@calcit/procs 0.29.0-alpha.26 → 0.29.0-alpha.28
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.mjs +81 -49
- package/lib/js-cirru.d.mts +1 -1
- package/lib/js-cirru.mjs +9 -2
- 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.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";
|
|
@@ -930,14 +930,25 @@ export let add_watch_$x_ = (a, k, f) => {
|
|
|
930
930
|
if (!(typeof f === "function")) {
|
|
931
931
|
throw new Error("Expected watcher function");
|
|
932
932
|
}
|
|
933
|
+
for (const listenerKey of a.listeners.keys()) {
|
|
934
|
+
if (listenerKey instanceof CalcitTag && listenerKey.value === k.value) {
|
|
935
|
+
throw new Error(`add-watch! failed: listener with key \`${k.value}\` already existed`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
933
938
|
a.listeners.set(k, f);
|
|
934
939
|
};
|
|
935
940
|
export let remove_watch = (a, k) => {
|
|
936
|
-
|
|
937
|
-
|
|
941
|
+
for (const listenerKey of a.listeners.keys()) {
|
|
942
|
+
if (listenerKey instanceof CalcitTag && listenerKey.value === k.value) {
|
|
943
|
+
a.listeners.delete(listenerKey);
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
938
946
|
}
|
|
947
|
+
throw new Error(`remove-watch failed: listener with key \`${k.value}\` not found`);
|
|
939
948
|
};
|
|
940
|
-
|
|
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`);
|
|
941
952
|
export let range = (n, m, step = 1) => {
|
|
942
953
|
const base = m == null ? 0 : n;
|
|
943
954
|
const bound = m == null ? n : m;
|
|
@@ -955,11 +966,13 @@ export let range = (n, m, step = 1) => {
|
|
|
955
966
|
? Math.ceil(Math.abs(base) / Math.abs(step) + Math.abs(bound) / Math.abs(step))
|
|
956
967
|
: Math.ceil((bound - base) / step);
|
|
957
968
|
if (!Number.isFinite(estimatedLength) || estimatedLength > MAX_RANGE_LENGTH) {
|
|
958
|
-
throw
|
|
969
|
+
throw rangeTooLarge();
|
|
959
970
|
}
|
|
960
971
|
const result = [];
|
|
961
972
|
if (step > 0) {
|
|
962
973
|
for (let value = base; value < bound;) {
|
|
974
|
+
if (result.length >= MAX_RANGE_LENGTH)
|
|
975
|
+
throw rangeTooLarge();
|
|
963
976
|
result.push(value);
|
|
964
977
|
const next = value + step;
|
|
965
978
|
if (next === value) {
|
|
@@ -970,6 +983,8 @@ export let range = (n, m, step = 1) => {
|
|
|
970
983
|
}
|
|
971
984
|
else {
|
|
972
985
|
for (let value = base; value > bound;) {
|
|
986
|
+
if (result.length >= MAX_RANGE_LENGTH)
|
|
987
|
+
throw rangeTooLarge();
|
|
973
988
|
result.push(value);
|
|
974
989
|
const next = value + step;
|
|
975
990
|
if (next === value) {
|
|
@@ -1149,11 +1164,12 @@ export let _$n_list_$o_slice = (xs, from, to) => {
|
|
|
1149
1164
|
if (to == null) {
|
|
1150
1165
|
to = size;
|
|
1151
1166
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
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}`);
|
|
1154
1170
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1171
|
+
if (from === to) {
|
|
1172
|
+
return new CalcitSliceList([]);
|
|
1157
1173
|
}
|
|
1158
1174
|
return xs.slice(from, to);
|
|
1159
1175
|
};
|
|
@@ -1351,13 +1367,19 @@ export let cos = (n) => {
|
|
|
1351
1367
|
return Math.cos(n);
|
|
1352
1368
|
};
|
|
1353
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
|
+
}
|
|
1354
1374
|
return Math.pow(n, m);
|
|
1355
1375
|
};
|
|
1356
1376
|
export let ceil = (n) => {
|
|
1357
1377
|
return Math.ceil(n);
|
|
1358
1378
|
};
|
|
1359
1379
|
export let round = (n) => {
|
|
1360
|
-
|
|
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);
|
|
1361
1383
|
};
|
|
1362
1384
|
export let _$n_number_$o_fract = (n) => {
|
|
1363
1385
|
return n - Math.floor(n);
|
|
@@ -1510,6 +1532,10 @@ export let _$n_number_$o_format = (x, n) => {
|
|
|
1510
1532
|
return x.toFixed(n);
|
|
1511
1533
|
};
|
|
1512
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
|
+
}
|
|
1513
1539
|
switch (n) {
|
|
1514
1540
|
case 2:
|
|
1515
1541
|
return `0b${x.toString(2)}`;
|
|
@@ -1681,37 +1707,6 @@ export let quit_$x_ = (code) => {
|
|
|
1681
1707
|
throw new Error(`quit!(${code})`);
|
|
1682
1708
|
}
|
|
1683
1709
|
};
|
|
1684
|
-
let format_calcit_number = (x) => {
|
|
1685
|
-
// Match native f64 Display, which expands finite exponents into decimal notation.
|
|
1686
|
-
if (Object.is(x, -0)) {
|
|
1687
|
-
return "-0";
|
|
1688
|
-
}
|
|
1689
|
-
if (x === Infinity) {
|
|
1690
|
-
return "inf";
|
|
1691
|
-
}
|
|
1692
|
-
if (x === -Infinity) {
|
|
1693
|
-
return "-inf";
|
|
1694
|
-
}
|
|
1695
|
-
const text = x.toString();
|
|
1696
|
-
const exponentIndex = text.indexOf("e");
|
|
1697
|
-
if (exponentIndex < 0) {
|
|
1698
|
-
return text;
|
|
1699
|
-
}
|
|
1700
|
-
const mantissa = text.slice(0, exponentIndex);
|
|
1701
|
-
const exponent = Number(text.slice(exponentIndex + 1));
|
|
1702
|
-
const sign = mantissa.startsWith("-") ? "-" : "";
|
|
1703
|
-
const unsigned = sign ? mantissa.slice(1) : mantissa;
|
|
1704
|
-
const decimalPoint = unsigned.indexOf(".");
|
|
1705
|
-
const decimalIndex = (decimalPoint < 0 ? unsigned.length : decimalPoint) + exponent;
|
|
1706
|
-
const digits = unsigned.replace(".", "");
|
|
1707
|
-
if (decimalIndex <= 0) {
|
|
1708
|
-
return `${sign}0.${"0".repeat(-decimalIndex)}${digits}`;
|
|
1709
|
-
}
|
|
1710
|
-
if (decimalIndex >= digits.length) {
|
|
1711
|
-
return `${sign}${digits}${"0".repeat(decimalIndex - digits.length)}`;
|
|
1712
|
-
}
|
|
1713
|
-
return `${sign}${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
|
|
1714
|
-
};
|
|
1715
1710
|
export let turn_string = (x) => {
|
|
1716
1711
|
if (x === null) {
|
|
1717
1712
|
return "";
|
|
@@ -2971,23 +2966,30 @@ export let _$n_map_$o_diff_triple = (a, b) => {
|
|
|
2971
2966
|
throw new Error("&map:diff-triple expected 2 maps");
|
|
2972
2967
|
}
|
|
2973
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
|
+
};
|
|
2974
2976
|
export let bit_shr = (base, step) => {
|
|
2975
|
-
return base >> step;
|
|
2977
|
+
return bit_operand("bit-shr", base) >> bit_operand("bit-shr", step);
|
|
2976
2978
|
};
|
|
2977
2979
|
export let bit_shl = (base, step) => {
|
|
2978
|
-
return base << step;
|
|
2980
|
+
return bit_operand("bit-shl", base) << bit_operand("bit-shl", step);
|
|
2979
2981
|
};
|
|
2980
2982
|
export let bit_and = (a, b) => {
|
|
2981
|
-
return a & b;
|
|
2983
|
+
return bit_operand("bit-and", a) & bit_operand("bit-and", b);
|
|
2982
2984
|
};
|
|
2983
2985
|
export let bit_or = (a, b) => {
|
|
2984
|
-
return a | b;
|
|
2986
|
+
return bit_operand("bit-or", a) | bit_operand("bit-or", b);
|
|
2985
2987
|
};
|
|
2986
2988
|
export let bit_xor = (a, b) => {
|
|
2987
|
-
return a ^ b;
|
|
2989
|
+
return bit_operand("bit-xor", a) ^ bit_operand("bit-xor", b);
|
|
2988
2990
|
};
|
|
2989
2991
|
export let bit_not = (a) => {
|
|
2990
|
-
return ~a;
|
|
2992
|
+
return ~bit_operand("bit-not", a);
|
|
2991
2993
|
};
|
|
2992
2994
|
export let _$n_list_$o_to_set = (xs) => {
|
|
2993
2995
|
var result = [];
|
|
@@ -3010,11 +3012,41 @@ export let _$n_list_$o_distinct = (xs) => {
|
|
|
3010
3012
|
}
|
|
3011
3013
|
return new CalcitSliceList(result);
|
|
3012
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
|
+
};
|
|
3013
3045
|
export let _$n_str_$o_pad_left = (s, size, pattern) => {
|
|
3014
|
-
return s
|
|
3046
|
+
return strPadding("&str:pad-left", s, size, pattern) + s;
|
|
3015
3047
|
};
|
|
3016
3048
|
export let _$n_str_$o_pad_right = (s, size, pattern) => {
|
|
3017
|
-
return s
|
|
3049
|
+
return s + strPadding("&str:pad-right", s, size, pattern);
|
|
3018
3050
|
};
|
|
3019
3051
|
export let _$n_get_os = () => {
|
|
3020
3052
|
return newTag("js-engine");
|
package/lib/js-cirru.d.mts
CHANGED
|
@@ -12,7 +12,7 @@ export declare class CalcitCirruQuote {
|
|
|
12
12
|
/** provide a simple text representation in Console or std out, with indentations */
|
|
13
13
|
textForm(): string;
|
|
14
14
|
}
|
|
15
|
-
export declare let format_cirru: (data: CalcitCirruQuote | CalcitList, useInline
|
|
15
|
+
export declare let format_cirru: (data: CalcitCirruQuote | CalcitList, useInline?: boolean) => string;
|
|
16
16
|
export declare let format_cirru_one_liner: (data: CalcitCirruQuote | CalcitList) => string;
|
|
17
17
|
/** better use string version of Cirru EDN in future */
|
|
18
18
|
export declare let to_cirru_edn: (x: CalcitValue) => CirruEdnFormat;
|
package/lib/js-cirru.mjs
CHANGED
|
@@ -160,7 +160,12 @@ export class CalcitCirruQuote {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
-
export let format_cirru = (data, useInline)
|
|
163
|
+
export let format_cirru = function (data, useInline) {
|
|
164
|
+
if (arguments.length < 2)
|
|
165
|
+
useInline = false;
|
|
166
|
+
if (typeof useInline !== "boolean") {
|
|
167
|
+
throw new Error("format-cirru requires a boolean inline option");
|
|
168
|
+
}
|
|
164
169
|
if (data instanceof CalcitCirruQuote) {
|
|
165
170
|
return writeCirruCode(data.value, { useInline });
|
|
166
171
|
}
|
|
@@ -563,7 +568,9 @@ export let extract_cirru_edn = (x, options) => {
|
|
|
563
568
|
export let extract_cirru_edn_for_typed = (x, options) => {
|
|
564
569
|
return extract_cirru_edn_inner(x, options, true);
|
|
565
570
|
};
|
|
566
|
-
export let format_cirru_edn = (data, useInline
|
|
571
|
+
export let format_cirru_edn = function (data, useInline) {
|
|
572
|
+
if (arguments.length < 2)
|
|
573
|
+
useInline = true;
|
|
567
574
|
if (typeof useInline !== "boolean") {
|
|
568
575
|
throw new Error("format-cirru-edn requires a boolean inline option");
|
|
569
576
|
}
|
package/lib/package.json
CHANGED