@calcit/procs 0.29.0-alpha.27 → 0.29.0-alpha.29
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/lib/calcit-data.d.mts +1 -0
- package/lib/calcit-data.mjs +33 -1
- package/lib/calcit.procs.d.mts +3 -3
- package/lib/calcit.procs.mjs +117 -90
- package/lib/package.json +1 -1
- package/package.json +1 -1
package/lib/calcit-data.d.mts
CHANGED
|
@@ -37,6 +37,7 @@ export declare let newTag: (content: string) => CalcitTag;
|
|
|
37
37
|
export declare let castTag: (x: CalcitValue) => CalcitTag;
|
|
38
38
|
export declare var refsRegistry: Map<string, CalcitRef>;
|
|
39
39
|
export declare let hashFunction: (x: CalcitValue) => Hash;
|
|
40
|
+
export declare let format_calcit_number: (x: number) => string;
|
|
40
41
|
export declare let toString: (x: CalcitValue, escaped: boolean, disableJsDataWarning?: boolean) => string;
|
|
41
42
|
export declare let to_js_data: (x: CalcitValue, options?: CalcitValue) => any;
|
|
42
43
|
export declare let _$n_map_$o_get: (xs: CalcitValue, k: CalcitValue) => CalcitValue;
|
package/lib/calcit-data.mjs
CHANGED
|
@@ -447,6 +447,38 @@ let hashCirru = (base, x) => {
|
|
|
447
447
|
};
|
|
448
448
|
// Dirty code to change ternary-tree behavior
|
|
449
449
|
overwriteHashGenerator(hashFunction);
|
|
450
|
+
// Calcit number text, shared by `turn-string`, `str` and printing (see docs/data/number.md).
|
|
451
|
+
export let format_calcit_number = (x) => {
|
|
452
|
+
// Match native f64 Display, which expands finite exponents into decimal notation.
|
|
453
|
+
if (Object.is(x, -0)) {
|
|
454
|
+
return "-0";
|
|
455
|
+
}
|
|
456
|
+
if (x === Infinity) {
|
|
457
|
+
return "inf";
|
|
458
|
+
}
|
|
459
|
+
if (x === -Infinity) {
|
|
460
|
+
return "-inf";
|
|
461
|
+
}
|
|
462
|
+
const text = x.toString();
|
|
463
|
+
const exponentIndex = text.indexOf("e");
|
|
464
|
+
if (exponentIndex < 0) {
|
|
465
|
+
return text;
|
|
466
|
+
}
|
|
467
|
+
const mantissa = text.slice(0, exponentIndex);
|
|
468
|
+
const exponent = Number(text.slice(exponentIndex + 1));
|
|
469
|
+
const sign = mantissa.startsWith("-") ? "-" : "";
|
|
470
|
+
const unsigned = sign ? mantissa.slice(1) : mantissa;
|
|
471
|
+
const decimalPoint = unsigned.indexOf(".");
|
|
472
|
+
const decimalIndex = (decimalPoint < 0 ? unsigned.length : decimalPoint) + exponent;
|
|
473
|
+
const digits = unsigned.replace(".", "");
|
|
474
|
+
if (decimalIndex <= 0) {
|
|
475
|
+
return `${sign}0.${"0".repeat(-decimalIndex)}${digits}`;
|
|
476
|
+
}
|
|
477
|
+
if (decimalIndex >= digits.length) {
|
|
478
|
+
return `${sign}${digits}${"0".repeat(decimalIndex - digits.length)}`;
|
|
479
|
+
}
|
|
480
|
+
return `${sign}${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
|
|
481
|
+
};
|
|
450
482
|
export let toString = (x, escaped, disableJsDataWarning = false) => {
|
|
451
483
|
if (x === null) {
|
|
452
484
|
return "nil";
|
|
@@ -468,7 +500,7 @@ export let toString = (x, escaped, disableJsDataWarning = false) => {
|
|
|
468
500
|
}
|
|
469
501
|
}
|
|
470
502
|
if (typeof x === "number") {
|
|
471
|
-
return x
|
|
503
|
+
return format_calcit_number(x);
|
|
472
504
|
}
|
|
473
505
|
if (typeof x === "boolean") {
|
|
474
506
|
return x.toString();
|
package/lib/calcit.procs.d.mts
CHANGED
|
@@ -398,7 +398,7 @@ export declare let macroexpand_all: () => void;
|
|
|
398
398
|
export declare let _$n_get_calcit_running_mode: () => void;
|
|
399
399
|
export declare let _$n_get_def_doc: () => void;
|
|
400
400
|
export declare let _$n_get_def_schema: () => void;
|
|
401
|
-
export declare let _$n_ffi_response_resolve: () =>
|
|
402
|
-
export declare let _$n_ffi_response_reject: () =>
|
|
403
|
-
export declare let _$n_ffi_task_cancel: () =>
|
|
401
|
+
export declare let _$n_ffi_response_resolve: (..._args: CalcitValue[]) => never;
|
|
402
|
+
export declare let _$n_ffi_response_reject: (..._args: CalcitValue[]) => never;
|
|
403
|
+
export declare let _$n_ffi_task_cancel: (..._args: CalcitValue[]) => never;
|
|
404
404
|
export declare let raise: () => void;
|
package/lib/calcit.procs.mjs
CHANGED
|
@@ -3,7 +3,7 @@ export const calcit_version = pkg.version;
|
|
|
3
3
|
export const calcit_package_json = pkg;
|
|
4
4
|
import { parse } from "@cirru/parser.ts";
|
|
5
5
|
import { writeCirruCode } from "@cirru/writer.ts";
|
|
6
|
-
import { CalcitSymbol, CalcitTag, CalcitRecur, castTag, newTag, refsRegistry, toString, getStringName, compareTagNames, _$n__$e_, hashFunction, } from "./calcit-data.mjs";
|
|
6
|
+
import { CalcitSymbol, CalcitTag, CalcitRecur, castTag, newTag, refsRegistry, toString, format_calcit_number, getStringName, compareTagNames, _$n__$e_, hashFunction, } from "./calcit-data.mjs";
|
|
7
7
|
import { CalcitRef, atom } from "./js-ref.mjs";
|
|
8
8
|
import { CalcitStructValue } from "./js-struct-value.mjs";
|
|
9
9
|
import { CalcitImpl } from "./js-impl.mjs";
|
|
@@ -946,7 +946,9 @@ export let remove_watch = (a, k) => {
|
|
|
946
946
|
}
|
|
947
947
|
throw new Error(`remove-watch failed: listener with key \`${k.value}\` not found`);
|
|
948
948
|
};
|
|
949
|
-
|
|
949
|
+
// Same eager range limit as native `MAX_RANGE_LEN` and WASM, 2^24 elements (#1852).
|
|
950
|
+
const MAX_RANGE_LENGTH = 2 ** 24;
|
|
951
|
+
const rangeTooLarge = () => new Error(`&list:range result is too large: more than ${MAX_RANGE_LENGTH} elements`);
|
|
950
952
|
export let range = (n, m, step = 1) => {
|
|
951
953
|
const base = m == null ? 0 : n;
|
|
952
954
|
const bound = m == null ? n : m;
|
|
@@ -964,11 +966,13 @@ export let range = (n, m, step = 1) => {
|
|
|
964
966
|
? Math.ceil(Math.abs(base) / Math.abs(step) + Math.abs(bound) / Math.abs(step))
|
|
965
967
|
: Math.ceil((bound - base) / step);
|
|
966
968
|
if (!Number.isFinite(estimatedLength) || estimatedLength > MAX_RANGE_LENGTH) {
|
|
967
|
-
throw
|
|
969
|
+
throw rangeTooLarge();
|
|
968
970
|
}
|
|
969
971
|
const result = [];
|
|
970
972
|
if (step > 0) {
|
|
971
973
|
for (let value = base; value < bound;) {
|
|
974
|
+
if (result.length >= MAX_RANGE_LENGTH)
|
|
975
|
+
throw rangeTooLarge();
|
|
972
976
|
result.push(value);
|
|
973
977
|
const next = value + step;
|
|
974
978
|
if (next === value) {
|
|
@@ -979,6 +983,8 @@ export let range = (n, m, step = 1) => {
|
|
|
979
983
|
}
|
|
980
984
|
else {
|
|
981
985
|
for (let value = base; value > bound;) {
|
|
986
|
+
if (result.length >= MAX_RANGE_LENGTH)
|
|
987
|
+
throw rangeTooLarge();
|
|
982
988
|
result.push(value);
|
|
983
989
|
const next = value + step;
|
|
984
990
|
if (next === value) {
|
|
@@ -1158,11 +1164,12 @@ export let _$n_list_$o_slice = (xs, from, to) => {
|
|
|
1158
1164
|
if (to == null) {
|
|
1159
1165
|
to = size;
|
|
1160
1166
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1167
|
+
// Bounds are integers with 0 <= from <= to <= size, as in native (docs/data/number.md).
|
|
1168
|
+
if (!Number.isInteger(from) || !Number.isInteger(to) || from < 0 || from > to || to > size) {
|
|
1169
|
+
throw new Error(`&list:slice expected integer bounds within 0..${size}, but received: ${from} ${to}`);
|
|
1163
1170
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1171
|
+
if (from === to) {
|
|
1172
|
+
return new CalcitSliceList([]);
|
|
1166
1173
|
}
|
|
1167
1174
|
return xs.slice(from, to);
|
|
1168
1175
|
};
|
|
@@ -1360,13 +1367,19 @@ export let cos = (n) => {
|
|
|
1360
1367
|
return Math.cos(n);
|
|
1361
1368
|
};
|
|
1362
1369
|
export let pow = (n, m) => {
|
|
1370
|
+
// IEEE 754 pow, which Math.pow breaks: pow(1, y) is 1 for any y, pow(-1, ±Infinity) is 1.
|
|
1371
|
+
if (n === 1 || (n === -1 && (m === Infinity || m === -Infinity))) {
|
|
1372
|
+
return 1;
|
|
1373
|
+
}
|
|
1363
1374
|
return Math.pow(n, m);
|
|
1364
1375
|
};
|
|
1365
1376
|
export let ceil = (n) => {
|
|
1366
1377
|
return Math.ceil(n);
|
|
1367
1378
|
};
|
|
1368
1379
|
export let round = (n) => {
|
|
1369
|
-
|
|
1380
|
+
// Ties round away from zero; `Math.round` alone rounds them toward +Infinity.
|
|
1381
|
+
// Negating keeps `-0` for inputs such as -0.4.
|
|
1382
|
+
return n < 0 ? -Math.round(-n) : Math.round(n);
|
|
1370
1383
|
};
|
|
1371
1384
|
export let _$n_number_$o_fract = (n) => {
|
|
1372
1385
|
return n - Math.floor(n);
|
|
@@ -1519,6 +1532,10 @@ export let _$n_number_$o_format = (x, n) => {
|
|
|
1519
1532
|
return x.toFixed(n);
|
|
1520
1533
|
};
|
|
1521
1534
|
export let _$n_number_$o_display_by = (x, n) => {
|
|
1535
|
+
// a non-negative safe integer, printed exactly (docs/data/number.md)
|
|
1536
|
+
if (typeof x !== "number" || !Number.isSafeInteger(x) || x < 0) {
|
|
1537
|
+
throw new Error(`&number:display-by expected a non-negative safe integer, but received: ${x}`);
|
|
1538
|
+
}
|
|
1522
1539
|
switch (n) {
|
|
1523
1540
|
case 2:
|
|
1524
1541
|
return `0b${x.toString(2)}`;
|
|
@@ -1690,37 +1707,6 @@ export let quit_$x_ = (code) => {
|
|
|
1690
1707
|
throw new Error(`quit!(${code})`);
|
|
1691
1708
|
}
|
|
1692
1709
|
};
|
|
1693
|
-
let format_calcit_number = (x) => {
|
|
1694
|
-
// Match native f64 Display, which expands finite exponents into decimal notation.
|
|
1695
|
-
if (Object.is(x, -0)) {
|
|
1696
|
-
return "-0";
|
|
1697
|
-
}
|
|
1698
|
-
if (x === Infinity) {
|
|
1699
|
-
return "inf";
|
|
1700
|
-
}
|
|
1701
|
-
if (x === -Infinity) {
|
|
1702
|
-
return "-inf";
|
|
1703
|
-
}
|
|
1704
|
-
const text = x.toString();
|
|
1705
|
-
const exponentIndex = text.indexOf("e");
|
|
1706
|
-
if (exponentIndex < 0) {
|
|
1707
|
-
return text;
|
|
1708
|
-
}
|
|
1709
|
-
const mantissa = text.slice(0, exponentIndex);
|
|
1710
|
-
const exponent = Number(text.slice(exponentIndex + 1));
|
|
1711
|
-
const sign = mantissa.startsWith("-") ? "-" : "";
|
|
1712
|
-
const unsigned = sign ? mantissa.slice(1) : mantissa;
|
|
1713
|
-
const decimalPoint = unsigned.indexOf(".");
|
|
1714
|
-
const decimalIndex = (decimalPoint < 0 ? unsigned.length : decimalPoint) + exponent;
|
|
1715
|
-
const digits = unsigned.replace(".", "");
|
|
1716
|
-
if (decimalIndex <= 0) {
|
|
1717
|
-
return `${sign}0.${"0".repeat(-decimalIndex)}${digits}`;
|
|
1718
|
-
}
|
|
1719
|
-
if (decimalIndex >= digits.length) {
|
|
1720
|
-
return `${sign}${digits}${"0".repeat(decimalIndex - digits.length)}`;
|
|
1721
|
-
}
|
|
1722
|
-
return `${sign}${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
|
|
1723
|
-
};
|
|
1724
1710
|
export let turn_string = (x) => {
|
|
1725
1711
|
if (x === null) {
|
|
1726
1712
|
return "";
|
|
@@ -2053,75 +2039,75 @@ const typed_edn_error = (path, message) => {
|
|
|
2053
2039
|
const enum_prototype_name = (value) => {
|
|
2054
2040
|
return value instanceof CalcitEnumDef ? value.name() : value.name.value;
|
|
2055
2041
|
};
|
|
2056
|
-
const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
|
|
2042
|
+
const decode_typed_edn_node = (graph, nodeId, input, path, depth, fail = typed_edn_error) => {
|
|
2057
2043
|
if (depth > 1024)
|
|
2058
|
-
|
|
2044
|
+
fail(path, "decode nesting exceeds 1024");
|
|
2059
2045
|
const node = graph.nodes[nodeId];
|
|
2060
2046
|
if (node == null)
|
|
2061
|
-
|
|
2047
|
+
fail(path, `invalid data shape node #${nodeId}`);
|
|
2062
2048
|
switch (node.kind) {
|
|
2063
2049
|
case "nil":
|
|
2064
2050
|
if (input === null)
|
|
2065
2051
|
return null;
|
|
2066
|
-
return
|
|
2052
|
+
return fail(path, `expected nil, got ${typed_edn_kind(input)}`);
|
|
2067
2053
|
case "unit":
|
|
2068
2054
|
if (input === undefined)
|
|
2069
2055
|
return input;
|
|
2070
|
-
return
|
|
2056
|
+
return fail(path, `expected &unit, got ${typed_edn_kind(input)}`);
|
|
2071
2057
|
case "bool":
|
|
2072
2058
|
if (typeof input === "boolean")
|
|
2073
2059
|
return input;
|
|
2074
|
-
return
|
|
2060
|
+
return fail(path, `expected bool, got ${typed_edn_kind(input)}`);
|
|
2075
2061
|
case "number":
|
|
2076
2062
|
if (typeof input === "number")
|
|
2077
2063
|
return input;
|
|
2078
|
-
return
|
|
2064
|
+
return fail(path, `expected number, got ${typed_edn_kind(input)}`);
|
|
2079
2065
|
case "numeric":
|
|
2080
2066
|
if (typeof input !== "number")
|
|
2081
|
-
return
|
|
2067
|
+
return fail(path, `expected ${node.target}, got ${typed_edn_kind(input)}`);
|
|
2082
2068
|
if (_$n_number_$o_fits_$q_(input, newTag(node.target)))
|
|
2083
2069
|
return input;
|
|
2084
|
-
return
|
|
2070
|
+
return fail(path, `number ${input} does not fit ${node.target}`);
|
|
2085
2071
|
case "string":
|
|
2086
2072
|
if (typeof input === "string")
|
|
2087
2073
|
return input;
|
|
2088
|
-
return
|
|
2074
|
+
return fail(path, `expected string, got ${typed_edn_kind(input)}`);
|
|
2089
2075
|
case "symbol":
|
|
2090
2076
|
if (input instanceof CalcitSymbol)
|
|
2091
2077
|
return input;
|
|
2092
|
-
return
|
|
2078
|
+
return fail(path, `expected symbol, got ${typed_edn_kind(input)}`);
|
|
2093
2079
|
case "tag":
|
|
2094
2080
|
if (input instanceof CalcitTag)
|
|
2095
2081
|
return input;
|
|
2096
|
-
return
|
|
2082
|
+
return fail(path, `expected tag, got ${typed_edn_kind(input)}`);
|
|
2097
2083
|
case "buffer":
|
|
2098
2084
|
if (input instanceof Uint8Array)
|
|
2099
2085
|
return input;
|
|
2100
|
-
return
|
|
2086
|
+
return fail(path, `expected buffer, got ${typed_edn_kind(input)}`);
|
|
2101
2087
|
case "cirru-quote":
|
|
2102
2088
|
if (input instanceof CalcitCirruQuote)
|
|
2103
2089
|
return input;
|
|
2104
|
-
return
|
|
2090
|
+
return fail(path, `expected cirru-quote, got ${typed_edn_kind(input)}`);
|
|
2105
2091
|
case "optional":
|
|
2106
|
-
return input === null ? null : decode_typed_edn_node(graph, node.inner, input, path, depth + 1);
|
|
2092
|
+
return input === null ? null : decode_typed_edn_node(graph, node.inner, input, path, depth + 1, fail);
|
|
2107
2093
|
case "list": {
|
|
2108
2094
|
if (!(input instanceof CalcitList || input instanceof CalcitSliceList)) {
|
|
2109
|
-
return
|
|
2095
|
+
return fail(path, `expected list, got ${typed_edn_kind(input)}`);
|
|
2110
2096
|
}
|
|
2111
|
-
const values = Array.from(input.items()).map((value, idx) => decode_typed_edn_node(graph, node.inner, value, `${path}[${idx}]`, depth + 1));
|
|
2097
|
+
const values = Array.from(input.items()).map((value, idx) => decode_typed_edn_node(graph, node.inner, value, `${path}[${idx}]`, depth + 1, fail));
|
|
2112
2098
|
return new CalcitSliceList(values);
|
|
2113
2099
|
}
|
|
2114
2100
|
case "set": {
|
|
2115
2101
|
if (!(input instanceof CalcitSet || input instanceof TypedEdnSetView)) {
|
|
2116
|
-
return
|
|
2102
|
+
return fail(path, `expected set, got ${typed_edn_kind(input)}`);
|
|
2117
2103
|
}
|
|
2118
2104
|
const values = [];
|
|
2119
2105
|
const inputValues = input instanceof TypedEdnSetView ? input.items : input.values();
|
|
2120
2106
|
inputValues.forEach((value) => {
|
|
2121
2107
|
const itemPath = `${path}.item`;
|
|
2122
|
-
const decoded = decode_typed_edn_node(graph, node.inner, value, itemPath, depth + 1);
|
|
2108
|
+
const decoded = decode_typed_edn_node(graph, node.inner, value, itemPath, depth + 1, fail);
|
|
2123
2109
|
if (values.some((existing) => _$n__$e_(existing, decoded))) {
|
|
2124
|
-
|
|
2110
|
+
fail(itemPath, "duplicate decoded set value");
|
|
2125
2111
|
}
|
|
2126
2112
|
values.push(decoded);
|
|
2127
2113
|
});
|
|
@@ -2129,53 +2115,53 @@ const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
|
|
|
2129
2115
|
}
|
|
2130
2116
|
case "map": {
|
|
2131
2117
|
if (!(input instanceof CalcitMap || input instanceof CalcitSliceMap)) {
|
|
2132
|
-
return
|
|
2118
|
+
return fail(path, `expected map, got ${typed_edn_kind(input)}`);
|
|
2133
2119
|
}
|
|
2134
2120
|
const entries = [];
|
|
2135
2121
|
input.pairs().forEach(([key, value]) => {
|
|
2136
2122
|
const keyPath = `${path}.key`;
|
|
2137
|
-
const decodedKey = decode_typed_edn_node(graph, node.key, key, keyPath, depth + 1);
|
|
2123
|
+
const decodedKey = decode_typed_edn_node(graph, node.key, key, keyPath, depth + 1, fail);
|
|
2138
2124
|
for (let idx = 0; idx < entries.length; idx += 2) {
|
|
2139
2125
|
if (_$n__$e_(entries[idx], decodedKey)) {
|
|
2140
|
-
|
|
2126
|
+
fail(keyPath, "duplicate decoded map key");
|
|
2141
2127
|
}
|
|
2142
2128
|
}
|
|
2143
|
-
const decodedValue = decode_typed_edn_node(graph, node.value, value, `${path}.value`, depth + 1);
|
|
2129
|
+
const decodedValue = decode_typed_edn_node(graph, node.value, value, `${path}.value`, depth + 1, fail);
|
|
2144
2130
|
entries.push(decodedKey, decodedValue);
|
|
2145
2131
|
});
|
|
2146
2132
|
return new CalcitSliceMap(entries);
|
|
2147
2133
|
}
|
|
2148
2134
|
case "ref":
|
|
2149
2135
|
if (!(input instanceof CalcitRef))
|
|
2150
|
-
return
|
|
2151
|
-
return atom(decode_typed_edn_node(graph, node.inner, input.value, `${path}.value`, depth + 1));
|
|
2136
|
+
return fail(path, `expected atom, got ${typed_edn_kind(input)}`);
|
|
2137
|
+
return atom(decode_typed_edn_node(graph, node.inner, input.value, `${path}.value`, depth + 1, fail));
|
|
2152
2138
|
case "struct": {
|
|
2153
2139
|
if (!(input instanceof CalcitStructValue)) {
|
|
2154
|
-
return
|
|
2140
|
+
return fail(path, `expected struct :${node.nominal.name.value}, got ${typed_edn_kind(input)}`);
|
|
2155
2141
|
}
|
|
2156
2142
|
if (input.name.value !== node.nominal.name.value) {
|
|
2157
|
-
return
|
|
2143
|
+
return fail(path, `expected struct :${node.nominal.name.value}, got struct :${input.name.value}`);
|
|
2158
2144
|
}
|
|
2159
2145
|
const expectedNames = node.fields.map(([name]) => name);
|
|
2160
2146
|
const actualNames = input.fields.map((field) => field.value);
|
|
2161
2147
|
const missing = expectedNames.filter((name) => !actualNames.includes(name)).sort();
|
|
2162
2148
|
const unknown = actualNames.filter((name) => !expectedNames.includes(name)).sort();
|
|
2163
2149
|
if (missing.length > 0 || unknown.length > 0 || expectedNames.length !== actualNames.length) {
|
|
2164
|
-
return
|
|
2150
|
+
return fail(path, `struct :${node.nominal.name.value} fields mismatch; missing [${missing.join(", ")}], unknown [${unknown.join(", ")}]`);
|
|
2165
2151
|
}
|
|
2166
2152
|
const decodedFields = new Map();
|
|
2167
2153
|
node.fields.forEach(([name, fieldNode]) => {
|
|
2168
2154
|
const idx = actualNames.indexOf(name);
|
|
2169
|
-
decodedFields.set(name, decode_typed_edn_node(graph, fieldNode, input.values[idx], `${path}.${name}`, depth + 1));
|
|
2155
|
+
decodedFields.set(name, decode_typed_edn_node(graph, fieldNode, input.values[idx], `${path}.${name}`, depth + 1, fail));
|
|
2170
2156
|
});
|
|
2171
2157
|
// Re-align by name so values produced by older runtimes or external data
|
|
2172
2158
|
// still adopt the current nominal declaration's canonical field layout.
|
|
2173
2159
|
if (decodedFields.size !== node.nominal.fields.length) {
|
|
2174
|
-
return
|
|
2160
|
+
return fail(path, `struct :${node.nominal.name.value} decoder fields do not match its nominal declaration`);
|
|
2175
2161
|
}
|
|
2176
2162
|
const values = node.nominal.fields.map((field) => {
|
|
2177
2163
|
if (!decodedFields.has(field.value)) {
|
|
2178
|
-
return
|
|
2164
|
+
return fail(path, `struct :${node.nominal.name.value} is missing declared field :${field.value}`);
|
|
2179
2165
|
}
|
|
2180
2166
|
return decodedFields.get(field.value);
|
|
2181
2167
|
});
|
|
@@ -2183,28 +2169,28 @@ const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
|
|
|
2183
2169
|
}
|
|
2184
2170
|
case "enum": {
|
|
2185
2171
|
if (!(input instanceof CalcitEnumValue) || input.enumPrototype == null) {
|
|
2186
|
-
return
|
|
2172
|
+
return fail(path, `expected enum :${node.nominal.name()}, got ${typed_edn_kind(input)}`);
|
|
2187
2173
|
}
|
|
2188
2174
|
const actualEnumName = enum_prototype_name(input.enumPrototype);
|
|
2189
2175
|
if (actualEnumName !== node.nominal.name()) {
|
|
2190
|
-
return
|
|
2176
|
+
return fail(path, `expected enum :${node.nominal.name()}, got enum :${actualEnumName}`);
|
|
2191
2177
|
}
|
|
2192
2178
|
if (!(input.tag instanceof CalcitTag)) {
|
|
2193
|
-
return
|
|
2179
|
+
return fail(path, `enum :${node.nominal.name()} variant must be a tag`);
|
|
2194
2180
|
}
|
|
2195
2181
|
const inputTag = input.tag;
|
|
2196
2182
|
const variant = node.variants.find((candidate) => candidate.tag === inputTag.value);
|
|
2197
2183
|
if (variant == null) {
|
|
2198
|
-
return
|
|
2184
|
+
return fail(path, `enum :${node.nominal.name()} has no variant :${inputTag.value}`);
|
|
2199
2185
|
}
|
|
2200
2186
|
if (variant.payload.length !== input.extra.length) {
|
|
2201
|
-
return
|
|
2187
|
+
return fail(path, `enum :${node.nominal.name()} variant :${variant.tag} expects ${variant.payload.length} payload(s), got ${input.extra.length}`);
|
|
2202
2188
|
}
|
|
2203
|
-
const values = variant.payload.map((payloadNode, idx) => decode_typed_edn_node(graph, payloadNode, input.extra[idx], `${path}.payload[${idx}]`, depth + 1));
|
|
2189
|
+
const values = variant.payload.map((payloadNode, idx) => decode_typed_edn_node(graph, payloadNode, input.extra[idx], `${path}.payload[${idx}]`, depth + 1, fail));
|
|
2204
2190
|
return new CalcitEnumValue(newTag(variant.tag), values, node.nominal);
|
|
2205
2191
|
}
|
|
2206
2192
|
default:
|
|
2207
|
-
return
|
|
2193
|
+
return fail(path, `invalid data shape node kind: ${node.kind}`);
|
|
2208
2194
|
}
|
|
2209
2195
|
};
|
|
2210
2196
|
export let parse_cirru_edn_as = (code, graph) => {
|
|
@@ -2355,7 +2341,7 @@ const decode_runtime_map_node = (graph, nodeId, input, path, depth) => {
|
|
|
2355
2341
|
return new CalcitEnumValue(newTag(variant.tag), values, node.nominal);
|
|
2356
2342
|
}
|
|
2357
2343
|
default:
|
|
2358
|
-
return decode_typed_edn_node(graph, nodeId, input, path, depth);
|
|
2344
|
+
return decode_typed_edn_node(graph, nodeId, input, path, depth, map_decode_error);
|
|
2359
2345
|
}
|
|
2360
2346
|
};
|
|
2361
2347
|
export let decode_map_as = (value, graph) => {
|
|
@@ -2980,23 +2966,30 @@ export let _$n_map_$o_diff_triple = (a, b) => {
|
|
|
2980
2966
|
throw new Error("&map:diff-triple expected 2 maps");
|
|
2981
2967
|
}
|
|
2982
2968
|
};
|
|
2969
|
+
// Bitwise operands are integers within i32 (docs/data/number.md); JS would otherwise wrap or truncate them.
|
|
2970
|
+
let bit_operand = (name, x) => {
|
|
2971
|
+
if (typeof x !== "number" || !Number.isInteger(x) || x < -2147483648 || x > 2147483647) {
|
|
2972
|
+
throw new Error(`&math:${name} operand expected an integer within i32, but got: ${x}`);
|
|
2973
|
+
}
|
|
2974
|
+
return x;
|
|
2975
|
+
};
|
|
2983
2976
|
export let bit_shr = (base, step) => {
|
|
2984
|
-
return base >> step;
|
|
2977
|
+
return bit_operand("bit-shr", base) >> bit_operand("bit-shr", step);
|
|
2985
2978
|
};
|
|
2986
2979
|
export let bit_shl = (base, step) => {
|
|
2987
|
-
return base << step;
|
|
2980
|
+
return bit_operand("bit-shl", base) << bit_operand("bit-shl", step);
|
|
2988
2981
|
};
|
|
2989
2982
|
export let bit_and = (a, b) => {
|
|
2990
|
-
return a & b;
|
|
2983
|
+
return bit_operand("bit-and", a) & bit_operand("bit-and", b);
|
|
2991
2984
|
};
|
|
2992
2985
|
export let bit_or = (a, b) => {
|
|
2993
|
-
return a | b;
|
|
2986
|
+
return bit_operand("bit-or", a) | bit_operand("bit-or", b);
|
|
2994
2987
|
};
|
|
2995
2988
|
export let bit_xor = (a, b) => {
|
|
2996
|
-
return a ^ b;
|
|
2989
|
+
return bit_operand("bit-xor", a) ^ bit_operand("bit-xor", b);
|
|
2997
2990
|
};
|
|
2998
2991
|
export let bit_not = (a) => {
|
|
2999
|
-
return ~a;
|
|
2992
|
+
return ~bit_operand("bit-not", a);
|
|
3000
2993
|
};
|
|
3001
2994
|
export let _$n_list_$o_to_set = (xs) => {
|
|
3002
2995
|
var result = [];
|
|
@@ -3019,11 +3012,41 @@ export let _$n_list_$o_distinct = (xs) => {
|
|
|
3019
3012
|
}
|
|
3020
3013
|
return new CalcitSliceList(result);
|
|
3021
3014
|
};
|
|
3015
|
+
// Longest padded string, the V8 string length limit, so every backend fails at the same size.
|
|
3016
|
+
const MAX_PADDED_LEN = 536870888;
|
|
3017
|
+
// Padding for `&str:pad-left` / `&str:pad-right`, measured in Unicode scalars like `&str:count`
|
|
3018
|
+
// (not UTF-16 units, so astral characters are never split). NaN and negative lengths pad nothing,
|
|
3019
|
+
// and so does an empty pattern.
|
|
3020
|
+
const strPadding = (procName, s, size, pattern) => {
|
|
3021
|
+
if (size > MAX_PADDED_LEN) {
|
|
3022
|
+
throw new Error(`${procName} expected a finite length up to ${MAX_PADDED_LEN}, but received: ${format_calcit_number(size)}`);
|
|
3023
|
+
}
|
|
3024
|
+
if (!(size > 0) || pattern === "")
|
|
3025
|
+
return "";
|
|
3026
|
+
let missing = Math.floor(size);
|
|
3027
|
+
for (const _scalar of s) {
|
|
3028
|
+
missing -= 1;
|
|
3029
|
+
if (missing <= 0)
|
|
3030
|
+
return "";
|
|
3031
|
+
}
|
|
3032
|
+
let patternCount = 0;
|
|
3033
|
+
for (const _scalar of pattern)
|
|
3034
|
+
patternCount += 1;
|
|
3035
|
+
let padding = pattern.repeat(Math.floor(missing / patternCount));
|
|
3036
|
+
let rest = missing % patternCount;
|
|
3037
|
+
for (const scalar of pattern) {
|
|
3038
|
+
if (rest <= 0)
|
|
3039
|
+
break;
|
|
3040
|
+
padding += scalar;
|
|
3041
|
+
rest -= 1;
|
|
3042
|
+
}
|
|
3043
|
+
return padding;
|
|
3044
|
+
};
|
|
3022
3045
|
export let _$n_str_$o_pad_left = (s, size, pattern) => {
|
|
3023
|
-
return s
|
|
3046
|
+
return strPadding("&str:pad-left", s, size, pattern) + s;
|
|
3024
3047
|
};
|
|
3025
3048
|
export let _$n_str_$o_pad_right = (s, size, pattern) => {
|
|
3026
|
-
return s
|
|
3049
|
+
return s + strPadding("&str:pad-right", s, size, pattern);
|
|
3027
3050
|
};
|
|
3028
3051
|
export let _$n_get_os = () => {
|
|
3029
3052
|
return newTag("js-engine");
|
|
@@ -3079,8 +3102,12 @@ export let macroexpand_all = unavailableProc;
|
|
|
3079
3102
|
export let _$n_get_calcit_running_mode = unavailableProc;
|
|
3080
3103
|
export let _$n_get_def_doc = unavailableProc;
|
|
3081
3104
|
export let _$n_get_def_schema = unavailableProc;
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3105
|
+
// A missing native lifecycle capability must not look like a successful Unit.
|
|
3106
|
+
const unavailableNativeFfi = (operation) => {
|
|
3107
|
+
throw new Error(`${operation}: native FFI capability is not available for calcit-js`);
|
|
3108
|
+
};
|
|
3109
|
+
export let _$n_ffi_response_resolve = (..._args) => unavailableNativeFfi("&ffi-response-resolve");
|
|
3110
|
+
export let _$n_ffi_response_reject = (..._args) => unavailableNativeFfi("&ffi-response-reject");
|
|
3111
|
+
export let _$n_ffi_task_cancel = (..._args) => unavailableNativeFfi("&ffi-task-cancel");
|
|
3085
3112
|
// already handled in code emitter
|
|
3086
3113
|
export let raise = unavailableProc;
|
package/lib/package.json
CHANGED