@calcit/procs 0.13.43 → 0.13.45

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.
Files changed (83) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/RFCs/04-15-match-syntax-rfc.md +14 -8
  3. package/RFCs/04-15-type-directed-optimization-catalog.md +20 -14
  4. package/RFCs/08-05-systematic-nil-reduction-rfc.md +16 -5
  5. package/editing-history/20260824-2119-validate-number-call-metadata.md +8 -0
  6. package/editing-history/20260824-2155-stable-js-struct-layout.md +11 -0
  7. package/editing-history/20260824-2224-struct-index-review-followups.md +7 -0
  8. package/editing-history/20260824-2233-indexed-struct-js-regressions.md +5 -0
  9. package/editing-history/20260824-2256-dynamic-method-analysis.md +9 -0
  10. package/editing-history/20260824-2329-dynamic-method-review-followups.md +7 -0
  11. package/editing-history/202608241731-contiguous-executable-calls.md +34 -0
  12. package/editing-history/202608241920-borrowed-syntax-arguments.md +34 -0
  13. package/editing-history/202608241924-unify-editing-history-directory.md +7 -0
  14. package/editing-history/202608242013-typed-native-number-ops.md +34 -0
  15. package/editing-history/20260825-0020-indexed-enum-match.md +34 -0
  16. package/editing-history/20260825-0100-indexed-enum-match-validation.md +7 -0
  17. package/editing-history/20260825-0120-indexed-enum-match-review.md +7 -0
  18. package/editing-history/20260825-1215-typed-literal-paths.md +56 -0
  19. package/editing-history/20260825-1344-typed-literal-path-review.md +17 -0
  20. package/editing-history/20260825-1505-typed-method-native-op.md +23 -0
  21. package/editing-history/20260825-1540-nil-unit-runtime-separation.md +15 -0
  22. package/editing-history/20260825-1725-typed-method-error-stack-review.md +10 -0
  23. package/editing-history/20260825-1733-nil-unit-doc-review.md +5 -0
  24. package/editing-history/20260825-1758-nil-unit-review-followup.md +6 -0
  25. package/editing-history/20260825-1845-release-01344.md +6 -0
  26. package/editing-history/20260825-2121-macro-parameter-diagnostics.md +10 -0
  27. package/editing-history/20260825-2138-keep-malformed-macro-params-hard.md +5 -0
  28. package/editing-history/20260825-2311-macro-capability-review-followup.md +10 -0
  29. package/editing-history/20260825-2312-macro-expansion-metrics.md +11 -0
  30. package/editing-history/20260825-2337-macro-query-and-capability-scope.md +11 -0
  31. package/editing-history/20260825-2338-core-structural-macro-contracts.md +10 -0
  32. package/editing-history/20260825-2356-delayed-macro-metrics-review.md +5 -0
  33. package/editing-history/202608252220-phase-aware-macro-signatures.md +35 -0
  34. package/editing-history/202608252249-macro-compile-time-capabilities.md +27 -0
  35. package/editing-history/20260826-0007-assertion-macro-contracts.md +8 -0
  36. package/editing-history/20260826-0023-assertion-macro-review.md +4 -0
  37. package/editing-history/20260826-0038-control-flow-macro-contracts.md +9 -0
  38. package/editing-history/20260826-0100-review-exact-control-flow-contracts.md +5 -0
  39. package/editing-history/20260826-0120-pattern-macro-contracts.md +8 -0
  40. package/editing-history/20260826-0133-collection-macro-contracts.md +9 -0
  41. package/editing-history/20260826-0152-definition-macro-contracts.md +25 -0
  42. package/editing-history/20260826-0203-transform-macro-contracts.md +28 -0
  43. package/editing-history/20260826-0214-binding-update-macro-contracts.md +14 -0
  44. package/editing-history/20260826-0629-type-observability-macros.md +8 -0
  45. package/editing-history/20260826-0642-type-remaining-match-macros.md +7 -0
  46. package/editing-history/20260826-0654-macro-log-capability.md +8 -0
  47. package/editing-history/20260826-0707-release-01345.md +6 -0
  48. package/examples/bench_enum_match.rs +41 -0
  49. package/lib/calcit-data.d.mts +4 -0
  50. package/lib/calcit-data.mjs +59 -9
  51. package/lib/calcit.procs.d.mts +16 -8
  52. package/lib/calcit.procs.mjs +68 -46
  53. package/lib/custom-formatter.mjs +12 -3
  54. package/lib/js-cirru.mjs +6 -5
  55. package/lib/js-impl.mjs +4 -3
  56. package/lib/js-primes.d.mts +1 -1
  57. package/lib/js-primes.mjs +22 -18
  58. package/lib/js-struct-def.mjs +4 -6
  59. package/lib/js-struct-value.d.mts +5 -1
  60. package/lib/js-struct-value.mjs +66 -38
  61. package/lib/package.json +8 -2
  62. package/package.json +8 -2
  63. package/ts-src/calcit-data.mts +54 -9
  64. package/ts-src/calcit.procs.mts +66 -49
  65. package/ts-src/custom-formatter.mts +12 -3
  66. package/ts-src/js-cirru.mts +6 -5
  67. package/ts-src/js-impl.mts +4 -3
  68. package/ts-src/js-primes.mts +5 -1
  69. package/ts-src/js-struct-def.mts +4 -6
  70. package/ts-src/js-struct-value.mts +78 -33
  71. /package/{history → editing-history}/202608191501-release-01326.md +0 -0
  72. /package/{history → editing-history}/202608191628-revert-transparent-union-types.md +0 -0
  73. /package/{history → editing-history}/202608191741-release-01327.md +0 -0
  74. /package/{history → editing-history}/202608212020-release-01328.md +0 -0
  75. /package/{2026082200-release-01330.md → editing-history/2026082200-release-01330.md} +0 -0
  76. /package/{2026082200-same-package-module-meta.md → editing-history/2026082200-same-package-module-meta.md} +0 -0
  77. /package/{2026082200-transitive-module-loading.md → editing-history/2026082200-transitive-module-loading.md} +0 -0
  78. /package/{2026082222-release-01331.md → editing-history/2026082222-release-01331.md} +0 -0
  79. /package/{history → editing-history}/2026082223-release-01332.md +0 -0
  80. /package/{history → editing-history}/2026082223-same-package-namespaces.md +0 -0
  81. /package/{history → editing-history}/2026082300-fix-cross-package-namespace-merge.md +0 -0
  82. /package/{history → editing-history}/2026082300-release-01333.md +0 -0
  83. /package/{history → editing-history}/2026082316-release-01334.md +0 -0
