10.5.1
change klsknrsqvzknvlnqpztmqksvwtluoomw
commit f5fcb5757dbd5fb21e48b5c025b70d43cec5c199
author Alpha Chen <alpha@kejadlen.dev>
date
parent rsuvptyt
diff --git a/ruby/lib/lox/ast_printer.rb b/ruby/lib/lox/ast_printer.rb
index ae8bdd1..f7578b4 100644
--- a/ruby/lib/lox/ast_printer.rb
+++ b/ruby/lib/lox/ast_printer.rb
@@ -48,9 +48,7 @@ module Lox
     private
 
     def parenthesize(name, *exprs)
-      inside = [name]
-      inside.concat(exprs.map {|expr| expr.accept(self) })
-      "(#{inside.join(" ")})"
+      "(#{[name, *exprs.map { _1.accept(self) }].join(" ")})"
     end
   end
 end
diff --git a/ruby/lib/lox/function.rb b/ruby/lib/lox/function.rb
index 298a1a0..2f291a0 100644
--- a/ruby/lib/lox/function.rb
+++ b/ruby/lib/lox/function.rb
@@ -14,8 +14,9 @@ module Lox
         env.define(name, value)
       end
 
-      interpreter.execute_block(@decl.body, env)
-      nil
+      catch(:return) {
+        interpreter.execute_block(@decl.body, env)
+      }
     end
 
     def to_s = "<fn #{@decl.name.lexeme}>"
diff --git a/ruby/lib/lox/interpreter.rb b/ruby/lib/lox/interpreter.rb
index 8e9b305..1cd5536 100644
--- a/ruby/lib/lox/interpreter.rb
+++ b/ruby/lib/lox/interpreter.rb
@@ -69,6 +69,12 @@ module Lox
       nil
     end
 
+    def visit_return(stmt)
+      value = stmt.value ? evaluate(stmt.value) : nil
+
+      throw(:return, value)
+    end
+
     def visit_var(stmt)
       value = stmt.initializer&.yield_self { evaluate(_1) }
       @env.define(stmt.name.lexeme, value)
diff --git a/ruby/test/lox/test_interpreter.rb b/ruby/test/lox/test_interpreter.rb
index 7960957..3b89b2f 100644
--- a/ruby/test/lox/test_interpreter.rb
+++ b/ruby/test/lox/test_interpreter.rb
@@ -235,6 +235,28 @@ class TestInterpreter < Lox::Test
       sayHi("Dear", "Reader");
     SRC
   end
+
+  def test_function
+    assert_interpreted <<~EXPECTED.chomp, <<~SRC
+      0
+      1
+      1
+      2
+      3
+      5
+      8
+    EXPECTED
+      fun fib(n) {
+        if (n <= 1) return n;
+        return fib(n - 2) + fib(n - 1);
+      }
+
+      for (var i = 0; i < 7; i = i + 1) {
+        print fib(i);
+      }
+    SRC
+  end
+
   private
 
   def assert_interpreted(expected, src)