8.challenges.1
FossilOrigin-Name: 4dd1670a4466cf079d61e11677e4aa8dd9b9ec096700e2ae565a4073ec4efc12
diff --git a/ruby/bin/lox b/ruby/bin/lox
index 4cbfcbb..8e03bf6 100755
--- a/ruby/bin/lox
+++ b/ruby/bin/lox
@@ -4,33 +4,17 @@ $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
require "lox"
-def run_prompt
+def run_prompt(runner)
loop do
print "> "
line = gets
break if line.nil? || line.empty?
- begin
- run(line)
- rescue Lox::ParseError => e
- STDERR.puts e.message
- rescue Lox::RuntimeError => e
- STDERR.puts e.message
- end
+ runner.run(line)
end
end
-def run_file(io)
- run(io.read)
-rescue Lox::ParseError => e
- STDERR.puts e.message
- exit 65
-rescue Lox::RuntimeError => e
- STDERR.puts e.message, "[line #{e.token.line}]"
- exit 70
-end
-
-def run(src)
- Lox::Runner.new.run(src)
+def run_file(runner, io)
+ runner.run(io.read)
end
@@ -38,8 +22,8 @@ if __FILE__ == $0
puts "Usage: #$0 [script]" or exit 64 if ARGV.length > 1
if ARGV.empty?
- run_prompt
+ run_prompt(Lox::PromptRunner.new)
else
- run_file(ARGF)
+ Lox::FileRunner.new.run(ARGF.read)
end
end
diff --git a/ruby/lib/lox.rb b/ruby/lib/lox.rb
index 3cb4e82..9a7ce98 100644
--- a/ruby/lib/lox.rb
+++ b/ruby/lib/lox.rb
@@ -10,18 +10,48 @@ require_relative "lox/token"
module Lox
class Runner
+ def initialize(scanner: Scanner.new, interpreter: Interpreter.new)
+ @scanner, @interpreter = scanner, interpreter
+ end
+
+ def run(src) = interpret(parse(scan(src)))
+
+ def scan(src) = @scanner.scan(src)
+ def parse(tokens) = Parser.new(tokens).parse!
+ def interpret(stmts) = @interpreter.interpret(stmts)
+ end
+
+ class FileRunner < Runner
+ def run(src)
+ super
+ rescue Lox::ParseError => e
+ STDERR.puts e.message
+ exit 65
+ rescue Lox::RuntimeError => e
+ STDERR.puts e.message, "[line #{e.token.line}]"
+ exit 70
+ end
+ end
+
+ class PromptRunner < Runner
def initialize
- @scanner = Scanner.new
- @parser = Parser.new
- @interpreter = Interpreter.new
+ super(interpreter: Interpreter.new(Environment.new))
end
def run(src)
- tokens = @scanner.scan(src)
- expr = @parser.parse(tokens)
- value = @interpreter.interpret(expr)
+ super
+ rescue Lox::ParseError => e
+ STDERR.puts e.message
+ rescue Lox::RuntimeError => e
+ STDERR.puts e.message
+ end
- puts value
+ def parse(tokens)
+ stmts = Parser.new(tokens).parse!
+ if stmts.last.instance_of?(Stmt::Expr)
+ stmts << Stmt::Print.new(stmts.pop.expr)
+ end
+ stmts
end
end
end
diff --git a/ruby/lib/lox/interpreter.rb b/ruby/lib/lox/interpreter.rb
index 3725811..0066043 100644
--- a/ruby/lib/lox/interpreter.rb
+++ b/ruby/lib/lox/interpreter.rb
@@ -3,8 +3,8 @@ require_relative "environment"
module Lox
class Interpreter
- def initialize
- @env = Environment.new
+ def initialize(env=Environment.new)
+ @env = env
end
# The book does printing and error catching here, but