From cd50d4283ef3aa12df9d4f98d32b365c1912d725 Mon Sep 17 00:00:00 2001 From: alpha Date: Fri, 12 Aug 2022 21:56:51 +0000 Subject: [PATCH] 9.3 FossilOrigin-Name: a8acba027eac65be97ac3bcd57fbdd71b177c922f1bc8c18deb9864de2a9da33 --- ruby/lib/lox/expr.rb | 4 ++++ ruby/lib/lox/interpreter.rb | 12 ++++++++++++ ruby/lib/lox/parser.rb | 26 +++++++++++++++++++++++++- ruby/test/lox/test_interpreter.rb | 10 ++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) 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)