FossilOrigin-Name: f2b21a08789cde121fca0488c7fbe95cb01b98589dc92ac383f4d42847b2433e
private
alpha 2 years ago
parent 1cb62101d8
commit b879ae44ff

@ -2,7 +2,8 @@ require_relative "error"
module Lox module Lox
class Environment class Environment
def initialize def initialize(enclosing = nil)
@enclosing = enclosing
@values = {} @values = {}
end end
@ -13,13 +14,27 @@ module Lox
def get(token) def get(token)
name = token.lexeme name = token.lexeme
@values.fetch(name) { raise RuntimeError.new(token, "Undefined variable '#{name}'.") } @values.fetch(name) {
raise RuntimeError.new(token, "Undefined variable '#{name}'.") if @enclosing.nil?
@enclosing.get(token)
}
end end
def assign(name, value) def assign(name, value)
raise RuntimeError.new(name, "Undefined variable '#{name.lexeme}'.") unless @values.has_key?(name.lexeme) lexeme = name.lexeme
if @values.has_key?(lexeme)
@values[lexeme] = value
return
end
unless @enclosing.nil?
@enclosing.assign(name, value)
return
end
@values[name.lexeme] = value raise RuntimeError.new(name, "Undefined variable '#{lexeme}'.")
end end
end end
end end

@ -5,6 +5,8 @@ require "lox/error"
require "lox/token" require "lox/token"
class TestEnvironment < Lox::Test class TestEnvironment < Lox::Test
NAME_TOKEN = Lox::Token.new(:IDENTIFIER, "name", "name", 0)
def setup def setup
@env = Lox::Environment.new @env = Lox::Environment.new
end end
@ -12,12 +14,34 @@ class TestEnvironment < Lox::Test
def test_define def test_define
@env.define("name", "value") @env.define("name", "value")
assert_equal "value", @env.get(Lox::Token.new(:IDENTIFIER, "name", "name", 0)) assert_equal "value", @env.get(NAME_TOKEN)
end end
def test_get def test_get
assert_raises Lox::RuntimeError, "Undefined variable name 'name'." do assert_raises Lox::RuntimeError, "Undefined variable name 'name'." do
@env.get(Lox::Token.new(:IDENTIFIER, "name", "name", 0)) @env.get(NAME_TOKEN)
end end
end end
def test_enclosing_define
@env.define("name", "value")
enclosed = Lox::Environment.new(@env)
assert_equal "value", enclosed.get(NAME_TOKEN)
enclosed.define("name", "foo")
assert_equal "foo", enclosed.get(NAME_TOKEN)
end
def test_enclosing_assign
@env.define("name", "foo")
enclosed = Lox::Environment.new(@env)
enclosed.assign(NAME_TOKEN, "bar")
assert_equal "bar", enclosed.get(NAME_TOKEN)
assert_equal "bar", @env.get(NAME_TOKEN)
enclosed.define("name", "baz")
enclosed.assign(NAME_TOKEN, "qux")
assert_equal "qux", enclosed.get(NAME_TOKEN)
assert_equal "bar", @env.get(NAME_TOKEN)
end
end end

Loading…
Cancel
Save