@rcrsr/rill 0.17.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 (83) hide show
  1. package/dist/ast-nodes.d.ts +14 -4
  2. package/dist/ast-unions.d.ts +1 -1
  3. package/dist/constants.d.ts +1 -1
  4. package/dist/constants.js +1 -0
  5. package/dist/error-registry.js +228 -0
  6. package/dist/ext/crypto/index.js +5 -5
  7. package/dist/ext/exec/index.js +3 -3
  8. package/dist/ext/fetch/index.js +4 -4
  9. package/dist/ext/fetch/request.js +1 -1
  10. package/dist/ext/fs/index.js +101 -114
  11. package/dist/ext/fs/sandbox.d.ts +18 -0
  12. package/dist/ext/fs/sandbox.js +33 -0
  13. package/dist/ext/kv/index.js +12 -12
  14. package/dist/ext/kv/store.d.ts +1 -1
  15. package/dist/ext/kv/store.js +1 -1
  16. package/dist/generated/version-data.d.ts +1 -1
  17. package/dist/generated/version-data.js +2 -2
  18. package/dist/highlight-map.js +1 -0
  19. package/dist/index.d.ts +1 -15
  20. package/dist/index.js +1 -14
  21. package/dist/lexer/operators.js +1 -0
  22. package/dist/parser/helpers.js +1 -0
  23. package/dist/parser/parser-expr.js +44 -5
  24. package/dist/parser/parser-literals.js +111 -4
  25. package/dist/parser/parser-shape.js +2 -2
  26. package/dist/parser/parser-use.js +19 -2
  27. package/dist/parser/parser.d.ts +2 -0
  28. package/dist/parser/parser.js +2 -0
  29. package/dist/runtime/core/callable.d.ts +5 -6
  30. package/dist/runtime/core/callable.js +10 -17
  31. package/dist/runtime/core/context.d.ts +2 -2
  32. package/dist/runtime/core/context.js +8 -8
  33. package/dist/runtime/core/eval/base.d.ts +2 -2
  34. package/dist/runtime/core/eval/base.js +2 -0
  35. package/dist/runtime/core/eval/evaluator.d.ts +1 -1
  36. package/dist/runtime/core/eval/index.d.ts +2 -2
  37. package/dist/runtime/core/eval/mixins/closures.js +367 -27
  38. package/dist/runtime/core/eval/mixins/collections.js +81 -6
  39. package/dist/runtime/core/eval/mixins/control-flow.js +1 -1
  40. package/dist/runtime/core/eval/mixins/conversion.js +17 -12
  41. package/dist/runtime/core/eval/mixins/core.js +15 -2
  42. package/dist/runtime/core/eval/mixins/expressions.js +3 -2
  43. package/dist/runtime/core/eval/mixins/extraction.js +2 -3
  44. package/dist/runtime/core/eval/mixins/list-dispatch.js +1 -1
  45. package/dist/runtime/core/eval/mixins/literals.js +14 -3
  46. package/dist/runtime/core/eval/mixins/types.js +30 -1
  47. package/dist/runtime/core/eval/mixins/variables.js +3 -1
  48. package/dist/runtime/core/execute.d.ts +1 -1
  49. package/dist/runtime/core/field-descriptor.d.ts +1 -1
  50. package/dist/runtime/core/introspection.d.ts +2 -2
  51. package/dist/runtime/core/introspection.js +2 -1
  52. package/dist/runtime/core/resolvers.d.ts +1 -1
  53. package/dist/runtime/core/signals.d.ts +6 -1
  54. package/dist/runtime/core/signals.js +9 -0
  55. package/dist/runtime/core/types/constructors.d.ts +54 -0
  56. package/dist/runtime/core/types/constructors.js +201 -0
  57. package/dist/runtime/core/types/guards.d.ts +42 -0
  58. package/dist/runtime/core/types/guards.js +88 -0
  59. package/dist/runtime/core/types/index.d.ts +18 -0
  60. package/dist/runtime/core/types/index.js +19 -0
  61. package/dist/runtime/core/types/operations.d.ts +98 -0
  62. package/dist/runtime/core/types/operations.js +804 -0
  63. package/dist/runtime/core/{type-registrations.d.ts → types/registrations.d.ts} +12 -22
  64. package/dist/runtime/core/{type-registrations.js → types/registrations.js} +94 -92
  65. package/dist/runtime/core/{types.d.ts → types/runtime.d.ts} +8 -8
  66. package/dist/runtime/core/{type-structures.d.ts → types/structures.d.ts} +21 -3
  67. package/dist/runtime/core/values.d.ts +13 -102
  68. package/dist/runtime/core/values.js +26 -722
  69. package/dist/runtime/ext/builtins.js +9 -8
  70. package/dist/runtime/ext/extensions.d.ts +2 -2
  71. package/dist/runtime/ext/extensions.js +2 -1
  72. package/dist/runtime/ext/test-context.d.ts +2 -2
  73. package/dist/runtime/ext/test-context.js +3 -2
  74. package/dist/runtime/index.d.ts +8 -22
  75. package/dist/runtime/index.js +10 -16
  76. package/dist/signature-parser.d.ts +1 -1
  77. package/dist/token-types.d.ts +1 -0
  78. package/dist/token-types.js +1 -0
  79. package/package.json +1 -1
  80. /package/dist/runtime/core/{markers.d.ts → types/markers.d.ts} +0 -0
  81. /package/dist/runtime/core/{markers.js → types/markers.js} +0 -0
  82. /package/dist/runtime/core/{types.js → types/runtime.js} +0 -0
  83. /package/dist/runtime/core/{type-structures.js → types/structures.js} +0 -0
