Module: Fusion::CLI
- Extended by:
- CLI
- Included in:
- CLI
- Defined in:
- lib/fusion/cli.rb,
lib/fusion/cli/repl.rb,
lib/fusion/cli/parser.rb,
lib/fusion/cli/decoder.rb,
lib/fusion/cli/encoder.rb,
lib/fusion/cli/options.rb,
lib/fusion/cli/serializer.rb
Defined Under Namespace
Modules: Decoder, Encoder, Parser, Serializer Classes: Options, Repl
Instance Method Summary collapse
-
#apply(input, function, environment:) ⇒ Object
runtime value + runtime value -> runtime value input | function -> output Confines @-resolution to the environment's jail.
-
#decode(string, mode:) ⇒ Object
String (treated as stdin) -> WirePair Doesn't support mode
:unix. -
#encode(wire_pair, mode:) ⇒ Object
WirePair -> String Doesn't support mode
:unix. -
#evaluate(ast, environment) ⇒ Object
expression (AST) -> runtime value Mutates environment if given an assignment statement.
-
#load_file(rel_path, root_env) ⇒ Object
relative path -> runtime_value.
-
#load_source(inline_source, root_env) ⇒ Object
String (treated as inline source) -> runtime value.
-
#parse(wire_pair) ⇒ Object
WirePair -> runtime value.
- #prepare! ⇒ Object
-
#root_environment(jail: Dir.pwd) ⇒ Object
A binding-free root environment.
- #run(options) ⇒ Object
- #run_pipe(options) ⇒ Object
- #run_repl(options) ⇒ Object
- #run_stream(options) ⇒ Object
-
#serialize(runtime_value) ⇒ Object
runtime value -> WirePair CAUTION: resolves "internal" error status, only use for final output.
Instance Method Details
#apply(input, function, environment:) ⇒ Object
runtime value + runtime value -> runtime value input | function -> output Confines @-resolution to the environment's jail. Ignores the environment's bindings. The function carries its own closure.
122 123 124 |
# File 'lib/fusion/cli.rb', line 122 def apply(input, function, environment:) Interpreter.safe_apply(function, input, environment) end |
#decode(string, mode:) ⇒ Object
String (treated as stdin) -> WirePair
Doesn't support mode :unix
86 87 88 |
# File 'lib/fusion/cli.rb', line 86 def decode(string, mode:) Decoder.decode(string, mode:) end |
#encode(wire_pair, mode:) ⇒ Object
WirePair -> String
Doesn't support mode :unix
151 152 153 |
# File 'lib/fusion/cli.rb', line 151 def encode(wire_pair, mode:) Encoder.encode(wire_pair, mode:) end |
#evaluate(ast, environment) ⇒ Object
expression (AST) -> runtime value Mutates environment if given an assignment statement. Confines @-resolution to the environment's jail. Has access to the environment's bindings.
130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/fusion/cli.rb', line 130 def evaluate(ast, environment) case ast when AST::Statement::Assignment value = Interpreter.safe_evaluate(ast.expression, environment) environment.bind(ast.name, value, checked: false) value when AST::Expression Interpreter.safe_evaluate(ast, environment) else raise Unreachable, "Unhandled AST node #{ast.class}" end end |
#load_file(rel_path, root_env) ⇒ Object
relative path -> runtime_value
110 111 112 113 114 115 116 |
# File 'lib/fusion/cli.rb', line 110 def load_file(rel_path, root_env) interp = Fusion::Interpreter.new(root_env) abspath = File.(rel_path) # The top-level program file is loaded by the runtime, not via an @-reference: # the operation is "loading code", with the path as `input` (which file). interp.load_file(abspath).force(operation: "loading code", input: interp.display_path(abspath), site: { origin: "code", file: nil }) end |
#load_source(inline_source, root_env) ⇒ Object
String (treated as inline source) -> runtime value
101 102 103 104 105 106 107 |
# File 'lib/fusion/cli.rb', line 101 def load_source(inline_source, root_env) ast = Fusion::Parser.parse_file(inline_source, site: { origin: "code", file: "<inline>" }) return ast if ast.is_a?(Fusion::Interpreter::ErrorVal) # a parse error inline_env = root_env.child.set_context(:dir, Dir.pwd) Fusion::Interpreter.new(inline_env).evaluate_unit(ast) end |
#parse(wire_pair) ⇒ Object
WirePair -> runtime value
91 92 93 |
# File 'lib/fusion/cli.rb', line 91 def parse(wire_pair) Parser.parse(wire_pair) end |
#prepare! ⇒ Object
24 25 26 27 28 29 30 |
# File 'lib/fusion/cli.rb', line 24 def prepare! $stdout.sync = true $stderr.sync = true $stdin.set_encoding(Encoding::UTF_8) $stdout.set_encoding(Encoding::UTF_8) $stderr.set_encoding(Encoding::UTF_8) end |
#root_environment(jail: Dir.pwd) ⇒ Object
A binding-free root environment
96 97 98 |
# File 'lib/fusion/cli.rb', line 96 def root_environment(jail: Dir.pwd) Interpreter::Env.new.set_context(:jail, jail) end |
#run(options) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/fusion/cli.rb', line 32 def run() case .use_case when :pipe run_pipe() when :stream run_stream() when :repl run_repl() else raise Unreachable, "Unknown use case #{.use_case}" end end |
#run_pipe(options) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/fusion/cli.rb', line 45 def run_pipe() prepare! root = root_environment(jail: jail_root()) program = load_program(, root) input = load_input() output = if input.nil? program else apply(parse(input), program, environment: root) end emit_output(serialize(output), output_mode: .output_mode) end |
#run_repl(options) ⇒ Object
80 81 82 |
# File 'lib/fusion/cli.rb', line 80 def run_repl() Repl.new(root_env: root_environment(jail: jail_root())).run end |
#run_stream(options) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/fusion/cli.rb', line 61 def run_stream() prepare! root = root_environment(jail: jail_root()) program = load_program(, root) $stdin.each_line do |line| record = line.chomp if record.strip.empty? $stdout.puts unless .skip_blank_lines? else input = decode(record, mode: .input_mode) output = apply(parse(input), program, environment: root) $stdout.puts(encode(serialize(output), mode: .output_mode)) end end end |
#serialize(runtime_value) ⇒ Object
runtime value -> WirePair CAUTION: resolves "internal" error status, only use for final output
145 146 147 |
# File 'lib/fusion/cli.rb', line 145 def serialize(runtime_value) Serializer.serialize(runtime_value) end |