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)