Alpha Chen 2 years ago
parent 952bd06dce
commit ec7a788377

@ -18,6 +18,7 @@ module Lox
expr :Literal, :value
expr :Logical, :left, :op, :right
expr :Set, :object, :name, :value
expr :This, :keyword
expr :Unary, :op, :right
expr :Variable, :name
end

@ -6,6 +6,12 @@ module Lox
@decl, @closure = decl, closure
end
def bind(instance)
env = Environment.new(@closure)
env.define("this", instance)
Function.new(@decl, env)
end
def arity = @decl.params.size
def call(interpreter, args)

@ -13,7 +13,7 @@ module Lox
return @fields.fetch(name.lexeme) if @fields.has_key?(name.lexeme)
method = @klass.find_method(name.lexeme)
return method unless method.nil?
return method.bind(self) unless method.nil?
raise RuntimeError.new(name, "Undefined property '#{name.lexeme}'.")
end

@ -136,6 +136,8 @@ module Lox
value
end
def visit_this(expr) = lookup_var(expr.keyword, expr)
def visit_unary(expr)
right = evaluate(expr.right)

@ -308,6 +308,7 @@ module Lox
return Expr::Literal.new(true) if match?(:TRUE)
return Expr::Literal.new(nil) if match?(:NIL)
return Expr::Literal.new(prev.literal) if match?(:NUMBER, :STRING)
return Expr::This.new(prev) if match?(:THIS)
return Expr::Variable.new(prev) if match?(:IDENTIFIER)
if match?(:LEFT_PAREN)

@ -27,11 +27,16 @@ module Lox
def visit_class(stmt)
declare(stmt.name)
stmt.methods.each do |method|
resolve_function(method, :METHOD)
with_scope do
@scopes.last["this"] = true
stmt.methods.each do |method|
resolve_function(method, :METHOD)
end
define(stmt.name)
end
define(stmt.name)
nil
end
@ -98,6 +103,11 @@ module Lox
nil
end
def visit_this(expr)
resolve_local(expr, expr.keyword)
nil
end
def visit_unary(expr) = resolve(expr.right)
private

@ -356,22 +356,50 @@ class TestInterpreter < Lox::Test
Bacon().eat(); // Prints "Crunch crunch crunch!".
SRC
# assert_interpreted "", <<~SRC
# class Person {
# sayName() {
# print this.name;
# }
# }
# var jane = Person();
# jane.name = "Jane";
# var bill = Person();
# bill.name = "Bill";
# bill.sayName = jane.sayName;
# bill.sayName(); // "Jane"
# SRC
assert_interpreted "The German chocolate cake is delicious!", <<~SRC
class Cake {
taste() {
var adjective = "delicious";
print "The " + this.flavor + " cake is " + adjective + "!";
}
}
var cake = Cake();
cake.flavor = "German chocolate";
cake.taste(); // Prints "The German chocolate cake is delicious!".
SRC
assert_interpreted "Thing instance", <<~SRC
class Thing {
getCallback() {
fun localFunction() {
print this;
}
return localFunction;
}
}
var callback = Thing().getCallback();
callback();
SRC
assert_interpreted "Jane", <<~SRC
class Person {
sayName() {
print this.name;
}
}
var jane = Person();
jane.name = "Jane";
var bill = Person();
bill.name = "Bill";
bill.sayName = jane.sayName;
bill.sayName(); // "Jane"
SRC
end
private

Loading…
Cancel
Save