Skip to content

Commit

Permalink
Add Crystal::Repl#parse_and_interpret (#14138)
Browse files Browse the repository at this point in the history
* Add Crystal::Repl#parse_and_interpret

* Use single EvalResult type

* skip if without_interpreter
  • Loading branch information
bcardiff authored Jan 2, 2024
1 parent d15435d commit 316422f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
20 changes: 20 additions & 0 deletions spec/compiler/crystal/tools/repl_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{% skip_file if flag?(:without_interpreter) %}

require "../../../spec_helper"

private def success_value(result : Crystal::Repl::EvalResult) : Crystal::Repl::Value
result.warnings.infos.should be_empty
result.value.should_not be_nil
end

describe Crystal::Repl do
it "can parse and evaluate snippets" do
repl = Crystal::Repl.new
repl.prelude = "primitives"
repl.load_prelude

success_value(repl.parse_and_interpret("1 + 2")).value.should eq(3)
success_value(repl.parse_and_interpret("def foo; 1 + 2; end")).value.should eq(nil)
success_value(repl.parse_and_interpret("foo")).value.should eq(3)
end
end
24 changes: 17 additions & 7 deletions src/compiler/crystal/interpreter/repl.cr
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,13 @@ class Crystal::Repl
when "exit"
break
when .presence
parser = new_parser(expression)
parser.warnings.report(STDOUT)
result = parse_and_interpret(expression)
result.warnings.report(STDOUT)

node = parser.parse
next unless node
next unless result.value

value = interpret(node)
print " => "
puts SyntaxHighlighter::Colorize.highlight!(value.to_s)
puts SyntaxHighlighter::Colorize.highlight!(result.value.to_s)
end
rescue ex : EscapingException
print "Unhandled exception: "
Expand All @@ -44,6 +42,18 @@ class Crystal::Repl
end
end

record EvalResult, value : Value?, warnings : WarningCollection

def parse_and_interpret(expression : String) : EvalResult
parser = new_parser(expression)

node = parser.parse
return EvalResult.new(value: nil, warnings: parser.warnings) unless node

value = interpret(node)
return EvalResult.new(value: value, warnings: parser.warnings)
end

def run_file(filename, argv)
@interpreter.argv = argv

Expand All @@ -68,7 +78,7 @@ class Crystal::Repl
interpret(exps)
end

private def load_prelude
def load_prelude
node = parse_prelude

interpret_and_exit_on_error(node)
Expand Down

0 comments on commit 316422f

Please sign in to comment.