FossilOrigin-Name: 0d44d8a3a62b9bd884f12a5497f7b085c6727ae0861100ca22488b67564750df
private
alpha 2 years ago
parent fb649eeaba
commit 1cb62101d8

@ -10,17 +10,24 @@ module Lox
def visit_print(expr) = parenthesize("print", expr.expr)
def visit_var(expr)
if init = expr.initializer
"(assign #{expr.name.lexeme} #{expr.initializer.value})"
else
exprs = [expr.initializer].reject(&:nil?)
parenthesize("var #{expr.name.lexeme}", *exprs)
end
def visit_variable(expr)
"(var #{expr.name.lexeme})"
end
def visit_assign(expr)
parenthesize("assign #{expr.name.lexeme}", expr.value)
end
private
def parenthesize(name, *exprs)
"(#{name} #{exprs.map {|expr| expr.accept(self) }.join(" ")})"
inside = [name]
inside.concat(exprs.map {|expr| expr.accept(self) })
"(#{inside.join(" ")})"
end
end
end

@ -1,3 +1,5 @@
require_relative "error"
module Lox
class Environment
def initialize
@ -13,5 +15,11 @@ module Lox
@values.fetch(name) { raise RuntimeError.new(token, "Undefined variable '#{name}'.") }
end
def assign(name, value)
raise RuntimeError.new(name, "Undefined variable '#{name.lexeme}'.") unless @values.has_key?(name.lexeme)
@values[name.lexeme] = value
end
end
end

@ -52,6 +52,12 @@ module Lox
@env.get(expr.name)
end
def visit_assign(expr)
value = evaluate(expr.value)
@env.assign(expr.name, value)
value
end
def visit_binary(expr)
left = evaluate(expr.left)
right = evaluate(expr.right)

@ -63,13 +63,13 @@ module Lox
raise ParseError.new(eq, "Invalid assignment target.") unless expr.instance_of?(Expr::Variable)
Expr::Assign.new(expr.name, value)
return Expr::Assign.new(expr.name, value)
end
expr
end
def expression = equality
def expression = assignment
def equality
expr = comparison

@ -107,6 +107,15 @@ class TestInterpreter < Lox::Test
SRC
end
def test_assignment
assert_interpreted <<~EXPECTED.chomp, <<~SRC
2
EXPECTED
var a = 1;
print a = 2;
SRC
end
private
def assert_interpreted(expected, src)

@ -53,10 +53,11 @@ class TestParser < Lox::Test
def test_var
assert_parsed "(var foo)", :declaration, "var foo;"
assert_parsed "(var foo 42.0)", :declaration, "var foo = 42.0;"
end
def test_assign
assert_parsed "(assign foo 42.0)", :declaration, "var foo = 42.0;"
assert_parsed "(print (assign foo 42.0))", :declaration, "print foo = 42.0;"
end
private

Loading…
Cancel
Save