jz 0.0.0 → 0.1.0

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/src/ctx.js ADDED
@@ -0,0 +1,243 @@
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
+ currentPrefix: null,
113
+ }
114
+
115
+ ctx.scope = {
116
+ chain: derive(globals),
117
+ globals: new Map(),
118
+ userGlobals: new Set(),
119
+ globalTypes: new Map(),
120
+ globalValTypes: null,
121
+ globalTypedElem: null,
122
+ repByGlobal: null, // Map<name, ValueRep> — module-level pointer reps (TYPED const globals stored as raw i32 offset, etc.)
123
+ consts: null,
124
+ }
125
+
126
+ ctx.func = {
127
+ list: [],
128
+ names: new Set(), // Set<string> — known func names (list + imported funcs); populated at compile() start
129
+ map: new Map(), // Map<string, func> — name → func entry; populated at compile() start
130
+ exports: {},
131
+ current: null,
132
+ locals: new Map(),
133
+ repByLocal: null,
134
+ refinements: new Map(), // flow-sensitive: name → VAL.* inside a type-guarded branch
135
+ boxed: new Map(),
136
+ stack: [],
137
+ uniq: 0,
138
+ inTry: false,
139
+ localProps: null,
140
+ }
141
+
142
+ ctx.types = {
143
+ typedElem: null,
144
+ dynKeyVars: null,
145
+ anyDynKey: false,
146
+ }
147
+
148
+ ctx.schema = {
149
+ list: [],
150
+ vars: new Map(),
151
+ register: null,
152
+ find: null,
153
+ targetStack: [],
154
+ autoBox: null,
155
+ slotTypes: new Map(), // schemaId → Array<VAL.* | null | undefined>
156
+ // undefined: no observation, null: ≥2 distinct kinds, VAL.*: monomorphic
157
+ // Populated by collectProgramFacts on object literals;
158
+ // read by ctx.schema.slotVT (precise-only) so valTypeOf
159
+ // returns the slot's kind for `.prop` AST nodes, letting
160
+ // `+`/`===`/method dispatch elide `__is_str_key` checks
161
+ // on numeric properties of known shapes.
162
+ }
163
+
164
+ ctx.closure = {
165
+ types: null,
166
+ table: null,
167
+ bodies: null,
168
+ make: null,
169
+ call: null,
170
+ }
171
+
172
+ ctx.runtime = {
173
+ atom: null,
174
+ regex: null,
175
+ data: null,
176
+ dataDedup: new Map(), // str → offset (dedup literal bytes in active data segment)
177
+ strPool: null, // shared-memory: accumulated raw bytes of string literals (no length prefix)
178
+ strPoolDedup: new Map(), // str → offset in strPool
179
+ throws: false,
180
+ }
181
+
182
+ ctx.memory = {
183
+ shared: false,
184
+ pages: 0,
185
+ }
186
+
187
+ ctx.error = {
188
+ src: '',
189
+ loc: null,
190
+ }
191
+
192
+ ctx.transform = {
193
+ jzify: null,
194
+ noTailCall: false, // when true, emit `return call` instead of `return_call` (wasm2c compat)
195
+ strict: false, // when true, dynamic features (obj[k], for-in) error at compile time
196
+ // instead of pulling in dynamic-dispatch stdlib. See ProgramFacts walk.
197
+ runtimeExports: true, // when false, omit helper exports like _alloc/_reset from raw wasm output.
198
+ optimize: null, // resolved {watr, hoistPtrType, ...} config — set in index.js via resolveOptimize().
199
+ // Read by optimizeModule() (compile.js) and the post-watr pass (index.js).
200
+ // null is treated as level 2 (all on) for back-compat with internal callers.
201
+ }
202
+
203
+ // Feature flags: capabilities the compiled module may exercise at runtime.
204
+ // Set true by producer sites (import points, auto-imports, dynamic call sites).
205
+ // Read by stdlib template factories and deps graph at resolveIncludes() time to
206
+ // elide dead branches / skip unused imports. All default false; templates must be
207
+ // safe when flag is off (i.e. no way to produce a value of the gated kind).
208
+ //
209
+ // Only `external` is wired into emission today. The rest are slots for future
210
+ // work — most are currently usage-gated organically by `inc()`/stdlibDeps (a
211
+ // stdlib only lands in the binary if something called inc() for it, directly
212
+ // or transitively). Promote them here when one of two conditions holds:
213
+ // (a) a stdlib has dead conditional branches that can be elided when off
214
+ // (how `external` saves bytes in __hash_*/__set_*/__map_*/__dyn_get_any)
215
+ // (b) a capability needs an opt-in A/B switch against the default path
216
+ // (SSO is the planned first user — default string-literal emission
217
+ // currently forces SSO for ≤4 ASCII chars at string.js:49)
218
+ ctx.features = {
219
+ external: false, // PTR.EXTERNAL possible — opts.imports, HOST_GLOBALS, or __ext_call site. WIRED.
220
+ hash: false, // PTR.HASH + __dyn_* substrate. Organic: any inc(__hash_*/__dyn_*) implies on.
221
+ sso: true, // ≤4-ASCII string packing. Default on; flip off to A/B the heap-only path.
222
+ regex: false, // RegExp literals + methods. Organic via inc(__regex_*).
223
+ json: false, // JSON.parse/stringify. Organic via inc(__jp_*/__json_*).
224
+ typedarray: false,// Float64Array/Int32Array/etc. Organic via inc(__typed_*) + ctx.closure.floor.
225
+ set: false, // Set. Organic via inc(__set_*).
226
+ map: false, // Map. Organic via inc(__map_*).
227
+ closure: false, // First-class functions. Organic via ctx.closure.table population.
228
+ timers: false, // Set by prepare.js when timer module is included
229
+ blockingTimers: false, // wasmtime CLI: include __timer_loop in _start
230
+ }
231
+ }
232
+
233
+ /** Throw with source location context. */
234
+ export function err(msg) {
235
+ if (ctx.error.loc != null && ctx.error.src) {
236
+ const before = ctx.error.src.slice(0, ctx.error.loc)
237
+ const line = before.split('\n').length
238
+ const col = ctx.error.loc - before.lastIndexOf('\n')
239
+ const src = ctx.error.src.split('\n')[line - 1]
240
+ throw Error(`${msg}\n at line ${line}:${col}\n ${src}\n ${' '.repeat(col - 1)}^`)
241
+ }
242
+ throw Error(msg)
243
+ }