diff --git a/src/com/craftinginterpreters/lox/Interpreter.java b/src/com/craftinginterpreters/lox/Interpreter.java index fd13455..ac42369 100644 --- a/src/com/craftinginterpreters/lox/Interpreter.java +++ b/src/com/craftinginterpreters/lox/Interpreter.java @@ -62,6 +62,11 @@ class Interpreter implements Expr.Visitor, Stmt.Visitor { return value; } + @Override + public Object visitThisExpr(Expr.This expr) { + return lookUpVariable(expr.keyword, expr); + } + @Override public Object visitUnaryExpr(Expr.Unary expr) { Object right = evaluate(expr.right); diff --git a/src/com/craftinginterpreters/lox/LoxFunction.java b/src/com/craftinginterpreters/lox/LoxFunction.java index fb3e8e3..371b822 100644 --- a/src/com/craftinginterpreters/lox/LoxFunction.java +++ b/src/com/craftinginterpreters/lox/LoxFunction.java @@ -11,6 +11,12 @@ class LoxFunction implements LoxCallable { this.declaration = declaration; } + LoxFunction bind(LoxInstance instance) { + Environment environment = new Environment(closure); + environment.define("this", instance); + return new LoxFunction(declaration, environment); + } + @Override public int arity() { return declaration.params.size(); diff --git a/src/com/craftinginterpreters/lox/LoxInstance.java b/src/com/craftinginterpreters/lox/LoxInstance.java index 20accaa..64989e0 100644 --- a/src/com/craftinginterpreters/lox/LoxInstance.java +++ b/src/com/craftinginterpreters/lox/LoxInstance.java @@ -18,7 +18,7 @@ class LoxInstance { LoxFunction method = klass.findMethod(name.lexeme); if (method != null) - return method; + return method.bind(this); throw new RuntimeError(name, "Undefined proprety '" + name.lexeme + "'."); } diff --git a/src/com/craftinginterpreters/lox/Parser.java b/src/com/craftinginterpreters/lox/Parser.java index fe51e45..a3f4897 100644 --- a/src/com/craftinginterpreters/lox/Parser.java +++ b/src/com/craftinginterpreters/lox/Parser.java @@ -355,6 +355,8 @@ class Parser { return new Expr.Literal(previous().literal); } + if (match(THIS)) return new Expr.This(previous()); + if (match(IDENTIFIER)) { return new Expr.Variable(previous()); } diff --git a/src/com/craftinginterpreters/lox/Resolver.java b/src/com/craftinginterpreters/lox/Resolver.java index 649235a..f68e4dc 100644 --- a/src/com/craftinginterpreters/lox/Resolver.java +++ b/src/com/craftinginterpreters/lox/Resolver.java @@ -37,11 +37,16 @@ class Resolver implements Expr.Visitor, Stmt.Visitor { declare(stmt.name); define(stmt.name); + beginScope(); + scopes.peek().put("this", true); + for (Stmt.Function method : stmt.methods) { FunctionType declaration = FunctionType.METHOD; resolveFunction(method, declaration); } + endScope(); + return null; } @@ -154,6 +159,12 @@ class Resolver implements Expr.Visitor, Stmt.Visitor { return null; } + @Override + public Void visitThisExpr(Expr.This expr) { + resolveLocal(expr, expr.keyword); + return null; + } + @Override public Void visitLogicalExpr(Expr.Logical expr) { resolve(expr.left); diff --git a/src/com/craftinginterpreters/tool/GenerateAst.java b/src/com/craftinginterpreters/tool/GenerateAst.java index 0ca2239..2097e31 100644 --- a/src/com/craftinginterpreters/tool/GenerateAst.java +++ b/src/com/craftinginterpreters/tool/GenerateAst.java @@ -19,7 +19,7 @@ public class GenerateAst { "Call : Expr callee, Token paren, List arguments", "Get : Expr object, Token name", "Grouping : Expr expression", "Literal : Object value", "Logical : Expr left, Token operator, Expr right", "Set : Expr object, Token name, Expr value", - "Unary : Token operator, Expr right", "Variable : Token name")); + "This : Token keyword", "Unary : Token operator, Expr right", "Variable : Token name")); defineAst(outputDir, "Stmt", Arrays.asList("Block : List statements", "Class : Token name, List methods", "Expression : Expr expression", "Function : Token name, List params, List body",