package coffee.liz.lambda; import coffee.liz.lambda.parser.ArrowParser; import coffee.liz.lambda.parser.LambdaParser; import coffee.liz.lambda.parser.ParseException; import coffee.liz.lambda.ast.Expression; import coffee.liz.lambda.ast.LambdaProgram; import coffee.liz.lambda.ast.Macro; import coffee.liz.lambda.ast.SourceCode; import coffee.liz.lambda.bind.ExternalBinding; import coffee.liz.lambda.eval.Environment; import coffee.liz.lambda.eval.NormalOrderEvaluator; import coffee.liz.lambda.eval.Value; import java.io.StringReader; import java.util.List; /** * Entry point for parsing and interpreting lambda calculus programs. */ public class LambdaDriver { /** * Parses source code into an AST. * * @param sourceCode * the source code (either Lambda or Arrow syntax) * @return the parsed program */ public static LambdaProgram parse(final SourceCode sourceCode) { return switch (sourceCode) { case SourceCode.Lambda(String source) -> parseLambda(source); case SourceCode.Arrow(String source) -> parseArrow(source); }; } private static LambdaProgram parseLambda(final String source) { try (final StringReader reader = new StringReader(source)) { return new LambdaParser(reader).Program(); } catch (final ParseException parseException) { throw new RuntimeException("Failed to parse program", parseException); } } private static LambdaProgram parseArrow(final String source) { try (final StringReader reader = new StringReader(source)) { return new ArrowParser(reader).Program(); } catch (final ParseException parseException) { throw new RuntimeException("Failed to parse program", parseException); } } /** * Parses and evaluates lambda calculus programs. * * @param sourceCode * the source code * @return the evaluated result */ public static Value interpret(final SourceCode sourceCode) { return interpret(sourceCode, List.of()); } /** * Parses and evaluates lambda calculus programs with "FFI"'s. * * @param sourceCode * the source code * @param bindings * external Java functions available during evaluation * @return the evaluated result */ public static Value interpret(final SourceCode sourceCode, final List bindings) { final LambdaProgram program = parse(sourceCode); final Expression expression = program.expression(); final List macros = program.macros(); return NormalOrderEvaluator.evaluate(expression, Environment.from(macros, bindings)); } }