Binary file
@@ -127,20 +127,26 @@ missing = all_variants - covered_tags
127
127
 
128
128
  ## 6. JS 代码生成
129
129
 
130
- 生成立即执行函数表达式(IIFE):
130
+ 动态或无法安全重排的 match 保留立即执行函数中的 if-else 链。静态已知 enum 且分支没有重复 tag、wildcard 位于末尾时,预处理器会生成内部 declaration-order branch table;JS codegen 对该形式生成 `switch (tag.idx)`,native evaluator 通过 enum definition 的 variant index 直接选择 slot。这个内部表示不增加用户语法,匿名 enum 和动态边界仍使用兼容路径。
131
+
132
+ 概念上的 JS 输出如下:
131
133
 
132
134
  ```javascript
133
135
  (() => {
134
136
  let match_v = <value>;
135
137
  let match_t = _$n_tuple_$o_nth(match_v, 0);
136
- if (match_t === _kn_ok && _$n_tuple_$o_count(match_v) === 1) {
137
- return kwd_$o_success; // (:ok) :success
138
- } else if (match_t === _kn_err && _$n_tuple_$o_count(match_v) === 2) {
139
- let msg = _$n_tuple_$o_nth(match_v, 1);
140
- return msg; // (:err msg) msg
141
- } else {
142
- throw new Error("match: no matching branch for tag");
138
+ switch (match_t.idx) {
139
+ case _kn_ok.idx:
140
+ if (_$n_tuple_$o_count(match_v) === 1) return kwd_$o_success;
141
+ break;
142
+ case _kn_err.idx:
143
+ if (_$n_tuple_$o_count(match_v) === 2) {
144
+ let msg = _$n_tuple_$o_nth(match_v, 1);
145
+ return msg;
146
+ }
147
+ break;
143
148
  }
149
+ throw new Error("match: no matching branch for tag");
144
150
  })()
145
151
  ```
146
152
 
@@ -71,30 +71,33 @@
71
71
 
72
72
  ---
73
73
 
74
- ### P3: `tag-match` 分支整数化 推迟(侵入性大,CalcitTuple 12+ 构造点需改动)
74
+ ### P3: 已知 enum 的 `match` 分支索引化 #422
75
75
 
76
- **问题**: `tag-match` 运行时用 tag 字符串逐一比较(线性扫描分支)。JS codegen 也是 if-else 链。
76
+ **问题**: 原生 `match` 虽然保留了 enum 类型和分支结构,native 运行时仍逐项比较 tagJS codegen 也输出 if-else 链。旧目录将其写成 `tag-match` 优化,但该宏展开后已经丢失结构;真正可安全优化的是原生 `match`。
77
77
 
78
- **位置**: `src/builtins/syntax.rs` L933-1050(runner),`src/codegen/emit_js.rs` L897-978(JS codegen)。
78
+ **实际方案**:
79
79
 
80
- **方案**:
80
+ - 预处理器仅在 enum 类型已知、tag 不重复、wildcard 位于末尾时,生成内部 declaration-order branch table;
81
+ - native 复用 `CalcitEnumDef` 已有的 tag→variant HashMap,一次查找后直接选择 branch slot;
82
+ - JS 对同一内部表示生成 `switch (tag.idx)`;
83
+ - WASM 继续消费其已有整数 tag,并兼容 branch table 表示;
84
+ - 动态/匿名 enum、重复 tag、early wildcard 保留原始线性表示和语义。
81
85
 
82
- - **Rust 端**: enum 类型已知时预处理阶段把 tag 比较替换为 `variant_index` 的整数比较
83
- - **JS 端**: emit `switch (tag.idx)` 替代 if-else 链
86
+ 没有给 `CalcitEnumValue` 新增字段,也没有增加用户语法,因此避免修改所有 enum 构造和序列化边界。
84
87
 
85
- **收益**: 5+ 分支时 O(n) O(1)
88
+ **收益**: native O(branches) 降为平均 O(1) branch selection;JS 由引擎整数 switch 分派。
86
89
 
87
90
  **影响**: 中 — 状态机、消息路由场景(Cumulo updater dispatcher)明显加速。
88
91
 
89
92
  ---
90
93
 
91
- ### P4: Method dispatch 静态绑定 推迟(复杂度高,待类型覆盖率提高)
94
+ ### P4: Method dispatch 静态绑定 #426
92
95
 
93
96
  **问题**: `.method obj` 运行时路径:① 匹配 receiver 类型 → ② 查 impl 列表(builtin 还要 evaluate symbol)→ ③ 线性遍历 `impls` 数组找方法名。
94
97
 
95
98
  **位置**: `src/builtins/meta.rs` L1016-1095,`method_call_impls` 函数。
96
99
 
97
- **方案**: 预处理阶段 receiver 类型和 trait 均已知时,直接解析到 `CalcitFn`/`CalcitProc`,把 `.method obj args` 重写为 `(resolved-fn obj args)`。
100
+ **实际方案**: 预处理阶段 receiver 类型和 impl precedence 已知时,已有的 `try_inline_method_call` 会直接解析到稳定的 top-level callable 或 `CalcitProc`,把 `.method obj args` 重写为 `(resolved-fn obj args)`;Dynamic receiver、无法安全保留 closure 身份的 method entry 继续运行时 dispatch。#426 补齐了静态绑定后的 executable call metadata,使 `.add`、`.multiply`、`.rem` 等 resolved proc 还能进入 typed native number fast path,并把 remainder 纳入该 fast path。runtime 在执行 metadata 前仍校验实际 proc,hot reload 或 host interop 使静态证据过期时退回普通错误路径。
98
101
 
99
102
  **收益**: 消除 symbol resolution + linear impl search。
100
103
 
@@ -118,11 +121,13 @@
118
121
 
119
122
  ---
120
123
 
121
- ### P6: `get-in` / `assoc-in` 静态路径展开
124
+ ### P6: `get-in` / `assoc-in` 静态路径展开 ✅ #424
122
125
 
123
126
  **问题**: `get-in base [:a :b :c]` 是 Calcit 编写的递归函数(`calcit-core.cirru`),每层递归拆列表 + 动态 `get`。
