@rcrsr/rill 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/README.md +37 -21
  2. package/dist/ast-nodes.d.ts +2 -13
  3. package/dist/ast-nodes.js +0 -1
  4. package/dist/ast-unions.d.ts +0 -1
  5. package/dist/ast-unions.js +0 -1
  6. package/dist/constants.d.ts +0 -1
  7. package/dist/constants.js +0 -1
  8. package/dist/error-classes.d.ts +0 -1
  9. package/dist/error-classes.js +0 -1
  10. package/dist/error-formatter.d.ts +0 -1
  11. package/dist/error-formatter.js +0 -1
  12. package/dist/error-registry.d.ts +0 -1
  13. package/dist/error-registry.js +32 -1
  14. package/dist/ext/crypto/index.d.ts +3 -4
  15. package/dist/ext/crypto/index.js +66 -64
  16. package/dist/ext/exec/index.d.ts +3 -4
  17. package/dist/ext/exec/index.js +17 -12
  18. package/dist/ext/exec/runner.d.ts +0 -1
  19. package/dist/ext/exec/runner.js +0 -1
  20. package/dist/ext/fetch/index.d.ts +3 -4
  21. package/dist/ext/fetch/index.js +23 -49
  22. package/dist/ext/fetch/request.d.ts +0 -1
  23. package/dist/ext/fetch/request.js +0 -1
  24. package/dist/ext/fs/index.d.ts +3 -4
  25. package/dist/ext/fs/index.js +268 -266
  26. package/dist/ext/fs/sandbox.d.ts +0 -1
  27. package/dist/ext/fs/sandbox.js +0 -1
  28. package/dist/ext/kv/index.d.ts +3 -4
  29. package/dist/ext/kv/index.js +216 -215
  30. package/dist/ext/kv/store.d.ts +0 -1
  31. package/dist/ext/kv/store.js +2 -2
  32. package/dist/ext-parse-bridge.d.ts +10 -0
  33. package/dist/ext-parse-bridge.js +10 -0
  34. package/dist/generated/introspection-data.d.ts +1 -2
  35. package/dist/generated/introspection-data.js +385 -297
  36. package/dist/generated/version-data.d.ts +1 -2
  37. package/dist/generated/version-data.js +2 -3
  38. package/dist/highlight-map.d.ts +0 -1
  39. package/dist/highlight-map.js +0 -1
  40. package/dist/index.d.ts +15 -5
  41. package/dist/index.js +14 -6
  42. package/dist/lexer/errors.d.ts +0 -1
  43. package/dist/lexer/errors.js +0 -1
  44. package/dist/lexer/helpers.d.ts +0 -1
  45. package/dist/lexer/helpers.js +0 -1
  46. package/dist/lexer/index.d.ts +0 -1
  47. package/dist/lexer/index.js +0 -1
  48. package/dist/lexer/operators.d.ts +0 -1
  49. package/dist/lexer/operators.js +0 -1
  50. package/dist/lexer/readers.d.ts +0 -1
  51. package/dist/lexer/readers.js +0 -1
  52. package/dist/lexer/state.d.ts +0 -1
  53. package/dist/lexer/state.js +0 -1
  54. package/dist/lexer/tokenizer.d.ts +0 -1
  55. package/dist/lexer/tokenizer.js +0 -1
  56. package/dist/parser/helpers.d.ts +0 -1
  57. package/dist/parser/helpers.js +0 -1
  58. package/dist/parser/index.d.ts +0 -1
  59. package/dist/parser/index.js +0 -1
  60. package/dist/parser/parser-collect.d.ts +0 -1
  61. package/dist/parser/parser-collect.js +0 -1
  62. package/dist/parser/parser-control.d.ts +0 -1
  63. package/dist/parser/parser-control.js +0 -1
  64. package/dist/parser/parser-expr.d.ts +0 -1
  65. package/dist/parser/parser-expr.js +0 -1
  66. package/dist/parser/parser-extract.d.ts +0 -1
  67. package/dist/parser/parser-extract.js +0 -1
  68. package/dist/parser/parser-functions.d.ts +0 -1
  69. package/dist/parser/parser-functions.js +0 -1
  70. package/dist/parser/parser-literals.d.ts +0 -1
  71. package/dist/parser/parser-literals.js +4 -2
  72. package/dist/parser/parser-script.d.ts +0 -1
  73. package/dist/parser/parser-script.js +0 -1
  74. package/dist/parser/parser-shape.d.ts +2 -3
  75. package/dist/parser/parser-shape.js +8 -52
  76. package/dist/parser/parser-types.d.ts +28 -2
  77. package/dist/parser/parser-types.js +76 -13
  78. package/dist/parser/parser-use.d.ts +0 -1
  79. package/dist/parser/parser-use.js +7 -2
  80. package/dist/parser/parser-variables.d.ts +0 -1
  81. package/dist/parser/parser-variables.js +0 -1
  82. package/dist/parser/parser.d.ts +0 -1
  83. package/dist/parser/parser.js +0 -1
  84. package/dist/parser/state.d.ts +0 -1
  85. package/dist/parser/state.js +0 -1
  86. package/dist/runtime/core/callable.d.ts +59 -20
  87. package/dist/runtime/core/callable.js +188 -39
  88. package/dist/runtime/core/context.d.ts +0 -12
  89. package/dist/runtime/core/context.js +77 -77
  90. package/dist/runtime/core/equals.d.ts +0 -1
  91. package/dist/runtime/core/equals.js +35 -3
  92. package/dist/runtime/core/eval/base.d.ts +0 -1
  93. package/dist/runtime/core/eval/base.js +0 -1
  94. package/dist/runtime/core/eval/evaluator.d.ts +0 -1
  95. package/dist/runtime/core/eval/evaluator.js +0 -1
  96. package/dist/runtime/core/eval/index.d.ts +2 -3
  97. package/dist/runtime/core/eval/index.js +11 -1
  98. package/dist/runtime/core/eval/mixins/annotations.d.ts +0 -1
  99. package/dist/runtime/core/eval/mixins/annotations.js +0 -1
  100. package/dist/runtime/core/eval/mixins/closures.d.ts +0 -1
  101. package/dist/runtime/core/eval/mixins/closures.js +92 -70
  102. package/dist/runtime/core/eval/mixins/collections.d.ts +0 -1
  103. package/dist/runtime/core/eval/mixins/collections.js +9 -4
  104. package/dist/runtime/core/eval/mixins/control-flow.d.ts +0 -1
  105. package/dist/runtime/core/eval/mixins/control-flow.js +0 -1
  106. package/dist/runtime/core/eval/mixins/conversion.d.ts +0 -1
  107. package/dist/runtime/core/eval/mixins/conversion.js +196 -188
  108. package/dist/runtime/core/eval/mixins/core.d.ts +0 -1
  109. package/dist/runtime/core/eval/mixins/core.js +2 -3
  110. package/dist/runtime/core/eval/mixins/expressions.d.ts +0 -1
  111. package/dist/runtime/core/eval/mixins/expressions.js +35 -28
  112. package/dist/runtime/core/eval/mixins/extraction.d.ts +0 -1
  113. package/dist/runtime/core/eval/mixins/extraction.js +8 -9
  114. package/dist/runtime/core/eval/mixins/list-dispatch.d.ts +0 -1
  115. package/dist/runtime/core/eval/mixins/list-dispatch.js +0 -1
  116. package/dist/runtime/core/eval/mixins/literals.d.ts +0 -1
  117. package/dist/runtime/core/eval/mixins/literals.js +6 -10
  118. package/dist/runtime/core/eval/mixins/types.d.ts +2 -1
  119. package/dist/runtime/core/eval/mixins/types.js +231 -261
  120. package/dist/runtime/core/eval/mixins/use.d.ts +0 -1
  121. package/dist/runtime/core/eval/mixins/use.js +0 -1
  122. package/dist/runtime/core/eval/mixins/variables.d.ts +0 -1
  123. package/dist/runtime/core/eval/mixins/variables.js +16 -15
  124. package/dist/runtime/core/eval/types.d.ts +0 -1
  125. package/dist/runtime/core/eval/types.js +0 -1
  126. package/dist/runtime/core/execute.d.ts +0 -1
  127. package/dist/runtime/core/execute.js +0 -1
  128. package/dist/runtime/core/field-descriptor.d.ts +4 -5
  129. package/dist/runtime/core/field-descriptor.js +2 -2
  130. package/dist/runtime/core/introspection.d.ts +0 -1
  131. package/dist/runtime/core/introspection.js +6 -7
  132. package/dist/runtime/core/markers.d.ts +12 -0
  133. package/dist/runtime/core/markers.js +7 -0
  134. package/dist/runtime/core/resolvers.d.ts +0 -1
  135. package/dist/runtime/core/resolvers.js +0 -1
  136. package/dist/runtime/core/signals.d.ts +0 -1
  137. package/dist/runtime/core/signals.js +0 -1
  138. package/dist/runtime/core/type-registrations.d.ts +136 -0
  139. package/dist/runtime/core/type-registrations.js +749 -0
  140. package/dist/runtime/core/type-structures.d.ts +128 -0
  141. package/dist/runtime/core/type-structures.js +12 -0
  142. package/dist/runtime/core/types.d.ts +15 -4
  143. package/dist/runtime/core/types.js +0 -1
  144. package/dist/runtime/core/values.d.ts +88 -146
  145. package/dist/runtime/core/values.js +466 -470
  146. package/dist/runtime/ext/builtins.d.ts +0 -1
  147. package/dist/runtime/ext/builtins.js +125 -80
  148. package/dist/runtime/ext/extensions.d.ts +30 -125
  149. package/dist/runtime/ext/extensions.js +0 -94
  150. package/dist/runtime/ext/test-context.d.ts +28 -0
  151. package/dist/runtime/ext/test-context.js +154 -0
  152. package/dist/runtime/index.d.ts +22 -9
  153. package/dist/runtime/index.js +18 -5
  154. package/dist/signature-parser.d.ts +2 -3
  155. package/dist/signature-parser.js +19 -17
  156. package/dist/source-location.d.ts +0 -1
  157. package/dist/source-location.js +0 -1
  158. package/dist/token-types.d.ts +0 -1
  159. package/dist/token-types.js +0 -1
  160. package/dist/types.d.ts +0 -1
  161. package/dist/types.js +0 -1
  162. package/dist/value-types.d.ts +15 -12
  163. package/dist/value-types.js +0 -1
  164. package/package.json +2 -1
  165. package/dist/ast-nodes.d.ts.map +0 -1
  166. package/dist/ast-nodes.js.map +0 -1
  167. package/dist/ast-unions.d.ts.map +0 -1
  168. package/dist/ast-unions.js.map +0 -1
  169. package/dist/constants.d.ts.map +0 -1
  170. package/dist/constants.js.map +0 -1
  171. package/dist/error-classes.d.ts.map +0 -1
  172. package/dist/error-classes.js.map +0 -1
  173. package/dist/error-formatter.d.ts.map +0 -1
  174. package/dist/error-formatter.js.map +0 -1
  175. package/dist/error-registry.d.ts.map +0 -1
  176. package/dist/error-registry.js.map +0 -1
  177. package/dist/ext/crypto/index.d.ts.map +0 -1
  178. package/dist/ext/crypto/index.js.map +0 -1
  179. package/dist/ext/exec/index.d.ts.map +0 -1
  180. package/dist/ext/exec/index.js.map +0 -1
  181. package/dist/ext/exec/runner.d.ts.map +0 -1
  182. package/dist/ext/exec/runner.js.map +0 -1
  183. package/dist/ext/fetch/index.d.ts.map +0 -1
  184. package/dist/ext/fetch/index.js.map +0 -1
  185. package/dist/ext/fetch/request.d.ts.map +0 -1
  186. package/dist/ext/fetch/request.js.map +0 -1
  187. package/dist/ext/fs/index.d.ts.map +0 -1
  188. package/dist/ext/fs/index.js.map +0 -1
  189. package/dist/ext/fs/sandbox.d.ts.map +0 -1
  190. package/dist/ext/fs/sandbox.js.map +0 -1
  191. package/dist/ext/kv/index.d.ts.map +0 -1
  192. package/dist/ext/kv/index.js.map +0 -1
  193. package/dist/ext/kv/store.d.ts.map +0 -1
  194. package/dist/ext/kv/store.js.map +0 -1
  195. package/dist/generated/introspection-data.d.ts.map +0 -1
  196. package/dist/generated/introspection-data.js.map +0 -1
  197. package/dist/generated/version-data.d.ts.map +0 -1
  198. package/dist/generated/version-data.js.map +0 -1
  199. package/dist/highlight-map.d.ts.map +0 -1
  200. package/dist/highlight-map.js.map +0 -1
  201. package/dist/index.d.ts.map +0 -1
  202. package/dist/index.js.map +0 -1
  203. package/dist/lexer/errors.d.ts.map +0 -1
  204. package/dist/lexer/errors.js.map +0 -1
  205. package/dist/lexer/helpers.d.ts.map +0 -1
  206. package/dist/lexer/helpers.js.map +0 -1
  207. package/dist/lexer/index.d.ts.map +0 -1
  208. package/dist/lexer/index.js.map +0 -1
  209. package/dist/lexer/operators.d.ts.map +0 -1
  210. package/dist/lexer/operators.js.map +0 -1
  211. package/dist/lexer/readers.d.ts.map +0 -1
  212. package/dist/lexer/readers.js.map +0 -1
  213. package/dist/lexer/state.d.ts.map +0 -1
  214. package/dist/lexer/state.js.map +0 -1
  215. package/dist/lexer/tokenizer.d.ts.map +0 -1
  216. package/dist/lexer/tokenizer.js.map +0 -1
  217. package/dist/parser/helpers.d.ts.map +0 -1
  218. package/dist/parser/helpers.js.map +0 -1
  219. package/dist/parser/index.d.ts.map +0 -1
  220. package/dist/parser/index.js.map +0 -1
  221. package/dist/parser/parser-collect.d.ts.map +0 -1
  222. package/dist/parser/parser-collect.js.map +0 -1
  223. package/dist/parser/parser-control.d.ts.map +0 -1
  224. package/dist/parser/parser-control.js.map +0 -1
  225. package/dist/parser/parser-expr.d.ts.map +0 -1
  226. package/dist/parser/parser-expr.js.map +0 -1
  227. package/dist/parser/parser-extract.d.ts.map +0 -1
  228. package/dist/parser/parser-extract.js.map +0 -1
  229. package/dist/parser/parser-functions.d.ts.map +0 -1
  230. package/dist/parser/parser-functions.js.map +0 -1
  231. package/dist/parser/parser-literals.d.ts.map +0 -1
  232. package/dist/parser/parser-literals.js.map +0 -1
  233. package/dist/parser/parser-script.d.ts.map +0 -1
  234. package/dist/parser/parser-script.js.map +0 -1
  235. package/dist/parser/parser-shape.d.ts.map +0 -1
  236. package/dist/parser/parser-shape.js.map +0 -1
  237. package/dist/parser/parser-types.d.ts.map +0 -1
  238. package/dist/parser/parser-types.js.map +0 -1
  239. package/dist/parser/parser-use.d.ts.map +0 -1
  240. package/dist/parser/parser-use.js.map +0 -1
  241. package/dist/parser/parser-variables.d.ts.map +0 -1
  242. package/dist/parser/parser-variables.js.map +0 -1
  243. package/dist/parser/parser.d.ts.map +0 -1
  244. package/dist/parser/parser.js.map +0 -1
  245. package/dist/parser/state.d.ts.map +0 -1
  246. package/dist/parser/state.js.map +0 -1
  247. package/dist/runtime/core/callable.d.ts.map +0 -1
  248. package/dist/runtime/core/callable.js.map +0 -1
  249. package/dist/runtime/core/context.d.ts.map +0 -1
  250. package/dist/runtime/core/context.js.map +0 -1
  251. package/dist/runtime/core/equals.d.ts.map +0 -1
  252. package/dist/runtime/core/equals.js.map +0 -1
  253. package/dist/runtime/core/eval/base.d.ts.map +0 -1
  254. package/dist/runtime/core/eval/base.js.map +0 -1
  255. package/dist/runtime/core/eval/evaluator.d.ts.map +0 -1
  256. package/dist/runtime/core/eval/evaluator.js.map +0 -1
  257. package/dist/runtime/core/eval/index.d.ts.map +0 -1
  258. package/dist/runtime/core/eval/index.js.map +0 -1
  259. package/dist/runtime/core/eval/mixins/annotations.d.ts.map +0 -1
  260. package/dist/runtime/core/eval/mixins/annotations.js.map +0 -1
  261. package/dist/runtime/core/eval/mixins/closures.d.ts.map +0 -1
  262. package/dist/runtime/core/eval/mixins/closures.js.map +0 -1
  263. package/dist/runtime/core/eval/mixins/collections.d.ts.map +0 -1
  264. package/dist/runtime/core/eval/mixins/collections.js.map +0 -1
  265. package/dist/runtime/core/eval/mixins/control-flow.d.ts.map +0 -1
  266. package/dist/runtime/core/eval/mixins/control-flow.js.map +0 -1
  267. package/dist/runtime/core/eval/mixins/conversion.d.ts.map +0 -1
  268. package/dist/runtime/core/eval/mixins/conversion.js.map +0 -1
  269. package/dist/runtime/core/eval/mixins/core.d.ts.map +0 -1
  270. package/dist/runtime/core/eval/mixins/core.js.map +0 -1
  271. package/dist/runtime/core/eval/mixins/expressions.d.ts.map +0 -1
  272. package/dist/runtime/core/eval/mixins/expressions.js.map +0 -1
  273. package/dist/runtime/core/eval/mixins/extraction.d.ts.map +0 -1
  274. package/dist/runtime/core/eval/mixins/extraction.js.map +0 -1
  275. package/dist/runtime/core/eval/mixins/list-dispatch.d.ts.map +0 -1
  276. package/dist/runtime/core/eval/mixins/list-dispatch.js.map +0 -1
  277. package/dist/runtime/core/eval/mixins/literals.d.ts.map +0 -1
  278. package/dist/runtime/core/eval/mixins/literals.js.map +0 -1
  279. package/dist/runtime/core/eval/mixins/types.d.ts.map +0 -1
  280. package/dist/runtime/core/eval/mixins/types.js.map +0 -1
  281. package/dist/runtime/core/eval/mixins/use.d.ts.map +0 -1
  282. package/dist/runtime/core/eval/mixins/use.js.map +0 -1
  283. package/dist/runtime/core/eval/mixins/variables.d.ts.map +0 -1
  284. package/dist/runtime/core/eval/mixins/variables.js.map +0 -1
  285. package/dist/runtime/core/eval/types.d.ts.map +0 -1
  286. package/dist/runtime/core/eval/types.js.map +0 -1
  287. package/dist/runtime/core/execute.d.ts.map +0 -1
  288. package/dist/runtime/core/execute.js.map +0 -1
  289. package/dist/runtime/core/field-descriptor.d.ts.map +0 -1
  290. package/dist/runtime/core/field-descriptor.js.map +0 -1
  291. package/dist/runtime/core/introspection.d.ts.map +0 -1
  292. package/dist/runtime/core/introspection.js.map +0 -1
  293. package/dist/runtime/core/resolvers.d.ts.map +0 -1
  294. package/dist/runtime/core/resolvers.js.map +0 -1
  295. package/dist/runtime/core/signals.d.ts.map +0 -1
  296. package/dist/runtime/core/signals.js.map +0 -1
  297. package/dist/runtime/core/types.d.ts.map +0 -1
  298. package/dist/runtime/core/types.js.map +0 -1
  299. package/dist/runtime/core/values.d.ts.map +0 -1
  300. package/dist/runtime/core/values.js.map +0 -1
  301. package/dist/runtime/ext/builtins.d.ts.map +0 -1
  302. package/dist/runtime/ext/builtins.js.map +0 -1
  303. package/dist/runtime/ext/extensions.d.ts.map +0 -1
  304. package/dist/runtime/ext/extensions.js.map +0 -1
  305. package/dist/runtime/index.d.ts.map +0 -1
  306. package/dist/runtime/index.js.map +0 -1
  307. package/dist/signature-parser.d.ts.map +0 -1
  308. package/dist/signature-parser.js.map +0 -1
  309. package/dist/source-location.d.ts.map +0 -1
  310. package/dist/source-location.js.map +0 -1
  311. package/dist/token-types.d.ts.map +0 -1
  312. package/dist/token-types.js.map +0 -1
  313. package/dist/types.d.ts.map +0 -1
  314. package/dist/types.js.map +0 -1
  315. package/dist/value-types.d.ts.map +0 -1
  316. package/dist/value-types.js.map +0 -1
