## Description The `Repr` type name was unclear — it was intended to represent a lambda calculus expression, not a "representation." This PR renames `Repr` to `Expr` throughout the registry package for clarity. - Rename `Repr` interface to `Expr` and `baseRepr` struct to `baseExpr`. - Rename `repr.go` to `expr.go`. - Rename `ID()` method to `Repr()` to indicate the representation type. - Rename `NewRepr` constructor to `NewExpr`. - Update all usages in codec, conversion, engine, process, and registry files. - Add command aliases `conv` and `eng` for `convert` and `engine` subcommands. ## Benefits - The naming better reflects the domain: an `Expr` is an expression, and `Repr()` returns its representation kind. - Command aliases reduce typing for common subcommands. ## Checklist - [x] Code follows conventional commit format. - [x] Branch follows naming convention (`<type>/<description>`). Always use underscores. - [x] Tests pass (if applicable). - [x] Documentation updated (if applicable). Reviewed-on: #44 Co-authored-by: M.V. Hutz <git@maximhutz.me> Co-committed-by: M.V. Hutz <git@maximhutz.me>
96 lines
2.4 KiB
Go
96 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// inferReprFromPath returns the repr type based on file extension.
|
|
func inferReprFromPath(path string) (string, error) {
|
|
switch ext := strings.ToLower(filepath.Ext(path)); ext {
|
|
case ".lambda", ".lam", ".lc":
|
|
return "lambda", nil
|
|
case ".saccharine", ".sch":
|
|
return "saccharine", nil
|
|
default:
|
|
return "", fmt.Errorf("unknown file extension '%s'", ext)
|
|
}
|
|
}
|
|
|
|
func LambdaConvert() *cobra.Command {
|
|
var inputReprFlag, outputReprFlag string
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "convert <input-file> <output-file>",
|
|
Aliases: []string{"conv"},
|
|
Short: "Convert between lambda calculus representations",
|
|
SilenceUsage: true,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
if len(args) != 2 {
|
|
return cmd.Help()
|
|
}
|
|
|
|
var err error
|
|
inputPath, outputPath := args[0], args[1]
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
outputRepr := outputReprFlag
|
|
if outputRepr == "" {
|
|
if outputRepr, err = inferReprFromPath(outputPath); err != nil {
|
|
return fmt.Errorf("output file: %w", err)
|
|
}
|
|
}
|
|
|
|
// Read input file.
|
|
input, err := os.ReadFile(inputPath)
|
|
if err != nil {
|
|
return fmt.Errorf("reading input file: %w", err)
|
|
}
|
|
|
|
r := GetRegistry()
|
|
|
|
// Parse input into syntax tree.
|
|
repr, err := r.Unmarshal(string(input), inputRepr)
|
|
if err != nil {
|
|
return fmt.Errorf("parsing input: %w", err)
|
|
}
|
|
|
|
// Convert to output repr if different.
|
|
result, err := r.ConvertTo(repr, outputRepr)
|
|
if err != nil {
|
|
return fmt.Errorf("converting %s to %s: %w", inputRepr, outputRepr, err)
|
|
}
|
|
|
|
// Marshal output.
|
|
output, err := r.Marshal(result)
|
|
if err != nil {
|
|
return fmt.Errorf("unmarshaling output: %w", err)
|
|
}
|
|
|
|
// Write output file.
|
|
err = os.WriteFile(outputPath, []byte(output), 0644)
|
|
if err != nil {
|
|
return fmt.Errorf("writing output file: %w", err)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cmd.Flags().StringVarP(&inputReprFlag, "input", "i", "", "Input representation (inferred from extension if unset)")
|
|
cmd.Flags().StringVarP(&outputReprFlag, "output", "o", "", "Output representation (inferred from extension if unset)")
|
|
|
|
return cmd
|
|
}
|