forked from defunkt/ReefVM
examples
This commit is contained in:
parent
2f2a8fe9f2
commit
8c187a89aa
91
examples/README.md
Normal file
91
examples/README.md
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
# Bytecode Examples
|
||||||
|
|
||||||
|
This directory contains example `.reef` bytecode files demonstrating various features of the ReefVM.
|
||||||
|
|
||||||
|
## Running Examples
|
||||||
|
|
||||||
|
You can run any example using the reef binary:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/reef examples/add.reef
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic Operations
|
||||||
|
|
||||||
|
- **add.reef** - Simple addition of two numbers
|
||||||
|
- **simple-function.reef** - Function that adds two parameters
|
||||||
|
- **arrays.reef** - Array creation and operations (MAKE_ARRAY, ARRAY_PUSH, ARRAY_GET)
|
||||||
|
- **dicts.reef** - Dictionary operations (MAKE_DICT, DICT_GET)
|
||||||
|
- **loop.reef** - Simple loop using JUMP and conditional jumps
|
||||||
|
|
||||||
|
### Advanced Function Features
|
||||||
|
|
||||||
|
- **variadic.reef** - Variadic parameters that collect remaining positional arguments (`...rest`)
|
||||||
|
- **kwargs.reef** - Named arguments that collect unmatched named args into a dict (`@kwargs`)
|
||||||
|
- **mixed-variadic-kwargs.reef** - Combining variadic positional and named arguments
|
||||||
|
- **tail-recursion.reef** - Tail-recursive factorial using TAIL_CALL
|
||||||
|
- **closure.reef** - Closures that capture variables from outer scope
|
||||||
|
|
||||||
|
### Exception Handling
|
||||||
|
|
||||||
|
- **exception-handling.reef** - Try-catch-finally blocks with PUSH_TRY, THROW, and PUSH_FINALLY
|
||||||
|
|
||||||
|
## Bytecode Syntax
|
||||||
|
|
||||||
|
The `.reef` files use the following syntax:
|
||||||
|
|
||||||
|
- Comments start with `;`
|
||||||
|
- Instructions are written as `OPCODE operand`
|
||||||
|
- Labels use `#N` for relative offsets
|
||||||
|
- Function signatures: `MAKE_FUNCTION (params) #address`
|
||||||
|
- Fixed params: `(a b c)`
|
||||||
|
- Variadic: `(a ...rest)`
|
||||||
|
- Named args: `(a @kwargs)`
|
||||||
|
- Mixed: `(a ...rest @kwargs)`
|
||||||
|
|
||||||
|
## Function Calling Convention
|
||||||
|
|
||||||
|
When calling functions, the stack must contain (bottom to top):
|
||||||
|
1. The function to call
|
||||||
|
2. Positional arguments (in order)
|
||||||
|
3. Named argument key-value pairs (key, value, key, value, ...)
|
||||||
|
4. Positional argument count
|
||||||
|
5. Named argument count
|
||||||
|
|
||||||
|
Example with positional arguments:
|
||||||
|
|
||||||
|
```
|
||||||
|
LOAD functionName ; push function onto stack
|
||||||
|
PUSH arg1 ; first positional arg
|
||||||
|
PUSH arg2 ; second positional arg
|
||||||
|
PUSH 2 ; positional count
|
||||||
|
PUSH 0 ; named count
|
||||||
|
CALL
|
||||||
|
```
|
||||||
|
|
||||||
|
Example with named arguments:
|
||||||
|
|
||||||
|
```
|
||||||
|
LOAD functionName ; push function onto stack
|
||||||
|
PUSH "key1" ; first named arg key
|
||||||
|
PUSH "value1" ; first named arg value
|
||||||
|
PUSH "key2" ; second named arg key
|
||||||
|
PUSH "value2" ; second named arg value
|
||||||
|
PUSH 0 ; positional count
|
||||||
|
PUSH 2 ; named count
|
||||||
|
CALL
|
||||||
|
```
|
||||||
|
|
||||||
|
Example with mixed arguments:
|
||||||
|
|
||||||
|
```
|
||||||
|
LOAD functionName ; push function onto stack
|
||||||
|
PUSH arg1 ; positional arg
|
||||||
|
PUSH "name" ; named arg key
|
||||||
|
PUSH "Bob" ; named arg value
|
||||||
|
PUSH 1 ; positional count
|
||||||
|
PUSH 1 ; named count
|
||||||
|
CALL
|
||||||
|
```
|
||||||
16
examples/arrays.reef
Normal file
16
examples/arrays.reef
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
; Array operations example
|
||||||
|
; Create array, push element, get element
|
||||||
|
PUSH 10
|
||||||
|
PUSH 20
|
||||||
|
PUSH 30
|
||||||
|
MAKE_ARRAY #3
|
||||||
|
STORE arr
|
||||||
|
; Push 40 to array
|
||||||
|
LOAD arr
|
||||||
|
PUSH 40
|
||||||
|
ARRAY_PUSH
|
||||||
|
; Get element at index 2
|
||||||
|
LOAD arr
|
||||||
|
PUSH 2
|
||||||
|
ARRAY_GET
|
||||||
|
HALT
|
||||||
24
examples/closure.reef
Normal file
24
examples/closure.reef
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
; Closure example: counter function that captures state
|
||||||
|
; outer() returns inner() which increments and returns captured count
|
||||||
|
MAKE_FUNCTION () #8
|
||||||
|
PUSH 0
|
||||||
|
PUSH 0
|
||||||
|
CALL
|
||||||
|
STORE counter_fn
|
||||||
|
LOAD counter_fn
|
||||||
|
PUSH 0
|
||||||
|
PUSH 0
|
||||||
|
CALL
|
||||||
|
HALT
|
||||||
|
; Outer function body
|
||||||
|
PUSH 0
|
||||||
|
STORE count
|
||||||
|
MAKE_FUNCTION () #8
|
||||||
|
RETURN
|
||||||
|
; Inner function body (closure over count)
|
||||||
|
LOAD count
|
||||||
|
PUSH 1
|
||||||
|
ADD
|
||||||
|
STORE count
|
||||||
|
LOAD count
|
||||||
|
RETURN
|
||||||
14
examples/dicts.reef
Normal file
14
examples/dicts.reef
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
; Dictionary operations example
|
||||||
|
PUSH 'name'
|
||||||
|
PUSH 'Alice'
|
||||||
|
PUSH 'age'
|
||||||
|
PUSH 30
|
||||||
|
PUSH 'city'
|
||||||
|
PUSH 'NYC'
|
||||||
|
MAKE_DICT #3
|
||||||
|
STORE person
|
||||||
|
; Get value by key
|
||||||
|
LOAD person
|
||||||
|
PUSH 'name'
|
||||||
|
DICT_GET
|
||||||
|
HALT
|
||||||
19
examples/exception-handling.reef
Normal file
19
examples/exception-handling.reef
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
; Try-catch-finally example
|
||||||
|
PUSH_TRY #9
|
||||||
|
PUSH_FINALLY #16
|
||||||
|
PUSH 'Something went wrong!'
|
||||||
|
THROW
|
||||||
|
PUSH 999
|
||||||
|
POP_TRY
|
||||||
|
JUMP #4
|
||||||
|
HALT
|
||||||
|
; Catch block
|
||||||
|
STORE err
|
||||||
|
PUSH 'Caught: '
|
||||||
|
LOAD err
|
||||||
|
ADD
|
||||||
|
HALT
|
||||||
|
; Finally block
|
||||||
|
POP
|
||||||
|
PUSH 'Finally executed'
|
||||||
|
HALT
|
||||||
13
examples/kwargs.reef
Normal file
13
examples/kwargs.reef
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
; Named arguments (kwargs) example
|
||||||
|
MAKE_FUNCTION (x @kwargs) #9
|
||||||
|
PUSH 'name'
|
||||||
|
PUSH 'Alice'
|
||||||
|
PUSH 'age'
|
||||||
|
PUSH 30
|
||||||
|
PUSH 1
|
||||||
|
PUSH 2
|
||||||
|
CALL
|
||||||
|
HALT
|
||||||
|
; Return the kwargs dict
|
||||||
|
LOAD kwargs
|
||||||
|
RETURN
|
||||||
17
examples/loop.reef
Normal file
17
examples/loop.reef
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
; Loop example: count from 0 to 5
|
||||||
|
PUSH 0
|
||||||
|
STORE i
|
||||||
|
; Loop condition
|
||||||
|
LOAD i
|
||||||
|
PUSH 5
|
||||||
|
LT
|
||||||
|
JUMP_IF_FALSE #6
|
||||||
|
; Loop body
|
||||||
|
LOAD i
|
||||||
|
PUSH 1
|
||||||
|
ADD
|
||||||
|
STORE i
|
||||||
|
JUMP #-9
|
||||||
|
; After loop
|
||||||
|
LOAD i
|
||||||
|
HALT
|
||||||
18
examples/mixed-variadic-kwargs.reef
Normal file
18
examples/mixed-variadic-kwargs.reef
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
; Mixed variadic and named arguments
|
||||||
|
; Function takes one fixed param, variadic positional, and kwargs
|
||||||
|
MAKE_FUNCTION (x ...rest @kwargs) #10
|
||||||
|
PUSH 'name'
|
||||||
|
PUSH 'Bob'
|
||||||
|
PUSH 1
|
||||||
|
PUSH 2
|
||||||
|
PUSH 3
|
||||||
|
PUSH 3
|
||||||
|
PUSH 1
|
||||||
|
CALL
|
||||||
|
HALT
|
||||||
|
; Return array with all three parts
|
||||||
|
LOAD x
|
||||||
|
LOAD rest
|
||||||
|
LOAD kwargs
|
||||||
|
MAKE_ARRAY #3
|
||||||
|
RETURN
|
||||||
12
examples/simple-function.reef
Normal file
12
examples/simple-function.reef
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
; Simple function that adds two numbers
|
||||||
|
MAKE_FUNCTION (a b) #7
|
||||||
|
PUSH 10
|
||||||
|
PUSH 20
|
||||||
|
PUSH 2
|
||||||
|
PUSH 0
|
||||||
|
CALL
|
||||||
|
HALT
|
||||||
|
LOAD a
|
||||||
|
LOAD b
|
||||||
|
ADD
|
||||||
|
RETURN
|
||||||
28
examples/tail-recursion.reef
Normal file
28
examples/tail-recursion.reef
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
; Tail-recursive factorial function
|
||||||
|
; factorial(n, acc) = if n <= 1 then acc else factorial(n-1, n*acc)
|
||||||
|
MAKE_FUNCTION (n acc) #21
|
||||||
|
DUP
|
||||||
|
PUSH 5
|
||||||
|
PUSH 1
|
||||||
|
PUSH 2
|
||||||
|
PUSH 0
|
||||||
|
CALL
|
||||||
|
HALT
|
||||||
|
; Function body
|
||||||
|
LOAD n
|
||||||
|
PUSH 1
|
||||||
|
LTE
|
||||||
|
JUMP_IF_FALSE #2
|
||||||
|
LOAD acc
|
||||||
|
RETURN
|
||||||
|
; Tail recursive call
|
||||||
|
DUP
|
||||||
|
LOAD n
|
||||||
|
PUSH 1
|
||||||
|
SUB
|
||||||
|
LOAD n
|
||||||
|
LOAD acc
|
||||||
|
MUL
|
||||||
|
PUSH 2
|
||||||
|
PUSH 0
|
||||||
|
TAIL_CALL
|
||||||
33
examples/variadic.reef
Normal file
33
examples/variadic.reef
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
; Variadic function that sums all arguments
|
||||||
|
MAKE_FUNCTION (x ...rest) #19
|
||||||
|
PUSH 5
|
||||||
|
PUSH 10
|
||||||
|
PUSH 15
|
||||||
|
PUSH 20
|
||||||
|
PUSH 4
|
||||||
|
PUSH 0
|
||||||
|
CALL
|
||||||
|
HALT
|
||||||
|
; Function body: sum x and all rest elements
|
||||||
|
LOAD x
|
||||||
|
STORE sum
|
||||||
|
PUSH 0
|
||||||
|
STORE i
|
||||||
|
LOAD i
|
||||||
|
LOAD rest
|
||||||
|
ARRAY_LEN
|
||||||
|
LT
|
||||||
|
JUMP_IF_FALSE #8
|
||||||
|
LOAD sum
|
||||||
|
LOAD rest
|
||||||
|
LOAD i
|
||||||
|
ARRAY_GET
|
||||||
|
ADD
|
||||||
|
STORE sum
|
||||||
|
LOAD i
|
||||||
|
PUSH 1
|
||||||
|
ADD
|
||||||
|
STORE i
|
||||||
|
JUMP #-18
|
||||||
|
LOAD sum
|
||||||
|
RETURN
|
||||||
|
|
@ -103,6 +103,12 @@ export function toBytecode(str: string): Bytecode /* throws */ {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let line of lines) {
|
for (let line of lines) {
|
||||||
|
// Strip semicolon comments
|
||||||
|
const commentIndex = line.indexOf(';')
|
||||||
|
if (commentIndex !== -1) {
|
||||||
|
line = line.slice(0, commentIndex)
|
||||||
|
}
|
||||||
|
|
||||||
const trimmed = line.trim()
|
const trimmed = line.trim()
|
||||||
if (!trimmed) continue
|
if (!trimmed) continue
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,3 +144,45 @@ test("MAKE_FUNCTION - default with string", async () => {
|
||||||
expect(result).toEqual({ type: 'string', value: 'World' })
|
expect(result).toEqual({ type: 'string', value: 'World' })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("semicolon comments are ignored", () => {
|
||||||
|
const bytecode = toBytecode(`
|
||||||
|
; This is a comment
|
||||||
|
PUSH 1 ; push one
|
||||||
|
PUSH 5 ; push five
|
||||||
|
ADD ; add them
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(bytecode).toEqual({
|
||||||
|
instructions: [
|
||||||
|
{ op: OpCode.PUSH, operand: 0 },
|
||||||
|
{ op: OpCode.PUSH, operand: 1 },
|
||||||
|
{ op: OpCode.ADD },
|
||||||
|
],
|
||||||
|
constants: [
|
||||||
|
{ type: 'number', value: 1 },
|
||||||
|
{ type: 'number', value: 5 }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("semicolon comments work with functions", async () => {
|
||||||
|
const bytecode = toBytecode(`
|
||||||
|
MAKE_FUNCTION (x y) #7 ; function with two params
|
||||||
|
PUSH 10 ; first arg
|
||||||
|
PUSH 20 ; second arg
|
||||||
|
PUSH 2 ; positional count
|
||||||
|
PUSH 0 ; named count
|
||||||
|
CALL ; call the function
|
||||||
|
HALT
|
||||||
|
; Function body starts here
|
||||||
|
LOAD x ; load first param
|
||||||
|
LOAD y ; load second param
|
||||||
|
ADD ; add them
|
||||||
|
RETURN ; return result
|
||||||
|
`)
|
||||||
|
|
||||||
|
const vm = new VM(bytecode)
|
||||||
|
const result = await vm.run()
|
||||||
|
expect(result).toEqual({ type: 'number', value: 30 })
|
||||||
|
})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user