aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/craftinginterpreters/lox/Interpreter.java
diff options
context:
space:
mode:
authorGravatar Tom Willemse2021-07-08 00:14:31 -0700
committerGravatar Tom Willemse2021-07-08 02:25:13 -0700
commit68a2ebd34fc94488e89ffb82b359ec6e7e152ae9 (patch)
tree0dbbe26aff8fc38805b4b3780ae7842c433b9522 /src/com/craftinginterpreters/lox/Interpreter.java
parent62bd0f83dc909547a69abb8b0aed40cf098b4c95 (diff)
downloadcrafting-interpreters-68a2ebd34fc94488e89ffb82b359ec6e7e152ae9.tar.gz
crafting-interpreters-68a2ebd34fc94488e89ffb82b359ec6e7e152ae9.zip
Restructure project to make room for clox
Diffstat (limited to 'src/com/craftinginterpreters/lox/Interpreter.java')
-rw-r--r--src/com/craftinginterpreters/lox/Interpreter.java392
1 files changed, 0 insertions, 392 deletions
diff --git a/src/com/craftinginterpreters/lox/Interpreter.java b/src/com/craftinginterpreters/lox/Interpreter.java
deleted file mode 100644
index 3f4d385..0000000
--- a/src/com/craftinginterpreters/lox/Interpreter.java
+++ /dev/null
@@ -1,392 +0,0 @@
-package com.craftinginterpreters.lox;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
- final Environment globals = new Environment();
- private Environment environment = globals;
- private final Map<Expr, Integer> locals = new HashMap<>();
-
- Interpreter() {
- globals.define("clock", new LoxCallable() {
- @Override
- public int arity() {
- return 0;
- }
-
- @Override
- public Object call(Interpreter interpreter, List<Object> arguments) {
- return (double) System.currentTimeMillis() / 1000.0;
- }
-
- @Override
- public String toString() {
- return "<native fn>";
- }
- });
- }
-
- @Override
- public Object visitLiteralExpr(Expr.Literal expr) {
- return expr.value;
- }
-
- @Override
- public Object visitLogicalExpr(Expr.Logical expr) {
- Object left = evaluate(expr.left);
-
- if (expr.operator.type == TokenType.OR) {
- if (isTruthy(left))
- return left;
- } else {
- if (!isTruthy(left))
- return left;
- }
-
- return evaluate(expr.right);
- }
-
- @Override
- public Object visitSetExpr(Expr.Set expr) {
- Object object = evaluate(expr.object);
-
- if (!(object instanceof LoxInstance)) {
- throw new RuntimeError(expr.name, "Only instances have fields.");
- }
-
- Object value = evaluate(expr.value);
- ((LoxInstance) object).set(expr.name, value);
- return value;
- }
-
- @Override
- public Object visitSuperExpr(Expr.Super expr) {
- int distance = locals.get(expr);
- LoxClass superclass = (LoxClass) environment.getAt(distance, "super");
-
- LoxInstance object = (LoxInstance) environment.getAt(distance - 1, "this");
-
- LoxFunction method = superclass.findMethod(expr.method.lexeme);
-
- if (method == null) {
- throw new RuntimeError(expr.method, "Undefined property '" + expr.method.lexeme + "'.");
- }
-
- return method.bind(object);
- }
-
- @Override
- public Object visitThisExpr(Expr.This expr) {
- return lookUpVariable(expr.keyword, expr);
- }
-
- @Override
- public Object visitUnaryExpr(Expr.Unary expr) {
- Object right = evaluate(expr.right);
-
- switch (expr.operator.type) {
- case BANG:
- return !isTruthy(right);
- case MINUS:
- checkNumberOperand(expr.operator, right);
- return -(double) right;
- }
-
- // Unreachable.
- return null;
- }
-
- @Override
- public Object visitVariableExpr(Expr.Variable expr) {
- return lookUpVariable(expr.name, expr);
- }
-
- private Object lookUpVariable(Token name, Expr expr) {
- Integer distance = locals.get(expr);
- if (distance != null) {
- return environment.getAt(distance, name.lexeme);
- } else {
- return globals.get(name);
- }
- }
-
- private void checkNumberOperand(Token operator, Object operand) {
- if (operand instanceof Double)
- return;
- throw new RuntimeError(operator, "Operand must be a number.");
- }
-
- private void checkNumberOperands(Token operator, Object left, Object right) {
- if (left instanceof Double && right instanceof Double)
- return;
-
- throw new RuntimeError(operator, "Operands must be numbers.");
- }
-
- private boolean isTruthy(Object object) {
- if (object == null)
- return false;
- if (object instanceof Boolean)
- return (boolean) object;
- return true;
- }
-
- private boolean isEqual(Object a, Object b) {
- if (a == null && b == null)
- return true;
- if (a == null)
- return false;
-
- return a.equals(b);
- }
-
- private String stringify(Object object) {
- if (object == null)
- return "nil";
-
- if (object instanceof Double) {
- String text = object.toString();
- if (text.endsWith(".0")) {
- text = text.substring(0, text.length() - 2);
- }
- return text;
- }
-
- return object.toString();
- }
-
- @Override
- public Object visitGroupingExpr(Expr.Grouping expr) {
- return evaluate(expr.expression);
- }
-
- private Object evaluate(Expr expr) {
- return expr.accept(this);
- }
-
- private void execute(Stmt stmt) {
- stmt.accept(this);
- }
-
- public void resolve(Expr expr, int depth) {
- locals.put(expr, depth);
- }
-
- public 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 visitClassStmt(Stmt.Class stmt) {
- Object superclass = null;
- if (stmt.superclass != null) {
- superclass = evaluate(stmt.superclass);
- if (!(superclass instanceof LoxClass)) {
- throw new RuntimeError(stmt.superclass.name, "Superclass must be a class.");
- }
- }
- environment.define(stmt.name.lexeme, null);
-
- if (stmt.superclass != null) {
- environment = new Environment(environment);
- environment.define("super", superclass);
- }
-
- Map<String, LoxFunction> methods = new HashMap<>();
- for (Stmt.Function method : stmt.methods) {
- LoxFunction function = new LoxFunction(method, environment, method.name.lexeme.equals("init"));
- methods.put(method.name.lexeme, function);
- }
-
- LoxClass klass = new LoxClass(stmt.name.lexeme, (LoxClass) superclass, methods);
-
- if (superclass != null) {
- environment = environment.enclosing;
- }
-
- environment.assign(stmt.name, klass);
- return null;
- }
-
- @Override
- public Void visitExpressionStmt(Stmt.Expression stmt) {
- evaluate(stmt.expression);
- return null;
- }
-
- @Override
- public Void visitFunctionStmt(Stmt.Function stmt) {
- LoxFunction function = new LoxFunction(stmt, environment, false);
- environment.define(stmt.name.lexeme, function);
- return null;
- }
-
- @Override
- public Void visitIfStmt(Stmt.If stmt) {
- if (isTruthy(evaluate(stmt.condition))) {
- execute(stmt.thenBranch);
- } else if (stmt.elseBranch != null) {
- execute(stmt.elseBranch);
- }
-
- return null;
- }
-
- @Override
- public Void visitPrintStmt(Stmt.Print stmt) {
- Object value = evaluate(stmt.expression);
- System.out.println(stringify(value));
- 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;
- if (stmt.initializer != null) {
- value = evaluate(stmt.initializer);
- }
-
- environment.define(stmt.name.lexeme, value);
- return null;
- }
-
- @Override
- public Void visitWhileStmt(Stmt.While stmt) {
- while (isTruthy(evaluate(stmt.condition))) {
- execute(stmt.body);
- }
-
- return null;
- }
-
- @Override
- public Object visitAssignExpr(Expr.Assign expr) {
- Object value = evaluate(expr.value);
-
- Integer distance = locals.get(expr);
- if (distance != null) {
- environment.assignAt(distance, expr.name, value);
- } else {
- globals.assign(expr.name, value);
- }
-
- return value;
- }
-
- @Override
- public Object visitBinaryExpr(Expr.Binary expr) {
- Object left = evaluate(expr.left);
- Object right = evaluate(expr.right);
-
- switch (expr.operator.type) {
- case GREATER:
- checkNumberOperands(expr.operator, left, right);
- return (double) left > (double) right;
- case GREATER_EQUAL:
- checkNumberOperands(expr.operator, left, right);
- return (double) left >= (double) right;
- case LESS:
- checkNumberOperands(expr.operator, left, right);
- return (double) left < (double) right;
- case LESS_EQUAL:
- checkNumberOperands(expr.operator, left, right);
- return (double) left <= (double) right;
- case BANG_EQUAL:
- return !isEqual(left, right);
- case EQUAL_EQUAL:
- return isEqual(left, right);
- case MINUS:
- checkNumberOperands(expr.operator, left, right);
- return (double) left - (double) right;
- case PLUS:
- if (left instanceof Double && right instanceof Double) {
- return (double) left + (double) right;
- }
-
- if (left instanceof String && right instanceof String) {
- return (String) left + (String) right;
- }
-
- throw new RuntimeError(expr.operator, "Operands must be two numbers or two strings.");
- case SLASH:
- checkNumberOperands(expr.operator, left, right);
- return (double) left / (double) right;
- case STAR:
- checkNumberOperands(expr.operator, left, right);
- return (double) left * (double) right;
- }
-
- // Unreachable.
- return null;
- }
-
- @Override
- public Object visitCallExpr(Expr.Call expr) {
- Object callee = evaluate(expr.callee);
-
- List<Object> arguments = new ArrayList<>();
- for (Expr argument : expr.arguments) {
- arguments.add(evaluate(argument));
- }
-
- if (!(callee instanceof LoxCallable)) {
- throw new RuntimeError(expr.paren, "Can only call functions and classes.");
- }
-
- LoxCallable function = (LoxCallable) callee;
- if (arguments.size() != function.arity()) {
- throw new RuntimeError(expr.paren,
- "Expected " + function.arity() + " arguments but got " + arguments.size() + ".");
- }
-
- return function.call(this, arguments);
- }
-
- @Override
- public Object visitGetExpr(Expr.Get expr) {
- Object object = evaluate(expr.object);
- if (object instanceof LoxInstance) {
- return ((LoxInstance) object).get(expr.name);
- }
-
- throw new RuntimeError(expr.name, "Only instances have properties.");
- }
-
- public void interpret(List<Stmt> statements) {
- try {
- for (Stmt statement : statements) {
- execute(statement);
- }
- } catch (RuntimeError error) {
- Lox.runtimeError(error);
- }
- }
-}