@@ -27,9 +27,12 @@
27
27
  * @internal
28
28
  */
29
29
  import { RuntimeError } from '../../../../types.js';
30
- import { inferType, isTuple, isOrdered, isTypeValue, createOrdered, createTuple, deepCopyRillValue, hasCollectionFields, emptyForType, } from '../../values.js';
30
+ import { inferType } from '../../types/registrations.js';
31
+ import { isTuple, isOrdered, isTypeValue } from '../../types/guards.js';
32
+ import { createOrdered, createTuple, copyValue, emptyForType, } from '../../types/constructors.js';
33
+ import { hasCollectionFields } from '../../values.js';
31
34
  import { isDict } from '../../callable.js';
32
- import { BUILT_IN_TYPES } from '../../type-registrations.js';
35
+ import { BUILT_IN_TYPES } from '../../types/registrations.js';
33
36
  import { getVariable } from '../../context.js';
34
37
  /**
35
38
  * ConversionMixin implementation.
@@ -123,6 +126,10 @@ function createConversionMixin(Base) {
123
126
  if (sourceType === targetType) {
124
127
  return input;
125
128
  }
129
+ // IR-11: :>stream is not supported — stream type cannot be a conversion target
130
+ if (targetType === 'stream') {
131
+ throw new RuntimeError('RILL-R003', 'Type conversion not supported for stream type', this.getNodeLocation(node));
132
+ }
126
133
  // dict -> :>ordered without structural sig is always RILL-R037 (EC-11)
127
134
  if (sourceType === 'dict' && targetType === 'ordered') {
128
135
  throw new RuntimeError('RILL-R037', 'dict to ordered conversion requires structural type signature', this.getNodeLocation(node));
@@ -137,10 +144,8 @@ function createConversionMixin(Base) {
137
144
  return converter(input);
138
145
  }
139
146
  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;
147
+ // Protocol converters throw RuntimeError (RILL-R064/R065/R066);
148
+ // wrap with evaluator-level error codes for user-facing messages.
144
149
  // String-to-number parse failures use RILL-R038 (EC-12)
145
150
  // Preserve the protocol's detailed message (includes unparseable value).
146
151
  if (sourceType === 'string' && targetType === 'number') {
@@ -190,7 +195,7 @@ function createConversionMixin(Base) {
190
195
  else if (field.defaultValue !== undefined) {
191
196
  entries.push([
192
197
  fieldName,
193
- this.hydrateNested(deepCopyRillValue(field.defaultValue), field.type, node),
198
+ this.hydrateNested(copyValue(field.defaultValue), field.type, node),
194
199
  ]);
195
200
  }
196
201
  else if (hasCollectionFields(field.type)) {
@@ -252,7 +257,7 @@ function createConversionMixin(Base) {
252
257
  // Field missing from input: use default if available, else error
253
258
  if (resolvedField !== undefined &&
254
259
  resolvedField.defaultValue !== undefined) {
255
- result[fieldName] = this.hydrateNested(deepCopyRillValue(resolvedField.defaultValue), resolvedField.type, node);
260
+ result[fieldName] = this.hydrateNested(copyValue(resolvedField.defaultValue), resolvedField.type, node);
256
261
  }
257
262
  else if (resolvedField !== undefined &&
258
263
  hasCollectionFields(resolvedField.type)) {
@@ -298,7 +303,7 @@ function createConversionMixin(Base) {
298
303
  }
299
304
  else if (element.defaultValue !== undefined) {
300
305
  // Missing trailing element with default: deep copy and hydrate
301
- result.push(this.hydrateNested(deepCopyRillValue(element.defaultValue), element.type, node));
306
+ result.push(this.hydrateNested(copyValue(element.defaultValue), element.type, node));
302
307
  }
303
308
  else if (hasCollectionFields(element.type)) {
304
309
  // Missing element with collection type: seed empty and hydrate
@@ -330,7 +335,7 @@ function createConversionMixin(Base) {
330
335
  }
331
336
  else {
332
337
  if (resolvedField.defaultValue !== undefined) {
333
- result[fieldName] = this.hydrateNested(deepCopyRillValue(resolvedField.defaultValue), resolvedField.type, node);
338
+ result[fieldName] = this.hydrateNested(copyValue(resolvedField.defaultValue), resolvedField.type, node);
334
339
  }
335
340
  else if (hasCollectionFields(resolvedField.type)) {
336
341
  result[fieldName] = this.hydrateNested(emptyForType(resolvedField.type), resolvedField.type, node);
@@ -364,7 +369,7 @@ function createConversionMixin(Base) {
364
369
  else if (field.defaultValue !== undefined) {
365
370
  resultEntries.push([
366
371
  name,
367
- this.hydrateNested(deepCopyRillValue(field.defaultValue), field.type, node),
372
+ this.hydrateNested(copyValue(field.defaultValue), field.type, node),
368
373
  ]);
369
374
  }
370
375
  else if (hasCollectionFields(field.type)) {
@@ -395,7 +400,7 @@ function createConversionMixin(Base) {
395
400
  resultEntries.push(elementValue);
396
401
  }
397
402
  else if (element.defaultValue !== undefined) {
398
- resultEntries.push(this.hydrateNested(deepCopyRillValue(element.defaultValue), element.type, node));
403
+ resultEntries.push(this.hydrateNested(copyValue(element.defaultValue), element.type, node));
399
404
  }
400
405
  else if (hasCollectionFields(element.type)) {
401
406
  resultEntries.push(this.hydrateNested(emptyForType(element.type), element.type, node));
@@ -21,7 +21,7 @@
21
21
  * @internal
22
22
  */
