jz 0.1.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/src/plan.js ADDED
@@ -0,0 +1,105 @@
1
+ /** Pre-emit compile planning: collect facts, resolve ABIs, and run narrowing. */
2
+
3
+ import { ctx } from './ctx.js'
4
+ import { VAL, valTypeOf, typedElemCtor, typedElemAux, updateGlobalRep, collectProgramFacts } from './analyze.js'
5
+ import { MAX_CLOSURE_ARITY } from './ir.js'
6
+ import narrowSignatures, { specializeBimorphicTyped, refineDynKeys } from './narrow.js'
7
+
8
+ const scanGlobalValueFacts = (root) => {
9
+ if (!root) return
10
+ const stmts = Array.isArray(root) && root[0] === ';' ? root.slice(1) : [root]
11
+ for (const stmt of stmts) {
12
+ if (!Array.isArray(stmt) || (stmt[0] !== 'const' && stmt[0] !== 'let')) continue
13
+ for (const decl of stmt.slice(1)) {
14
+ if (!Array.isArray(decl) || decl[0] !== '=' || typeof decl[1] !== 'string') continue
15
+ const vt = valTypeOf(decl[2])
16
+ if (vt) {
17
+ if (!ctx.scope.globalValTypes) ctx.scope.globalValTypes = new Map()
18
+ ctx.scope.globalValTypes.set(decl[1], vt)
19
+ if (vt === VAL.REGEX && ctx.runtime.regex) ctx.runtime.regex.vars.set(decl[1], decl[2])
20
+ }
21
+ const ctor = typedElemCtor(decl[2])
22
+ if (ctor) {
23
+ if (!ctx.scope.globalTypedElem) ctx.scope.globalTypedElem = new Map()
24
+ ctx.scope.globalTypedElem.set(decl[1], ctor)
25
+ }
26
+ }
27
+ }
28
+ }
29
+
30
+ const unboxConstTypedGlobals = () => {
31
+ if (!ctx.scope.globalTypedElem || !ctx.scope.consts) return
32
+ for (const [name, ctor] of ctx.scope.globalTypedElem) {
33
+ if (!ctx.scope.consts.has(name)) continue
34
+ if (ctx.scope.globalValTypes?.get(name) !== VAL.TYPED) continue
35
+ const aux = typedElemAux(ctor)
36
+ if (aux == null) continue
37
+ const decl = ctx.scope.globals.get(name)
38
+ if (typeof decl !== 'string' || !decl.includes('mut f64')) continue
39
+ ctx.scope.globals.set(name, `(global $${name} (mut i32) (i32.const 0))`)
40
+ ctx.scope.globalTypes.set(name, 'i32')
41
+ updateGlobalRep(name, { ptrKind: VAL.TYPED, ptrAux: aux })
42
+ }
43
+ }
44
+
45
+ const materializeAutoBoxSchemas = (programFacts) => {
46
+ if (!ctx.schema.register) return
47
+ for (const [name, props] of programFacts.propMap) {
48
+ if (ctx.schema.vars.has(name)) {
49
+ const existing = ctx.schema.resolve(name)
50
+ const newProps = [...props].filter(prop => !existing.includes(prop))
51
+ if (newProps.length) {
52
+ const merged = [...existing, ...newProps]
53
+ const mergedId = ctx.schema.register(merged)
54
+ ctx.schema.vars.set(name, mergedId)
55
+ }
56
+ continue
57
+ }
58
+ const valueProps = [...props].filter(prop => !ctx.func.names.has(`${name}$${prop}`))
59
+ if (!valueProps.length) continue
60
+ const allProps = [...props]
61
+ const schema = ['__inner__', ...allProps]
62
+ const schemaId = ctx.schema.register(schema)
63
+ ctx.schema.vars.set(name, schemaId)
64
+ if (ctx.func.names.has(name) && !ctx.scope.globals.has(name))
65
+ ctx.scope.globals.set(name, `(global $${name} (mut f64) (f64.const 0))`)
66
+ if (!ctx.schema.autoBox) ctx.schema.autoBox = new Map()
67
+ ctx.schema.autoBox.set(name, { schemaId, schema })
68
+ }
69
+ }
70
+
71
+ const resolveClosureWidth = (programFacts) => {
72
+ if (!ctx.closure.make) return
73
+ const { hasSpread, hasRest, maxCall, maxDef } = programFacts
74
+ const floor = ctx.closure.floor ?? 0
75
+ ctx.closure.width = (hasSpread && hasRest)
76
+ ? MAX_CLOSURE_ARITY
77
+ : Math.min(MAX_CLOSURE_ARITY, Math.max(maxCall, maxDef + (hasRest ? 1 : 0), floor))
78
+ }
79
+
80
+ const canSkipWholeProgramNarrowing = (programFacts) =>
81
+ programFacts.callSites.length === 0 &&
82
+ programFacts.valueUsed.size === 0 &&
83
+ !programFacts.anyDyn &&
84
+ programFacts.propMap.size === 0 &&
85
+ !programFacts.hasSchemaLiterals &&
86
+ !ctx.closure.make
87
+
88
+ export default function plan(ast) {
89
+ scanGlobalValueFacts(ast)
90
+ unboxConstTypedGlobals()
91
+
92
+ const programFacts = collectProgramFacts(ast)
93
+ ctx.types.dynKeyVars = programFacts.dynVars
94
+ ctx.types.anyDynKey = programFacts.anyDyn
95
+
96
+ materializeAutoBoxSchemas(programFacts)
97
+ resolveClosureWidth(programFacts)
98
+ if (canSkipWholeProgramNarrowing(programFacts)) return programFacts
99
+
100
+ narrowSignatures(programFacts, ast)
101
+ specializeBimorphicTyped(programFacts)
102
+ refineDynKeys(programFacts)
103
+
104
+ return programFacts
105
+ }