@rcrsr/rill 0.16.0 → 0.18.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 (97) hide show
  1. package/README.md +37 -21
  2. package/dist/ast-nodes.d.ts +14 -4
  3. package/dist/ast-unions.d.ts +1 -1
  4. package/dist/constants.d.ts +1 -1
  5. package/dist/constants.js +1 -0
  6. package/dist/error-registry.js +228 -0
  7. package/dist/ext/crypto/index.d.ts +3 -3
  8. package/dist/ext/crypto/index.js +62 -59
  9. package/dist/ext/exec/index.d.ts +3 -3
  10. package/dist/ext/exec/index.js +15 -9
  11. package/dist/ext/fetch/index.d.ts +3 -3
  12. package/dist/ext/fetch/index.js +17 -12
  13. package/dist/ext/fetch/request.js +1 -1
  14. package/dist/ext/fs/index.d.ts +3 -3
  15. package/dist/ext/fs/index.js +256 -266
  16. package/dist/ext/fs/sandbox.d.ts +18 -0
  17. package/dist/ext/fs/sandbox.js +33 -0
  18. package/dist/ext/kv/index.d.ts +3 -3
  19. package/dist/ext/kv/index.js +198 -196
  20. package/dist/ext/kv/store.d.ts +1 -1
  21. package/dist/ext/kv/store.js +2 -1
  22. package/dist/ext-parse-bridge.d.ts +10 -0
  23. package/dist/ext-parse-bridge.js +10 -0
  24. package/dist/generated/introspection-data.d.ts +1 -1
  25. package/dist/generated/introspection-data.js +385 -296
  26. package/dist/generated/version-data.d.ts +1 -1
  27. package/dist/generated/version-data.js +2 -2
  28. package/dist/highlight-map.js +1 -0
  29. package/dist/index.d.ts +1 -4
  30. package/dist/index.js +1 -5
  31. package/dist/lexer/operators.js +1 -0
  32. package/dist/parser/helpers.js +1 -0
  33. package/dist/parser/parser-expr.js +44 -5
  34. package/dist/parser/parser-literals.js +111 -4
  35. package/dist/parser/parser-shape.js +2 -2
  36. package/dist/parser/parser-types.js +12 -0
  37. package/dist/parser/parser-use.js +26 -3
  38. package/dist/parser/parser.d.ts +2 -0
  39. package/dist/parser/parser.js +2 -0
  40. package/dist/runtime/core/callable.d.ts +24 -13
  41. package/dist/runtime/core/callable.js +71 -38
  42. package/dist/runtime/core/context.d.ts +2 -13
  43. package/dist/runtime/core/context.js +80 -79
  44. package/dist/runtime/core/eval/base.d.ts +2 -2
  45. package/dist/runtime/core/eval/base.js +2 -0
  46. package/dist/runtime/core/eval/evaluator.d.ts +1 -1
  47. package/dist/runtime/core/eval/index.d.ts +3 -3
  48. package/dist/runtime/core/eval/index.js +11 -0
  49. package/dist/runtime/core/eval/mixins/closures.js +381 -41
  50. package/dist/runtime/core/eval/mixins/collections.js +81 -6
  51. package/dist/runtime/core/eval/mixins/control-flow.js +1 -1
  52. package/dist/runtime/core/eval/mixins/conversion.js +61 -115
  53. package/dist/runtime/core/eval/mixins/core.js +17 -4
  54. package/dist/runtime/core/eval/mixins/expressions.js +36 -27
  55. package/dist/runtime/core/eval/mixins/extraction.js +2 -3
  56. package/dist/runtime/core/eval/mixins/list-dispatch.js +1 -1
  57. package/dist/runtime/core/eval/mixins/literals.js +17 -6
  58. package/dist/runtime/core/eval/mixins/types.js +73 -54
  59. package/dist/runtime/core/eval/mixins/variables.js +12 -8
  60. package/dist/runtime/core/execute.d.ts +1 -1
  61. package/dist/runtime/core/field-descriptor.d.ts +3 -3
  62. package/dist/runtime/core/field-descriptor.js +2 -1
  63. package/dist/runtime/core/introspection.d.ts +2 -2
  64. package/dist/runtime/core/introspection.js +7 -6
  65. package/dist/runtime/core/resolvers.d.ts +1 -1
  66. package/dist/runtime/core/signals.d.ts +6 -1
  67. package/dist/runtime/core/signals.js +9 -0
  68. package/dist/runtime/core/types/constructors.d.ts +54 -0
  69. package/dist/runtime/core/types/constructors.js +201 -0
  70. package/dist/runtime/core/types/guards.d.ts +42 -0
  71. package/dist/runtime/core/types/guards.js +88 -0
  72. package/dist/runtime/core/types/index.d.ts +18 -0
  73. package/dist/runtime/core/types/index.js +19 -0
  74. package/dist/runtime/core/types/markers.d.ts +12 -0
  75. package/dist/runtime/core/types/markers.js +7 -0
  76. package/dist/runtime/core/types/operations.d.ts +98 -0
  77. package/dist/runtime/core/types/operations.js +804 -0
  78. package/dist/runtime/core/types/registrations.d.ts +126 -0
  79. package/dist/runtime/core/types/registrations.js +751 -0
  80. package/dist/runtime/core/{types.d.ts → types/runtime.d.ts} +22 -10
  81. package/dist/runtime/core/types/structures.d.ts +146 -0
  82. package/dist/runtime/core/types/structures.js +12 -0
  83. package/dist/runtime/core/values.d.ts +29 -209
  84. package/dist/runtime/core/values.js +56 -968
  85. package/dist/runtime/ext/builtins.js +88 -68
  86. package/dist/runtime/ext/extensions.d.ts +31 -125
  87. package/dist/runtime/ext/extensions.js +2 -94
  88. package/dist/runtime/ext/test-context.d.ts +28 -0
  89. package/dist/runtime/ext/test-context.js +155 -0
  90. package/dist/runtime/index.d.ts +12 -12
  91. package/dist/runtime/index.js +13 -5
  92. package/dist/signature-parser.d.ts +2 -2
  93. package/dist/signature-parser.js +14 -14
  94. package/dist/token-types.d.ts +1 -0
  95. package/dist/token-types.js +1 -0
  96. package/package.json +1 -1
  97. /package/dist/runtime/core/{types.js → types/runtime.js} +0 -0