23
23
  import { RuntimeError } from '../../../../types.js';
24
- import { isTuple } from '../../values.js';
24
+ import { isTuple } from '../../types/guards.js';
25
25
  import { isCallable, isDict, isScriptCallable } from '../../callable.js';
26
26
  import { BreakSignal, ReturnSignal } from '../../signals.js';
27
27
  /**
@@ -102,7 +102,7 @@ function createCoreMixin(Base) {
102
102
  value = await this.evaluatePipeTarget(target, value);
103
103
  this.ctx.pipeValue = value; // OK: flows within chain
104
104
  }
105
- // Handle chain terminator (capture, break, return)
105
+ // Handle chain terminator (capture, break, return, yield)
106
106
  if (chain.terminator) {
107
107
  if (chain.terminator.type === 'Break') {
108
108
  // Restore parent's $ before throwing (cleanup)
@@ -114,6 +114,19 @@ function createCoreMixin(Base) {
114
114
  this.ctx.pipeValue = savedPipeValue;
115
115
  throw new ReturnSignal(value);
116
116
  }
117
+ if (chain.terminator.type === 'Yield') {
118
+ // Restore parent's $ before throwing (cleanup)
119
+ this.ctx.pipeValue = savedPipeValue;
120
+ // Delegate to evaluateYield for chunk type validation + YieldSignal.
121
+ // When inside a stream closure body, evaluateYield pushes to the
122
+ // channel and blocks until the consumer pulls (returns Promise<void>).
123
+ // When outside, it throws YieldSignal synchronously.
124
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
125
+ await this.evaluateYield(value, chain.terminator.span.start);
126
+ // After yield resumes (stream channel case), restore pipe value
127
+ // and return the yielded value as the chain result
128
+ return value;
129
+ }
117
130
  // Capture
118
131
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
132
  await this.handleCapture(chain.terminator, value);
@@ -18,8 +18,9 @@
18
18
  * @internal
19
19
  */
