@rcrsr/rill 0.16.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 (57) hide show
  1. package/README.md +37 -21
  2. package/dist/ext/crypto/index.d.ts +3 -3
  3. package/dist/ext/crypto/index.js +61 -58
  4. package/dist/ext/exec/index.d.ts +3 -3
  5. package/dist/ext/exec/index.js +14 -8
  6. package/dist/ext/fetch/index.d.ts +3 -3
  7. package/dist/ext/fetch/index.js +16 -11
  8. package/dist/ext/fs/index.d.ts +3 -3
  9. package/dist/ext/fs/index.js +242 -239
  10. package/dist/ext/kv/index.d.ts +3 -3
  11. package/dist/ext/kv/index.js +197 -195
  12. package/dist/ext/kv/store.js +2 -1
  13. package/dist/ext-parse-bridge.d.ts +10 -0
  14. package/dist/ext-parse-bridge.js +10 -0
  15. package/dist/generated/introspection-data.d.ts +1 -1
  16. package/dist/generated/introspection-data.js +385 -296
  17. package/dist/generated/version-data.d.ts +1 -1
  18. package/dist/generated/version-data.js +2 -2
  19. package/dist/index.d.ts +15 -4
  20. package/dist/index.js +14 -5
  21. package/dist/parser/parser-types.js +12 -0
  22. package/dist/parser/parser-use.js +7 -1
  23. package/dist/runtime/core/callable.d.ts +20 -8
  24. package/dist/runtime/core/callable.js +63 -23
  25. package/dist/runtime/core/context.d.ts +0 -11
  26. package/dist/runtime/core/context.js +76 -75
  27. package/dist/runtime/core/eval/index.d.ts +2 -2
  28. package/dist/runtime/core/eval/index.js +11 -0
  29. package/dist/runtime/core/eval/mixins/closures.js +15 -15
  30. package/dist/runtime/core/eval/mixins/conversion.js +51 -110
  31. package/dist/runtime/core/eval/mixins/core.js +2 -2
  32. package/dist/runtime/core/eval/mixins/expressions.js +35 -27
  33. package/dist/runtime/core/eval/mixins/literals.js +3 -3
  34. package/dist/runtime/core/eval/mixins/types.js +44 -54
  35. package/dist/runtime/core/eval/mixins/variables.js +10 -8
  36. package/dist/runtime/core/field-descriptor.d.ts +3 -3
  37. package/dist/runtime/core/field-descriptor.js +2 -1
  38. package/dist/runtime/core/introspection.js +6 -6
  39. package/dist/runtime/core/markers.d.ts +12 -0
  40. package/dist/runtime/core/markers.js +7 -0
  41. package/dist/runtime/core/type-registrations.d.ts +136 -0
  42. package/dist/runtime/core/type-registrations.js +749 -0
  43. package/dist/runtime/core/type-structures.d.ts +128 -0
  44. package/dist/runtime/core/type-structures.js +12 -0
  45. package/dist/runtime/core/types.d.ts +15 -3
  46. package/dist/runtime/core/values.d.ts +62 -153
  47. package/dist/runtime/core/values.js +308 -524
  48. package/dist/runtime/ext/builtins.js +83 -64
  49. package/dist/runtime/ext/extensions.d.ts +30 -124
  50. package/dist/runtime/ext/extensions.js +0 -93
  51. package/dist/runtime/ext/test-context.d.ts +28 -0
  52. package/dist/runtime/ext/test-context.js +154 -0
  53. package/dist/runtime/index.d.ts +22 -8
  54. package/dist/runtime/index.js +18 -4
  55. package/dist/signature-parser.d.ts +2 -2
  56. package/dist/signature-parser.js +14 -14
  57. package/package.json +1 -1
@@ -23,21 +23,8 @@
23
23
  * @internal
24
24
  */
25
25
  import { RuntimeError } from '../../../../types.js';
26
- import { inferType, checkType, isTypeValue, structuralTypeMatches, inferStructuralType, formatStructuralType, } from '../../values.js';
26
+ import { inferType, checkType, isTypeValue, structureMatches, inferStructure, formatStructure, } from '../../values.js';
27
27
  import { getVariable } from '../../context.js';
