summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemse2020-11-25 23:10:58 -0800
committerGravatar Tom Willemse2020-11-25 23:10:58 -0800
commitca9fd3ae3a1ef5ca1fbe33a83abb12e656a2556f (patch)
tree77d16c7e6b87ed0f4472f6a421eeb9496d6f33bc
parent57e87978ef416ce2898a65a9b67e37be91263e67 (diff)
downloadcrafting-interpreters-ca9fd3ae3a1ef5ca1fbe33a83abb12e656a2556f.tar.gz
crafting-interpreters-ca9fd3ae3a1ef5ca1fbe33a83abb12e656a2556f.zip
Chapter 8: Add blocks and scopes
-rw-r--r--src/com/craftinginterpreters/lox/AstPrinter.java20
-rw-r--r--src/com/craftinginterpreters/lox/Environment.java17
-rw-r--r--src/com/craftinginterpreters/lox/Interpreter.java20
-rw-r--r--src/com/craftinginterpreters/lox/Parser.java13
-rw-r--r--src/com/craftinginterpreters/tool/GenerateAst.java9
5 files changed, 75 insertions, 4 deletions
diff --git a/src/com/craftinginterpreters/lox/AstPrinter.java b/src/com/craftinginterpreters/lox/AstPrinter.java
index 58376cb..d5163df 100644
--- a/src/com/craftinginterpreters/lox/AstPrinter.java
+++ b/src/com/craftinginterpreters/lox/AstPrinter.java
@@ -1,5 +1,7 @@
package com.craftinginterpreters.lox;
+import java.util.List;
+
/**
* AstPrinter
*/
@@ -55,6 +57,11 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
return expression.expression.accept(this);
}
+ @Override
+ public String visitBlockStmt(Stmt.Block block) {
+ return parenthesize("", block.statements);
+ }
+
private String parenthesize(String name, Expr... exprs) {
StringBuilder builder = new StringBuilder();
@@ -68,6 +75,19 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
return builder.toString();
}
+ private String parenthesize(String name, List<Stmt> statements) {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("(").append(name);
+ for (Stmt statement : statements) {
+ builder.append(" ");
+ builder.append(statement.accept(this));
+ }
+ builder.append(")");
+
+ return builder.toString();
+ }
+
public static void main(String[] args) {
Expr expression = new Expr.Binary(
new Expr.Unary(new Token(TokenType.MINUS, "-", null, 1), new Expr.Literal(123)),
diff --git a/src/com/craftinginterpreters/lox/Environment.java b/src/com/craftinginterpreters/lox/Environment.java
index 8d8a374..0a95282 100644
--- a/src/com/craftinginterpreters/lox/Environment.java
+++ b/src/com/craftinginterpreters/lox/Environment.java
@@ -4,13 +4,25 @@ import java.util.HashMap;
import java.util.Map;
class Environment {
+ private final Environment enclosing;
private final Map<String, Object> values = new HashMap<>();
+ Environment() {
+ enclosing = null;
+ }
+
+ Environment(Environment enclosing) {
+ this.enclosing = enclosing;
+ }
+
Object get(Token name) {
if (values.containsKey(name.lexeme)) {
return values.get(name.lexeme);
}
+ if (enclosing != null)
+ return enclosing.get(name);
+
throw new RuntimeError(name, "Undefined variable '" + name.lexeme + "'.");
}
@@ -20,6 +32,11 @@ class Environment {
return;
}
+ if (enclosing != null) {
+ enclosing.assign(name, value);
+ return;
+ }
+
throw new RuntimeError(name, "Undefined variable '" + name.lexeme + "'.");
}
diff --git a/src/com/craftinginterpreters/lox/Interpreter.java b/src/com/craftinginterpreters/lox/Interpreter.java
index 7378164..e03ca37 100644
--- a/src/com/craftinginterpreters/lox/Interpreter.java
+++ b/src/com/craftinginterpreters/lox/Interpreter.java
@@ -89,6 +89,26 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
stmt.accept(this);
}
+ private void executeBlock(List<Stmt> statements, Environment environment) {
+ Environment previous = this.environment;
+
+ try {
+ this.environment = environment;
+
+ for (Stmt statement : statements) {
+ execute(statement);
+ }
+ } finally {
+ this.environment = previous;
+ }
+ }
+
+ @Override
+ public Void visitBlockStmt(Stmt.Block stmt) {
+ executeBlock(stmt.statements, new Environment(environment));
+ return null;
+ }
+
@Override
public Void visitExpressionStmt(Stmt.Expression stmt) {
evaluate(stmt.expression);
diff --git a/src/com/craftinginterpreters/lox/Parser.java b/src/com/craftinginterpreters/lox/Parser.java
index 9e76a54..f044feb 100644
--- a/src/com/craftinginterpreters/lox/Parser.java
+++ b/src/com/craftinginterpreters/lox/Parser.java
@@ -45,6 +45,8 @@ class Parser {
private Stmt statement() {
if (match(PRINT))
return printStatement();
+ if (match(LEFT_BRACE))
+ return new Stmt.Block(block());
return expressionStatement();
}
@@ -73,6 +75,17 @@ class Parser {
return new Stmt.Expression(expr);
}
+ private List<Stmt> block() {
+ List<Stmt> statements = new ArrayList<>();
+
+ while (!check(RIGHT_BRACE) && !isAtEnd()) {
+ statements.add(declaration());
+ }
+
+ consume(RIGHT_BRACE, "Expect '}' after block.");
+ return statements;
+ }
+
private Expr assignment() {
Expr expr = equality();
diff --git a/src/com/craftinginterpreters/tool/GenerateAst.java b/src/com/craftinginterpreters/tool/GenerateAst.java
index f96e315..c9f1398 100644
--- a/src/com/craftinginterpreters/tool/GenerateAst.java
+++ b/src/com/craftinginterpreters/tool/GenerateAst.java
@@ -15,10 +15,11 @@ public class GenerateAst {
String outputDir = args[0];
defineAst(outputDir, "Expr",
- Arrays.asList("Assign : Token name, Expr value", "Binary : Expr left, Token operator, Expr right", "Grouping : Expr expression",
- "Literal : Object value", "Unary : Token operator, Expr right", "Variable : Token name"));
- defineAst(outputDir, "Stmt", Arrays.asList("Expression : Expr expression", "Print : Expr expression",
- "Var : Token name, Expr initializer"));
+ Arrays.asList("Assign : Token name, Expr value", "Binary : Expr left, Token operator, Expr right",
+ "Grouping : Expr expression", "Literal : Object value", "Unary : Token operator, Expr right",
+ "Variable : Token name"));
+ defineAst(outputDir, "Stmt", Arrays.asList("Block : List<Stmt> statements", "Expression : Expr expression",
+ "Print : Expr expression", "Var : Token name, Expr initializer"));
}
private static void defineAst(String outputDir, String baseName, List<String> types) throws IOException {