20
20
  import { RuntimeError } from '../../../../types.js';
21
- import { inferType, isTruthy } from '../../values.js';
22
- import { BUILT_IN_TYPES } from '../../type-registrations.js';
21
+ import { inferType } from '../../types/registrations.js';
22
+ import { isTruthy } from '../../values.js';
23
+ import { BUILT_IN_TYPES } from '../../types/registrations.js';
23
24
  import { createChildContext } from '../../context.js';
24
25
  import { isCallable } from '../../callable.js';
25
26
  /**
@@ -7,7 +7,8 @@
7
7
  * @internal
8
8
  */
9
9
  import { RuntimeError } from '../../../../types.js';
10
- import { createOrdered, createTuple, inferElementType } from '../../values.js';
10
+ import { createOrdered, createTuple } from '../../types/constructors.js';
11
+ import { inferElementType } from '../../types/operations.js';
11
12
  import { isDict } from '../../callable.js';
12
13
  import { getVariable } from '../../context.js';
13
14
  /**
@@ -77,7 +78,6 @@ function createExtractionMixin(Base) {
77
78
  }
78
79
  // Note: setVariable and resolveTypeRef will be available from VariablesMixin
79
80
  // and TypesMixin which are applied before ExtractionMixin in the composition order
80
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
81
  const dictResolved = elem.typeRef !== null
82
82
  ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
83
  await this.resolveTypeRef(elem.typeRef, (name) => getVariable(this.ctx, name))
@@ -112,7 +112,6 @@ function createExtractionMixin(Base) {
112
112
  }
113
113
  // Note: setVariable and resolveTypeRef will be available from VariablesMixin
114
114
  // and TypesMixin which are applied before ExtractionMixin in the composition order
115
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
116
115
  const listResolved = elem.typeRef !== null
117
116
  ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
117
  await this.resolveTypeRef(elem.typeRef, (name) => getVariable(this.ctx, name))
@@ -14,7 +14,7 @@
14
14
  * @internal
15
15
  */
16
16
  import { RuntimeError } from '../../../../types.js';
17
- import { inferElementType } from '../../values.js';
17
+ import { inferElementType } from '../../types/operations.js';
18
18
  /**
19
19
  * ListDispatchMixin implementation.
20
20
  *
@@ -25,7 +25,10 @@
25
25
  * @internal
26
26
  */
27
27
  import { RuntimeError } from '../../../../types.js';
28
- import { anyTypeValue, deepEquals, formatValue, inferElementType, isReservedMethod, isTypeValue, isVector, } from '../../values.js';
28
+ import { deepEquals, formatValue } from '../../types/registrations.js';
29
+ import { isTypeValue, isVector } from '../../types/guards.js';
30
+ import { inferElementType } from '../../types/operations.js';
31
+ import { anyTypeValue, isReservedMethod } from '../../values.js';
29
32
  import { isCallable, } from '../../callable.js';
30
33
  import { getVariable } from '../../context.js';
31
34
  /**
@@ -667,12 +670,20 @@ function createLiteralsMixin(Base) {
667
670
  }
668
671
  const isProperty = rillParams.length === 0;
669
672
  // Evaluate returnTypeTarget at closure creation time (IR-4).
673
+ // TypeConstructorNode → resolve via evaluateTypeConstructor() (e.g., stream(T):R).
670
674
  // TypeRef → resolve via resolveTypeRef() — returns RillTypeValue.
671
675
  // Absent → returnType defaults to anyTypeValue (omission implies :any, AC-17, AC-18, AC-19).
672
676
  let returnType = anyTypeValue;
673
677
  if (node.returnTypeTarget !== undefined) {
674
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
675
- returnType = await this.resolveTypeRef(node.returnTypeTarget, (name) => getVariable(this.ctx, name));
678
+ if ('type' in node.returnTypeTarget &&
679
+ node.returnTypeTarget.type === 'TypeConstructor') {
680
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
681
+ returnType = await this.evaluateTypeConstructor(node.returnTypeTarget);
682
+ }
683
+ else {
684
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
685
+ returnType = await this.resolveTypeRef(node.returnTypeTarget, (name) => getVariable(this.ctx, name));
686
+ }
676
687
  }
677
688
  return {
678
689
  __type: 'callable',
@@ -23,7 +23,10 @@
23
23
  * @internal
24
24
  */
25
25
  import { RuntimeError } from '../../../../types.js';
