Add return statement

This commit is contained in:
Tom Willemse 2021-02-08 17:42:18 -08:00
parent 4a71c219b5
commit 0dbf155da5
6 changed files with 53 additions and 11 deletions

View file

@ -21,4 +21,5 @@ add_jar(Lox
Environment.java Environment.java
LoxCallable.java LoxCallable.java
LoxFunction.java LoxFunction.java
Return.java
ENTRY_POINT com/craftinginterpreters/lox/Lox) ENTRY_POINT com/craftinginterpreters/lox/Lox)

View file

@ -10,7 +10,9 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
Interpreter() { Interpreter() {
globals.define("clock", new LoxCallable() { globals.define("clock", new LoxCallable() {
@Override @Override
public int arity() { return 0; } public int arity() {
return 0;
}
@Override @Override
public Object call(Interpreter interpreter, List<Object> arguments) { public Object call(Interpreter interpreter, List<Object> arguments) {
@ -18,7 +20,9 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
} }
@Override @Override
public String toString() { return "<native fn>"; } public String toString() {
return "<native fn>";
}
}); });
} }
@ -172,6 +176,15 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
return null; return null;
} }
@Override
public Void visitReturnStmt(Stmt.Return stmt) {
Object value = null;
if (stmt.value != null)
value = evaluate(stmt.value);
throw new Return(value);
}
@Override @Override
public Void visitVarStmt(Stmt.Var stmt) { public Void visitVarStmt(Stmt.Var stmt) {
Object value = null; Object value = null;

View file

@ -22,7 +22,11 @@ class LoxFunction implements LoxCallable {
environment.define(declaration.params.get(i).lexeme, arguments.get(i)); environment.define(declaration.params.get(i).lexeme, arguments.get(i));
} }
try {
interpreter.executeBlock(declaration.body, environment); interpreter.executeBlock(declaration.body, environment);
} catch (Return returnValue) {
return returnValue.value;
}
return null; return null;
} }

View file

@ -52,6 +52,8 @@ class Parser {
return ifStatement(); return ifStatement();
if (match(PRINT)) if (match(PRINT))
return printStatement(); return printStatement();
if (match(RETURN))
return returnStatement();
if (match(WHILE)) if (match(WHILE))
return whileStatement(); return whileStatement();
if (match(LEFT_BRACE)) if (match(LEFT_BRACE))
@ -120,6 +122,17 @@ class Parser {
return new Stmt.Print(value); return new Stmt.Print(value);
} }
private Stmt returnStatement() {
Token keyword = previous();
Expr value = null;
if (!check(SEMICOLON)) {
value = expression();
}
consume(SEMICOLON, "Expect ';' after return value.");
return new Stmt.Return(keyword, value);
}
private Stmt varDeclaration() { private Stmt varDeclaration() {
Token name = consume(IDENTIFIER, "Expect variable name."); Token name = consume(IDENTIFIER, "Expect variable name.");

View file

@ -0,0 +1,10 @@
package com.craftinginterpreters.lox;
class Return extends RuntimeException {
final Object value;
Return(Object value) {
super(null, null, false, false);
this.value = value;
}
}

View file

@ -23,7 +23,8 @@ public class GenerateAst {
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",
"If : Expr condition, Stmt thenBranch, Stmt elseBranch", "Print : Expr expression", "If : Expr condition, Stmt thenBranch, Stmt elseBranch", "Print : Expr expression",
"Var : Token name, Expr initializer", "While : Expr condition, Stmt body")); "Return : Token keyword, Expr value", "Var : Token name, Expr initializer",
"While : Expr condition, Stmt body"));
} }
private static void defineAst(String outputDir, String baseName, List<String> types) throws IOException { private static void defineAst(String outputDir, String baseName, List<String> types) throws IOException {