# Code Instructions

Code instructions are made up of an operator and operands. For example:

```
iload #0
```

The above shows the operator to load an integer. This particular operator expects only one operand and in this instance is the immediate value '0'.

Instructions usually denote the type of data it is operating upon (integer, boolean, etc.) with a prefix of the type. For example:

```
iload #0                // An integer to be loaded onto the stack
bload #true             // A boolean value to be loaded onto the stack
sstore localStringValue // The string on the stack to be stored in the 
                        // table declaration referenced by localStringValue
```

> Instructions are not type safe. It is up to the programmer to ensure the code is made type safe. Poorly developed code will result in unpredictable results.

## Instruction Structure

Instructions are usually structured in the following way:

```
{type}{action}
```

### Type

The type can be one of the followings:

| Type | Description |
| ---- | ----------- |
| `b`  | Boolean     |
| `by` | byte        |
| `d`  | date/time   |
| `i`  | integer     |
| `e`  | set         |
| `f`  | float       |
| `s`  | string      |

### Action

Depending on the type the action can be one of the following:

| Action   | Description                                                                     |
| -------- | ------------------------------------------------------------------------------- |
| `load`   | Load a value onto the stack                                                     |
| `store`  | Store a value in a program location. This could be in a local, or global entry. |
| `return` | Return a frame off the stack returning to the current program counter location. |
| `add`    | Add a value to another value and store the result.                              |
| `sub`    | Subtract one value from another and store the result.                           |
| `div`    | Divide one value by another and store the result.                               |
| `mul`    | Multiply one value by another and store the result.                             |
| `cvt`    | Convert one value to another.                                                   |
| `return` | Return a value from a method                                                    |
| `or`     | Perform a logical or binary or and store the result.                            |
| `and`    | Perform a logical or binary and and store the result.                           |

## Operands

Operands fall into the following types:

### Immediate Operands

Immediate operands refer to constants or values that can be assessed at compile time. They are prefixed with a `#` unless it is a string which is automatically interpreted as a literal:

```
sload "This is a string"
byload #23
```

### Registers

Macro has 12 registers that allow provide an alternative to storing temporary data in a table or on the stack and access to processor status values. For example:

```
loads "This is a string"
store r0
```

| Name     | Description                                                                                         |
| -------- | --------------------------------------------------------------------------------------------------- |
| r0 - r9  | Registers that can hold any object                                                                  |
| pc (r10) | The program counter of the current instruction. Any changes made to this must be handled with care. |
| sp (r11) | The stack pointer for the current stack. Any changes made to this must be handled with care.        |
| ps (r12) | The processor status. Any changes to this must be handles with care.                                |

### Processor Status

The process Status is an integer that indicates the status of the current processor thread. Each bit has a certain function:

| Position | Description                                            |
| -------- | ------------------------------------------------------ |
| 0        | Floating Overflow has occurred in the last instruction |
| 1        | Divide By Zero has occurred in the last instruction    |
| 2        | Zero result has occurred with the last instruction.    |
| 3        | Null result has occurred with the last instruction.    |
| 4        | Boolean                                                |

### Referenced

Referenced operands refer to a position in a local table or to an external address. For example:

```
sload AReallyBigString
store r0
```

The above will load a string from a local reference (`AReallyBigString`) and store the value in the register `r0`. To access an external value the following modification to the reference can be applied:

```
sload G^AReallyBigString
store r0
```

In the above the reference to AReallyBigString will be searched for in referenced external libraries referred to in the import directives.

### Indexed

Where appropriate it is possible to extend an operand by an index. For example:

```
byload bytearray[#0]
store r0
```

This will assume the `bytearray` is an array and load the element from it referred to by the immediate operand `#0`.  The index can be any type of operand that returns a number for an index relevant to array is is referring to. This means only operands that result ina byte or int value can be used.

### Deferred

An operand can sometimes point to the actual operand. For example:

```
sload (aStringReference)
```

## Combinations

Combining instructions and operands is where the real power of Macro coding resides. Consider a basic instruction to add two integers together and store the result in another value:

```
iadd #2, #3, result
```

The basic `iadd` instruction combines one instruction and three operands together to achieve this process. However, it is possible to use a combination of operands and stack to push the result onto the stack for further use (if it not required to be stored). This would be achieved in the following way:

```
iadd #2, #3
```

By missing the third operand off it is assumed that the result should be pushed onto the stack. To complete the initial instruction using this approach:

```
iadd #2, #3
store result
```

