diff --git a/ruby/lib/lox/function.rb b/ruby/lib/lox/function.rb index f1f5475..0751ff5 100644 --- a/ruby/lib/lox/function.rb +++ b/ruby/lib/lox/function.rb @@ -2,14 +2,14 @@ require_relative "environment" module Lox class Function - def initialize(decl, closure) - @decl, @closure = decl, closure + def initialize(decl, closure, is_initializer) + @decl, @closure, @is_initializer = decl, closure, is_initializer end def bind(instance) env = Environment.new(@closure) env.define("this", instance) - Function.new(@decl, env) + Function.new(@decl, env, @is_initializer) end def arity = @decl.params.size @@ -20,9 +20,13 @@ module Lox env.define(name, value) end - catch(:return) { + return_value = catch(:return) { interpreter.execute_block(@decl.body, env) } + + return @closure.get_at(0, "this") if @is_initializer + + return_value end def to_s = "" diff --git a/ruby/lib/lox/interpreter.rb b/ruby/lib/lox/interpreter.rb index 1774d51..95c8737 100644 --- a/ruby/lib/lox/interpreter.rb +++ b/ruby/lib/lox/interpreter.rb @@ -48,7 +48,7 @@ module Lox @env.define(stmt.name.lexeme, nil) methods = stmt.methods.to_h {|method| - [method.name.lexeme, Function.new(method, @env)] + [method.name.lexeme, Function.new(method, @env, method.name.lexeme == "init")] } klass = LoxClass.new(stmt.name.lexeme, methods) @@ -73,7 +73,7 @@ module Lox end def visit_function(stmt) - function = Function.new(stmt, @env) + function = Function.new(stmt, @env, false) @env.define(stmt.name.lexeme, function) nil end diff --git a/ruby/test/lox/test_interpreter.rb b/ruby/test/lox/test_interpreter.rb index 73e42df..849af6b 100644 --- a/ruby/test/lox/test_interpreter.rb +++ b/ruby/test/lox/test_interpreter.rb @@ -416,6 +416,23 @@ class TestInterpreter < Lox::Test end end + def test_init + assert_interpreted <<~EXPECTED.chomp, <<~SRC + Foo instance + Foo instance + Foo instance + EXPECTED + class Foo { + init() { + print this; + } + } + + var foo = Foo(); + print foo.init(); + SRC + end + private def assert_interpreted(expected, src)