@rcrsr/rill 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -21
- 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.d.ts +3 -3
- package/dist/ext/crypto/index.js +62 -59
- package/dist/ext/exec/index.d.ts +3 -3
- package/dist/ext/exec/index.js +15 -9
- package/dist/ext/fetch/index.d.ts +3 -3
- package/dist/ext/fetch/index.js +17 -12
- package/dist/ext/fetch/request.js +1 -1
- package/dist/ext/fs/index.d.ts +3 -3
- package/dist/ext/fs/index.js +256 -266
- package/dist/ext/fs/sandbox.d.ts +18 -0
- package/dist/ext/fs/sandbox.js +33 -0
- package/dist/ext/kv/index.d.ts +3 -3
- package/dist/ext/kv/index.js +198 -196
- package/dist/ext/kv/store.d.ts +1 -1
- package/dist/ext/kv/store.js +2 -1
- package/dist/ext-parse-bridge.d.ts +10 -0
- package/dist/ext-parse-bridge.js +10 -0
- package/dist/generated/introspection-data.d.ts +1 -1
- package/dist/generated/introspection-data.js +385 -296
- 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 -4
- package/dist/index.js +1 -5
- 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-types.js +12 -0
- package/dist/parser/parser-use.js +26 -3
- package/dist/parser/parser.d.ts +2 -0
- package/dist/parser/parser.js +2 -0
- package/dist/runtime/core/callable.d.ts +24 -13
- package/dist/runtime/core/callable.js +71 -38
- package/dist/runtime/core/context.d.ts +2 -13
- package/dist/runtime/core/context.js +80 -79
- 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 +3 -3
- package/dist/runtime/core/eval/index.js +11 -0
- package/dist/runtime/core/eval/mixins/closures.js +381 -41
- 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 +61 -115
- package/dist/runtime/core/eval/mixins/core.js +17 -4
- package/dist/runtime/core/eval/mixins/expressions.js +36 -27
- 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 +17 -6
- package/dist/runtime/core/eval/mixins/types.js +73 -54
- package/dist/runtime/core/eval/mixins/variables.js +12 -8
- package/dist/runtime/core/execute.d.ts +1 -1
- package/dist/runtime/core/field-descriptor.d.ts +3 -3
- package/dist/runtime/core/field-descriptor.js +2 -1
- package/dist/runtime/core/introspection.d.ts +2 -2
- package/dist/runtime/core/introspection.js +7 -6
- 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/markers.d.ts +12 -0
- package/dist/runtime/core/types/markers.js +7 -0
- package/dist/runtime/core/types/operations.d.ts +98 -0
- package/dist/runtime/core/types/operations.js +804 -0
- package/dist/runtime/core/types/registrations.d.ts +126 -0
- package/dist/runtime/core/types/registrations.js +751 -0
- package/dist/runtime/core/{types.d.ts → types/runtime.d.ts} +22 -10
- package/dist/runtime/core/types/structures.d.ts +146 -0
- package/dist/runtime/core/types/structures.js +12 -0
- package/dist/runtime/core/values.d.ts +29 -209
- package/dist/runtime/core/values.js +56 -968
- package/dist/runtime/ext/builtins.js +88 -68
- package/dist/runtime/ext/extensions.d.ts +31 -125
- package/dist/runtime/ext/extensions.js +2 -94
- package/dist/runtime/ext/test-context.d.ts +28 -0
- package/dist/runtime/ext/test-context.js +155 -0
- package/dist/runtime/index.d.ts +12 -12
- package/dist/runtime/index.js +13 -5
- package/dist/signature-parser.d.ts +2 -2
- package/dist/signature-parser.js +14 -14
- package/dist/token-types.d.ts +1 -0
- package/dist/token-types.js +1 -0
- package/package.json +1 -1
- /package/dist/runtime/core/{types.js → types/runtime.js} +0 -0
|
@@ -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
|
/**
|
|
@@ -642,13 +645,13 @@ function createLiteralsMixin(Base) {
|
|
|
642
645
|
if (resolvedType === undefined && defaultValue !== undefined) {
|
|
643
646
|
const defaultKind = typeof defaultValue;
|
|
644
647
|
if (defaultKind === 'string') {
|
|
645
|
-
resolvedType = {
|
|
648
|
+
resolvedType = { kind: 'string' };
|
|
646
649
|
}
|
|
647
650
|
else if (defaultKind === 'number') {
|
|
648
|
-
resolvedType = {
|
|
651
|
+
resolvedType = { kind: 'number' };
|
|
649
652
|
}
|
|
650
653
|
else if (defaultKind === 'boolean') {
|
|
651
|
-
resolvedType = {
|
|
654
|
+
resolvedType = { kind: 'bool' };
|
|
652
655
|
}
|
|
653
656
|
}
|
|
654
657
|
// Evaluate per-param annotations inline
|
|
@@ -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,21 +23,11 @@
|
|
|
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
|
-
/**
|
|
29
|
-
* Leaf types that reject all type arguments.
|
|
30
|
-
* Extracted as module-level constant to avoid per-call allocation.
|
|
31
|
-
*/
|
|
32
|
-
const LEAF_TYPES = new Set([
|
|
33
|
-
'string',
|
|
34
|
-
'number',
|
|
35
|
-
'bool',
|
|
36
|
-
'vector',
|
|
37
|
-
'type',
|
|
38
|
-
'any',
|
|
39
|
-
'closure',
|
|
40
|
-
]);
|
|
41
31
|
/**
|
|
42
32
|
* TypesMixin implementation.
|
|
43
33
|
*
|
|
@@ -87,7 +77,7 @@ function createTypesMixin(Base) {
|
|
|
87
77
|
throw new RuntimeError('RILL-R004', 'list() requires exactly 1 type argument', location);
|
|
88
78
|
}
|
|
89
79
|
const element = await resolveArg(args[0]);
|
|
90
|
-
const structure = {
|
|
80
|
+
const structure = { kind: 'list', element };
|
|
91
81
|
return Object.freeze({
|
|
92
82
|
__rill_type: true,
|
|
93
83
|
typeName: name,
|
|
@@ -107,11 +97,11 @@ function createTypesMixin(Base) {
|
|
|
107
97
|
// EC-B6: Default type mismatch on uniform single-arg path
|
|
108
98
|
if (positional[0].defaultValue !== undefined) {
|
|
109
99
|
const defaultVal = await evaluateDefault(positional[0].defaultValue);
|
|
110
|
-
if (!
|
|
111
|
-
throw new RuntimeError('RILL-R004', `Default value for ${name} element must be ${
|
|
100
|
+
if (!structureMatches(defaultVal, valueType)) {
|
|
101
|
+
throw new RuntimeError('RILL-R004', `Default value for ${name} element must be ${formatStructure(valueType)}, got ${inferType(defaultVal)}`, location);
|
|
112
102
|
}
|
|
113
103
|
}
|
|
114
|
-
const structure = {
|
|
104
|
+
const structure = { kind: name, valueType };
|
|
115
105
|
return Object.freeze({
|
|
116
106
|
__rill_type: true,
|
|
117
107
|
typeName: name,
|
|
@@ -131,14 +121,14 @@ function createTypesMixin(Base) {
|
|
|
131
121
|
if (arg.defaultValue !== undefined) {
|
|
132
122
|
const defaultVal = await evaluateDefault(arg.defaultValue);
|
|
133
123
|
// EC-B6: Default type mismatch
|
|
134
|
-
if (!
|
|
135
|
-
throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${
|
|
124
|
+
if (!structureMatches(defaultVal, resolvedType)) {
|
|
125
|
+
throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
|
|
136
126
|
}
|
|
137
127
|
fieldDef.defaultValue = defaultVal;
|
|
138
128
|
}
|
|
139
129
|
fields[arg.name] = fieldDef;
|
|
140
130
|
}
|
|
141
|
-
const structure = {
|
|
131
|
+
const structure = { kind: 'dict', fields };
|
|
142
132
|
return Object.freeze({
|
|
143
133
|
__rill_type: true,
|
|
144
134
|
typeName: name,
|
|
@@ -156,14 +146,17 @@ function createTypesMixin(Base) {
|
|
|
156
146
|
if (arg.defaultValue !== undefined) {
|
|
157
147
|
const defaultVal = await evaluateDefault(arg.defaultValue);
|
|
158
148
|
// EC-B6: Default type mismatch
|
|
159
|
-
if (!
|
|
160
|
-
throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${
|
|
149
|
+
if (!structureMatches(defaultVal, resolvedType)) {
|
|
150
|
+
throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
|
|
161
151
|
}
|
|
162
152
|
fieldDef.defaultValue = defaultVal;
|
|
163
153
|
}
|
|
164
154
|
orderedFields.push(fieldDef);
|
|
165
155
|
}
|
|
166
|
-
const structure = {
|
|
156
|
+
const structure = {
|
|
157
|
+
kind: 'ordered',
|
|
158
|
+
fields: orderedFields,
|
|
159
|
+
};
|
|
167
160
|
return Object.freeze({
|
|
168
161
|
__rill_type: true,
|
|
169
162
|
typeName: name,
|
|
@@ -183,11 +176,11 @@ function createTypesMixin(Base) {
|
|
|
183
176
|
// EC-B6: Default type mismatch on uniform single-arg path
|
|
184
177
|
if (args[0].defaultValue !== undefined) {
|
|
185
178
|
const defaultVal = await evaluateDefault(args[0].defaultValue);
|
|
186
|
-
if (!
|
|
187
|
-
throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${
|
|
179
|
+
if (!structureMatches(defaultVal, valueType)) {
|
|
180
|
+
throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${formatStructure(valueType)}, got ${inferType(defaultVal)}`, location);
|
|
188
181
|
}
|
|
189
182
|
}
|
|
190
|
-
const structure = {
|
|
183
|
+
const structure = { kind: 'tuple', valueType };
|
|
191
184
|
return Object.freeze({
|
|
192
185
|
__rill_type: true,
|
|
193
186
|
typeName: 'tuple',
|
|
@@ -202,8 +195,8 @@ function createTypesMixin(Base) {
|
|
|
202
195
|
if (arg.defaultValue !== undefined) {
|
|
203
196
|
const defaultVal = await evaluateDefault(arg.defaultValue);
|
|
204
197
|
// EC-B6: Default type mismatch
|
|
205
|
-
if (!
|
|
206
|
-
throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${
|
|
198
|
+
if (!structureMatches(defaultVal, resolvedType)) {
|
|
199
|
+
throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
|
|
207
200
|
}
|
|
208
201
|
fieldDef.defaultValue = defaultVal;
|
|
209
202
|
}
|
|
@@ -221,7 +214,7 @@ function createTypesMixin(Base) {
|
|
|
221
214
|
throw new RuntimeError('RILL-R004', `tuple() default values must be trailing: element at position ${i} has no default but a preceding element does`, location);
|
|
222
215
|
}
|
|
223
216
|
}
|
|
224
|
-
const structure = {
|
|
217
|
+
const structure = { kind: 'tuple', elements };
|
|
225
218
|
return Object.freeze({
|
|
226
219
|
__rill_type: true,
|
|
227
220
|
typeName: 'tuple',
|
|
@@ -254,13 +247,26 @@ function createTypesMixin(Base) {
|
|
|
254
247
|
return Object.freeze({
|
|
255
248
|
__rill_type: true,
|
|
256
249
|
typeName,
|
|
257
|
-
structure: {
|
|
250
|
+
structure: { kind: typeName },
|
|
258
251
|
});
|
|
259
252
|
}
|
|
260
|
-
// EC-B1: Leaf types reject all type arguments
|
|
261
|
-
if (
|
|
253
|
+
// EC-B1: Leaf types reject all type arguments (AC-4: derived from registrations)
|
|
254
|
+
if (this.ctx.leafTypes.has(typeName)) {
|
|
262
255
|
throw new RuntimeError('RILL-R004', `${typeName} does not accept type arguments`);
|
|
263
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
|
+
}
|
|
264
270
|
// Delegate to buildCollectionType with recursive resolveTypeRef
|
|
265
271
|
return this.buildCollectionType(typeName, args, async (arg) => {
|
|
266
272
|
const resolved = await this.resolveTypeRef(arg.value, getVariableFn);
|
|
@@ -271,7 +277,7 @@ function createTypesMixin(Base) {
|
|
|
271
277
|
});
|
|
272
278
|
}
|
|
273
279
|
// Union type ref: (A | B) -- resolve each member recursively and
|
|
274
|
-
// return a RillTypeValue with structure: {
|
|
280
|
+
// return a RillTypeValue with structure: { kind: 'union', members: [...] }.
|
|
275
281
|
// typeName is set to a display string for error messages; the structure
|
|
276
282
|
// field carries the authoritative type shape for validation (DR-1).
|
|
277
283
|
if (typeRef.kind === 'union') {
|
|
@@ -280,9 +286,9 @@ function createTypesMixin(Base) {
|
|
|
280
286
|
const resolved = await this.resolveTypeRef(member, getVariableFn);
|
|
281
287
|
members.push(resolved.structure);
|
|
282
288
|
}
|
|
283
|
-
const structure = {
|
|
289
|
+
const structure = { kind: 'union', members };
|
|
284
290
|
const displayName = members
|
|
285
|
-
.map(
|
|
291
|
+
.map(formatStructure)
|
|
286
292
|
.join('|');
|
|
287
293
|
return Object.freeze({
|
|
288
294
|
__rill_type: true,
|
|
@@ -301,13 +307,13 @@ function createTypesMixin(Base) {
|
|
|
301
307
|
/**
|
|
302
308
|
* Assert that a value is of the expected type.
|
|
303
309
|
* Returns the value unchanged if assertion passes, throws on mismatch.
|
|
304
|
-
* Accepts a bare RillTypeName or a full
|
|
305
|
-
* When expected is a
|
|
306
|
-
* dispatches to
|
|
310
|
+
* Accepts a bare RillTypeName or a full TypeStructure.
|
|
311
|
+
* When expected is a TypeStructure with sub-fields (element, fields, elements),
|
|
312
|
+
* dispatches to structureMatches for deep validation.
|
|
307
313
|
* Exported for use by type assertion evaluation.
|
|
308
314
|
*/
|
|
309
315
|
assertType(value, expected, location) {
|
|
310
|
-
// Structural path: expected is a
|
|
316
|
+
// Structural path: expected is a TypeStructure object
|
|
311
317
|
if (typeof expected !== 'string') {
|
|
312
318
|
const hasSubFields = 'element' in expected ||
|
|
313
319
|
'fields' in expected ||
|
|
@@ -315,15 +321,15 @@ function createTypesMixin(Base) {
|
|
|
315
321
|
'members' in expected ||
|
|
316
322
|
'valueType' in expected;
|
|
317
323
|
if (hasSubFields) {
|
|
318
|
-
if (!
|
|
319
|
-
const expectedStr =
|
|
320
|
-
const actualStr =
|
|
324
|
+
if (!structureMatches(value, expected)) {
|
|
325
|
+
const expectedStr = formatStructure(expected);
|
|
326
|
+
const actualStr = formatStructure(inferStructure(value));
|
|
321
327
|
throw new RuntimeError('RILL-R004', `Type assertion failed: expected ${expectedStr}, got ${actualStr}`, location, { expectedType: expectedStr, actualType: actualStr });
|
|
322
328
|
}
|
|
323
329
|
return value;
|
|
324
330
|
}
|
|
325
331
|
// Bare structural type (no sub-fields): fall through using type name
|
|
326
|
-
expected = expected.
|
|
332
|
+
expected = expected.kind;
|
|
327
333
|
}
|
|
328
334
|
// Bare type name path
|
|
329
335
|
if (expected === 'any')
|
|
@@ -366,7 +372,7 @@ function createTypesMixin(Base) {
|
|
|
366
372
|
'members' in resolved.structure ||
|
|
367
373
|
'valueType' in resolved.structure;
|
|
368
374
|
if (hasSubFields) {
|
|
369
|
-
return
|
|
375
|
+
return structureMatches(value, resolved.structure);
|
|
370
376
|
}
|
|
371
377
|
return checkType(value, resolved.typeName);
|
|
372
378
|
}
|
|
@@ -407,11 +413,24 @@ function createTypesMixin(Base) {
|
|
|
407
413
|
async evaluateTypeConstructor(node) {
|
|
408
414
|
const name = node.constructorName;
|
|
409
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
|
+
}
|
|
410
429
|
return this.buildCollectionType(name, node.args, async (arg) => {
|
|
411
430
|
const resolved = await this.resolveTypeRef(arg.value, (varName) => getVariable(this.ctx, varName));
|
|
412
|
-
return resolved.structure.
|
|
431
|
+
return resolved.structure.kind === 'any' &&
|
|
413
432
|
resolved.typeName !== 'any'
|
|
414
|
-
? {
|
|
433
|
+
? { kind: resolved.typeName }
|
|
415
434
|
: resolved.structure;
|
|
416
435
|
}, async (node) => {
|
|
417
436
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -422,7 +441,7 @@ function createTypesMixin(Base) {
|
|
|
422
441
|
* Evaluate a closure signature literal into a RillTypeValue [IR-8].
|
|
423
442
|
*
|
|
424
443
|
* Creates a closure type value from |param: T, ...|: R syntax.
|
|
425
|
-
* Each parameter produces a [name,
|
|
444
|
+
* Each parameter produces a [name, TypeStructure] entry.
|
|
426
445
|
*
|
|
427
446
|
* Error contracts:
|
|
428
447
|
* - EC-8: missing return type -> RILL-R004 (enforced at parse time; node always has returnType)
|
|
@@ -430,14 +449,14 @@ function createTypesMixin(Base) {
|
|
|
430
449
|
*/
|
|
431
450
|
async evaluateClosureSigLiteral(node) {
|
|
432
451
|
const location = node.span.start;
|
|
433
|
-
// Helper: evaluate a type expression and extract
|
|
452
|
+
// Helper: evaluate a type expression and extract TypeStructure
|
|
434
453
|
const resolveTypeExpr = async (argVal) => {
|
|
435
454
|
if (!isTypeValue(argVal)) {
|
|
436
455
|
throw new RuntimeError('RILL-R004', `Parameter type must be a type value, got ${inferType(argVal)}`, location);
|
|
437
456
|
}
|
|
438
|
-
return argVal.structure.
|
|
457
|
+
return argVal.structure.kind === 'any' &&
|
|
439
458
|
argVal.typeName !== 'any'
|
|
440
|
-
? {
|
|
459
|
+
? { kind: argVal.typeName }
|
|
441
460
|
: argVal.structure;
|
|
442
461
|
};
|
|
443
462
|
// Evaluate parameter types
|
|
@@ -456,11 +475,11 @@ function createTypesMixin(Base) {
|
|
|
456
475
|
if (!isTypeValue(retVal)) {
|
|
457
476
|
throw new RuntimeError('RILL-R004', `Closure type literal requires return type after |, got ${inferType(retVal)}`, location);
|
|
458
477
|
}
|
|
459
|
-
const ret = retVal.structure.
|
|
478
|
+
const ret = retVal.structure.kind === 'any' &&
|
|
460
479
|
retVal.typeName !== 'any'
|
|
461
|
-
? {
|
|
480
|
+
? { kind: retVal.typeName }
|
|
462
481
|
: retVal.structure;
|
|
463
|
-
const structure = {
|
|
482
|
+
const structure = { kind: 'closure', params, ret };
|
|
464
483
|
return Object.freeze({
|
|
465
484
|
__rill_type: true,
|
|
466
485
|
typeName: 'closure',
|
|
@@ -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
|
/**
|
|
@@ -69,8 +71,8 @@ function createVariablesMixin(Base) {
|
|
|
69
71
|
if (explicitType !== undefined) {
|
|
70
72
|
if (typeof explicitType === 'object') {
|
|
71
73
|
// Structural type check
|
|
72
|
-
if (!
|
|
73
|
-
const expectedLabel =
|
|
74
|
+
if (!structureMatches(value, explicitType)) {
|
|
75
|
+
const expectedLabel = formatStructure(explicitType);
|
|
74
76
|
throw new RuntimeError('RILL-R001', `Type mismatch: cannot assign ${valueType} to $${name}:${expectedLabel}`, location, {
|
|
75
77
|
variableName: name,
|
|
76
78
|
expectedType: expectedLabel,
|
|
@@ -98,8 +100,8 @@ function createVariablesMixin(Base) {
|
|
|
98
100
|
if (lockedType !== undefined && lockedType !== 'any') {
|
|
99
101
|
if (typeof lockedType === 'object') {
|
|
100
102
|
// Structural locked type — validate full shape
|
|
101
|
-
if (!
|
|
102
|
-
const expectedLabel =
|
|
103
|
+
if (!structureMatches(value, lockedType)) {
|
|
104
|
+
const expectedLabel = formatStructure(lockedType);
|
|
103
105
|
throw new RuntimeError('RILL-R001', `Type mismatch: cannot assign ${valueType} to $${name} (locked as ${expectedLabel})`, location, {
|
|
104
106
|
variableName: name,
|
|
105
107
|
expectedType: expectedLabel,
|
|
@@ -120,7 +122,9 @@ function createVariablesMixin(Base) {
|
|
|
120
122
|
if (!this.ctx.variableTypes.has(name)) {
|
|
121
123
|
// Store structural type (object) directly so re-assignment checks
|
|
122
124
|
// validate the full shape. Fall back to valueType when no annotation.
|
|
123
|
-
const lockType = explicitType !== undefined
|
|
125
|
+
const lockType = explicitType !== undefined
|
|
126
|
+
? explicitType
|
|
127
|
+
: valueType;
|
|
124
128
|
this.ctx.variableTypes.set(name, lockType);
|
|
125
129
|
}
|
|
126
130
|
}
|
|
@@ -260,7 +264,7 @@ function createVariablesMixin(Base) {
|
|
|
260
264
|
value = value.typeName;
|
|
261
265
|
}
|
|
262
266
|
else if (field === 'signature') {
|
|
263
|
-
value =
|
|
267
|
+
value = formatStructure(value.structure);
|
|
264
268
|
}
|
|
265
269
|
else {
|
|
266
270
|
throw new RuntimeError('RILL-R003', `Type value has no property "${field}"`, this.getNodeLocation(node));
|
|
@@ -322,7 +326,7 @@ function createVariablesMixin(Base) {
|
|
|
322
326
|
return true;
|
|
323
327
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
324
328
|
const resolved = await this.resolveTypeRef(typeRef, (name) => getVariable(this.ctx, name));
|
|
325
|
-
return
|
|
329
|
+
return structureMatches(fieldValue, resolved.structure);
|
|
326
330
|
};
|
|
327
331
|
if (finalAccess.kind === 'literal') {
|
|
328
332
|
// Check if literal field exists in dict
|
|
@@ -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,
|
|
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.
|
|
@@ -23,6 +23,6 @@ export interface RillFieldDescriptor {
|
|
|
23
23
|
*
|
|
24
24
|
* EC-1: Throws RILL-R003 when fieldName is absent from structuralType.fields.
|
|
25
25
|
*/
|
|
26
|
-
export declare function buildFieldDescriptor(structuralType:
|
|
27
|
-
|
|
26
|
+
export declare function buildFieldDescriptor(structuralType: TypeStructure & {
|
|
27
|
+
kind: 'dict';
|
|
28
28
|
}, fieldName: string, location: SourceLocation): RillFieldDescriptor;
|
|
@@ -14,7 +14,8 @@ import { RuntimeError } from '../../types.js';
|
|
|
14
14
|
* EC-1: Throws RILL-R003 when fieldName is absent from structuralType.fields.
|
|
15
15
|
*/
|
|
16
16
|
export function buildFieldDescriptor(structuralType, fieldName, location) {
|
|
17
|
-
const
|
|
17
|
+
const fields = structuralType.fields;
|
|
18
|
+
const fieldType = fields?.[fieldName];
|
|
18
19
|
if (fieldType === undefined) {
|
|
19
20
|
throw new RuntimeError('RILL-R003', `Shape has no field "${fieldName}"`, location);
|
|
20
21
|
}
|
|
@@ -4,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 {
|
|
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';
|
|
@@ -40,7 +41,7 @@ export function getFunctions(ctx) {
|
|
|
40
41
|
if (callable.params) {
|
|
41
42
|
const params = callable.params.map((p) => ({
|
|
42
43
|
name: p.name,
|
|
43
|
-
type: p.type !== undefined ?
|
|
44
|
+
type: p.type !== undefined ? formatStructure(p.type) : 'any',
|
|
44
45
|
description: typeof p.annotations['description'] === 'string'
|
|
45
46
|
? p.annotations['description']
|
|
46
47
|
: '',
|
|
@@ -50,7 +51,7 @@ export function getFunctions(ctx) {
|
|
|
50
51
|
name,
|
|
51
52
|
description: callable.annotations?.['description'] ?? '',
|
|
52
53
|
params,
|
|
53
|
-
returnType:
|
|
54
|
+
returnType: formatStructure(callable.returnType.structure),
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
57
|
else {
|
|
@@ -93,7 +94,7 @@ export function getFunctions(ctx) {
|
|
|
93
94
|
// Convert params to ParamMetadata using RillParam.type (IC-5)
|
|
94
95
|
const params = value.params.map((p) => ({
|
|
95
96
|
name: p.name,
|
|
96
|
-
type: p.type !== undefined ?
|
|
97
|
+
type: p.type !== undefined ? formatStructure(p.type) : 'any',
|
|
97
98
|
description: typeof p.annotations['description'] === 'string'
|
|
98
99
|
? p.annotations['description']
|
|
99
100
|
: '',
|
|
@@ -131,7 +132,7 @@ function serializeParam(p) {
|
|
|
131
132
|
parts.push(`^(description: "${desc}") `);
|
|
132
133
|
}
|
|
133
134
|
// Name and type
|
|
134
|
-
const typeName = p.type !== undefined ?
|
|
135
|
+
const typeName = p.type !== undefined ? formatStructure(p.type) : 'any';
|
|
135
136
|
parts.push(`${p.name}: ${typeName}`);
|
|
136
137
|
// Default value
|
|
137
138
|
if (p.defaultValue !== undefined) {
|
|
@@ -189,7 +190,7 @@ export function generateManifest(ctx) {
|
|
|
189
190
|
if (!isApplicationCallable(callable) || callable.params === undefined) {
|
|
190
191
|
continue;
|
|
191
192
|
}
|
|
192
|
-
const signature = serializeClosureSignature(callable.params,
|
|
193
|
+
const signature = serializeClosureSignature(callable.params, formatStructure(callable.returnType.structure), callable.annotations?.['description'] ?? undefined);
|
|
193
194
|
entries.push(` "${name}": ${signature}`);
|
|
194
195
|
}
|
|
195
196
|
if (entries.length === 0) {
|
|
@@ -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;
|