7 DATEX Execution
7.1 Runtime Environments
A DATEX Runtime Environment has to take care of sequential execution of incoming instructions, handling of encrpytion, permissions, variables and pointers. Furthermore, it must have a DXB generator to automatically generate response and synchronization messages.
A full DATEX Compiler is not required for a Runtime.
A Runtime Environment can also provide an interface to the host system (e.g. to manipulate a UI, access a database, or communicate with peripherals)
7.2 Sandboxed Execution
Since arbitrary DATEX binary code can be executed from other directly or indirectly connected endpoints ("remote endpoints"), the Runtime has to provide a sandboxed environment in which the access to pointers and static scopes it restricted depending on the permissions of the remote endpoint.
Per default, a remote endpoint should not be allowed to execute instructions on a third party endpoint, because it could impersonate the intermediate endpoint that way.
7.3 Internal Slots
Each scope has a number of memory locations to store values that are relevant for the scope execution process. Some internal slots are directly accessible in the scope as internal variables (e.g. #result
, #this
). Internal variables can be readonly.
7.3.1 List of internal slots:
[[ACTIVE_VALUE]]
[[LAST_VALUE]]
[[PROC_RESULT]]
[[OPERATOR]]
[[INSERT_LOCATION]]
[[SCOPE_RESULT]]
[[RESULT]]
[[INDEX]]
[[INSTRUCTION_CODE]]
[[INSTRUCTION]]
[[THIS]]
[[ROOT]]
7.4 General procedure for instruction processing
READ THE INSTRUCTION
- Store the Instruction Code in
[[INSTRUCTION_CODE]]
- Store the remaining instruction data in
[[INSTRUCTION]]
(length depends on the Instruction Code, can also be 0)
- Store the Instruction Code in
EXECUTE THE INSTRUCTION
- Validate the parameter types depending on the
[[INSTRUCTION_CODE]]
- Run the custom instruction procedure depending on
[[INSTRUCTION_CODE]]
- Move
[[ACTIVE_VALUE]]
to[[LAST_VALUE]]
- Move the return value of the instruction procedure (
[[PROC_RESULT]]
) to[[ACTIVE_VALUE]]
- Validate the parameter types depending on the
APPLY IN CONTEXT
- If
[[OPERATOR]]
is set, apply the operator to[[LAST_VALUE]]
and[[ACTIVE_VALUE]]
and store the result value in[[ACTIVE_VALUE]]
; clear[[OPERATOR]]
- Else apply
[[ACTIVE_VALUE]]
directly to[[LAST_VALUE]]
and store the result in[[ACTIVE_VALUE]]
- If
INSERT THE VALUE
- If
[[INSERT_LOCATION]]
is set, insert[[ACTIVE_VALUE]]
at[[INSERT_LOCATION]]
- If
7.5 Statements
The CLOSE_AND_STORE
Instruction is used to separate groups of Instructions ("Statements").
The [[ACTIVE_VALUE]]
is stored in [[SCOPE_RESULT]]
. [[ACTIVE_VALUE]]
, [[LAST_VALUE]]
, [[OPERATOR]]
, and [[INSERT_LOCATION]]
are cleared.
7.6 Global Runtime data
- global:
Runtime.Global
- The
scope
keyword acts as context of the current scope (Runtime.Scope
).
7.7 General Runtime procedures
7.7.1 runtimeExecution
function runtimeExecution(scope: Runtime.Scope, global: Runtime.Global):
while scope.byteIndex < len(scope.executable):
(instructionCode, scope.byteIndex) <- extractUint32(
scope.executable,
scope.byteIndex
)
instrDefinition <- global.instructionDefinitions[instructionCode]
if len(scope.executable) - scope.byteIndex <
instrDefinition.minimumSize:
scope.byteIndex <- scope.byteIndex - 2
return
data <- scope.executable[scope.byteIndex..len(scope.executable)]
if instrDefinition.validation and
not instrDefinition.validation(data)
scope.byteIndex <- scope.byteIndex - 2
return
result <- instrDefinition.procedure(data as Instruction.*)
scope.lastValue <- scope.activeValue
scope.activeValue <- result
if scope.operator:
scope.activeValue <- applyOperator(scope.operator, scope.lastValue, scope.activeValue) // TODO
scope.operator <- void
else:
scope.activeValue <- apply(scope.lastValue, scope.activeValue) // TODO
if scope.insertLocation:
insert(scope.insertLocation, scope.activeValue) // TODO
scope.insertLocation <- void
7.7.2 newSubScope
function newSubScope(scope: Runtime.Scope)
// TODO add new subscope to heap
scope.subscopes += Runtime.Subscope {
}
7.8 Instruction-specific procedures
7.8.1 COUNT
- If
[[ACTIVE_VALUE]]
is primitive, set[[PROC_RESULT]]
to1
...