This can be taken further so that none, some or all of the operands for an `add` action (or similar type of instruction) can be removed and the stack can be used. Taking the initial `add` instruction to have no operands the same process could be achieved in the following way:

```
iload #3
iload #2
iadd
store result
```

In this example the two values are popped off the stack added and the result is pushed onto the stack. Then the result is popped off the stack and stored in `result`.

> Not all instructions provide this capability.

## Fast Instructions

Some more common instructions have been combined into single instructions to save time. These are as follows:

| Instruction | Description                                                           |
| ----------- | --------------------------------------------------------------------- |
| `bload_n`   | Load a boolean value where n can be `true` or `false` onto the stack. |
| `byload_n`  | Load a byte value where n can be `0` to `3` onto the stack.           |
| `iload_n`   | Load an integer value where n can be `0` to `3` onto the stack        |

## Conversion Instructions

These instructions convert one type to another. They take the form:

```
{base}cvt{destination}
```

For example:

```
icvtb
```

It is possible to convert types based on the table:

| ?          | bool (b) | byte(by) | int (i) | date (d) | set (e) | float (f) | string (s) |
| ---------- | -------- | -------- | ------- | -------- | ------- | --------- | ---------- |
| bool (b)   | .        | x        | .       | .        | .       | .         | x          |
| byte (by)  | x        | .        | x       | .        | .       | .         | x          |
| int (i)    | x        | x        | .       | x        | x       | x         | x          |
| date (d)   | .        | .        | .       | .        | .       | .         | x          |
| float (f)  | x        | x        | x       | .        | .       | .         | x          |
| string (s) | x        | x        | x       | x        | x       | x         | .          |

## Conditional Instructions

It is possible to branch from one location to another based on that value on te top of the stack.

| Instruction | Description                                           |
| ----------- | ----------------------------------------------------- |
| `ifeq`      | If equal to zero then branch                          |
| `ifne`      | If not equal to zero then branch                      |
| `ifgt`      | If greater than zero then branch                      |
| `iflt`      | If less than zero then branch                         |
| `ifge`      | If greater than or equal to zero then branch          |
| `ifle`      | If less than or equal to zero then branch             |
| `iftrue`    | If true then branch                                   |
| `iffalse`   | If false then branch                                  |
| `ifnull`    | If there is a null value on the stack then branch     |
| `ifnotnull` | If there if not a null value on the stack then branch |

Each on of the conditional instructions has a boolean push stack version. this is achieved by adding a `b` to the instruction. For example:

```
ifeqb
```

The above instruction pops the integer value from the stack and converts it to a boolean value (if value equals zero then push true else push false).

## Unconditional Branching Instructions

### Goto Instruction

To support this there is also the `goto` instruction that you can use to branch unconditionally to a position in the instructions. For example:

```
    ...
    load questions
    invokevirtual InitialiseLooping()
a10$:
    load questions
    invokevirtual Next()
    iffalse a20$
    load questions
    invokevirtual GetItem()
    store question
    load question
    invokevirtual Ask()
    goto a10$
a20$:
    ...
```

### Call and Return

To support code that you want to repeat it is possible to call a method and return from it.

```
    ...
    load question
    call testQuestion(IQuestion)
    ...

    ...
.method testQuestion(IQuestion question)
    load question
    invokevirtual Ask()
    return
    ...
```

### Gosub and Ret

It is possible to run a subroutine of code that is not a specially declared method, but simply referred to by a label in the `gosub` instruction:

```
    iload_0
    iload #1
    gosub 10$
    iload #2
    gosub 10$
    ireturn
10$:
    add
    ret
```

Whilst the example could be better, the benefit of this approach is that no call stack is created for what could be a repetitive task and therefore save time.

## Transferring Data

The `move` instruction is one untyped instruction that allows a reference to be moved from one location to another.&#x20;

```
    move #1, r0
```

The move instruction will take any operands that make sense to transfer a value from one location to another.

## Accessing External Libraries

It is possible to access static and dynamic instances of classes and access its methods and properties through a set of instructions.

To create an instance of an object use the `new` instruction:

```
    ...
    sload #jsonString
    new IQuestion(string)
    store q1
    ...
```

To access a method in the object:

```
    ...
    sload #jsonString
    new IQuestion(string)
    store q1
    load q1
    invokeVirtual Ask()
    ...
```

To access a property it is possible to access the direct method if it known or the general property:

```
    ...
    sload #jsonString
    new IQuestion(string)
    store q1
    load q1
    invokeVirtual get_Label()
    ...
```