@@ -24,7 +24,7 @@ import { RuntimeError } from '../../../../types.js';
24
24
  import { inferType, isRillIterator, isVector } from '../../values.js';
25
25
  import { createChildContext, getVariable } from '../../context.js';
26
26
  import { BreakSignal } from '../../signals.js';
27
- import { isCallable, isDict } from '../../callable.js';
27
+ import { isCallable, isDict, marshalArgs } from '../../callable.js';
28
28
  import { getEvaluator } from '../evaluator.js';
29
29
  /**
30
30
  * Default maximum iteration count for iterators.
@@ -223,9 +223,15 @@ function createCollectionsMixin(Base) {
223
223
  if (accumulator !== null) {
224
224
  args.push(accumulator);
225
225
  }
226
- // Handle both CallableFn and ApplicationCallable (task 1.5 will refactor validation)
227
226
  const fnToCall = typeof fn === 'function' ? fn : fn.fn;
228
- return fnToCall(args, this.ctx, body.span.start);
227
+ // Marshal args to named record if fn has params; cast otherwise (IC-1).
228
+ const callArgs = typeof fn !== 'function' && fn.params !== undefined
229
+ ? marshalArgs(args, fn.params, {
230
+ functionName: body.name,
231
+ location: body.span.start,
232
+ })
233
+ : args;
234
+ return fnToCall(callArgs, this.ctx, body.span.start);
229
235
  }
230
236
  default: {
231
237
  // TypeScript exhaustiveness check - should never reach here
@@ -509,4 +515,3 @@ function createCollectionsMixin(Base) {
509
515
  // TypeScript can't generate declarations for functions returning classes with protected members
510
516
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
511
517
  export const CollectionsMixin = createCollectionsMixin;
512
- //# sourceMappingURL=collections.js.map
@@ -24,4 +24,3 @@
24
24
  * @internal
25
25
  */
