@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.
- package/dist/ast-nodes.d.ts +14 -4
- package/dist/ast-unions.d.ts +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -0
- package/dist/error-registry.js +228 -0
- package/dist/ext/crypto/index.js +5 -5
- package/dist/ext/exec/index.js +3 -3
- package/dist/ext/fetch/index.js +4 -4
- package/dist/ext/fetch/request.js +1 -1
- package/dist/ext/fs/index.js +101 -114
- package/dist/ext/fs/sandbox.d.ts +18 -0
- package/dist/ext/fs/sandbox.js +33 -0
- package/dist/ext/kv/index.js +12 -12
- package/dist/ext/kv/store.d.ts +1 -1
- package/dist/ext/kv/store.js +1 -1
- package/dist/generated/version-data.d.ts +1 -1
- package/dist/generated/version-data.js +2 -2
- package/dist/highlight-map.js +1 -0
- package/dist/index.d.ts +1 -15
- package/dist/index.js +1 -14
- package/dist/lexer/operators.js +1 -0
- package/dist/parser/helpers.js +1 -0
- package/dist/parser/parser-expr.js +44 -5
- package/dist/parser/parser-literals.js +111 -4
- package/dist/parser/parser-shape.js +2 -2
- package/dist/parser/parser-use.js +19 -2
- package/dist/parser/parser.d.ts +2 -0
- package/dist/parser/parser.js +2 -0
- package/dist/runtime/core/callable.d.ts +5 -6
- package/dist/runtime/core/callable.js +10 -17
- package/dist/runtime/core/context.d.ts +2 -2
- package/dist/runtime/core/context.js +8 -8
- package/dist/runtime/core/eval/base.d.ts +2 -2
- package/dist/runtime/core/eval/base.js +2 -0
- package/dist/runtime/core/eval/evaluator.d.ts +1 -1
- package/dist/runtime/core/eval/index.d.ts +2 -2
- package/dist/runtime/core/eval/mixins/closures.js +367 -27
- package/dist/runtime/core/eval/mixins/collections.js +81 -6
- package/dist/runtime/core/eval/mixins/control-flow.js +1 -1
- package/dist/runtime/core/eval/mixins/conversion.js +17 -12
- package/dist/runtime/core/eval/mixins/core.js +15 -2
- package/dist/runtime/core/eval/mixins/expressions.js +3 -2
- package/dist/runtime/core/eval/mixins/extraction.js +2 -3
- package/dist/runtime/core/eval/mixins/list-dispatch.js +1 -1
- package/dist/runtime/core/eval/mixins/literals.js +14 -3
- package/dist/runtime/core/eval/mixins/types.js +30 -1
- package/dist/runtime/core/eval/mixins/variables.js +3 -1
- package/dist/runtime/core/execute.d.ts +1 -1
- package/dist/runtime/core/field-descriptor.d.ts +1 -1
- package/dist/runtime/core/introspection.d.ts +2 -2
- package/dist/runtime/core/introspection.js +2 -1
- package/dist/runtime/core/resolvers.d.ts +1 -1
- package/dist/runtime/core/signals.d.ts +6 -1
- package/dist/runtime/core/signals.js +9 -0
- package/dist/runtime/core/types/constructors.d.ts +54 -0
- package/dist/runtime/core/types/constructors.js +201 -0
- package/dist/runtime/core/types/guards.d.ts +42 -0
- package/dist/runtime/core/types/guards.js +88 -0
- package/dist/runtime/core/types/index.d.ts +18 -0
- package/dist/runtime/core/types/index.js +19 -0
- package/dist/runtime/core/types/operations.d.ts +98 -0
- package/dist/runtime/core/types/operations.js +804 -0
- package/dist/runtime/core/{type-registrations.d.ts → types/registrations.d.ts} +12 -22
- package/dist/runtime/core/{type-registrations.js → types/registrations.js} +94 -92
- package/dist/runtime/core/{types.d.ts → types/runtime.d.ts} +8 -8
- package/dist/runtime/core/{type-structures.d.ts → types/structures.d.ts} +21 -3
- package/dist/runtime/core/values.d.ts +13 -102
- package/dist/runtime/core/values.js +26 -722
- package/dist/runtime/ext/builtins.js +9 -8
- package/dist/runtime/ext/extensions.d.ts +2 -2
- package/dist/runtime/ext/extensions.js +2 -1
- package/dist/runtime/ext/test-context.d.ts +2 -2
- package/dist/runtime/ext/test-context.js +3 -2
- package/dist/runtime/index.d.ts +8 -22
- package/dist/runtime/index.js +10 -16
- package/dist/signature-parser.d.ts +1 -1
- package/dist/token-types.d.ts +1 -0
- package/dist/token-types.js +1 -0
- package/package.json +1 -1
- /package/dist/runtime/core/{markers.d.ts → types/markers.d.ts} +0 -0
- /package/dist/runtime/core/{markers.js → types/markers.js} +0 -0
- /package/dist/runtime/core/{types.js → types/runtime.js} +0 -0
- /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
|
|
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 '../../
|
|
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
|
|
141
|
-
// with
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 '../../
|
|
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
|
|
22
|
-
import {
|
|
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
|
|
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))
|
|
@@ -25,7 +25,10 @@
|
|
|
25
25
|
* @internal
|
|
26
26
|
*/
|
|
27
27
|
import { RuntimeError } from '../../../../types.js';
|
|
28
|
-
import {
|
|
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
|
-
|
|
675
|
-
|
|
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
|
|
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 {
|
|
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 './
|
|
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 './
|
|
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
|
|
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 './
|
|
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
|
+
}
|