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
|
LoxCallable.java
|
||||||
LoxFunction.java
|
LoxFunction.java
|
||||||
Return.java
|
Return.java
|
||||||
|
LoxLambda.java
|
||||||
ENTRY_POINT com/craftinginterpreters/lox/Lox)
|
ENTRY_POINT com/craftinginterpreters/lox/Lox)
|
||||||
|
|
|
@ -158,6 +158,11 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitLambdaExpr(Expr.Lambda expr) {
|
||||||
|
return new LoxLambda(expr, environment);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitIfStmt(Stmt.If stmt) {
|
public Void visitIfStmt(Stmt.If stmt) {
|
||||||
if (isTruthy(evaluate(stmt.condition))) {
|
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() {
|
private Expr expression() {
|
||||||
|
if (match(FUN))
|
||||||
|
return lambda();
|
||||||
return assignment();
|
return assignment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +182,25 @@ class Parser {
|
||||||
return new Stmt.Function(name, parameters, body);
|
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() {
|
private List<Stmt> block() {
|
||||||
List<Stmt> statements = new ArrayList<>();
|
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",
|
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",
|
"Call : Expr callee, Token paren, List<Expr> arguments", "Grouping : Expr expression",
|
||||||
"Literal : Object value", "Logical : Expr left, Token operator, Expr right",
|
"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",
|
defineAst(outputDir, "Stmt",
|
||||||
Arrays.asList("Block : List<Stmt> statements", "Expression : Expr expression",
|
Arrays.asList("Block : List<Stmt> statements", "Expression : Expr expression",
|
||||||
"Function : Token name, List<Token> params, List<Stmt> body",
|
"Function : Token name, List<Token> params, List<Stmt> body",
|
||||||
|
|
Loading…
Reference in a new issue