@calcit/procs 0.12.10 → 0.12.11
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/.yarn/install-state.gz
CHANGED
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
This commit moves JSON parsing and serialization into Calcit builtins and aligns the surrounding runtime/docs/tooling updates needed to ship it cleanly.
|
|
4
|
+
|
|
5
|
+
1. Added builtin JSON runtime functions
|
|
6
|
+
- Introduced `json-parse`, `json-stringify`, and `json-pretty` in Rust builtin dispatch and JS runtime exports.
|
|
7
|
+
- Added fast arity/type checks on exposed runtime entry points.
|
|
8
|
+
- Normalized integer-valued numbers to encode as JSON integers in Rust, matching JS output.
|
|
9
|
+
- Added native tests and Calcit-level coverage for parse/stringify/pretty behavior and error paths.
|
|
10
|
+
|
|
11
|
+
2. Updated core docs and runtime placeholder naming
|
|
12
|
+
- Added `calcit.core` docs/examples for the JSON runtime functions.
|
|
13
|
+
- Renamed the runtime placeholder spelling from `runtime-inplementation` to `runtime-implementation` across core snapshot metadata and Rust handling.
|
|
14
|
+
- Preserved an explicit `cr <snapshot-file> edit format` example in `docs/CalcitAgent.md`.
|
|
15
|
+
|
|
16
|
+
3. Snapshot formatting workflow
|
|
17
|
+
- Re-ran `cr edit format` against the touched Cirru snapshot files:
|
|
18
|
+
- `src/cirru/calcit-core.cirru`
|
|
19
|
+
- `calcit/test.cirru`
|
|
20
|
+
|
|
21
|
+
## Files touched (high level)
|
|
22
|
+
|
|
23
|
+
- Rust builtin registration and implementation for JSON runtime support.
|
|
24
|
+
- JS runtime proc exports for JSON behavior and validation.
|
|
25
|
+
- Calcit core snapshot docs/examples and test snapshot updates.
|
|
26
|
+
- CLI/codegen placeholder spelling cleanup.
|
|
27
|
+
- Agent guide example for `edit format`.
|
|
28
|
+
|
|
29
|
+
## Validation notes
|
|
30
|
+
|
|
31
|
+
- `cargo test json_`
|
|
32
|
+
- `cargo test validate_runtime_impl_is_skipped -- --nocapture`
|
|
33
|
+
- `cargo test runtime_placeholder -- --nocapture`
|
|
34
|
+
- `cargo run --bin cr -- calcit/test.cirru -1`
|
|
35
|
+
- `yarn check-all`
|
|
36
|
+
|
|
37
|
+
## Release size check
|
|
38
|
+
|
|
39
|
+
Measured `target/release/cr` against `HEAD` using a detached worktree build:
|
|
40
|
+
|
|
41
|
+
- Current: `5192960` bytes (`5.0M`)
|
|
42
|
+
- Base: `5174400` bytes (`4.9M`)
|
|
43
|
+
- Delta: `+18560` bytes (about `+18.1 KiB`)
|
|
44
|
+
|
|
45
|
+
Conclusion: the builtin JSON work increases the release binary size slightly, but the delta is small relative to the ~5 MB target.
|
package/lib/calcit.procs.mjs
CHANGED
|
@@ -1438,6 +1438,103 @@ export let parse_cirru_edn = (code, options) => {
|
|
|
1438
1438
|
throw new Error(`Expected EDN in a single node, got ${nodes.length}`);
|
|
1439
1439
|
}
|
|
1440
1440
|
};
|
|
1441
|
+
const json_to_calcit = (value) => {
|
|
1442
|
+
if (value == null)
|
|
1443
|
+
return null;
|
|
1444
|
+
if (typeof value === "string")
|
|
1445
|
+
return value;
|
|
1446
|
+
if (typeof value === "number")
|
|
1447
|
+
return value;
|
|
1448
|
+
if (typeof value === "boolean")
|
|
1449
|
+
return value;
|
|
1450
|
+
if (Array.isArray(value)) {
|
|
1451
|
+
return new CalcitSliceList(value.map(json_to_calcit));
|
|
1452
|
+
}
|
|
1453
|
+
if (typeof value === "object") {
|
|
1454
|
+
const entries = [];
|
|
1455
|
+
for (const key of Object.keys(value)) {
|
|
1456
|
+
entries.push(newTag(key), json_to_calcit(value[key]));
|
|
1457
|
+
}
|
|
1458
|
+
return new CalcitSliceMap(entries);
|
|
1459
|
+
}
|
|
1460
|
+
throw new Error(`Unsupported JSON value: ${value}`);
|
|
1461
|
+
};
|
|
1462
|
+
const calcit_json_key = (value) => {
|
|
1463
|
+
if (value instanceof CalcitTag)
|
|
1464
|
+
return value.value;
|
|
1465
|
+
if (typeof value === "string")
|
|
1466
|
+
return value;
|
|
1467
|
+
throw new Error(`json-stringify expected object keys to be tags or strings, got: ${toString(value, true)}`);
|
|
1468
|
+
};
|
|
1469
|
+
const cirru_quote_to_json = (value) => {
|
|
1470
|
+
if (typeof value === "string")
|
|
1471
|
+
return value;
|
|
1472
|
+
if (Array.isArray(value))
|
|
1473
|
+
return value.map(cirru_quote_to_json);
|
|
1474
|
+
throw new Error(`Unsupported cirru quote node: ${value}`);
|
|
1475
|
+
};
|
|
1476
|
+
const calcit_to_json = (value) => {
|
|
1477
|
+
if (value == null)
|
|
1478
|
+
return null;
|
|
1479
|
+
if (typeof value === "string")
|
|
1480
|
+
return value;
|
|
1481
|
+
if (typeof value === "number") {
|
|
1482
|
+
if (Number.isFinite(value))
|
|
1483
|
+
return value;
|
|
1484
|
+
throw new Error(`json-stringify cannot encode number: ${value}`);
|
|
1485
|
+
}
|
|
1486
|
+
if (typeof value === "boolean")
|
|
1487
|
+
return value;
|
|
1488
|
+
if (value instanceof CalcitTag)
|
|
1489
|
+
return value.value;
|
|
1490
|
+
if (value instanceof CalcitSymbol)
|
|
1491
|
+
return value.value;
|
|
1492
|
+
if (value instanceof CalcitList || value instanceof CalcitSliceList) {
|
|
1493
|
+
return Array.from(value.items()).map(calcit_to_json);
|
|
1494
|
+
}
|
|
1495
|
+
if (value instanceof CalcitSet) {
|
|
1496
|
+
return value.values().map(calcit_to_json);
|
|
1497
|
+
}
|
|
1498
|
+
if (value instanceof CalcitMap || value instanceof CalcitSliceMap) {
|
|
1499
|
+
const result = {};
|
|
1500
|
+
for (const [key, item] of value.pairs()) {
|
|
1501
|
+
result[calcit_json_key(key)] = calcit_to_json(item);
|
|
1502
|
+
}
|
|
1503
|
+
return result;
|
|
1504
|
+
}
|
|
1505
|
+
if (value instanceof CalcitTuple) {
|
|
1506
|
+
return [calcit_to_json(value.tag), ...value.extra.map(calcit_to_json)];
|
|
1507
|
+
}
|
|
1508
|
+
if (value instanceof CalcitCirruQuote) {
|
|
1509
|
+
return cirru_quote_to_json(value.value);
|
|
1510
|
+
}
|
|
1511
|
+
if (value instanceof CalcitRecord) {
|
|
1512
|
+
const result = {};
|
|
1513
|
+
for (let idx = 0; idx < value.fields.length; idx++) {
|
|
1514
|
+
result[value.fields[idx].value] = calcit_to_json(value.values[idx]);
|
|
1515
|
+
}
|
|
1516
|
+
return result;
|
|
1517
|
+
}
|
|
1518
|
+
throw new Error(`json-stringify cannot encode value: ${toString(value, true)}`);
|
|
1519
|
+
};
|
|
1520
|
+
export let json_parse = function (code) {
|
|
1521
|
+
if (arguments.length !== 1)
|
|
1522
|
+
throw new Error("json-parse expected 1 argument");
|
|
1523
|
+
if (typeof code !== "string") {
|
|
1524
|
+
throw new Error(`json-parse expected a string, got: ${toString(code, true)}`);
|
|
1525
|
+
}
|
|
1526
|
+
return json_to_calcit(JSON.parse(code));
|
|
1527
|
+
};
|
|
1528
|
+
export let json_stringify = function (value) {
|
|
1529
|
+
if (arguments.length !== 1)
|
|
1530
|
+
throw new Error("json-stringify expected 1 argument");
|
|
1531
|
+
return JSON.stringify(calcit_to_json(value));
|
|
1532
|
+
};
|
|
1533
|
+
export let json_pretty = function (value) {
|
|
1534
|
+
if (arguments.length !== 1)
|
|
1535
|
+
throw new Error("json-pretty expected 1 argument");
|
|
1536
|
+
return JSON.stringify(calcit_to_json(value), null, 2);
|
|
1537
|
+
};
|
|
1441
1538
|
export let format_to_lisp = (x) => {
|
|
1442
1539
|
if (x == null) {
|
|
1443
1540
|
return "nil";
|
package/lib/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@calcit/procs",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.11",
|
|
4
4
|
"main": "./lib/calcit.procs.mjs",
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"@types/node": "^25.0.9",
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"test-rs": "cargo test -q",
|
|
17
17
|
"test-fail": "cargo test -q --bin cr type_fail_",
|
|
18
18
|
"test-snippets": "cargo test -q snippets::tests",
|
|
19
|
-
"bench-recur-smoke": "cargo run --bin cr -- calcit/test.cirru
|
|
19
|
+
"bench-recur-smoke": "cargo run --bin cr -- calcit/test.cirru js && node --input-type=module -e \"import { test_loop } from './js-out/test-recursion.main.mjs'; const n=3000; const t0=process.hrtime.bigint(); for(let i=0;i<n;i++) test_loop(); const dt=Number(process.hrtime.bigint()-t0)/1e6; console.log('test_loop_ms='+dt.toFixed(3));\"",
|
|
20
20
|
"check-smooth": "yarn fmt-rs && yarn lint-rs && yarn test-rs && yarn check-all",
|
|
21
21
|
"check-all": "yarn compile && yarn try-rs && yarn try-js && yarn try-ir",
|
|
22
|
-
"try-rs": "cargo run --bin cr -- calcit/test.cirru
|
|
23
|
-
"warn-dyn-method": "cargo run --bin cr -- calcit/test.cirru
|
|
24
|
-
"try-js-brk": "cargo run --bin cr -- calcit/test.cirru
|
|
25
|
-
"try-js": "cargo run --bin cr -- calcit/test.cirru
|
|
26
|
-
"try-ir": "cargo run --bin cr -- calcit/test.cirru
|
|
22
|
+
"try-rs": "cargo run --bin cr -- calcit/test.cirru",
|
|
23
|
+
"warn-dyn-method": "cargo run --bin cr -- calcit/test.cirru --warn-dyn-method",
|
|
24
|
+
"try-js-brk": "cargo run --bin cr -- calcit/test.cirru js && node --inspect-brk js-out/main.mjs",
|
|
25
|
+
"try-js": "cargo run --bin cr -- calcit/test.cirru js && node js-out/main.mjs",
|
|
26
|
+
"try-ir": "cargo run --bin cr -- calcit/test.cirru js"
|
|
27
27
|
},
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@calcit/procs",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.11",
|
|
4
4
|
"main": "./lib/calcit.procs.mjs",
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"@types/node": "^25.0.9",
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"test-rs": "cargo test -q",
|
|
17
17
|
"test-fail": "cargo test -q --bin cr type_fail_",
|
|
18
18
|
"test-snippets": "cargo test -q snippets::tests",
|
|
19
|
-
"bench-recur-smoke": "cargo run --bin cr -- calcit/test.cirru
|
|
19
|
+
"bench-recur-smoke": "cargo run --bin cr -- calcit/test.cirru js && node --input-type=module -e \"import { test_loop } from './js-out/test-recursion.main.mjs'; const n=3000; const t0=process.hrtime.bigint(); for(let i=0;i<n;i++) test_loop(); const dt=Number(process.hrtime.bigint()-t0)/1e6; console.log('test_loop_ms='+dt.toFixed(3));\"",
|
|
20
20
|
"check-smooth": "yarn fmt-rs && yarn lint-rs && yarn test-rs && yarn check-all",
|
|
21
21
|
"check-all": "yarn compile && yarn try-rs && yarn try-js && yarn try-ir",
|
|
22
|
-
"try-rs": "cargo run --bin cr -- calcit/test.cirru
|
|
23
|
-
"warn-dyn-method": "cargo run --bin cr -- calcit/test.cirru
|
|
24
|
-
"try-js-brk": "cargo run --bin cr -- calcit/test.cirru
|
|
25
|
-
"try-js": "cargo run --bin cr -- calcit/test.cirru
|
|
26
|
-
"try-ir": "cargo run --bin cr -- calcit/test.cirru
|
|
22
|
+
"try-rs": "cargo run --bin cr -- calcit/test.cirru",
|
|
23
|
+
"warn-dyn-method": "cargo run --bin cr -- calcit/test.cirru --warn-dyn-method",
|
|
24
|
+
"try-js-brk": "cargo run --bin cr -- calcit/test.cirru js && node --inspect-brk js-out/main.mjs",
|
|
25
|
+
"try-js": "cargo run --bin cr -- calcit/test.cirru js && node js-out/main.mjs",
|
|
26
|
+
"try-ir": "cargo run --bin cr -- calcit/test.cirru js"
|
|
27
27
|
},
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
package/ts-src/calcit.procs.mts
CHANGED
|
@@ -1560,6 +1560,93 @@ export let parse_cirru_edn = (code: string, options: CalcitValue) => {
|
|
|
1560
1560
|
}
|
|
1561
1561
|
};
|
|
1562
1562
|
|
|
1563
|
+
const json_to_calcit = (value: any): CalcitValue => {
|
|
1564
|
+
if (value == null) return null;
|
|
1565
|
+
if (typeof value === "string") return value;
|
|
1566
|
+
if (typeof value === "number") return value;
|
|
1567
|
+
if (typeof value === "boolean") return value;
|
|
1568
|
+
if (Array.isArray(value)) {
|
|
1569
|
+
return new CalcitSliceList(value.map(json_to_calcit));
|
|
1570
|
+
}
|
|
1571
|
+
if (typeof value === "object") {
|
|
1572
|
+
const entries: CalcitValue[] = [];
|
|
1573
|
+
for (const key of Object.keys(value)) {
|
|
1574
|
+
entries.push(newTag(key), json_to_calcit(value[key]));
|
|
1575
|
+
}
|
|
1576
|
+
return new CalcitSliceMap(entries);
|
|
1577
|
+
}
|
|
1578
|
+
throw new Error(`Unsupported JSON value: ${value}`);
|
|
1579
|
+
};
|
|
1580
|
+
|
|
1581
|
+
const calcit_json_key = (value: CalcitValue): string => {
|
|
1582
|
+
if (value instanceof CalcitTag) return value.value;
|
|
1583
|
+
if (typeof value === "string") return value;
|
|
1584
|
+
throw new Error(`json-stringify expected object keys to be tags or strings, got: ${toString(value, true)}`);
|
|
1585
|
+
};
|
|
1586
|
+
|
|
1587
|
+
const cirru_quote_to_json = (value: ICirruNode): any => {
|
|
1588
|
+
if (typeof value === "string") return value;
|
|
1589
|
+
if (Array.isArray(value)) return value.map(cirru_quote_to_json);
|
|
1590
|
+
throw new Error(`Unsupported cirru quote node: ${value}`);
|
|
1591
|
+
};
|
|
1592
|
+
|
|
1593
|
+
const calcit_to_json = (value: CalcitValue): any => {
|
|
1594
|
+
if (value == null) return null;
|
|
1595
|
+
if (typeof value === "string") return value;
|
|
1596
|
+
if (typeof value === "number") {
|
|
1597
|
+
if (Number.isFinite(value)) return value;
|
|
1598
|
+
throw new Error(`json-stringify cannot encode number: ${value}`);
|
|
1599
|
+
}
|
|
1600
|
+
if (typeof value === "boolean") return value;
|
|
1601
|
+
if (value instanceof CalcitTag) return value.value;
|
|
1602
|
+
if (value instanceof CalcitSymbol) return value.value;
|
|
1603
|
+
if (value instanceof CalcitList || value instanceof CalcitSliceList) {
|
|
1604
|
+
return Array.from(value.items()).map(calcit_to_json);
|
|
1605
|
+
}
|
|
1606
|
+
if (value instanceof CalcitSet) {
|
|
1607
|
+
return value.values().map(calcit_to_json);
|
|
1608
|
+
}
|
|
1609
|
+
if (value instanceof CalcitMap || value instanceof CalcitSliceMap) {
|
|
1610
|
+
const result: Record<string, any> = {};
|
|
1611
|
+
for (const [key, item] of value.pairs()) {
|
|
1612
|
+
result[calcit_json_key(key)] = calcit_to_json(item);
|
|
1613
|
+
}
|
|
1614
|
+
return result;
|
|
1615
|
+
}
|
|
1616
|
+
if (value instanceof CalcitTuple) {
|
|
1617
|
+
return [calcit_to_json(value.tag), ...value.extra.map(calcit_to_json)];
|
|
1618
|
+
}
|
|
1619
|
+
if (value instanceof CalcitCirruQuote) {
|
|
1620
|
+
return cirru_quote_to_json(value.value as ICirruNode);
|
|
1621
|
+
}
|
|
1622
|
+
if (value instanceof CalcitRecord) {
|
|
1623
|
+
const result: Record<string, any> = {};
|
|
1624
|
+
for (let idx = 0; idx < value.fields.length; idx++) {
|
|
1625
|
+
result[value.fields[idx].value] = calcit_to_json(value.values[idx]);
|
|
1626
|
+
}
|
|
1627
|
+
return result;
|
|
1628
|
+
}
|
|
1629
|
+
throw new Error(`json-stringify cannot encode value: ${toString(value, true)}`);
|
|
1630
|
+
};
|
|
1631
|
+
|
|
1632
|
+
export let json_parse = function (code: CalcitValue): CalcitValue {
|
|
1633
|
+
if (arguments.length !== 1) throw new Error("json-parse expected 1 argument");
|
|
1634
|
+
if (typeof code !== "string") {
|
|
1635
|
+
throw new Error(`json-parse expected a string, got: ${toString(code, true)}`);
|
|
1636
|
+
}
|
|
1637
|
+
return json_to_calcit(JSON.parse(code));
|
|
1638
|
+
};
|
|
1639
|
+
|
|
1640
|
+
export let json_stringify = function (value: CalcitValue): string {
|
|
1641
|
+
if (arguments.length !== 1) throw new Error("json-stringify expected 1 argument");
|
|
1642
|
+
return JSON.stringify(calcit_to_json(value));
|
|
1643
|
+
};
|
|
1644
|
+
|
|
1645
|
+
export let json_pretty = function (value: CalcitValue): string {
|
|
1646
|
+
if (arguments.length !== 1) throw new Error("json-pretty expected 1 argument");
|
|
1647
|
+
return JSON.stringify(calcit_to_json(value), null, 2);
|
|
1648
|
+
};
|
|
1649
|
+
|
|
1563
1650
|
export let format_to_lisp = (x: CalcitValue): string => {
|
|
1564
1651
|
if (x == null) {
|
|
1565
1652
|
return "nil";
|