ForthVM (ForthVM v0.5.0) View Source
A toy Forth-like virtual machine.
I have written it to experiment implementing a stack-based preemtive multitasking interpreter (and to play) with Elixir.
Link to this section Summary
Functions
Returns the PID for the Core with the given core_id
string.
Returns a map with cores' id as keys and cores' pid as values.
Executes Forth code in source
string using process_id
Process
managed by the core_id
Core.
Optionally, a custom Forth dictionary
can be passed.
Loads Forth code from the source
string into process_id
Process
managed by core_id
Core, replacing all code currrently stored into the process.
The loaded code is executed right away.
Sends a message to process_id
Process managed by core_id
Core:
word_name
is the name of the dictionary's word that will handle the message,
message_data
is a list containing the data to be placed on top of the data stack.
Spawns a new process with given process_id
that will be managed by the core_id
Core,
If process_id
is nil
, an new id will be automatically generated using System.unique_integer()
.
Starts a new VM supervisor, initializin num_cores
cores.
Link to this section Functions
Returns the PID for the Core with the given core_id
string.
Examples
ForthVM.core_pid("core_2") #PID<0.408.0>
Returns a map with cores' id as keys and cores' pid as values.
Examples
ForthVM.Supervisor.cores() %{"core_1" => #PID<0.407.0>, "core_2" => #PID<0.408.0>}
Executes Forth code in source
string using process_id
Process
managed by the core_id
Core.
Optionally, a custom Forth dictionary
can be passed.
Returns the updated Core state.
Examples
ForthVM.execute("core_2", "p_1", "40 2 +") %ForthVM.Core{ id: 2, io: :stdio, processes: [
%ForthVM.Process{
context: {[], '*', [],
%{
"dup" => {:word, &ForthVM.Words.Stack.dup/5,
%{doc: "duplicate element from top of stack", stack: "( x -- x x )"}},
...
},
%{
core_id: 2,
debug: false,
io: %{
device: :stdio,
devices: %{"core_io" => :stdio, "stdio" => :stdio}
},
messages: [],
process_id: "p_1",
reductions: 997,
sleep: 0
}},
core_id: nil,
exit_value: 42,
id: "p_1",
status: :exit
}
] }
Loads Forth code from the source
string into process_id
Process
managed by core_id
Core, replacing all code currrently stored into the process.
The loaded code is executed right away.
If the process_id
does not exist, a message will be logged, but no error raised.
Returns the updated Core state.
Sends a message to process_id
Process managed by core_id
Core:
word_name
is the name of the dictionary's word that will handle the message,
message_data
is a list containing the data to be placed on top of the data stack.
The message will place {word_name, message_data}
into the Process' messages FIFO queue.
Messages are handled when the Process has no more tokens to process:
word_name
is placed into the list of tokens to executemessage_data
list is joined with the data stack- the message is removed from the
messages
queue
This is a cast call, so nothing is returned.
Examples
ForthVM.send_message("core_2", "p_new", ".", ["hello world"]) :ok hello world
Spawns a new process with given process_id
that will be managed by the core_id
Core,
If process_id
is nil
, an new id will be automatically generated using System.unique_integer()
.
Returns the newly spawned Process' state.
Examples
ForthVM.spawn("core_2", "p_new") %ForthVM.Process{ context: {[], [], [], %{
"<<" => {:word, &ForthVM.Words.Logic.b_shift_left/5,
%{doc: "bitwise shift left", stack: "( x y -- v )"}},
...
}, %{
core_id: 2,
debug: false,
io: %{device: :stdio, devices: %{"core_io" => :stdio, "stdio" => :stdio}},
messages: [],
process_id: "p_new",
reductions: 0,
sleep: 0
}}, core_id: nil, exit_value: nil, id: "p_new", status: nil }
Starts a new VM supervisor, initializin num_cores
cores.
Examples
ForthVM.start(num_cores: 2)