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) {
|
||||
// Strip semicolon comments
|
||||
const commentIndex = line.indexOf(';')
|
||||
if (commentIndex !== -1) {
|
||||
line = line.slice(0, commentIndex)
|
||||
}
|
||||
|
||||
const trimmed = line.trim()
|
||||
if (!trimmed) continue
|
||||
|
||||
|
|
|
|||
|
|
@ -144,3 +144,45 @@ test("MAKE_FUNCTION - default with string", async () => {
|
|||
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