jz 0.0.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +373 -0
- package/cli.js +163 -0
- package/index.js +247 -0
- package/module/array.js +1322 -0
- package/module/collection.js +793 -0
- package/module/console.js +192 -0
- package/module/core.js +644 -0
- package/module/function.js +181 -0
- package/module/index.js +15 -0
- package/module/json.js +506 -0
- package/module/math.js +390 -0
- package/module/number.js +601 -0
- package/module/object.js +359 -0
- package/module/regex.js +914 -0
- package/module/schema.js +106 -0
- package/module/string.js +985 -0
- package/module/symbol.js +55 -0
- package/module/timer.js +253 -0
- package/module/typedarray.js +713 -0
- package/package.json +56 -5
- package/src/analyze.js +1927 -0
- package/src/autoload.js +175 -0
- package/src/compile.js +1211 -0
- package/src/ctx.js +244 -0
- package/src/emit.js +2105 -0
- package/src/host.js +536 -0
- package/src/ir.js +649 -0
- package/src/jzify.js +418 -0
- package/src/key.js +73 -0
- package/src/narrow.js +928 -0
- package/src/optimize.js +1352 -0
- package/src/plan.js +105 -0
- package/src/prepare.js +1534 -0
- package/src/source.js +76 -0
- package/wasi.js +80 -0
package/src/ctx.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global compilation context, reset per jz() call.
|
|
3
|
+
*
|
|
4
|
+
* Everything is f64. Scalars are regular numbers. Pointers are NaN-boxed f64.
|
|
5
|
+
* Memory auto-enabled when arrays/objects/strings are used.
|
|
6
|
+
*
|
|
7
|
+
* Refactored into focused sub-contexts for better maintainability.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// === NaN-boxing pointer type codes ===
|
|
11
|
+
// SEALED: 4-bit tag (values 0-15). Layout is hardcoded in dispatch funcs
|
|
12
|
+
// (__length/__typeof/__to_str/__ptr_type) and the static-data strip pass
|
|
13
|
+
// ([src/compile.js] SHIFTABLE). No plugin/extension API — internal A/B
|
|
14
|
+
// measurement goes through `ctx.features.*` flags instead (see reset()).
|
|
15
|
+
// To retire a type, gate emission behind a feature flag and drop its dispatch
|
|
16
|
+
// branches; to add, renumber with care — all hardcoded branches must update.
|
|
17
|
+
export const PTR = {
|
|
18
|
+
ATOM: 0, // null, undefined, booleans
|
|
19
|
+
ARRAY: 1, // heap-allocated arrays
|
|
20
|
+
BUFFER: 2, // ArrayBuffer: [-8:byteLen][-4:byteCap][bytes]
|
|
21
|
+
TYPED: 3, // TypedArrays (Float64Array, etc.)
|
|
22
|
+
STRING: 4, // heap-allocated strings
|
|
23
|
+
SSO: 5, // short string optimization (≤4 ASCII chars inline)
|
|
24
|
+
OBJECT: 6, // plain objects
|
|
25
|
+
HASH: 7, // dynamic objects (Map-like)
|
|
26
|
+
SET: 8, // Set collections
|
|
27
|
+
MAP: 9, // Map collections
|
|
28
|
+
CLOSURE: 10, // first-class functions
|
|
29
|
+
EXTERNAL: 11, // JS host object refs (aux=0, offset→extMap index)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// === Global context with nested sub-contexts ===
|
|
33
|
+
// Each namespace has a single lifecycle phase and clear ownership. Violating
|
|
34
|
+
// these boundaries (e.g. emit writing to ctx.scope) signals a design smell.
|
|
35
|
+
//
|
|
36
|
+
// Lifecycle phases (reset() at phase start):
|
|
37
|
+
// init — once at boot (reset() on first jz() call)
|
|
38
|
+
// compile — per jz() invocation
|
|
39
|
+
// function — per function being lowered
|
|
40
|
+
// emit — transient during a single AST→IR dispatch
|
|
41
|
+
//
|
|
42
|
+
// | Namespace | Phase | Writers | Readers |
|
|
43
|
+
// |-----------|----------|---------------------------|----------------------------|
|
|
44
|
+
// | core | compile | reset, modules, inc() | emit, compile, modules |
|
|
45
|
+
// | module | compile | prepare, index.js | prepare, compile, emit |
|
|
46
|
+
// | scope | compile | analyze, compile | compile, emit |
|
|
47
|
+
// | func | function | compile | emit, modules |
|
|
48
|
+
// | types | function | analyze | emit, modules |
|
|
49
|
+
// | schema | compile | prepare, analyze, compile | prepare, analyze, emit |
|
|
50
|
+
// | closure | init | modules (fn plugin) | emit, compile |
|
|
51
|
+
// | runtime | compile | emit, modules | emit, compile |
|
|
52
|
+
// | memory | compile | index.js | compile |
|
|
53
|
+
// | error | compile | prepare, compile, emit | err() |
|
|
54
|
+
// | transform | compile | index.js | prepare |
|
|
55
|
+
// | features | compile | emit, modules, prepare | compile (resolveIncludes), |
|
|
56
|
+
// | | | | stdlib factories |
|
|
57
|
+
export const ctx = {
|
|
58
|
+
core: {}, // emitter table + stdlib registry (seeded by reset + modules)
|
|
59
|
+
module: {}, // module graph: imports, resolved sources, module-init blocks
|
|
60
|
+
scope: {}, // bindings: globals, consts, typed-elem ctors per global
|
|
61
|
+
func: {}, // current function: locals, signature, name registry, uniq counter
|
|
62
|
+
types: {}, // per-function type analysis: typedElem map, dyn-key vars
|
|
63
|
+
schema: {}, // object shape inference: var→schema, schema list
|
|
64
|
+
closure: {}, // first-class fn infrastructure (installed by module/function.js)
|
|
65
|
+
runtime: {}, // runtime state: data segments, string pool, atom table, throws flag
|
|
66
|
+
memory: {}, // module memory config (pages, shared)
|
|
67
|
+
error: {}, // source location carried through emit for err() messages
|
|
68
|
+
transform: {}, // compile-time options (jzify, etc.)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Create a child scope via shallow flat copy (metacircular-safe: no prototype chain).
|
|
72
|
+
* Mutations to the child do not affect the parent; lookups work via direct property access. */
|
|
73
|
+
export const derive = (parent) => ({ ...parent })
|
|
74
|
+
|
|
75
|
+
/** Include stdlib names for emission. */
|
|
76
|
+
export const inc = (...names) => names.forEach(n => ctx.core.includes.add(n))
|
|
77
|
+
|
|
78
|
+
/** Expand ctx.core.includes transitively via ctx.core.stdlibDeps. Call before WASM assembly.
|
|
79
|
+
* Each module co-locates its own deps with its stdlib registrations at init time. */
|
|
80
|
+
export function resolveIncludes() {
|
|
81
|
+
const graph = ctx.core.stdlibDeps
|
|
82
|
+
const queue = [...ctx.core.includes]
|
|
83
|
+
while (queue.length) {
|
|
84
|
+
const name = queue.pop()
|
|
85
|
+
const entry = graph[name]
|
|
86
|
+
const deps = typeof entry === 'function' ? entry() : entry
|
|
87
|
+
if (deps) for (const dep of deps) {
|
|
88
|
+
if (!ctx.core.includes.has(dep)) { ctx.core.includes.add(dep); queue.push(dep) }
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Reset all compilation state. Called once per jz() invocation. */
|
|
94
|
+
export function reset(proto, globals) {
|
|
95
|
+
ctx.core = {
|
|
96
|
+
emit: derive(proto),
|
|
97
|
+
stdlib: {},
|
|
98
|
+
stdlibDeps: {}, // populated per-module at init time (was STDLIB_DEPS in this file)
|
|
99
|
+
includes: new Set(),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
ctx.module = {
|
|
104
|
+
imports: [],
|
|
105
|
+
modules: {},
|
|
106
|
+
importSources: null,
|
|
107
|
+
hostImports: null,
|
|
108
|
+
hostImportValTypes: new Map(),
|
|
109
|
+
resolvedModules: new Map(),
|
|
110
|
+
moduleStack: [],
|
|
111
|
+
moduleInits: [],
|
|
112
|
+
initFacts: null,
|
|
113
|
+
currentPrefix: null,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
ctx.scope = {
|
|
117
|
+
chain: derive(globals),
|
|
118
|
+
globals: new Map(),
|
|
119
|
+
userGlobals: new Set(),
|
|
120
|
+
globalTypes: new Map(),
|
|
121
|
+
globalValTypes: null,
|
|
122
|
+
globalTypedElem: null,
|
|
123
|
+
repByGlobal: null, // Map<name, ValueRep> — module-level pointer reps (TYPED const globals stored as raw i32 offset, etc.)
|
|
124
|
+
consts: null,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
ctx.func = {
|
|
128
|
+
list: [],
|
|
129
|
+
names: new Set(), // Set<string> — known func names (list + imported funcs); populated at compile() start
|
|
130
|
+
map: new Map(), // Map<string, func> — name → func entry; populated at compile() start
|
|
131
|
+
exports: {},
|
|
132
|
+
current: null,
|
|
133
|
+
locals: new Map(),
|
|
134
|
+
repByLocal: null,
|
|
135
|
+
refinements: new Map(), // flow-sensitive: name → VAL.* inside a type-guarded branch
|
|
136
|
+
boxed: new Map(),
|
|
137
|
+
stack: [],
|
|
138
|
+
uniq: 0,
|
|
139
|
+
inTry: false,
|
|
140
|
+
localProps: null,
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
ctx.types = {
|
|
144
|
+
typedElem: null,
|
|
145
|
+
dynKeyVars: null,
|
|
146
|
+
anyDynKey: false,
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
ctx.schema = {
|
|
150
|
+
list: [],
|
|
151
|
+
vars: new Map(),
|
|
152
|
+
register: null,
|
|
153
|
+
find: null,
|
|
154
|
+
targetStack: [],
|
|
155
|
+
autoBox: null,
|
|
156
|
+
slotTypes: new Map(), // schemaId → Array<VAL.* | null | undefined>
|
|
157
|
+
// undefined: no observation, null: ≥2 distinct kinds, VAL.*: monomorphic
|
|
158
|
+
// Populated by collectProgramFacts on object literals;
|
|
159
|
+
// read by ctx.schema.slotVT (precise-only) so valTypeOf
|
|
160
|
+
// returns the slot's kind for `.prop` AST nodes, letting
|
|
161
|
+
// `+`/`===`/method dispatch elide `__is_str_key` checks
|
|
162
|
+
// on numeric properties of known shapes.
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
ctx.closure = {
|
|
166
|
+
types: null,
|
|
167
|
+
table: null,
|
|
168
|
+
bodies: null,
|
|
169
|
+
make: null,
|
|
170
|
+
call: null,
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
ctx.runtime = {
|
|
174
|
+
atom: null,
|
|
175
|
+
regex: null,
|
|
176
|
+
data: null,
|
|
177
|
+
dataDedup: new Map(), // str → offset (dedup literal bytes in active data segment)
|
|
178
|
+
strPool: null, // shared-memory: accumulated raw bytes of string literals (no length prefix)
|
|
179
|
+
strPoolDedup: new Map(), // str → offset in strPool
|
|
180
|
+
throws: false,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
ctx.memory = {
|
|
184
|
+
shared: false,
|
|
185
|
+
pages: 0,
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
ctx.error = {
|
|
189
|
+
src: '',
|
|
190
|
+
loc: null,
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
ctx.transform = {
|
|
194
|
+
jzify: null,
|
|
195
|
+
noTailCall: false, // when true, emit `return call` instead of `return_call` (wasm2c compat)
|
|
196
|
+
strict: false, // when true, dynamic features (obj[k], for-in) error at compile time
|
|
197
|
+
// instead of pulling in dynamic-dispatch stdlib. See ProgramFacts walk.
|
|
198
|
+
runtimeExports: true, // when false, omit helper exports like _alloc/_reset from raw wasm output.
|
|
199
|
+
optimize: null, // resolved {watr, hoistPtrType, ...} config — set in index.js via resolveOptimize().
|
|
200
|
+
// Read by optimizeModule() (compile.js) and the post-watr pass (index.js).
|
|
201
|
+
// null is treated as level 2 (all on) for back-compat with internal callers.
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Feature flags: capabilities the compiled module may exercise at runtime.
|
|
205
|
+
// Set true by producer sites (import points, auto-imports, dynamic call sites).
|
|
206
|
+
// Read by stdlib template factories and deps graph at resolveIncludes() time to
|
|
207
|
+
// elide dead branches / skip unused imports. All default false; templates must be
|
|
208
|
+
// safe when flag is off (i.e. no way to produce a value of the gated kind).
|
|
209
|
+
//
|
|
210
|
+
// Only `external` is wired into emission today. The rest are slots for future
|
|
211
|
+
// work — most are currently usage-gated organically by `inc()`/stdlibDeps (a
|
|
212
|
+
// stdlib only lands in the binary if something called inc() for it, directly
|
|
213
|
+
// or transitively). Promote them here when one of two conditions holds:
|
|
214
|
+
// (a) a stdlib has dead conditional branches that can be elided when off
|
|
215
|
+
// (how `external` saves bytes in __hash_*/__set_*/__map_*/__dyn_get_any)
|
|
216
|
+
// (b) a capability needs an opt-in A/B switch against the default path
|
|
217
|
+
// (SSO is the planned first user — default string-literal emission
|
|
218
|
+
// currently forces SSO for ≤4 ASCII chars at string.js:49)
|
|
219
|
+
ctx.features = {
|
|
220
|
+
external: false, // PTR.EXTERNAL possible — opts.imports, HOST_GLOBALS, or __ext_call site. WIRED.
|
|
221
|
+
hash: false, // PTR.HASH + __dyn_* substrate. Organic: any inc(__hash_*/__dyn_*) implies on.
|
|
222
|
+
sso: true, // ≤4-ASCII string packing. Default on; flip off to A/B the heap-only path.
|
|
223
|
+
regex: false, // RegExp literals + methods. Organic via inc(__regex_*).
|
|
224
|
+
json: false, // JSON.parse/stringify. Organic via inc(__jp_*/__json_*).
|
|
225
|
+
typedarray: false,// Float64Array/Int32Array/etc. Organic via inc(__typed_*) + ctx.closure.floor.
|
|
226
|
+
set: false, // Set. Organic via inc(__set_*).
|
|
227
|
+
map: false, // Map. Organic via inc(__map_*).
|
|
228
|
+
closure: false, // First-class functions. Organic via ctx.closure.table population.
|
|
229
|
+
timers: false, // Set by prepare.js when timer module is included
|
|
230
|
+
blockingTimers: false, // wasmtime CLI: include __timer_loop in _start
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Throw with source location context. */
|
|
235
|
+
export function err(msg) {
|
|
236
|
+
if (ctx.error.loc != null && ctx.error.src) {
|
|
237
|
+
const before = ctx.error.src.slice(0, ctx.error.loc)
|
|
238
|
+
const line = before.split('\n').length
|
|
239
|
+
const col = ctx.error.loc - before.lastIndexOf('\n')
|
|
240
|
+
const src = ctx.error.src.split('\n')[line - 1]
|
|
241
|
+
throw Error(`${msg}\n at line ${line}:${col}\n ${src}\n ${' '.repeat(col - 1)}^`)
|
|
242
|
+
}
|
|
243
|
+
throw Error(msg)
|
|
244
|
+
}
|