28
- /**
29
- * Leaf types that reject all type arguments.
30
- * Extracted as module-level constant to avoid per-call allocation.
31
- */
32
- const LEAF_TYPES = new Set([
33
- 'string',
34
- 'number',
35
- 'bool',
36
- 'vector',
37
- 'type',
38
- 'any',
39
- 'closure',
40
- ]);
41
28
  /**
42
29
  * TypesMixin implementation.
43
30
  *
@@ -87,7 +74,7 @@ function createTypesMixin(Base) {
87
74
  throw new RuntimeError('RILL-R004', 'list() requires exactly 1 type argument', location);
88
75
  }
89
76
  const element = await resolveArg(args[0]);
90
- const structure = { type: 'list', element };
77
+ const structure = { kind: 'list', element };
91
78
  return Object.freeze({
92
79
  __rill_type: true,
93
80
  typeName: name,
@@ -107,11 +94,11 @@ function createTypesMixin(Base) {
107
94
  // EC-B6: Default type mismatch on uniform single-arg path
108
95
  if (positional[0].defaultValue !== undefined) {
109
96
  const defaultVal = await evaluateDefault(positional[0].defaultValue);
110
- if (!structuralTypeMatches(defaultVal, valueType)) {
111
- throw new RuntimeError('RILL-R004', `Default value for ${name} element must be ${formatStructuralType(valueType)}, got ${inferType(defaultVal)}`, location);
97
+ if (!structureMatches(defaultVal, valueType)) {
98
+ throw new RuntimeError('RILL-R004', `Default value for ${name} element must be ${formatStructure(valueType)}, got ${inferType(defaultVal)}`, location);
112
99
  }
113
100
  }
114
- const structure = { type: name, valueType };
101
+ const structure = { kind: name, valueType };
115
102
  return Object.freeze({
116
103
  __rill_type: true,
117
104
  typeName: name,
@@ -131,14 +118,14 @@ function createTypesMixin(Base) {
131
118
  if (arg.defaultValue !== undefined) {
132
119
  const defaultVal = await evaluateDefault(arg.defaultValue);
133
120
  // EC-B6: Default type mismatch
134
- if (!structuralTypeMatches(defaultVal, resolvedType)) {
135
- throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructuralType(resolvedType)}, got ${inferType(defaultVal)}`, location);
121
+ if (!structureMatches(defaultVal, resolvedType)) {
122
+ throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
136
123
  }
137
124
  fieldDef.defaultValue = defaultVal;
138
125
  }
139
126
  fields[arg.name] = fieldDef;
140
127
  }
141
- const structure = { type: 'dict', fields };
128
+ const structure = { kind: 'dict', fields };
142
129
  return Object.freeze({
143
130
  __rill_type: true,
144
131
  typeName: name,
@@ -156,14 +143,17 @@ function createTypesMixin(Base) {
156
143
  if (arg.defaultValue !== undefined) {
157
144
  const defaultVal = await evaluateDefault(arg.defaultValue);
158
145
  // EC-B6: Default type mismatch
159
- if (!structuralTypeMatches(defaultVal, resolvedType)) {
160
- throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructuralType(resolvedType)}, got ${inferType(defaultVal)}`, location);
146
+ if (!structureMatches(defaultVal, resolvedType)) {
147
+ throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
161
148
  }
162
149
  fieldDef.defaultValue = defaultVal;
163
150
  }
164
151
  orderedFields.push(fieldDef);
165
152
  }
166
- const structure = { type: 'ordered', fields: orderedFields };
153
+ const structure = {
154
+ kind: 'ordered',
155
+ fields: orderedFields,
156
+ };
167
157
  return Object.freeze({
168
158
  __rill_type: true,
169
159
  typeName: name,
@@ -183,11 +173,11 @@ function createTypesMixin(Base) {
183
173
  // EC-B6: Default type mismatch on uniform single-arg path
184
174
  if (args[0].defaultValue !== undefined) {
185
175
  const defaultVal = await evaluateDefault(args[0].defaultValue);
186
- if (!structuralTypeMatches(defaultVal, valueType)) {
187
- throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${formatStructuralType(valueType)}, got ${inferType(defaultVal)}`, location);
176
+ if (!structureMatches(defaultVal, valueType)) {
177
+ throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${formatStructure(valueType)}, got ${inferType(defaultVal)}`, location);
188
178
  }
189
179
  }
190
- const structure = { type: 'tuple', valueType };
180
+ const structure = { kind: 'tuple', valueType };
191
181
  return Object.freeze({
192
182
  __rill_type: true,
193
183
  typeName: 'tuple',
@@ -202,8 +192,8 @@ function createTypesMixin(Base) {
202
192
  if (arg.defaultValue !== undefined) {
203
193
  const defaultVal = await evaluateDefault(arg.defaultValue);
204
194
  // EC-B6: Default type mismatch
205
- if (!structuralTypeMatches(defaultVal, resolvedType)) {
206
- throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${formatStructuralType(resolvedType)}, got ${inferType(defaultVal)}`, location);
195
+ if (!structureMatches(defaultVal, resolvedType)) {
196
+ throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
207
197
  }
208
198
  fieldDef.defaultValue = defaultVal;
209
199
  }
@@ -221,7 +211,7 @@ function createTypesMixin(Base) {
221
211
  throw new RuntimeError('RILL-R004', `tuple() default values must be trailing: element at position ${i} has no default but a preceding element does`, location);
222
212
  }
223
213
  }
224
- const structure = { type: 'tuple', elements };
214
+ const structure = { kind: 'tuple', elements };
225
215
  return Object.freeze({
226
216
  __rill_type: true,
227
217
  typeName: 'tuple',
@@ -254,11 +244,11 @@ function createTypesMixin(Base) {
254
244
  return Object.freeze({
255
245
  __rill_type: true,
256
246
  typeName,
257
- structure: { type: typeName },
247
+ structure: { kind: typeName },
258
248
  });
259
249
  }
260
- // EC-B1: Leaf types reject all type arguments
261
- if (LEAF_TYPES.has(typeName)) {
250
+ // EC-B1: Leaf types reject all type arguments (AC-4: derived from registrations)
251
+ if (this.ctx.leafTypes.has(typeName)) {
262
252
  throw new RuntimeError('RILL-R004', `${typeName} does not accept type arguments`);
263
253
  }
264
254
  // Delegate to buildCollectionType with recursive resolveTypeRef
@@ -271,7 +261,7 @@ function createTypesMixin(Base) {
271
261
  });
272
262
  }
273
263
  // Union type ref: (A | B) -- resolve each member recursively and
274
- // return a RillTypeValue with structure: { type: 'union', members: [...] }.
264
+ // return a RillTypeValue with structure: { kind: 'union', members: [...] }.
275
265
  // typeName is set to a display string for error messages; the structure
276
266
  // field carries the authoritative type shape for validation (DR-1).
277
267
  if (typeRef.kind === 'union') {
@@ -280,9 +270,9 @@ function createTypesMixin(Base) {
280
270
  const resolved = await this.resolveTypeRef(member, getVariableFn);
281
271
  members.push(resolved.structure);
282
272
  }
283
- const structure = { type: 'union', members };
273
+ const structure = { kind: 'union', members };
284
274
  const displayName = members
285
- .map(formatStructuralType)
275
+ .map(formatStructure)
286
276
  .join('|');
287
277
  return Object.freeze({
288
278
  __rill_type: true,
@@ -301,13 +291,13 @@ function createTypesMixin(Base) {
301
291
  /**
302
292
  * Assert that a value is of the expected type.
303
293
  * Returns the value unchanged if assertion passes, throws on mismatch.
304
- * Accepts a bare RillTypeName or a full RillType.
305
- * When expected is a RillType with sub-fields (element, fields, elements),
306
- * dispatches to structuralTypeMatches for deep validation.
294
+ * Accepts a bare RillTypeName or a full TypeStructure.
295
+ * When expected is a TypeStructure with sub-fields (element, fields, elements),
296
+ * dispatches to structureMatches for deep validation.
307
297
  * Exported for use by type assertion evaluation.
308
298
  */
