feat: move lambda reduction to "lambda reduce"
This commit is contained in:
@@ -4,8 +4,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"git.maximhutz.com/max/lambda/internal/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Lambda() *cobra.Command {
|
func Lambda() *cobra.Command {
|
||||||
@@ -14,73 +12,13 @@ func Lambda() *cobra.Command {
|
|||||||
Short: "Lambda calculus interpreter",
|
Short: "Lambda calculus interpreter",
|
||||||
Long: "A lambda calculus interpreter supporting multiple representations.",
|
Long: "A lambda calculus interpreter supporting multiple representations.",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
// Legacy behavior when no subcommand is given.
|
return cmd.Help()
|
||||||
options, err := config.FromArgs()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
logger := options.GetLogger()
|
|
||||||
logger.Info("using program arguments", "args", os.Args)
|
|
||||||
logger.Info("parsed CLI options", "options", options)
|
|
||||||
|
|
||||||
r := GetRegistry()
|
|
||||||
|
|
||||||
// Get input.
|
|
||||||
input, err := options.Source.Extract()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse code into syntax tree.
|
|
||||||
repr, err := r.Unmarshal(input, "saccharine")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
logger.Info("parsed syntax tree", "tree", repr)
|
|
||||||
|
|
||||||
// Compile expression to lambda calculus.
|
|
||||||
compiled, err := r.ConvertTo(repr, "lambda")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
logger.Info("compiled λ expression", "tree", compiled)
|
|
||||||
|
|
||||||
// Create reducer with the compiled expression.
|
|
||||||
engine, err := r.GetDefaultEngine("lambda")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
process := engine.Load()
|
|
||||||
err = process.Set(compiled)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run reduction.
|
|
||||||
for process.Step(1) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the final reduced result.
|
|
||||||
result, err := process.Get()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
output, err := r.Marshal(result)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return options.Destination.Write(output)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().BoolP("verbose", "v", false, "Enable verbose output")
|
|
||||||
|
|
||||||
cmd.AddCommand(LambdaConvert())
|
cmd.AddCommand(LambdaConvert())
|
||||||
cmd.AddCommand(LambdaEngine())
|
cmd.AddCommand(LambdaEngine())
|
||||||
|
cmd.AddCommand(LambdaReduce())
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ func LambdaConvert() *cobra.Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringVarP(&inputReprFlag, "input", "i", "", "Input representation (inferred from extension if unset)")
|
cmd.Flags().StringVar(&inputReprFlag, "from", "", "Input representation (inferred from extension if unset)")
|
||||||
cmd.Flags().StringVarP(&outputReprFlag, "output", "o", "", "Output representation (inferred from extension if unset)")
|
cmd.Flags().StringVar(&outputReprFlag, "to", "", "Output representation (inferred from extension if unset)")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
109
cmd/lambda/lambda_reduce.go
Normal file
109
cmd/lambda/lambda_reduce.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"git.maximhutz.com/max/lambda/internal/cli"
|
||||||
|
"git.maximhutz.com/max/lambda/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LambdaReduce() *cobra.Command {
|
||||||
|
var inputReprFlag string
|
||||||
|
var engineFlag string
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "reduce <input-file>",
|
||||||
|
Short: "Reduce a lambda calculus expression",
|
||||||
|
SilenceUsage: true,
|
||||||
|
Aliases: []string{"run"},
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if len(args) != 1 {
|
||||||
|
return cmd.Help()
|
||||||
|
}
|
||||||
|
|
||||||
|
inputPath := args[0]
|
||||||
|
|
||||||
|
// Get input source.
|
||||||
|
var source config.Source
|
||||||
|
if inputPath == "-" {
|
||||||
|
source = config.StdinSource{}
|
||||||
|
} else {
|
||||||
|
source = config.FileSource{Path: inputPath}
|
||||||
|
}
|
||||||
|
|
||||||
|
destination := config.StdoutDestination{}
|
||||||
|
|
||||||
|
r := GetRegistry()
|
||||||
|
|
||||||
|
// Get input.
|
||||||
|
input, err := source.Extract()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use flag if provided, otherwise infer from extension.
|
||||||
|
inputRepr := inputReprFlag
|
||||||
|
if inputRepr == "" {
|
||||||
|
if inputRepr, err = inferReprFromPath(inputPath); err != nil {
|
||||||
|
return fmt.Errorf("input file: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find engine.
|
||||||
|
var engine cli.Engine
|
||||||
|
if engineFlag == "" {
|
||||||
|
if engine, err = r.GetDefaultEngine(inputRepr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if engine, err = r.GetEngine(engineFlag); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse code into syntax tree.
|
||||||
|
repr, err := r.Unmarshal(input, inputRepr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile expression to lambda calculus.
|
||||||
|
compiled, err := r.ConvertTo(repr, "lambda")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create process.
|
||||||
|
process := engine.Load()
|
||||||
|
err = process.Set(compiled)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run reduction.
|
||||||
|
for process.Step(1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the final reduced result.
|
||||||
|
result, err := process.Get()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := r.Marshal(result)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return destination.Write(output)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().StringVar(&inputReprFlag, "from", "", "Input representation (inferred from extension if unset)")
|
||||||
|
cmd.Flags().StringVarP(&engineFlag, "engine", "e", "", "Reduction engine (inferred from '--input' if unset)")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user