9.2
FossilOrigin-Name: d0e9947d95fd8cad638edb04ff5d9d450516434320a54f6d478214d6e90800b5
diff --git a/ruby/lib/lox/ast_printer.rb b/ruby/lib/lox/ast_printer.rb
index a073805..a303c5f 100644
--- a/ruby/lib/lox/ast_printer.rb
+++ b/ruby/lib/lox/ast_printer.rb
@@ -26,6 +26,16 @@ module Lox
parenthesize("block", *expr.stmts)
end
+ def visit_if(stmt)
+ exprs = [stmt.cond, stmt.then]
+ exprs << stmt.else if stmt.else
+ parenthesize("if", *exprs)
+ end
+
+ def visit_expr(expr)
+ expr.expr.accept(self)
+ end
+
private
def parenthesize(name, *exprs)
diff --git a/ruby/lib/lox/interpreter.rb b/ruby/lib/lox/interpreter.rb
index 0066043..494fe26 100644
--- a/ruby/lib/lox/interpreter.rb
+++ b/ruby/lib/lox/interpreter.rb
@@ -39,6 +39,15 @@ module Lox
nil
end
+ def visit_if(stmt)
+ if truthy?(evaluate(stmt.cond))
+ evaluate(stmt.then)
+ elsif stmt.else
+ evaluate(stmt.else)
+ end
+ nil
+ end
+
def visit_print(expr)
puts stringify(evaluate(expr.expr))
nil
diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb
index bfece21..a30f4ff 100644
--- a/ruby/lib/lox/parser.rb
+++ b/ruby/lib/lox/parser.rb
@@ -37,12 +37,24 @@ module Lox
end
def statement
+ return if_stmt if match?(:IF)
return print if match?(:PRINT)
return Stmt::Block.new(block) if match?(:LEFT_BRACE)
expression_stmt
end
+ def if_stmt
+ consume!(:LEFT_PAREN, "Expect '(' after 'if'.")
+ cond = expression
+ consume!(:RIGHT_PAREN, "Expect ')' after 'if'.")
+
+ then_stmt = statement
+ else_stmt = match?(:ELSE) ? statement : nil
+
+ Stmt::If.new(cond, then_stmt, else_stmt)
+ end
+
def print
value = expression
consume!(:SEMICOLON, "Expect ';' after value.")
diff --git a/ruby/lib/lox/stmt.rb b/ruby/lib/lox/stmt.rb
index ba05b17..8f95201 100644
--- a/ruby/lib/lox/stmt.rb
+++ b/ruby/lib/lox/stmt.rb
@@ -10,6 +10,10 @@ module Lox
include Visitable
end
+ If = Struct.new(:cond, :then, :else) do
+ include Visitable
+ end
+
Print = Struct.new(:expr) do
include Visitable
end
diff --git a/ruby/test/lox/test_interpreter.rb b/ruby/test/lox/test_interpreter.rb
index 53b8113..5bc5e41 100644
--- a/ruby/test/lox/test_interpreter.rb
+++ b/ruby/test/lox/test_interpreter.rb
@@ -159,6 +159,23 @@ class TestInterpreter < Lox::Test
SRC
end
+ def test_if
+ assert_interpreted <<~EXPECTED.chomp, <<~SRC
+ true
+ false
+ EXPECTED
+ if (true)
+ print "true";
+ else
+ print "false";
+
+ if (false)
+ print "true";
+ else
+ print "false";
+ 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 e5ad65c..aaad61e 100644
--- a/ruby/test/lox/test_parser.rb
+++ b/ruby/test/lox/test_parser.rb
@@ -69,6 +69,12 @@ class TestParser < Lox::Test
SRC
end
+ def test_if
+ assert_parsed "(if (var first) (if (var second) true false))", :statement, <<~SRC
+ if (first) if (second) true; else false;
+ SRC
+ end
+
private
def assert_parsed(expected, name, src)