8.4.2
FossilOrigin-Name: 0d44d8a3a62b9bd884f12a5497f7b085c6727ae0861100ca22488b67564750df
diff --git a/ruby/lib/lox/ast_printer.rb b/ruby/lib/lox/ast_printer.rb
index d394311..b79776b 100644
--- a/ruby/lib/lox/ast_printer.rb
+++ b/ruby/lib/lox/ast_printer.rb
@@ -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
- "(var #{expr.name.lexeme})"
- end
+ 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
diff --git a/ruby/lib/lox/environment.rb b/ruby/lib/lox/environment.rb
index 3f32be2..b568f69 100644
--- a/ruby/lib/lox/environment.rb
+++ b/ruby/lib/lox/environment.rb
@@ -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
diff --git a/ruby/lib/lox/interpreter.rb b/ruby/lib/lox/interpreter.rb
index c04c6e7..b712ffe 100644
--- a/ruby/lib/lox/interpreter.rb
+++ b/ruby/lib/lox/interpreter.rb
@@ -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)
diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb
index a2dc1dd..197cdef 100644
--- a/ruby/lib/lox/parser.rb
+++ b/ruby/lib/lox/parser.rb
@@ -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
diff --git a/ruby/test/lox/test_interpreter.rb b/ruby/test/lox/test_interpreter.rb
index af0eb94..fde7786 100644
--- a/ruby/test/lox/test_interpreter.rb
+++ b/ruby/test/lox/test_interpreter.rb
@@ -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)
diff --git a/ruby/test/lox/test_parser.rb b/ruby/test/lox/test_parser.rb
index 579676e..67b80ae 100644
--- a/ruby/test/lox/test_parser.rb
+++ b/ruby/test/lox/test_parser.rb
@@ -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