vise
asm
Assembly parser and compiler.
cache
Holds and manages all loaded content.
engine
Outermost interface. Orchestrates execution of bytecode against input.
lang
Validation and specification of language context.
logging
Logging interface and build tags for loglevels.
persist
Interface and reference implementation of ‘state‘ and ‘cache‘ persistence across asynchronous vm executions.
render
Renders menu and templates, and enforces output size constraints.
resource
Retrieves data and bytecode from external symbols, and retrieves templates.
state
Holds the bytecode buffer, error states and navigation states.
vm
Defines instructions, and applies transformations according to the instructions.
vise
¶Implementers of vise
should interface with the system using the engine
module.
The engine comes in two implementations, one volatile base implemetnation and a subclass that includes persistent state.
The engine
module provides three different modes of operation for the engine implementations.
Directly interaction with an engine.Engine
instance.
The engine is manually initialized, and execution must be explicitly triggered with input every time the VM yields control.
Output flushing must also be operated manually.
The interface is the same for both persistent and volatile operation.
Receives input from a reader and writes into to a writer, and executes the underlying engine.Engine
with given inputs until execution is terminated.
The loop may be either persistent or volatile.
This mode drives the interactive driver execution tool.
Compatible with e.g. a network socket or HTTP frontend. The engine.RunPersisted
method restores a persisted state and runs one single input until VM yield after which the new state is persisted.
This mode of operation can only be used with persistent state.
The engine configuration defines the top-level parameters for the execution environment, including maximum output size, default language, execution entry point and more.
Please refer to engine.Config
for details.
The engine.Config.SessionId
is used to disambiguate the end-user that is interacting with the engine.
For example, in a USSD context, the SessionId
may be the phone number of the end-user.
The engine stores the SessionId
aswell as the current chosen lang.Language
in the execution context. This is passed through to the VM operation, and is available for client code, specifically:
LOAD
. (resource.EntryFunc
).
resource.Resource.GetMenu
).
resource.Resource.GetTemplate
).
The core of implementation code is defined by implementing the resource.Resource
interface. This is also described in the LOAD handler section.
In addition to resolving external code symbols, resource.Resource
implementations also translate menu labels and templates based on the current language context, and retrieves bytecode for execution nodes.
One of two reference implementations of resource.Resource
is the resource.MemResource
class. It enables the client to register all node and symbol resolutions at runtime, using its functions prefixed with Add...
.
The resource.MemResource
implementation is primarily useful for use in tests.
The Filesystem based resource implemementation is used by the dev/interactive
tool, aswell as the executable examples in examples/ directory.
It is instantiated with a base directory location relative to which all resources are read.
resource.Resource.GetCode
)resource.Resource.GetTemplate
)resource.Resource.GetMenu
)resource.Resource.FuncFor
)resource.Resource.GetCode
) ¶Read from basedir/<node>.bin.
resource.Resource.GetTemplate
) ¶If language has been set, the template will be read from basedir/<node>_<lang>. For example, the norwegian template for the node root
will be read from basedir/root_nor.
If reading the language specific template fails (or if no language has been set), template will be read from basedir/<node>.
A missing template file will result in load failure and program termination.
resource.Resource.GetMenu
) ¶If language has been set, the template will be read from basedir/<label>_<lang>_menu. For example, the norwegian template for the menu label foo
will be read from basedir/foo_nor_menu.
If reading the language specific menu label fails (or if no language has been set), label will be read from basedir/<label>_menu.
If this also fails, the implementation returns the original label used for lookup.
resource.Resource.FuncFor
) ¶The implementation allows setting resolver functions for symbols at runtime, using the resource.FsResource.AddLocalFunc
method. This registers an resource.FsResource.EntryFunc
with the lookup symbol as key. Note that the EntryFunc
receives the language setting through the execution context.
If no function has been registered for the requested symbol, it will be looked up in the filesystem on basedir/<symbol>_<lang>.txt. For example, the norwegian entry for the symbol foo
will be read from basedir/foo_nor.txt.
If reading the language specific entry fails (or if no language has been set), entry will be read from basedir/<symbol>.txt.
A missing entry will result in load failure and program termination.
The implementation contains no built-in handling of the SessionId
supplied by the context.
Loglevels are set at compile-time using the following build tags:
lognone
logerror
logwarn
loginfo
logdebug
logtrace
Only use ONE of these tags.
The default tag is lognone
which disables logging completely.
logging.Logger
defines the logging interface. It is faintly inspired by the experimental slog.
Located in the dev/ directory of the source code repository.
go run ./dev/gendata/ <directory>
Outputs bytecodes and templates for test data scenarios used in ‘engine‘ unit tests.
go run ./dev/interactive [-d <data_directory>] [--root <root_symbol>] [--session-id <session_id>] [--persist]
Creates a new interactive session using engine.DefaultEngine
, starting execution at symbol root_symbol
data_directory
points to a directory where templates and bytecode is to be found (in the same format as generated by dev/gendata).
If data_directory
is not set, current directory will be used.
if root_symbol
is not set, the symbol root
will be used.
if session_id
is set, mutable data will be stored and retrieved keyed by the given identifer (if implemented).
If persist
is set, the execution state will be persisted across sessions.
go run ./dev/asm <assembly_file>
Will output bytecode on STDOUT generated from a valid assembly file.
go run ./dev/disasm/ <binary_file>
Will list all the instructions on STDOUT from a valid binary file.
Found in examples/.
Be sure to make examples
before running them.
Can be run with:
go run ./examples/<case> [...]
except helloworld which is run as
go run ./dev/interactive -d ./examples/helloworld [...]
The available options are the same as for the dev/interactive tool.
Contents of the case directory:
assembly code.
bytecode for each node symbol (only available after make).
default contents of a single data entry.
current contents of a single data entry (only available after make).
See testdata/*.vis
Currently the following rules apply for encoding in version 0
:
symbol
value is encoded as one byte of string length, after which the byte-value of the string follows.
size
value is encoded as one byte of numeric length, after which the big-endian byte-value of the integer follows.
signal
value is encoded as one byte of byte length, after which a byte-array representing the defined signal follows.
(Minimal, WIP)
000a 03666f6f 05746f666f6f # MOUT tofoo foo - display a menu entry for choice "foo", described by "to foo" 0008 03666f6f 03626172 # INCMP bar foo - move to node "bar" if input is "FOO" 0001 0461696565 01 01 # CATCH aiee 1 1 - move to node "aiee" (and immediately halt) if input match flag (1) is not set (1) 0003 04616263 020104 # LOAD abc 260 - execute code symbol "abc" with a result size limit of 260 (2 byte BE integer, 0x0104) 0003 04646566 00 # LOAD def 0 - execute code symbol "abc" with no size limit (sink) 0005 04616263 # MAP abc - make "abc" available for renderer 0007 # HALT - stop execution (require new input to continue) 0006 0461313233 # MOVE a123 - move to node "a123" (regardless of input) 0007 # HALT - stop execution