309
299
  assertType(value, expected, location) {
310
- // Structural path: expected is a RillType object
300
+ // Structural path: expected is a TypeStructure object
311
301
  if (typeof expected !== 'string') {
312
302
  const hasSubFields = 'element' in expected ||
313
303
  'fields' in expected ||
@@ -315,15 +305,15 @@ function createTypesMixin(Base) {
315
305
  'members' in expected ||
316
306
  'valueType' in expected;
317
307
  if (hasSubFields) {
318
- if (!structuralTypeMatches(value, expected)) {
319
- const expectedStr = formatStructuralType(expected);
320
- const actualStr = formatStructuralType(inferStructuralType(value));
308
+ if (!structureMatches(value, expected)) {
309
+ const expectedStr = formatStructure(expected);
310
+ const actualStr = formatStructure(inferStructure(value));
321
311
  throw new RuntimeError('RILL-R004', `Type assertion failed: expected ${expectedStr}, got ${actualStr}`, location, { expectedType: expectedStr, actualType: actualStr });
322
312
  }
323
313
  return value;
324
314
  }
325
315
  // Bare structural type (no sub-fields): fall through using type name
326
- expected = expected.type;
316
+ expected = expected.kind;
327
317
  }
328
318
  // Bare type name path
329
319
  if (expected === 'any')
@@ -366,7 +356,7 @@ function createTypesMixin(Base) {
366
356
  'members' in resolved.structure ||
367
357
  'valueType' in resolved.structure;
368
358
  if (hasSubFields) {
369
- return structuralTypeMatches(value, resolved.structure);
359
+ return structureMatches(value, resolved.structure);
370
360
  }
371
361
  return checkType(value, resolved.typeName);
372
362
  }
@@ -409,9 +399,9 @@ function createTypesMixin(Base) {
409
399
  const location = node.span.start;
410
400
  return this.buildCollectionType(name, node.args, async (arg) => {
411
401
  const resolved = await this.resolveTypeRef(arg.value, (varName) => getVariable(this.ctx, varName));
412
- return resolved.structure.type === 'any' &&
402
+ return resolved.structure.kind === 'any' &&
413
403
  resolved.typeName !== 'any'
414
- ? { type: resolved.typeName }
404
+ ? { kind: resolved.typeName }
415
405
  : resolved.structure;
416
406
  }, async (node) => {
417
407
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -422,7 +412,7 @@ function createTypesMixin(Base) {
422
412
  * Evaluate a closure signature literal into a RillTypeValue [IR-8].
423
413
  *
424
414
  * Creates a closure type value from |param: T, ...|: R syntax.
425
- * Each parameter produces a [name, RillType] entry.
415
+ * Each parameter produces a [name, TypeStructure] entry.
426
416
  *
427
417
  * Error contracts:
428
418
  * - EC-8: missing return type -> RILL-R004 (enforced at parse time; node always has returnType)
@@ -430,14 +420,14 @@ function createTypesMixin(Base) {
430
420
  */
431
421
  async evaluateClosureSigLiteral(node) {
432
422
  const location = node.span.start;
433
- // Helper: evaluate a type expression and extract RillType
423
+ // Helper: evaluate a type expression and extract TypeStructure
434
424
  const resolveTypeExpr = async (argVal) => {
435
425
  if (!isTypeValue(argVal)) {
436
426
  throw new RuntimeError('RILL-R004', `Parameter type must be a type value, got ${inferType(argVal)}`, location);
437
427
  }
438
- return argVal.structure.type === 'any' &&
428
+ return argVal.structure.kind === 'any' &&
439
429
  argVal.typeName !== 'any'
440
- ? { type: argVal.typeName }
430
+ ? { kind: argVal.typeName }
441
431
  : argVal.structure;
442
432
  };
443
433
  // Evaluate parameter types
@@ -456,11 +446,11 @@ function createTypesMixin(Base) {
456
446
  if (!isTypeValue(retVal)) {
457
447
  throw new RuntimeError('RILL-R004', `Closure type literal requires return type after |, got ${inferType(retVal)}`, location);
458
448
  }
459
- const ret = retVal.structure.type === 'any' &&
449
+ const ret = retVal.structure.kind === 'any' &&
460
450
  retVal.typeName !== 'any'
461
- ? { type: retVal.typeName }
451
+ ? { kind: retVal.typeName }
462
452
  : retVal.structure;
463
- const structure = { type: 'closure', params, ret };
453
+ const structure = { kind: 'closure', params, ret };
464
454
  return Object.freeze({
465
455
  __rill_type: true,
466
456
  typeName: 'closure',
@@ -31,7 +31,7 @@
31
31
  * @internal
32
32
  */
33
33
  import { RuntimeError } from '../../../../types.js';
34
- import { formatStructuralType, inferType, isTypeValue, structuralTypeMatches, } from '../../values.js';
34
+ import { formatStructure, inferType, isTypeValue, structureMatches, } from '../../values.js';
35
35
  import { getVariable, hasVariable } from '../../context.js';
36
36
  import { isDict, isCallable } from '../../callable.js';
37
37
  /**
@@ -69,8 +69,8 @@ function createVariablesMixin(Base) {
69
69
  if (explicitType !== undefined) {
70
70
  if (typeof explicitType === 'object') {
71
71
  // Structural type check
72
- if (!structuralTypeMatches(value, explicitType)) {
73
- const expectedLabel = formatStructuralType(explicitType);
72
+ if (!structureMatches(value, explicitType)) {
73
+ const expectedLabel = formatStructure(explicitType);
74
74
  throw new RuntimeError('RILL-R001', `Type mismatch: cannot assign ${valueType} to $${name}:${expectedLabel}`, location, {
75
75
  variableName: name,
76
76
  expectedType: expectedLabel,
@@ -98,8 +98,8 @@ function createVariablesMixin(Base) {
98
98
  if (lockedType !== undefined && lockedType !== 'any') {
99
99
  if (typeof lockedType === 'object') {
100
100
  // Structural locked type — validate full shape
101
- if (!structuralTypeMatches(value, lockedType)) {
102
- const expectedLabel = formatStructuralType(lockedType);
101
+ if (!structureMatches(value, lockedType)) {
102
+ const expectedLabel = formatStructure(lockedType);
103
103
  throw new RuntimeError('RILL-R001', `Type mismatch: cannot assign ${valueType} to $${name} (locked as ${expectedLabel})`, location, {
104
104
  variableName: name,
105
105
  expectedType: expectedLabel,
@@ -120,7 +120,9 @@ function createVariablesMixin(Base) {
120
120
  if (!this.ctx.variableTypes.has(name)) {
121
121
  // Store structural type (object) directly so re-assignment checks
122
122
  // validate the full shape. Fall back to valueType when no annotation.
123
- const lockType = explicitType !== undefined ? explicitType : valueType;
123
+ const lockType = explicitType !== undefined
124
+ ? explicitType
125
+ : valueType;
124
126
  this.ctx.variableTypes.set(name, lockType);
125
127
  }
126
128
  }
@@ -260,7 +262,7 @@ function createVariablesMixin(Base) {
260
262
  value = value.typeName;
261
263
  }
262
264
  else if (field === 'signature') {
263
- value = formatStructuralType(value.structure);
265
+ value = formatStructure(value.structure);
264
266
  }
265
267
  else {
266
268
  throw new RuntimeError('RILL-R003', `Type value has no property "${field}"`, this.getNodeLocation(node));
@@ -322,7 +324,7 @@ function createVariablesMixin(Base) {
322
324
  return true;
323
325
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
324
326
  const resolved = await this.resolveTypeRef(typeRef, (name) => getVariable(this.ctx, name));
325
- return structuralTypeMatches(fieldValue, resolved.structure);
327
+ return structureMatches(fieldValue, resolved.structure);
326
328
  };
327
329
  if (finalAccess.kind === 'literal') {
328
330
  // Check if literal field exists in dict
@@ -8,7 +8,7 @@
8
8
  * @internal
9
9
  */
10
10
  import type { SourceLocation } from '../../types.js';
11
- import type { RillFieldDef, RillType } from './values.js';
11
+ import type { RillFieldDef, TypeStructure } from './values.js';
12
12
  /**
13
13
  * Field descriptor — carries field name and structural type when accessing a
14
14
  * dict-kind RillType field.
@@ -23,6 +23,6 @@ export interface RillFieldDescriptor {
23
23
  *
24
24
  * EC-1: Throws RILL-R003 when fieldName is absent from structuralType.fields.
25
25
  */
26
- export declare function buildFieldDescriptor(structuralType: RillType & {
27
- type: 'dict';
26
+ export declare function buildFieldDescriptor(structuralType: TypeStructure & {
27
+ kind: 'dict';
28
28
  }, fieldName: string, location: SourceLocation): RillFieldDescriptor;
@@ -14,7 +14,8 @@ import { RuntimeError } from '../../types.js';
14
14
  * EC-1: Throws RILL-R003 when fieldName is absent from structuralType.fields.
15
15
  */
16
16
  export function buildFieldDescriptor(structuralType, fieldName, location) {
17
- const fieldType = structuralType.fields?.[fieldName];
17
+ const fields = structuralType.fields;
18
+ const fieldType = fields?.[fieldName];
18
19
  if (fieldType === undefined) {
19
20
  throw new RuntimeError('RILL-R003', `Shape has no field "${fieldName}"`, location);
20
21
  }
@@ -4,7 +4,7 @@
4
4
  * Functions for inspecting runtime context at runtime.
5
5
  * These enable host applications to discover available functions and their signatures.
6
6
  */
7
- import { formatStructuralType, formatValue } from './values.js';
7
+ import { formatStructure, formatValue } from './values.js';
8
8
  import { isApplicationCallable, isRuntimeCallable, isScriptCallable, } from './callable.js';
9
9
  import { LANGUAGE_REFERENCE } from '../../generated/introspection-data.js';
10
10
  import { BUILTIN_FUNCTIONS } from '../ext/builtins.js';
@@ -40,7 +40,7 @@ export function getFunctions(ctx) {
40
40
  if (callable.params) {
41
41
  const params = callable.params.map((p) => ({
42
42
  name: p.name,
43
- type: p.type !== undefined ? formatStructuralType(p.type) : 'any',
43
+ type: p.type !== undefined ? formatStructure(p.type) : 'any',
44
44
  description: typeof p.annotations['description'] === 'string'
45
45
  ? p.annotations['description']
46
46
  : '',
@@ -50,7 +50,7 @@ export function getFunctions(ctx) {
50
50
  name,
51
51
  description: callable.annotations?.['description'] ?? '',
52
52
  params,
53
- returnType: formatStructuralType(callable.returnType.structure),
53
+ returnType: formatStructure(callable.returnType.structure),
54
54
  });
55
55
  }
56
56
  else {
@@ -93,7 +93,7 @@ export function getFunctions(ctx) {
93
93
  // Convert params to ParamMetadata using RillParam.type (IC-5)
94
94
  const params = value.params.map((p) => ({
95
95
  name: p.name,
96
- type: p.type !== undefined ? formatStructuralType(p.type) : 'any',
96
+ type: p.type !== undefined ? formatStructure(p.type) : 'any',
97
97
  description: typeof p.annotations['description'] === 'string'
98
98
  ? p.annotations['description']
99
99
  : '',
@@ -131,7 +131,7 @@ function serializeParam(p) {
131
131
  parts.push(`^(description: "${desc}") `);
132
132
  }
133
133
  // Name and type
134
- const typeName = p.type !== undefined ? formatStructuralType(p.type) : 'any';
134
+ const typeName = p.type !== undefined ? formatStructure(p.type) : 'any';
135
135
  parts.push(`${p.name}: ${typeName}`);
136
136
  // Default value
137
137
  if (p.defaultValue !== undefined) {
@@ -189,7 +189,7 @@ export function generateManifest(ctx) {
189
189
  if (!isApplicationCallable(callable) || callable.params === undefined) {
190
190
  continue;
191
191
  }
192
- const signature = serializeClosureSignature(callable.params, formatStructuralType(callable.returnType.structure), callable.annotations?.['description'] ?? undefined);
192
+ const signature = serializeClosureSignature(callable.params, formatStructure(callable.returnType.structure), callable.annotations?.['description'] ?? undefined);
193
193
  entries.push(` "${name}": ${signature}`);
194
194
  }
195
195
  if (entries.length === 0) {
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared marker interfaces for forward declarations.
3
+ *
4
+ * These interfaces break circular dependencies between values.ts,
5
+ * type-structures.ts, and callable.ts. Actual types are defined in callable.ts.
6
+ */
7
+ export interface CallableMarker {
8
+ readonly __type: 'callable';
9
+ }
10
+ export interface FieldDescriptorMarker {
11
+ readonly __rill_field_descriptor: true;
12
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared marker interfaces for forward declarations.
3
+ *
4
+ * These interfaces break circular dependencies between values.ts,
5
+ * type-structures.ts, and callable.ts. Actual types are defined in callable.ts.
6
+ */
7
+ export {};
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Type Registration Definitions
3
+ *
4
+ * Defines the TypeDefinition interface, TypeProtocol interface, and
5
+ * BUILT_IN_TYPES registration array. Each of the 12 built-in types
6
+ * carries identity predicates, protocol functions (format, eq, compare,
7
+ * convertTo, serialize), and a methods record populated from BUILTIN_METHODS.
8
+ *
9
+ * Dispatch functions (inferType, formatValue, deepEquals, serializeValue,
10
+ * deserializeValue, copyValue) iterate registrations and delegate to
11
+ * per-type protocol implementations.
12
+ *
13
+ * Registration order:
14
+ * primitives -> discriminator-based -> structural -> list -> dict fallback
15
+ *
16
+ * @internal
17
+ */
18
+ import type { TypeStructure, RillValue, RillFieldDef, RillTuple, RillOrdered, RillVector, RillTypeValue, RillIterator } from './values.js';
19
+ import type { RillFunction } from './callable.js';
20
+ import { isTuple, isVector, isOrdered, isTypeValue, isIterator, createTuple, createOrdered, createVector } from './values.js';
21
+ /**
22
+ * Protocol functions that define per-type behavior.
23
+ * Every type must provide `format`. All other protocols are optional.
24
+ */
25
+ export interface TypeProtocol {
26
+ format: (v: RillValue) => string;
27
+ structure?: ((v: RillValue) => TypeStructure) | undefined;
28
+ eq?: ((a: RillValue, b: RillValue) => boolean) | undefined;
29
+ compare?: ((a: RillValue, b: RillValue) => number) | undefined;
30
+ convertTo?: Record<string, (v: RillValue) => RillValue> | undefined;
31
+ serialize?: ((v: RillValue) => unknown) | undefined;
32
+ deserialize?: ((data: unknown) => RillValue) | undefined;
33
+ }
34
+ /**
35
+ * A single type registration record. Each of the 12 built-in types
36
+ * has exactly one TypeDefinition in the BUILT_IN_TYPES array.
37
+ */
38
+ export interface TypeDefinition {
39
+ name: string;
40
+ identity: (v: RillValue) => boolean;
41
+ isLeaf: boolean;
42
+ immutable: boolean;
43
+ methods: Record<string, RillFunction>;
44
+ protocol: TypeProtocol;
45
+ }
46
+ /**
47
+ * All 12 built-in type registrations.
48
+ *
49
+ * Registration order:
50
+ * 1. Primitives: string, number, bool
51
+ * 2. Discriminator-based: tuple, ordered, vector, type, closure, field_descriptor
52
+ * 3. Structural: iterator
53
+ * 4. list
54
+ * 5. dict (fallback, must be last)
55
+ *
56
+ * AC-1: 12 registrations, one per type.
57
+ * BC-2: Vector identity checked before dict fallback.
58
+ * EC-3: Iterator has no protocol.eq.
59
+ * EC-4: Bool has no protocol.compare.
60
+ * EC-8: Non-serializable types throw plain Error.
61
+ */
62
+ export declare const BUILT_IN_TYPES: readonly TypeDefinition[];
63
+ /**
64
+ * Infer the Rill type name from a runtime value.
65
+ * Iterates registrations in order; returns first matching name.
66
+ * Returns 'string' as fallback (BC-1: null IS type string, not a coercion).
67
+ *
68
+ * IR-2: Return type widens from RillTypeName to string for extensibility.
69
+ */
70
+ export declare function inferType(value: RillValue): string;
71
+ /**
72
+ * Format a value as a human-readable string.
73
+ * Determines type via inferType, then calls protocol.format.
74
+ * Falls back to String(value) when no registration matches.
75
+ *
76
+ * IR-3: Protocol dispatcher for formatting.
77
+ */
78
+ export declare function formatValue(value: RillValue): string;
79
+ /**
80
+ * Deep equality comparison for two Rill values.
81
+ * Short-circuit: a === b returns true.
82
+ * Dispatches to left operand's protocol.eq.
83
+ * No protocol.eq returns false.
84
+ *
85
+ * IR-4: Container protocol.eq calls deepEquals recursively.
86
+ */
87
+ export declare function deepEquals(a: RillValue, b: RillValue): boolean;
88
+ /**
89
+ * Serialize a Rill value for JSON transport.
90
+ * Dispatches to protocol.serialize; container types recurse.
91
+ *
92
+ * IR-7: Renamed from valueToJSON.
93
+ */
94
+ export declare function serializeValue(value: RillValue): unknown;
95
+ /**
96
+ * Deserialize raw data into a Rill value.
97
+ * Dispatches to protocol.deserialize for the given type name.
98
+ * Falls back to raw value when no protocol.deserialize exists (primitives).
99
+ *
100
+ * IR-8: Raw value fallback rejects null/undefined inputs with RILL-R004.
101
+ * EC-9: Invalid data raises RILL-R004.
102
+ * EC-10: null/undefined input raises RILL-R004.
103
+ */
104
+ export declare function deserializeValue(data: unknown, typeName: string): RillValue;
105
+ /**
106
+ * Copy a Rill value.
107
+ * Reads immutable flag from registration.
108
+ * Immutable types return same reference.
109
+ * Mutable types (list, dict, iterator) recurse.
110
+ *
111
+ * IR-9: Renamed from deepCopyRillValue.
112
+ */
113
+ export declare function copyValue(value: RillValue): RillValue;
114
+ /**
115
+ * Populate registration `methods` fields from BUILTIN_METHODS.
116
+ *
117
+ * Called after builtins.ts finishes initialization to avoid circular
118
+ * dependency at module load time. The 6 method-bearing types (string,
119
+ * number, bool, list, dict, vector) receive their methods records;
120
+ * other types keep `methods: {}`.
121
+ *
122
+ * AC-3: Consolidates method data into registrations.
123
+ *
124
+ * MUTATION NOTE: BUILT_IN_TYPES is shallow-frozen (the array), but each
125
+ * registration object is mutable. This function relies on that mutability.
126
+ * If registration objects are ever deep-frozen (e.g. Object.freeze(reg)),
127
+ * this assignment will throw in strict mode. The runtime guard below catches
128
+ * that condition early with a clear error rather than a silent no-op.
129
+ */
130
+ export declare function populateBuiltinMethods(builtinMethods: Record<string, Record<string, RillFunction>>): void;
131
+ export { createTuple, createOrdered, createVector };
132
+ export { isTuple, isVector, isTypeValue, isOrdered, isIterator };
133
+ /** @deprecated Use isIterator instead. */
134
+ export declare const isRillIterator: typeof isIterator;
135
+ export type { TypeStructure };
136
+ export type { RillValue, RillTuple, RillOrdered, RillVector, RillTypeValue, RillIterator, RillFieldDef, };