commit 33acabf456055883cc5101d9968694a872e834f8
parent d0da8b73ba305b16f669267cb208a962b6b0fc41
Author: Demonstrandum <moi@knutsen.co>
Date: Tue, 18 Feb 2020 15:39:21 +0000
Updated bytecode spec.
Diffstat:
3 files changed, 83 insertions(+), 42 deletions(-)
diff --git a/BYTECODE.md b/BYTECODE.md
@@ -4,38 +4,44 @@ Sizes are as follows:
| Type | Size |
|----------|--------------------------|
-| Operator | 1 Byte (8 Bits, `u8`) |
+| Operator | 1 Byte (8 Bits, `u8`) |
| Operand | 2 Bytes (16 Bits, `u16`) |
## Bytecodes
| Byte | Name | Operands | Description |
|:---:|:---:|---|---|
-| `0xc8` | `HALT` | 1 — Exit Code (Integer) | Stops execution. |
-| `0x01` | `PUSH_CONST` | 1 — Unsigned index to constants table | Pushes a constant onto the stack. Constant is specified by a given index to the constant-table, containing all local constant. |
-| `0x02` | `PUSH_LOCAL` | 1 — Local variable index (Unsigned) | Pushes a local variable (e.g. a function param) onto the stack. The local variable is identified by an index operand, to where it is in the current symbol table. |
-| `0x03` | `PUSH_SUPER` | 1 — Name of super-scoped variable (String) | When a variable is out of the local scope, load it onto the stack by searching up the super-scope by its name, (much slower than `PUSH_LOCAL`). |
-| `0x04` | `POP` | | Pops the top element off of the stack. |
-| `0x05` | `STORE_LOCAL` | 1 — Index to store local variable in table (Unsigned) | Pops the top value and stores it in the local symbol table at a given index. |
-| `0x06` | `STORE_SUPER` | 1 — Name of super-scoped variable (String) | When a variable is out of the local scope, pop it off of the stack to store it in the super-scope searching up the frames for its name, (much slower than `STORE_LOCAL`). |
-| `0x06` | `DUP` | | Duplicates what was on the top of the stack, by popping it off and then pushing two copies. |
-| `0x07` | `DUP_N` | 1 — The number of duplicates | Duplicates the top value on the stack N times. |
-| `0x08` | `SWAP` | | Swaps the position of the top two stack elements. |
-| `0x28` | `N_ADD` | | Addition between two pointer-sized unsigned integers. Pops top two elements from the stacks and adds them together, pushing the result. |
-| `0x29` | `I_ADD` | | Addition between two pointer-sized signed integers. Pops top two elements from the stacks and adds them together, pushing the result. |
-| `0x2a` | `R_ADD` | | Addition between two 64-bit floating-point numbers. Pops top two elements from the stacks and adds them together, pushing the result. |
-| `0x2b` | `U_ADD` | | Addition between two values of unknown types, found out at runtime. Pops top two elements from the stacks and adds them together, pushing the result. |
-| `0x2c` | `CONCAT` | | Works like add, but concatenates strings. |
-| `0x2d` | `N_SUB` | | Subtraction between two pointer-sized unsigned integers. Pops top two elements from the stacks and subtracts them together, pushing the result. |
-| `0x2e` | `I_SUB` | | Subtraction between two pointer-sized signed integers. Pops top two elements from the stacks and subtracts them together, pushing the result. |
-| `0x2f` | `R_SUB` | | Subtraction between two 64-bit floating-point numbers. Pops top two elements from the stacks and subtracts them together, pushing the result. |
-| `0x30` | `U_SUB` | | Subtraction between two values of unknown types, found out at runtime. Pops top two elements from the stacks and subtracts one from the other, pushing the result. |
-| `0x31` | `N_MUL` | | Multiplication between two pointer-sized unsigned integers. Pops top two elements from the stacks and multiplies them together, pushing the result. |
-| `0x32` | `I_MUL` | | Multiplication between two pointer-sized signed integers. Pops top two elements from the stacks and multiplies them together, pushing the result. |
-| `0x33` | `R_MUL` | | Multiplication between two 64-bit floating-point numbers. Pops top two elements from the stacks and multiplies them together, pushing the result. |
-| `0x34` | `U_MUL` | | Multiplication between two values of unknown types, found out at runtime. Pops top two elements from the stacks and multiplies them together, pushing the result. |
-| `0x35` | `N_DIV` | | Division between two pointer-sized unsigned integers. Pops top two elements from the stacks and finds their quotient, pushing the result. |
-| `0x36` | `I_DIV` | | Division between two pointer-sized signed integers. Pops top two elements from the stacks and finds their quotient, pushing the result. |
-| `0x37` | `R_DIV` | | Division between two 64-bit floating-point numbers. Pops top two elements from the stacks and finds their quotient, pushing the result. |
-| `0x38` | `U_DIV` | | Division between two values of unknown types, found out at runtime. Pops top two elements from the stacks and finds their quotient, pushing the result. |
-| `0xfe` | `SET_LINE` | 1 — Current line number, given directly as `u16`. Operand value is line number. | Sets the current line number that the subsequent bytecode instructions correspond to in the code source file. |
-| `0xff` | `NOP` | | <u>N</u>o <u>Op</u>eration. Does nothing. You shouldn't see this in the final compiled bytecode, it may only exists temporarily while the bytecode is being produced. |
+| `0x00`<br />(0) | `EOI` | <center>N/A</center> | End Of Instructions! This is not a real opcode and only appears at the end of the instruction byte-stream to signal that there are no more instructions to be read. Essentially it's just a null-terminator. |
+| `0xc8`<br />(200) | `HALT` | 1 — Exit Code (Integer) | Stops execution. |
+| `0x01`<br />(1) | `PUSH_CONST` | 1 — Unsigned index to constants table | Pushes a constant onto the stack. Constant is specified by a given index to the constant-table, containing all local constant. |
+| `0x02`<br />(2) | `PUSH_LOCAL` | 1 — Local variable index (Unsigned) | Pushes a local variable (e.g. a function param) onto the stack. The local variable is identified by an index operand, to where it is in the current symbol table. |
+| `0x03`<br />(3) | `PUSH_SUPER` | 1 — Name of super-scoped variable (String) | When a variable is out of the local scope, load it onto the stack by searching up the super-scope by its name, (much slower than `PUSH_LOCAL`). |
+| `0x04`<br />(4) | `POP` | <center>N/A</center> | Pops the top element off of the stack. |
+| `0x05`<br />(5) | `STORE_LOCAL` | 1 — Index to store local variable in table (Unsigned) | Pops the top value and stores it in the local symbol table at a given index. |
+| `0x06`<br />(6) | `DUP` | <center>N/A</center> | Duplicates what was on the top of the stack, by popping it off and then pushing two copies. |
+| `0x07`<br />(7) | `DUP_N` | 1 — The number of duplicates | Duplicates the top value on the stack N times. |
+| `0x08`<br />(8) | `SWAP` | <center>N/A</center> | Swaps the position of the top two stack elements. |
+| `0x09`<br />(9) | `CALL_1` | <center>N/A</center> | Calls function at top of stack with argument at second from top of stack. |
+| `0x0a`<br />(10) | `CHECK_TYPE` | <center>N/A</center> | Checks if second from top of stack value is a member of the set/type loaded from the top of the stack. |
+| `0x0b`<br />(11) | `CAST` | 1 — One byte, specifies the origin type.<br />2 — One byte, specifies the destination type. | Changes the top-of-stack value to have a different primitive type. |
+| `0x0c`<br />(12) | `MAKE_FUNC` | <center>N/A</center> | Takes the top-of-stack value, referencing a code block, and makes it a function, with all the special properties that come with that. |
+| `0x0d`<br />(13) | `YIELD` | <center>N/A</center> | Causes the current function to yield a value (i.e. return). |
+| `0x0e`<br />(14) | `RAW_PRINT` | <center>N/A</center> | Native debug print of `TOS`. Should not be used unless working on the compiler. |
+| `0x28`<br />(40) | `N_ADD` | <center>N/A</center> | Addition between two pointer-sized unsigned integers. Pops top two elements from the stacks and adds them together, pushing the result. |
+| `0x29`<br />(41) | `I_ADD` | <center>N/A</center> | Addition between two pointer-sized signed integers. Pops top two elements from the stacks and adds them together, pushing the result. |
+| `0x2a`<br />(42) | `R_ADD` | <center>N/A</center> | Addition between two 64-bit floating-point numbers. Pops top two elements from the stacks and adds them together, pushing the result. |
+| `0x2b`<br />(43) | `U_ADD` | <center>N/A</center> | Addition between two values of unknown types, found out at runtime. Pops top two elements from the stacks and adds them together, pushing the result. |
+| `0x2c`<br />(44) | `CONCAT` | <center>N/A</center> | Works like add, but concatenates strings. |
+| `0x2d`<br />(45) | `N_SUB` | <center>N/A</center> | Subtraction between two pointer-sized unsigned integers. Pops top two elements from the stacks and subtracts them together, pushing the result. |
+| `0x2e`<br />(46) | `I_SUB` | <center>N/A</center> | Subtraction between two pointer-sized signed integers. Pops top two elements from the stacks and subtracts them together, pushing the result. |
+| `0x2f`<br />(47) | `R_SUB` | <center>N/A</center> | Subtraction between two 64-bit floating-point numbers. Pops top two elements from the stacks and subtracts them together, pushing the result. |
+| `0x30`<br />(48) | `U_SUB` | <center>N/A</center> | Subtraction between two values of unknown types, found out at runtime. Pops top two elements from the stacks and subtracts one from the other, pushing the result. |
+| `0x31`<br />(49) | `N_MUL` | <center>N/A</center> | Multiplication between two pointer-sized unsigned integers. Pops top two elements from the stacks and multiplies them together, pushing the result. |
+| `0x32`<br />(50) | `I_MUL` | <center>N/A</center> | Multiplication between two pointer-sized signed integers. Pops top two elements from the stacks and multiplies them together, pushing the result. |
+| `0x33`<br />(51) | `R_MUL` | <center>N/A</center> | Multiplication between two 64-bit floating-point numbers. Pops top two elements from the stacks and multiplies them together, pushing the result. |
+| `0x34`<br />(52) | `U_MUL` | <center>N/A</center> | Multiplication between two values of unknown types, found out at runtime. Pops top two elements from the stacks and multiplies them together, pushing the result. |
+| `0x35`<br />(53) | `N_DIV` | <center>N/A</center> | Division between two pointer-sized unsigned integers. Pops top two elements from the stacks and finds their quotient, pushing the result. |
+| `0x36`<br />(54) | `I_DIV` | <center>N/A</center> | Division between two pointer-sized signed integers. Pops top two elements from the stacks and finds their quotient, pushing the result. |
+| `0x37`<br />(55) | `R_DIV` | <center>N/A</center> | Division between two 64-bit floating-point numbers. Pops top two elements from the stacks and finds their quotient, pushing the result. |
+| `0x38`<br />(56) | `U_DIV` | <center>N/A</center> | Division between two values of unknown types, found out at runtime. Pops top two elements from the stacks and finds their quotient, pushing the result. |
+| `0xfe`<br />(254) | `SET_LINE` | 1 — Current line number, given directly as `u16`. Operand value is line number. | Sets the current line number that the subsequent bytecode instructions correspond to in the code source file. |
+| `0xff`<br />(255) | `NOP` | <center>N/A</center> | <u>N</u>o <u>Op</u>eration. Does nothing. You shouldn't see this in the final compiled bytecode, it may only exists temporarily while the bytecode is being produced. |
diff --git a/bytecode_spec.yaml b/bytecode_spec.yaml
@@ -64,16 +64,15 @@
Pops the top value and stores it in the local symbol table
at a given index.
-- :byte: 6
- :name: STORE_SUPER
- :operands: 1
- :operand_desc: ['Name of super-scoped variable (String)']
- :desc: >-
- When a variable is out of the local scope, pop it
- off of the stack to store it in the super-scope
- searching up the frames for its name, (much slower
- than `STORE_LOCAL`).
-
+# - :byte: 6
+# :name: STORE_SUPER
+# :operands: 1
+# :operand_desc: ['Name of super-scoped variable (String)']
+# :desc: >-
+# When a variable is out of the local scope, pop it
+# off of the stack to store it in the super-scope
+# searching up the frames for its name, (much slower
+# than `STORE_LOCAL`).
- :byte: 6
:name: DUP
@@ -109,6 +108,40 @@
Checks if second from top of stack value is a member
of the set/type loaded from the top of the stack.
+- :byte: 11
+ :name: CAST
+ :operands: 2
+ :operand_desc: [
+ 'One byte, specifies the origin type.',
+ 'One byte, specifies the destination type.'
+ ]
+ :desc: >-
+ Changes the top-of-stack value to have a different
+ primitive type.
+
+- :byte: 12
+ :name: MAKE_FUNC
+ :operands: 0
+ :desc: >-
+ Takes the top-of-stack value, referencing a code
+ block, and makes it a function, with all the special
+ properties that come with that.
+
+- :byte: 13
+ :name: YIELD
+ :operands: 0
+ :desc: >-
+ Causes the current function to yield a value
+ (i.e. return).
+
+- :byte: 14
+ :name: RAW_PRINT
+ :operands: 0
+ :desc: >-
+ Native debug print of `TOS`.
+ Should not be used unless working on the
+ compiler.
+
- :byte: 40
:name: N_ADD
:operands: 0
diff --git a/scripts/gen_bytecode_md_spec.rb b/scripts/gen_bytecode_md_spec.rb
@@ -13,7 +13,7 @@ rows = Array.new
LIST.each do |row|
fields = Array.new
- fields << "`0x#{row[:byte].to_s(16).rjust(2, '0')}`"
+ fields << "`0x#{row[:byte].to_s(16).rjust(2, '0')}`<br />(#{row[:byte]})"
fields << "`#{row[:name].upcase}`"
operand_desc = Array.new
@@ -21,6 +21,8 @@ LIST.each do |row|
operand_desc << "#{i + 1} — #{row[:operand_desc][i]}"
end
+ operand_desc = ['<center>N/A</center>'] if operand_desc.empty?
+
fields << operand_desc.join('<br />')
fields << row[:desc]
@@ -36,7 +38,7 @@ Sizes are as follows:
| Type | Size |
|----------|--------------------------|
-| Operator | 1 Byte (8 Bits, `u8`) |
+| Operator | 1 Byte (8 Bits, `u8`) |
| Operand | 2 Bytes (16 Bits, `u16`) |
EOF