9.3
FossilOrigin-Name: a8acba027eac65be97ac3bcd57fbdd71b177c922f1bc8c18deb9864de2a9da33
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)