@rcrsr/rill 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -21
- package/dist/ast-nodes.d.ts +2 -13
- package/dist/ast-nodes.js +0 -1
- package/dist/ast-unions.d.ts +0 -1
- package/dist/ast-unions.js +0 -1
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +0 -1
- package/dist/error-classes.d.ts +0 -1
- package/dist/error-classes.js +0 -1
- package/dist/error-formatter.d.ts +0 -1
- package/dist/error-formatter.js +0 -1
- package/dist/error-registry.d.ts +0 -1
- package/dist/error-registry.js +32 -1
- package/dist/ext/crypto/index.d.ts +3 -4
- package/dist/ext/crypto/index.js +66 -64
- package/dist/ext/exec/index.d.ts +3 -4
- package/dist/ext/exec/index.js +17 -12
- package/dist/ext/exec/runner.d.ts +0 -1
- package/dist/ext/exec/runner.js +0 -1
- package/dist/ext/fetch/index.d.ts +3 -4
- package/dist/ext/fetch/index.js +23 -49
- package/dist/ext/fetch/request.d.ts +0 -1
- package/dist/ext/fetch/request.js +0 -1
- package/dist/ext/fs/index.d.ts +3 -4
- package/dist/ext/fs/index.js +268 -266
- package/dist/ext/fs/sandbox.d.ts +0 -1
- package/dist/ext/fs/sandbox.js +0 -1
- package/dist/ext/kv/index.d.ts +3 -4
- package/dist/ext/kv/index.js +216 -215
- package/dist/ext/kv/store.d.ts +0 -1
- package/dist/ext/kv/store.js +2 -2
- 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 -2
- package/dist/generated/introspection-data.js +385 -297
- package/dist/generated/version-data.d.ts +1 -2
- package/dist/generated/version-data.js +2 -3
- package/dist/highlight-map.d.ts +0 -1
- package/dist/highlight-map.js +0 -1
- package/dist/index.d.ts +15 -5
- package/dist/index.js +14 -6
- package/dist/lexer/errors.d.ts +0 -1
- package/dist/lexer/errors.js +0 -1
- package/dist/lexer/helpers.d.ts +0 -1
- package/dist/lexer/helpers.js +0 -1
- package/dist/lexer/index.d.ts +0 -1
- package/dist/lexer/index.js +0 -1
- package/dist/lexer/operators.d.ts +0 -1
- package/dist/lexer/operators.js +0 -1
- package/dist/lexer/readers.d.ts +0 -1
- package/dist/lexer/readers.js +0 -1
- package/dist/lexer/state.d.ts +0 -1
- package/dist/lexer/state.js +0 -1
- package/dist/lexer/tokenizer.d.ts +0 -1
- package/dist/lexer/tokenizer.js +0 -1
- package/dist/parser/helpers.d.ts +0 -1
- package/dist/parser/helpers.js +0 -1
- package/dist/parser/index.d.ts +0 -1
- package/dist/parser/index.js +0 -1
- package/dist/parser/parser-collect.d.ts +0 -1
- package/dist/parser/parser-collect.js +0 -1
- package/dist/parser/parser-control.d.ts +0 -1
- package/dist/parser/parser-control.js +0 -1
- package/dist/parser/parser-expr.d.ts +0 -1
- package/dist/parser/parser-expr.js +0 -1
- package/dist/parser/parser-extract.d.ts +0 -1
- package/dist/parser/parser-extract.js +0 -1
- package/dist/parser/parser-functions.d.ts +0 -1
- package/dist/parser/parser-functions.js +0 -1
- package/dist/parser/parser-literals.d.ts +0 -1
- package/dist/parser/parser-literals.js +4 -2
- package/dist/parser/parser-script.d.ts +0 -1
- package/dist/parser/parser-script.js +0 -1
- package/dist/parser/parser-shape.d.ts +2 -3
- package/dist/parser/parser-shape.js +8 -52
- package/dist/parser/parser-types.d.ts +28 -2
- package/dist/parser/parser-types.js +76 -13
- package/dist/parser/parser-use.d.ts +0 -1
- package/dist/parser/parser-use.js +7 -2
- package/dist/parser/parser-variables.d.ts +0 -1
- package/dist/parser/parser-variables.js +0 -1
- package/dist/parser/parser.d.ts +0 -1
- package/dist/parser/parser.js +0 -1
- package/dist/parser/state.d.ts +0 -1
- package/dist/parser/state.js +0 -1
- package/dist/runtime/core/callable.d.ts +59 -20
- package/dist/runtime/core/callable.js +188 -39
- package/dist/runtime/core/context.d.ts +0 -12
- package/dist/runtime/core/context.js +77 -77
- package/dist/runtime/core/equals.d.ts +0 -1
- package/dist/runtime/core/equals.js +35 -3
- package/dist/runtime/core/eval/base.d.ts +0 -1
- package/dist/runtime/core/eval/base.js +0 -1
- package/dist/runtime/core/eval/evaluator.d.ts +0 -1
- package/dist/runtime/core/eval/evaluator.js +0 -1
- package/dist/runtime/core/eval/index.d.ts +2 -3
- package/dist/runtime/core/eval/index.js +11 -1
- package/dist/runtime/core/eval/mixins/annotations.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/annotations.js +0 -1
- package/dist/runtime/core/eval/mixins/closures.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/closures.js +92 -70
- package/dist/runtime/core/eval/mixins/collections.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/collections.js +9 -4
- package/dist/runtime/core/eval/mixins/control-flow.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/control-flow.js +0 -1
- package/dist/runtime/core/eval/mixins/conversion.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/conversion.js +196 -188
- package/dist/runtime/core/eval/mixins/core.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/core.js +2 -3
- package/dist/runtime/core/eval/mixins/expressions.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/expressions.js +35 -28
- package/dist/runtime/core/eval/mixins/extraction.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/extraction.js +8 -9
- package/dist/runtime/core/eval/mixins/list-dispatch.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/list-dispatch.js +0 -1
- package/dist/runtime/core/eval/mixins/literals.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/literals.js +6 -10
- package/dist/runtime/core/eval/mixins/types.d.ts +2 -1
- package/dist/runtime/core/eval/mixins/types.js +231 -261
- package/dist/runtime/core/eval/mixins/use.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/use.js +0 -1
- package/dist/runtime/core/eval/mixins/variables.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/variables.js +16 -15
- package/dist/runtime/core/eval/types.d.ts +0 -1
- package/dist/runtime/core/eval/types.js +0 -1
- package/dist/runtime/core/execute.d.ts +0 -1
- package/dist/runtime/core/execute.js +0 -1
- package/dist/runtime/core/field-descriptor.d.ts +4 -5
- package/dist/runtime/core/field-descriptor.js +2 -2
- package/dist/runtime/core/introspection.d.ts +0 -1
- package/dist/runtime/core/introspection.js +6 -7
- package/dist/runtime/core/markers.d.ts +12 -0
- package/dist/runtime/core/markers.js +7 -0
- package/dist/runtime/core/resolvers.d.ts +0 -1
- package/dist/runtime/core/resolvers.js +0 -1
- package/dist/runtime/core/signals.d.ts +0 -1
- package/dist/runtime/core/signals.js +0 -1
- package/dist/runtime/core/type-registrations.d.ts +136 -0
- package/dist/runtime/core/type-registrations.js +749 -0
- package/dist/runtime/core/type-structures.d.ts +128 -0
- package/dist/runtime/core/type-structures.js +12 -0
- package/dist/runtime/core/types.d.ts +15 -4
- package/dist/runtime/core/types.js +0 -1
- package/dist/runtime/core/values.d.ts +88 -146
- package/dist/runtime/core/values.js +466 -470
- package/dist/runtime/ext/builtins.d.ts +0 -1
- package/dist/runtime/ext/builtins.js +125 -80
- package/dist/runtime/ext/extensions.d.ts +30 -125
- package/dist/runtime/ext/extensions.js +0 -94
- package/dist/runtime/ext/test-context.d.ts +28 -0
- package/dist/runtime/ext/test-context.js +154 -0
- package/dist/runtime/index.d.ts +22 -9
- package/dist/runtime/index.js +18 -5
- package/dist/signature-parser.d.ts +2 -3
- package/dist/signature-parser.js +19 -17
- package/dist/source-location.d.ts +0 -1
- package/dist/source-location.js +0 -1
- package/dist/token-types.d.ts +0 -1
- package/dist/token-types.js +0 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.js +0 -1
- package/dist/value-types.d.ts +15 -12
- package/dist/value-types.js +0 -1
- package/package.json +2 -1
- package/dist/ast-nodes.d.ts.map +0 -1
- package/dist/ast-nodes.js.map +0 -1
- package/dist/ast-unions.d.ts.map +0 -1
- package/dist/ast-unions.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/error-classes.d.ts.map +0 -1
- package/dist/error-classes.js.map +0 -1
- package/dist/error-formatter.d.ts.map +0 -1
- package/dist/error-formatter.js.map +0 -1
- package/dist/error-registry.d.ts.map +0 -1
- package/dist/error-registry.js.map +0 -1
- package/dist/ext/crypto/index.d.ts.map +0 -1
- package/dist/ext/crypto/index.js.map +0 -1
- package/dist/ext/exec/index.d.ts.map +0 -1
- package/dist/ext/exec/index.js.map +0 -1
- package/dist/ext/exec/runner.d.ts.map +0 -1
- package/dist/ext/exec/runner.js.map +0 -1
- package/dist/ext/fetch/index.d.ts.map +0 -1
- package/dist/ext/fetch/index.js.map +0 -1
- package/dist/ext/fetch/request.d.ts.map +0 -1
- package/dist/ext/fetch/request.js.map +0 -1
- package/dist/ext/fs/index.d.ts.map +0 -1
- package/dist/ext/fs/index.js.map +0 -1
- package/dist/ext/fs/sandbox.d.ts.map +0 -1
- package/dist/ext/fs/sandbox.js.map +0 -1
- package/dist/ext/kv/index.d.ts.map +0 -1
- package/dist/ext/kv/index.js.map +0 -1
- package/dist/ext/kv/store.d.ts.map +0 -1
- package/dist/ext/kv/store.js.map +0 -1
- package/dist/generated/introspection-data.d.ts.map +0 -1
- package/dist/generated/introspection-data.js.map +0 -1
- package/dist/generated/version-data.d.ts.map +0 -1
- package/dist/generated/version-data.js.map +0 -1
- package/dist/highlight-map.d.ts.map +0 -1
- package/dist/highlight-map.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lexer/errors.d.ts.map +0 -1
- package/dist/lexer/errors.js.map +0 -1
- package/dist/lexer/helpers.d.ts.map +0 -1
- package/dist/lexer/helpers.js.map +0 -1
- package/dist/lexer/index.d.ts.map +0 -1
- package/dist/lexer/index.js.map +0 -1
- package/dist/lexer/operators.d.ts.map +0 -1
- package/dist/lexer/operators.js.map +0 -1
- package/dist/lexer/readers.d.ts.map +0 -1
- package/dist/lexer/readers.js.map +0 -1
- package/dist/lexer/state.d.ts.map +0 -1
- package/dist/lexer/state.js.map +0 -1
- package/dist/lexer/tokenizer.d.ts.map +0 -1
- package/dist/lexer/tokenizer.js.map +0 -1
- package/dist/parser/helpers.d.ts.map +0 -1
- package/dist/parser/helpers.js.map +0 -1
- package/dist/parser/index.d.ts.map +0 -1
- package/dist/parser/index.js.map +0 -1
- package/dist/parser/parser-collect.d.ts.map +0 -1
- package/dist/parser/parser-collect.js.map +0 -1
- package/dist/parser/parser-control.d.ts.map +0 -1
- package/dist/parser/parser-control.js.map +0 -1
- package/dist/parser/parser-expr.d.ts.map +0 -1
- package/dist/parser/parser-expr.js.map +0 -1
- package/dist/parser/parser-extract.d.ts.map +0 -1
- package/dist/parser/parser-extract.js.map +0 -1
- package/dist/parser/parser-functions.d.ts.map +0 -1
- package/dist/parser/parser-functions.js.map +0 -1
- package/dist/parser/parser-literals.d.ts.map +0 -1
- package/dist/parser/parser-literals.js.map +0 -1
- package/dist/parser/parser-script.d.ts.map +0 -1
- package/dist/parser/parser-script.js.map +0 -1
- package/dist/parser/parser-shape.d.ts.map +0 -1
- package/dist/parser/parser-shape.js.map +0 -1
- package/dist/parser/parser-types.d.ts.map +0 -1
- package/dist/parser/parser-types.js.map +0 -1
- package/dist/parser/parser-use.d.ts.map +0 -1
- package/dist/parser/parser-use.js.map +0 -1
- package/dist/parser/parser-variables.d.ts.map +0 -1
- package/dist/parser/parser-variables.js.map +0 -1
- package/dist/parser/parser.d.ts.map +0 -1
- package/dist/parser/parser.js.map +0 -1
- package/dist/parser/state.d.ts.map +0 -1
- package/dist/parser/state.js.map +0 -1
- package/dist/runtime/core/callable.d.ts.map +0 -1
- package/dist/runtime/core/callable.js.map +0 -1
- package/dist/runtime/core/context.d.ts.map +0 -1
- package/dist/runtime/core/context.js.map +0 -1
- package/dist/runtime/core/equals.d.ts.map +0 -1
- package/dist/runtime/core/equals.js.map +0 -1
- package/dist/runtime/core/eval/base.d.ts.map +0 -1
- package/dist/runtime/core/eval/base.js.map +0 -1
- package/dist/runtime/core/eval/evaluator.d.ts.map +0 -1
- package/dist/runtime/core/eval/evaluator.js.map +0 -1
- package/dist/runtime/core/eval/index.d.ts.map +0 -1
- package/dist/runtime/core/eval/index.js.map +0 -1
- package/dist/runtime/core/eval/mixins/annotations.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/annotations.js.map +0 -1
- package/dist/runtime/core/eval/mixins/closures.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/closures.js.map +0 -1
- package/dist/runtime/core/eval/mixins/collections.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/collections.js.map +0 -1
- package/dist/runtime/core/eval/mixins/control-flow.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/control-flow.js.map +0 -1
- package/dist/runtime/core/eval/mixins/conversion.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/conversion.js.map +0 -1
- package/dist/runtime/core/eval/mixins/core.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/core.js.map +0 -1
- package/dist/runtime/core/eval/mixins/expressions.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/expressions.js.map +0 -1
- package/dist/runtime/core/eval/mixins/extraction.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/extraction.js.map +0 -1
- package/dist/runtime/core/eval/mixins/list-dispatch.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/list-dispatch.js.map +0 -1
- package/dist/runtime/core/eval/mixins/literals.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/literals.js.map +0 -1
- package/dist/runtime/core/eval/mixins/types.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/types.js.map +0 -1
- package/dist/runtime/core/eval/mixins/use.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/use.js.map +0 -1
- package/dist/runtime/core/eval/mixins/variables.d.ts.map +0 -1
- package/dist/runtime/core/eval/mixins/variables.js.map +0 -1
- package/dist/runtime/core/eval/types.d.ts.map +0 -1
- package/dist/runtime/core/eval/types.js.map +0 -1
- package/dist/runtime/core/execute.d.ts.map +0 -1
- package/dist/runtime/core/execute.js.map +0 -1
- package/dist/runtime/core/field-descriptor.d.ts.map +0 -1
- package/dist/runtime/core/field-descriptor.js.map +0 -1
- package/dist/runtime/core/introspection.d.ts.map +0 -1
- package/dist/runtime/core/introspection.js.map +0 -1
- package/dist/runtime/core/resolvers.d.ts.map +0 -1
- package/dist/runtime/core/resolvers.js.map +0 -1
- package/dist/runtime/core/signals.d.ts.map +0 -1
- package/dist/runtime/core/signals.js.map +0 -1
- package/dist/runtime/core/types.d.ts.map +0 -1
- package/dist/runtime/core/types.js.map +0 -1
- package/dist/runtime/core/values.d.ts.map +0 -1
- package/dist/runtime/core/values.js.map +0 -1
- package/dist/runtime/ext/builtins.d.ts.map +0 -1
- package/dist/runtime/ext/builtins.js.map +0 -1
- package/dist/runtime/ext/extensions.d.ts.map +0 -1
- package/dist/runtime/ext/extensions.js.map +0 -1
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js.map +0 -1
- package/dist/signature-parser.d.ts.map +0 -1
- package/dist/signature-parser.js.map +0 -1
- package/dist/source-location.d.ts.map +0 -1
- package/dist/source-location.js.map +0 -1
- package/dist/token-types.d.ts.map +0 -1
- package/dist/token-types.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/value-types.d.ts.map +0 -1
- package/dist/value-types.js.map +0 -1
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* - evaluateTypeCheckPrimary(node) -> Promise<boolean>
|
|
13
13
|
* - evaluateTypeConstructor(node) -> Promise<RillTypeValue> [IR-7]
|
|
14
14
|
* - evaluateClosureSigLiteral(node) -> Promise<RillTypeValue> [IR-8]
|
|
15
|
+
* - resolveTypeRef(typeRef, getVariable) -> Promise<RillTypeValue> [IR-2]
|
|
16
|
+
* - buildCollectionType(name, args, resolveArg, evaluateDefault, location?) -> Promise<RillTypeValue> [IR-4]
|
|
15
17
|
*
|
|
16
18
|
* Error Handling:
|
|
17
19
|
* - Type assertion failures throw RuntimeError(RUNTIME_TYPE_ERROR) [EC-24]
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
* @internal
|
|
22
24
|
*/
|
|
23
25
|
import { RuntimeError } from '../../../../types.js';
|
|
24
|
-
import { inferType, checkType, isTypeValue,
|
|
26
|
+
import { inferType, checkType, isTypeValue, structureMatches, inferStructure, formatStructure, } from '../../values.js';
|
|
25
27
|
import { getVariable } from '../../context.js';
|
|
26
28
|
/**
|
|
27
29
|
* TypesMixin implementation.
|
|
@@ -34,6 +36,7 @@ import { getVariable } from '../../context.js';
|
|
|
34
36
|
* - EvaluatorBase: ctx, checkAborted(), getNodeLocation()
|
|
35
37
|
* - evaluatePostfixExpr() (from future CoreMixin composition)
|
|
36
38
|
* - evaluateExpression() (from CoreMixin, for type constructor arg evaluation)
|
|
39
|
+
* - evaluatePrimary() (from CoreMixin, for default value evaluation)
|
|
37
40
|
*
|
|
38
41
|
* Methods added:
|
|
39
42
|
* - assertType(value, expected, location?) -> RillValue
|
|
@@ -43,133 +46,233 @@ import { getVariable } from '../../context.js';
|
|
|
43
46
|
* - evaluateTypeCheckPrimary(node) -> Promise<boolean>
|
|
44
47
|
* - evaluateTypeConstructor(node) -> Promise<RillTypeValue>
|
|
45
48
|
* - evaluateClosureSigLiteral(node) -> Promise<RillTypeValue>
|
|
49
|
+
* - resolveTypeRef(typeRef, getVariable) -> Promise<RillTypeValue>
|
|
50
|
+
* - buildCollectionType(name, args, resolveArg, evaluateDefault, location?) -> Promise<RillTypeValue>
|
|
46
51
|
*/
|
|
47
52
|
function createTypesMixin(Base) {
|
|
48
53
|
return class TypesEvaluator extends Base {
|
|
49
54
|
/**
|
|
50
|
-
*
|
|
55
|
+
* Shared helper that partitions args, enforces validation, evaluates
|
|
56
|
+
* defaults, and constructs a RillTypeValue [IR-4].
|
|
51
57
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* Dynamic refs call getVariable, then dispatch on the result:
|
|
55
|
-
* - RillTypeValue → return as-is
|
|
56
|
-
* - Otherwise → throw RILL-R004
|
|
58
|
+
* Called by both resolveTypeRef and evaluateTypeConstructor with
|
|
59
|
+
* different resolution/evaluation strategies via callbacks.
|
|
57
60
|
*
|
|
58
|
-
*
|
|
59
|
-
* EC-
|
|
60
|
-
* EC-
|
|
61
|
-
* EC-
|
|
62
|
-
* EC-
|
|
63
|
-
* EC-
|
|
64
|
-
* EC-
|
|
61
|
+
* Error contracts:
|
|
62
|
+
* - EC-B1: Leaf type with args -> RILL-R004
|
|
63
|
+
* - EC-B2: list != 1 arg -> RILL-R004
|
|
64
|
+
* - EC-B3: Positional+named mix -> RILL-R004
|
|
65
|
+
* - EC-B4: tuple with named arg -> RILL-R004
|
|
66
|
+
* - EC-B5: Non-type arg value (delegated to resolveArg callback)
|
|
67
|
+
* - EC-B6: Default type mismatch -> RILL-R004
|
|
68
|
+
* - EC-B7: Tuple non-trailing default -> RILL-R004
|
|
65
69
|
*/
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return Object.freeze({
|
|
72
|
-
__rill_type: true,
|
|
73
|
-
typeName,
|
|
74
|
-
structure: { type: typeName },
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
// EC-3: Leaf types reject all type arguments
|
|
78
|
-
const LEAF_TYPES = new Set([
|
|
79
|
-
'string',
|
|
80
|
-
'number',
|
|
81
|
-
'bool',
|
|
82
|
-
'vector',
|
|
83
|
-
'type',
|
|
84
|
-
'any',
|
|
85
|
-
'closure',
|
|
86
|
-
]);
|
|
87
|
-
if (LEAF_TYPES.has(typeName)) {
|
|
88
|
-
throw new RuntimeError('RILL-R004', `${typeName} does not accept type arguments`);
|
|
70
|
+
async buildCollectionType(name, args, resolveArg, evaluateDefault, location) {
|
|
71
|
+
if (name === 'list') {
|
|
72
|
+
// EC-B2: list requires exactly 1 positional arg
|
|
73
|
+
if (args.length !== 1 || args[0].name !== undefined) {
|
|
74
|
+
throw new RuntimeError('RILL-R004', 'list() requires exactly 1 type argument', location);
|
|
89
75
|
}
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
};
|
|
104
|
-
return Object.freeze({
|
|
105
|
-
__rill_type: true,
|
|
106
|
-
typeName,
|
|
107
|
-
structure,
|
|
108
|
-
});
|
|
76
|
+
const element = await resolveArg(args[0]);
|
|
77
|
+
const structure = { kind: 'list', element };
|
|
78
|
+
return Object.freeze({
|
|
79
|
+
__rill_type: true,
|
|
80
|
+
typeName: name,
|
|
81
|
+
structure,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (name === 'dict' || name === 'ordered') {
|
|
85
|
+
const positional = args.filter((a) => a.name === undefined);
|
|
86
|
+
const named = args.filter((a) => a.name !== undefined);
|
|
87
|
+
// EC-B3: Cannot mix positional and named arguments
|
|
88
|
+
if (positional.length > 0 && named.length > 0) {
|
|
89
|
+
throw new RuntimeError('RILL-R004', `${name}() cannot mix positional and named arguments`, location);
|
|
109
90
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
91
|
+
// Uniform path: exactly 1 positional, 0 named -> valueType
|
|
92
|
+
if (positional.length === 1 && named.length === 0) {
|
|
93
|
+
const valueType = await resolveArg(positional[0]);
|
|
94
|
+
// EC-B6: Default type mismatch on uniform single-arg path
|
|
95
|
+
if (positional[0].defaultValue !== undefined) {
|
|
96
|
+
const defaultVal = await evaluateDefault(positional[0].defaultValue);
|
|
97
|
+
if (!structureMatches(defaultVal, valueType)) {
|
|
98
|
+
throw new RuntimeError('RILL-R004', `Default value for ${name} element must be ${formatStructure(valueType)}, got ${inferType(defaultVal)}`, location);
|
|
115
99
|
}
|
|
116
100
|
}
|
|
117
|
-
const
|
|
118
|
-
for (const arg of args) {
|
|
119
|
-
fields[arg.name] = resolveArg(arg);
|
|
120
|
-
}
|
|
121
|
-
const structure = { type: 'dict', fields };
|
|
101
|
+
const structure = { kind: name, valueType };
|
|
122
102
|
return Object.freeze({
|
|
123
103
|
__rill_type: true,
|
|
124
|
-
typeName,
|
|
104
|
+
typeName: name,
|
|
125
105
|
structure,
|
|
126
106
|
});
|
|
127
107
|
}
|
|
128
|
-
|
|
129
|
-
|
|
108
|
+
// EC: dict/ordered with 2+ positional args
|
|
109
|
+
if (positional.length >= 2) {
|
|
110
|
+
throw new RuntimeError('RILL-R004', `${name}() requires exactly 1 positional type argument`, location);
|
|
111
|
+
}
|
|
112
|
+
// Structural path: named args only -> fields
|
|
113
|
+
if (name === 'dict') {
|
|
114
|
+
const fields = {};
|
|
130
115
|
for (const arg of args) {
|
|
131
|
-
|
|
132
|
-
|
|
116
|
+
const resolvedType = await resolveArg(arg);
|
|
117
|
+
const fieldDef = { type: resolvedType };
|
|
118
|
+
if (arg.defaultValue !== undefined) {
|
|
119
|
+
const defaultVal = await evaluateDefault(arg.defaultValue);
|
|
120
|
+
// EC-B6: Default type mismatch
|
|
121
|
+
if (!structureMatches(defaultVal, resolvedType)) {
|
|
122
|
+
throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
|
|
123
|
+
}
|
|
124
|
+
fieldDef.defaultValue = defaultVal;
|
|
133
125
|
}
|
|
126
|
+
fields[arg.name] = fieldDef;
|
|
134
127
|
}
|
|
135
|
-
const
|
|
136
|
-
const structure = { type: 'tuple', elements };
|
|
128
|
+
const structure = { kind: 'dict', fields };
|
|
137
129
|
return Object.freeze({
|
|
138
130
|
__rill_type: true,
|
|
139
|
-
typeName,
|
|
131
|
+
typeName: name,
|
|
140
132
|
structure,
|
|
141
133
|
});
|
|
142
134
|
}
|
|
143
|
-
//
|
|
144
|
-
|
|
135
|
+
// name === 'ordered': structural path -> fields array with name
|
|
136
|
+
const orderedFields = [];
|
|
145
137
|
for (const arg of args) {
|
|
146
|
-
|
|
147
|
-
|
|
138
|
+
const resolvedType = await resolveArg(arg);
|
|
139
|
+
const fieldDef = {
|
|
140
|
+
name: arg.name,
|
|
141
|
+
type: resolvedType,
|
|
142
|
+
};
|
|
143
|
+
if (arg.defaultValue !== undefined) {
|
|
144
|
+
const defaultVal = await evaluateDefault(arg.defaultValue);
|
|
145
|
+
// EC-B6: Default type mismatch
|
|
146
|
+
if (!structureMatches(defaultVal, resolvedType)) {
|
|
147
|
+
throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
|
|
148
|
+
}
|
|
149
|
+
fieldDef.defaultValue = defaultVal;
|
|
148
150
|
}
|
|
151
|
+
orderedFields.push(fieldDef);
|
|
149
152
|
}
|
|
150
|
-
const orderedFields = args.map((arg) => [arg.name, resolveArg(arg)]);
|
|
151
153
|
const structure = {
|
|
152
|
-
|
|
154
|
+
kind: 'ordered',
|
|
153
155
|
fields: orderedFields,
|
|
154
156
|
};
|
|
155
157
|
return Object.freeze({
|
|
156
158
|
__rill_type: true,
|
|
157
|
-
typeName,
|
|
159
|
+
typeName: name,
|
|
160
|
+
structure,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// name === 'tuple'
|
|
164
|
+
// EC-B4: tuple requires positional args only
|
|
165
|
+
for (const arg of args) {
|
|
166
|
+
if (arg.name !== undefined) {
|
|
167
|
+
throw new RuntimeError('RILL-R004', 'tuple() requires positional arguments', location);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Uniform path: exactly 1 positional -> valueType
|
|
171
|
+
if (args.length === 1 && args[0].name === undefined) {
|
|
172
|
+
const valueType = await resolveArg(args[0]);
|
|
173
|
+
// EC-B6: Default type mismatch on uniform single-arg path
|
|
174
|
+
if (args[0].defaultValue !== undefined) {
|
|
175
|
+
const defaultVal = await evaluateDefault(args[0].defaultValue);
|
|
176
|
+
if (!structureMatches(defaultVal, valueType)) {
|
|
177
|
+
throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${formatStructure(valueType)}, got ${inferType(defaultVal)}`, location);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const structure = { kind: 'tuple', valueType };
|
|
181
|
+
return Object.freeze({
|
|
182
|
+
__rill_type: true,
|
|
183
|
+
typeName: 'tuple',
|
|
158
184
|
structure,
|
|
159
185
|
});
|
|
160
186
|
}
|
|
161
|
-
//
|
|
162
|
-
|
|
187
|
+
// Structural path: 2+ positional -> elements
|
|
188
|
+
const elements = [];
|
|
189
|
+
for (const arg of args) {
|
|
190
|
+
const resolvedType = await resolveArg(arg);
|
|
191
|
+
const fieldDef = { type: resolvedType };
|
|
192
|
+
if (arg.defaultValue !== undefined) {
|
|
193
|
+
const defaultVal = await evaluateDefault(arg.defaultValue);
|
|
194
|
+
// EC-B6: Default type mismatch
|
|
195
|
+
if (!structureMatches(defaultVal, resolvedType)) {
|
|
196
|
+
throw new RuntimeError('RILL-R004', `Default value for tuple element must be ${formatStructure(resolvedType)}, got ${inferType(defaultVal)}`, location);
|
|
197
|
+
}
|
|
198
|
+
fieldDef.defaultValue = defaultVal;
|
|
199
|
+
}
|
|
200
|
+
elements.push(fieldDef);
|
|
201
|
+
}
|
|
202
|
+
// EC-B7: Tuple non-trailing default — no element without a default
|
|
203
|
+
// may follow an element that has one.
|
|
204
|
+
let sawDefault = false;
|
|
205
|
+
for (let i = 0; i < elements.length; i++) {
|
|
206
|
+
const hasDefault = elements[i].defaultValue !== undefined;
|
|
207
|
+
if (hasDefault) {
|
|
208
|
+
sawDefault = true;
|
|
209
|
+
}
|
|
210
|
+
else if (sawDefault) {
|
|
211
|
+
throw new RuntimeError('RILL-R004', `tuple() default values must be trailing: element at position ${i} has no default but a preceding element does`, location);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const structure = { kind: 'tuple', elements };
|
|
215
|
+
return Object.freeze({
|
|
216
|
+
__rill_type: true,
|
|
217
|
+
typeName: 'tuple',
|
|
218
|
+
structure,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Resolve a TypeRef to a RillTypeValue [IR-2].
|
|
223
|
+
*
|
|
224
|
+
* Static refs with no args return a frozen RillTypeValue directly.
|
|
225
|
+
* Static refs with args delegate to buildCollectionType.
|
|
226
|
+
* Dynamic refs call getVariable, then dispatch on the result:
|
|
227
|
+
* - RillTypeValue -> return as-is
|
|
228
|
+
* - Otherwise -> throw RILL-R004
|
|
229
|
+
*
|
|
230
|
+
* EC-3: Variable not found -> RILL-R005.
|
|
231
|
+
* EC-4: Non-type variable value -> RILL-R004.
|
|
232
|
+
* EC-5: list with != 1 positional arg -> RILL-R004.
|
|
233
|
+
* EC-6: dict/ordered positional+named mix -> RILL-R004.
|
|
234
|
+
* EC-7: tuple with named arg -> RILL-R004.
|
|
235
|
+
* EC-8: Default type mismatch -> RILL-R004.
|
|
236
|
+
* EC-9: Default evaluation failure -> propagated.
|
|
237
|
+
* EC-10: Tuple non-trailing default -> RILL-R004.
|
|
238
|
+
*/
|
|
239
|
+
async resolveTypeRef(typeRef, getVariableFn) {
|
|
240
|
+
if (typeRef.kind === 'static') {
|
|
241
|
+
const { typeName, args } = typeRef;
|
|
242
|
+
// No args: existing bare-type behavior
|
|
243
|
+
if (!args || args.length === 0) {
|
|
244
|
+
return Object.freeze({
|
|
245
|
+
__rill_type: true,
|
|
246
|
+
typeName,
|
|
247
|
+
structure: { kind: typeName },
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
// EC-B1: Leaf types reject all type arguments (AC-4: derived from registrations)
|
|
251
|
+
if (this.ctx.leafTypes.has(typeName)) {
|
|
252
|
+
throw new RuntimeError('RILL-R004', `${typeName} does not accept type arguments`);
|
|
253
|
+
}
|
|
254
|
+
// Delegate to buildCollectionType with recursive resolveTypeRef
|
|
255
|
+
return this.buildCollectionType(typeName, args, async (arg) => {
|
|
256
|
+
const resolved = await this.resolveTypeRef(arg.value, getVariableFn);
|
|
257
|
+
return resolved.structure;
|
|
258
|
+
}, async (node) => {
|
|
259
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
260
|
+
return this.evaluatePrimary(node);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
// Union type ref: (A | B) -- resolve each member recursively and
|
|
264
|
+
// return a RillTypeValue with structure: { kind: 'union', members: [...] }.
|
|
163
265
|
// typeName is set to a display string for error messages; the structure
|
|
164
266
|
// field carries the authoritative type shape for validation (DR-1).
|
|
165
267
|
if (typeRef.kind === 'union') {
|
|
166
|
-
const members =
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
268
|
+
const members = [];
|
|
269
|
+
for (const member of typeRef.members) {
|
|
270
|
+
const resolved = await this.resolveTypeRef(member, getVariableFn);
|
|
271
|
+
members.push(resolved.structure);
|
|
272
|
+
}
|
|
273
|
+
const structure = { kind: 'union', members };
|
|
171
274
|
const displayName = members
|
|
172
|
-
.map(
|
|
275
|
+
.map(formatStructure)
|
|
173
276
|
.join('|');
|
|
174
277
|
return Object.freeze({
|
|
175
278
|
__rill_type: true,
|
|
@@ -177,7 +280,7 @@ function createTypesMixin(Base) {
|
|
|
177
280
|
structure,
|
|
178
281
|
});
|
|
179
282
|
}
|
|
180
|
-
const result =
|
|
283
|
+
const result = getVariableFn(typeRef.varName);
|
|
181
284
|
if (result === undefined) {
|
|
182
285
|
throw new RuntimeError('RILL-R005', `Variable $${typeRef.varName} is not defined`);
|
|
183
286
|
}
|
|
@@ -188,28 +291,29 @@ function createTypesMixin(Base) {
|
|
|
188
291
|
/**
|
|
189
292
|
* Assert that a value is of the expected type.
|
|
190
293
|
* Returns the value unchanged if assertion passes, throws on mismatch.
|
|
191
|
-
* Accepts a bare RillTypeName or a full
|
|
192
|
-
* When expected is a
|
|
193
|
-
* dispatches to
|
|
294
|
+
* Accepts a bare RillTypeName or a full TypeStructure.
|
|
295
|
+
* When expected is a TypeStructure with sub-fields (element, fields, elements),
|
|
296
|
+
* dispatches to structureMatches for deep validation.
|
|
194
297
|
* Exported for use by type assertion evaluation.
|
|
195
298
|
*/
|
|
196
299
|
assertType(value, expected, location) {
|
|
197
|
-
// Structural path: expected is a
|
|
300
|
+
// Structural path: expected is a TypeStructure object
|
|
198
301
|
if (typeof expected !== 'string') {
|
|
199
302
|
const hasSubFields = 'element' in expected ||
|
|
200
303
|
'fields' in expected ||
|
|
201
304
|
'elements' in expected ||
|
|
202
|
-
'members' in expected
|
|
305
|
+
'members' in expected ||
|
|
306
|
+
'valueType' in expected;
|
|
203
307
|
if (hasSubFields) {
|
|
204
|
-
if (!
|
|
205
|
-
const expectedStr =
|
|
206
|
-
const actualStr =
|
|
308
|
+
if (!structureMatches(value, expected)) {
|
|
309
|
+
const expectedStr = formatStructure(expected);
|
|
310
|
+
const actualStr = formatStructure(inferStructure(value));
|
|
207
311
|
throw new RuntimeError('RILL-R004', `Type assertion failed: expected ${expectedStr}, got ${actualStr}`, location, { expectedType: expectedStr, actualType: actualStr });
|
|
208
312
|
}
|
|
209
313
|
return value;
|
|
210
314
|
}
|
|
211
315
|
// Bare structural type (no sub-fields): fall through using type name
|
|
212
|
-
expected = expected.
|
|
316
|
+
expected = expected.kind;
|
|
213
317
|
}
|
|
214
318
|
// Bare type name path
|
|
215
319
|
if (expected === 'any')
|
|
@@ -231,7 +335,7 @@ function createTypesMixin(Base) {
|
|
|
231
335
|
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
232
336
|
await this.evaluatePostfixExpr(node.operand)
|
|
233
337
|
: input;
|
|
234
|
-
const resolved = this.resolveTypeRef(node.typeRef, (name) => getVariable(this.ctx, name));
|
|
338
|
+
const resolved = await this.resolveTypeRef(node.typeRef, (name) => getVariable(this.ctx, name));
|
|
235
339
|
return this.assertType(value, resolved.structure, node.span.start);
|
|
236
340
|
}
|
|
237
341
|
/**
|
|
@@ -245,13 +349,14 @@ function createTypesMixin(Base) {
|
|
|
245
349
|
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
246
350
|
await this.evaluatePostfixExpr(node.operand)
|
|
247
351
|
: input;
|
|
248
|
-
const resolved = this.resolveTypeRef(node.typeRef, (name) => getVariable(this.ctx, name));
|
|
352
|
+
const resolved = await this.resolveTypeRef(node.typeRef, (name) => getVariable(this.ctx, name));
|
|
249
353
|
const hasSubFields = 'element' in resolved.structure ||
|
|
250
354
|
'fields' in resolved.structure ||
|
|
251
355
|
'elements' in resolved.structure ||
|
|
252
|
-
'members' in resolved.structure
|
|
356
|
+
'members' in resolved.structure ||
|
|
357
|
+
'valueType' in resolved.structure;
|
|
253
358
|
if (hasSubFields) {
|
|
254
|
-
return
|
|
359
|
+
return structureMatches(value, resolved.structure);
|
|
255
360
|
}
|
|
256
361
|
return checkType(value, resolved.typeName);
|
|
257
362
|
}
|
|
@@ -282,166 +387,32 @@ function createTypesMixin(Base) {
|
|
|
282
387
|
/**
|
|
283
388
|
* Evaluate a type constructor node into a RillTypeValue [IR-7].
|
|
284
389
|
*
|
|
285
|
-
* Handles list(T), dict(
|
|
286
|
-
*
|
|
390
|
+
* Handles list(T), dict(...), tuple(...), ordered(...).
|
|
391
|
+
* Delegates to buildCollectionType with evaluateTypeConstructor-specific
|
|
392
|
+
* resolution strategy (resolves TypeRef via resolveTypeRef, evaluates
|
|
393
|
+
* defaults via evaluatePrimary).
|
|
287
394
|
*
|
|
288
|
-
* Error contracts
|
|
289
|
-
* - EC-4: list() with != 1 arg -> RILL-R004
|
|
290
|
-
* - EC-5: non-type argument -> RILL-R004
|
|
291
|
-
* - EC-6: positional arg in dict/ordered -> RILL-R004
|
|
292
|
-
* - EC-7: named arg in tuple -> RILL-R004
|
|
395
|
+
* Error contracts delegated to buildCollectionType.
|
|
293
396
|
*/
|
|
294
397
|
async evaluateTypeConstructor(node) {
|
|
295
398
|
const name = node.constructorName;
|
|
296
399
|
const location = node.span.start;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
? { type: argValue.typeName }
|
|
305
|
-
: argValue.structure;
|
|
306
|
-
};
|
|
307
|
-
if (name === 'list') {
|
|
308
|
-
// EC-4: list() requires exactly 1 argument
|
|
309
|
-
if (node.args.length !== 1) {
|
|
310
|
-
throw new RuntimeError('RILL-R004', 'list() requires exactly 1 type argument', location);
|
|
311
|
-
}
|
|
312
|
-
const arg = node.args[0];
|
|
400
|
+
return this.buildCollectionType(name, node.args, async (arg) => {
|
|
401
|
+
const resolved = await this.resolveTypeRef(arg.value, (varName) => getVariable(this.ctx, varName));
|
|
402
|
+
return resolved.structure.kind === 'any' &&
|
|
403
|
+
resolved.typeName !== 'any'
|
|
404
|
+
? { kind: resolved.typeName }
|
|
405
|
+
: resolved.structure;
|
|
406
|
+
}, async (node) => {
|
|
313
407
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const structure = {
|
|
317
|
-
type: 'list',
|
|
318
|
-
element: elementType,
|
|
319
|
-
};
|
|
320
|
-
return Object.freeze({
|
|
321
|
-
__rill_type: true,
|
|
322
|
-
typeName: 'list',
|
|
323
|
-
structure,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
if (name === 'dict') {
|
|
327
|
-
// EC-6: dict() requires named arguments
|
|
328
|
-
for (const arg of node.args) {
|
|
329
|
-
if (arg.kind === 'positional') {
|
|
330
|
-
throw new RuntimeError('RILL-R004', 'dict() requires named arguments (field: type)', location);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
const fields = {};
|
|
334
|
-
for (const arg of node.args) {
|
|
335
|
-
if (arg.kind === 'named') {
|
|
336
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
337
|
-
const argVal = await this.evaluateExpression(arg.value);
|
|
338
|
-
const resolvedType = await resolveArgAsType(argVal);
|
|
339
|
-
if (arg.defaultValue !== undefined) {
|
|
340
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
341
|
-
const defaultVal = await this.evaluatePrimary(arg.defaultValue);
|
|
342
|
-
if (!structuralTypeMatches(defaultVal, resolvedType)) {
|
|
343
|
-
throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructuralType(resolvedType)}, got ${inferType(defaultVal)}`, location);
|
|
344
|
-
}
|
|
345
|
-
fields[arg.name] = {
|
|
346
|
-
type: resolvedType,
|
|
347
|
-
defaultValue: defaultVal,
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
fields[arg.name] = resolvedType;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
const structure = { type: 'dict', fields };
|
|
356
|
-
return Object.freeze({
|
|
357
|
-
__rill_type: true,
|
|
358
|
-
typeName: 'dict',
|
|
359
|
-
structure,
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
if (name === 'tuple') {
|
|
363
|
-
// EC-7: tuple() requires positional arguments
|
|
364
|
-
for (const arg of node.args) {
|
|
365
|
-
if (arg.kind === 'named') {
|
|
366
|
-
throw new RuntimeError('RILL-R004', 'tuple() requires positional arguments', location);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
const elements = [];
|
|
370
|
-
for (const arg of node.args) {
|
|
371
|
-
if (arg.kind === 'positional') {
|
|
372
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
373
|
-
const argVal = await this.evaluateExpression(arg.value);
|
|
374
|
-
const resolvedType = await resolveArgAsType(argVal);
|
|
375
|
-
if (arg.defaultValue !== undefined) {
|
|
376
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
377
|
-
const defaultVal = await this.evaluatePrimary(arg.defaultValue);
|
|
378
|
-
elements.push([resolvedType, defaultVal]);
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
elements.push([resolvedType]);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
// EC-3: defaults must be trailing-only — no element without a default
|
|
386
|
-
// may follow an element that has one.
|
|
387
|
-
let sawDefault = false;
|
|
388
|
-
for (let i = 0; i < elements.length; i++) {
|
|
389
|
-
const hasDefault = elements[i].length === 2;
|
|
390
|
-
if (hasDefault) {
|
|
391
|
-
sawDefault = true;
|
|
392
|
-
}
|
|
393
|
-
else if (sawDefault) {
|
|
394
|
-
throw new RuntimeError('RILL-P003', `tuple() default values must be trailing: element at position ${i} has no default but a preceding element does`, location);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
const structure = { type: 'tuple', elements };
|
|
398
|
-
return Object.freeze({
|
|
399
|
-
__rill_type: true,
|
|
400
|
-
typeName: 'tuple',
|
|
401
|
-
structure,
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
// name === 'ordered'
|
|
405
|
-
// EC-6: ordered() requires named arguments
|
|
406
|
-
for (const arg of node.args) {
|
|
407
|
-
if (arg.kind === 'positional') {
|
|
408
|
-
throw new RuntimeError('RILL-R004', 'ordered() requires named arguments (field: type)', location);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
const orderedFields = [];
|
|
412
|
-
for (const arg of node.args) {
|
|
413
|
-
if (arg.kind === 'named') {
|
|
414
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
415
|
-
const argVal = await this.evaluateExpression(arg.value);
|
|
416
|
-
const resolvedType = await resolveArgAsType(argVal);
|
|
417
|
-
if (arg.defaultValue !== undefined) {
|
|
418
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
419
|
-
const defaultVal = await this.evaluatePrimary(arg.defaultValue);
|
|
420
|
-
if (!structuralTypeMatches(defaultVal, resolvedType)) {
|
|
421
|
-
throw new RuntimeError('RILL-R004', `Default value for field '${arg.name}' must be ${formatStructuralType(resolvedType)}, got ${inferType(defaultVal)}`, location);
|
|
422
|
-
}
|
|
423
|
-
orderedFields.push([arg.name, resolvedType, defaultVal]);
|
|
424
|
-
}
|
|
425
|
-
else {
|
|
426
|
-
orderedFields.push([arg.name, resolvedType]);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
const structure = {
|
|
431
|
-
type: 'ordered',
|
|
432
|
-
fields: orderedFields,
|
|
433
|
-
};
|
|
434
|
-
return Object.freeze({
|
|
435
|
-
__rill_type: true,
|
|
436
|
-
typeName: 'ordered',
|
|
437
|
-
structure,
|
|
438
|
-
});
|
|
408
|
+
return this.evaluatePrimary(node);
|
|
409
|
+
}, location);
|
|
439
410
|
}
|
|
440
411
|
/**
|
|
441
412
|
* Evaluate a closure signature literal into a RillTypeValue [IR-8].
|
|
442
413
|
*
|
|
443
414
|
* Creates a closure type value from |param: T, ...|: R syntax.
|
|
444
|
-
* Each parameter produces a [name,
|
|
415
|
+
* Each parameter produces a [name, TypeStructure] entry.
|
|
445
416
|
*
|
|
446
417
|
* Error contracts:
|
|
447
418
|
* - EC-8: missing return type -> RILL-R004 (enforced at parse time; node always has returnType)
|
|
@@ -449,14 +420,14 @@ function createTypesMixin(Base) {
|
|
|
449
420
|
*/
|
|
450
421
|
async evaluateClosureSigLiteral(node) {
|
|
451
422
|
const location = node.span.start;
|
|
452
|
-
// Helper: evaluate a type expression and extract
|
|
423
|
+
// Helper: evaluate a type expression and extract TypeStructure
|
|
453
424
|
const resolveTypeExpr = async (argVal) => {
|
|
454
425
|
if (!isTypeValue(argVal)) {
|
|
455
426
|
throw new RuntimeError('RILL-R004', `Parameter type must be a type value, got ${inferType(argVal)}`, location);
|
|
456
427
|
}
|
|
457
|
-
return argVal.structure.
|
|
428
|
+
return argVal.structure.kind === 'any' &&
|
|
458
429
|
argVal.typeName !== 'any'
|
|
459
|
-
? {
|
|
430
|
+
? { kind: argVal.typeName }
|
|
460
431
|
: argVal.structure;
|
|
461
432
|
};
|
|
462
433
|
// Evaluate parameter types
|
|
@@ -465,9 +436,9 @@ function createTypesMixin(Base) {
|
|
|
465
436
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
466
437
|
const paramVal = await this.evaluateExpression(param.typeExpr);
|
|
467
438
|
const paramType = await resolveTypeExpr(paramVal);
|
|
468
|
-
params.push(
|
|
439
|
+
params.push({ name: param.name, type: paramType });
|
|
469
440
|
}
|
|
470
|
-
// Evaluate return type (EC-8: required
|
|
441
|
+
// Evaluate return type (EC-8: required -- parser enforces this at parse time)
|
|
471
442
|
// returnType is PostfixExprNode (stops before pipe operators) so the
|
|
472
443
|
// return type annotation cannot accidentally consume a trailing pipe chain.
|
|
473
444
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -475,11 +446,11 @@ function createTypesMixin(Base) {
|
|
|
475
446
|
if (!isTypeValue(retVal)) {
|
|
476
447
|
throw new RuntimeError('RILL-R004', `Closure type literal requires return type after |, got ${inferType(retVal)}`, location);
|
|
477
448
|
}
|
|
478
|
-
const ret = retVal.structure.
|
|
449
|
+
const ret = retVal.structure.kind === 'any' &&
|
|
479
450
|
retVal.typeName !== 'any'
|
|
480
|
-
? {
|
|
451
|
+
? { kind: retVal.typeName }
|
|
481
452
|
: retVal.structure;
|
|
482
|
-
const structure = {
|
|
453
|
+
const structure = { kind: 'closure', params, ret };
|
|
483
454
|
return Object.freeze({
|
|
484
455
|
__rill_type: true,
|
|
485
456
|
typeName: 'closure',
|
|
@@ -492,4 +463,3 @@ function createTypesMixin(Base) {
|
|
|
492
463
|
// TypeScript can't generate declarations for functions returning classes with protected members
|
|
493
464
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
494
465
|
export const TypesMixin = createTypesMixin;
|
|
495
|
-
//# sourceMappingURL=types.js.map
|