109 lines
2.8 KiB
Elixir
109 lines
2.8 KiB
Elixir
defmodule Scopes.CSys.Program do
|
|
import Scopes.CSys, only: [
|
|
neuron: 1, update_neuron: 1, synapse: 3
|
|
]
|
|
alias Scopes.CSys
|
|
alias Scopes.Shape
|
|
|
|
defmodule State do
|
|
defstruct [:value, :stage, :prog]
|
|
end
|
|
|
|
def prepare(prog, value \\ []) do
|
|
state = %State{value: value, stage: :initial, prog: prog}
|
|
{state, get_proc(state)}
|
|
end
|
|
|
|
def get_proc(state) do
|
|
get_proc(elem(state.prog, 0), state.stage)
|
|
end
|
|
|
|
defp get_proc(stages, stage) do
|
|
stages[stage] || stages[:default]
|
|
end
|
|
|
|
# basic program
|
|
|
|
def basic_prog() do
|
|
default = &basic_active/2
|
|
stages = %{
|
|
default: default,
|
|
initial: &basic_initial/2,
|
|
active: default,
|
|
retired: default
|
|
}
|
|
transitions = %{
|
|
restart: :initial,
|
|
retire: :retired,
|
|
next: [initial: :active, active: :retired]
|
|
}
|
|
{stages, transitions}
|
|
end
|
|
|
|
def prepare_basic(value \\ []) do
|
|
prepare(basic_prog(), value)
|
|
end
|
|
|
|
# basic processors
|
|
|
|
def basic_initial(msg, scope) do
|
|
basic(msg, scope)
|
|
end
|
|
|
|
def basic_active(msg, scope) do
|
|
basic(msg, scope)
|
|
end
|
|
|
|
def basic(msg = {head, _info}, scope) do
|
|
case head do
|
|
[:csys, :connect, :succ | _rest] -> connect_succ(msg, scope)
|
|
[:csys, :create, :succ | _rest] -> create_succ(msg, scope)
|
|
[:csys, :create, :pred | _rest] -> create_pred(msg, scope)
|
|
#[:csys, :next | _rest] -> next(scope, meta)
|
|
#[:csys, :data | rest] -> process_data(rest, Shape.data(msg), scope)
|
|
#[:csys, action | rest] -> transition(action, scope)
|
|
_ -> CSys.forward(msg, scope) || CSys.notify(msg, scope)
|
|
end
|
|
end
|
|
|
|
def basic(msg, scope) do
|
|
CSys.forward(msg, scope) || CSys.notify(msg, scope)
|
|
end
|
|
|
|
# helper functions
|
|
|
|
def restart({state, _proc, syns, env}) do
|
|
nstate = %{state | stage: :initial}
|
|
{nstate, get_proc(nstate), syns, env}
|
|
end
|
|
|
|
# step functions
|
|
|
|
# connect, create_... steps
|
|
# todo: provide parameters for initial state, proc / stage, op,
|
|
# depending on state and stage (proc) of self, as well as message, env, ...
|
|
|
|
def connect_succ(msg, {state, proc, syns, env}) do
|
|
data = Shape.data(msg)
|
|
op = data[:op] || CSys.noop()
|
|
succ = data[:succ]
|
|
syn = synapse(succ, op, 0)
|
|
update_neuron({state, proc, [syn | syns], env})
|
|
end
|
|
|
|
def create_succ(msg, scope = {state, proc, syns, env}) do
|
|
op = Shape.data(msg)[:op] || CSys.noop()
|
|
new = neuron(restart({state, proc, [], env}))
|
|
CSys.notify({:created, new}, scope)
|
|
syn = synapse(new, op, 0)
|
|
update_neuron(restart({state, proc, [syn | syns], env}))
|
|
end
|
|
|
|
def create_pred(msg, scope = {state, proc, _syns, env}) do
|
|
op = Shape.data(msg)[:op] || CSys.noop()
|
|
syn = synapse(self(), op, 0)
|
|
new = neuron(restart({state, proc, [syn], env}))
|
|
CSys.notify({:created, new}, scope)
|
|
update_neuron(restart(scope))
|
|
end
|
|
end
|