124
127
 
125
- **方案**: 路径是字面量列表且 base 类型已知 Record 时,编译期展开为嵌套 `&record:nth`。`assoc-in` 同理展开为嵌套的 `&record:assoc-at`。
128
+ **方案**: 路径是非空字面量列表,且 base 与每个需要继续遍历的中间 payload 都有非 Dynamic 静态类型时,在预处理阶段展开。`get-in` 的最终 payload 可以是 Dynamic,展开结果仍为对应的 `Option`;`assoc-in` 第一阶段只接受全 Map 路径,并额外要求最终 payload 非 Dynamic,再展开为逐层 `&map:contains?`、`&map:get`、`&map:assoc`。Dynamic collection hop、混合容器、空路径以及任何进入 Struct 的路径继续调用原函数。`get-in` 展开保留 `%some` / `%none`、nil 短路与逐层 Struct guard。
129
+
130
+ 旧方案中沿 Record/Struct 字段展开的设想已经废弃。公开 `get-in` / `assoc-in` 明确不遍历 Struct;必填字段继续使用 `(:field value)` 与直接 `assoc`,不能借性能优化绕开名义类型检查。
126
131
 
127
132
  **收益**: 消除递归、list 分解、运行时字段查找。
128
133
 
@@ -162,9 +167,10 @@
162
167
  | 4 | P2 | `0e705f1` | NativeRecordWithAt 批量索引化 | Record 批量更新加速(fibo 不涉及) |
163
168
  | 5 | P7 | `fa325c6` | if 常量折叠 | 宏展开场景受益 |
164
169
  | - | 额外 | `7c04880` | runtime def resolution 去重复 RwLock 读 | 微优化 |
170
+ | 6 | P3 | #422 | typed `match` branch table + JS switch | enum dispatcher / state machine |
171
+ | 7 | P6 | #424 | typed literal collection path expansion | nested map/list lookup and map update |
172
+ | 8 | P4 | #426 | static method calls retain native op metadata | typed remainder loop ~11% faster |
165
173
 
166
174
  ### 待定
167
175
 
168
- - **P3**: tag-match 整数化 推迟,CalcitTuple 12+ 构造点需改动,侵入性大
169
- - **P4**: Method dispatch 静态绑定 — 推迟,实现复杂度高
170
- - **P6**: get-in/assoc-in 静态路径展开 — 未开始,视实际瓶颈决定
176
+ - 在最新 Respo/Recollect 工作负载上继续 profiling;后续项目以实测热点为准,不再预设广泛 unboxing 或关闭 Dynamic 边界。
@@ -25,7 +25,7 @@
25
25
  - 名称以 `&` 开头的 raw primitive 属于 semver-private 实现细节,允许在内部使用 nullable 表示,但不得直接挂入公开方法表;
26
26
  - 已生成 JS bundle 引用的 npm runtime export 属于 codegen ABI:typed wrapper/raw proc 改名时必须保留兼容 export,并由 runtime identity test 覆盖;类型系统负责阻断重新编译的旧 FFI 源码,但不能替代旧 bundle 的装载兼容性;
27
27
  - 新增查询 API 不得先返回 nil、再在后续版本改成 Option。类型和所有后端实现必须在首次发布时一致;
28
- - `analyze weak-types --only code-nil --intent unresolved,declared-optional` 必须对 core 返回零结果;
28
+ - `analyze weak-types --only code-nil --intent unresolved,declared-unit,declared-optional` 必须对 core 返回零结果;
29
29
  - 以后若要改变这些名义返回类型,只能作为独立的非 nil 设计变更处理,不能再以“清理遗留 nil”为由制造连续 breaking change。
30
30
 
31
31
  本次最终迁移表:
@@ -48,7 +48,7 @@
48
48
 
49
49
  - `CalcitTypeAnnotation::Optional(T)` 能表达 `T | nil`;
50
50
  - `CalcitTypeAnnotation::JsNullish(T)` 独立表达 JavaScript 宿主空值,不与 Optional/Option 相互匹配;
51
- - `nil` 推断为 `Unit`,且 `Unit` 可以匹配 `Optional<T>`;
51
+ - `nil` `Unit` 过去共享静态表示,导致声明为 `Unit` 的副作用函数仍可能实际返回 nil;
52
52
  - `nil?` / `some?` 已支持分支内的 Optional 类型收窄;
53
53
  - core 已定义 `Option<T>`、`Result<T, E>` 及基本组合函数;
54
54
  - `get` 对 List、Map 和 String 已采用可能缺失的返回推断。
@@ -64,7 +64,7 @@
64
64
 
65
65
  ### Unit
66
66
 
67
- `Unit` 只用于副作用操作或明确没有有意义返回值的表达式,例如写文件、注册 watcher。新代码显式返回 `&unit`;它与 `nil` 不相等、不会通过 `nil?`,JavaScript 后端生成 `void 0`(而 `nil` 仍生成 `null`)。为了兼容既有代码,标注为 `Unit` 的位置仍可接受旧的 `nil`,而 `;nil` 也保留为旧的兼容宏;新业务代码不得把两者当 Unit 标记或缺失值容器。
67
+ `Unit` 只用于副作用操作或明确没有有意义返回值的表达式,例如写文件、注册 watcher。新代码显式返回 `&unit`;它与 `nil` 不相等、不会通过 `nil?`,JavaScript 后端生成 `void 0`(而 `nil` 仍生成 `null`)。`Unit` 标注不再接受 nil;`nil` 具有独立的 `Nil` 静态类型,并且只有 Nil 可以进入遗留 `Optional<T>`。`;nil` 保留为返回 Nil 的兼容宏,不能用作 Unit 标记;副作用函数应以 `&unit` 或最终得到 Unit 的 `do` 收尾。
68
68
 
69
69
  ### Optional<T>(遗留内部表示)
70
70
 
@@ -97,7 +97,7 @@ JS FFI 是无法立即消除的宿主空值边界。原生属性读取、方法
97
97
  - 将底层 `&parse-float` 和 `&get-env` proc 的 nullable 返回标成 Optional,作为公开名义 API 之下的兼容边界;
98
98
  - 将 `rest` / `butlast` 对空 List 的结果统一为同类型空 List,并同步 Native、JS、WASM;`rest` 与 `empty` 的公开契约改为 `T -> T`,因此确定存在的集合/String 不再被无条件提升为 Optional,而显式 Optional/nil 输入仍保留其可空类型;
