-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathtypes.ts
132 lines (90 loc) · 3.19 KB
/
types.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import type { Instruction } from "./instructions/instructions"
import type { WasmType, WasmValue, Wasm } from "ts-type-math"
export type MemoryAddress = WasmValue;
export type MemoryByAddress = Record<MemoryAddress, Wasm.Byte>
export type BranchId = string;
export type GlobalsById = Record<string, WasmValue>;
export type Param = string;
export type FuncId = string;
export type Func = {
kind: 'func';
params: Param[];
paramsTypes: WasmType[];
resultTypes: WasmType[];
locals: string[];
instructions: Instruction[];
}
export type LocalsById = Record<string, WasmValue>;
export type BranchesById = Record<BranchId, Instruction[]>;
export type FuncsById = Record<FuncId, Func>;
export type GarbageCollection = number;
export type IndirectTable = Record<MemoryAddress, FuncId>;
/** do a memory sweep every 4 kibibytes */
export type SweepL1Every = 1024;
export type StorageBits = 8 | 16 | 32 | 64;
export type ExecutionContext = {
/** the current local variable values */
locals: LocalsById;
/** not really required, but really helpful for debugging */
funcId: string;
/**
* a control flow helper that tells the program how to interpret the next when it hits a branch
*/
branches: BranchesById;
/** the size of the stack right before this function is called (but after params are populated) */
stackDepth: number;
/** the state of the instruction stack right before this function was called, we will resume from this */
instructions: Instruction[]
}
/** matches what JS implementations do regarding returning one vs multiple values */
export type Results = (number | bigint)[] | (number | bigint) | null;
export type Count = number;
export type CallHistory = [FuncId, Count];
export type ProgramState = {
/** the number of instructions we've executed, useful for debugging */
count: Count;
/** a stack of values */
stack: WasmValue[];
/** the current execution context funcId */
activeFuncId: string;
/** the current execution context's stack depth */
activeStackDepth: number;
/** the current execution context locals */
activeLocals: LocalsById;
/** the currently executing instructions */
instructions: Instruction[];
/** the current execution context branches */
activeBranches: BranchesById;
/** the L1 cache */
L1Cache: MemoryByAddress;
/** the linear memory of the program */
memory: MemoryByAddress;
/** a stack of execution contexts */
executionContexts: ExecutionContext[];
funcs: FuncsById;
/** records interval for GarbageCollection */
garbageCollection: GarbageCollection;
globals: GlobalsById;
memorySize: WasmValue;
/** used for dynamic dispatch: maps directly to funcs */
indirect: IndirectTable;
/** the result of the program */
results: Results;
/** used for debugging */
callHistory: CallHistory[];
}
export type ProgramInput = Pick<
ProgramState,
| "memory" | "indirect" | "globals" | "memorySize"
> & {
arguments: number[] | bigint[];
funcs: FuncsById & {
$entry: Func;
};
}
type RemoveNullTerminator<T extends string> =
T extends `${infer A}${infer B}`
? `${A extends "\0" ? "" : A}${RemoveNullTerminator<B>}`
: T;
type Example = RemoveNullTerminator<`Make it perfect!\u0000`>;
// ^?