@@ -3,673 +3,28 @@
3
3
  *
4
4
  * Core value types that flow through Rill programs.
5
5
  * Public API for host applications.
6
- */
7
- import { RuntimeError } from '../../types.js';
8
- import { VALID_TYPE_NAMES } from '../../constants.js';
9
- import { callableEquals, isCallable, isDict, isScriptCallable, } from './callable.js';
10
- /** Type guard for RillTuple (spread args) */
11
- export function isTuple(value) {
12
- return (typeof value === 'object' &&
13
- value !== null &&
14
- '__rill_tuple' in value &&
15
- value.__rill_tuple === true);
16
- }
17
- /** Type guard for RillVector */
18
- export function isVector(value) {
19
- return (typeof value === 'object' &&
20
- value !== null &&
21
- '__rill_vector' in value &&
22
- value.__rill_vector === true);
23
- }
24
- /** Type guard for RillOrdered (named spread args) */
25
- export function isOrdered(value) {
26
- return (typeof value === 'object' &&
27
- value !== null &&
28
- '__rill_ordered' in value &&
29
- value.__rill_ordered === true);
30
- }
31
- /** Type guard for RillTypeValue */
32
- export function isTypeValue(value) {
33
- return (typeof value === 'object' &&
34
- value !== null &&
35
- '__rill_type' in value &&
36
- value.__rill_type === true);
37
- }
38
- /**
39
- * Create ordered from entries array (named, preserves insertion order).
40
- * Entries may be 2-element [name, value] or 3-element [name, value, default]
41
- * tuples; the third element carries a default value for `.^input` reflection.
42
- */
43
- export function createOrdered(entries) {
44
- return Object.freeze({ __rill_ordered: true, entries: [...entries] });
45
- }
46
- /** Create tuple from entries array (positional, preserves order) */
47
- export function createTuple(entries) {
48
- return Object.freeze({ __rill_tuple: true, entries: [...entries] });
49
- }
50
- /**
51
- * Create vector from Float32Array with model name.
52
- * @throws {Error} if data.length is 0 (zero-dimension vectors not allowed)
53
- */
54
- export function createVector(data, model) {
55
- if (data.length === 0) {
56
- throw new Error('Vector data must have at least one dimension');
57
- }
58
- return { __rill_vector: true, data, model };
59
- }
60
- /** Infer the Rill type from a runtime value */
61
- export function inferType(value) {
62
- if (value === null)
63
- return 'string'; // null treated as empty string
64
- if (typeof value === 'string')
65
- return 'string';
66
- if (typeof value === 'number')
67
- return 'number';
68
- if (typeof value === 'boolean')
69
- return 'bool';
70
- if (isTuple(value))
71
- return 'tuple';
72
- if (isOrdered(value))
73
- return 'ordered';
74
- if (isVector(value))
75
- return 'vector';
76
- if (Array.isArray(value))
77
- return 'list';
78
- if (isTypeValue(value))
79
- return 'type';
80
- if (isRillIterator(value))
81
- return 'iterator';
82
- if (typeof value === 'object' &&
83
- '__type' in value &&
84
- value.__type === 'callable') {
85
- return 'closure';
86
- }
87
- if (typeof value === 'object')
88
- return 'dict';
89
- return 'string'; // fallback
90
- }
91
- /**
92
- * Infer the element type for a homogeneous list.
93
- * Empty arrays return { type: 'any' }.
94
- * Mixed types throw RILL-R002.
95
- */
96
- export function inferElementType(elements) {
97
- if (elements.length === 0)
98
- return { type: 'any' };
99
- const firstElem = elements[0];
100
- let accType = inferStructuralType(firstElem);
101
- for (let i = 1; i < elements.length; i++) {
102
- const elem = elements[i];
103
- const elemType = inferStructuralType(elem);
104
- const merged = commonType(accType, elemType);
105
- if (merged === null) {
106
- throw new RuntimeError('RILL-R002', `List elements must be the same type: expected ${formatStructuralType(accType)}, got ${formatStructuralType(elemType)} at index ${i}`);
107
- }
108
- accType = merged;
109
- }
110
- return accType;
111
- }
112
- /**
113
- * Merge uniform value types from two sides of the same compound type.
114
- * Sub-case A: both carry valueType -> recurse commonType.
115
- * Sub-case B: both carry structural fields -> extract value types, merge all.
116
- * Returns the merged RillType on success, undefined when no uniform merge applies.
117
- */
118
- function mergeUniformValueType(aValue, bValue, aFields, bFields) {
119
- // Sub-case A: both carry valueType
120
- if (aValue !== undefined && bValue !== undefined) {
121
- const merged = commonType(aValue, bValue);
122
- if (merged !== null)
123
- return merged;
124
- return undefined;
125
- }
126
- // Sub-case B: both carry structural fields
127
- if (aFields !== undefined && bFields !== undefined) {
128
- const allTypes = [
129
- ...aFields.map((f) => f.type),
130
- ...bFields.map((f) => f.type),
131
- ];
132
- if (allTypes.length === 0)
133
- return undefined;
134
- let merged = allTypes[0];
135
- for (let i = 1; i < allTypes.length; i++) {
136
- const next = commonType(merged, allTypes[i]);
137
- if (next === null)
138
- return undefined;
139
- merged = next;
140
- }
141
- return merged;
142
- }
143
- return undefined;
144
- }
145
- /**
146
- * Return the most specific shared type for two RillType values.
147
- * Returns null when types are incompatible at the top level.
148
6
  *
149
- * Cascade priority:
150
- * 1. Any-narrowing: if either side is `any`, return the other
151
- * 2. Structural match: delegate to structuralTypeEquals; on true, return a
152
- * 3. Recursive list: merge inner element types
153
- * 3b. Uniform valueType: merge dict/tuple/ordered value types
154
- * 4. Bare type fallback: same compound type but structural mismatch
155
- * 5. Incompatible: different top-level types return null
156
- */
157
- export function commonType(a, b) {
158
- // 1. Any-narrowing
159
- if (a.type === 'any')
160
- return b;
161
- if (b.type === 'any')
162
- return a;
163
- // 5. Incompatible top-level types (checked early to short-circuit)
164
- if (a.type !== b.type)
165
- return null;
166
- // 2. Structural match
167
- if (structuralTypeEquals(a, b))
168
- return a;
169
- // 3. Recursive list element merging
170
- if (a.type === 'list' && b.type === 'list') {
171
- if (a.element !== undefined && b.element !== undefined) {
172
- const inner = commonType(a.element, b.element);
173
- if (inner !== null)
174
- return { type: 'list', element: inner };
175
- }
176
- return { type: 'list' };
177
- }
178
- // 3b. Uniform valueType merging for dict/tuple/ordered
179
- if (a.type === 'dict' && b.type === 'dict') {
180
- const merged = mergeUniformValueType(a.valueType, b.valueType, a.fields ? Object.values(a.fields) : undefined, b.fields ? Object.values(b.fields) : undefined);
181
- if (merged !== undefined)
182
- return { type: 'dict', valueType: merged };
183
- }
184
- if (a.type === 'tuple' && b.type === 'tuple') {
185
- const merged = mergeUniformValueType(a.valueType, b.valueType, a.elements, b.elements);
186
- if (merged !== undefined)
187
- return { type: 'tuple', valueType: merged };
188
- }
189
- if (a.type === 'ordered' && b.type === 'ordered') {
190
- const merged = mergeUniformValueType(a.valueType, b.valueType, a.fields, b.fields);
191
- if (merged !== undefined)
192
- return { type: 'ordered', valueType: merged };
193
- }
194
- // 4. Bare type fallback for compound types.
195
- // The cast is safe for closure/dict/tuple/ordered (all sub-fields optional).
196
- // For union, members is required by RillType but omitted here intentionally:
197
- // bare union signals structural incompatibility without enumerating members.
198
- if (a.type === 'closure' ||
199
- a.type === 'dict' ||
200
- a.type === 'tuple' ||
201
- a.type === 'ordered' ||
202
- a.type === 'union') {
203
- return { type: a.type };
204
- }
205
- return null;
206
- }
207
- /** Compare two structural types for equality. */
208
- export function structuralTypeEquals(a, b) {
209
- if (a.type !== b.type)
210
- return false;
211
- // Leaf variants compare by type alone
212
- if (a.type === 'number' ||
213
- a.type === 'string' ||
214
- a.type === 'bool' ||
215
- a.type === 'vector' ||
216
- a.type === 'type' ||
217
- a.type === 'any') {
218
- return true;
219
- }
220
- if (a.type === 'list' && b.type === 'list') {
221
- if (a.element === undefined && b.element === undefined)
222
- return true;
223
- if (a.element === undefined || b.element === undefined)
224
- return false;
225
- return structuralTypeEquals(a.element, b.element);
226
- }
227
- if (a.type === 'dict' && b.type === 'dict') {
228
- // Uniform valueType comparison (mirrors list element at line 308)
229
- const aHasValue = a.valueType !== undefined;
230
- const bHasValue = b.valueType !== undefined;
231
- if (aHasValue || bHasValue) {
232
- if (!aHasValue || !bHasValue)
233
- return false;
234
- return structuralTypeEquals(a.valueType, b.valueType);
235
- }
236
- // Structural fields comparison
237
- if (a.fields === undefined && b.fields === undefined)
238
- return true;
239
- if (a.fields === undefined || b.fields === undefined)
240
- return false;
241
- const aKeys = Object.keys(a.fields).sort();
242
- const bKeys = Object.keys(b.fields).sort();
243
- if (aKeys.length !== bKeys.length)
244
- return false;
245
- for (let i = 0; i < aKeys.length; i++) {
246
- const key = aKeys[i];
247
- if (key !== bKeys[i])
248
- return false;
249
- const aField = a.fields[key];
250
- const bField = b.fields[key];
251
- const aHasDefault = aField.defaultValue !== undefined;
252
- const bHasDefault = bField.defaultValue !== undefined;
253
- if (aHasDefault !== bHasDefault)
254
- return false;
255
- if (!structuralTypeEquals(aField.type, bField.type))
256
- return false;
257
- if (aHasDefault && bHasDefault) {
258
- if (!deepEquals(aField.defaultValue, bField.defaultValue))
259
- return false;
260
- }
261
- }
262
- return true;
263
- }
264
- if (a.type === 'tuple' && b.type === 'tuple') {
265
- // Uniform valueType comparison (mirrors list element at line 308)
266
- const aHasValue = a.valueType !== undefined;
267
- const bHasValue = b.valueType !== undefined;
268
- if (aHasValue || bHasValue) {
269
- if (!aHasValue || !bHasValue)
270
- return false;
271
- return structuralTypeEquals(a.valueType, b.valueType);
272
- }
273
- // Structural elements comparison
274
- if (a.elements === undefined && b.elements === undefined)
275
- return true;
276
- if (a.elements === undefined || b.elements === undefined)
277
- return false;
278
- if (a.elements.length !== b.elements.length)
279
- return false;
280
- for (let i = 0; i < a.elements.length; i++) {
281
- const aElem = a.elements[i];
282
- const bElem = b.elements[i];
283
- if (!structuralTypeEquals(aElem.type, bElem.type))
284
- return false;
285
- const aDefault = aElem.defaultValue;
286
- const bDefault = bElem.defaultValue;
287
- if (aDefault === undefined && bDefault === undefined)
288
- continue;
289
- if (aDefault === undefined || bDefault === undefined)
290
- return false;
291
- if (!deepEquals(aDefault, bDefault))
292
- return false;
293
- }
294
- return true;
295
- }
296
- if (a.type === 'ordered' && b.type === 'ordered') {
297
- // Uniform valueType comparison (mirrors list element at line 308)
298
- const aHasValue = a.valueType !== undefined;
299
- const bHasValue = b.valueType !== undefined;
300
- if (aHasValue || bHasValue) {
301
- if (!aHasValue || !bHasValue)
302
- return false;
303
- return structuralTypeEquals(a.valueType, b.valueType);
304
- }
305
- // Structural fields comparison
306
- if (a.fields === undefined && b.fields === undefined)
307
- return true;
308
- if (a.fields === undefined || b.fields === undefined)
309
- return false;
310
- if (a.fields.length !== b.fields.length)
311
- return false;
312
- for (let i = 0; i < a.fields.length; i++) {
313
- const aField = a.fields[i];
314
- const bField = b.fields[i];
315
- if (aField.name !== bField.name)
316
- return false;
317
- if (!structuralTypeEquals(aField.type, bField.type))
318
- return false;
319
- const aDefault = aField.defaultValue;
320
- const bDefault = bField.defaultValue;
321
- if (aDefault === undefined && bDefault === undefined)
322
- continue;
323
- if (aDefault === undefined || bDefault === undefined)
324
- return false;
325
- if (!deepEquals(aDefault, bDefault))
326
- return false;
327
- }
328
- return true;
329
- }
330
- if (a.type === 'union' && b.type === 'union') {
331
- if (a.members.length !== b.members.length)
332
- return false;
333
- for (let i = 0; i < a.members.length; i++) {
334
- if (!structuralTypeEquals(a.members[i], b.members[i]))
335
- return false;
336
- }
337
- return true;
338
- }
339
- if (a.type === 'closure' && b.type === 'closure') {
340
- if (a.params === undefined && b.params === undefined) {
341
- // Both absent: compare ret
342
- }
343
- else if (a.params === undefined || b.params === undefined) {
344
- return false;
345
- }
346
- else {
347
- if (a.params.length !== b.params.length)
348
- return false;
349
- for (let i = 0; i < a.params.length; i++) {
350
- const aParam = a.params[i];
351
- const bParam = b.params[i];
352
- if (aParam.name !== bParam.name)
353
- return false;
354
- if (!structuralTypeEquals(aParam.type, bParam.type))
355
- return false;
356
- const aDefault = aParam.defaultValue;
357
- const bDefault = bParam.defaultValue;
358
- if (aDefault === undefined && bDefault === undefined)
359
- continue;
360
- if (aDefault === undefined || bDefault === undefined)
361
- return false;
362
- if (!deepEquals(aDefault, bDefault))
363
- return false;
364
- }
365
- }
366
- if (a.ret === undefined && b.ret === undefined)
367
- return true;
368
- if (a.ret === undefined || b.ret === undefined)
369
- return false;
370
- return structuralTypeEquals(a.ret, b.ret);
371
- }
372
- return false;
373
- }
374
- /** Infer the structural type descriptor for any Rill value. */
375
- export function inferStructuralType(value) {
376
- if (value === null || typeof value === 'string') {
377
- return { type: 'string' };
378
- }
379
- if (typeof value === 'number') {
380
- return { type: 'number' };
381
- }
382
- if (typeof value === 'boolean') {
383
- return { type: 'bool' };
384
- }
385
- if (isTypeValue(value)) {
386
- return { type: 'type' };
387
- }
388
- if (Array.isArray(value)) {
389
- return { type: 'list', element: inferElementType(value) };
390
- }
391
- if (isTuple(value)) {
392
- return {
393
- type: 'tuple',
394
- elements: value.entries.map((e) => ({
395
- type: inferStructuralType(e),
396
- })),
397
- };
398
- }
399
- if (isOrdered(value)) {
400
- return {
401
- type: 'ordered',
402
- fields: value.entries.map(([k, v]) => ({
403
- name: k,
404
- type: inferStructuralType(v),
405
- })),
406
- };
407
- }
408
- if (isVector(value)) {
409
- return { type: 'vector' };
410
- }
411
- if (isCallable(value)) {
412
- const params = (value.params ?? []).map((p) => paramToFieldDef(p.name, p.type ?? { type: 'any' }, p.defaultValue));
413
- const ret = value.returnType.structure;
414
- return { type: 'closure', params, ret };
415
- }
416
- if (typeof value === 'object') {
417
- const dict = value;
418
- const fields = {};
419
- for (const [k, v] of Object.entries(dict)) {
420
- fields[k] = { type: inferStructuralType(v) };
421
- }
422
- return { type: 'dict', fields };
423
- }
424
- throw new RuntimeError('RILL-R004', `Cannot infer structural type for ${formatValue(value)}`);
425
- }
426
- /**
427
- * Check if a value matches a structural type descriptor.
428
- * Used for runtime type checking (`:?` operator).
7
+ * Structural operations (structureEquals, structureMatches, formatStructure,
8
+ * inferStructure, commonType) live in types/operations.ts and are re-exported.
9
+ *
10
+ * Dispatch functions (inferType, formatValue, deepEquals, serializeValue,
11
+ * copyValue) re-export from type-registrations.ts protocol implementations.
429
12
  */
