forked from defunkt/ReefVM
update spec
This commit is contained in:
parent
8c187a89aa
commit
0270424f9b
77
SPEC.md
77
SPEC.md
|
|
@ -38,8 +38,8 @@ type Value =
|
|||
| { type: 'string', value: string }
|
||||
| { type: 'array', value: Value[] }
|
||||
| { type: 'dict', value: Map<string, Value> }
|
||||
| { type: 'function', params: string[], defaults: Record<string, Value>,
|
||||
body: number, parentScope: Scope, variadic: boolean, kwargs: boolean }
|
||||
| { type: 'function', params: string[], defaults: Record<string, number>,
|
||||
body: number, parentScope: Scope, variadic: boolean, named: boolean }
|
||||
```
|
||||
|
||||
### Type Coercion
|
||||
|
|
@ -67,7 +67,7 @@ type Instruction = {
|
|||
type Constant =
|
||||
| Value
|
||||
| { type: 'function_def', params: string[], defaults: Record<string, number>,
|
||||
body: number, variadic: boolean, kwargs: boolean }
|
||||
body: number, variadic: boolean, named: boolean }
|
||||
```
|
||||
|
||||
## Scope Chain
|
||||
|
|
@ -276,12 +276,12 @@ Adds a finally block to the current try/catch. The finally block will execute wh
|
|||
|
||||
**Behavior**:
|
||||
1. Pop exception handler
|
||||
2. If handler has `finallyAddress`, jump there
|
||||
3. Otherwise continue to next instruction
|
||||
2. Continue to next instruction
|
||||
|
||||
**Notes**:
|
||||
- The VM ensures finally runs when try completes normally
|
||||
- The compiler must ensure catch blocks jump to finally when present
|
||||
- The VM does NOT automatically jump to finally blocks on POP_TRY
|
||||
- The compiler must explicitly generate JUMP instructions to finally blocks when the try block completes normally
|
||||
- The compiler must ensure catch blocks also jump to finally when present
|
||||
- Finally blocks should end with normal control flow (no special terminator needed)
|
||||
|
||||
#### THROW
|
||||
|
|
@ -296,8 +296,12 @@ Adds a finally block to the current try/catch. The finally block will execute wh
|
|||
4. Unwind call stack to handler's depth
|
||||
5. Restore handler's scope
|
||||
6. Push error value back onto stack
|
||||
7. Jump to handler's catch address
|
||||
8. **Note**: After catch block executes, compiler must jump to finally if present
|
||||
7. If handler has `finallyAddress`, jump there; otherwise jump to `catchAddress`
|
||||
|
||||
**Notes**:
|
||||
- When THROW jumps to finally (if present), the error value remains on stack for the finally block
|
||||
- The compiler must structure catch/finally blocks appropriately to handle the error value
|
||||
- If finally is present, the catch block is typically entered via a jump from the finally block or through explicit compiler-generated control flow
|
||||
|
||||
### Function Operations
|
||||
|
||||
|
|
@ -310,8 +314,8 @@ The constant must be a `function_def` with:
|
|||
- `params`: Parameter names
|
||||
- `defaults`: Map of param names to constant indices for default values
|
||||
- `body`: Instruction address of function body
|
||||
- `variadic`: If true, last param collects remaining positional args as array
|
||||
- `kwargs`: If true, last param collects all named args as dict
|
||||
- `variadic`: If true, second-to-last param (if `named` is also true) or last param collects remaining positional args as array
|
||||
- `named`: If true, last param collects unmatched named args as dict
|
||||
|
||||
The created function captures `currentScope` as its `parentScope`.
|
||||
|
||||
|
|
@ -332,7 +336,7 @@ The created function captures `currentScope` as its `parentScope`.
|
|||
9. Bind parameters:
|
||||
- For regular functions: bind params by position, then by name, then defaults, then null
|
||||
- For variadic functions: bind fixed params, collect rest into array
|
||||
- For kwargs functions: bind fixed params by position/name, collect unmatched named args into dict
|
||||
- For functions with `named: true`: bind fixed params by position/name, collect unmatched named args into dict
|
||||
10. Set currentScope to new scope
|
||||
11. Jump to function body
|
||||
|
||||
|
|
@ -344,8 +348,8 @@ The created function captures `currentScope` as its `parentScope`.
|
|||
|
||||
**Named Args Handling**:
|
||||
- Named args that match fixed parameter names are bound to those params
|
||||
- Remaining named args (that don't match any fixed param) are collected into `@kwargs` dict
|
||||
- This allows flexible calling: `fn(x=10, y=20, extra=30)` where `extra` goes to kwargs
|
||||
- If the function has `named: true`, remaining named args (that don't match any fixed param) are collected into the last parameter as a dict
|
||||
- This allows flexible calling: `fn(x=10, y=20, extra=30)` where `extra` goes to the named args dict
|
||||
|
||||
**Errors**: Throws if top of stack is not a function
|
||||
|
||||
|
|
@ -510,14 +514,30 @@ skip_body:
|
|||
|
||||
### Try-Catch
|
||||
```
|
||||
PUSH_TRY catch_label
|
||||
# try block
|
||||
PUSH_TRY #3 ; Jump to catch block (3 instructions ahead)
|
||||
; try block
|
||||
POP_TRY
|
||||
JUMP end_label
|
||||
catch_label:
|
||||
STORE 'errorVar' # Error is on stack
|
||||
# catch block
|
||||
end_label:
|
||||
JUMP #2 ; Jump past catch block
|
||||
; catch:
|
||||
STORE 'errorVar' ; Error is on stack
|
||||
; catch block
|
||||
; end:
|
||||
```
|
||||
|
||||
### Try-Catch-Finally
|
||||
```
|
||||
PUSH_TRY #4 ; Jump to catch block (4 instructions ahead)
|
||||
PUSH_FINALLY #7 ; Jump to finally block (7 instructions ahead)
|
||||
; try block
|
||||
POP_TRY
|
||||
JUMP #5 ; Jump to finally
|
||||
; catch:
|
||||
STORE 'errorVar' ; Error is on stack
|
||||
; catch block
|
||||
JUMP #2 ; Jump to finally
|
||||
; finally:
|
||||
; finally block (executes in both cases)
|
||||
; end:
|
||||
```
|
||||
|
||||
### Named Function Call
|
||||
|
|
@ -601,7 +621,7 @@ All of these should throw errors:
|
|||
### Function Parameter Binding
|
||||
- Missing positional args → use named args → use defaults → use null
|
||||
- Extra positional args → collected by variadic parameter or ignored
|
||||
- Extra named args → collected by kwargs parameter or ignored
|
||||
- Extra named args → collected by named args parameter (if `named: true`) or ignored
|
||||
- Named arg matching is case-sensitive
|
||||
|
||||
### Tail Call Optimization
|
||||
|
|
@ -615,11 +635,12 @@ All of these should throw errors:
|
|||
- CONTINUE is implemented by the compiler using JUMPs
|
||||
|
||||
### Exception Unwinding
|
||||
- THROW unwinds call stack to handler's depth, not just to handler
|
||||
- THROW unwinds call stack to handler's depth
|
||||
- Exception handlers form a stack (nested try blocks)
|
||||
- Error value on stack is available in catch block via STORE
|
||||
- Finally blocks always execute, even if there's a return/break in try or catch
|
||||
- Finally executes after try (if no exception) or after catch (if exception)
|
||||
- Error value on stack is available in catch/finally blocks
|
||||
- When THROW occurs and handler has finallyAddress, VM jumps to finally first
|
||||
- Compiler is responsible for structuring control flow so finally executes in all cases
|
||||
- Finally typically executes after try (if no exception) or after catch (if exception), but control flow is compiler-managed
|
||||
|
||||
## VM Initialization
|
||||
|
||||
|
|
@ -643,7 +664,7 @@ const result = await vm.execute()
|
|||
6. **Break/continue** (nested functions, iterator pattern)
|
||||
7. **Closures** (capturing variables, multiple nesting levels)
|
||||
8. **Tail calls** (self-recursive, mutual recursion)
|
||||
9. **Parameter binding** (positional, named, defaults, variadic, kwargs, combinations)
|
||||
9. **Parameter binding** (positional, named, defaults, variadic, named args collection, combinations)
|
||||
10. **Array/dict operations** (creation, access, mutation)
|
||||
11. **Error conditions** (all error cases listed above)
|
||||
12. **Edge cases** (empty stack, null values, shadowing, etc.)
|
||||
|
|
@ -655,7 +676,7 @@ const result = await vm.execute()
|
|||
3. **Closure examples** (counters, adder factories)
|
||||
4. **Exception examples** (try/catch/throw chains)
|
||||
5. **Complex scope** (deeply nested functions)
|
||||
6. **Mixed features** (variadic + defaults + kwargs)
|
||||
6. **Mixed features** (variadic + defaults + named args)
|
||||
|
||||
### Property-Based Tests Should Cover
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user