extract some classes, write some tests
FossilOrigin-Name: a0174386a70769c2c274f725ccb1a52a11ec925acdd6c63a1d13ceb8fd4fd9a8
change xlvzwyouowrqorywntvqmpqmquttwlzo
commit ec6830bcbc48a5930b4caf32ec77f219747cfe03
author alpha <alpha@kejadlen.dev>
date
parent ylnlqpmz
diff --git a/ruby/Gemfile b/ruby/Gemfile
index 88bd7be..b7c57df 100644
--- a/ruby/Gemfile
+++ b/ruby/Gemfile
@@ -5,4 +5,6 @@ source "https://rubygems.org"
 git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
 
 gem "minitest"
+gem "mocktail"
 gem "pry"
+gem "rake"
diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock
index 911cc11..dc09b9d 100644
--- a/ruby/Gemfile.lock
+++ b/ruby/Gemfile.lock
@@ -4,16 +4,20 @@ GEM
     coderay (1.1.3)
     method_source (1.0.0)
     minitest (5.16.2)
+    mocktail (1.1.3)
     pry (0.14.1)
       coderay (~> 1.1)
       method_source (~> 1.0)
+    rake (13.0.6)
 
 PLATFORMS
   arm64-darwin-21
 
 DEPENDENCIES
   minitest
+  mocktail
   pry
+  rake
 
 BUNDLED WITH
    2.3.18
diff --git a/ruby/lox.rb b/ruby/lox.rb
index af9d26d..e2b1c4a 100755
--- a/ruby/lox.rb
+++ b/ruby/lox.rb
@@ -1,8 +1,14 @@
 #!/usr/bin/env ruby -w
 
 module Lox
-  class << self
-    @had_error = false
+  class Error < StandardError
+    def initialize(line:, where: "", message:)
+      @line, @where, @message = line, where, message
+    end
+
+    def to_s
+      "[line #@line] Error#@where: #@message"
+    end
   end
 
   def self.run_prompt
@@ -10,33 +16,42 @@ module Lox
       print "> "
       line = gets
       break if line.empty?
-      run(line)
-      @had_error = false
+      begin
+        run(line)
+      rescue Error => e
+        puts e.message
+      end
     end
   end
 
   def self.run_file(io)
     run(io.read)
-
-    exit 65 if @had_error
+  rescue Error
+    puts e.message
+    exit 65
   end
 
   def self.run(src)
-    scanner = Scanner.new(src)
-    tokens = scanner.scan()
-
-    tokens.each do |token|
-      puts token
-    end
+    Runner.new(src).run
   end
 
   def self.error(line, msg)
-    report(line, "", msg)
+    raise Error(line:, message:)
   end
 
-  def self.report(line, where, message)
-    puts "[line #{line}] Error#{where}: #{message}"
-    @had_error = true;
+  class Runner
+    def initialize(scanner:)
+      @scanner = scanner
+    end
+
+    def run(src)
+      @scanner.scan(src)
+    end
+  end
+
+  class Scanner
+    def scan(src)
+    end
   end
 end
 
diff --git a/ruby/test_lox.rb b/ruby/test_lox.rb
index 1424231..b0f493a 100644
--- a/ruby/test_lox.rb
+++ b/ruby/test_lox.rb
@@ -1,8 +1,9 @@
-require "minitest/autorun"
-
 require "lox"
 
 require "open3"
+
+require "minitest/autorun"
+require "mocktail"
 require "pry"
 
 class TestLox < Minitest::Test
@@ -12,3 +13,21 @@ class TestLox < Minitest::Test
     assert_equal "Usage: ./lox.rb [script]\n", o
   end
 end
+
+class TestRunner < Minitest::Test
+  include Mocktail::DSL
+
+  def teardown
+    Mocktail.reset
+  end
+
+  def test_returns_tokens
+    scanner = Mocktail.of(Lox::Scanner)
+    runner = Lox::Runner.new(scanner:)
+    stubs { scanner.scan("src") }.with { %w[ some tokens ] }
+
+    tokens = runner.run("src")
+
+    assert_equal %w[ some tokens ], tokens
+  end
+end