26
- import { inferType, checkType, isTypeValue, structureMatches, inferStructure, formatStructure, } from '../../values.js';
26
+ import { inferType } from '../../types/registrations.js';
27
+ import { isTypeValue } from '../../types/guards.js';
28
+ import { structureMatches, inferStructure, formatStructure, } from '../../types/operations.js';
29
+ import { checkType, structureToTypeValue } from '../../values.js';
27
30
  import { getVariable } from '../../context.js';
28
31
  /**
29
32
  * TypesMixin implementation.
@@ -251,6 +254,19 @@ function createTypesMixin(Base) {
251
254
  if (this.ctx.leafTypes.has(typeName)) {
252
255
  throw new RuntimeError('RILL-R004', `${typeName} does not accept type arguments`);
253
256
  }
257
+ // Stream type: extract chunk/ret from args if present
258
+ if (typeName === 'stream') {
259
+ const streamStructure = { kind: 'stream' };
260
+ if (args.length > 0 && args[0] !== undefined) {
261
+ const chunkResolved = await this.resolveTypeRef(args[0].value, getVariableFn);
262
+ streamStructure.chunk = chunkResolved.structure;
263
+ }
264
+ if (args.length > 1 && args[1] !== undefined) {
265
+ const retResolved = await this.resolveTypeRef(args[1].value, getVariableFn);
266
+ streamStructure.ret = retResolved.structure;
267
+ }
268
+ return structureToTypeValue(streamStructure);
269
+ }
254
270
  // Delegate to buildCollectionType with recursive resolveTypeRef
255
271
  return this.buildCollectionType(typeName, args, async (arg) => {
256
272
  const resolved = await this.resolveTypeRef(arg.value, getVariableFn);
@@ -397,6 +413,19 @@ function createTypesMixin(Base) {
397
413
  async evaluateTypeConstructor(node) {
398
414
  const name = node.constructorName;
399
415
  const location = node.span.start;
416
+ // Stream type constructor: extract chunk type (arg 0) and ret type (arg 1)
417
+ if (name === 'stream') {
418
+ const streamStructure = { kind: 'stream' };
419
+ if (node.args.length > 0 && node.args[0] !== undefined) {
420
+ const chunkResolved = await this.resolveTypeRef(node.args[0].value, (varName) => getVariable(this.ctx, varName));
421
+ streamStructure.chunk = chunkResolved.structure;
422
+ }
423
+ if (node.args.length > 1 && node.args[1] !== undefined) {
424
+ const retResolved = await this.resolveTypeRef(node.args[1].value, (varName) => getVariable(this.ctx, varName));
425
+ streamStructure.ret = retResolved.structure;
426
+ }
427
+ return structureToTypeValue(streamStructure);
428
+ }
400
429
  return this.buildCollectionType(name, node.args, async (arg) => {
401
430
  const resolved = await this.resolveTypeRef(arg.value, (varName) => getVariable(this.ctx, varName));
402
431
  return resolved.structure.kind === 'any' &&
@@ -31,7 +31,9 @@
31
31
  * @internal
32
32
  */
33
33
  import { RuntimeError } from '../../../../types.js';
34
- import { formatStructure, inferType, isTypeValue, structureMatches, } from '../../values.js';
34
+ import { inferType } from '../../types/registrations.js';
35
+ import { isTypeValue } from '../../types/guards.js';
36
+ import { formatStructure, structureMatches } from '../../types/operations.js';
35
37
  import { getVariable, hasVariable } from '../../context.js';
36
38
  import { isDict, isCallable } from '../../callable.js';
37
39
  /**
@@ -5,7 +5,7 @@
5
5
  * Provides both full execution and step-by-step execution.
6
6
  */
7
7
  import type { ScriptNode } from '../../types.js';
8
- import type { ExecutionResult, ExecutionStepper, RuntimeContext } from './types.js';
8
+ import type { ExecutionResult, ExecutionStepper, RuntimeContext } from './types/runtime.js';
9
9
  /**
10
10
  * Execute a parsed Rill script.
11
11
  *
@@ -8,7 +8,7 @@
8
8
  * @internal
9
9
  */
10
10
  import type { SourceLocation } from '../../types.js';
