8.4.1
FossilOrigin-Name: f908d358ac9f54ee9935ba8f2b55c54e072cdda14ed3693b6959a828aef34a65
change lrqnquunqpzsxouqyqqqzwpssptzuyum
commit f41b8183d1a9bafe49bb183f84af80a5e4f3a0a6
author alpha <alpha@kejadlen.dev>
date
parent sypllprl
diff --git a/ruby/lib/lox/ast_printer.rb b/ruby/lib/lox/ast_printer.rb
index be30643..d394311 100644
--- a/ruby/lib/lox/ast_printer.rb
+++ b/ruby/lib/lox/ast_printer.rb
@@ -8,7 +8,14 @@ module Lox
     def visit_unary(expr)    = parenthesize(expr.op.lexeme, expr.right)
 
     def visit_print(expr)    = parenthesize("print", expr.expr)
-    def visit_var(expr)      = "(var #{expr.name.lexeme} #{expr.initializer.value})"
+
+    def visit_var(expr)
+      if init = expr.initializer
+        "(assign #{expr.name.lexeme} #{expr.initializer.value})"
+      else
+        "(var #{expr.name.lexeme})"
+      end
+    end
 
     private
 
diff --git a/ruby/lib/lox/expr.rb b/ruby/lib/lox/expr.rb
index 0f81c8f..606e5dd 100644
--- a/ruby/lib/lox/expr.rb
+++ b/ruby/lib/lox/expr.rb
@@ -2,6 +2,10 @@ require_relative "visitable"
 
 module Lox
   module Expr
+    Assign = Struct.new(:name, :value) do
+      include Visitable
+    end
+
     Binary = Struct.new(:left, :op, :right) do
       include Visitable
     end
diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb
index c263624..a2dc1dd 100644
--- a/ruby/lib/lox/parser.rb
+++ b/ruby/lib/lox/parser.rb
@@ -54,6 +54,21 @@ module Lox
       Stmt::Expr.new(value)
     end
 
+    def assignment
+      expr = equality
+
+      if match?(:EQUAL)
+        eq = prev
+        value = assignment
+
+        raise ParseError.new(eq, "Invalid assignment target.") unless expr.instance_of?(Expr::Variable)
+
+        Expr::Assign.new(expr.name, value)
+      end
+
+      expr
+    end
+
     def expression = equality
 
     def equality
diff --git a/ruby/test/lox/test_parser.rb b/ruby/test/lox/test_parser.rb
index cc9f1e9..579676e 100644
--- a/ruby/test/lox/test_parser.rb
+++ b/ruby/test/lox/test_parser.rb
@@ -52,7 +52,11 @@ class TestParser < Lox::Test
   end
 
   def test_var
-    assert_parsed "(var foo 42.0)", :declaration, "var foo = 42.0;"
+    assert_parsed "(var foo)", :declaration, "var foo;"
+  end
+
+  def test_assign
+    assert_parsed "(assign foo 42.0)", :declaration, "var foo = 42.0;"
   end
 
   private