12.7.1
change xuzvtlumoyywnmuqxtrqnvyloytolrmz
commit 2875cc243e5dbca34a018f227f82f0931afa9227
author Alpha Chen <alpha@kejadlen.dev>
date
parent ovslyxyq
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 = "<fn #{@decl.name.lexeme}>"
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)