Add anonymous functions
This commit is contained in:
parent
4fbfa53dd7
commit
a0df1715fc
5 changed files with 69 additions and 1 deletions
|
@ -22,4 +22,5 @@ add_jar(Lox
|
|||
LoxCallable.java
|
||||
LoxFunction.java
|
||||
Return.java
|
||||
LoxLambda.java
|
||||
ENTRY_POINT com/craftinginterpreters/lox/Lox)
|
||||
|
|
|
@ -158,6 +158,11 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitLambdaExpr(Expr.Lambda expr) {
|
||||
return new LoxLambda(expr, environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitIfStmt(Stmt.If stmt) {
|
||||
if (isTruthy(evaluate(stmt.condition))) {
|
||||
|
|
40
src/com/craftinginterpreters/lox/LoxLambda.java
Normal file
40
src/com/craftinginterpreters/lox/LoxLambda.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
package com.craftinginterpreters.lox;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class LoxLambda implements LoxCallable {
|
||||
private final Expr.Lambda declaration;
|
||||
private final Environment closure;
|
||||
|
||||
LoxLambda(Expr.Lambda declaration, Environment closure) {
|
||||
this.closure = closure;
|
||||
this.declaration = declaration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int arity() {
|
||||
return declaration.params.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(Interpreter interpreter, List<Object> arguments) {
|
||||
Environment environment = new Environment(closure);
|
||||
|
||||
for (int i = 0; i < declaration.params.size(); i++) {
|
||||
environment.define(declaration.params.get(i).lexeme, arguments.get(i));
|
||||
}
|
||||
|
||||
try {
|
||||
interpreter.executeBlock(declaration.body, environment);
|
||||
} catch (Return returnValue) {
|
||||
return returnValue.value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<fn anonymous>";
|
||||
}
|
||||
}
|
|
@ -28,6 +28,8 @@ class Parser {
|
|||
}
|
||||
|
||||
private Expr expression() {
|
||||
if (match(FUN))
|
||||
return lambda();
|
||||
return assignment();
|
||||
}
|
||||
|
||||
|
@ -180,6 +182,25 @@ class Parser {
|
|||
return new Stmt.Function(name, parameters, body);
|
||||
}
|
||||
|
||||
private Expr.Lambda lambda() {
|
||||
consume(LEFT_PAREN, "You can't see this message.");
|
||||
List<Token> parameters = new ArrayList();
|
||||
if (!check(RIGHT_PAREN)) {
|
||||
do {
|
||||
if (parameters.size() >= 255) {
|
||||
error(peek(), "Can't have more than 255 parameters.");
|
||||
}
|
||||
|
||||
parameters.add(consume(IDENTIFIER, "Expect parameter name."));
|
||||
} while (match(COMMA));
|
||||
}
|
||||
consume(RIGHT_PAREN, "Expect ')' after parameters.");
|
||||
|
||||
consume(LEFT_BRACE, "Expext '{' before lambda body.");
|
||||
List<Stmt> body = block();
|
||||
return new Expr.Lambda(parameters, body);
|
||||
}
|
||||
|
||||
private List<Stmt> block() {
|
||||
List<Stmt> statements = new ArrayList<>();
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ public class GenerateAst {
|
|||
Arrays.asList("Assign : Token name, Expr value", "Binary : Expr left, Token operator, Expr right",
|
||||
"Call : Expr callee, Token paren, List<Expr> arguments", "Grouping : Expr expression",
|
||||
"Literal : Object value", "Logical : Expr left, Token operator, Expr right",
|
||||
"Unary : Token operator, Expr right", "Variable : Token name"));
|
||||
"Unary : Token operator, Expr right", "Variable : Token name",
|
||||
"Lambda : List<Token> params, List<Stmt> body"));
|
||||
defineAst(outputDir, "Stmt",
|
||||
Arrays.asList("Block : List<Stmt> statements", "Expression : Expr expression",
|
||||
"Function : Token name, List<Token> params, List<Stmt> body",
|
||||
|
|
Loading…
Reference in a new issue