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_nameis placed into the list of tokens to executemessage_datalist is joined with the data stack- the message is removed from the
messagesqueue
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)