Most properties are accessible through a `getter` which is identified by the `get_` prefix. Setting a property is achieved through the `setter` which is identified by the `set_` prefix:

```
    ...
    sload #jsonString
    new IQuestion(string)
    store q1
    load q1
    load label1
    invokeVirtual set_Label(label)
    ...
```

Accessing static classes is also easy with Macro. These do no need to instantiated, but can simply be accessed directly:

```
    new InterviewContext()
    invokestatic InterviewState.set_Context(InterviewContext)
    getstatic InterviewState.get_Context
```

## Stack Management

Just in case you want to mange the stack independently of the rest of the instructions set you can also use the `pop` instruction to remove unwanted items from the stack.

## Error Handling

It is possible to define error management using the `pushh`, `throw` and `poph` instructions. For example:

```
    ...
    pushh Exception,x30$ NullException,x40$
    load questions
    invokevirtual InitialiseLooping()
a10$:
    load questions
    invokevirtual Next()
    iffalse a20$
    load questions
    invokevirtual GetItem()
    store question
    load question
    invokevirtual Ask()
    goto a10$
a20$:
    ...
x30$:
    // general exception
    ...
x40$:
    // Null exception
    ...
```

The `pushh` instruction pushes a handler onto the handler stack. The handler stack operates as a cascading exception handler, so if the error is not picked up by the handler on top of the stack the next handler is used.

The `throw` instruction will cause an exception to be thrown and the handler stack to be accessed for in search for an exception handler that will support the error. If a handler is available then the stack will have the exception details on it if you wish to use them. For example:

```
10$:
    store error
    return
```

The above example assumes (as performed by the runtime error handling) that the error has been pushed onto the stack for use by the error handler.

The `poph` instruction will remove the handler off the top of the handler stack.

These three instructions allow the Macro Virtual Machine to mimic most language try, catch type error handlers.

### Exceptions

It is possible that an instruction itself can cause an exception. If this happens it will trigger access to the handler stack. An exception is based on the following list:

| Exception     | Description                         |
| ------------- | ----------------------------------- |
| Exception     | A general exception and a catchall. |
| NullException | A null value was detected.          |
| DivideByZero  | Division by zero detected.          |

{% hint style="info" %}
More exceptions will be made available over time to support the standard libraries.
{% endhint %}

## Process Control

The Macro Virtual Machine includes the ability to pass control back to the calling environment. This can be achieved through the Show and Ask methods of the Interview Models Standard Library. But it is also possible to pass back control using the wait instruction:

```
wait [ operand ]
```

The operand can be any operand which is passed back to the calling environment. It is up to the calling environment to expect and process it.

## Threads

There are a set of instructions that make it possible to create threads for asynchronous programming. Threads can be created using the follwoing approach:

```
.method void Test()
.table
    Thread threada
.code
    thread ThreadTest, threada
    start threada
    return
    
.method void ThreadTest()
.code
    load #0, r0
10$:
    add #1, r0, r0
    sub r0, #10
    bneq 10$
    return
```

In the above example a thread is created and started. To stop a thread before it is completed you can use the `kill` instruction.

```
.method void Test()
.table
    Thread threada
.code
    thread ThreadTest, threada
    start threada
    kill threada
    return
    
.method void ThreadTest()
.code
    load #0, r0
10$:
    add #1, r0, r0
    sub r0, #10000
    bneq 10$
    return
```

To wait for a thread to complete you can use the `join` instruction.

```
.method void Test()
.table
    Thread threada
.code
    thread ThreadTest, threada
    start threada
    join threada
    return
    
.method void ThreadTest()
.code
    load #0, r0
10$:
    add #1, r0, r0
    sub r0, #10
    bneq 10$
    return
```

To paused a thread the `wait` instruction can be used, specifying an operand that refers to the number of milliseconds to pause.

```
.method void Test()
.table
    Thread threada
.code
    thread ThreadTest, threada
    start threada
    return
    
.method void ThreadTest()
.code
    load #0, r0
10$:
    add #1, r0, r0
    sub r0, #10
    wait #30000
    bneq 10$
    return
```

To support multi threaded code it is possible to queue threads up to run the same code using the `lock` and `unlock` instructions.

```
```

Locking an object will add it to a thread watchlist and any other threads attemping to lock the same object will placed into a wait state until the object is freed up to be locked again. Unlocking an object will make available for the next thread to lock and continue with the code.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.onescript.org/macro/instructions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
