113 lines
3.4 KiB
Markdown
113 lines
3.4 KiB
Markdown
# Error output
|
|
|
|
When a runtime error occurs, the VM prints its state at the time it stopped. The output includes:
|
|
|
|
1. The instruction pointer;
|
|
2. The data stack;
|
|
3. The environment stack;
|
|
4. The call stack.
|
|
|
|
## Instruction pointer (IP)
|
|
|
|
The instruction pointer is useful for debugging alongside the program's opcode listing. Run the VM with the `--debug` (`-d`) flag and the path to a compiled program to print its opcodes without running it.
|
|
|
|
The output looks roughly like this:
|
|
|
|
```
|
|
0000: MK_ENVTABLE
|
|
0001: JMP IP: 53
|
|
0003: MK_ENVTABLE
|
|
0004: LOADCONST #0 ('a')
|
|
0006: STORE
|
|
0007: LOADCONST #0 ('a')
|
|
0009: WRITE
|
|
0010: MK_ENVTABLE
|
|
0011: LOADCONST #0 ('a')
|
|
0013: LOOKUP_ENV
|
|
0014: GET_FIELD #0
|
|
...
|
|
```
|
|
|
|
The instruction index helps you find the instruction where the exception occurred. See the [opcode reference](../internals/opcodes.md) for the complete list and descriptions.
|
|
|
|
## Data stack
|
|
|
|
The data stack is printed as a list of values in the form `[T] V`, where `T` is the type number and `V` is the value. Strings and objects are prefixed with `str: V` and `ref: V`, respectively.
|
|
|
|
Example:
|
|
|
|
```
|
|
> Data stack:
|
|
> [2] str: 'this'
|
|
```
|
|
|
|
Values are printed from top to bottom, so the most recent values appear first.
|
|
|
|
## Environment stack
|
|
|
|
The environment stack is printed as two lists: objects owned by the environment and names local to it.
|
|
|
|
Example environment:
|
|
|
|
```
|
|
> Environments:
|
|
> [1] 0x55a9d8196a20:
|
|
> Owned objects (0/2):
|
|
> Local entries (3/4):
|
|
> [14] b = 4
|
|
> [1] a = ref 0x55a9d81969e0
|
|
> [0] this = 0
|
|
> [0] 0x55a9d8196930:
|
|
> Owned objects (1/2):
|
|
> ref: 0x55a9d81969e0 (entries: 1)
|
|
> Local entries (1/2):
|
|
> [1] sum = ref 0x55a9d81969e0
|
|
```
|
|
|
|
`> [N] A` identifies the environment table itself. `N` is the table's nesting level (larger values mean a deeper environment), and `A` is its memory address.
|
|
|
|
The first list is `Owned objects`; it shows the number of elements and the allocated array size as `(<count>/<capacity>)`. Objects are listed as `ref: A (entries: N)`, where `A` is the object's memory address and `N` is the number of fields it contains.
|
|
|
|
The second list is `Local entries`, with the number of entries and allocated capacity. Each entry has the form `[T] N = V`, where `T` is the type number, `N` is the entry name, and `V` is its value.
|
|
|
|
## Call stack
|
|
|
|
The call stack contains return addresses. An address is pushed when the `CALL` opcode runs and popped by `RET`.
|
|
|
|
```
|
|
> Call stack:
|
|
> [0] 53
|
|
```
|
|
|
|
Each entry has the form `[L] IP`, where `L` is the nesting level (larger means deeper) and `IP` is the instruction index to jump to after returning.
|
|
|
|
## Complete output
|
|
|
|
A complete error report looks like this:
|
|
|
|
```
|
|
===== ERROR =====
|
|
> Caused on IP: 21
|
|
|
|
> Data stack:
|
|
> [2] str: 'this'
|
|
|
|
> Environments:
|
|
> [1] 0x55a9d8196a20:
|
|
> Owned objects (0/2):
|
|
> Local entries (3/4):
|
|
> [14] b = 4
|
|
> [1] a = ref 0x55a9d81969e0
|
|
> [0] this = 0
|
|
> [0] 0x55a9d8196930:
|
|
> Owned objects (1/2):
|
|
> ref: 0x55a9d81969e0 (entries: 1)
|
|
> Local entries (1/2):
|
|
> [1] sum = ref 0x55a9d81969e0
|
|
|
|
> Call stack:
|
|
> [0] 53
|
|
Error: runtime error - expected 2 values in data stack
|
|
```
|
|
|