430
- export function structuralTypeMatches(value, type) {
431
- if (typeof value === 'undefined') {
432
- throw new RuntimeError('RILL-R004', 'Cannot type-check non-value');
433
- }
434
- if (type.type === 'any')
435
- return true;
436
- // Leaf primitive variants: match by inferred type name
437
- if (type.type === 'number' ||
438
- type.type === 'string' ||
439
- type.type === 'bool' ||
440
- type.type === 'vector' ||
441
- type.type === 'type') {
442
- return inferType(value) === type.type;
443
- }
444
- if (type.type === 'list') {
445
- if (!Array.isArray(value))
446
- return false;
447
- // Absent element sub-field: matches any list value
448
- if (type.element === undefined)
449
- return true;
450
- if (type.element.type === 'any')
451
- return true;
452
- return value.every((elem) => structuralTypeMatches(elem, type.element));
453
- }
454
- if (type.type === 'dict') {
455
- if (!isDict(value))
456
- return false;
457
- // Uniform value type check: every value must match valueType
458
- if (type.valueType !== undefined) {
459
- const vals = Object.values(value);
460
- return vals.every((v) => structuralTypeMatches(v, type.valueType));
461
- }
462
- // Absent fields sub-field: matches any dict value
463
- if (type.fields === undefined)
464
- return true;
465
- const dictKeys = Object.keys(type.fields);
466
- // Empty fields object matches any dict
467
- if (dictKeys.length === 0)
468
- return true;
469
- const dict = value;
470
- for (const key of dictKeys) {
471
- if (!(key in dict)) {
472
- const field = type.fields[key];
473
- if (field.defaultValue !== undefined)
474
- continue;
475
- return false;
476
- }
477
- const field = type.fields[key];
478
- if (!structuralTypeMatches(dict[key], field.type))
479
- return false;
480
- }
481
- return true;
482
- }
483
- if (type.type === 'tuple') {
484
- if (!isTuple(value))
485
- return false;
486
- // Uniform value type check: every entry must match valueType
487
- if (type.valueType !== undefined) {
488
- return value.entries.every((v) => structuralTypeMatches(v, type.valueType));
489
- }
490
- // Absent elements sub-field: matches any tuple value
491
- if (type.elements === undefined)
492
- return true;
493
- if (type.elements.length === 0)
494
- return value.entries.length === 0;
495
- // Reject if value has more entries than type elements
496
- if (value.entries.length > type.elements.length)
497
- return false;
498
- // Reject if value is shorter and any trailing missing element lacks a default
499
- if (value.entries.length < type.elements.length) {
500
- for (let i = value.entries.length; i < type.elements.length; i++) {
501
- const field = type.elements[i];
502
- if (field.defaultValue === undefined)
503
- return false;
504
- }
505
- }
506
- for (let i = 0; i < value.entries.length; i++) {
507
- if (!structuralTypeMatches(value.entries[i], type.elements[i].type))
508
- return false;
509
- }
510
- return true;
511
- }
512
- if (type.type === 'ordered') {
513
- if (!isOrdered(value))
514
- return false;
515
- // Uniform value type check: every entry value must match valueType
516
- if (type.valueType !== undefined) {
517
- return value.entries.every(([, v]) => structuralTypeMatches(v, type.valueType));
518
- }
519
- // Absent fields sub-field: matches any ordered value
520
- if (type.fields === undefined)
521
- return true;
522
- if (type.fields.length === 0)
523
- return value.entries.length === 0;
524
- // Reject if value has more entries than type fields
525
- if (value.entries.length > type.fields.length)
526
- return false;
527
- // Reject if value is shorter and any trailing missing field lacks a default
528
- if (value.entries.length < type.fields.length) {
529
- for (let i = value.entries.length; i < type.fields.length; i++) {
530
- const field = type.fields[i];
531
- if (field.defaultValue === undefined)
532
- return false;
533
- }
534
- }
535
- for (let i = 0; i < value.entries.length; i++) {
536
- const field = type.fields[i];
537
- const [actualName, actualValue] = value.entries[i];
538
- if (actualName !== field.name)
539
- return false;
540
- if (!structuralTypeMatches(actualValue, field.type))
541
- return false;
542
- }
543
- return true;
544
- }
545
- if (type.type === 'closure') {
546
- if (!isCallable(value))
547
- return false;
548
- // Absent params sub-field: matches any closure value of that compound type
549
- if (type.params === undefined)
550
- return true;
551
- const valueParams = value.params ?? [];
552
- if (valueParams.length !== type.params.length)
553
- return false;
554
- for (let i = 0; i < type.params.length; i++) {
555
- const field = type.params[i];
556
- const param = valueParams[i];
557
- if (param.name !== field.name)
558
- return false;
559
- const paramType = param.type ?? { type: 'any' };
560
- if (!structuralTypeEquals(paramType, field.type))
561
- return false;
562
- }
563
- const retType = value.returnType.structure;
564
- if (type.ret === undefined)
565
- return true;
566
- return structuralTypeEquals(retType, type.ret);
567
- }
568
- if (type.type === 'union') {
569
- return type.members.some((member) => structuralTypeMatches(value, member));
570
- }
571
- return false;
572
- }
573
- /** Build a closure param field definition from name, type, and optional default. */
574
- export function paramToFieldDef(name, type, defaultValue) {
575
- const field = { name, type };
576
- if (defaultValue !== undefined)
577
- field.defaultValue = defaultValue;
578
- return field;
579
- }
580
- /** Format a RillValue as a rill literal for use in type signatures. */
581
- function formatRillLiteral(value) {
582
- if (typeof value === 'string') {
583
- const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
584
- return `"${escaped}"`;
585
- }
586
- if (typeof value === 'number')
587
- return String(value);
588
- if (typeof value === 'boolean')
589
- return value ? 'true' : 'false';
590
- if (value === null)
591
- return 'null';
592
- return formatValue(value);
593
- }
594
- /** Format a structural type descriptor as a human-readable string. */
595
- export function formatStructuralType(type) {
596
- if (type.type === 'any' ||
597
- type.type === 'number' ||
598
- type.type === 'string' ||
599
- type.type === 'bool' ||
600
- type.type === 'vector' ||
601
- type.type === 'type') {
602
- return type.type;
603
- }
604
- if (type.type === 'list') {
605
- if (type.element === undefined)
606
- return 'list';
607
- return `list(${formatStructuralType(type.element)})`;
608
- }
609
- if (type.type === 'dict') {
610
- if (type.valueType !== undefined && type.fields === undefined) {
611
- return `dict(${formatStructuralType(type.valueType)})`;
612
- }
613
- if (type.fields === undefined)
614
- return 'dict';
615
- const parts = Object.keys(type.fields)
616
- .sort()
617
- .map((k) => {
618
- const field = type.fields[k];
619
- const base = `${k}: ${formatStructuralType(field.type)}`;
620
- if (field.defaultValue === undefined)
621
- return base;
622
- return `${base} = ${formatRillLiteral(field.defaultValue)}`;
623
- });
624
- return `dict(${parts.join(', ')})`;
625
- }
626
- if (type.type === 'tuple') {
627
- if (type.valueType !== undefined && type.elements === undefined) {
628
- return `tuple(${formatStructuralType(type.valueType)})`;
629
- }
630
- if (type.elements === undefined)
631
- return 'tuple';
632
- const parts = type.elements.map((field) => {
633
- const base = formatStructuralType(field.type);
634
- if (field.defaultValue === undefined)
635
- return base;
636
- return `${base} = ${formatRillLiteral(field.defaultValue)}`;
637
- });
638
- return `tuple(${parts.join(', ')})`;
639
- }
640
- if (type.type === 'ordered') {
641
- if (type.valueType !== undefined && type.fields === undefined) {
642
- return `ordered(${formatStructuralType(type.valueType)})`;
643
- }
644
- if (type.fields === undefined)
645
- return 'ordered';
646
- const parts = type.fields.map((field) => {
647
- const base = `${field.name}: ${formatStructuralType(field.type)}`;
648
- if (field.defaultValue === undefined)
649
- return base;
650
- return `${base} = ${formatRillLiteral(field.defaultValue)}`;
651
- });
652
- return `ordered(${parts.join(', ')})`;
653
- }
654
- if (type.type === 'closure') {
655
- if (type.params === undefined)
656
- return 'closure';
657
- const params = type.params
658
- .map((field) => {
659
- const base = `${field.name}: ${formatStructuralType(field.type)}`;
660
- if (field.defaultValue === undefined)
661
- return base;
662
- return `${base} = ${formatRillLiteral(field.defaultValue)}`;
663
- })
664
- .join(', ');
665
- const ret = type.ret !== undefined ? formatStructuralType(type.ret) : 'any';
666
- return `|${params}| :${ret}`;
667
- }
668
- if (type.type === 'union') {
669
- return type.members.map(formatStructuralType).join('|');
670
- }
671
- return 'any';
672
- }
13
+ import { VALID_TYPE_NAMES } from '../../constants.js';
14
+ import { isCallable as _isCallableGuard, isDict, isIterator, isOrdered, isStream, isTuple, isTypeValue, isVector, } from './types/guards.js';
15
+ /** isCallable guard widened to narrow to full RillCallable (not just CallableMarker) */
16
+ const isCallable = _isCallableGuard;
17
+ import { inferType as registryInferType, formatValue as registryFormatValue, deepEquals as registryDeepEquals, serializeValue as registrySerializeValue, } from './types/registrations.js';
18
+ // Re-export guards from canonical source (types/guards.ts)
19
+ export { isCallable, isDict, isIterator, isOrdered, isStream, isTuple, isTypeValue, isVector, };
20
+ // Value constructors re-exported from canonical source (types/constructors.ts)
21
+ export { copyValue, createOrdered, createTuple, createVector, emptyForType, } from './types/constructors.js';
22
+ // Structural operations re-exported from types/operations.ts
23
+ export { commonType, compareStructuredFields, formatStructure, inferElementType, inferStructure, paramToFieldDef, structureEquals, structureMatches, } from './types/operations.js';
24
+ // Re-import for local use (toNative, structureToTypeValue)
25
+ import { formatStructure, inferStructure } from './types/operations.js';
26
+ /** Infer the Rill type from a runtime value. Delegates to type-registrations. */
27
+ export const inferType = registryInferType;
673
28
  /**
674
29
  * Check if a value is of the expected type.
675
30
  * Returns true if the value matches the expected type, false otherwise.
@@ -706,88 +61,10 @@ export function isTruthy(value) {
706
61
  export function isEmpty(value) {
707
62
  return !isTruthy(value);
708
63
  }
709
- /** Format a value for display */
710
- export function formatValue(value) {
711
- if (value === null)
712
- return 'type(null)';
713
- if (typeof value === 'string')
714
- return value;
715
- if (typeof value === 'number')
716
- return String(value);
717
- if (typeof value === 'boolean')
718
- return value ? 'true' : 'false';
719
- if (isCallable(value)) {
720
- return 'type(closure)';
721
- }
722
- if (isTuple(value)) {
723
- return `tuple[${value.entries.map(formatValue).join(', ')}]`;
724
- }
725
- if (isOrdered(value)) {
726
- const parts = value.entries.map(([k, v]) => `${k}: ${formatValue(v)}`);
727
- return `ordered[${parts.join(', ')}]`;
728
- }
729
- if (isRillIterator(value)) {
730
- return 'type(iterator)';
731
- }
732
- if (Array.isArray(value)) {
733
- return `list[${value.map(formatValue).join(', ')}]`;
734
- }
735
- if (isVector(value)) {
736
- return `vector(${value.model}, ${value.data.length}d)`;
737
- }
738
- if (isTypeValue(value)) {
739
- return formatStructuralType(value.structure);
740
- }
741
- // Plain dict
742
- if (typeof value === 'object') {
743
- const dict = value;
744
- const parts = Object.entries(dict).map(([k, v]) => `${k}: ${formatValue(v)}`);
745
- return `dict[${parts.join(', ')}]`;
746
- }
747
- return String(value);
748
- }
749
- /**
750
- * Convert a RillValue to a JSON-serializable value.
751
- * @throws {Error} plain Error (not RuntimeError) for non-serializable types
752
- */
753
- export function valueToJSON(value) {
754
- if (value === null)
755
- return null;
756
- if (typeof value === 'string')
757
- return value;
758
- if (typeof value === 'number')
759
- return value;
760
- if (typeof value === 'boolean')
761
- return value;
762
- if (Array.isArray(value)) {
763
- return value.map(valueToJSON);
764
- }
765
- if (isCallable(value)) {
766
- throw new Error('closures are not JSON-serializable');
767
- }
768
- if (isTuple(value)) {
769
- throw new Error('tuples are not JSON-serializable');
770
- }
771
- if (isOrdered(value)) {
772
- throw new Error('ordered values are not JSON-serializable');
773
- }
774
- if (isVector(value)) {
775
- throw new Error('vectors are not JSON-serializable');
776
- }
777
- if (isTypeValue(value)) {
778
- throw new Error('type values are not JSON-serializable');
779
- }
780
- if (isRillIterator(value)) {
781
- throw new Error('iterators are not JSON-serializable');
782
- }
783
- // Plain dict
784
- const dict = value;
785
- const result = {};
786
- for (const [k, v] of Object.entries(dict)) {
787
- result[k] = valueToJSON(v);
788
- }
789
- return result;
790
- }
64
+ /** Format a value for display. Delegates to type-registrations. */
65
+ export const formatValue = registryFormatValue;
66
+ /** Serialize a Rill value for JSON transport. Delegates to type-registrations. */
67
+ export const serializeValue = registrySerializeValue;
791
68
  /**
792
69
  * Convert a RillValue to a NativeResult for host consumption.
793
70
  * Non-representable types (closures, vectors, type values, iterators) produce descriptor objects.
@@ -795,7 +72,7 @@ export function valueToJSON(value) {
795
72
  */