11
- import type { RillFieldDef, TypeStructure } from './values.js';
11
+ import type { RillFieldDef, TypeStructure } from './types/structures.js';
12
12
  /**
13
13
  * Field descriptor — carries field name and structural type when accessing a
14
14
  * dict-kind RillType field.
@@ -4,8 +4,8 @@
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 type { RuntimeContext } from './types.js';
8
- import type { RillValue } from './values.js';
7
+ import type { RuntimeContext } from './types/runtime.js';
8
+ import type { RillValue } from './types/structures.js';
9
9
  /**
10
10
  * Metadata describing a function's signature and documentation.
11
11
  * Returned by introspection APIs like getFunctions().
@@ -4,7 +4,8 @@
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 { formatStructure, formatValue } from './values.js';
7
+ import { formatStructure } from './types/operations.js';
8
+ import { formatValue } from './types/registrations.js';
8
9
  import { isApplicationCallable, isRuntimeCallable, isScriptCallable, } from './callable.js';
9
10
  import { LANGUAGE_REFERENCE } from '../../generated/introspection-data.js';
10
11
  import { BUILTIN_FUNCTIONS } from '../ext/builtins.js';
@@ -4,7 +4,7 @@
4
4
  * moduleResolver — reads Rill source files from the filesystem.
5
5
  * extResolver — returns extension values from a host-provided config map.
6
6
  */
7
- import type { SchemeResolver } from './types.js';
7
+ import type { SchemeResolver } from './types/runtime.js';
8
8
  /**
9
9
  * Resolves a module ID to Rill source text by reading a file.
10
10
  *
@@ -5,7 +5,7 @@
5
5
  * These are part of the public API for host applications that
6
6
  * need to catch and handle control flow.
7
7
  */
8
- import type { RillValue } from './values.js';
8
+ import type { RillValue } from './types/structures.js';
9
9
  /** Signal thrown by `break` to exit loops */
10
10
  export declare class BreakSignal extends Error {
11
11
  readonly value: RillValue;
@@ -16,3 +16,8 @@ export declare class ReturnSignal extends Error {
16
16
  readonly value: RillValue;
17
17
  constructor(value: RillValue);
18
18
  }
19
+ /** Signal thrown when a stream yields a chunk value */
20
+ export declare class YieldSignal extends Error {
21
+ readonly value: RillValue;
22
+ constructor(value: RillValue);
23
+ }
@@ -23,3 +23,12 @@ export class ReturnSignal extends Error {
23
23
  this.name = 'ReturnSignal';
24
24
  }
25
25
  }
