12.5 This

This commit is contained in:
Tom Willemse 2021-04-18 17:25:03 -07:00
parent 591caeb216
commit 21a58ffb20
6 changed files with 26 additions and 2 deletions

View file

@ -62,6 +62,11 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
return value; return value;
} }
@Override
public Object visitThisExpr(Expr.This expr) {
return lookUpVariable(expr.keyword, expr);
}
@Override @Override
public Object visitUnaryExpr(Expr.Unary expr) { public Object visitUnaryExpr(Expr.Unary expr) {
Object right = evaluate(expr.right); Object right = evaluate(expr.right);

View file

@ -11,6 +11,12 @@ class LoxFunction implements LoxCallable {
this.declaration = declaration; this.declaration = declaration;
} }
LoxFunction bind(LoxInstance instance) {
Environment environment = new Environment(closure);
environment.define("this", instance);
return new LoxFunction(declaration, environment);
}
@Override @Override
public int arity() { public int arity() {
return declaration.params.size(); return declaration.params.size();

View file

@ -18,7 +18,7 @@ class LoxInstance {
LoxFunction method = klass.findMethod(name.lexeme); LoxFunction method = klass.findMethod(name.lexeme);
if (method != null) if (method != null)
return method; return method.bind(this);
throw new RuntimeError(name, "Undefined proprety '" + name.lexeme + "'."); throw new RuntimeError(name, "Undefined proprety '" + name.lexeme + "'.");
} }

View file

@ -355,6 +355,8 @@ class Parser {
return new Expr.Literal(previous().literal); return new Expr.Literal(previous().literal);
} }
if (match(THIS)) return new Expr.This(previous());
if (match(IDENTIFIER)) { if (match(IDENTIFIER)) {
return new Expr.Variable(previous()); return new Expr.Variable(previous());
} }

View file

@ -37,11 +37,16 @@ class Resolver implements Expr.Visitor<Void>, Stmt.Visitor<Void> {
declare(stmt.name); declare(stmt.name);
define(stmt.name); define(stmt.name);
beginScope();
scopes.peek().put("this", true);
for (Stmt.Function method : stmt.methods) { for (Stmt.Function method : stmt.methods) {
FunctionType declaration = FunctionType.METHOD; FunctionType declaration = FunctionType.METHOD;
resolveFunction(method, declaration); resolveFunction(method, declaration);
} }
endScope();
return null; return null;
} }
@ -154,6 +159,12 @@ class Resolver implements Expr.Visitor<Void>, Stmt.Visitor<Void> {
return null; return null;
} }
@Override
public Void visitThisExpr(Expr.This expr) {
resolveLocal(expr, expr.keyword);
return null;
}
@Override @Override
public Void visitLogicalExpr(Expr.Logical expr) { public Void visitLogicalExpr(Expr.Logical expr) {
resolve(expr.left); resolve(expr.left);

View file

@ -19,7 +19,7 @@ public class GenerateAst {
"Call : Expr callee, Token paren, List<Expr> arguments", "Get : Expr object, Token name", "Call : Expr callee, Token paren, List<Expr> arguments", "Get : Expr object, Token name",
"Grouping : Expr expression", "Literal : Object value", "Grouping : Expr expression", "Literal : Object value",
"Logical : Expr left, Token operator, Expr right", "Set : Expr object, Token name, Expr 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", defineAst(outputDir, "Stmt",
Arrays.asList("Block : List<Stmt> statements", "Class : Token name, List<Stmt.Function> methods", Arrays.asList("Block : List<Stmt> statements", "Class : Token name, List<Stmt.Function> methods",
"Expression : Expr expression", "Function : Token name, List<Token> params, List<Stmt> body", "Expression : Expr expression", "Function : Token name, List<Token> params, List<Stmt> body",