796
73
  export function toNative(value) {
797
74
  const rillTypeName = inferType(value);
798
- const rillTypeSignature = formatStructuralType(inferStructuralType(value));
75
+ const rillTypeSignature = formatStructure(inferStructure(value));
799
76
  const nativeValue = toNativeValue(value);
800
77
  return { rillTypeName, rillTypeSignature, value: nativeValue };
801
78
  }
@@ -812,7 +89,7 @@ function toNativeValue(value) {
812
89
  return value.map(toNativeValue);
813
90
  }
814
91
  if (isCallable(value)) {
815
- return { signature: formatStructuralType(inferStructuralType(value)) };
92
+ return { signature: formatStructure(inferStructure(value)) };
816
93
  }
817
94
  if (isTuple(value)) {
818
95
  return value.entries.map(toNativeValue);
@@ -830,10 +107,21 @@ function toNativeValue(value) {
830
107
  if (isTypeValue(value)) {
831
108
  return {
832
109
  name: value.typeName,
833
- signature: formatStructuralType(value.structure),
110
+ signature: formatStructure(value.structure),
111
+ };
112
+ }
113
+ if (isStream(value)) {
114
+ const descriptor = {
115
+ __type: 'stream',
116
+ done: value.done,
834
117
  };
118
+ const chunkType = value['__rill_stream_chunk_type'];
119
+ const retType = value['__rill_stream_ret_type'];
120
+ descriptor['chunkType'] = chunkType ? formatStructure(chunkType) : null;
121
+ descriptor['resolutionType'] = retType ? formatStructure(retType) : null;
122
+ return descriptor;
835
123
  }
836
- if (isRillIterator(value)) {
124
+ if (isIterator(value)) {
837
125
  return { done: value.done };
838
126
  }
839
127
  // Plain dict
@@ -844,152 +132,8 @@ function toNativeValue(value) {
844
132
  }
845
133
  return result;
846
134
  }
847
- /**
848
- * Deep structural equality for all Rill values.
849
- * - Primitives: value equality
850
- * - Tuples: length + recursive element equality
851
- * - Dicts: same keys + recursive value equality (order-independent)
852
- */
853
- export function deepEquals(a, b) {
854
- // Handle primitives and null
855
- if (a === b)
856
- return true;
857
- if (a === null || b === null)
858
- return false;
859
- if (typeof a !== typeof b)
860
- return false;
861
- // Primitives (string, number, boolean) - covered by === above
862
- if (typeof a !== 'object' || typeof b !== 'object')
863
- return false;
864
- // Both are non-null objects at this point
865
- const aObj = a;
866
- const bObj = b;
867
- // Check for tuples (positional spread args)
868
- const aIsTuple = isTuple(a);
869
- const bIsTuple = isTuple(b);
870
- if (aIsTuple !== bIsTuple)
871
- return false;
872
- if (aIsTuple && bIsTuple) {
873
- if (a.entries.length !== b.entries.length)
874
- return false;
875
- for (let i = 0; i < a.entries.length; i++) {
876
- const aVal = a.entries[i];
877
- const bVal = b.entries[i];
878
- if (aVal === undefined || bVal === undefined) {
879
- if (aVal !== bVal)
880
- return false;
881
- }
882
- else if (!deepEquals(aVal, bVal)) {
883
- return false;
884
- }
885
- }
886
- return true;
887
- }
888
- // Check for ordered (named spread args)
889
- const aIsOrdered = isOrdered(a);
890
- const bIsOrdered = isOrdered(b);
891
- if (aIsOrdered !== bIsOrdered)
892
- return false;
893
- if (aIsOrdered && bIsOrdered) {
894
- if (a.entries.length !== b.entries.length)
895
- return false;
896
- for (let i = 0; i < a.entries.length; i++) {
897
- const aEntry = a.entries[i];
898
- const bEntry = b.entries[i];
899
- if (aEntry === undefined || bEntry === undefined)
900
- return false;
901
- if (aEntry[0] !== bEntry[0])
902
- return false;
903
- if (!deepEquals(aEntry[1], bEntry[1]))
904
- return false;
905
- }
906
- return true;
907
- }
908
- // Check for vectors
909
- const aIsVector = isVector(a);
910
- const bIsVector = isVector(b);
911
- if (aIsVector !== bIsVector)
912
- return false;
913
- if (aIsVector && bIsVector) {
914
- // Vectors equal when model matches AND all float elements match
915
- if (a.model !== b.model)
916
- return false;
917
- if (a.data.length !== b.data.length)
918
- return false;
919
- for (let i = 0; i < a.data.length; i++) {
920
- const aVal = a.data[i];
921
- const bVal = b.data[i];
922
- if (aVal !== bVal)
923
- return false;
924
- }
925
- return true;
926
- }
927
- // Check for type values (first-class type names)
928
- const aIsTypeValue = isTypeValue(a);
929
- const bIsTypeValue = isTypeValue(b);
930
- if (aIsTypeValue !== bIsTypeValue)
931
- return false;
932
- if (aIsTypeValue && bIsTypeValue) {
933
- return structuralTypeEquals(a.structure, b.structure);
934
- }
935
- // Check for arrays (lists)
936
- const aIsArray = Array.isArray(a);
937
- const bIsArray = Array.isArray(b);
938
- if (aIsArray !== bIsArray)
939
- return false;
940
- if (aIsArray && bIsArray) {
941
- if (a.length !== b.length)
942
- return false;
943
- for (let i = 0; i < a.length; i++) {
944
- const aElem = a[i];
945
- const bElem = b[i];
946
- if (aElem === undefined || bElem === undefined) {
947
- if (aElem !== bElem)
948
- return false;
949
- }
950
- else if (!deepEquals(aElem, bElem)) {
951
- return false;
952
- }
953
- }
954
- return true;
955
- }
956
- // Both are dicts (plain objects) or callables
957
- // For script callables, use structural equality (params + body AST + captured values)
958
- // For runtime/application callables, use reference equality
959
- if ('__type' in aObj || '__type' in bObj) {
960
- // Both must be callables to be equal
961
- if (!('__type' in aObj) || !('__type' in bObj))
962
- return false;
963
- if (aObj.__type !== 'callable' || bObj.__type !== 'callable')
964
- return false;
965
- // Script callables: structural equality
966
- if (isScriptCallable(a) && isScriptCallable(b)) {
967
- return callableEquals(a, b, deepEquals);
968
- }
969
- // Runtime/application callables: reference equality
970
- return a === b;
971
- }
972
- const aDict = a;
973
- const bDict = b;
974
- const aKeys = Object.keys(aDict);
975
- const bKeys = Object.keys(bDict);
976
- if (aKeys.length !== bKeys.length)
977
- return false;
978
- for (const key of aKeys) {
979
- if (!(key in bDict))
980
- return false;
981
- const aVal = aDict[key];
982
- const bVal = bDict[key];
983
- if (aVal === undefined || bVal === undefined) {
984
- if (aVal !== bVal)
985
- return false;
986
- }
987
- else if (!deepEquals(aVal, bVal)) {
988
- return false;
989
- }
990
- }
991
- return true;
992
- }
135
+ /** Deep structural equality for all Rill values. Delegates to type-registrations. */
136
+ export const deepEquals = registryDeepEquals;
993
137
  /** Reserved dict method names that cannot be overridden */
994
138
  export const RESERVED_DICT_METHODS = ['keys', 'values', 'entries'];
995
139
  /**
@@ -999,19 +143,19 @@ export const RESERVED_DICT_METHODS = ['keys', 'values', 'entries'];
999
143
  export const anyTypeValue = Object.freeze({
1000
144
  __rill_type: true,
1001
145
  typeName: 'any',
1002
- structure: { type: 'any' },
146
+ structure: { kind: 'any' },
1003
147
  });
1004
148
  /**
1005
- * Convert a RillType structural descriptor to a RillTypeValue.
1006
- * Uses the RillType's `type` field as the `typeName`.
149
+ * Convert a TypeStructure descriptor to a RillTypeValue.
150
+ * Uses the TypeStructure's `kind` field as the `typeName`.
1007
151
  * Falls back to 'any' for compound types that lack a direct RillTypeName mapping.
1008
152
  */
1009
- export function rillTypeToTypeValue(type) {
153
+ export function structureToTypeValue(type) {
1010
154
  const validNames = VALID_TYPE_NAMES;
1011
155
  return Object.freeze({
1012
156
  __rill_type: true,
1013
- typeName: (validNames.includes(type.type)
1014
- ? type.type
157
+ typeName: (validNames.includes(type.kind)
158
+ ? type.kind
1015
159
  : 'any'),
1016
160
  structure: type,
1017
161
  });
@@ -1022,73 +166,17 @@ export function rillTypeToTypeValue(type) {
1022
166
  * synthesized and hydrated.
1023
167
  */
1024
168
  export function hasCollectionFields(type) {
1025
- return ((type.type === 'dict' && (!!type.fields || !!type.valueType)) ||
1026
- (type.type === 'ordered' && (!!type.fields || !!type.valueType)) ||
1027
- (type.type === 'tuple' && (!!type.elements || !!type.valueType)));
1028
- }
1029
- /**
1030
- * Create an empty collection value matching the given RillType.
1031
- * Assumes the type is dict, ordered, or tuple.
1032
- */
1033
- export function emptyForType(type) {
1034
- if (type.type === 'dict')
1035
- return {};
1036
- if (type.type === 'ordered')
1037
- return createOrdered([]);
1038
- if (type.type === 'tuple')
1039
- return createTuple([]);
1040
- return {};
169
+ return ((type.kind === 'dict' &&
170
+ (!!type.fields ||
171
+ !!type.valueType)) ||
172
+ (type.kind === 'ordered' &&
173
+ (!!type.fields ||
174
+ !!type.valueType)) ||
175
+ (type.kind === 'tuple' &&
176
+ (!!type.elements ||
177
+ !!type.valueType)));
1041
178
  }
1042
179
  /** Check if a key name is reserved */
1043
180
  export function isReservedMethod(name) {
1044
181
  return RESERVED_DICT_METHODS.includes(name);
1045
182
  }
1046
- /**
1047
- * Type guard for Rill iterator (lazy sequence).
1048
- * An iterator is a dict with:
1049
- * - done: boolean - whether iteration is complete
1050
- * - next: callable - function to get next iterator
1051
- * - value: any (only required when not done) - current element
1052
- */
1053
- export function isRillIterator(value) {
1054
- if (!isDict(value))
1055
- return false;
1056
- const dict = value;
1057
- if (!('done' in dict && typeof dict['done'] === 'boolean'))
1058
- return false;
1059
- if (!('next' in dict && isCallable(dict['next'])))
1060
- return false;
1061
- // 'value' field only required when not done
1062
- if (!dict['done'] && !('value' in dict))
1063
- return false;
1064
- return true;
1065
- }
1066
- /**
1067
- * Deep copy a RillValue, producing a new independent value.
1068
- * Handles primitives, arrays, plain dicts, and null.
1069
- * Special markers (closures, tuples, ordered, vectors, type values) are returned
1070
- * as-is since they are immutable by contract.
1071
- */
1072
- export function deepCopyRillValue(value) {
1073
- if (value === null || typeof value !== 'object') {
1074
- return value;
1075
- }
1076
- if (Array.isArray(value)) {
1077
- return value.map(deepCopyRillValue);
1078
- }
1079
- // Plain dict: copy recursively. Special markers (RillTuple, RillOrdered, etc.)
1080
- // carry __rill_* own properties and are treated as immutable; return as-is.
1081
- if (!('__rill_tuple' in value) &&
1082
- !('__rill_ordered' in value) &&
1083
- !('__rill_vector' in value) &&
1084
- !('__rill_type' in value) &&
1085
- !('__type' in value) &&
1086
- !('__rill_field_descriptor' in value)) {
1087
- const copy = {};
1088
- for (const [k, v] of Object.entries(value)) {
1089
- copy[k] = deepCopyRillValue(v);
1090
- }
1091
- return copy;
1092
- }
1093
- return value;
1094
- }