Class: Fusion::CLI::Repl

Inherits:
Object
  • Object
show all
Defined in:
lib/fusion/cli/repl.rb

Constant Summary collapse

PROMPT =
"fsn> "
CONTINUATION_PROMPT =
"...> "
LOCATION =

REPL entries report errors with the same location as inline (‘-e`) code.

"code <inline>"

Instance Method Summary collapse

Instance Method Details

#complete?(buffer) ⇒ Boolean

Returns:

  • (Boolean)


43
44
45
46
47
48
# File 'lib/fusion/cli/repl.rb', line 43

def complete?(buffer)
  return true if buffer.strip.empty?

  ast = Fusion::Parser.parse_repl(buffer, location: LOCATION)
  ast.is_a?(AST::Expression) || ast.is_a?(AST::Statement::Assignment)
end

#handle(buffer, environment) ⇒ Object



50
51
52
53
54
55
# File 'lib/fusion/cli/repl.rb', line 50

def handle(buffer, environment)
  ast = Fusion::Parser.parse_repl(buffer, location: LOCATION)
  runtime_value = evaluate(ast, environment)
  wire_pair = Serializer.serialize(runtime_value, lenient: true)
  Encoder.encode(wire_pair, mode: :bang)
end

#runObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/fusion/cli/repl.rb', line 18

def run
  require "reline"
  $stdout.sync = true
  Reline.output = $stderr
  Reline.prompt_proc = proc do |lines|
    lines.each_index.map { |i| i.zero? ? PROMPT : CONTINUATION_PROMPT }
  end

  environment = Interpreter::Env.new.define("__dir__", Dir.pwd)

  loop do
    buffer = begin
      Reline.readmultiline(PROMPT, true) { complete?(_1) }
    rescue Interrupt
      $stderr.puts("^C") # discard the half-typed entry and re-prompt
      next
    end

    break if buffer.nil? # Ctrl-D on an empty line ends the session
    next if buffer.strip.empty?

    $stdout.puts(handle(buffer, environment))
  end
end