diff --git a/ruby/lib/lox/environment.rb b/ruby/lib/lox/environment.rb index 91366c6..543e07e 100644 --- a/ruby/lib/lox/environment.rb +++ b/ruby/lib/lox/environment.rb @@ -2,6 +2,8 @@ require_relative "error" module Lox class Environment + attr_reader :values, :enclosing + def initialize(enclosing = nil) @enclosing = enclosing @values = {} @@ -11,6 +13,12 @@ module Lox @values[name] = value end + def ancestor(distance) + env = self + distance.times { env = env.enclosing } + env + end + def get(token) name = token.lexeme @@ -23,6 +31,10 @@ module Lox end end + def get_at(distance, name) + ancestor(distance).values.fetch(name) + end + def assign(name, value) lexeme = name.lexeme diff --git a/ruby/test/lox/test_environment.rb b/ruby/test/lox/test_environment.rb index 1838a3d..fd5b3ee 100644 --- a/ruby/test/lox/test_environment.rb +++ b/ruby/test/lox/test_environment.rb @@ -44,4 +44,16 @@ class TestEnvironment < Lox::Test assert_equal "qux", enclosed.get(NAME_TOKEN) assert_equal "bar", @env.get(NAME_TOKEN) end + + def test_get_at + @env.define("name", "foo") + enclosed = Lox::Environment.new(@env) + enclosed.define("name", "bar") + + assert_equal "foo", enclosed.get_at(1, "name") + assert_equal "bar", enclosed.get_at(0, "name") + + assert_equal "foo", @env.get_at(0, "name") + end + end