PULL Instruction - craterdog-archives/js-bali-virtual-machine GitHub Wiki

PULL

The PULL instruction causes the component (or the exception handler address) that is currently on top of the component (or the exception handler) stack to be pulled off and potentially used for a specific purpose that depends on the specified modifier:

An operand is never specified for this instruction.

PULL HANDLER

The PULL instruction with a HANDLER modifier pulls the handler address that is currently on the handler stack off and discards it. The bytecode for this instruction has the form:

[01000000][00000000]

The following pseudo-code defines this instruction:

context.handlers.pop()  -- discard the top handler address
context.address = context.address + 1

Example Context Before Execution

PULL HANDLER - Before

Example Context After Execution

PULL HANDLER - After

PULL COMPONENT

The PULL instruction with a COMPONENT modifier pulls the component that is currently on the component stack off and discards it. The bytecode for this instruction has the form:

[01001000][00000000]

The following pseudo-code defines this instruction:

task.components.pop()
context.address = context.address + 1

Example Context Before Execution

PULL COMPONENT - Before

Example Context After Execution

PULL COMPONENT - After

PULL RESULT

The PULL instruction with a RESULT modifier pulls the component that is currently on the component stack off and passed it as the result of the calling execution context. The bytecode for this instruction has the form:

[01010000][00000000]

The following pseudo-code defines this instruction:

if task.contexts.isNotEmpty() then {
    -- pass result on top of the stack to calling context
    task.context = task.contexts.pop()
} else {
    -- the task is done return the result
    task.result = task.components.pop()
    task.status = $completed
}

Example Context Before Execution

PULL RESULT - Before

Example Context After Execution

PULL RESULT - After

PULL EXCEPTION

The PULL instruction with an EXCEPTION modifier pulls the exception handler address that is currently on the handler stack off and uses it as the address of the next instruction to be executed. If the handler stack is empty, the context that is on top of the context stack is used to replace the current context and its handler stack is used. If there are no more contexts, the exception that is on top of the component stack is returned as an unhandled exception. The bytecode for this instruction has the form:

[01011000][00000000]

The following pseudo-code defines this instruction:

while context do {
    if context.handlers.isNotEmpty() then {
        -- try the each handler for this context
        context.address = context.handlers.pop()
        break loop
    } else if task.contexts.isNotEmpty() then {
        -- try the handlers for the calling context
        task.context = task.contexts.pop()
    } else {
        -- no more handlers to try, unhandled exception
        task.exception = task.components.pop()
        task.status = $abandoned
        break loop
    }
}

Example Context Before Execution

PULL EXCEPTION - Before

Example Context After Execution

PULL EXCEPTION - After