This is a small Lisp/Scheme-like interpreter written in Java. It reads a single S-expression from stdin and evaluates it in a persistent environment (REPL).
- Interactive REPL
- Numeric literals: integers (e.g.
42,-7) - Boolean literals:
true/false - Variables: symbols like
x,myVar - Special forms
define: define/update a variablelambda: create procedures (lexical closures)if: conditional evaluationbegin: evaluate multiple expressions sequentially
- Primitive procedures (built in)
+,*,=(binary, two arguments)
- Java: JDK 8+ (any recent JDK should work)
From the repository root:
javac -d out $(find src -name "*.java")java -cp out interpreter.MainYou should see the prompt:
λ >
λ > (+ 1 2)
3
λ > (* 6 7)
42
λ > (= 10 10)
true
λ > (= 10 11)
falseλ > (define x 5)
5
λ > (+ x 3)
8λ > (if true 1 2)
1
λ > (if (= 1 2) 10 20)
20lambda takes a parameter list and one or more body expressions.
λ > (define inc (lambda (x) (+ x 1)))
backend.CompoundProcedure@...
λ > (inc 41)
42λ > (begin (define x 1) (define y 2) (+ x y))
3Input is parsed as a single expression per line:
- Atoms: integers,
true/false, or symbols - Lists: parenthesized forms like
(operator arg1 arg2 ...)
Special forms are recognized by the first word in a list:
(define <name> <expr>)(lambda (<params...>) <body1> <body2> ...)(if <predicate> <consequent> <alternative>)(begin <expr1> <expr2> ...)
Everything else is treated as application:
(<operator> <operand1> <operand2> ...)
- Only one expression per REPL line (no multi-line forms).
- No quoting:
'(...)/(quote ...)is not supported yet. - No lists/cons: there is no list data type beyond syntax; you should create it using
lambdas. +,*,=currently require exactly two arguments.- Error handling: the REPL catches exceptions and prints the exception value.
src/interpreter/Main.java: starts the REPL, initializes the global environment, registers primitive procedures.src/forntend/Parser.java: tokenizes a one-line program string and parses it into aRawExpressionAST.src/interpreter/RawExpressionTranslator.java: lowersRawExpressioninto backendExpressionnodes.src/backend/*: evaluation model (AST nodes, environment, procedures, primitive procedures).
- Tokenize:
Parser.programStrToListadds spaces around parentheses and splits the line into tokens. - Parse:
Parser.parsebuilds aRawExpressiontree. - Translate:
RawExpressionTranslator.translateToExpressionconverts raw nodes into typed backendExpressions. - Evaluate: each backend
Expressionimplementseval(Environment)and returns aSelfEvaluatingvalue.
- Environment is a
HashMap<String, SelfEvaluating>. definemutates the current environment (Environment.addMut). This makes definitions persist across REPL inputs.- Procedures are
SelfEvaluatingvalues. Alambdacaptures an environment and evaluates its body in an extended environment during application.
Syntax Error- Likely indicates mismatched parentheses.
Too few arguments supplied!!!/Too many arguments supplied!!!- Your procedure call arity does not match the procedure's parameter list.
- Add quoting (
quote/') and list primitives (cons,car,cdr). - Add variadic primitives for
+and*. - Add better error messages with line context.
MIT