diff --git a/ruby/lib/lox/function.rb b/ruby/lib/lox/function.rb index 2f291a0..cc92c2f 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) - @decl = decl + def initialize(decl, closure) + @decl, @closure = decl, closure end def arity = @decl.params.size def call(interpreter, args) - env = Environment.new(interpreter.globals) + env = Environment.new(@closure) @decl.params.map(&:lexeme).zip(args).each do |name, value| env.define(name, value) end diff --git a/ruby/lib/lox/interpreter.rb b/ruby/lib/lox/interpreter.rb index 1cd5536..34cf8f3 100644 --- a/ruby/lib/lox/interpreter.rb +++ b/ruby/lib/lox/interpreter.rb @@ -50,7 +50,7 @@ module Lox end def visit_function(stmt) - function = Function.new(stmt) + function = Function.new(stmt, @env) @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 3b89b2f..0799786 100644 --- a/ruby/test/lox/test_interpreter.rb +++ b/ruby/test/lox/test_interpreter.rb @@ -257,6 +257,27 @@ class TestInterpreter < Lox::Test SRC end + def test_local_functions_and_closures + assert_interpreted <<~EXPECTED.chomp, <<~SRC + 1 + 2 + EXPECTED + fun makeCounter() { + var i = 0; + fun count() { + i = i + 1; + print i; + } + + return count; + } + + var counter = makeCounter(); + counter(); // "1". + counter(); // "2". + SRC + end + private def assert_interpreted(expected, src)