jz 0.5.1 → 0.6.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/README.md +288 -314
- package/bench/README.md +319 -0
- package/bench/bench.svg +112 -0
- package/cli.js +32 -24
- package/index.js +177 -55
- package/interop.js +88 -159
- package/jz.svg +5 -0
- package/jzify/arguments.js +97 -0
- package/jzify/bundler.js +382 -0
- package/jzify/classes.js +328 -0
- package/jzify/hoist-vars.js +177 -0
- package/jzify/index.js +51 -0
- package/jzify/names.js +37 -0
- package/jzify/switch.js +106 -0
- package/jzify/transform.js +349 -0
- package/layout.js +179 -0
- package/module/array.js +322 -153
- package/module/collection.js +603 -145
- package/module/console.js +55 -43
- package/module/core.js +266 -153
- package/module/date.js +15 -3
- package/module/function.js +73 -6
- package/module/index.js +2 -1
- package/module/json.js +226 -61
- package/module/math.js +414 -186
- package/module/number.js +306 -60
- package/module/object.js +448 -184
- package/module/regex.js +255 -25
- package/module/schema.js +24 -6
- package/module/simd.js +85 -0
- package/module/string.js +586 -220
- package/module/symbol.js +1 -1
- package/module/timer.js +9 -14
- package/module/typedarray.js +45 -48
- package/package.json +41 -12
- package/src/abi/index.js +39 -23
- package/src/abi/string.js +38 -41
- package/src/ast.js +460 -0
- package/src/autoload.js +26 -24
- package/src/bridge.js +111 -0
- package/src/compile/analyze-scans.js +661 -0
- package/src/compile/analyze.js +1565 -0
- package/src/compile/emit-assign.js +408 -0
- package/src/compile/emit.js +3201 -0
- package/src/compile/flow-types.js +103 -0
- package/src/{compile.js → compile/index.js} +497 -125
- package/src/{infer.js → compile/infer.js} +27 -98
- package/src/{narrow.js → compile/narrow.js} +302 -96
- package/src/compile/plan/advise.js +316 -0
- package/src/compile/plan/common.js +150 -0
- package/src/compile/plan/index.js +118 -0
- package/src/compile/plan/inline.js +679 -0
- package/src/compile/plan/literals.js +984 -0
- package/src/compile/plan/loops.js +472 -0
- package/src/compile/plan/scope.js +573 -0
- package/src/compile/program-facts.js +404 -0
- package/src/ctx.js +176 -58
- package/src/ir.js +540 -171
- package/src/kind-traits.js +105 -0
- package/src/kind.js +462 -0
- package/src/op-policy.js +57 -0
- package/src/{optimize.js → optimize/index.js} +1106 -446
- package/src/optimize/vectorize.js +1874 -0
- package/src/param-reps.js +65 -0
- package/src/parse.js +44 -0
- package/src/{prepare.js → prepare/index.js} +589 -202
- package/src/reps.js +115 -0
- package/src/resolve.js +12 -3
- package/src/static.js +199 -0
- package/src/type.js +647 -0
- package/src/{assemble.js → wat/assemble.js} +86 -48
- package/src/wat/optimize.js +3760 -0
- package/transform.js +21 -0
- package/wasi.js +47 -5
- package/src/analyze.js +0 -3818
- package/src/emit.js +0 -3040
- package/src/jzify.js +0 -1580
- package/src/plan.js +0 -2132
- package/src/vectorize.js +0 -1088
- /package/src/{codegen.js → wat/codegen.js} +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-call paramReps lattice — Map<funcName, Map<paramIdx, ValueRep fields>>.
|
|
3
|
+
*
|
|
4
|
+
* Cycle-free leaf consumed by narrow.js (fixpoint) and infer.js (call-site
|
|
5
|
+
* evidence producers).
|
|
6
|
+
*
|
|
7
|
+
* THE LATTICE (per field). Three states:
|
|
8
|
+
* - BOTTOM = `undefined` — unobserved / "no site has spoken yet".
|
|
9
|
+
* - a value — consensus across all sites seen so far.
|
|
10
|
+
* - TOP = `null` — conflict: two sites disagreed. Sticky.
|
|
11
|
+
*
|
|
12
|
+
* The meet is monotone: meet(BOTTOM, x) = x, meet(x, x) = x, meet(x, y≠x) = TOP,
|
|
13
|
+
* meet(TOP, _) = TOP. Over a finite height-2 lattice it converges with NO resets —
|
|
14
|
+
* narrow.js's clearStickyNull (which used to un-stick a spurious "can't tell yet"
|
|
15
|
+
* poison) is gone entirely (root B closed). Two complementary policies keep it so:
|
|
16
|
+
*
|
|
17
|
+
* - `val` runs SOFT (narrow.js mergeRule soft=true): a can't-tell-yet site is
|
|
18
|
+
* skipped (stays BOTTOM), never poisoned, so a later pass — e.g. once pointer-
|
|
19
|
+
* ABI enrichment puts VAL.TYPED into callerValTypes — simply fills it in. A
|
|
20
|
+
* signature-mutating consumer (applyPointerParamAbi) can't trust this partial
|
|
21
|
+
* soft value, so it re-folds the sites HARD (hardParamVal); a final hard sweep
|
|
22
|
+
* settles `val` for emit + late readers (specializeBimorphicTyped, …).
|
|
23
|
+
* - `schemaId` (and the others) stay HARD, but no longer get stuck: narrowValResults
|
|
24
|
+
* is hoisted ABOVE the param lattice, so a call arg `f()` resolves to its VAL
|
|
25
|
+
* result on the first pass and the can't-tell poison never forms.
|
|
26
|
+
*
|
|
27
|
+
* @module param-reps
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/** Build `paramName → fact` lookup for a caller's already-narrowed param facts. */
|
|
31
|
+
export const paramFactsOf = (paramReps, callerFunc, key) => {
|
|
32
|
+
if (!callerFunc) return null
|
|
33
|
+
const m = paramReps.get(callerFunc.name)
|
|
34
|
+
if (!m) return null
|
|
35
|
+
let out = null
|
|
36
|
+
for (const [k, r] of m) {
|
|
37
|
+
const v = r[key]
|
|
38
|
+
if (v != null && k < callerFunc.sig.params.length) {
|
|
39
|
+
out ||= new Map()
|
|
40
|
+
out.set(callerFunc.sig.params[k].name, v)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return out
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The meet itself: fold `observed` into a param's ValueRep field. BOTTOM
|
|
47
|
+
* (undefined) → observed; equal → unchanged; disagreement → TOP (null, sticky).
|
|
48
|
+
* A null `observed` is "can't tell" — whether that means BOTTOM (skip) or TOP
|
|
49
|
+
* (poison) is the *caller's* policy: narrow.js's soft mergeRule skips before
|
|
50
|
+
* calling here; the hard mergeRule / missing-arg path poisons by passing null. */
|
|
51
|
+
export const mergeParamFact = (rep, key, observed) => {
|
|
52
|
+
if (rep[key] === null) return // already TOP — sticky
|
|
53
|
+
if (observed == null) { rep[key] = null; return } // caller chose to poison (hard path)
|
|
54
|
+
if (rep[key] === undefined) rep[key] = observed // BOTTOM → first observation
|
|
55
|
+
else if (rep[key] !== observed) rep[key] = null // disagreement → TOP
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Get-or-create per-param rep at (funcName, paramIdx) on a paramReps map. */
|
|
59
|
+
export const ensureParamRep = (paramReps, funcName, k) => {
|
|
60
|
+
let m = paramReps.get(funcName)
|
|
61
|
+
if (!m) { m = new Map(); paramReps.set(funcName, m) }
|
|
62
|
+
let r = m.get(k)
|
|
63
|
+
if (!r) { r = {}; m.set(k, r) }
|
|
64
|
+
return r
|
|
65
|
+
}
|
package/src/parse.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* jz's parser entry — subscript's jessie dialect with one jz-specific override.
|
|
3
|
+
*
|
|
4
|
+
* `NaN` parses to the self-describing `['nan']` marker rather than subscript's
|
|
5
|
+
* default `[, NaN]` value-literal. A raw number-NaN (0x7FF8…) is ambiguous with
|
|
6
|
+
* jz's NaN-boxed value space: as the literal flows through the self-host kernel's
|
|
7
|
+
* parse/marshalling path it decodes back as a boxed value (object), so `() => NaN`
|
|
8
|
+
* would miscompile to `f64.const 0`. The string-tagged marker can't be mistaken
|
|
9
|
+
* for a number, survives intact, and emit() lowers it to the canonical quiet NaN
|
|
10
|
+
* (see compile/emit.js `op === 'nan'`). This mirrors subscript's own reason for
|
|
11
|
+
* encoding `undefined` as `[]` instead of `[, undefined]` (feature/literal.js).
|
|
12
|
+
* Infinity is 0x7FF0 — outside the NaN-box space — so it survives as a plain
|
|
13
|
+
* literal and needs no override.
|
|
14
|
+
*/
|
|
15
|
+
import { parse as jessieParse, token } from 'subscript/feature/jessie'
|
|
16
|
+
|
|
17
|
+
// Strip a leading `#!` shebang line before subscript sees it. subscript registers the
|
|
18
|
+
// shebang via `parse.comment['#!']='\n'` (feature/shebang.js) on a literal-seeded object,
|
|
19
|
+
// then enumerates it — a cross-module dynamic-extension of a fixed-schema object that the
|
|
20
|
+
// self-host kernel doesn't surface (the added key is stored but unenumerated). An explicit
|
|
21
|
+
// strip is the conventional parser responsibility anyway (Node, V8 do the same), is
|
|
22
|
+
// host/kernel-identical, and is independent of object-model internals.
|
|
23
|
+
const parse = (src) => {
|
|
24
|
+
if (typeof src === 'string' && src.charCodeAt(0) === 35 && src.charCodeAt(1) === 33) {
|
|
25
|
+
const nl = src.indexOf('\n')
|
|
26
|
+
src = nl < 0 ? '' : src.slice(nl)
|
|
27
|
+
}
|
|
28
|
+
return jessieParse(src)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
token('NaN', 200, a => !a && ['nan'])
|
|
32
|
+
|
|
33
|
+
// `true`/`false` parse to the self-describing `['bool', 1|0]` marker rather than
|
|
34
|
+
// subscript's `[, true]`/`[, false]` value-literal. The raw JS boolean degrades to
|
|
35
|
+
// the bare number 1/0 as the literal flows through the self-host kernel's
|
|
36
|
+
// parse/marshalling path, so `valTypeOf` reads VAL.NUMBER and the value loses its
|
|
37
|
+
// VAL.BOOL kind — `typeof true` returns "number", `JSON.stringify(true)` yields "1".
|
|
38
|
+
// The marker (op `'bool'`) is type-tagged by op, not by its degradable payload, so
|
|
39
|
+
// valTypeOf returns VAL.BOOL unconditionally; emit lowers it to the same 0/1 carrier
|
|
40
|
+
// (no perf cost). Same rationale as the `NaN` → `['nan']` override above.
|
|
41
|
+
token('true', 200, a => !a && ['bool', 1])
|
|
42
|
+
token('false', 200, a => !a && ['bool', 0])
|
|
43
|
+
|
|
44
|
+
export { parse }
|