- [x] go through usage of scopes and ensure all are being exited properly
- [x] fix native stuff
- [ ] vm fully async
- [x] stackless import
- [ ] stackless class init
- [x] make `init` a contextual keyword that doesn't require `fn` in classes
- [x] user cannot access initializer (to call it again)
only way is to call the class type
- [ ] remove `super.init()` and replace with calling the proxy (`super()`)
- [x] remove `__miri` feature and put args in `xtask miri` instead (`--filter` for running only specific tests)
- [x] should unlock `--all-features`
- [x] change ptr repr to use manual vtable + static object trait
- [x] remove Table `named_field`, it should be reserved for methods
- [x] move all field access/index access/etc. to delegate to the object trait
- [x] fix `from m import a, b, c` bug
- [x] unify globals/global
- [x] remove `Ref` from name of public value types (inner should be prefix by `Owned` or qualified path)
- [x] fix `scope.params` will panic if given the wrong number of args
- [x] comma between disassembly operands
- [x] rename `emit` to `codegen`
- [x] print to configurable writer
- [x] allow printing disassembly (add option to compile snippet and explicitly run it -> expose `disassemble` on it)
- [x] list indexing
- [x] list index oob should return None instead of error (improve error message)
- [x] to_index should check MIN_SAFE_INT
- [x] methods on builtins
- [x] for iter loops (list)
- [ ] ops on builtins <<<
- [ ] store `this` as a special register in `Thread`
- method calls can set `this` and `self` access will fetch through `this` as opposed to slot 0
- `this` can be pushed onto the stack if it needs to be saved, such as script->script function calls
- native/builtin functions can also access `this` through their `scope` as opposed to expecting it in param 0
- [ ] fix "invalid indentation" errors in parser which should be more specific
- [ ] all function types should have the same global type `Function` for use in `is` checks
- [ ] all class types (including native) should have the same global type `Type` for use in `is` checks
- [ ] class instances should walk the parent chain in `is` checks
- [ ] derive(Data)
- immutable
- non-constructible
- no methods
- [ ] repl
- multi-line editor
- [ ] spaces only, make better error message for tabs
- [ ] debugger
- egui
- inspect state of VM
- call frames
- stack, accumulator
- pretty-print values (using Debug)
- step through bytecode (not necessarily source code)
- [ ] tuples
- [ ] generators
- [ ] f-strings
- [ ] `is`
- [ ] `in`
- [ ] exceptions (try/catch)
- [ ] script-land inheritable error type
- [ ] inherit from native class
- [ ] report code locations (intern spans, track in hashmap of `offset->span_id`)
- [ ] timeout feature (abort signal, `Arc<AtomicBool>` or similar)
- [ ] semicolons (`;` for stmt, `;;` for block)
- [ ] codegen optimizations
- [ ] dead code elimination (using basic blocks)
- [ ] constant pool compaction
- [ ] elide previous instruction for clobbered reads
- [ ] peephole previous 2 instructions
- [ ] load + store -> mov
- [ ] load_field + call -> invoke
- [ ] (load_smi 1) + add -> add1
- [ ] specializations
- [ ] load rN -> loadN, for N in 0 to some max bound
- [ ] store rN -> storeN, for N in 0 to some max bound
- [ ] inspect dispatch loop codegen (should be a jump table)
- [ ] inline caching
- per-function IC
- reserve IC slot in codegen
- [ ] quickening
## repro
https://haste.zneix.eu/wucivywofu.swift
## main/call
```
thread.main(function: Ptr<Function>) async
push_frame(function, &[])
run().await
pop_frame()
take(self.acc)
thread.run() async
loop
frame = current()
match dispatch(frame)
Poll(future) -> self.acc = future.await
Yield -> break
thread.call(function: Ptr<Any>, args) -> Result<Value> async
match function.call(get_empty_scope(), args)
Return(value) -> value
Poll(future) -> future.await
Dispatch ->
run().await
take(self.acc)
// TODO
thread.op_call(callee, count)
trait Object
call(scope, this: Ptr<Self>, args: Args) -> Result<Call>
impl for Ptr<Function>
call(scope, this: Ptr<Function>, args: Args) -> Result<Call>
check_args?
if !has_self
scope.stack.push(this)
scope.stack.extend_from_within(args.to_range())
scope.stack.extend(frame_size - args.count - (has_self as usize))
push_frame()
enum Call
Return(value)
Poll(future)
Dispatch
```
### class type trait
can be derived or implemented manually
```
trait Type {
fn build(&mut ClassBuilder) -> ClassDescriptor;
}
NativeModuleBuilder
.class(str, impl Type)
```
### IntoValue changes
users may only store userdata which is Send, so intovalue does not have to require send, because the only way to create a value is
out of Send things.
public API accepts impl IntoValue
### error reporting
Map code offset -> span
also need to know which file we're in so we can report
### codegen comparison to V8
```
LdaZero ; a = 0
Star0 ;
LdaSmi [1] ; b = 1
Star1 ;
LdaZero ; i = 0
Star2 ;
; loop:
Ldar a0 ; i < n
TestLessThan r2, [0] ;
JumpIfFalse [24] (0x120efd313ffa @ 36) ; jump? .end
Ldar r1 ; temp = a + b
Add r0, [1] ;
Star3 ;
Mov r1, r0 ; a = b
Mov r3, r1 ; b = temp
Ldar r2 ; i += 1
AddSmi [1], [2] ;
Star2 ;
JumpLoop [25], [0], [3] (0x120efd313fdd @ 7) ; jump .loop
; end:
Ldar r0 ; return a
Return ;
load_smi 0 ; a = 0
store r2 ;
load_smi 1 ; b = 1
store r3 ;
load_smi 0 ; i = 0
store r4 ;
; loop:
load r1 ; n0 = n # why isn't it directly using `n`?
store r5 ;
load r5 ;
cmp_lt r4 ; i < n
jump_if_false 32 ; jump? .end
jump 10 ; jump .body # numerical `for` should put the latch at end
# which would remove `jump.body` and `jump .loop` here
# the ending `jump .latch` would turn to `jump .loop`
; latch:
load_smi 1 ; i += 1
add r4 ;
store r4 ;
jump_loop 14 ; jump .loop
; body:
load r2 ; temp = a # probably same problem as `n0` above
store r6 ;
load r3 ; temp += b
add r6 ;
store r6 ;
load r3 ; a = b # need a `mov` that's a peephole of `load, store`
store r2 ;
load r6 ; b = temp # also mov
store r3 ;
jump_loop 26 ; jump .latch
load r2 ; return a
return ;
load_none ; return none # basic block DCE would eliminate this
return ;
```