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>}

Link to this function

execute(core_id, process_id, source, dictionary \\ nil)

View Source

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
}

] }

Link to this function

load(core_id, process_id, source)

View Source

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.

Link to this function

send_message(core_id, process_id, word_name, message_data)

View Source

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 execute
  • message_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

Link to this function

spawn(core_id, process_id, dictionary \\ nil)

View Source

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)