26
26
  export declare const ControlFlowMixin: any;
27
- //# sourceMappingURL=control-flow.d.ts.map
@@ -453,4 +453,3 @@ function createControlFlowMixin(Base) {
453
453
  // TypeScript can't generate declarations for functions returning classes with protected members
454
454
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
455
455
  export const ControlFlowMixin = createControlFlowMixin;
456
- //# sourceMappingURL=control-flow.js.map
@@ -27,4 +27,3 @@
27
27
  * @internal
28
28
  */
29
29
  export declare const ConversionMixin: any;
30
- //# sourceMappingURL=conversion.d.ts.map
@@ -27,8 +27,9 @@
27
27
  * @internal
28
28
  */
29
29
  import { RuntimeError } from '../../../../types.js';
30
- import { inferType, isTuple, isOrdered, isTypeValue, createOrdered, createTuple, formatValue, isFieldTypeWithDefault, } from '../../values.js';
30
+ import { inferType, isTuple, isOrdered, isTypeValue, createOrdered, createTuple, deepCopyRillValue, hasCollectionFields, emptyForType, } from '../../values.js';
31
31
  import { isDict } from '../../callable.js';
32
+ import { BUILT_IN_TYPES } from '../../type-registrations.js';
32
33
  import { getVariable } from '../../context.js';
33
34
  /**
34
35
  * ConversionMixin implementation.
@@ -54,16 +55,31 @@ function createConversionMixin(Base) {
54
55
  const typeRef = node.typeRef;
55
56
  // Structural type constructor: :>ordered(name: type, ...) or :>list(T), :>dict(...), :>tuple(...)
56
57
  if (isTypeConstructorNode(typeRef)) {
57
- if (typeRef.constructorName === 'ordered') {
58
- return this.convertToOrderedWithSig(input, typeRef, node);
59
- }
60
- if (typeRef.constructorName === 'dict') {
61
- return this.convertToDictWithSig(input, typeRef, node);
62
- }
63
- if (typeRef.constructorName === 'tuple') {
58
+ // For dict/ordered/tuple, evaluate the type constructor to determine
59
+ // uniform (valueType) vs structural (fields/elements) dispatch.
60
+ if (typeRef.constructorName === 'ordered' ||
61
+ typeRef.constructorName === 'dict' ||
62
+ typeRef.constructorName === 'tuple') {
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ const typeValue = await this.evaluateTypeConstructor(typeRef);
65
+ const structure = typeValue.structure;
66
+ // Uniform types (valueType present): use general convert-then-assert path
67
+ if ('valueType' in structure && structure.valueType) {
68
+ const result = this.applyConversion(input, typeRef.constructorName, node);
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
+ this.assertType(result, structure, node.span.start);
71
+ return result;
72
+ }
73
+ // Structural types (fields/elements present): use structural-specific handlers
74
+ if (typeRef.constructorName === 'ordered') {
75
+ return this.convertToOrderedWithSig(input, typeRef, node);
76
+ }
77
+ if (typeRef.constructorName === 'dict') {
78
+ return this.convertToDictWithSig(input, typeRef, node);
79
+ }
64
80
  return this.convertToTupleWithSig(input, typeRef, node);
65
81
  }
66
- // Non-dict/ordered constructors: convert first, then assert structural type
82
+ // Non-dict/ordered/tuple constructors: convert first, then assert structural type
67
83
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
84
  const typeValue = await this.evaluateTypeConstructor(typeRef);
69
85
  const result = this.applyConversion(input, typeRef.constructorName, node);
@@ -91,7 +107,15 @@ function createConversionMixin(Base) {
91
107
  }
92
108
  /**
93
109
  * Apply conversion from source value to target type name.
94
- * Implements the compatibility matrix from IR-9.
110
+ * Dispatches to protocol.convertTo on the source type's registration.
111
+ *
112
+ * IR-6: Replaces the hardcoded conversion matrix with protocol dispatch.
113
+ *
114
+ * Special cases preserved:
115
+ * - Same type = no-op (short-circuit)
116
+ * - dict -> :>ordered without structural sig raises RILL-R037 (EC-11)
117
+ * - String-to-number parse failure raises RILL-R038 (EC-12)
118
+ * - Missing convertTo target raises RILL-R036 (EC-10)
95
119
  */
96
120
  applyConversion(input, targetType, node) {
97
121
  const sourceType = inferType(input);
@@ -99,105 +123,34 @@ function createConversionMixin(Base) {
99
123
  if (sourceType === targetType) {
100
124
  return input;
101
125
  }
102
- // Apply compatibility matrix
103
- switch (targetType) {
104
- case 'list':
105
- return this.convertToList(input, sourceType, node);
106
- case 'dict':
107
- return this.convertToDict(input, sourceType, node);
108
- case 'tuple':
109
- return this.convertToTuple(input, sourceType, node);
110
- case 'ordered':
111
- // dict -> :>ordered without structural sig is always a runtime error (EC-11)
112
- if (sourceType === 'dict') {
113
- throw new RuntimeError('RILL-R037', 'dict to ordered conversion requires structural type signature', this.getNodeLocation(node));
114
- }
115
- return this.convertToOrdered(input, sourceType, node);
116
- case 'number':
117
- return this.convertToNumber(input, sourceType, node);
118
- case 'string':
119
- return this.convertToString(input, sourceType, node);
120
- case 'bool':
121
- return this.convertToBoolean(input, sourceType, node);
122
- default:
123
- this.throwIncompatible(sourceType, targetType, node);
124
- }
125
- // TypeScript exhaustiveness
126
- return input;
127
- }
128
- /** Convert to list type. Valid source: tuple. */
129
- convertToList(input, sourceType, node) {
130
- if (isTuple(input)) {
131
- return input.entries;
126
+ // dict -> :>ordered without structural sig is always RILL-R037 (EC-11)
127
+ if (sourceType === 'dict' && targetType === 'ordered') {
128
+ throw new RuntimeError('RILL-R037', 'dict to ordered conversion requires structural type signature', this.getNodeLocation(node));
132
129
  }
133
- this.throwIncompatible(sourceType, 'list', node);
134
- return input;
135
- }
136
- /** Convert to dict type. Valid source: ordered. */
137
- convertToDict(input, sourceType, node) {
138
- if (isOrdered(input)) {
139
- const result = {};
140
- for (const [key, value] of input.entries) {
141
- result[key] = value;
142
- }
143
- return result;
130
+ // Find source type registration and dispatch via protocol.convertTo
131
+ const reg = BUILT_IN_TYPES.find((r) => r.name === sourceType);
132
+ const converter = reg?.protocol.convertTo?.[targetType];
133
+ if (!converter) {
134
+ throw new RuntimeError('RILL-R036', `cannot convert ${sourceType} to ${targetType}`, this.getNodeLocation(node), { source: sourceType, target: targetType });
144
135
  }
145
- this.throwIncompatible(sourceType, 'dict', node);
146
- return input;
147
- }
148
- /** Convert to tuple type. Valid source: list. */
149
- convertToTuple(input, sourceType, node) {
150
- if (Array.isArray(input) && !isTuple(input) && !isOrdered(input)) {
151
- return createTuple(input);
136
+ try {
137
+ return converter(input);
152
138
  }
153
- this.throwIncompatible(sourceType, 'tuple', node);
154
- return input;
155
- }
156
- /** Convert to ordered type. Valid source: dict (with sig, handled separately). */
157
- convertToOrdered(input, sourceType, node) {
158
- // Only dict -> ordered is valid, but it requires a sig (checked by caller)
159
- this.throwIncompatible(sourceType, 'ordered', node);
160
- return input;
161
- }
162
- /** Convert to number type. Valid source: string (parseable) or bool. */
163
- convertToNumber(input, sourceType, node) {
164
- if (sourceType === 'string') {
165
- const str = input;
166
- const parsed = Number(str);
167
- if (isNaN(parsed) || str.trim() === '') {
168
- throw new RuntimeError('RILL-R038', `cannot convert string "${str}" to number`, this.getNodeLocation(node), { value: str });
139
+ catch (err) {
140
+ // Protocol converters throw plain Errors; wrap as RuntimeError
141
+ // with the appropriate error code.
142
+ if (err instanceof RuntimeError)
143
+ throw err;
144
+ // String-to-number parse failures use RILL-R038 (EC-12)
145
+ // Preserve the protocol's detailed message (includes unparseable value).
146
+ if (sourceType === 'string' && targetType === 'number') {
147
+ const message = err instanceof Error ? err.message : String(err);
148
+ throw new RuntimeError('RILL-R038', message, this.getNodeLocation(node), { value: input });
169
149
  }
170
- return parsed;
171
- }
172
- if (sourceType === 'bool') {
173
- return input ? 1 : 0;
174
- }
175
- this.throwIncompatible(sourceType, 'number', node);
176
- return input;
177
- }
178
- /** Convert to bool type. Valid source: number (0 or 1) or string ("true" or "false"). */
179
- convertToBoolean(input, sourceType, node) {
180
- if (sourceType === 'number') {
181
- const n = input;
182
- if (n === 0)
183
- return false;
184
- if (n === 1)
185
- return true;
186
- this.throwIncompatible(sourceType, 'bool', node);
150
+ // All other conversion failures use RILL-R036 (EC-10)
151
+ // Use consistent "cannot convert X to Y" format.
152
+ throw new RuntimeError('RILL-R036', `cannot convert ${sourceType} to ${targetType}`, this.getNodeLocation(node), { source: sourceType, target: targetType });
187
153
  }
188
- if (sourceType === 'string') {
189
- const s = input;
190
- if (s === 'true')
191
- return true;
192
- if (s === 'false')
193
- return false;
194
- this.throwIncompatible(sourceType, 'bool', node);
195
- }
196
- this.throwIncompatible(sourceType, 'bool', node);
197
- }
198
- /** Convert to string type. Valid source: any type via formatValue semantics. */
199
- convertToString(input, _sourceType, _node) {
200
- return formatValue(input);
201
154
  }
202
155
  /**
203
156
  * Convert dict -> :>ordered(field: type = default, ...) using structural signature.
@@ -209,28 +162,45 @@ function createConversionMixin(Base) {
209
162
  * - Extra keys not in signature: omitted from result
210
163
  */
211
164
  async convertToOrderedWithSig(input, sigNode, node) {
212
- if (!isDict(input)) {
165
+ let dictInput;
166
+ if (isOrdered(input)) {
167
+ dictInput = Object.fromEntries(input.entries);
168
+ }
169
+ else if (isDict(input)) {
170
+ dictInput = input;
171
+ }
172
+ else {
213
173
  throw new RuntimeError('RILL-R036', `cannot convert ${inferType(input)} to ordered`, this.getNodeLocation(node), { source: inferType(input), target: 'ordered' });
214
174
  }
175
+ const sourceType = isOrdered(input) ? 'ordered' : 'dict';
215
176
  // Evaluate the full type constructor to get resolved fields with defaults.
216
177
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
217
178
  const typeValue = await this.evaluateTypeConstructor(sigNode);
218
- const resolvedFields = typeValue.structure.type === 'ordered' && typeValue.structure.fields
179
+ const resolvedFields = typeValue.structure.kind === 'ordered' && typeValue.structure.fields
219
180
  ? typeValue.structure.fields
220
181
  : [];
221
- const dictInput = input;
222
182
  const entries = [];
223
183
  for (const field of resolvedFields) {
224
- const fieldName = field[0];
225
- const hasDefault = field.length === 3;
184
+ const fieldName = field.name;
226
185
  if (fieldName in dictInput) {
227
- entries.push([fieldName, dictInput[fieldName]]);
186
+ let fieldValue = dictInput[fieldName];
187
+ fieldValue = this.hydrateNested(fieldValue, field.type, node);
188
+ entries.push([fieldName, fieldValue]);
189
+ }
190
+ else if (field.defaultValue !== undefined) {
191
+ entries.push([
192
+ fieldName,
193
+ this.hydrateNested(deepCopyRillValue(field.defaultValue), field.type, node),
194
+ ]);
228
195
  }
229
- else if (hasDefault) {
230
- entries.push([fieldName, deepCopyRillValue(field[2])]);
196
+ else if (hasCollectionFields(field.type)) {
197
+ entries.push([
198
+ fieldName,
199
+ this.hydrateNested(emptyForType(field.type), field.type, node),
200
+ ]);
231
201
  }
232
202
  else {
233
- throw new RuntimeError('RILL-R044', `cannot convert dict to ordered: missing required field '${fieldName}'`, this.getNodeLocation(node), { source: 'dict', target: 'ordered' });
203
+ throw new RuntimeError('RILL-R044', `cannot convert ${sourceType} to ordered: missing required field '${fieldName}'`, this.getNodeLocation(node), { source: sourceType, target: 'ordered' });
234
204
  }
235
205
  }
236
206
  return createOrdered(entries);
@@ -246,19 +216,26 @@ function createConversionMixin(Base) {
246
216
  * - Recurses into nested dict-typed fields for nested hydration
247
217
  */
248
218
  async convertToDictWithSig(input, sigNode, node) {
249
- if (!isDict(input)) {
219
+ let dictInput;
220
+ if (isOrdered(input)) {
221
+ dictInput = Object.fromEntries(input.entries);
222
+ }
223
+ else if (isDict(input)) {
224
+ dictInput = input;
225
+ }
226
+ else {
250
227
  throw new RuntimeError('RILL-R036', `cannot convert ${inferType(input)} to dict`, this.getNodeLocation(node), { source: inferType(input), target: 'dict' });
251
228
  }
229
+ const sourceType = isOrdered(input) ? 'ordered' : 'dict';
252
230
  // Evaluate the full type constructor to get resolved fields with defaults.
253
231
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
254
232
  const typeValue = await this.evaluateTypeConstructor(sigNode);
255
- const resolvedFields = typeValue.structure.type === 'dict' && typeValue.structure.fields
233
+ const resolvedFields = typeValue.structure.kind === 'dict' && typeValue.structure.fields
256
234
  ? typeValue.structure.fields
257
235
  : {};
258
- const dictInput = input;
259
236
  const result = {};
260
237
  for (const arg of sigNode.args) {
261
- if (arg.kind !== 'named') {
238
+ if (arg.name === undefined) {
262
239
  continue;
263
240
  }
264
241
  const fieldName = arg.name;
@@ -267,21 +244,22 @@ function createConversionMixin(Base) {
267
244
  // Field present in input: use it, recursing if the field type is a nested dict
268
245
  let fieldValue = dictInput[fieldName];
269
246
  if (resolvedField !== undefined) {
270
- const innerType = isFieldTypeWithDefault(resolvedField)
271
- ? resolvedField.type
272
- : resolvedField;
273
- fieldValue = this.hydrateNestedDict(fieldValue, innerType, node);
247
+ fieldValue = this.hydrateNested(fieldValue, resolvedField.type, node);
274
248
  }
275
249
  result[fieldName] = fieldValue;
276
250
  }
277
251
  else {
278
252
  // Field missing from input: use default if available, else error
279
253
  if (resolvedField !== undefined &&
280
- isFieldTypeWithDefault(resolvedField)) {
281
- result[fieldName] = deepCopyRillValue(resolvedField.defaultValue);
254
+ resolvedField.defaultValue !== undefined) {
255
+ result[fieldName] = this.hydrateNested(deepCopyRillValue(resolvedField.defaultValue), resolvedField.type, node);
256
+ }
257
+ else if (resolvedField !== undefined &&
258
+ hasCollectionFields(resolvedField.type)) {
259
+ result[fieldName] = this.hydrateNested(emptyForType(resolvedField.type), resolvedField.type, node);
282
260
  }
283
261
  else {
284
- throw new RuntimeError('RILL-R044', `cannot convert dict to dict: missing required field '${fieldName}'`, this.getNodeLocation(node), { source: 'dict', target: 'dict' });
262
+ throw new RuntimeError('RILL-R044', `cannot convert ${sourceType} to dict: missing required field '${fieldName}'`, this.getNodeLocation(node), { source: sourceType, target: 'dict' });
285
263
  }
286
264
  }
287
265
  }
@@ -305,7 +283,7 @@ function createConversionMixin(Base) {
305
283
  // Evaluate the full type constructor to get resolved elements with defaults.
306
284
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
307
285
  const typeValue = await this.evaluateTypeConstructor(sigNode);
308
- const resolvedElements = typeValue.structure.type === 'tuple' && typeValue.structure.elements
286
+ const resolvedElements = typeValue.structure.kind === 'tuple' && typeValue.structure.elements
309
287
  ? typeValue.structure.elements
310
288
  : [];
311
289
  const inputEntries = isTupleInput
@@ -314,14 +292,17 @@ function createConversionMixin(Base) {
314
292
  const result = [];
315
293
  for (let i = 0; i < resolvedElements.length; i++) {
316
294
  const element = resolvedElements[i];
317
- const hasDefault = element.length === 2;
318
295
  if (i < inputEntries.length) {
319
- // Element present in input: use it directly
320
- result.push(inputEntries[i]);
296
+ // Element present in input: recurse into nested types
297
+ result.push(this.hydrateNested(inputEntries[i], element.type, node));
321
298
  }
322
- else if (hasDefault) {
323
- // Missing trailing element with default: deep copy default
324
- result.push(deepCopyRillValue(element[1]));
299
+ else if (element.defaultValue !== undefined) {
300
+ // Missing trailing element with default: deep copy and hydrate
301
+ result.push(this.hydrateNested(deepCopyRillValue(element.defaultValue), element.type, node));
302
+ }
303
+ else if (hasCollectionFields(element.type)) {
304
+ // Missing element with collection type: seed empty and hydrate
305
+ result.push(this.hydrateNested(emptyForType(element.type), element.type, node));
325
306
  }
326
307
  else {
327
308
  // Missing element without default
@@ -331,76 +312,104 @@ function createConversionMixin(Base) {
331
312
  return createTuple(result);
332
313
  }
333
314
  /**
334
- * Recursively hydrate a dict value against a nested dict RillType.
335
- * Only applies when the field type is a dict with explicit fields.
336
- * Returns the value unchanged if it is not a dict or the type has no fields.
315
+ * Recursively hydrate a value against a nested dict, ordered, or tuple RillType.
316
+ * Only applies when the field type has explicit fields/elements.
317
+ * Returns the value unchanged if the type has no fields or the value type does not match.
337
318
  */
338
- hydrateNestedDict(value, fieldType, node) {
339
- if (fieldType.type !== 'dict' || !fieldType.fields) {
340
- return value;
341
- }
342
- if (!isDict(value)) {
343
- return value;
319
+ hydrateNested(value, fieldType, node) {
320
+ if (fieldType.kind === 'dict' &&
321
+ fieldType.fields &&
322
+ isDict(value)) {
323
+ const ft = fieldType;
324
+ const dictValue = value;
325
+ const result = {};
326
+ for (const [fieldName, resolvedField] of Object.entries(ft.fields)) {
327
+ if (fieldName in dictValue) {
328
+ const fieldValue = this.hydrateNested(dictValue[fieldName], resolvedField.type, node);
329
+ result[fieldName] = fieldValue;
330
+ }
331
+ else {
332
+ if (resolvedField.defaultValue !== undefined) {
333
+ result[fieldName] = this.hydrateNested(deepCopyRillValue(resolvedField.defaultValue), resolvedField.type, node);
334
+ }
335
+ else if (hasCollectionFields(resolvedField.type)) {
336
+ result[fieldName] = this.hydrateNested(emptyForType(resolvedField.type), resolvedField.type, node);
337
+ }
338
+ else {
339
+ throw new RuntimeError('RILL-R044', `cannot convert dict to dict: missing required field '${fieldName}'`, this.getNodeLocation(node), { source: 'dict', target: 'dict' });
340
+ }
341
+ }
342
+ }
343
+ return result;
344
344
  }
345
- const dictValue = value;
346
- const result = {};
347
- for (const [fieldName, resolvedField] of Object.entries(fieldType.fields)) {
348
- if (fieldName in dictValue) {
349
- let fieldValue = dictValue[fieldName];
350
- if (isFieldTypeWithDefault(resolvedField)) {
351
- fieldValue = this.hydrateNestedDict(fieldValue, resolvedField.type, node);
345
+ else if (fieldType.kind === 'ordered' &&
346
+ fieldType.fields) {
347
+ const ft = fieldType;
348
+ // Only hydrate if the runtime value is an ordered or dict; return unchanged otherwise.
349
+ if (!isOrdered(value) && !isDict(value)) {
350
+ return value;
351
+ }
352
+ const source = isOrdered(value) ? 'ordered' : 'dict';
353
+ // Build a key->value lookup from either an ordered value or a dict value.
354
+ const lookup = new Map(isOrdered(value)
355
+ ? value.entries.map(([k, v]) => [k, v])
356
+ : Object.entries(value));
357
+ const resultEntries = [];
358
+ for (const field of ft.fields) {
359
+ const name = field.name;
360
+ if (lookup.has(name)) {
361
+ const fieldValue = this.hydrateNested(lookup.get(name), field.type, node);
362
+ resultEntries.push([name, fieldValue]);
363
+ }
364
+ else if (field.defaultValue !== undefined) {
365
+ resultEntries.push([
366
+ name,
367
+ this.hydrateNested(deepCopyRillValue(field.defaultValue), field.type, node),
368
+ ]);
369
+ }
370
+ else if (hasCollectionFields(field.type)) {
371
+ resultEntries.push([
372
+ name,
373
+ this.hydrateNested(emptyForType(field.type), field.type, node),
374
+ ]);
352
375
  }
353
376
  else {
354
- fieldValue = this.hydrateNestedDict(fieldValue, resolvedField, node);
377
+ throw new RuntimeError('RILL-R044', `cannot convert ${source} to ordered: missing required field '${name}'`, this.getNodeLocation(node), { source, target: 'ordered' });
355
378
  }
356
- result[fieldName] = fieldValue;
357
379
  }
358
- else {
359
- if (isFieldTypeWithDefault(resolvedField)) {
360
- result[fieldName] = deepCopyRillValue(resolvedField.defaultValue);
380
+ return createOrdered(resultEntries);
381
+ }
382
+ else if (fieldType.kind === 'tuple' &&
383
+ fieldType.elements) {
384
+ const ft = fieldType;
385
+ // Only hydrate if the runtime value is a tuple; return unchanged otherwise.
386
+ if (!isTuple(value)) {
387
+ return value;
388
+ }
389
+ const inputEntries = value.entries;
390
+ const resultEntries = [];
391
+ for (let i = 0; i < ft.elements.length; i++) {
392
+ const element = ft.elements[i];
393
+ if (i < inputEntries.length) {
394
+ const elementValue = this.hydrateNested(inputEntries[i], element.type, node);
395
+ resultEntries.push(elementValue);
396
+ }
397
+ else if (element.defaultValue !== undefined) {
398
+ resultEntries.push(this.hydrateNested(deepCopyRillValue(element.defaultValue), element.type, node));
399
+ }
400
+ else if (hasCollectionFields(element.type)) {
401
+ resultEntries.push(this.hydrateNested(emptyForType(element.type), element.type, node));
361
402
  }
362
403
  else {
363
- throw new RuntimeError('RILL-R044', `cannot convert dict to dict: missing required field '${fieldName}'`, this.getNodeLocation(node), { source: 'dict', target: 'dict' });
404
+ throw new RuntimeError('RILL-R044', `cannot convert tuple to tuple: missing required element at position ${i}`, this.getNodeLocation(node), { source: 'tuple', target: 'tuple' });
364
405
  }
365
406
  }
407
+ return createTuple(resultEntries);
366
408
  }
367
- return result;
368
- }
369
- /** Throw EC-10 incompatible conversion error. */
370
- throwIncompatible(source, target, node) {
371
- throw new RuntimeError('RILL-R036', `cannot convert ${source} to ${target}`, this.getNodeLocation(node), { source, target });
409
+ return value;
372
410
  }
373
411
  };
374
412
  }
375
- /**
376
- * Deep copy a RillValue, producing a new independent value.
377
- * Handles primitives, arrays, plain dicts, and null.
378
- * Special markers (closures, tuples, ordered, vectors, type values) are returned
379
- * as-is since they are immutable by contract.
380
- */
381
- function deepCopyRillValue(value) {
382
- if (value === null || typeof value !== 'object') {
383
- return value;
384
- }
385
- if (Array.isArray(value)) {
386
- return value.map(deepCopyRillValue);
387
- }
388
- // Plain dict: copy recursively. Special markers (RillTuple, RillOrdered, etc.)
389
- // carry __rill_* own properties and are treated as immutable; return as-is.
390
- if (!('__rill_tuple' in value) &&
391
- !('__rill_ordered' in value) &&
392
- !('__rill_vector' in value) &&
393
- !('__rill_type' in value) &&
394
- !('__type' in value) &&
395
- !('__rill_field_descriptor' in value)) {
396
- const copy = {};
397
- for (const [k, v] of Object.entries(value)) {
398
- copy[k] = deepCopyRillValue(v);
399
- }
400
- return copy;
401
- }
402
- return value;
403
- }
404
413
  /**
405
414
  * Type guard: check if a TypeRef | TypeConstructorNode is a TypeConstructorNode.
406
415
  */
@@ -410,4 +419,3 @@ function isTypeConstructorNode(ref) {
410
419
  // Export with type assertion to work around TS4094 limitation
411
420
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
412
421
  export const ConversionMixin = createConversionMixin;
413
- //# sourceMappingURL=conversion.js.map
@@ -21,4 +21,3 @@
21
21
  * @internal
22
22
  */
23
23
  export declare const CoreMixin: any;
24
- //# sourceMappingURL=core.d.ts.map
@@ -282,8 +282,8 @@ function createCoreMixin(Base) {
282
282
  primary.typeName === 'ordered' ||
283
283
  primary.typeName === 'vector' ||
284
284
  primary.typeName === 'type'
285
- ? { type: primary.typeName }
286
- : { type: 'any' },
285
+ ? { kind: primary.typeName }
286
+ : { kind: 'any' },
287
287
  });
288
288
  case 'TypeConstructor':
289
289
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -753,4 +753,3 @@ function createCoreMixin(Base) {
753
753
  // TypeScript can't generate declarations for functions returning classes with protected members
754
754
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
755
755
  export const CoreMixin = createCoreMixin;
756
- //# sourceMappingURL=core.js.map
@@ -18,4 +18,3 @@
18
18
  * @internal
19
19
  */
20
20
  export declare const ExpressionsMixin: any;
21
- //# sourceMappingURL=expressions.d.ts.map