-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathbootstrap.ts
118 lines (110 loc) · 3.01 KB
/
bootstrap.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { executeInstruction } from "./program"
import type { Func, LocalsById, ProgramInput } from "./types"
import type { Convert, WasmType, WasmValue, evaluate, Satisfies } from "ts-type-math"
type _ProcessInputStack<
args extends [number[] | bigint[], WasmType[]],
_Acc extends WasmValue[] = []
> = Satisfies<WasmValue[],
args extends [
[
infer headValue extends (number | bigint),
...infer tailValue extends number[] | bigint[]
],
[
infer headType extends WasmType,
...infer tailType extends WasmType[]
],
]
? _ProcessInputStack<
[tailValue, tailType],
[
..._Acc,
headValue extends bigint
? Convert.TSBigInt.ToWasmValue<headValue>
: headValue extends number
? headType extends 'i32'
? Convert.TSNumber.ToWasmValue<headValue, headType>
: never
: never
]
>
: _Acc
>
export type ProcessInputStack<
input extends ProgramInput
> = Satisfies<WasmValue[],
_ProcessInputStack<[
input['arguments'],
input['funcs']['$entry']['paramsTypes'],
]>
>
type PopLocals<
params extends string[],
stack extends WasmValue[],
_Acc extends {
stack: WasmValue[];
activeLocals: LocalsById;
} = {
stack: stack;
activeLocals: {}
}
> = Satisfies<{ stack: WasmValue[]; activeLocals: LocalsById; },
params extends [
...infer remainingParams extends string[],
infer param extends string,
]
? stack extends [
...infer remainingStack extends WasmValue[],
infer pop extends WasmValue,
]
? PopLocals<
remainingParams,
remainingStack,
{
stack: remainingStack;
// append the new local to the activeLocals
activeLocals: _Acc['activeLocals'] & {
[k in param]: pop;
}
}
>
: never
: _Acc
>
export type bootstrap<
input extends ProgramInput,
debugMode extends boolean = false,
stopAt extends number = number, // defaulting to `number` ensures it'll always keep executing unless an explicit value is provided
_$entry extends Func = input['funcs']['$entry'],
_freshStack extends WasmValue[] = ProcessInputStack<input>,
_startData extends {
stack: WasmValue[];
activeLocals: LocalsById;
} = PopLocals<_$entry['params'], _freshStack>
> =
executeInstruction<
{
count: 0;
stack: _startData['stack'];
activeFuncId: "$entry";
activeStackDepth: _startData['stack']['length']; // BUG
activeLocals: _startData['activeLocals'];
instructions: [
..._$entry['instructions'],
{ kind: 'EndFunction', id: '$entry' },
];
activeBranches: {};
L1Cache: {};
memory: evaluate<input['memory']>; // copy readonly memory into memory registers
executionContexts: [];
funcs: input['funcs'];
garbageCollection: 0;
globals: input['globals'];
memorySize: input['memorySize'];
indirect: input['indirect'];
results: null;
callHistory: [];
},
debugMode,
stopAt
>