99
99
  - 公开 core 的 `first`、`last`、`nth`、`get`、`get-in` schema 返回名义 `Option`;内部 `&list:first`、`&list:nth`、`&map:get` 等 raw primitive 保留 nullable 表示并标记为 internal;
100
- - `analyze weak-types` 将裸 `nil` 与 `;nil` 都纳入审计,仅在结构上可证明的返回位置读取函数契约,并区分 `declared-unit`、`declared-optional` 与 `unresolved`;JSON 对后两类迁移债务发出 `W_NIL_TYPE_DEBT`;
100
+ - `analyze weak-types` 将裸 `nil` 与 `;nil` 都纳入审计,仅在结构上可证明的返回位置读取函数契约,并区分 `declared-unit`、`declared-optional` 与 `unresolved`;三类都属于迁移债务并由 JSON 发出 `W_NIL_TYPE_DEBT`;
101
101
  - `analyze.weak-types` 的机器协议升级到 schema v2,避免旧消费者在 v1 下错误接受新增的封闭 intent/diagnostic 枚举;
102
102
  - 修正既有 `optionally` 桥接函数的契约为 `Optional<T> -> Option<T>`,为遗留 nullable 边界提供不丢失类型关系的显式出口;
103
103
  - 为上述规则增加单元测试。
@@ -106,7 +106,7 @@ Phase 1 的类型契约修正本身不改变相关过程的运行时返回值;
106
106
 
107
107
  低层专用推断不能通过批量 `unsafe-coerce` 清理:core 宏在检查列表形状后读取 AST,当前类型系统尚不能携带“非空列表”及 guard clause 终止证据。此类宏改用明确的 `&` raw primitive;公开包装器始终保留 Option 外层,不把内部 nullable 表示扩散成 API。
108
108
 
109
- nil 审计也坚持证据边界:返回的 `do` 只有最后一项继承返回契约,返回的 `if` 只有结果分支继承契约;中间步骤、集合内容和尚未建模的控制流仍标成 `unresolved`。`declared-unit` 不计入迁移债务,`declared-optional` 则继续提示迁移到 Option/Result。
109
+ nil 审计也坚持证据边界:返回的 `do` 只有最后一项继承返回契约,返回的 `if` 只有结果分支继承契约;中间步骤、集合内容和尚未建模的控制流仍标成 `unresolved`。`declared-unit` 提示改为真正的 `&unit`,`declared-optional` 则继续提示迁移到 Option/Result。
110
110
 
111
111
  ### Phase 2:建立名义安全 API
112
112
 
@@ -141,6 +141,17 @@ core 自举宏已经迁到明确的 `&` raw primitive,公开 `first`、`last`
141
141
  - Optional 仅由迁移工具与 internal raw primitive 识别;公开 schema 由稳定诊断阻断;
142
142
  - 审计 JS/WASM 后端,确保名义类型的表示和分支行为一致。
143
143
 
