|
|
@ -55,11 +55,18 @@ module Lox
|
|
|
|
|
|
|
|
|
|
|
|
@env.define(stmt.name.lexeme, nil)
|
|
|
|
@env.define(stmt.name.lexeme, nil)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if superclass
|
|
|
|
|
|
|
|
@env = Environment.new(@env)
|
|
|
|
|
|
|
|
@env.define("super", superclass)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
methods = stmt.methods.to_h {|method|
|
|
|
|
methods = stmt.methods.to_h {|method|
|
|
|
|
[method.name.lexeme, Function.new(method, @env, method.name.lexeme == "init")]
|
|
|
|
[method.name.lexeme, Function.new(method, @env, method.name.lexeme == "init")]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
klass = LoxClass.new(stmt.name.lexeme, superclass, methods)
|
|
|
|
klass = LoxClass.new(stmt.name.lexeme, superclass, methods)
|
|
|
|
|
|
|
|
@env = @env.enclosing if superclass
|
|
|
|
|
|
|
|
|
|
|
|
@env.assign(stmt.name, klass)
|
|
|
|
@env.assign(stmt.name, klass)
|
|
|
|
nil
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -144,6 +151,16 @@ module Lox
|
|
|
|
value
|
|
|
|
value
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def visit_super(expr)
|
|
|
|
|
|
|
|
distance = @locals.fetch(expr)
|
|
|
|
|
|
|
|
superclass = @env.get_at(distance, "super")
|
|
|
|
|
|
|
|
object = @env.get_at(distance-1, "this")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
method = superclass.find_method(expr.method.lexeme)
|
|
|
|
|
|
|
|
raise RuntimeError.new(expr.method, "Undefined property '#{expr.method.lexeme}'.") if method.nil?
|
|
|
|
|
|
|
|
method.bind(object)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def visit_this(expr) = lookup_var(expr.keyword, expr)
|
|
|
|
def visit_this(expr) = lookup_var(expr.keyword, expr)
|
|
|
|
|
|
|
|
|
|
|
|
def visit_unary(expr)
|
|
|
|
def visit_unary(expr)
|
|
|
|