Files
lambda/cmd/lambda/lambda_convert.go
M.V. Hutz 1f486875fd style: rename repr to expr (#44)
## 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>
2026-02-07 15:26:50 +00:00

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
}