From 0dbf155da52c5db1cab2688b04c87386a55c5d5b Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Mon, 8 Feb 2021 17:42:18 -0800 Subject: [PATCH] Add return statement --- .../craftinginterpreters/lox/CMakeLists.txt | 1 + .../craftinginterpreters/lox/Interpreter.java | 31 +++++++++++++------ .../craftinginterpreters/lox/LoxFunction.java | 6 +++- src/com/craftinginterpreters/lox/Parser.java | 13 ++++++++ src/com/craftinginterpreters/lox/Return.java | 10 ++++++ .../tool/GenerateAst.java | 3 +- 6 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 src/com/craftinginterpreters/lox/Return.java diff --git a/src/com/craftinginterpreters/lox/CMakeLists.txt b/src/com/craftinginterpreters/lox/CMakeLists.txt index a068037..fa93588 100644 --- a/src/com/craftinginterpreters/lox/CMakeLists.txt +++ b/src/com/craftinginterpreters/lox/CMakeLists.txt @@ -21,4 +21,5 @@ add_jar(Lox Environment.java LoxCallable.java LoxFunction.java + Return.java ENTRY_POINT com/craftinginterpreters/lox/Lox) diff --git a/src/com/craftinginterpreters/lox/Interpreter.java b/src/com/craftinginterpreters/lox/Interpreter.java index 407c537..4549e11 100644 --- a/src/com/craftinginterpreters/lox/Interpreter.java +++ b/src/com/craftinginterpreters/lox/Interpreter.java @@ -9,17 +9,21 @@ class Interpreter implements Expr.Visitor, Stmt.Visitor { Interpreter() { globals.define("clock", new LoxCallable() { - @Override - public int arity() { return 0; } + @Override + public int arity() { + return 0; + } - @Override - public Object call(Interpreter interpreter, List arguments) { - return (double)System.currentTimeMillis() / 1000.0; - } + @Override + public Object call(Interpreter interpreter, List arguments) { + return (double) System.currentTimeMillis() / 1000.0; + } - @Override - public String toString() { return ""; } - }); + @Override + public String toString() { + return ""; + } + }); } @Override @@ -172,6 +176,15 @@ class Interpreter implements Expr.Visitor, Stmt.Visitor { 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 public Void visitVarStmt(Stmt.Var stmt) { Object value = null; diff --git a/src/com/craftinginterpreters/lox/LoxFunction.java b/src/com/craftinginterpreters/lox/LoxFunction.java index d2e367b..0f7ebd4 100644 --- a/src/com/craftinginterpreters/lox/LoxFunction.java +++ b/src/com/craftinginterpreters/lox/LoxFunction.java @@ -22,7 +22,11 @@ class LoxFunction implements LoxCallable { environment.define(declaration.params.get(i).lexeme, arguments.get(i)); } - interpreter.executeBlock(declaration.body, environment); + try { + interpreter.executeBlock(declaration.body, environment); + } catch (Return returnValue) { + return returnValue.value; + } return null; } diff --git a/src/com/craftinginterpreters/lox/Parser.java b/src/com/craftinginterpreters/lox/Parser.java index c427bc4..528326c 100644 --- a/src/com/craftinginterpreters/lox/Parser.java +++ b/src/com/craftinginterpreters/lox/Parser.java @@ -52,6 +52,8 @@ class Parser { return ifStatement(); if (match(PRINT)) return printStatement(); + if (match(RETURN)) + return returnStatement(); if (match(WHILE)) return whileStatement(); if (match(LEFT_BRACE)) @@ -120,6 +122,17 @@ class Parser { 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() { Token name = consume(IDENTIFIER, "Expect variable name."); diff --git a/src/com/craftinginterpreters/lox/Return.java b/src/com/craftinginterpreters/lox/Return.java new file mode 100644 index 0000000..5bd62d0 --- /dev/null +++ b/src/com/craftinginterpreters/lox/Return.java @@ -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; + } +} diff --git a/src/com/craftinginterpreters/tool/GenerateAst.java b/src/com/craftinginterpreters/tool/GenerateAst.java index 92c7967..2bf442b 100644 --- a/src/com/craftinginterpreters/tool/GenerateAst.java +++ b/src/com/craftinginterpreters/tool/GenerateAst.java @@ -23,7 +23,8 @@ public class GenerateAst { Arrays.asList("Block : List statements", "Expression : Expr expression", "Function : Token name, List params, List body", "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 types) throws IOException {