26
+ /** Signal thrown when a stream yields a chunk value */
27
+ export class YieldSignal extends Error {
28
+ value;
29
+ constructor(value) {
30
+ super('yield');
31
+ this.value = value;
32
+ this.name = 'YieldSignal';
33
+ }
34
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Value Constructors
3
+ *
4
+ * Factory functions for creating Rill compound values (tuples, ordered,
5
+ * vectors) and collection utilities (emptyForType, copyValue).
6
+ *
7
+ * Import constraints:
8
+ * - Imports from ./structures.js and ./guards.js
9
+ * - No imports from values.ts or callable.ts
10
+ */
11
+ import type { RillOrdered, RillStream, RillTuple, RillValue, RillVector, TypeStructure } from './structures.js';
12
+ /**
13
+ * Create ordered from entries array (named, preserves insertion order).
14
+ * Entries may be 2-element [name, value] or 3-element [name, value, default]
15
+ * tuples; the third element carries a default value for `.^input` reflection.
16
+ */
17
+ export declare function createOrdered(entries: [string, RillValue, RillValue?][]): RillOrdered;
18
+ /** Create tuple from entries array (positional, preserves order) */
19
+ export declare function createTuple(entries: RillValue[]): RillTuple;
20
+ /**
21
+ * Create vector from Float32Array with model name.
22
+ * @throws {RuntimeError} RILL-R074 if data.length is 0 (zero-dimension vectors not allowed)
23
+ */
24
+ export declare function createVector(data: Float32Array, model: string): RillVector;
25
+ /**
26
+ * Create an empty collection value matching the given TypeStructure.
27
+ * Assumes the type is dict, ordered, or tuple.
28
+ */
29
+ export declare function emptyForType(type: TypeStructure): RillValue;
30
+ /**
31
+ * Create a RillStream from an AsyncIterable of chunks and a resolve function.
32
+ *
33
+ * The stream is a linked-list of steps. Each `.next` call advances to the
34
+ * next chunk. Once exhausted, `done` becomes true and re-iteration throws
35
+ * RILL-R002. The `resolve` function is called after chunk exhaustion (or on
36
+ * direct invocation) and caches its result for idempotent access.
37
+ *
38
+ * @throws {RuntimeError} RILL-R003 if chunks is not an AsyncIterable
39
+ * @throws {RuntimeError} RILL-R003 if resolve is not a function
40
+ */
41
+ export declare function createRillStream(options: {
42
+ chunks: AsyncIterable<RillValue>;
43
+ resolve: () => Promise<RillValue>;
44
+ dispose?: (() => void) | undefined;
45
+ chunkType?: TypeStructure | undefined;
46
+ retType?: TypeStructure | undefined;
47
+ }): RillStream;
48
+ /**
49
+ * Copy a RillValue.
50
+ * Primitives and immutable compound values return the same reference.
51
+ * Mutable values (list, dict) copy recursively.
52
+ * Iterators return the same reference (not meaningfully copyable).
53
+ */
54
+ export declare function copyValue(value: RillValue): RillValue;
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Value Constructors
3
+ *
4
+ * Factory functions for creating Rill compound values (tuples, ordered,
5
+ * vectors) and collection utilities (emptyForType, copyValue).
6
+ *
7
+ * Import constraints:
8
+ * - Imports from ./structures.js and ./guards.js
9
+ * - No imports from values.ts or callable.ts
10
+ */
11
+ import { isCallable, isIterator, isOrdered, isStream, isTuple, isTypeValue, isVector, } from './guards.js';
12
+ import { callable } from '../callable.js';
13
+ import { RuntimeError } from '../../../types.js';
14
+ /**
15
+ * Create ordered from entries array (named, preserves insertion order).
16
+ * Entries may be 2-element [name, value] or 3-element [name, value, default]
17
+ * tuples; the third element carries a default value for `.^input` reflection.
18
+ */
19
+ export function createOrdered(entries) {
20
+ return Object.freeze({ __rill_ordered: true, entries: [...entries] });
21
+ }
22
+ /** Create tuple from entries array (positional, preserves order) */
23
+ export function createTuple(entries) {
24
+ return Object.freeze({ __rill_tuple: true, entries: [...entries] });
25
+ }
26
+ /**
27
+ * Create vector from Float32Array with model name.
28
+ * @throws {RuntimeError} RILL-R074 if data.length is 0 (zero-dimension vectors not allowed)
29
+ */
30
+ export function createVector(data, model) {
31
+ if (data.length === 0) {
32
+ throw new RuntimeError('RILL-R074', 'Vector data must have at least one dimension');
33
+ }
34
+ return { __rill_vector: true, data, model };
35
+ }
36
+ /**
37
+ * Create an empty collection value matching the given TypeStructure.
38
+ * Assumes the type is dict, ordered, or tuple.
39
+ */
40
+ export function emptyForType(type) {
41
+ if (type.kind === 'dict')
42
+ return {};
43
+ if (type.kind === 'ordered')
44
+ return createOrdered([]);
45
+ if (type.kind === 'tuple')
46
+ return createTuple([]);
47
+ return {};
48
+ }
49
+ /**
50
+ * Create a RillStream from an AsyncIterable of chunks and a resolve function.
51
+ *
52
+ * The stream is a linked-list of steps. Each `.next` call advances to the
53
+ * next chunk. Once exhausted, `done` becomes true and re-iteration throws
54
+ * RILL-R002. The `resolve` function is called after chunk exhaustion (or on
55
+ * direct invocation) and caches its result for idempotent access.
56
+ *
57
+ * @throws {RuntimeError} RILL-R003 if chunks is not an AsyncIterable
58
+ * @throws {RuntimeError} RILL-R003 if resolve is not a function
59
+ */
60
+ export function createRillStream(options) {
61
+ const { chunks, resolve, dispose, chunkType, retType } = options;
62
+ // Validate chunks is AsyncIterable
63
+ if (chunks === null ||
64
+ chunks === undefined ||
65
+ typeof chunks[Symbol.asyncIterator] !==
66
+ 'function') {
67
+ throw new RuntimeError('RILL-R003', 'createRillStream requires AsyncIterable chunks');
68
+ }
69
+ // Validate resolve is a function
70
+ if (typeof resolve !== 'function') {
71
+ throw new RuntimeError('RILL-R003', 'createRillStream requires resolve function');
72
+ }
73
+ const iterator = chunks[Symbol.asyncIterator]();
74
+ let exhausted = false;
75
+ let disposed = false;
76
+ let cachedResolution;
77
+ /** Idempotent resolve wrapper that caches the resolution value. */
78
+ async function resolveOnce() {
79
+ if (cachedResolution !== undefined)
80
+ return cachedResolution.value;
81
+ const value = await resolve();
82
+ cachedResolution = { value };
83
+ return value;
84
+ }
85
+ /** Build a stream step from an iterator result. */
86
+ function makeStep(iterResult) {
87
+ if (iterResult.done) {
88
+ exhausted = true;
89
+ if (!disposed && dispose) {
90
+ disposed = true;
91
+ dispose();
92
+ }
93
+ const doneStep = {
94
+ __rill_stream: true,
95
+ done: true,
96
+ next: callable(() => {
97
+ throw new RuntimeError('RILL-R002', 'Stream already consumed; cannot re-iterate');
98
+ }),
99
+ };
100
+ return doneStep;
101
+ }
102
+ let stale = false;
103
+ const step = {
104
+ __rill_stream: true,
105
+ done: false,
106
+ value: iterResult.value,
107
+ next: callable(async () => {
108
+ if (stale) {
109
+ throw new RuntimeError('RILL-R002', 'Stream already consumed; cannot re-iterate');
110
+ }
111
+ if (exhausted) {
112
+ throw new RuntimeError('RILL-R002', 'Stream already consumed; cannot re-iterate');
113
+ }
114
+ stale = true;
115
+ const next = await iterator.next();
116
+ return makeStep(next);
117
+ }),
118
+ };
119
+ return step;
120
+ }
121
+ // Build initial step: eagerly fetch the first chunk
122
+ // The stream object itself is a "pending" step that advances on first .next call
123
+ let initialized = false;
124
+ const stream = {
125
+ __rill_stream: true,
126
+ done: false,
127
+ next: callable(async () => {
128
+ if (initialized) {
129
+ throw new RuntimeError('RILL-R002', 'Stream already consumed; cannot re-iterate');
130
+ }
131
+ initialized = true;
132
+ const first = await iterator.next();
133
+ return makeStep(first);
134
+ }),
135
+ };
136
+ // Attach resolve as a hidden property for runtime access
137
+ Object.defineProperty(stream, '__rill_stream_resolve', {
138
+ value: resolveOnce,
139
+ enumerable: false,
140
+ });
141
+ if (dispose) {
142
+ Object.defineProperty(stream, '__rill_stream_dispose', {
143
+ value: () => {
144
+ if (!disposed) {
145
+ disposed = true;
146
+ dispose();
147
+ }
148
+ },
149
+ enumerable: false,
150
+ });
151
+ }
152
+ if (chunkType) {
153
+ Object.defineProperty(stream, '__rill_stream_chunk_type', {
154
+ value: chunkType,
155
+ enumerable: false,
156
+ });
157
+ }
158
+ if (retType) {
159
+ Object.defineProperty(stream, '__rill_stream_ret_type', {
160
+ value: retType,
161
+ enumerable: false,
162
+ });
163
+ }
164
+ return stream;
165
+ }
166
+ /**
167
+ * Copy a RillValue.
168
+ * Primitives and immutable compound values return the same reference.
169
+ * Mutable values (list, dict) copy recursively.
170
+ * Iterators return the same reference (not meaningfully copyable).
171
+ */
172
+ export function copyValue(value) {
173
+ if (value === null || typeof value !== 'object')
174
+ return value;
175
+ // Immutable compound types
176
+ if (isTuple(value) ||
177
+ isOrdered(value) ||
178
+ isVector(value) ||
179
+ isTypeValue(value) ||
180
+ isCallable(value))
181
+ return value;
182
+ // field_descriptor: immutable (no guard exported from guards.ts)
183
+ if ('__rill_field_descriptor' in value &&
184
+ value['__rill_field_descriptor'] === true)
185
+ return value;
186
+ // Mutable list (Array but not tuple/ordered — those were checked above)
187
+ if (Array.isArray(value))
188
+ return value.map(copyValue);
189
+ // Iterator: mutable but opaque — return same reference
190
+ if (isIterator(value))
191
+ return value;
192
+ // Stream: immutable — return same reference
193
+ if (isStream(value))
194
+ return value;
195
+ // Mutable dict
196
+ const dict = value;
197
+ const copy = {};
198
+ for (const [k, v] of Object.entries(dict))
199
+ copy[k] = copyValue(v);
200
+ return copy;
201
+ }