9.2
FossilOrigin-Name: d0e9947d95fd8cad638edb04ff5d9d450516434320a54f6d478214d6e90800b5
change qktupzzplzvktpmlyuyptsmlumzklswt
commit c91a9a5f01d02bebaea40816bcc19f5b9b4e9c84
author alpha <alpha@kejadlen.dev>
date
parent otoymnnl
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)