9.3
FossilOrigin-Name: a8acba027eac65be97ac3bcd57fbdd71b177c922f1bc8c18deb9864de2a9da33
change pvlovrqrwptnmvnoyqkxoqkovruunksn
commit 9ac5a0c849061625db2ddd97976f51461c2faf49
author alpha <alpha@kejadlen.dev>
date
parent qktupzzp
diff --git a/ruby/lib/lox/expr.rb b/ruby/lib/lox/expr.rb
index 606e5dd..70da550 100644
--- a/ruby/lib/lox/expr.rb
+++ b/ruby/lib/lox/expr.rb
@@ -18,6 +18,10 @@ module Lox
       include Visitable
     end
 
+    Logical = Struct.new(:left, :op, :right) do
+      include Visitable
+    end
+
     Unary = Struct.new(:op, :right) do
       include Visitable
     end
diff --git a/ruby/lib/lox/interpreter.rb b/ruby/lib/lox/interpreter.rb
index 494fe26..3d7240e 100644
--- a/ruby/lib/lox/interpreter.rb
+++ b/ruby/lib/lox/interpreter.rb
@@ -62,6 +62,18 @@ module Lox
     def visit_grouping(expr) = evaluate(expr.expr)
     def visit_literal(expr)  = expr.value
 
+    def visit_logical(expr)
+      left = evaluate(expr.left)
+
+      if expr.op.type == :OR
+        return left if truthy?(left)
+      else
+        return left unless truthy?(left)
+      end
+
+      evaluate(expr.right)
+    end
+
     def visit_unary(expr)
       right = evaluate(expr.right)
 
diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb
index a30f4ff..421fe67 100644
--- a/ruby/lib/lox/parser.rb
+++ b/ruby/lib/lox/parser.rb
@@ -77,7 +77,7 @@ module Lox
     end
 
     def assignment
-      expr = equality
+      expr = or_
 
       if match?(:EQUAL)
         eq = prev
@@ -91,6 +91,30 @@ module Lox
       expr
     end
 
+    def or_
+      expr = and_
+
+      while match?(:OR)
+        op = prev
+        right = and_
+        expr = Expr::Logical.new(expr, op, right)
+      end
+
+      expr
+    end
+
+    def and_
+      expr = equality
+
+      while match?(:AND)
+        op = prev
+        right = equality
+        expr = Expr::Logical.new(expr, op, right)
+      end
+
+      expr
+    end
+
     def expression = assignment
 
     def equality
diff --git a/ruby/test/lox/test_interpreter.rb b/ruby/test/lox/test_interpreter.rb
index 5bc5e41..4f5b8be 100644
--- a/ruby/test/lox/test_interpreter.rb
+++ b/ruby/test/lox/test_interpreter.rb
@@ -176,6 +176,16 @@ class TestInterpreter < Lox::Test
     SRC
   end
 
+  def test_logical
+    assert_interpreted <<~EXPECTED.chomp, <<~SRC
+      hi
+      yes
+    EXPECTED
+      print "hi" or 2; // "hi".
+      print nil or "yes"; // "yes".
+    SRC
+  end
+
   private
 
   def assert_interpreted(expected, src)