feat: add De Bruijn index reduction engine

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>
This commit is contained in:
2026-01-12 21:27:40 -05:00
parent 335ce95c50
commit f3b9137d75
16 changed files with 679 additions and 63 deletions

View File

@@ -14,6 +14,7 @@ func FromArgs() (*Config, error) {
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.
@@ -45,6 +46,11 @@ func FromArgs() (*Config, error) {
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,
@@ -52,5 +58,6 @@ func FromArgs() (*Config, error) {
Explanation: *explanation,
Profile: *profile,
Statistics: *statistics,
Interpreter: *interpreter,
}, nil
}