Class: Vangrail::Colang::Interpreter

Inherits:
Object
  • Object
show all
Defined in:
lib/vangrail/colang/interpreter.rb

Overview

Runs one flow and reports what it decided.

The mapping onto rail statuses is the whole design:

`bot <message>` then `stop`     -> blocked, with the message as content
a change to a content binding   -> modified, with the new value
falls off the end               -> passed

$user_input is a rewrite alias of $user_message; $bot_response is a rewrite alias of $bot_message. Input and context seed the user pair from the turn text; output seeds the bot pair. The other pair is left unset so an output flow that reads $user_message is not reading the answer unless the caller put it there.

A stop without a preceding bot still blocks; it just has no refusal text to show. Actions are plain Ruby callables, so the flow decides the control shape and Ruby does the work.

Defined Under Namespace

Classes: Outcome

Constant Summary collapse

CONTENT_VARS =

The four names a flow assigns to when it rewrites the turn. Order is the last-write winner when more than one of them changed.

%w[user_message bot_message user_input bot_response].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(program:, actions:) ⇒ Interpreter

Returns a new instance of Interpreter.



34
35
36
37
# File 'lib/vangrail/colang/interpreter.rb', line 34

def initialize(program:, actions:)
  @program = program.check!
  @actions = actions
end

Instance Attribute Details

#actionsObject (readonly)

Returns the value of attribute actions.



32
33
34
# File 'lib/vangrail/colang/interpreter.rb', line 32

def actions
  @actions
end

#programObject (readonly)

Returns the value of attribute program.



32
33
34
# File 'lib/vangrail/colang/interpreter.rb', line 32

def program
  @program
end

Instance Method Details

#run(flow_name, context = {}) ⇒ Object

Raises:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/vangrail/colang/interpreter.rb', line 39

def run(flow_name, context = {})
  flow = program.flow(flow_name)
  raise ColangError, "no flow named #{flow_name.inspect}" unless flow

  seeds = seed_bindings(context)
  state = { 'context' => context }.merge(seeds)
  result = execute(flow.body, state, context)
  return stop_outcome(result.last, flow_name, state) if stop_tag?(result)

  rewrite = rewritten_content(state, seeds)
  if rewrite
    return Outcome.new(status: :modified, content: rewrite.to_s, reason: flow_name,
                       variables: state)
  end

  Outcome.new(status: :passed, content: result, reason: nil, variables: state)
end