Closes #26 - Added -i flag to select interpreter (lambda or debruijn) - Created debruijn package with Expression interface - Variable contains index and optional label - Abstraction contains only body (no parameter) - Application structure remains similar - Implemented De Bruijn reduction without variable renaming - Shift operation handles index adjustments - Substitute replaces by index instead of name - Abstracted Engine into interface with two implementations - LambdaEngine: original named variable engine - DeBruijnEngine: new index-based engine - Added conversion functions between representations - LambdaToDeBruijn: converts named to indexed - DeBruijnToLambda: converts indexed back to named - SaccharineToDeBruijn: direct saccharine to De Bruijn - Updated main to switch engines based on -i flag - All test samples pass with both engines Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
64 lines
2.1 KiB
Go
64 lines
2.1 KiB
Go
package config
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
)
|
|
|
|
// Extract the program configuration from the command-line arguments.
|
|
func FromArgs() (*Config, error) {
|
|
// Relevant flags.
|
|
verbose := flag.Bool("v", false, "Verbosity. If set, the program will print logs.")
|
|
explanation := flag.Bool("x", false, "Explanation. Whether or not to show all reduction steps.")
|
|
statistics := flag.Bool("s", false, "Statistics. If set, the process will print various statistics about the run.")
|
|
profile := flag.String("p", "", "CPU profiling. If an output file is defined, the program will profile its execution and dump its results into it.")
|
|
file := flag.String("f", "", "File. If set, read source from the specified file.")
|
|
output := flag.String("o", "", "Output. If set, write result to the specified file. Use '-' for stdout (default).")
|
|
interpreter := flag.String("i", "lambda", "Interpreter. Choose 'lambda' or 'debruijn' reduction engine (default: lambda).")
|
|
flag.Parse()
|
|
|
|
// Parse source type.
|
|
var source Source
|
|
if *file != "" {
|
|
// File flag takes precedence.
|
|
if flag.NArg() > 0 {
|
|
return nil, fmt.Errorf("cannot specify both -f flag and positional argument")
|
|
}
|
|
source = FileSource{Path: *file}
|
|
} else if flag.NArg() == 0 {
|
|
return nil, fmt.Errorf("no input given")
|
|
} else if flag.NArg() > 1 {
|
|
return nil, fmt.Errorf("more than 1 command-line argument")
|
|
} else {
|
|
// Positional argument.
|
|
if flag.Arg(0) == "-" {
|
|
source = StdinSource{}
|
|
} else {
|
|
source = StringSource{Data: flag.Arg(0)}
|
|
}
|
|
}
|
|
|
|
// Parse destination type.
|
|
var destination Destination
|
|
if *output == "" || *output == "-" {
|
|
destination = StdoutDestination{}
|
|
} else {
|
|
destination = FileDestination{Path: *output}
|
|
}
|
|
|
|
// Validate interpreter flag.
|
|
if *interpreter != "lambda" && *interpreter != "debruijn" {
|
|
return nil, fmt.Errorf("invalid interpreter: %s (must be 'lambda' or 'debruijn')", *interpreter)
|
|
}
|
|
|
|
return &Config{
|
|
Source: source,
|
|
Destination: destination,
|
|
Verbose: *verbose,
|
|
Explanation: *explanation,
|
|
Profile: *profile,
|
|
Statistics: *statistics,
|
|
Interpreter: *interpreter,
|
|
}, nil
|
|
}
|