@fraczak/k 6.3.2 → 6.4.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/DOCS/CODECS.md +258 -0
- package/DOCS/DICTIONARY.md +1172 -0
- package/DOCS/KIR_SPECIALIZATION_DESIGN.md +51 -46
- package/DOCS/KIR_V1.md +221 -0
- package/DOCS/KVM_EXECUTION_MODEL.md +56 -19
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +2 -1
- package/DOCS/PROFILING_AND_TRACING.md +196 -0
- package/DOCS/REPL.md +76 -14
- package/DOCS/WEB_REPL_REQUIREMENTS.md +135 -0
- package/DOCS/dependency-graph.md +144 -0
- package/Examples/arithmetics.k +51 -48
- package/Examples/bnat.k +1 -1
- package/Examples/buda.k +44 -0
- package/Examples/ieee.k +300 -8671
- package/Examples/poly.k +67 -0
- package/README.md +68 -19
- package/augmentation.mjs +9 -7
- package/backend-api.mjs +11 -2
- package/backends/arm64/README.md +104 -0
- package/backends/arm64/bin/k-arm64-compile.mjs +101 -0
- package/backends/arm64/bin/k-arm64-run.mjs +58 -0
- package/backends/arm64/bin/k-arm64.mjs +88 -0
- package/backends/arm64/scripts/run-tests.mjs +41 -0
- package/backends/arm64/src/arm64.mjs +229 -0
- package/backends/arm64/src/cli.mjs +155 -0
- package/backends/arm64/src/kvm2arm64.mjs +906 -0
- package/backends/arm64/src/runtime.c +728 -0
- package/backends/arm64/tests/integration.sh +112 -0
- package/backends/arm64/tests/test-arm64.mjs +240 -0
- package/backends/llvm/README.md +135 -0
- package/backends/llvm/bin/k-llvm-build.mjs +71 -0
- package/backends/llvm/bin/k-llvm-compile.mjs +68 -0
- package/backends/llvm/bin/k-llvm-jit.mjs +160 -0
- package/backends/llvm/bin/k-llvm-run.mjs +90 -0
- package/backends/llvm/runtime/krt.c +1508 -0
- package/backends/llvm/runtime/krt.h +109 -0
- package/backends/llvm/scripts/conformance.mjs +76 -0
- package/backends/llvm/scripts/run-tests.mjs +28 -0
- package/backends/llvm/src/executable.mjs +562 -0
- package/backends/llvm/src/kvm2llvm.mjs +998 -0
- package/backends/llvm/src/llvm.mjs +1092 -0
- package/backends/llvm/tests/composition-driver.c +22 -0
- package/backends/llvm/tests/identity-driver.c +27 -0
- package/backends/llvm/tests/integration.sh +153 -0
- package/backends/llvm/tests/perf-support.mjs +735 -0
- package/backends/llvm/tests/product-driver.c +23 -0
- package/backends/llvm/tests/projection-driver.c +19 -0
- package/backends/llvm/tests/relation-driver.c +29 -0
- package/backends/llvm/tests/test-llvm.mjs +240 -0
- package/backends/llvm/tests/union-driver.c +31 -0
- package/backends/llvm/tests/variant-driver.c +19 -0
- package/backends/llvm/tests/variant-projection-driver.c +21 -0
- package/backends/wasm/DOCS/USE-WEB-ASSEMBLY.md +233 -0
- package/backends/wasm/README.md +97 -0
- package/backends/wasm/TECHNICAL-DEBT.md +60 -0
- package/backends/wasm/bin/k-wasm-compile.mjs +50 -0
- package/backends/wasm/bin/k-wasm-run.mjs +140 -0
- package/backends/wasm/bin/k-wasm.mjs +49 -0
- package/backends/wasm/demo_ieee.mjs +319 -0
- package/backends/wasm/runtime.wat +102 -0
- package/backends/wasm/scripts/run-tests.mjs +41 -0
- package/backends/wasm/src/cli.mjs +133 -0
- package/backends/wasm/src/kvm2wasm.mjs +661 -0
- package/backends/wasm/src/wasm.mjs +1010 -0
- package/backends/wasm/tests/integration.sh +182 -0
- package/backends/wasm/tests/perf-support.mjs +336 -0
- package/backends/wasm/tests/test-wasm.mjs +617 -0
- package/browser/repl-browser.mjs +1584 -0
- package/browser/shims/assert.mjs +19 -0
- package/browser/shims/buffer.mjs +224 -0
- package/browser/shims/crypto.mjs +103 -0
- package/browser/shims/fs.mjs +159 -0
- package/browser/shims/os.mjs +17 -0
- package/browser/shims/path.mjs +54 -0
- package/browser/shims/process.mjs +44 -0
- package/browser/shims/readline.mjs +11 -0
- package/browser/shims/url.mjs +12 -0
- package/browser/vfs-data.mjs +19 -0
- package/codecs/README.md +3 -0
- package/codecs/json.mjs +16 -2
- package/codecs/runtime/show-value.mjs +2 -2
- package/conformance/helper-reuse/case.json +8 -0
- package/conformance/helper-reuse/expected.kv +1 -0
- package/conformance/helper-reuse/input.kv +1 -0
- package/conformance/helper-reuse/program.k +2 -0
- package/conformance/identity/case.json +8 -0
- package/conformance/identity/expected.kv +1 -0
- package/conformance/identity/input.kv +1 -0
- package/conformance/identity/program.k +1 -0
- package/conformance/product-projection/case.json +8 -0
- package/conformance/product-projection/expected.kv +1 -0
- package/conformance/product-projection/input.kv +1 -0
- package/conformance/product-projection/program.k +1 -0
- package/conformance/run.mjs +149 -0
- package/conformance/variant-construction/case.json +8 -0
- package/conformance/variant-construction/expected.kv +1 -0
- package/conformance/variant-construction/input.kv +1 -0
- package/conformance/variant-construction/program.k +1 -0
- package/harness/adapters/arm64.mjs +105 -0
- package/harness/adapters/kvm.mjs +144 -0
- package/harness/adapters/llvm.mjs +118 -0
- package/harness/adapters/native.mjs +77 -0
- package/harness/adapters/wasm.mjs +169 -0
- package/harness/backend.mjs +95 -0
- package/harness/cli.mjs +130 -0
- package/harness/format.mjs +95 -0
- package/harness/index.mjs +25 -0
- package/harness/persistent.mjs +121 -0
- package/harness/registry.mjs +44 -0
- package/harness/suite.mjs +257 -0
- package/harness/suites/poly.mjs +156 -0
- package/harness/trace.mjs +50 -0
- package/harness/util.mjs +92 -0
- package/intrinsics.mjs +41 -0
- package/kir.mjs +399 -0
- package/kvm.mjs +585 -81
- package/objects/README.md +37 -3
- package/objects/compile.mjs +15 -22
- package/objects/inspect.mjs +96 -0
- package/objects/validate.mjs +415 -0
- package/package.json +51 -19
- package/repl-codecs.mjs +133 -20
- package/repl.mjs +408 -59
- package/run.mjs +2 -7
- package/scripts/benchmark.mjs +406 -22
- package/scripts/build-repl-html.mjs +1784 -0
- package/scripts/perf-ieee.mjs +586 -0
- package/scripts/perf-int.mjs +531 -0
- package/scripts/perf-poly.mjs +945 -0
- package/scripts/render-benchmark.mjs +12 -8
- package/scripts/run-tests.mjs +6 -0
- package/tests/integration.sh +19 -2
- package/tests/test-arithmetics.mjs +54 -0
- package/tests/test-ieee-arithmetic.mjs +6 -2
- package/tests/test-kir.mjs +85 -0
- package/tests/test-kvm-polymorphic.mjs +278 -0
- package/tests/test-kvm.mjs +25 -6
- package/tests/test-poly.mjs +129 -0
- package/tests/test-repl-html.mjs +303 -0
- package/tests/test-repl.mjs +175 -1
- package/tests/test-validate-object.mjs +40 -0
- package/a.klib +0 -1
- package/a.kvm +0 -142676
- package/a.wasm +0 -0
- package/benchmark-results.html +0 -532
- package/benchmark-results.json +0 -480
- package/k-vscode/.vscode/launch.json +0 -14
- package/k-vscode/README.md +0 -75
- package/k-vscode/extension.js +0 -273
- package/k-vscode/language-configuration.json +0 -42
- package/k-vscode/package.json +0 -79
- package/k-vscode/snippets/k.json +0 -92
- package/k-vscode/syntaxes/k.tmLanguage.json +0 -599
- package/k-vscode/test/background-ranges.test.js +0 -50
- package/k-vscode/themes/k-contrast-color-theme.json +0 -104
- package/scripts/git-hooks/pre-commit +0 -10
package/repl.mjs
CHANGED
|
@@ -8,9 +8,17 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
import { argv, exit, stdin, stdout } from "node:process";
|
|
9
9
|
|
|
10
10
|
import { annotate, parse } from "./index.mjs";
|
|
11
|
-
import
|
|
11
|
+
import { constrainWithPattern } from "./run.mjs";
|
|
12
|
+
import { compileWasmArtifactFromObject, instantiateWasmArtifact } from "./backends/wasm/src/wasm.mjs";
|
|
13
|
+
import { exportPatternGraph } from "./codecs/runtime/codec.mjs";
|
|
14
|
+
import { patternToPropertyList } from "./codecs/runtime/pattern-json.mjs";
|
|
12
15
|
import codes from "./codes.mjs";
|
|
13
|
-
import { Value } from "./Value.mjs";
|
|
16
|
+
import { Value, isProduct, isVariant } from "./Value.mjs";
|
|
17
|
+
if (typeof globalThis !== "undefined") {
|
|
18
|
+
globalThis.Value = Value;
|
|
19
|
+
globalThis.isProduct = isProduct;
|
|
20
|
+
globalThis.isVariant = isVariant;
|
|
21
|
+
}
|
|
14
22
|
import { patterns2filters, prettyCode, prettyRel } from "./pretty.mjs";
|
|
15
23
|
import {
|
|
16
24
|
compileObject,
|
|
@@ -28,8 +36,13 @@ import {
|
|
|
28
36
|
codeHashToPattern,
|
|
29
37
|
listCodecs,
|
|
30
38
|
loadCodecModule,
|
|
39
|
+
normalizeCodecModule,
|
|
40
|
+
registerCodec,
|
|
31
41
|
resolveCodec,
|
|
32
|
-
|
|
42
|
+
unregisterCodec,
|
|
43
|
+
BUILTIN_CODECS,
|
|
44
|
+
closedPatternToCodeHash,
|
|
45
|
+
UNIVERSAL_CODE,
|
|
33
46
|
valueForCode
|
|
34
47
|
} from "./repl-codecs.mjs";
|
|
35
48
|
|
|
@@ -38,13 +51,22 @@ const TYPE_DEF_RE = /^\s*\$\s*([a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]*)\s*=/;
|
|
|
38
51
|
const REL_DEF_RE = /^\s*([a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]*)\s*=/;
|
|
39
52
|
const COMMAND_NAMES = [
|
|
40
53
|
"help", "type", "code", "rel", "def", "run", "eval", "t", "d", "C",
|
|
41
|
-
"codes", "rels", "val", "codec", "input", "reset", "klib", "ko", "load",
|
|
54
|
+
"codes", "codecs", "rels", "val", "codec", "input", "reset", "klib", "ko", "load",
|
|
55
|
+
"timing", "time",
|
|
42
56
|
"quit", "exit"
|
|
43
57
|
];
|
|
44
|
-
const CODEC_COMMAND_NAMES = ["load", "list"];
|
|
58
|
+
const CODEC_COMMAND_NAMES = ["load", "unload", "list", "define"];
|
|
45
59
|
const PATH_COMMANDS = new Set(["klib", "ko", "load"]);
|
|
60
|
+
const INPUT_TYPE_NAME = "__input__";
|
|
46
61
|
const initialCodes = codes.dump();
|
|
47
62
|
|
|
63
|
+
function formatDuration(ms) {
|
|
64
|
+
if (ms < 1000) {
|
|
65
|
+
return `${ms < 10 ? ms.toFixed(1) : Math.round(ms)}ms`;
|
|
66
|
+
}
|
|
67
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
68
|
+
}
|
|
69
|
+
|
|
48
70
|
function cloneJSON(value) {
|
|
49
71
|
return JSON.parse(JSON.stringify(value));
|
|
50
72
|
}
|
|
@@ -61,10 +83,13 @@ function createState() {
|
|
|
61
83
|
relAliases: {},
|
|
62
84
|
typeAliases: {},
|
|
63
85
|
codecs: {},
|
|
86
|
+
loadedFiles: new Set(),
|
|
64
87
|
pendingInput: null,
|
|
65
88
|
meta: {},
|
|
66
89
|
value: emptyValue(),
|
|
67
|
-
lastMain: null
|
|
90
|
+
lastMain: null,
|
|
91
|
+
lastTiming: null,
|
|
92
|
+
showTiming: false
|
|
68
93
|
};
|
|
69
94
|
}
|
|
70
95
|
|
|
@@ -209,6 +234,16 @@ function mergeLibrary(state, lib, source = "<load>", options = {}) {
|
|
|
209
234
|
}
|
|
210
235
|
}
|
|
211
236
|
recoverAliasesFromMeta(state, lib);
|
|
237
|
+
if (state.typeAliases.string && !state.typeAliases.utf8) {
|
|
238
|
+
state.typeAliases.utf8 = state.typeAliases.string;
|
|
239
|
+
} else if (state.typeAliases.utf8 && !state.typeAliases.string) {
|
|
240
|
+
state.typeAliases.string = state.typeAliases.utf8;
|
|
241
|
+
}
|
|
242
|
+
if (state.typeAliases.float64 && !state.typeAliases.ieee) {
|
|
243
|
+
state.typeAliases.ieee = state.typeAliases.float64;
|
|
244
|
+
} else if (state.typeAliases.ieee && !state.typeAliases.float64) {
|
|
245
|
+
state.typeAliases.float64 = state.typeAliases.ieee;
|
|
246
|
+
}
|
|
212
247
|
}
|
|
213
248
|
restoreCodes(state);
|
|
214
249
|
}
|
|
@@ -323,14 +358,19 @@ function printValue(value, state = null) {
|
|
|
323
358
|
const lines = [valueWithEnvelopeToK(value)];
|
|
324
359
|
if (!state || value === undefined) return lines[0];
|
|
325
360
|
|
|
326
|
-
const codeHash =
|
|
361
|
+
const codeHash = closedPatternToCodeHash(value.pattern);
|
|
327
362
|
if (!codeHash) return lines[0];
|
|
328
363
|
|
|
329
|
-
|
|
364
|
+
const codecs = [
|
|
365
|
+
...(state.codecs?.[codeHash] || []),
|
|
366
|
+
...(state.codecs?.[UNIVERSAL_CODE] || [])
|
|
367
|
+
];
|
|
368
|
+
for (const codec of codecs) {
|
|
330
369
|
if (typeof codec.print !== "function") continue;
|
|
331
370
|
try {
|
|
332
371
|
lines.push(`${codec.name}: ${formatCodecOutput(codec.print(value, { codeHash, state }))}`);
|
|
333
372
|
} catch (error) {
|
|
373
|
+
if (codec.universal) continue;
|
|
334
374
|
lines.push(`${codec.name}: <error: ${error.message || String(error)}>`);
|
|
335
375
|
}
|
|
336
376
|
}
|
|
@@ -590,15 +630,33 @@ function codecLoadPathCompletionStart(argStart, arg) {
|
|
|
590
630
|
return argStart + leading.length + "load".length + 1 + restLeadingWhitespace + completionTokenStart(rest.trimStart());
|
|
591
631
|
}
|
|
592
632
|
|
|
593
|
-
function completeCodecCommand(line, argStart, arg) {
|
|
633
|
+
function completeCodecCommand(line, argStart, arg, state) {
|
|
594
634
|
const trimmed = arg.trimStart();
|
|
595
635
|
if (trimmed === "" || !/\s/.test(trimmed)) {
|
|
596
636
|
return completeCommandWord(line, argStart, arg, CODEC_COMMAND_NAMES);
|
|
597
637
|
}
|
|
598
638
|
|
|
639
|
+
const unloadMatch = arg.match(/^(\s*)unload(?:\s+(.*))?$/);
|
|
640
|
+
if (unloadMatch) {
|
|
641
|
+
const [, leading, partial = ""] = unloadMatch;
|
|
642
|
+
const prefix = line.slice(0, argStart + leading.length + "unload".length + 1);
|
|
643
|
+
const names = state ? codecNames(state) : [];
|
|
644
|
+
const matches = names
|
|
645
|
+
.filter((name) => name.startsWith(partial.trim()))
|
|
646
|
+
.map((name) => `${prefix}${name}`);
|
|
647
|
+
return [matches, line];
|
|
648
|
+
}
|
|
649
|
+
|
|
599
650
|
const tokenStart = codecLoadPathCompletionStart(argStart, arg);
|
|
600
651
|
if (tokenStart == null) return [[], line];
|
|
601
|
-
|
|
652
|
+
const [pathMatches] = completePath(line, tokenStart);
|
|
653
|
+
const match = arg.match(/^(\s*)load(?:\s+(.*))?$/);
|
|
654
|
+
const partial = match && match[2] != null ? match[2].trim() : "";
|
|
655
|
+
const prefix = line.slice(0, tokenStart);
|
|
656
|
+
const builtinMatches = ["int", "utf8", "json", "ieee"]
|
|
657
|
+
.filter((name) => name.startsWith(partial))
|
|
658
|
+
.map((name) => `${prefix}${name}`);
|
|
659
|
+
return [[...builtinMatches, ...pathMatches], line];
|
|
602
660
|
}
|
|
603
661
|
|
|
604
662
|
function resolveTypeHash(state, rawName) {
|
|
@@ -609,6 +667,40 @@ function resolveTypeHash(state, rawName) {
|
|
|
609
667
|
return hash;
|
|
610
668
|
}
|
|
611
669
|
|
|
670
|
+
function isSimpleTypeReference(rawType) {
|
|
671
|
+
return /^\$?[a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]*$/.test(rawType.trim());
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
function resolveTypeExpressionHash(state, rawType) {
|
|
675
|
+
restoreCodes(state);
|
|
676
|
+
const preamble = aliasPreamble(state, INPUT_TYPE_NAME);
|
|
677
|
+
const source = [
|
|
678
|
+
preamble,
|
|
679
|
+
ensureSemicolon(`$ ${INPUT_TYPE_NAME} = ${rawType.trim()}`),
|
|
680
|
+
"()"
|
|
681
|
+
].filter(Boolean).join("\n");
|
|
682
|
+
|
|
683
|
+
try {
|
|
684
|
+
const annotated = annotate(source, { libraries: [stateLibrary(state)] });
|
|
685
|
+
const hash = annotated.representatives[INPUT_TYPE_NAME];
|
|
686
|
+
if (!hash) throw new Error(":input type expression did not produce a code hash");
|
|
687
|
+
state.codes = codes.dump();
|
|
688
|
+
return hash;
|
|
689
|
+
} catch (error) {
|
|
690
|
+
restoreCodes(state);
|
|
691
|
+
throw remapError(error, preambleLineCount(preamble));
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
function resolveInputTypeHash(state, rawType) {
|
|
696
|
+
try {
|
|
697
|
+
return resolveTypeHash(state, rawType);
|
|
698
|
+
} catch (error) {
|
|
699
|
+
if (isSimpleTypeReference(rawType)) throw error;
|
|
700
|
+
}
|
|
701
|
+
return resolveTypeExpressionHash(state, rawType);
|
|
702
|
+
}
|
|
703
|
+
|
|
612
704
|
function completeInputCommand(line, state, argStart, arg) {
|
|
613
705
|
const match = arg.match(/^(\s*)(\S+)?(\s+)?(\S*)?$/);
|
|
614
706
|
if (!match) return [[], line];
|
|
@@ -648,8 +740,8 @@ function completeCommandArgument(line, state) {
|
|
|
648
740
|
const argStart = 1 + firstSpace + 1;
|
|
649
741
|
const arg = line.slice(argStart);
|
|
650
742
|
|
|
651
|
-
if (command === "codec") {
|
|
652
|
-
return completeCodecCommand(line, argStart, arg);
|
|
743
|
+
if (command === "codec" || command === "codecs") {
|
|
744
|
+
return completeCodecCommand(line, argStart, arg, state);
|
|
653
745
|
}
|
|
654
746
|
|
|
655
747
|
if (command === "input") {
|
|
@@ -725,6 +817,102 @@ function parseLoadArgs(arg, usagePrefix = ":") {
|
|
|
725
817
|
return { path: arg.trim(), loadAliases: true };
|
|
726
818
|
}
|
|
727
819
|
|
|
820
|
+
const CODEC_FILES = {
|
|
821
|
+
int: "arithmetics.k",
|
|
822
|
+
utf8: "core.k",
|
|
823
|
+
json: "core.k",
|
|
824
|
+
ieee: "ieee.k",
|
|
825
|
+
unit: "core.k"
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
function normalizeFilePath(p) {
|
|
829
|
+
return p.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
function resolveKFilePath(filePath) {
|
|
833
|
+
try {
|
|
834
|
+
if (fs.existsSync(filePath)) return filePath;
|
|
835
|
+
} catch {}
|
|
836
|
+
try {
|
|
837
|
+
const fromRepo = path.resolve(path.dirname(fileURLToPath(import.meta.url)), filePath);
|
|
838
|
+
if (fs.existsSync(fromRepo)) return fromRepo;
|
|
839
|
+
} catch {}
|
|
840
|
+
const withEx = filePath.startsWith("Examples/") ? filePath : `Examples/${filePath}`;
|
|
841
|
+
try {
|
|
842
|
+
if (fs.existsSync(withEx)) return withEx;
|
|
843
|
+
} catch {}
|
|
844
|
+
try {
|
|
845
|
+
const fromRepoEx = path.resolve(path.dirname(fileURLToPath(import.meta.url)), withEx);
|
|
846
|
+
if (fs.existsSync(fromRepoEx)) return fromRepoEx;
|
|
847
|
+
} catch {}
|
|
848
|
+
const strippedEx = filePath.startsWith("Examples/") ? filePath.slice("Examples/".length) : filePath;
|
|
849
|
+
try {
|
|
850
|
+
if (fs.existsSync(strippedEx)) return strippedEx;
|
|
851
|
+
} catch {}
|
|
852
|
+
try {
|
|
853
|
+
const fromRepoStripped = path.resolve(path.dirname(fileURLToPath(import.meta.url)), strippedEx);
|
|
854
|
+
if (fs.existsSync(fromRepoStripped)) return fromRepoStripped;
|
|
855
|
+
} catch {}
|
|
856
|
+
return filePath;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
function loadSourceOrKlib(state, targetPath, options = {}) {
|
|
860
|
+
const loadAliases = options.loadAliases ?? true;
|
|
861
|
+
const normKey = normalizeFilePath(targetPath);
|
|
862
|
+
if (!state.loadedFiles) state.loadedFiles = new Set();
|
|
863
|
+
|
|
864
|
+
// If loading poly.k, auto-load arithmetics.k first if not already loaded
|
|
865
|
+
if (normKey === "Examples/poly.k" || normKey.endsWith("/poly.k") || normKey === "poly.k") {
|
|
866
|
+
const arithKey = "arithmetics.k";
|
|
867
|
+
const alreadyHasArith = Array.from(state.loadedFiles).some(f => path.basename(f) === "arithmetics.k");
|
|
868
|
+
if (!alreadyHasArith) {
|
|
869
|
+
loadSourceOrKlib(state, arithKey, { loadAliases });
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
const loadPath = resolveKFilePath(targetPath);
|
|
874
|
+
if (loadPath.endsWith(".klib")) {
|
|
875
|
+
const lib = loadLibrary(decodeLibrary(fs.readFileSync(loadPath)));
|
|
876
|
+
mergeLibrary(state, lib, targetPath, { loadAliases });
|
|
877
|
+
} else {
|
|
878
|
+
restoreCodes(state);
|
|
879
|
+
const source = fs.readFileSync(loadPath, "utf8");
|
|
880
|
+
const preamble = aliasPreamble(state);
|
|
881
|
+
const fullSource = [preamble, source].filter(Boolean).join("\n");
|
|
882
|
+
const compileOptions = {
|
|
883
|
+
source: targetPath,
|
|
884
|
+
libraries: [stateLibrary(state)]
|
|
885
|
+
};
|
|
886
|
+
try {
|
|
887
|
+
const lib = compileWithOptionalIdentity(fullSource, compileOptions);
|
|
888
|
+
const { relAlias, meta } = libraryOriginsFromSource(source, fullSource, lib, compileOptions);
|
|
889
|
+
mergeLibrary(state, { ...lib, relAlias, meta }, targetPath, { loadAliases });
|
|
890
|
+
} catch (error) {
|
|
891
|
+
throw remapError(error, preambleLineCount(preamble));
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
state.loadedFiles.add(normKey);
|
|
895
|
+
return targetPath;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
function ensureCodecDependencies(state, codecTarget) {
|
|
899
|
+
const norm = normalizeFilePath(codecTarget).toLowerCase();
|
|
900
|
+
const base = path.basename(norm, path.extname(norm));
|
|
901
|
+
const depFile = CODEC_FILES[base] || CODEC_FILES[norm];
|
|
902
|
+
if (!depFile) return null;
|
|
903
|
+
if (!state.loadedFiles) state.loadedFiles = new Set();
|
|
904
|
+
const depNormKey = normalizeFilePath(depFile);
|
|
905
|
+
const baseName = path.basename(depNormKey);
|
|
906
|
+
const alreadyLoaded = state.loadedFiles.has(depNormKey) ||
|
|
907
|
+
state.loadedFiles.has(`Examples/${depNormKey}`) ||
|
|
908
|
+
Array.from(state.loadedFiles).some(f => path.basename(f) === baseName);
|
|
909
|
+
if (!alreadyLoaded) {
|
|
910
|
+
loadSourceOrKlib(state, depFile);
|
|
911
|
+
return depFile;
|
|
912
|
+
}
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
|
|
728
916
|
function lineForContinuation(line) {
|
|
729
917
|
return line.replace(/\\\s*$/, "");
|
|
730
918
|
}
|
|
@@ -842,29 +1030,82 @@ async function defineRelation(input, state) {
|
|
|
842
1030
|
return [`${name} = ${hash}`];
|
|
843
1031
|
}
|
|
844
1032
|
|
|
1033
|
+
async function executeExpressionWithWasm(annotated, state, lineOffset = 0) {
|
|
1034
|
+
const mainRel = annotated.rels.__main__;
|
|
1035
|
+
if (!mainRel) return { result: undefined, wasmCompileMs: 0, executeMs: 0 };
|
|
1036
|
+
|
|
1037
|
+
let inputValue = state.value ?? emptyValue();
|
|
1038
|
+
if (mainRel.typePatternGraph && mainRel.def.patterns) {
|
|
1039
|
+
const graph = mainRel.typePatternGraph;
|
|
1040
|
+
const nodeId = graph.find(mainRel.def.patterns[0]);
|
|
1041
|
+
const inputPattern = patternToPropertyList(exportPatternGraph(graph, nodeId));
|
|
1042
|
+
inputValue = constrainWithPattern(inputValue, inputPattern, mainRel.def);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
const obj = {
|
|
1046
|
+
format: "k-object",
|
|
1047
|
+
codes: { ...state.codes, ...codes.dump() },
|
|
1048
|
+
rels: annotated.rels,
|
|
1049
|
+
relAlias: annotated.relAlias,
|
|
1050
|
+
compileStats: annotated.compileStats,
|
|
1051
|
+
main: "__main__"
|
|
1052
|
+
};
|
|
1053
|
+
|
|
1054
|
+
const wasmCompileStart = performance.now();
|
|
1055
|
+
const wasmBytes = await compileWasmArtifactFromObject(obj, {
|
|
1056
|
+
inputEnvelopePattern: inputValue?.pattern
|
|
1057
|
+
});
|
|
1058
|
+
const runner = await instantiateWasmArtifact(wasmBytes);
|
|
1059
|
+
const wasmCompileMs = performance.now() - wasmCompileStart;
|
|
1060
|
+
|
|
1061
|
+
const executeStart = performance.now();
|
|
1062
|
+
const result = runner.executeValue(inputValue);
|
|
1063
|
+
const executeMs = performance.now() - executeStart;
|
|
1064
|
+
|
|
1065
|
+
return { result, wasmCompileMs, executeMs };
|
|
1066
|
+
}
|
|
1067
|
+
|
|
845
1068
|
async function runExpression(input, state) {
|
|
846
1069
|
const expression = input.trim();
|
|
847
1070
|
if (!expression) throw new Error(":run requires an expression");
|
|
848
1071
|
|
|
849
1072
|
restoreCodes(state);
|
|
850
1073
|
const preamble = aliasPreamble(state);
|
|
1074
|
+
const lineOffset = preambleLineCount(preamble);
|
|
851
1075
|
const source = [preamble, expression].filter(Boolean).join("\n");
|
|
1076
|
+
const compileStart = performance.now();
|
|
852
1077
|
let annotated;
|
|
853
1078
|
try {
|
|
854
1079
|
annotated = annotate(source, { libraries: [stateLibrary(state)] });
|
|
855
1080
|
} catch (error) {
|
|
856
|
-
throw remapError(error,
|
|
1081
|
+
throw remapError(error, lineOffset);
|
|
857
1082
|
}
|
|
858
|
-
const
|
|
859
|
-
|
|
860
|
-
let
|
|
1083
|
+
const snippetCompileMs = performance.now() - compileStart;
|
|
1084
|
+
|
|
1085
|
+
let execRes;
|
|
861
1086
|
try {
|
|
862
|
-
|
|
1087
|
+
execRes = await executeExpressionWithWasm(annotated, state, lineOffset);
|
|
863
1088
|
} catch (error) {
|
|
864
|
-
throw remapError(error,
|
|
1089
|
+
throw remapError(error, lineOffset);
|
|
865
1090
|
}
|
|
1091
|
+
state.codes = codes.dump();
|
|
866
1092
|
restoreCodes(state);
|
|
867
|
-
|
|
1093
|
+
|
|
1094
|
+
const compileMs = snippetCompileMs + execRes.wasmCompileMs;
|
|
1095
|
+
const executeMs = execRes.executeMs;
|
|
1096
|
+
state.lastTiming = {
|
|
1097
|
+
compileMs,
|
|
1098
|
+
executeMs,
|
|
1099
|
+
totalMs: compileMs + executeMs,
|
|
1100
|
+
snippetCompileMs,
|
|
1101
|
+
wasmCompileMs: execRes.wasmCompileMs
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
const committed = commitResult(state, execRes.result, expression);
|
|
1105
|
+
if (state.showTiming) {
|
|
1106
|
+
committed.push(`/* comp: ${formatDuration(compileMs)}, exec: ${formatDuration(executeMs)} */`);
|
|
1107
|
+
}
|
|
1108
|
+
return committed;
|
|
868
1109
|
}
|
|
869
1110
|
|
|
870
1111
|
async function runSnippet(input, state, options = {}) {
|
|
@@ -873,53 +1114,133 @@ async function runSnippet(input, state, options = {}) {
|
|
|
873
1114
|
|
|
874
1115
|
const explicitTerminated = options.explicitTerminated ?? explicitSnippetTerminated(input);
|
|
875
1116
|
const analysis = analyzeAcceptedSnippet(snippet, explicitTerminated);
|
|
1117
|
+
const compileStart = performance.now();
|
|
876
1118
|
const { annotated, lib, lineOffset } = compileSnippetArtifacts(snippet, state);
|
|
1119
|
+
const snippetCompileMs = performance.now() - compileStart;
|
|
877
1120
|
mergeLibrary(state, lib, "<repl>");
|
|
878
1121
|
|
|
879
1122
|
if (analysis.kind === "definitionsOnly") {
|
|
880
1123
|
restoreCodes(state);
|
|
1124
|
+
state.lastTiming = {
|
|
1125
|
+
compileMs: snippetCompileMs,
|
|
1126
|
+
executeMs: 0,
|
|
1127
|
+
totalMs: snippetCompileMs,
|
|
1128
|
+
snippetCompileMs,
|
|
1129
|
+
wasmCompileMs: 0
|
|
1130
|
+
};
|
|
1131
|
+
if (state.showTiming) {
|
|
1132
|
+
return [`/* comp: ${formatDuration(snippetCompileMs)} */`];
|
|
1133
|
+
}
|
|
881
1134
|
return [];
|
|
882
1135
|
}
|
|
883
1136
|
|
|
884
|
-
|
|
885
|
-
run.defs = annotated;
|
|
886
|
-
let result;
|
|
1137
|
+
let execRes;
|
|
887
1138
|
try {
|
|
888
|
-
|
|
1139
|
+
execRes = await executeExpressionWithWasm(annotated, state, lineOffset);
|
|
889
1140
|
} catch (error) {
|
|
890
1141
|
throw remapError(error, lineOffset);
|
|
891
1142
|
}
|
|
1143
|
+
state.codes = codes.dump();
|
|
892
1144
|
restoreCodes(state);
|
|
893
|
-
|
|
1145
|
+
|
|
1146
|
+
const compileMs = snippetCompileMs + execRes.wasmCompileMs;
|
|
1147
|
+
const executeMs = execRes.executeMs;
|
|
1148
|
+
state.lastTiming = {
|
|
1149
|
+
compileMs,
|
|
1150
|
+
executeMs,
|
|
1151
|
+
totalMs: compileMs + executeMs,
|
|
1152
|
+
snippetCompileMs,
|
|
1153
|
+
wasmCompileMs: execRes.wasmCompileMs
|
|
1154
|
+
};
|
|
1155
|
+
|
|
1156
|
+
const committed = commitResult(state, execRes.result, snippet);
|
|
1157
|
+
if (state.showTiming) {
|
|
1158
|
+
committed.push(`/* comp: ${formatDuration(compileMs)}, exec: ${formatDuration(executeMs)} */`);
|
|
1159
|
+
}
|
|
1160
|
+
return committed;
|
|
894
1161
|
}
|
|
895
1162
|
|
|
896
1163
|
async function loadCodec(input, state) {
|
|
897
|
-
const
|
|
1164
|
+
const trimmed = input.trim();
|
|
1165
|
+
if (!trimmed || trimmed === "list") {
|
|
1166
|
+
return [listCodecs(state)];
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
const [subcommand, ...rest] = trimmed.split(/\s+/);
|
|
898
1170
|
switch (subcommand) {
|
|
899
1171
|
case "load": {
|
|
900
1172
|
const filePath = rest.join(" ");
|
|
901
|
-
if (!filePath) throw new Error(":codec load requires a file path");
|
|
1173
|
+
if (!filePath) throw new Error(":codec load requires a file path or codec name");
|
|
1174
|
+
const autoLoaded = ensureCodecDependencies(state, filePath);
|
|
902
1175
|
const registered = await loadCodecModule(state, expandHome(filePath));
|
|
903
|
-
return registered.map(({ name, codeHash }) =>
|
|
1176
|
+
return registered.map(({ name, codeHash }) =>
|
|
1177
|
+
`loaded codec ${name} for ${codeHash === UNIVERSAL_CODE ? "all types" : codeHash}${autoLoaded ? ` (auto-loaded ${autoLoaded})` : ""}`
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
case "unload": {
|
|
1181
|
+
const codecName = rest.join(" ").trim();
|
|
1182
|
+
if (!codecName) throw new Error(":codec unload requires a codec name");
|
|
1183
|
+
const removed = unregisterCodec(state, codecName);
|
|
1184
|
+
if (removed === 0) throw new Error(`Codec '${codecName}' is not loaded`);
|
|
1185
|
+
return [`unloaded codec ${codecName}`];
|
|
1186
|
+
}
|
|
1187
|
+
case "define": {
|
|
1188
|
+
const match = rest.join(" ").match(/^([a-zA-Z0-9_+-]+)\s+(\S+)\s+([\s\S]+)$/);
|
|
1189
|
+
if (!match) {
|
|
1190
|
+
throw new Error(":codec define requires: name type { parse: ..., print: ... }");
|
|
1191
|
+
}
|
|
1192
|
+
const [, name, rawType, bodyStr] = match;
|
|
1193
|
+
const fn = new Function("Value", "isProduct", "isVariant", "state", `return (${bodyStr});`);
|
|
1194
|
+
const obj = fn(Value, isProduct, isVariant, state);
|
|
1195
|
+
const codeHash = rawType === "*" ? UNIVERSAL_CODE : resolveInputTypeHash(state, rawType);
|
|
1196
|
+
const codec = normalizeCodecModule({
|
|
1197
|
+
name,
|
|
1198
|
+
codes: [codeHash],
|
|
1199
|
+
universal: codeHash === UNIVERSAL_CODE,
|
|
1200
|
+
parse: obj.parse,
|
|
1201
|
+
print: obj.print
|
|
1202
|
+
}, name);
|
|
1203
|
+
const registered = registerCodec(state, codec, "<inline>");
|
|
1204
|
+
return registered.map(({ name, codeHash }) =>
|
|
1205
|
+
`defined codec ${name} for ${codeHash === UNIVERSAL_CODE ? "all types" : codeHash}`
|
|
1206
|
+
);
|
|
904
1207
|
}
|
|
905
1208
|
case "list":
|
|
906
1209
|
if (rest.length > 0) throw new Error(":codec list does not accept arguments");
|
|
907
1210
|
return [listCodecs(state)];
|
|
908
|
-
default:
|
|
909
|
-
|
|
1211
|
+
default: {
|
|
1212
|
+
const autoLoaded = ensureCodecDependencies(state, trimmed);
|
|
1213
|
+
const registered = await loadCodecModule(state, expandHome(trimmed));
|
|
1214
|
+
return registered.map(({ name, codeHash }) =>
|
|
1215
|
+
`loaded codec ${name} for ${codeHash === UNIVERSAL_CODE ? "all types" : codeHash}${autoLoaded ? ` (auto-loaded ${autoLoaded})` : ""}`
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
910
1218
|
}
|
|
911
1219
|
}
|
|
912
1220
|
|
|
913
1221
|
async function requestCodecInput(input, state) {
|
|
914
|
-
const
|
|
915
|
-
if (
|
|
916
|
-
throw new Error(":input requires a
|
|
1222
|
+
const trimmed = input.trim();
|
|
1223
|
+
if (!trimmed) {
|
|
1224
|
+
throw new Error(":input requires a type and optional codec name");
|
|
917
1225
|
}
|
|
918
1226
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1227
|
+
let codeHash;
|
|
1228
|
+
let codecName = null;
|
|
1229
|
+
try {
|
|
1230
|
+
codeHash = resolveInputTypeHash(state, trimmed);
|
|
1231
|
+
} catch (wholeError) {
|
|
1232
|
+
const split = trimmed.match(/^(.*\S)\s+([a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]*)$/);
|
|
1233
|
+
if (!split) throw wholeError;
|
|
1234
|
+
try {
|
|
1235
|
+
codeHash = resolveInputTypeHash(state, split[1]);
|
|
1236
|
+
codecName = split[2];
|
|
1237
|
+
} catch (typeError) {
|
|
1238
|
+
throw typeError;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
const codec = resolveCodec(state, codeHash, codecName, "parse");
|
|
1243
|
+
state.pendingInput = { codeHash, codecName, promptName: codec.name };
|
|
923
1244
|
return [`input ${codeHash}${codecName ? ` using ${codecName}` : ""}: enter value text`];
|
|
924
1245
|
}
|
|
925
1246
|
|
|
@@ -942,6 +1263,7 @@ async function consumeCodecInput(input, state) {
|
|
|
942
1263
|
}
|
|
943
1264
|
|
|
944
1265
|
async function evaluateInput(input, state) {
|
|
1266
|
+
state.lastTiming = null;
|
|
945
1267
|
if (state.pendingInput) {
|
|
946
1268
|
return consumeCodecInput(input, state);
|
|
947
1269
|
}
|
|
@@ -972,6 +1294,29 @@ async function evaluateCommand(line, state) {
|
|
|
972
1294
|
exit(0);
|
|
973
1295
|
case "help":
|
|
974
1296
|
return [helpText()];
|
|
1297
|
+
case "timing": {
|
|
1298
|
+
const trimmed = arg.trim().toLowerCase();
|
|
1299
|
+
if (trimmed === "on" || trimmed === "true" || trimmed === "1") {
|
|
1300
|
+
state.showTiming = true;
|
|
1301
|
+
} else if (trimmed === "off" || trimmed === "false" || trimmed === "0") {
|
|
1302
|
+
state.showTiming = false;
|
|
1303
|
+
} else if (!trimmed) {
|
|
1304
|
+
state.showTiming = !state.showTiming;
|
|
1305
|
+
} else {
|
|
1306
|
+
throw new Error(":timing accepts 'on', 'off', or no arguments to toggle");
|
|
1307
|
+
}
|
|
1308
|
+
return [`timing reporting ${state.showTiming ? "enabled" : "disabled"}`];
|
|
1309
|
+
}
|
|
1310
|
+
case "time": {
|
|
1311
|
+
if (!arg) throw new Error(":time requires an expression");
|
|
1312
|
+
const wasTiming = state.showTiming;
|
|
1313
|
+
state.showTiming = true;
|
|
1314
|
+
try {
|
|
1315
|
+
return await evaluateInput(arg, state);
|
|
1316
|
+
} finally {
|
|
1317
|
+
state.showTiming = wasTiming;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
975
1320
|
case "type": {
|
|
976
1321
|
if (!arg) throw new Error(":type requires a name or definition");
|
|
977
1322
|
if (arg.includes("=")) {
|
|
@@ -999,6 +1344,7 @@ async function evaluateCommand(line, state) {
|
|
|
999
1344
|
JSON.stringify(state.value, null, 2)
|
|
1000
1345
|
];
|
|
1001
1346
|
case "codec":
|
|
1347
|
+
case "codecs":
|
|
1002
1348
|
return loadCodec(arg, state);
|
|
1003
1349
|
case "input":
|
|
1004
1350
|
return requestCodecInput(arg, state);
|
|
@@ -1025,26 +1371,7 @@ async function evaluateCommand(line, state) {
|
|
|
1025
1371
|
}
|
|
1026
1372
|
case "load": {
|
|
1027
1373
|
const { path: loadPath, loadAliases } = parseLoadArgs(arg, usagePrefix);
|
|
1028
|
-
|
|
1029
|
-
const lib = loadLibrary(decodeLibrary(fs.readFileSync(loadPath)));
|
|
1030
|
-
mergeLibrary(state, lib, loadPath, { loadAliases });
|
|
1031
|
-
} else {
|
|
1032
|
-
restoreCodes(state);
|
|
1033
|
-
const source = fs.readFileSync(loadPath, "utf8");
|
|
1034
|
-
const preamble = aliasPreamble(state);
|
|
1035
|
-
const fullSource = [preamble, source].filter(Boolean).join("\n");
|
|
1036
|
-
const options = {
|
|
1037
|
-
source: loadPath,
|
|
1038
|
-
libraries: [stateLibrary(state)]
|
|
1039
|
-
};
|
|
1040
|
-
try {
|
|
1041
|
-
const lib = compileWithOptionalIdentity(fullSource, options);
|
|
1042
|
-
const { relAlias, meta } = libraryOriginsFromSource(source, fullSource, lib, options);
|
|
1043
|
-
mergeLibrary(state, { ...lib, relAlias, meta }, loadPath, { loadAliases });
|
|
1044
|
-
} catch (error) {
|
|
1045
|
-
throw remapError(error, preambleLineCount(preamble));
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1374
|
+
loadSourceOrKlib(state, loadPath, { loadAliases });
|
|
1048
1375
|
return [`loaded ${loadPath}`];
|
|
1049
1376
|
}
|
|
1050
1377
|
case "t": {
|
|
@@ -1075,13 +1402,17 @@ function helpText() {
|
|
|
1075
1402
|
":type name = <...> define a type",
|
|
1076
1403
|
":rel name = expr define a relation",
|
|
1077
1404
|
":run expr run an expression on the current value",
|
|
1405
|
+
":time expr run an expression and report compilation/execution time",
|
|
1406
|
+
":timing [on|off] toggle timing reporting after every evaluation",
|
|
1078
1407
|
":t name show relation type",
|
|
1079
1408
|
":d name show relation definition",
|
|
1080
1409
|
":type name show type definition",
|
|
1081
1410
|
":codes list type aliases",
|
|
1082
1411
|
":rels list relation aliases",
|
|
1083
|
-
":codec load file load a REPL codec module",
|
|
1084
|
-
":codec
|
|
1412
|
+
":codec load file load a REPL codec module (or built-in: int, utf8, json, ieee)",
|
|
1413
|
+
":codec define n t b define a custom codec: name type { parse: ..., print: ... }",
|
|
1414
|
+
":codec unload name unload a registered codec",
|
|
1415
|
+
":codec list list loaded codecs (or simply :codecs)",
|
|
1085
1416
|
":input type [codec] read next line as codec input",
|
|
1086
1417
|
":load [--no-alias] file",
|
|
1087
1418
|
" load .k source or .klib",
|
|
@@ -1097,6 +1428,11 @@ function helpText() {
|
|
|
1097
1428
|
].join("\n");
|
|
1098
1429
|
}
|
|
1099
1430
|
|
|
1431
|
+
function promptForState(state) {
|
|
1432
|
+
const promptName = state.pendingInput?.promptName;
|
|
1433
|
+
return promptName ? `${promptName}> ` : "> ";
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1100
1436
|
function cliUsage() {
|
|
1101
1437
|
console.log("Usage: k-repl");
|
|
1102
1438
|
console.log(" k-repl -h");
|
|
@@ -1151,6 +1487,7 @@ function startRepl() {
|
|
|
1151
1487
|
} catch (error) {
|
|
1152
1488
|
console.error(error.message || String(error));
|
|
1153
1489
|
}
|
|
1490
|
+
rl.setPrompt(promptForState(state));
|
|
1154
1491
|
if (!closed) rl.prompt();
|
|
1155
1492
|
return;
|
|
1156
1493
|
}
|
|
@@ -1222,7 +1559,19 @@ export {
|
|
|
1222
1559
|
isMainEntrypoint,
|
|
1223
1560
|
lineHasExplicitContinuation,
|
|
1224
1561
|
lineTerminatesSnippet,
|
|
1562
|
+
listCodecs,
|
|
1563
|
+
loadCodecModule,
|
|
1564
|
+
registerCodec,
|
|
1565
|
+
unregisterCodec,
|
|
1566
|
+
resolveCodec,
|
|
1567
|
+
codeHashToPattern,
|
|
1568
|
+
BUILTIN_CODECS,
|
|
1225
1569
|
printValue,
|
|
1570
|
+
promptForState,
|
|
1226
1571
|
propertyListToFilter,
|
|
1227
|
-
|
|
1572
|
+
savedLibrary,
|
|
1573
|
+
loadSourceOrKlib,
|
|
1574
|
+
ensureCodecDependencies,
|
|
1575
|
+
valueToK,
|
|
1576
|
+
formatDuration
|
|
1228
1577
|
};
|
package/run.mjs
CHANGED
|
@@ -2,14 +2,9 @@ import assert from "assert";
|
|
|
2
2
|
import { Value, edgeSubpattern, composePattern, withPattern, isProduct, isVariant } from "./Value.mjs"
|
|
3
3
|
import { exportPatternGraph, intersectPropertyListPatterns } from "./codecs/runtime/codec.mjs";
|
|
4
4
|
import { patternToPropertyList } from "./codecs/runtime/pattern-json.mjs";
|
|
5
|
+
import { jsIntrinsicFunctions } from "./intrinsics.mjs";
|
|
5
6
|
|
|
6
|
-
const builtin =
|
|
7
|
-
"_log!": (arg) => {
|
|
8
|
-
console.error(`_log!: ${arg}`);
|
|
9
|
-
|
|
10
|
-
return arg;
|
|
11
|
-
}
|
|
12
|
-
};
|
|
7
|
+
const builtin = jsIntrinsicFunctions;
|
|
13
8
|
|
|
14
9
|
const codes = { };
|
|
15
10
|
const staticPatternCache = new WeakMap();
|