144
+ ### Phase 5:Nil / Unit 运行时与 ABI 分离
145
+
146
+ - 为 `nil` 增加独立的 `Nil` 类型标注,禁止其匹配 `Unit`,同时保留 Nil 到遗留 `Optional<T>` 的关系;
147
+ - Native effect proc 返回真实 Unit;有意义的 mutation(例如 `reset!`)保留并声明其写入值,而不是伪造 Unit;
148
+ - JavaScript 后端用 `null` 表示 Nil、用 `undefined` 表示 Unit,并在相等、哈希、格式化、类型反射和 typed decode 中保持二者可区分;
149
+ - data-shape ABI 增加独立 Nil 节点并升级版本,防止旧 runtime 静默把 Nil 当 Unit;Cirru EDN 和 JSON 均拒绝序列化 Unit;
150
+ - `;nil` 的零参数 hint form 必须生成真正的 Nil 返回;`assert-type` / `assert-traits` 在 JS 中保留被断言的值;
151
+ - 对 js-ffi、Respo 与 Recollect 做组合验证,只迁移明确的 effect tail;DOM 缺失、宿主 nullish 和框架动态边界不机械替换。
152
+
153
+ 实施跟踪见 [#428](https://github.com/calcit-lang/calcit/issues/428) 与 [#429](https://github.com/calcit-lang/calcit/issues/429)。
154
+
144
155
  ## 类型提示修复策略
145
156
 
146
157
  迁移应优先给出局部、可机械执行的建议:
@@ -0,0 +1,8 @@
1
+ # Validate specialized number-call metadata
2
+
3
+ - Guard the native NumberBinary fast path with the stored proc identity, so a
4
+ manually constructed executable call with stale or mismatched metadata uses
5
+ ordinary dispatch rather than a different arithmetic operation.
6
+ - Classify the small supported native-proc set before resolving argument types,
7
+ keeping all other calls off the specialization analysis path.
8
+ - Rename the function-hint regression to describe its compile-time-only role.
@@ -0,0 +1,11 @@
1
+ # Stable JavaScript Struct layout
2
+
3
+ - Align JavaScript Struct, Enum, and implementation metadata ordering with native lexical tag-name ordering.
4
+ - Make typed JS Struct reads and updates consume their precomputed field indices while retaining field-tag consistency checks.
5
+ - Canonicalize Cirru EDN Struct field/value pairs during parsing so serialized data adopts the same layout.
6
+ - Cover reversed tag-registration order and invalid indexed access in the JavaScript runtime regression suite.
7
+ - Add `yarn bench-struct-index` to compare the previous tag-lookup codegen path with indexed access plus its schema-drift check.
8
+ - Normalize paired metadata in exported JS Struct, StructDef, and Impl constructors for compatibility with older runtime values.
9
+ - Align native `&struct:nth` index/tag validation and empty JS `with-at` arity errors with the indexed update primitives.
10
+
11
+ Focused JS benchmark on Apple arm64 / Node 24.4.1, 5,000,000 reads over a 32-field Struct (three runs): tag lookup median 574.51 ms; indexed access with field-tag validation median 37.56 ms (~15.3x faster). Native indexed Struct access is unchanged by this JS-only runtime/codegen optimization.
@@ -0,0 +1,7 @@
1
+ # Struct index review follow-ups
2
+
3
+ - Reused native struct index validation for reads, including exact numeric indices and optional field-tag checks.
4
+ - Canonicalized paired struct metadata at exported JavaScript constructor boundaries so legacy or external callers cannot create unsorted field/value layouts.
5
+ - Aligned JavaScript `withAt` arity validation with the native runtime.
6
+ - Added reverse-registration EDN, legacy metadata, stale-tag, fractional-index, and empty-update regressions.
7
+ - Re-ran the full Rust, Calcit, JavaScript, IR, WASM, and agent-interface validation suites.
@@ -0,0 +1,5 @@
1
+ # Indexed Struct JavaScript regressions
2
+
3
+ - Covered fractional indices in JavaScript indexed Struct reads.
4
+ - Covered stale field tags in JavaScript indexed `assocAt` and `withAt` updates.
5
+ - Kept the regression matrix aligned with native indexed Struct validation.
@@ -0,0 +1,9 @@
1
+ # Dynamic method analysis
2
+
3
+ - Added `analyze dynamic-methods` to inventory unresolved method dispatch without mixing in unrelated preprocessing warnings.
4
+ - Added stable codes for prefix and postfix dynamic dispatch findings.
5
+ - Added project-only default scope, opt-in dependency scope, deterministic de-duplication, JSON and summary output.
6
+ - Added `--max` as an incremental CI performance policy for existing typed projects.
7
+ - Verified the initial project-only inventory against current Respo and Recollect main branches.
8
+ - Respo reports 8 project findings and passes a reviewed `--max 8`; Recollect reports 0 project findings and 4 reachable dependency findings.
9
+ - Respo native tests pass 25/25 and Recollect native tests pass 9/9 with the installed branch build.
@@ -0,0 +1,7 @@
1
+ # Dynamic method analysis review follow-ups
2
+
3
+ - Documented the accepted `text` output alias and advertised `dynamic-methods` in parent CLI help.
4
+ - Preserved every imprecisely located generated warning while still de-duplicating warnings with exact Snapshot coordinates.
5
+ - Added a module-backed CLI fixture proving project-only and reachable dependency scopes end to end.
6
+ - Strengthened the policy smoke test to require individual finding rows.
7
+ - Updated the upgrade CI template, checklist, and troubleshooting matrix to use the focused dynamic-method policy.
@@ -0,0 +1,34 @@
1
+ # Contiguous executable calls
2
+
3
+ ## Summary
4
+
5
+ - Keep immutable ordinary proc, function, and method call nodes in
6
+ `CalcitList::Vector` after preprocessing instead of rebuilding them as
7
+ persistent `TernaryTreeList` values.
8
+ - Preserve persistent storage for syntax calls because their runtime handlers
9
+ still rely on cheap structural `skip` operations.
10
+ - Leave quoted and runtime List values untouched; the optimization is confined
11
+ to the result of preprocessing executable non-syntax calls.
12
+ - Cover nested ordinary calls and the syntax/quote boundary with representation
13
+ regression tests.
14
+
15
+ ## Performance notes
16
+
17
+ - A broader prototype that also converted syntax calls regressed a 200,000
18
+ iteration tail loop by about 6%, since `CalcitList::skip` rebuilt a persistent
19
+ tail from the Vector on every `if` evaluation. A borrowed syntax-argument view
20
+ is required before that representation can change safely.
21
+ - On five release runs of the same 1,000,000-iteration loop, the retained
22
+ ordinary-call-only change reduced median internal runtime from 7,810.963 ms
23
+ to 6,998.677 ms (~10.4%) and median user CPU from 7.23 s to 6.95 s (~3.9%).
24
+
25
+ ## Validation
26
+
27
+ - `cargo fmt --all -- --check`
28
+ - `cargo test -q`
29
+ - `cargo clippy --all-targets -- -D warnings`
30
+ - `yarn compile`
31
+ - `yarn check-agent-interface`
32
+ - `yarn check-all`
33
+ - Current `calcit-lang/recollect` and `Respo/respo.calcit` main heads, including
34
+ native/JS tests, Respo production build, and real-browser interaction.
@@ -0,0 +1,34 @@
1
+ # Borrowed syntax arguments
2
+
3
+ ## Context
4
+
5
+ After ordinary executable calls moved to contiguous `CalcitList::Vector` storage, syntax dispatch still built a persistent tail with `skip(1)` on every evaluation. Converting syntax roots to vectors before changing that API regressed hot loops because each syntax call reconstructed a list.
6
+
7
+ ## Changes
8
+
9
+ - Added `CalcitListView`, a borrowed read-only range over either vector or persistent list storage.
10
+ - Routed `call_expr`, argument evaluation, syntax dispatch, and ref syntax handlers through borrowed views.
11
+ - Kept allocation explicit with `to_vec` only where owned stack/error data or function bodies require it.
12
+ - Normalized all preprocessed executable call roots, including syntax calls, to contiguous storage while preserving quoted list values.
13
+ - Added view coverage for both storage backends, nested skips, iteration, indexing, and invalid bounds; updated preprocessing representation coverage.
14
+
15
+ ## Performance
16
+
17
+ The release benchmark runs a two-argument tail-recursive loop for 1,000,000 iterations and returns `500000500000`.
18
+
19
+ - `main` (`1ef20077`) internal median: 7,062.173 ms; user CPU median: 7.06 s.
20
+ - This change internal median: 5,920.961 ms; user CPU median: 6.00 s.
21
+ - Improvement: 16.2% internal runtime and 15.0% user CPU.
22
+
23
+ ## Validation
24
+
25
+ - `cargo fmt --all -- --check`
26
+ - `cargo clippy --all-targets -- -D warnings`
27
+ - `cargo test -q`
28
+ - `yarn compile`
29
+ - `yarn check-agent-interface`
30
+ - `yarn check-all`
31
+ - Latest Recollect `a694d4c`: native tests 9/9, test-entry JS generation and Node runtime passed. Its default entry retains the same four pre-existing dependency type warnings.
32
+ - Latest Respo `ead78c3`: tests 25/25, JS generation and Vite production build passed. Browser Todo interaction added one task and produced zero console errors.
33
+
34
+ The downstream Dynamic coverage remains unchanged at 204/405 (50.4%) for Recollect and 284/1034 (27.5%) for Respo.
@@ -0,0 +1,7 @@
1
+ # Unify editing history storage
2
+
3
+ - Moved the remaining timestamped history notes from the repository root and legacy `history/` directory into `editing-history/`.
4
+ - Renamed `Agents.md` to the conventional `AGENTS.md` filename.
5
+ - Documented `editing-history/` as the single required destination for future per-commit notes.
6
+
7
+ Keeping one directory prevents validation tools and contributors from repeatedly migrating the same files and makes the historical index predictable.
@@ -0,0 +1,34 @@
1
+ # Typed native number operations
2
+
3
+ ## Context
4
+
5
+ Typed functions carried an injected one-argument `hint-fn` form in their native runtime body. Tail recursion therefore re-evaluated compile-time metadata on every iteration. Native calls also discarded proven `Number` argument types before evaluation and rebuilt a temporary argument vector for the normal proc dispatcher.
6
+
7
+ ## Changes
8
+
9
+ - Capture surrounding-function `hint-fn` metadata in `CalcitFn`, then remove that one-argument form from the executable body. Targeted two-argument hints retain their runtime behavior.
10
+ - Add internal executable-call metadata that does not affect Calcit List equality, ordering, hashing, display, or language-level mutation behavior.
11
+ - Mark exact two-argument `&+`, `&-`, `&*`, `&/`, `&<`, and `&>` calls only when both processed arguments resolve to `Number`.
12
+ - Evaluate specialized arguments exactly once from left to right into a fixed two-value array, execute the numeric operation directly, and preserve the existing dynamic proc error path if static evidence becomes stale.
13
+ - Leave Dynamic, unresolved, wrong-arity, spread, JS, and WASM calls on their existing paths.
14
+
15
+ ## Performance
16
+
17
+ The release benchmark runs the same two-argument tail-recursive loop for 1,000,000 iterations.
18
+
19
+ - Typed pre-change internal median: 1,664.953 ms.
20
+ - Typed post-change internal median: 457.819 ms, a 72.5% reduction after removing runtime metadata evaluation and adding the specialized calls.
21
+ - On the post-change binary, the specialized typed loop median was 457.819 ms versus 483.450 ms for the otherwise identical Dynamic loop, a 5.3% typed fast-path improvement.
22
+
23
+ ## Validation
24
+
25
+ - `cargo fmt --all -- --check`
26
+ - `cargo clippy --all-targets -- -D warnings`
27
+ - `cargo test -q` (463 + 241 + 24 + 4 tests)
28
+ - `yarn compile`
29
+ - `yarn check-agent-interface` (13/13)
30
+ - `yarn check-all`, including native, JS, IR, and WASM checks
31
+ - Latest Recollect `a694d4c`: native tests 9/9; test-entry JS generation and Node runtime passed. Its default entry retains the same four pre-existing dependency type warnings.
32
+ - Latest Respo `ead78c3`: tests 25/25, JS generation, Vite production build, and a browser Todo interaction passed with zero console errors.
33
+
34
+ The downstream Dynamic boundaries remain observable rather than being forced static: Recollect reports 204/405 (50.4%) Dynamic type positions, and Respo reports 284/1034 (27.5%).
@@ -0,0 +1,34 @@
1
+ # Indexed enum match dispatch
2
+
3
+ ## Context
4
+
5
+ Issue #422 continues the performance roadmap after scoped dynamic-method diagnostics. Native `match` retained typed enum structure but still scanned branch tags, while JS emitted an if/else chain.
6
+
7
+ ## Changes
8
+
9
+ - Exposed the existing enum tag-to-variant declaration index.
10
+ - Rewrote statically known, semantics-safe `match` forms into an internal declaration-ordered branch table.
11
+ - Declined the rewrite for duplicate tags, unknown tags, or a wildcard before the final branch so source-order behavior stays unchanged.
12
+ - Selected native branches directly through the enum variant index.
13
+ - Emitted JS integer-tag `switch` dispatch for indexed matches.
14
+ - Kept WASM compatible with the internal table representation.
15
+ - Added focused table/codegen tests and native/JS comparison benchmarks.
16
+ - Updated the optimization catalog and native-match RFC.
17
+
18
+ ## Compatibility notes
19
+
20
+ - No user-facing syntax was added.
21
+ - `CalcitEnumValue` layout and all enum construction/serialization boundaries remain unchanged.
22
+ - Dynamic and anonymous enum matches retain the original linear representation.
23
+ - Runtime type, payload arity, wildcard, and no-match behavior remain explicit.
24
+
25
+ ## Validation plan
26
+
27
+ - `cargo fmt`
28
+ - `cargo clippy --all-targets -- -D warnings`
29
+ - `yarn compile`
30
+ - `cargo test`
31
+ - `yarn check-all`
32
+ - `yarn check-agent-interface`
33
+ - `yarn bench-enum-match`
34
+ - current Respo and Recollect main regression
@@ -0,0 +1,7 @@
1
+ # Indexed enum match validation fixes
2
+
3
+ - Fixed the release benchmark example to import internal Calcit value types from the public `calcit::calcit` module.
4
+ - Reduced the indexed JS match helper argument count and derived the wildcard slot from the internal table layout, keeping Clippy clean without changing generated semantics.
5
+ - Applied `cargo fmt` to the touched Rust code.
6
+ - Verified `cargo clippy -- -D warnings`, `cargo test`, `yarn compile`, `yarn check-all`, and `yarn check-agent-interface`.
7
+ - Measured the 16-variant last-branch benchmark at 291.55 ms for linear native tag scanning versus 108.35 ms for indexed lookup; the JS comparison measured 37.62 ms versus 31.06 ms.
@@ -0,0 +1,7 @@
1
+ # Indexed enum match review fixes
2
+
3
+ - Kept indexed JS match control flow inside an IIFE with real branch returns, so non-tail and assignment contexts cannot leak into wildcard or no-match handling after a successful case.
4
+ - Included the matched value expression in `js-await` detection while continuing to exclude nested function scopes.
5
+ - Added native runtime coverage for indexed branch selection and arity-mismatch wildcard fallback.
6
+ - Added JS codegen coverage for non-return labels and awaited matched values.
7
+ - Re-ran formatting, Clippy, Rust tests, TypeScript compilation, Agent interface checks, and the native/JS/WASM integration suite.
@@ -0,0 +1,56 @@
1
+ # Typed literal collection paths
2
+
3
+ ## Context
4
+
5
+ Issue #424 completes the last executable optimization in roadmap #409. Public
6
+ `get-in` and `assoc-in` are recursive Calcit functions, so literal paths still
7
+ paid for path-list traversal and dynamic dispatch even when type inference had
8
+ already proved every hop.
9
+
10
+ The public APIs deliberately reject Struct traversal. Static evidence must not
11
+ turn either API into an alternate Struct field accessor; required fields remain
12
+ `(:field value)` and direct `assoc` operations.
13
+
14
+ ## Changes
15
+
16
+ - Expand a non-empty literal `get-in` path only when the base and every
17
+ collection value that needs another traversal step are statically
18
+ non-Dynamic and no hop is a Struct. The final payload may remain Dynamic.
19
+ - Preserve single evaluation, nil short-circuiting, `%some` / `%none`, missing
20
+ keys, and an explicit Struct guard at every generated lookup hop.
21
+ - Expand `assoc-in` only for Map-only paths with a statically non-Dynamic final
22
+ payload in this first phase. Generated code uses direct map
23
+ contains/get/assoc primitives while retaining missing-map construction, nil
24
+ normalization, evaluation order, and Struct rejection.
25
+ - Keep empty paths, Dynamic or unknown hops, Struct boundaries, and mixed
26
+ `assoc-in` containers on the original recursive functions.
27
+ - Add a checked-in native/generated-JS comparison benchmark and update RFC P6
28
+ to the reconciled Struct-safe contract.
29
+
30
+ ## Measurements
31
+
32
+ The 100,000-operation release benchmark produced the same outputs for typed and
33
+ dynamic variants. The checked-in warm/sample driver measured native at 2.98 s
34
+ versus 5.48 s for read (~1.8x faster), and 1.68 s versus 5.02 s for write
35
+ (~3.0x faster). Generated JS medians were 33.9 ms versus 50.9 ms for read (~33%
36
+ faster), and 16.2 ms versus 696.0 ms for write (~43x faster). Run `yarn
37
+ bench-literal-paths` to reproduce the focused comparison.
38
+
39
+ ## Validation
40
+
41
+ - `cargo fmt --all`
42
+ - `cargo clippy --all-targets -- -D warnings`
43
+ - `cargo test`
44
+ - `yarn check-all`
45
+ - `yarn bench-literal-paths`
46
+ - current `calcit-lang/recollect` main: native tests 9/9 and generated test-entry
47
+ JS runtime passed
48
+ - current `Respo/respo.calcit` main: native tests 25/25, JS generation passed,
49
+ and the browser demo rendered without runtime errors when Vite was pointed at
50
+ this workspace's matching 0.13.43 JS runtime
51
+
52
+ The published downstream JS runtimes lagged the compiler during validation
53
+ (Recollect 0.13.19, Respo 0.13.40). Respo's default package therefore lacks the
54
+ new struct `nthAt` method until the matching runtime release is installed; no
55
+ downstream files were changed. Recollect's default demo build also retains four
56
+ pre-existing Respo dependency type warnings, while its own test entry passes.
@@ -0,0 +1,17 @@
1
+ # Typed literal path review follow-up
2
+
3
+ - Suppressed diagnostics only while reprocessing compiler-generated path
4
+ guards; original caller expressions are checked before specialization.
5
+ - Added return-type inference for preprocessed `match` forms so expanded
6
+ `get-in` retains its `Option<T>` result type.
7
+ - Allowed a Dynamic final `get-in` payload while retaining the stricter static
8
+ final-payload requirement for Map-only `assoc-in`.
9
+ - Expanded the runtime fixture to cover nil intermediates, stored Options,
10
+ indexed lookup, runtime Struct rejection, fallback behavior, and actual
11
+ path/replacement side-effect order on native and generated JS.
12
+ - Made `yarn bench-literal-paths` build the JS runtime, execute correctness
13
+ assertions, verify typed/dynamic structural equality, and report warm native
14
+ and generated-JS median samples.
15
+
16
+ Validation: `cargo fmt --all -- --check`, `cargo clippy --all-targets -- -D
17
+ warnings`, `cargo test`, `yarn check-all`, and `yarn bench-literal-paths`.
@@ -0,0 +1,23 @@
1
+ # Typed method native executable-op follow-up
2
+
3
+ - Updated performance roadmap issue #409 after #424/#425 merged and opened
4
+ #426 for the remaining static-method/native-op metadata gap.
5
+ - Confirmed that typed method binding already existed; the missing link was
6
+ rebuilding its resolved callable as an executable call with current
7
+ `CalcitCallKind` classification.
8
+ - Added native typed remainder execution while retaining proc-identity checks,
9
+ left-to-right single argument evaluation, and ordinary dynamic error
10
+ fallback for stale static evidence. The fast path reuses the normal
11
+ remainder implementation so its integer conversion and error behavior stay
12
+ identical.
13
+ - Added native/generated-JS correctness fixtures and warm/sample benchmarks for
14
+ typed method, intentionally Dynamic method, and direct proc forms.
15
+ - Against `main@159b4520`, the 500,000-iteration native medians changed from
16
+ 547.33 ms to 485.50 ms for typed `.rem` (~11.3% faster) and from 548.42 ms to
17
+ 500.36 ms for direct `&number:rem` (~8.8% faster). Dynamic dispatch remained
18
+ intentionally unspecialized. Generated JS typed/direct forms remained
19
+ equivalent and substantially faster than Dynamic dispatch.
20
+
21
+ Validation includes Rust formatting, clippy/tests, `yarn check-all`, the focused
22
+ benchmark, current upstream Recollect native/generated-JS runtime checks, and
23
+ Respo native tests plus generated-JS/Vite production build.
@@ -0,0 +1,15 @@
1
+ # Nil and Unit runtime separation
2
+
3
+ - Split the static `Nil` and `Unit` annotations: `nil` remains absence and
4
+ `&unit` is the only canonical no-result value.
5
+ - Aligned native effects, generated JavaScript, runtime identity, hashing,
6
+ formatting, typed data-shape decoding, and serialization boundaries with
7
+ that distinction; bumped the data-shape ABI to reject stale runtimes.
8
+ - Preserved `;nil` as a real Nil expression, normalized only missing safe JS
9
+ property/call results to Nil, and kept raw `aget` capable of observing Unit.
10
+ - Migrated explicit effect tails in js-ffi and Respo, then exercised Recollect
11
+ against all three local worktrees to protect dynamic framework behavior.
12
+
13
+ Validation: `cargo test`, `npm run compile`, `npm run check-js-runtime`, native
14
+ and generated-JS core suites, js-ffi Node/browser contracts, Respo tests/build,
15
+ and Recollect unit/JS/build checks.
@@ -0,0 +1,10 @@
1
+ # Typed method error-stack review
2
+
3
+ - Kept the typed number-binary fast path aligned with normal proc dispatch by
4
+ attaching the active call stack when a specialized operation returns an
5
+ otherwise stackless error.
6
+ - Added a regression test comparing invalid specialized and ordinary remainder
7
+ dispatch with stack tracking enabled.
8
+
9
+ Validation: `cargo fmt --all -- --check`, targeted runner tests, `cargo clippy
10
+ --all-targets -- -D warnings`, and `cargo test`.
@@ -0,0 +1,5 @@
1
+ # Nil / Unit documentation review
2
+
3
+ - Corrected the static-analysis type table after the runtime/type split.
4
+ - `Unit` is represented by `&unit` and no longer accepts `nil`.
5
+ - `Nil` is documented as a distinct legacy absence type.
@@ -0,0 +1,6 @@
1
+ # Nil / Unit review follow-up
2
+
3
+ - Kept zero-argument `(:: 'Nil)` forms as the builtin Nil annotation in both parser representations.
4
+ - Made the JavaScript console formatter render nested Unit values as `&unit` while preserving nested nil handling.
5
+ - Added parser, formatter, and typed-EDN Nil decoder regressions for the reviewed edge cases.
6
+ - Documented why transaction tests use package metadata: serialized format versions are normalized, so version mutations cannot exercise change detection.
@@ -0,0 +1,6 @@
1
+ # Release 0.13.44
2
+
3
+ - Separate canonical Unit from Nil across native, JavaScript, and WASM runtimes.
4
+ - Canonicalize effect primitive Unit contracts while preserving `reset!`'s written value.
5
+ - Add static migration diagnostics for legacy nil-as-Unit code and explicit host nullish boundaries.
6
+ - Include the typed literal collection and typed method native-operation performance improvements merged after 0.13.43.
@@ -0,0 +1,10 @@
1
+ # Macro parameter diagnostics and coverage
2
+
3
+ - Added one shared parameter-shape model for required, optional, and rest bindings, including malformed marker sequences. Both preprocessing and `analyze check-types` now use the same comparison and stable diagnostic codes.
4
+ - Preserved ordinary function compatibility: existing function schemas describe fixed arity without separately encoding the `?` marker. Strict optional-shape comparison is enabled for macros, while ordinary functions compare total fixed arity.
5
+ - Macro schema-shape mismatches remain staged during ecosystem migration. `analyze check-types` reports them by default; location-aware preprocessing warnings can be enabled with `CALCIT_WARN_MACRO_SCHEMA_SHAPE=1` and use `W_MACRO_SCHEMA_PARAM_SHAPE`.
6
+ - Corrected whole-`Dynamic` macro coverage from `Full` to `None`; explicitly typed macro schemas with Dynamic argument/result slots remain `Partial`. Explicit `:: Dynamic` now remains distinct from an omitted schema across binary serialization and reports `W_MACRO_SCHEMA_DYNAMIC`, while omission reports `W_SCHEMA_MISSING`.
7
+ - Same-command coverage baseline:
8
+ - Calcit core: overall `full/partial/none` changed from `420/107/18` to `405/107/33`; macros changed from `18/61/0` to `3/61/15`.
9
+ - Respo `respo.core`: overall changed from `12/53/1` to `7/53/6`; its five whole-`Dynamic` macros changed from `Full` to `None`.
10
+ - External regression used latest Respo 0.16.86 and Recollect 0.0.34. Respo required rebuilding `.calcit/modules` with `caps --ci` because its local `js-ffi` view was still at 0.1.9 despite `deps.cirru` declaring 0.1.10.
@@ -0,0 +1,5 @@
1
+ # Keep malformed macro parameters as hard errors
2
+
3
+ - Review identified that the staged macro-schema partition was too broad and also included `E_DEF_PARAM_SHAPE`.
4
+ - Only schema compatibility mismatches (`E_SCHEMA_REQUIRED_ARGS`, `E_SCHEMA_OPTIONAL_ARGS`, and `E_SCHEMA_REST_ARGS`) are now staged during ecosystem migration.
5
+ - Malformed source parameter sequences and schema-kind mismatches remain hard preprocessing errors.
@@ -0,0 +1,10 @@
1
+ # Macro capability review follow-up
2
+
3
+ - Keep the canonical strict Macro signature example complete by serializing an
4
+ explicit empty `:capabilities` set.
5
+ - Treat mutable BufList construction and mutation as `:mutable-state` during
6
+ macro expansion.
7
+ - Validate capability leaves as colon-prefixed tags before general Cirru EDN
8
+ parsing, preserving a stable schema-specific error instead of accepting a
9
+ write that cannot round-trip.
10
+ - Verified with the macro capability and macro schema unit-test groups.
@@ -0,0 +1,11 @@
1
+ # Macro expansion metrics baseline
2
+
3
+ - Added opt-in `--macro-metrics` JSON-on-stderr instrumentation for expansion
4
+ counts, exclusive evaluator/post-preprocess time, general evaluator fallback,
5
+ and cache outcome reasons.
6
+ - Nested macro phases pause parent timers so aggregate costs are not inflated by
7
+ recursive inclusive timing.
8
+ - Release-mode baselines on the Calcit test snapshot and latest Respo identify
9
+ post-expansion processing and common structural macros as the next targets.
10
+ - This is the instrumentation checkpoint for issue #436; it deliberately does
11
+ not add the typed Macro IR or pure expansion cache yet.
@@ -0,0 +1,11 @@
1
+ # Macro query and capability scope follow-up
2
+
3
+ - Preserve strict Macro contracts in `query schema`, `query context`, and JSON
4
+ output instead of degrading them through ordinary type serialization.
5
+ - Serialize an explicit empty `:capabilities` set for every strict/pure Macro;
6
+ legacy signatures retain their compatibility representation.
7
+ - Limit a strict macro's capability context to evaluation of its own body.
8
+ Post-preprocessing an emitted expansion may invoke a separate nested macro,
9
+ whose effects must not be charged to the outer emitter.
10
+ - Added query regression coverage and validated the boundary with the migrated
11
+ core `fn` macro emitting bodies that contain platform-sensitive legacy macros.