@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
@@ -24,6 +24,7 @@ export const TOKEN_HIGHLIGHT_MAP = new Map([
24
24
  ['FILTER', 'keyword'],
25
25
  ['BREAK', 'keyword'],
26
26
  ['RETURN', 'keyword'],
27
+ ['YIELD', 'keyword'],
27
28
  ['PASS', 'keyword'],
28
29
  ['ASSERT', 'keyword'],
29
30
  ['ERROR', 'keyword'],
package/dist/index.d.ts CHANGED
@@ -5,21 +5,7 @@
5
5
  export { LexerError, tokenize, type TokenizeOptions } from './lexer/index.js';
6
6
  export { parse, parseWithRecovery } from './parser/index.js';
7
7
  export type { ParseResult, RecoveryErrorNode, ErrorNode } from './types.js';
8
- export { anyTypeValue, type ApplicationCallable, BreakSignal, buildFieldDescriptor, callable, type CallableFn, type CallFrame, commonType, type CaptureEvent, type ConfigFieldDescriptor, contextResolver, createRuntimeContext, createStepper, createTestContext, createTuple, createVector, type DocumentationCoverageResult, emitExtensionEvent, type ErrorEvent, execute, type ExecutionResult, type ExecutionStepper, ExtensionBindingError, type ExtensionConfigSchema, type ExtensionEvent, type ExtensionFactory, type ExtensionFactoryResult, type ExtensionManifest, extResolver, formatStructure, type FsExtensionContract, type FunctionMetadata, type FunctionReturnEvent, generateManifest, getCallStack, getDocumentationCoverage, getFunctions, getLanguageReference, type HostCallEvent, inferElementType, inferStructure, inferType, invokeCallable, isApplicationCallable, isCallable, isDict, isIterator, isReservedMethod, isRuntimeCallable, isScriptCallable, isTuple, isTypeValue, isVector, type KvExtensionContract, moduleResolver, type NativeArray, type NativePlainObject, type NativeResult, type NativeValue, type ObservabilityCallbacks, type ParamMetadata, paramToFieldDef, popCallFrame, pushCallFrame, RESERVED_DICT_METHODS, type ResolverResult, ReturnSignal, type RillCallable, type RillFieldDef, type RillFunction, type RillIterator, type RillParam, type RillTuple, type RillTypeValue, type RillValue, type RillVector, type RuntimeCallable, type RuntimeCallbacks, type RuntimeContext, type RuntimeOptions, type SchemaEntry, type SchemeResolver, type ScriptCallable, type StepEndEvent, type StepResult, type StepStartEvent, structureEquals, structureMatches, structureToTypeValue, toCallable, toNative, type TypeDefinition, type TypeProtocol, type TypeStructure, VERSION, VERSION_INFO, type VersionInfo, } from './runtime/index.js';
9
- /** @deprecated Use TypeStructure instead. Will be removed in the next major version. */
10
- export type { RillType } from './runtime/index.js';
11
- /** @deprecated Use formatStructure instead. */
12
- export { formatStructuralType } from './runtime/index.js';
13
- /** @deprecated Use inferStructure instead. */
14
- export { inferStructuralType } from './runtime/index.js';
15
- /** @deprecated Use isIterator instead. */
16
- export { isRillIterator } from './runtime/index.js';
17
- /** @deprecated Use structureToTypeValue instead. */
18
- export { rillTypeToTypeValue } from './runtime/index.js';
19
- /** @deprecated Use structureEquals instead. */
20
- export { structuralTypeEquals } from './runtime/index.js';
21
- /** @deprecated Use structureMatches instead. */
22
- export { structuralTypeMatches } from './runtime/index.js';
8
+ export { anyTypeValue, type ApplicationCallable, BreakSignal, BUILT_IN_TYPES, BUILTIN_METHODS, buildFieldDescriptor, callable, type CallableFn, type CallFrame, commonType, compareStructuredFields, type CaptureEvent, type ConfigFieldDescriptor, contextResolver, copyValue, createOrdered, createRillStream, createRuntimeContext, createStepper, createTestContext, createTuple, createVector, deepEquals, deserializeValue, type DocumentationCoverageResult, emitExtensionEvent, type ErrorEvent, execute, type ExecutionResult, type ExecutionStepper, ExtensionBindingError, type ExtensionConfigSchema, type ExtensionEvent, type ExtensionFactory, type ExtensionFactoryResult, type ExtensionManifest, extResolver, type FieldComparisonCallbacks, formatRillLiteral, formatStructure, formatValue, type FsExtensionContract, type FunctionMetadata, type FunctionReturnEvent, generateManifest, getCallStack, getDocumentationCoverage, getFunctions, getLanguageReference, type HostCallEvent, hydrateFieldDefaults, inferElementType, inferStructure, inferType, invokeCallable, isApplicationCallable, isCallable, isDict, isEmpty, isIterator, isReservedMethod, isRillStream, isRuntimeCallable, isScriptCallable, isStream, isTruthy, isTuple, isTypeValue, isVector, type KvExtensionContract, marshalArgs, type MarshalOptions, moduleResolver, type NativeArray, type NativePlainObject, type NativeResult, type NativeValue, type ObservabilityCallbacks, type ParamMetadata, paramToFieldDef, popCallFrame, pushCallFrame, RESERVED_DICT_METHODS, type ResolverResult, ReturnSignal, YieldSignal, type RillCallable, type RillFieldDef, type RillFunction, type RillIterator, type RillParam, type RillStream, type RillTuple, type RillTypeValue, type RillValue, type RillVector, type RuntimeCallable, type RuntimeCallbacks, type RuntimeContext, type RuntimeOptions, type SchemaEntry, type SchemeResolver, type ScriptCallable, serializeValue, type StepEndEvent, type StepResult, type StepStartEvent, structureEquals, structureMatches, structureToTypeValue, toCallable, toNative, type TypeDefinition, type TypeProtocol, type TypeStructure, VERSION, VERSION_INFO, type VersionInfo, } from './runtime/index.js';
23
9
  export { type ErrorCategory, type ErrorDefinition, type ErrorSeverity, ERROR_REGISTRY, renderMessage, getHelpUrl, createError, } from './types.js';
24
10
  export { formatRillError, formatRillErrorJson, type FormatErrorOptions, type FormatErrorJsonOptions, type SourceMap, } from './error-formatter.js';
25
11
  export { type HighlightCategory, TOKEN_HIGHLIGHT_MAP, } from './highlight-map.js';
package/dist/index.js CHANGED
@@ -4,20 +4,7 @@
4
4
  */
5
5
  export { LexerError, tokenize } from './lexer/index.js';
6
6
  export { parse, parseWithRecovery } from './parser/index.js';
7
- export { anyTypeValue, BreakSignal, buildFieldDescriptor, callable, commonType, contextResolver, createRuntimeContext, createStepper, createTestContext, createTuple, createVector, emitExtensionEvent, execute, ExtensionBindingError, extResolver, formatStructure, generateManifest, getCallStack, getDocumentationCoverage, getFunctions, getLanguageReference, inferElementType, inferStructure, inferType, invokeCallable, isApplicationCallable, isCallable, isDict, isIterator, isReservedMethod, isRuntimeCallable, isScriptCallable, isTuple, isTypeValue, isVector, moduleResolver, paramToFieldDef, popCallFrame, pushCallFrame, RESERVED_DICT_METHODS, ReturnSignal, structureEquals, structureMatches, structureToTypeValue, toCallable, toNative, VERSION, VERSION_INFO, } from './runtime/index.js';
8
- // Deprecated aliases — old names kept for one release
9
- /** @deprecated Use formatStructure instead. */
10
- export { formatStructuralType } from './runtime/index.js';
11
- /** @deprecated Use inferStructure instead. */
12
- export { inferStructuralType } from './runtime/index.js';
13
- /** @deprecated Use isIterator instead. */
14
- export { isRillIterator } from './runtime/index.js';
15
- /** @deprecated Use structureToTypeValue instead. */
16
- export { rillTypeToTypeValue } from './runtime/index.js';
17
- /** @deprecated Use structureEquals instead. */
18
- export { structuralTypeEquals } from './runtime/index.js';
19
- /** @deprecated Use structureMatches instead. */
20
- export { structuralTypeMatches } from './runtime/index.js';
7
+ export { anyTypeValue, BreakSignal, BUILT_IN_TYPES, BUILTIN_METHODS, buildFieldDescriptor, callable, commonType, compareStructuredFields, contextResolver, copyValue, createOrdered, createRillStream, createRuntimeContext, createStepper, createTestContext, createTuple, createVector, deepEquals, deserializeValue, emitExtensionEvent, execute, ExtensionBindingError, extResolver, formatRillLiteral, formatStructure, formatValue, generateManifest, getCallStack, getDocumentationCoverage, getFunctions, getLanguageReference, hydrateFieldDefaults, inferElementType, inferStructure, inferType, invokeCallable, isApplicationCallable, isCallable, isDict, isEmpty, isIterator, isReservedMethod, isRillStream, isRuntimeCallable, isScriptCallable, isStream, isTruthy, isTuple, isTypeValue, isVector, marshalArgs, moduleResolver, paramToFieldDef, popCallFrame, pushCallFrame, RESERVED_DICT_METHODS, ReturnSignal, YieldSignal, serializeValue, structureEquals, structureMatches, structureToTypeValue, toCallable, toNative, VERSION, VERSION_INFO, } from './runtime/index.js';
21
8
  // ============================================================
22
9
  // ERROR TAXONOMY
23
10
  // ============================================================
@@ -48,6 +48,7 @@ export const KEYWORDS = {
48
48
  false: TOKEN_TYPES.FALSE,
49
49
  break: TOKEN_TYPES.BREAK,
50
50
  return: TOKEN_TYPES.RETURN,
51
+ yield: TOKEN_TYPES.YIELD,
51
52
  pass: TOKEN_TYPES.PASS,
52
53
  assert: TOKEN_TYPES.ASSERT,
53
54
  error: TOKEN_TYPES.ERROR,
@@ -25,6 +25,7 @@ export function isIdentifierOrKeyword(token) {
25
25
  token.type === TOKEN_TYPES.FALSE ||
26
26
  token.type === TOKEN_TYPES.BREAK ||
27
27
  token.type === TOKEN_TYPES.RETURN ||
28
+ token.type === TOKEN_TYPES.YIELD ||
28
29
  token.type === TOKEN_TYPES.ASSERT ||
29
30
  token.type === TOKEN_TYPES.ERROR ||
30
31
  token.type === TOKEN_TYPES.EACH ||
@@ -139,6 +139,20 @@ Parser.prototype.parsePipeChain = function () {
139
139
  span: token.span,
140
140
  };
141
141
  }
142
+ // Handle bare yield: "yield" ≡ "$ -> yield"
143
+ if (check(this.state, TOKEN_TYPES.YIELD)) {
144
+ if (this.closureDepth === 0) {
145
+ throw new ParseError('RILL-P006', "'yield' is only valid inside a stream closure", current(this.state).span.start);
146
+ }
147
+ const token = advance(this.state);
148
+ return {
149
+ type: 'PipeChain',
150
+ head: this.implicitPipeVar(token.span),
151
+ pipes: [],
152
+ terminator: { type: 'Yield', span: token.span },
153
+ span: token.span,
154
+ };
155
+ }
142
156
  // Parse expression head with full precedence chain
143
157
  let head = this.parseLogicalOr();
144
158
  // Check for loop: expr @ body
@@ -214,6 +228,15 @@ Parser.prototype.parsePipeChain = function () {
214
228
  terminator = { type: 'Return', span: token.span };
215
229
  break;
216
230
  }
231
+ // Check for yield terminator: -> yield
232
+ if (check(this.state, TOKEN_TYPES.YIELD)) {
233
+ if (this.closureDepth === 0) {
234
+ throw new ParseError('RILL-P006', "'yield' is only valid inside a stream closure", current(this.state).span.start);
235
+ }
236
+ const token = advance(this.state);
237
+ terminator = { type: 'Yield', span: token.span };
238
+ break;
239
+ }
217
240
  // Guard against removed -> export syntax
218
241
  if (check(this.state, TOKEN_TYPES.IDENTIFIER) &&
219
242
  current(this.state).value === 'export') {
@@ -576,8 +599,14 @@ Parser.prototype.parsePrimary = function () {
576
599
  if (isMethodCall(this.state)) {
577
600
  return this.parseMethodCall(null);
578
601
  }
579
- // Type constructor: list(...), dict(...), tuple(...), ordered(...)
580
- const TYPE_CONSTRUCTORS = ['list', 'dict', 'tuple', 'ordered'];
602
+ // Type constructor: list(...), dict(...), tuple(...), ordered(...), stream(...)
603
+ const TYPE_CONSTRUCTORS = [
604
+ 'list',
605
+ 'dict',
606
+ 'tuple',
607
+ 'ordered',
608
+ 'stream',
609
+ ];
581
610
  if (check(this.state, TOKEN_TYPES.IDENTIFIER) &&
582
611
  TYPE_CONSTRUCTORS.includes(current(this.state).value) &&
583
612
  this.state.tokens[this.state.pos + 1]?.type === TOKEN_TYPES.LPAREN) {
@@ -615,6 +644,10 @@ Parser.prototype.parsePrimary = function () {
615
644
  const common = this.parseCommonConstruct();
616
645
  if (common)
617
646
  return common;
647
+ // Yield keyword in expression position (not valid as identifier)
648
+ if (check(this.state, TOKEN_TYPES.YIELD)) {
649
+ throw new ParseError('RILL-P001', "Unexpected keyword 'yield'", current(this.state).span.start);
650
+ }
618
651
  // Detect heredoc syntax (removed feature)
619
652
  const token = current(this.state);
620
653
  if (token.type === TOKEN_TYPES.LT &&
@@ -1063,10 +1096,16 @@ Parser.prototype.parseConvert = function () {
1063
1096
  const start = current(this.state).span.start;
1064
1097
  expect(this.state, TOKEN_TYPES.COLON, 'Expected :');
1065
1098
  expect(this.state, TOKEN_TYPES.GT, 'Expected >');
1066
- // Structural convert: :>ordered(field: type, ...)
1067
- const TYPE_CONSTRUCTORS = ['list', 'dict', 'tuple', 'ordered'];
1099
+ // Structural convert: :>ordered(field: type, ...), :>stream(T), etc.
1100
+ const TYPE_CONSTRUCTORS_CONVERT = [
1101
+ 'list',
1102
+ 'dict',
1103
+ 'tuple',
1104
+ 'ordered',
1105
+ 'stream',
1106
+ ];
1068
1107
  if (check(this.state, TOKEN_TYPES.IDENTIFIER) &&
1069
- TYPE_CONSTRUCTORS.includes(current(this.state).value) &&
1108
+ TYPE_CONSTRUCTORS_CONVERT.includes(current(this.state).value) &&
1070
1109
  this.state.tokens[this.state.pos + 1]?.type === TOKEN_TYPES.LPAREN) {
1071
1110
  const constructorName = current(this.state).value;
1072
1111
  const typeRef = this.parseTypeConstructor(constructorName);
@@ -7,7 +7,7 @@ import { ParseError, TOKEN_TYPES } from '../types.js';
7
7
  import { tokenize } from '../lexer/index.js';
8
8
  import { check, advance, expect, current, peek, skipNewlines, makeSpan, } from './state.js';
9
9
  import { isDictStart, isNegativeNumber, VALID_TYPE_NAMES } from './helpers.js';
10
- import { parseTypeRef } from './parser-types.js';
10
+ import { parseTypeRef, parseFieldArgList } from './parser-types.js';
11
11
  // ============================================================
12
12
  // LITERAL PARSING
13
13
  // ============================================================
@@ -384,14 +384,106 @@ Parser.prototype.parseDictEntry = function () {
384
384
  // ============================================================
385
385
  // CLOSURE PARSING
386
386
  // ============================================================
387
+ /**
388
+ * Parse a stream type constructor: stream(T):R
389
+ *
390
+ * Grammar: "stream" "(" [type-ref] ")" [":" type-ref]
391
+ *
392
+ * Chunk type goes in args[0], resolution type in args[1].
393
+ * stream() → 0 args, stream(T) → 1 arg, stream(T):R → 2 args.
394
+ *
395
+ * @internal
396
+ */
397
+ function parseStreamTypeConstructor(parser) {
398
+ const start = current(parser.state).span.start;
399
+ advance(parser.state); // consume 'stream'
400
+ if (!check(parser.state, TOKEN_TYPES.LPAREN)) {
401
+ throw new ParseError('RILL-P006', 'Expected type name in stream constructor', current(parser.state).span.start);
402
+ }
403
+ advance(parser.state); // consume '('
404
+ const args = parseFieldArgList(parser.state);
405
+ const rparen = expect(parser.state, TOKEN_TYPES.RPAREN, 'Expected )', 'RILL-P005');
406
+ // Check for resolution type: stream(T):R
407
+ if (check(parser.state, TOKEN_TYPES.COLON)) {
408
+ advance(parser.state); // consume ':'
409
+ skipNewlines(parser.state);
410
+ // Guard: resolution type must start with a valid type name
411
+ if (!check(parser.state, TOKEN_TYPES.IDENTIFIER)) {
412
+ throw new ParseError('RILL-P006', "Expected type name after ':' in stream type", current(parser.state).span.start);
413
+ }
414
+ // Parse the resolution type reference
415
+ const resolutionType = parseTypeRef(parser.state);
416
+ // Ensure positional alignment: args[0] = chunk, args[1] = ret.
417
+ // When parens are empty (no chunk type), insert an 'any' placeholder
418
+ // so the runtime correctly maps arg positions.
419
+ if (args.length === 0) {
420
+ args.push({ value: { kind: 'static', typeName: 'any' } });
421
+ }
422
+ args.push({ value: resolutionType });
423
+ return {
424
+ type: 'TypeConstructor',
425
+ constructorName: 'stream',
426
+ args,
427
+ span: makeSpan(start, current(parser.state).span.end),
428
+ };
429
+ }
430
+ return {
431
+ type: 'TypeConstructor',
432
+ constructorName: 'stream',
433
+ args,
434
+ span: makeSpan(start, rparen.span.end),
435
+ };
436
+ }
437
+ /**
438
+ * Check whether a closure body contains any yield terminators at the
439
+ * immediate level (not inside nested closures). Returns true if at
440
+ * least one yield is found.
441
+ * @internal
442
+ */
443
+ function bodyContainsYield(body) {
444
+ if (body.type === 'PipeChain') {
445
+ if (body.terminator?.type === 'Yield')
446
+ return true;
447
+ return false;
448
+ }
449
+ if (body.type === 'Block') {
450
+ for (const stmt of body.statements) {
451
+ const expr = stmt.type === 'AnnotatedStatement'
452
+ ? stmt.statement.expression
453
+ : stmt.expression;
454
+ if (expr.terminator?.type === 'Yield')
455
+ return true;
456
+ }
457
+ return false;
458
+ }
459
+ return false;
460
+ }
461
+ /**
462
+ * Validate that yield nodes in a closure body are only present when
463
+ * the closure has a stream return type. Throws RILL-P006 if yield
464
+ * appears without :stream(T):R annotation.
465
+ * @internal
466
+ */
467
+ function validateYieldInClosure(body, returnTypeTarget, closureStart) {
468
+ if (!bodyContainsYield(body))
469
+ return;
470
+ const isStream = returnTypeTarget !== undefined &&
471
+ 'type' in returnTypeTarget &&
472
+ returnTypeTarget.type === 'TypeConstructor' &&
473
+ returnTypeTarget.constructorName === 'stream';
474
+ if (!isStream) {
475
+ throw new ParseError('RILL-P006', "'yield' is only valid inside a stream closure", closureStart);
476
+ }
477
+ }
387
478
  /**
388
479
  * Parse the optional postfix `:type-target` after a closure body.
389
480
  *
390
481
  * Grammar: [ ":" , type-target ]
391
- * type-target = shape(...) | type-ref
482
+ * type-target = "stream" "(" [type-ref] ")" [":" type-ref] | type-ref
392
483
  *
393
- * Returns the parsed TypeRef or ShapeLiteralNode, or undefined if absent.
484
+ * Returns the parsed TypeRef, TypeConstructorNode, or undefined if absent.
394
485
  * Follows the same disambiguation logic as parsePostfixTypeOperation.
486
+ * Extended for stream(T):R return type pattern.
395
487
  */
396
488
  function parseClosureReturnTypeTarget(parser) {
397
489
  skipNewlines(parser.state);
@@ -400,6 +492,11 @@ function parseClosureReturnTypeTarget(parser) {
400
492
  }
401
493
  advance(parser.state); // consume ':'
402
494
  skipNewlines(parser.state);
495
+ // Stream type constructor: stream(T):R
496
+ if (check(parser.state, TOKEN_TYPES.IDENTIFIER) &&
497
+ current(parser.state).value === 'stream') {
498
+ return parseStreamTypeConstructor(parser);
499
+ }
403
500
  // Default: plain type name or dynamic type reference
404
501
  return parseTypeRef(parser.state);
405
502
  }
@@ -408,8 +505,11 @@ Parser.prototype.parseClosure = function () {
408
505
  if (check(this.state, TOKEN_TYPES.OR)) {
409
506
  advance(this.state);
410
507
  skipNewlines(this.state);
508
+ this.closureDepth++;
411
509
  const body = this.parseBody(true);
510
+ this.closureDepth--;
412
511
  const returnTypeTarget = parseClosureReturnTypeTarget(this);
512
+ validateYieldInClosure(body, returnTypeTarget, start);
413
513
  return {
414
514
  type: 'Closure',
415
515
  params: [],
@@ -454,8 +554,11 @@ Parser.prototype.parseClosure = function () {
454
554
  const typeRef = parseTypeRef(this.state, { allowTrailingPipe: true });
455
555
  expect(this.state, TOKEN_TYPES.PIPE_BAR, 'Expected |', 'RILL-P005');
456
556
  skipNewlines(this.state);
557
+ this.closureDepth++;
457
558
  const body = this.parseBody(true);
559
+ this.closureDepth--;
458
560
  const returnTypeTarget = parseClosureReturnTypeTarget(this);
561
+ validateYieldInClosure(body, returnTypeTarget, start);
459
562
  const param = {
460
563
  type: 'ClosureParam',
461
564
  name: '$',
@@ -482,8 +585,11 @@ Parser.prototype.parseClosure = function () {
482
585
  }
483
586
  expect(this.state, TOKEN_TYPES.PIPE_BAR, 'Expected |', 'RILL-P005');
484
587
  skipNewlines(this.state);
588
+ this.closureDepth++;
485
589
  const body = this.parseBody(true);
590
+ this.closureDepth--;
486
591
  const returnTypeTarget = parseClosureReturnTypeTarget(this);
592
+ validateYieldInClosure(body, returnTypeTarget, start);
487
593
  return {
488
594
  type: 'Closure',
489
595
  params,
@@ -500,7 +606,8 @@ Parser.prototype.parseBody = function (allowEmptyBlock) {
500
606
  return this.parseGrouped();
501
607
  }
502
608
  if (check(this.state, TOKEN_TYPES.BREAK) ||
503
- check(this.state, TOKEN_TYPES.RETURN)) {
609
+ check(this.state, TOKEN_TYPES.RETURN) ||
610
+ check(this.state, TOKEN_TYPES.YIELD)) {
504
611
  return this.parsePipeChain();
505
612
  }
506
613
  return this.parsePostfixExpr();
@@ -18,9 +18,9 @@ import { parseFieldArgList } from './parser-types.js';
18
18
  * Produces TypeConstructorNode.
19
19
  */
20
20
  Parser.prototype.parseTypeConstructor = function (constructorName) {
21
- const validNames = ['list', 'dict', 'tuple', 'ordered'];
21
+ const validNames = ['list', 'dict', 'tuple', 'ordered', 'stream'];
22
22
  if (!validNames.includes(constructorName)) {
23
- throw new ParseError('RILL-P001', `Expected type constructor name (list, dict, tuple, ordered), got: ${constructorName}`, current(this.state).span.start);
23
+ throw new ParseError('RILL-P001', `Expected type constructor name (list, dict, tuple, ordered, stream), got: ${constructorName}`, current(this.state).span.start);
24
24
  }
25
25
  const start = current(this.state).span.start;
26
26
  // Consume the constructor name identifier token
@@ -55,12 +55,18 @@ Parser.prototype.parseUseExpr = function () {
55
55
  expect(this.state, TOKEN_TYPES.GT, "Expected '>' to close use<>", 'RILL-P022');
56
56
  let typeRef = null;
57
57
  let closureAnnotation = null;
58
+ const parseLiteral = () => this.parseLiteral();
58
59
  if (check(this.state, TOKEN_TYPES.COLON)) {
59
60
  if (peek(this.state, 1).type === TOKEN_TYPES.OR) {
60
61
  // Zero-param closure annotation: :||
61
62
  advance(this.state); // consume :
62
63
  advance(this.state); // consume || (OR token)
63
64
  closureAnnotation = [];
65
+ // Optional return type after :||
66
+ if (check(this.state, TOKEN_TYPES.COLON)) {
67
+ advance(this.state); // consume :
68
+ typeRef = parseTypeRef(this.state, { parseLiteral });
69
+ }
64
70
  }
65
71
  else if (peek(this.state, 1).type === TOKEN_TYPES.PIPE_BAR) {
66
72
  // Closure annotation: :|param: type, ...|
@@ -72,11 +78,17 @@ Parser.prototype.parseUseExpr = function () {
72
78
  expect(this.state, TOKEN_TYPES.COLON, 'Expected : after parameter name in closure annotation');
73
79
  const paramTypeRef = parseTypeRef(this.state, {
74
80
  allowTrailingPipe: true,
81
+ parseLiteral,
75
82
  });
76
- closureAnnotation.push({
83
+ const entry = {
77
84
  name: nameToken.value,
78
85
  typeRef: paramTypeRef,
79
- });
86
+ };
87
+ if (check(this.state, TOKEN_TYPES.ASSIGN)) {
88
+ advance(this.state); // consume =
89
+ entry.defaultValue = parseLiteral();
90
+ }
91
+ closureAnnotation.push(entry);
80
92
  if (check(this.state, TOKEN_TYPES.COMMA)) {
81
93
  advance(this.state); // consume ,
82
94
  }
@@ -85,6 +97,11 @@ Parser.prototype.parseUseExpr = function () {
85
97
  }
86
98
  }
87
99
  advance(this.state); // consume closing |
100
+ // Optional return type after :|params|
101
+ if (check(this.state, TOKEN_TYPES.COLON)) {
102
+ advance(this.state); // consume :
103
+ typeRef = parseTypeRef(this.state, { parseLiteral });
104
+ }
88
105
  }
89
106
  else {
90
107
  advance(this.state); // consume :
@@ -33,6 +33,8 @@ import { type ParserState } from './state.js';
33
33
  export declare class Parser {
34
34
  /** Parser state including tokens, position, and error collection */
35
35
  state: ParserState;
36
+ /** Tracks closure nesting depth for yield validation */
37
+ closureDepth: number;
36
38
  constructor(tokens: Token[], options?: {
37
39
  recoveryMode?: boolean;
38
40
  source?: string;
@@ -32,6 +32,8 @@ import { createParserState } from './state.js';
32
32
  export class Parser {
33
33
  /** Parser state including tokens, position, and error collection */
34
34
  state;
35
+ /** Tracks closure nesting depth for yield validation */
36
+ closureDepth = 0;
35
37
  constructor(tokens, options) {
36
38
  this.state = createParserState(tokens, {
37
39
  recoveryMode: options?.recoveryMode ?? false,
@@ -20,7 +20,8 @@
20
20
  * - Kept for API consistency with marshalArgs signature
21
21
  */
22
22
  import type { BodyNode, SourceLocation } from '../../types.js';
23
- import type { TypeStructure, RillTypeValue, RillValue } from './values.js';
23
+ import { isDict } from './types/guards.js';
24
+ import type { TypeStructure, RillTypeValue, RillValue } from './types/structures.js';
24
25
  interface RuntimeContextLike {
25
26
  readonly parent?: RuntimeContextLike | undefined;
26
27
  readonly variables: Map<string, RillValue>;
@@ -99,8 +100,8 @@ export interface ApplicationCallable extends CallableBase {
99
100
  }
100
101
  /** Union of all callable types */
101
102
  export type RillCallable = ScriptCallable | RuntimeCallable | ApplicationCallable;
102
- /** Type guard for any callable */
103
- export declare function isCallable(value: RillValue): value is RillCallable;
103
+ /** Type guard for any callable (delegates to types/guards.ts) */
104
+ export declare const isCallable: (value: RillValue) => value is RillCallable;
104
105
  /** Type guard for script callable */
105
106
  export declare function isScriptCallable(value: RillValue): value is ScriptCallable;
106
107
  /** Type guard for runtime callable */
@@ -124,8 +125,7 @@ export declare function callable(fn: CallableFn, isProperty?: boolean): Applicat
124
125
  * @returns ApplicationCallable with __type, kind, isProperty, and preserved annotations
125
126
  */
126
127
  export declare function toCallable(def: RillFunction, isProperty?: boolean): ApplicationCallable;
127
- /** Type guard for dict (plain object, not array, not callable, not tuple) */
128
- export declare function isDict(value: RillValue): value is Record<string, RillValue>;
128
+ export { isDict };
129
129
  /** Format a callable for display */
130
130
  export declare function formatCallable(callable: RillCallable): string;
131
131
  /**
@@ -208,4 +208,3 @@ export declare function hydrateFieldDefaults(value: RillValue, type: TypeStructu
208
208
  * @returns Named argument map keyed by param name
209
209
  */
210
210
  export declare function marshalArgs(args: RillValue[], params: readonly RillParam[], options?: MarshalOptions): Record<string, RillValue>;
211
- export {};
@@ -21,14 +21,13 @@
21
21
  */
22
22
  import { RuntimeError } from '../../types.js';
23
23
  import { astEquals } from './equals.js';
24
- import { formatValue, formatStructure, inferType, isOrdered, createOrdered, copyValue, isTuple, paramToFieldDef, structureEquals, structureMatches, anyTypeValue, hasCollectionFields, emptyForType, } from './values.js';
25
- /** Type guard for any callable */
26
- export function isCallable(value) {
27
- return (typeof value === 'object' &&
28
- value !== null &&
29
- '__type' in value &&
30
- value.__type === 'callable');
31
- }
24
+ import { isCallable as _isCallableGuard, isDict, isOrdered, isTuple, } from './types/guards.js';
25
+ import { formatValue, inferType } from './types/registrations.js';
26
+ import { formatStructure, paramToFieldDef, structureEquals, structureMatches, } from './types/operations.js';
27
+ import { createOrdered, copyValue, emptyForType, } from './types/constructors.js';
28
+ import { anyTypeValue, hasCollectionFields } from './values.js';
29
+ /** Type guard for any callable (delegates to types/guards.ts) */
30
+ export const isCallable = _isCallableGuard;
32
31
  /** Type guard for script callable */
33
32
  export function isScriptCallable(value) {
34
33
  return isCallable(value) && value.kind === 'script';
@@ -90,14 +89,8 @@ export function toCallable(def, isProperty = false) {
90
89
  annotations: def.annotations ?? {},
91
90
  };
92
91
  }
93
- /** Type guard for dict (plain object, not array, not callable, not tuple) */
94
- export function isDict(value) {
95
- return (typeof value === 'object' &&
96
- value !== null &&
97
- !Array.isArray(value) &&
98
- !isCallable(value) &&
99
- !isTuple(value));
100
- }
92
+ // isDict imported from ./types/guards.js and re-exported
93
+ export { isDict };
101
94
  /** Format a callable for display */
102
95
  export function formatCallable(callable) {
103
96
  if (callable.kind === 'script') {
@@ -214,7 +207,7 @@ export function validateDefaultValueType(param, _functionName) {
214
207
  if (!structureMatches(param.defaultValue, param.type)) {
215
208
  const actualType = inferType(param.defaultValue);
216
209
  const expectedType = formatStructure(param.type);
217
- throw new Error(`Invalid defaultValue for parameter '${param.name}': expected ${expectedType}, got ${actualType}`);
210
+ throw new RuntimeError('RILL-R077', `Invalid defaultValue for parameter '${param.name}': expected ${expectedType}, got ${actualType}`);
218
211
  }
219
212
  }
220
213
  /**
@@ -4,8 +4,8 @@
4
4
  * Creates and configures the runtime context for script execution.
5
5
  * Public API for host applications.
6
6
  */
7
- import type { RuntimeContext, RuntimeOptions } from './types.js';
8
- import { type RillValue } from './values.js';
7
+ import type { RuntimeContext, RuntimeOptions } from './types/runtime.js';
8
+ import type { RillValue } from './types/structures.js';
9
9
  export declare const UNVALIDATED_METHOD_PARAMS: Set<string>;
10
10
  /**
11
11
  * Create a runtime context for script execution.
@@ -6,9 +6,9 @@
6
6
  */
7
7
  import { RuntimeError } from '../../types.js';
8
8
  import { BUILTIN_FUNCTIONS } from '../ext/builtins.js';
9
- import { BUILT_IN_TYPES } from './type-registrations.js';
10
- import { bindDictCallables } from './types.js';
11
- import { inferType } from './values.js';
9
+ import { BUILT_IN_TYPES } from './types/registrations.js';
10
+ import { bindDictCallables } from './types/runtime.js';
11
+ import { inferType } from './types/registrations.js';
12
12
  import { callable, validateDefaultValueType, } from './callable.js';
13
13
  // Built-in functions that are genuinely variadic and must skip arg validation.
14
14
  // log: tests call log("msg", extraValue) — extra args are silently ignored.
@@ -93,7 +93,7 @@ export function createRuntimeContext(options = {}) {
93
93
  if (description === undefined ||
94
94
  typeof description !== 'string' ||
95
95
  description.trim().length === 0) {
96
- throw new Error(`Function '${name}' requires description (requireDescriptions enabled)`);
96
+ throw new RuntimeError('RILL-R069', `Function '${name}' requires description (requireDescriptions enabled)`);
97
97
  }
98
98
  // Check parameter descriptions (EC-11)
99
99
  for (const param of params) {
@@ -101,7 +101,7 @@ export function createRuntimeContext(options = {}) {
101
101
  if (paramDesc === undefined ||
102
102
  typeof paramDesc !== 'string' ||
103
103
  paramDesc.trim().length === 0) {
104
- throw new Error(`Parameter '${param.name}' of function '${name}' requires description (requireDescriptions enabled)`);
104
+ throw new RuntimeError('RILL-R070', `Parameter '${param.name}' of function '${name}' requires description (requireDescriptions enabled)`);
105
105
  }
106
106
  }
107
107
  }
@@ -138,14 +138,14 @@ export function createRuntimeContext(options = {}) {
138
138
  const seenTypeNames = new Set();
139
139
  for (const reg of BUILT_IN_TYPES) {
140
140
  if (seenTypeNames.has(reg.name)) {
141
- throw new Error(`Duplicate type registration '${reg.name}'`);
141
+ throw new RuntimeError('RILL-R071', `Duplicate type registration '${reg.name}'`);
142
142
  }
143
143
  seenTypeNames.add(reg.name);
144
144
  }
145
145
  // EC-2: Validate every registration has protocol.format.
146
146
  for (const reg of BUILT_IN_TYPES) {
147
147
  if (!reg.protocol.format) {
148
- throw new Error(`Type '${reg.name}' missing required format protocol`);
148
+ throw new RuntimeError('RILL-R072', `Type '${reg.name}' missing required format protocol`);
149
149
  }
150
150
  }
151
151
  // Derive typeNames from registrations (replaces VALID_TYPE_NAMES in context).
@@ -170,7 +170,7 @@ export function createRuntimeContext(options = {}) {
170
170
  const dict = { ...existing };
171
171
  for (const [name, fn] of Object.entries(methods)) {
172
172
  if (seen.has(name)) {
173
- throw new Error(`Duplicate method '${name}' on type '${reg.name}'`);
173
+ throw new RuntimeError('RILL-R073', `Duplicate method '${name}' on type '${reg.name}'`);
174
174
  }
175
175
  seen.add(name);
176
176
  const appCallable = {
@@ -7,8 +7,8 @@
7
7
  * @internal
8
8
  */
9
9
  import type { ASTNode, CaptureNode, SourceLocation } from '../../../types.js';
10
- import type { RuntimeContext } from '../types.js';
11
- import type { RillValue } from '../values.js';
10
+ import type { RuntimeContext } from '../types/runtime.js';
11
+ import type { RillValue } from '../types/structures.js';
12
12
  /**
13
13
  * Base class for the evaluator.
14
14
  * Contains shared utilities used by all mixins.
@@ -74,6 +74,8 @@ export class EvaluatorBase {
74
74
  * Phase 1-3 use the functional evaluator which has its own handleCapture.
75
75
  */
76
76
  handleCapture(_capture, _value) {
77
+ // AC-13: Intentional raw throw - internal mixin guard, not user-reachable.
78
+ // This stub only runs if mixin composition is incomplete (programming error).
77
79
  throw new Error('handleCapture requires full Evaluator composition with VariablesMixin');
78
80
  }
79
81
  /**
@@ -100,7 +100,7 @@
100
100
  *
101
101
  * @internal
102
102
  */
103
- import type { RuntimeContext } from '../types.js';
103
+ import type { RuntimeContext } from '../types/runtime.js';
104
104
  /**
105
105
  * Complete Evaluator class composed from all mixins.
106
106
  *
@@ -8,8 +8,8 @@
8
8
  */
9
9
  import type { AnnotatedStatementNode, ASTNode, CaptureNode, ExpressionNode, RillTypeName, SourceLocation, StatementNode } from '../../../types.js';
10
10
  import type { RillCallable } from '../callable.js';
11
- import type { RuntimeContext } from '../types.js';
12
- import type { RillValue, TypeStructure } from '../values.js';
11
+ import type { RuntimeContext } from '../types/runtime.js';
12
+ import type { RillValue, TypeStructure } from '../types/structures.js';
13
13
  /**
14
14
  * Capture information returned by handleCapture.
15
15
  */