@rcrsr/rill 0.15.0 → 0.16.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 +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 +0 -1
- package/dist/ext/crypto/index.js +5 -6
- package/dist/ext/exec/index.d.ts +0 -1
- package/dist/ext/exec/index.js +3 -4
- package/dist/ext/exec/runner.d.ts +0 -1
- package/dist/ext/exec/runner.js +0 -1
- package/dist/ext/fetch/index.d.ts +0 -1
- package/dist/ext/fetch/index.js +8 -39
- package/dist/ext/fetch/request.d.ts +0 -1
- package/dist/ext/fetch/request.js +0 -1
- package/dist/ext/fs/index.d.ts +0 -1
- package/dist/ext/fs/index.js +26 -27
- package/dist/ext/fs/sandbox.d.ts +0 -1
- package/dist/ext/fs/sandbox.js +0 -1
- package/dist/ext/kv/index.d.ts +0 -1
- package/dist/ext/kv/index.js +19 -20
- package/dist/ext/kv/store.d.ts +0 -1
- package/dist/ext/kv/store.js +0 -1
- package/dist/generated/introspection-data.d.ts +0 -1
- package/dist/generated/introspection-data.js +0 -1
- 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 +1 -2
- package/dist/index.js +1 -2
- 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 +64 -13
- package/dist/parser/parser-use.d.ts +0 -1
- package/dist/parser/parser-use.js +0 -1
- 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 +40 -13
- package/dist/runtime/core/callable.js +137 -28
- package/dist/runtime/core/context.d.ts +0 -1
- package/dist/runtime/core/context.js +1 -2
- 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 +0 -1
- package/dist/runtime/core/eval/index.js +0 -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 +82 -60
- 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 +153 -86
- package/dist/runtime/core/eval/mixins/core.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/core.js +0 -1
- package/dist/runtime/core/eval/mixins/expressions.d.ts +0 -1
- package/dist/runtime/core/eval/mixins/expressions.js +0 -1
- 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 +3 -7
- package/dist/runtime/core/eval/mixins/types.d.ts +2 -1
- package/dist/runtime/core/eval/mixins/types.js +222 -242
- 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 +6 -7
- 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 +2 -3
- package/dist/runtime/core/field-descriptor.js +0 -1
- package/dist/runtime/core/introspection.d.ts +0 -1
- package/dist/runtime/core/introspection.js +0 -1
- 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/types.d.ts +0 -1
- package/dist/runtime/core/types.js +0 -1
- package/dist/runtime/core/values.d.ts +59 -26
- package/dist/runtime/core/values.js +289 -77
- package/dist/runtime/ext/builtins.d.ts +0 -1
- package/dist/runtime/ext/builtins.js +43 -17
- package/dist/runtime/ext/extensions.d.ts +0 -1
- package/dist/runtime/ext/extensions.js +0 -1
- package/dist/runtime/index.d.ts +2 -3
- package/dist/runtime/index.js +1 -2
- package/dist/signature-parser.d.ts +0 -1
- package/dist/signature-parser.js +8 -6
- 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
|
@@ -7,15 +7,6 @@
|
|
|
7
7
|
import { RuntimeError } from '../../types.js';
|
|
8
8
|
import { VALID_TYPE_NAMES } from '../../constants.js';
|
|
9
9
|
import { callableEquals, isCallable, isDict, isScriptCallable, } from './callable.js';
|
|
10
|
-
/**
|
|
11
|
-
* Type guard to distinguish the `{ type, defaultValue }` form of RillFieldType
|
|
12
|
-
* from a plain RillType.
|
|
13
|
-
*/
|
|
14
|
-
export function isFieldTypeWithDefault(fieldType) {
|
|
15
|
-
return (typeof fieldType === 'object' &&
|
|
16
|
-
fieldType !== null &&
|
|
17
|
-
'defaultValue' in fieldType);
|
|
18
|
-
}
|
|
19
10
|
/** Type guard for RillTuple (spread args) */
|
|
20
11
|
export function isTuple(value) {
|
|
21
12
|
return (typeof value === 'object' &&
|
|
@@ -44,7 +35,11 @@ export function isTypeValue(value) {
|
|
|
44
35
|
'__rill_type' in value &&
|
|
45
36
|
value.__rill_type === true);
|
|
46
37
|
}
|
|
47
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Create ordered from entries array (named, preserves insertion order).
|
|
40
|
+
* Entries may be 2-element [name, value] or 3-element [name, value, default]
|
|
41
|
+
* tuples; the third element carries a default value for `.^input` reflection.
|
|
42
|
+
*/
|
|
48
43
|
export function createOrdered(entries) {
|
|
49
44
|
return Object.freeze({ __rill_ordered: true, entries: [...entries] });
|
|
50
45
|
}
|
|
@@ -102,15 +97,112 @@ export function inferElementType(elements) {
|
|
|
102
97
|
if (elements.length === 0)
|
|
103
98
|
return { type: 'any' };
|
|
104
99
|
const firstElem = elements[0];
|
|
105
|
-
|
|
100
|
+
let accType = inferStructuralType(firstElem);
|
|
106
101
|
for (let i = 1; i < elements.length; i++) {
|
|
107
102
|
const elem = elements[i];
|
|
108
103
|
const elemType = inferStructuralType(elem);
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
const merged = commonType(accType, elemType);
|
|
105
|
+
if (merged === null) {
|
|
106
|
+
throw new RuntimeError('RILL-R002', `List elements must be the same type: expected ${formatStructuralType(accType)}, got ${formatStructuralType(elemType)} at index ${i}`);
|
|
107
|
+
}
|
|
108
|
+
accType = merged;
|
|
109
|
+
}
|
|
110
|
+
return accType;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Merge uniform value types from two sides of the same compound type.
|
|
114
|
+
* Sub-case A: both carry valueType -> recurse commonType.
|
|
115
|
+
* Sub-case B: both carry structural fields -> extract value types, merge all.
|
|
116
|
+
* Returns the merged RillType on success, undefined when no uniform merge applies.
|
|
117
|
+
*/
|
|
118
|
+
function mergeUniformValueType(aValue, bValue, aFields, bFields) {
|
|
119
|
+
// Sub-case A: both carry valueType
|
|
120
|
+
if (aValue !== undefined && bValue !== undefined) {
|
|
121
|
+
const merged = commonType(aValue, bValue);
|
|
122
|
+
if (merged !== null)
|
|
123
|
+
return merged;
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
// Sub-case B: both carry structural fields
|
|
127
|
+
if (aFields !== undefined && bFields !== undefined) {
|
|
128
|
+
const allTypes = [
|
|
129
|
+
...aFields.map((f) => f.type),
|
|
130
|
+
...bFields.map((f) => f.type),
|
|
131
|
+
];
|
|
132
|
+
if (allTypes.length === 0)
|
|
133
|
+
return undefined;
|
|
134
|
+
let merged = allTypes[0];
|
|
135
|
+
for (let i = 1; i < allTypes.length; i++) {
|
|
136
|
+
const next = commonType(merged, allTypes[i]);
|
|
137
|
+
if (next === null)
|
|
138
|
+
return undefined;
|
|
139
|
+
merged = next;
|
|
140
|
+
}
|
|
141
|
+
return merged;
|
|
142
|
+
}
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Return the most specific shared type for two RillType values.
|
|
147
|
+
* Returns null when types are incompatible at the top level.
|
|
148
|
+
*
|
|
149
|
+
* Cascade priority:
|
|
150
|
+
* 1. Any-narrowing: if either side is `any`, return the other
|
|
151
|
+
* 2. Structural match: delegate to structuralTypeEquals; on true, return a
|
|
152
|
+
* 3. Recursive list: merge inner element types
|
|
153
|
+
* 3b. Uniform valueType: merge dict/tuple/ordered value types
|
|
154
|
+
* 4. Bare type fallback: same compound type but structural mismatch
|
|
155
|
+
* 5. Incompatible: different top-level types return null
|
|
156
|
+
*/
|
|
157
|
+
export function commonType(a, b) {
|
|
158
|
+
// 1. Any-narrowing
|
|
159
|
+
if (a.type === 'any')
|
|
160
|
+
return b;
|
|
161
|
+
if (b.type === 'any')
|
|
162
|
+
return a;
|
|
163
|
+
// 5. Incompatible top-level types (checked early to short-circuit)
|
|
164
|
+
if (a.type !== b.type)
|
|
165
|
+
return null;
|
|
166
|
+
// 2. Structural match
|
|
167
|
+
if (structuralTypeEquals(a, b))
|
|
168
|
+
return a;
|
|
169
|
+
// 3. Recursive list element merging
|
|
170
|
+
if (a.type === 'list' && b.type === 'list') {
|
|
171
|
+
if (a.element !== undefined && b.element !== undefined) {
|
|
172
|
+
const inner = commonType(a.element, b.element);
|
|
173
|
+
if (inner !== null)
|
|
174
|
+
return { type: 'list', element: inner };
|
|
111
175
|
}
|
|
176
|
+
return { type: 'list' };
|
|
177
|
+
}
|
|
178
|
+
// 3b. Uniform valueType merging for dict/tuple/ordered
|
|
179
|
+
if (a.type === 'dict' && b.type === 'dict') {
|
|
180
|
+
const merged = mergeUniformValueType(a.valueType, b.valueType, a.fields ? Object.values(a.fields) : undefined, b.fields ? Object.values(b.fields) : undefined);
|
|
181
|
+
if (merged !== undefined)
|
|
182
|
+
return { type: 'dict', valueType: merged };
|
|
183
|
+
}
|
|
184
|
+
if (a.type === 'tuple' && b.type === 'tuple') {
|
|
185
|
+
const merged = mergeUniformValueType(a.valueType, b.valueType, a.elements, b.elements);
|
|
186
|
+
if (merged !== undefined)
|
|
187
|
+
return { type: 'tuple', valueType: merged };
|
|
112
188
|
}
|
|
113
|
-
|
|
189
|
+
if (a.type === 'ordered' && b.type === 'ordered') {
|
|
190
|
+
const merged = mergeUniformValueType(a.valueType, b.valueType, a.fields, b.fields);
|
|
191
|
+
if (merged !== undefined)
|
|
192
|
+
return { type: 'ordered', valueType: merged };
|
|
193
|
+
}
|
|
194
|
+
// 4. Bare type fallback for compound types.
|
|
195
|
+
// The cast is safe for closure/dict/tuple/ordered (all sub-fields optional).
|
|
196
|
+
// For union, members is required by RillType but omitted here intentionally:
|
|
197
|
+
// bare union signals structural incompatibility without enumerating members.
|
|
198
|
+
if (a.type === 'closure' ||
|
|
199
|
+
a.type === 'dict' ||
|
|
200
|
+
a.type === 'tuple' ||
|
|
201
|
+
a.type === 'ordered' ||
|
|
202
|
+
a.type === 'union') {
|
|
203
|
+
return { type: a.type };
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
114
206
|
}
|
|
115
207
|
/** Compare two structural types for equality. */
|
|
116
208
|
export function structuralTypeEquals(a, b) {
|
|
@@ -133,6 +225,15 @@ export function structuralTypeEquals(a, b) {
|
|
|
133
225
|
return structuralTypeEquals(a.element, b.element);
|
|
134
226
|
}
|
|
135
227
|
if (a.type === 'dict' && b.type === 'dict') {
|
|
228
|
+
// Uniform valueType comparison (mirrors list element at line 308)
|
|
229
|
+
const aHasValue = a.valueType !== undefined;
|
|
230
|
+
const bHasValue = b.valueType !== undefined;
|
|
231
|
+
if (aHasValue || bHasValue) {
|
|
232
|
+
if (!aHasValue || !bHasValue)
|
|
233
|
+
return false;
|
|
234
|
+
return structuralTypeEquals(a.valueType, b.valueType);
|
|
235
|
+
}
|
|
236
|
+
// Structural fields comparison
|
|
136
237
|
if (a.fields === undefined && b.fields === undefined)
|
|
137
238
|
return true;
|
|
138
239
|
if (a.fields === undefined || b.fields === undefined)
|
|
@@ -147,13 +248,11 @@ export function structuralTypeEquals(a, b) {
|
|
|
147
248
|
return false;
|
|
148
249
|
const aField = a.fields[key];
|
|
149
250
|
const bField = b.fields[key];
|
|
150
|
-
const aHasDefault =
|
|
151
|
-
const bHasDefault =
|
|
251
|
+
const aHasDefault = aField.defaultValue !== undefined;
|
|
252
|
+
const bHasDefault = bField.defaultValue !== undefined;
|
|
152
253
|
if (aHasDefault !== bHasDefault)
|
|
153
254
|
return false;
|
|
154
|
-
|
|
155
|
-
const bType = bHasDefault ? bField.type : bField;
|
|
156
|
-
if (!structuralTypeEquals(aType, bType))
|
|
255
|
+
if (!structuralTypeEquals(aField.type, bField.type))
|
|
157
256
|
return false;
|
|
158
257
|
if (aHasDefault && bHasDefault) {
|
|
159
258
|
if (!deepEquals(aField.defaultValue, bField.defaultValue))
|
|
@@ -163,6 +262,15 @@ export function structuralTypeEquals(a, b) {
|
|
|
163
262
|
return true;
|
|
164
263
|
}
|
|
165
264
|
if (a.type === 'tuple' && b.type === 'tuple') {
|
|
265
|
+
// Uniform valueType comparison (mirrors list element at line 308)
|
|
266
|
+
const aHasValue = a.valueType !== undefined;
|
|
267
|
+
const bHasValue = b.valueType !== undefined;
|
|
268
|
+
if (aHasValue || bHasValue) {
|
|
269
|
+
if (!aHasValue || !bHasValue)
|
|
270
|
+
return false;
|
|
271
|
+
return structuralTypeEquals(a.valueType, b.valueType);
|
|
272
|
+
}
|
|
273
|
+
// Structural elements comparison
|
|
166
274
|
if (a.elements === undefined && b.elements === undefined)
|
|
167
275
|
return true;
|
|
168
276
|
if (a.elements === undefined || b.elements === undefined)
|
|
@@ -172,10 +280,10 @@ export function structuralTypeEquals(a, b) {
|
|
|
172
280
|
for (let i = 0; i < a.elements.length; i++) {
|
|
173
281
|
const aElem = a.elements[i];
|
|
174
282
|
const bElem = b.elements[i];
|
|
175
|
-
if (!structuralTypeEquals(aElem
|
|
283
|
+
if (!structuralTypeEquals(aElem.type, bElem.type))
|
|
176
284
|
return false;
|
|
177
|
-
const aDefault = aElem
|
|
178
|
-
const bDefault = bElem
|
|
285
|
+
const aDefault = aElem.defaultValue;
|
|
286
|
+
const bDefault = bElem.defaultValue;
|
|
179
287
|
if (aDefault === undefined && bDefault === undefined)
|
|
180
288
|
continue;
|
|
181
289
|
if (aDefault === undefined || bDefault === undefined)
|
|
@@ -186,6 +294,15 @@ export function structuralTypeEquals(a, b) {
|
|
|
186
294
|
return true;
|
|
187
295
|
}
|
|
188
296
|
if (a.type === 'ordered' && b.type === 'ordered') {
|
|
297
|
+
// Uniform valueType comparison (mirrors list element at line 308)
|
|
298
|
+
const aHasValue = a.valueType !== undefined;
|
|
299
|
+
const bHasValue = b.valueType !== undefined;
|
|
300
|
+
if (aHasValue || bHasValue) {
|
|
301
|
+
if (!aHasValue || !bHasValue)
|
|
302
|
+
return false;
|
|
303
|
+
return structuralTypeEquals(a.valueType, b.valueType);
|
|
304
|
+
}
|
|
305
|
+
// Structural fields comparison
|
|
189
306
|
if (a.fields === undefined && b.fields === undefined)
|
|
190
307
|
return true;
|
|
191
308
|
if (a.fields === undefined || b.fields === undefined)
|
|
@@ -195,12 +312,12 @@ export function structuralTypeEquals(a, b) {
|
|
|
195
312
|
for (let i = 0; i < a.fields.length; i++) {
|
|
196
313
|
const aField = a.fields[i];
|
|
197
314
|
const bField = b.fields[i];
|
|
198
|
-
if (aField
|
|
315
|
+
if (aField.name !== bField.name)
|
|
199
316
|
return false;
|
|
200
|
-
if (!structuralTypeEquals(aField
|
|
317
|
+
if (!structuralTypeEquals(aField.type, bField.type))
|
|
201
318
|
return false;
|
|
202
|
-
const aDefault = aField
|
|
203
|
-
const bDefault = bField
|
|
319
|
+
const aDefault = aField.defaultValue;
|
|
320
|
+
const bDefault = bField.defaultValue;
|
|
204
321
|
if (aDefault === undefined && bDefault === undefined)
|
|
205
322
|
continue;
|
|
206
323
|
if (aDefault === undefined || bDefault === undefined)
|
|
@@ -232,12 +349,12 @@ export function structuralTypeEquals(a, b) {
|
|
|
232
349
|
for (let i = 0; i < a.params.length; i++) {
|
|
233
350
|
const aParam = a.params[i];
|
|
234
351
|
const bParam = b.params[i];
|
|
235
|
-
if (aParam
|
|
352
|
+
if (aParam.name !== bParam.name)
|
|
236
353
|
return false;
|
|
237
|
-
if (!structuralTypeEquals(aParam
|
|
354
|
+
if (!structuralTypeEquals(aParam.type, bParam.type))
|
|
238
355
|
return false;
|
|
239
|
-
const aDefault = aParam
|
|
240
|
-
const bDefault = bParam
|
|
356
|
+
const aDefault = aParam.defaultValue;
|
|
357
|
+
const bDefault = bParam.defaultValue;
|
|
241
358
|
if (aDefault === undefined && bDefault === undefined)
|
|
242
359
|
continue;
|
|
243
360
|
if (aDefault === undefined || bDefault === undefined)
|
|
@@ -274,25 +391,25 @@ export function inferStructuralType(value) {
|
|
|
274
391
|
if (isTuple(value)) {
|
|
275
392
|
return {
|
|
276
393
|
type: 'tuple',
|
|
277
|
-
elements: value.entries.map((e) =>
|
|
278
|
-
inferStructuralType(e),
|
|
279
|
-
|
|
394
|
+
elements: value.entries.map((e) => ({
|
|
395
|
+
type: inferStructuralType(e),
|
|
396
|
+
})),
|
|
280
397
|
};
|
|
281
398
|
}
|
|
282
399
|
if (isOrdered(value)) {
|
|
283
400
|
return {
|
|
284
401
|
type: 'ordered',
|
|
285
|
-
fields: value.entries.map(([k, v]) =>
|
|
286
|
-
k,
|
|
287
|
-
inferStructuralType(v),
|
|
288
|
-
|
|
402
|
+
fields: value.entries.map(([k, v]) => ({
|
|
403
|
+
name: k,
|
|
404
|
+
type: inferStructuralType(v),
|
|
405
|
+
})),
|
|
289
406
|
};
|
|
290
407
|
}
|
|
291
408
|
if (isVector(value)) {
|
|
292
409
|
return { type: 'vector' };
|
|
293
410
|
}
|
|
294
411
|
if (isCallable(value)) {
|
|
295
|
-
const params = (value.params ?? []).map((p) =>
|
|
412
|
+
const params = (value.params ?? []).map((p) => paramToFieldDef(p.name, p.type ?? { type: 'any' }, p.defaultValue));
|
|
296
413
|
const ret = value.returnType.structure;
|
|
297
414
|
return { type: 'closure', params, ret };
|
|
298
415
|
}
|
|
@@ -300,7 +417,7 @@ export function inferStructuralType(value) {
|
|
|
300
417
|
const dict = value;
|
|
301
418
|
const fields = {};
|
|
302
419
|
for (const [k, v] of Object.entries(dict)) {
|
|
303
|
-
fields[k] = inferStructuralType(v);
|
|
420
|
+
fields[k] = { type: inferStructuralType(v) };
|
|
304
421
|
}
|
|
305
422
|
return { type: 'dict', fields };
|
|
306
423
|
}
|
|
@@ -337,6 +454,11 @@ export function structuralTypeMatches(value, type) {
|
|
|
337
454
|
if (type.type === 'dict') {
|
|
338
455
|
if (!isDict(value))
|
|
339
456
|
return false;
|
|
457
|
+
// Uniform value type check: every value must match valueType
|
|
458
|
+
if (type.valueType !== undefined) {
|
|
459
|
+
const vals = Object.values(value);
|
|
460
|
+
return vals.every((v) => structuralTypeMatches(v, type.valueType));
|
|
461
|
+
}
|
|
340
462
|
// Absent fields sub-field: matches any dict value
|
|
341
463
|
if (type.fields === undefined)
|
|
342
464
|
return true;
|
|
@@ -346,13 +468,14 @@ export function structuralTypeMatches(value, type) {
|
|
|
346
468
|
return true;
|
|
347
469
|
const dict = value;
|
|
348
470
|
for (const key of dictKeys) {
|
|
349
|
-
if (!(key in dict))
|
|
471
|
+
if (!(key in dict)) {
|
|
472
|
+
const field = type.fields[key];
|
|
473
|
+
if (field.defaultValue !== undefined)
|
|
474
|
+
continue;
|
|
350
475
|
return false;
|
|
351
|
-
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
: fieldType;
|
|
355
|
-
if (!structuralTypeMatches(dict[key], resolvedType))
|
|
476
|
+
}
|
|
477
|
+
const field = type.fields[key];
|
|
478
|
+
if (!structuralTypeMatches(dict[key], field.type))
|
|
356
479
|
return false;
|
|
357
480
|
}
|
|
358
481
|
return true;
|
|
@@ -360,15 +483,28 @@ export function structuralTypeMatches(value, type) {
|
|
|
360
483
|
if (type.type === 'tuple') {
|
|
361
484
|
if (!isTuple(value))
|
|
362
485
|
return false;
|
|
486
|
+
// Uniform value type check: every entry must match valueType
|
|
487
|
+
if (type.valueType !== undefined) {
|
|
488
|
+
return value.entries.every((v) => structuralTypeMatches(v, type.valueType));
|
|
489
|
+
}
|
|
363
490
|
// Absent elements sub-field: matches any tuple value
|
|
364
491
|
if (type.elements === undefined)
|
|
365
492
|
return true;
|
|
366
493
|
if (type.elements.length === 0)
|
|
367
494
|
return value.entries.length === 0;
|
|
368
|
-
if
|
|
495
|
+
// Reject if value has more entries than type elements
|
|
496
|
+
if (value.entries.length > type.elements.length)
|
|
369
497
|
return false;
|
|
370
|
-
|
|
371
|
-
|
|
498
|
+
// Reject if value is shorter and any trailing missing element lacks a default
|
|
499
|
+
if (value.entries.length < type.elements.length) {
|
|
500
|
+
for (let i = value.entries.length; i < type.elements.length; i++) {
|
|
501
|
+
const field = type.elements[i];
|
|
502
|
+
if (field.defaultValue === undefined)
|
|
503
|
+
return false;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
for (let i = 0; i < value.entries.length; i++) {
|
|
507
|
+
if (!structuralTypeMatches(value.entries[i], type.elements[i].type))
|
|
372
508
|
return false;
|
|
373
509
|
}
|
|
374
510
|
return true;
|
|
@@ -376,19 +512,32 @@ export function structuralTypeMatches(value, type) {
|
|
|
376
512
|
if (type.type === 'ordered') {
|
|
377
513
|
if (!isOrdered(value))
|
|
378
514
|
return false;
|
|
515
|
+
// Uniform value type check: every entry value must match valueType
|
|
516
|
+
if (type.valueType !== undefined) {
|
|
517
|
+
return value.entries.every(([, v]) => structuralTypeMatches(v, type.valueType));
|
|
518
|
+
}
|
|
379
519
|
// Absent fields sub-field: matches any ordered value
|
|
380
520
|
if (type.fields === undefined)
|
|
381
521
|
return true;
|
|
382
522
|
if (type.fields.length === 0)
|
|
383
523
|
return value.entries.length === 0;
|
|
384
|
-
if
|
|
524
|
+
// Reject if value has more entries than type fields
|
|
525
|
+
if (value.entries.length > type.fields.length)
|
|
385
526
|
return false;
|
|
386
|
-
|
|
387
|
-
|
|
527
|
+
// Reject if value is shorter and any trailing missing field lacks a default
|
|
528
|
+
if (value.entries.length < type.fields.length) {
|
|
529
|
+
for (let i = value.entries.length; i < type.fields.length; i++) {
|
|
530
|
+
const field = type.fields[i];
|
|
531
|
+
if (field.defaultValue === undefined)
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
for (let i = 0; i < value.entries.length; i++) {
|
|
536
|
+
const field = type.fields[i];
|
|
388
537
|
const [actualName, actualValue] = value.entries[i];
|
|
389
|
-
if (actualName !==
|
|
538
|
+
if (actualName !== field.name)
|
|
390
539
|
return false;
|
|
391
|
-
if (!structuralTypeMatches(actualValue,
|
|
540
|
+
if (!structuralTypeMatches(actualValue, field.type))
|
|
392
541
|
return false;
|
|
393
542
|
}
|
|
394
543
|
return true;
|
|
@@ -403,12 +552,12 @@ export function structuralTypeMatches(value, type) {
|
|
|
403
552
|
if (valueParams.length !== type.params.length)
|
|
404
553
|
return false;
|
|
405
554
|
for (let i = 0; i < type.params.length; i++) {
|
|
406
|
-
const
|
|
555
|
+
const field = type.params[i];
|
|
407
556
|
const param = valueParams[i];
|
|
408
|
-
if (param.name !==
|
|
557
|
+
if (param.name !== field.name)
|
|
409
558
|
return false;
|
|
410
559
|
const paramType = param.type ?? { type: 'any' };
|
|
411
|
-
if (!structuralTypeEquals(paramType,
|
|
560
|
+
if (!structuralTypeEquals(paramType, field.type))
|
|
412
561
|
return false;
|
|
413
562
|
}
|
|
414
563
|
const retType = value.returnType.structure;
|
|
@@ -421,9 +570,12 @@ export function structuralTypeMatches(value, type) {
|
|
|
421
570
|
}
|
|
422
571
|
return false;
|
|
423
572
|
}
|
|
424
|
-
/** Build a closure param
|
|
425
|
-
export function
|
|
426
|
-
|
|
573
|
+
/** Build a closure param field definition from name, type, and optional default. */
|
|
574
|
+
export function paramToFieldDef(name, type, defaultValue) {
|
|
575
|
+
const field = { name, type };
|
|
576
|
+
if (defaultValue !== undefined)
|
|
577
|
+
field.defaultValue = defaultValue;
|
|
578
|
+
return field;
|
|
427
579
|
}
|
|
428
580
|
/** Format a RillValue as a rill literal for use in type signatures. */
|
|
429
581
|
function formatRillLiteral(value) {
|
|
@@ -455,38 +607,47 @@ export function formatStructuralType(type) {
|
|
|
455
607
|
return `list(${formatStructuralType(type.element)})`;
|
|
456
608
|
}
|
|
457
609
|
if (type.type === 'dict') {
|
|
610
|
+
if (type.valueType !== undefined && type.fields === undefined) {
|
|
611
|
+
return `dict(${formatStructuralType(type.valueType)})`;
|
|
612
|
+
}
|
|
458
613
|
if (type.fields === undefined)
|
|
459
614
|
return 'dict';
|
|
460
615
|
const parts = Object.keys(type.fields)
|
|
461
616
|
.sort()
|
|
462
617
|
.map((k) => {
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
return `${
|
|
618
|
+
const field = type.fields[k];
|
|
619
|
+
const base = `${k}: ${formatStructuralType(field.type)}`;
|
|
620
|
+
if (field.defaultValue === undefined)
|
|
621
|
+
return base;
|
|
622
|
+
return `${base} = ${formatRillLiteral(field.defaultValue)}`;
|
|
468
623
|
});
|
|
469
624
|
return `dict(${parts.join(', ')})`;
|
|
470
625
|
}
|
|
471
626
|
if (type.type === 'tuple') {
|
|
627
|
+
if (type.valueType !== undefined && type.elements === undefined) {
|
|
628
|
+
return `tuple(${formatStructuralType(type.valueType)})`;
|
|
629
|
+
}
|
|
472
630
|
if (type.elements === undefined)
|
|
473
631
|
return 'tuple';
|
|
474
|
-
const parts = type.elements.map((
|
|
475
|
-
const base = formatStructuralType(
|
|
476
|
-
if (
|
|
632
|
+
const parts = type.elements.map((field) => {
|
|
633
|
+
const base = formatStructuralType(field.type);
|
|
634
|
+
if (field.defaultValue === undefined)
|
|
477
635
|
return base;
|
|
478
|
-
return `${base} = ${formatRillLiteral(
|
|
636
|
+
return `${base} = ${formatRillLiteral(field.defaultValue)}`;
|
|
479
637
|
});
|
|
480
638
|
return `tuple(${parts.join(', ')})`;
|
|
481
639
|
}
|
|
482
640
|
if (type.type === 'ordered') {
|
|
641
|
+
if (type.valueType !== undefined && type.fields === undefined) {
|
|
642
|
+
return `ordered(${formatStructuralType(type.valueType)})`;
|
|
643
|
+
}
|
|
483
644
|
if (type.fields === undefined)
|
|
484
645
|
return 'ordered';
|
|
485
|
-
const parts = type.fields.map((
|
|
486
|
-
const base = `${
|
|
487
|
-
if (
|
|
646
|
+
const parts = type.fields.map((field) => {
|
|
647
|
+
const base = `${field.name}: ${formatStructuralType(field.type)}`;
|
|
648
|
+
if (field.defaultValue === undefined)
|
|
488
649
|
return base;
|
|
489
|
-
return `${base} = ${formatRillLiteral(
|
|
650
|
+
return `${base} = ${formatRillLiteral(field.defaultValue)}`;
|
|
490
651
|
});
|
|
491
652
|
return `ordered(${parts.join(', ')})`;
|
|
492
653
|
}
|
|
@@ -494,11 +655,11 @@ export function formatStructuralType(type) {
|
|
|
494
655
|
if (type.params === undefined)
|
|
495
656
|
return 'closure';
|
|
496
657
|
const params = type.params
|
|
497
|
-
.map((
|
|
498
|
-
const base = `${name}: ${formatStructuralType(
|
|
499
|
-
if (
|
|
658
|
+
.map((field) => {
|
|
659
|
+
const base = `${field.name}: ${formatStructuralType(field.type)}`;
|
|
660
|
+
if (field.defaultValue === undefined)
|
|
500
661
|
return base;
|
|
501
|
-
return `${base} = ${formatRillLiteral(
|
|
662
|
+
return `${base} = ${formatRillLiteral(field.defaultValue)}`;
|
|
502
663
|
})
|
|
503
664
|
.join(', ');
|
|
504
665
|
const ret = type.ret !== undefined ? formatStructuralType(type.ret) : 'any';
|
|
@@ -855,6 +1016,29 @@ export function rillTypeToTypeValue(type) {
|
|
|
855
1016
|
structure: type,
|
|
856
1017
|
});
|
|
857
1018
|
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Check if a type is a collection (dict, ordered, tuple) with defined
|
|
1021
|
+
* fields or elements. Used to decide if an empty collection can be
|
|
1022
|
+
* synthesized and hydrated.
|
|
1023
|
+
*/
|
|
1024
|
+
export function hasCollectionFields(type) {
|
|
1025
|
+
return ((type.type === 'dict' && (!!type.fields || !!type.valueType)) ||
|
|
1026
|
+
(type.type === 'ordered' && (!!type.fields || !!type.valueType)) ||
|
|
1027
|
+
(type.type === 'tuple' && (!!type.elements || !!type.valueType)));
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* Create an empty collection value matching the given RillType.
|
|
1031
|
+
* Assumes the type is dict, ordered, or tuple.
|
|
1032
|
+
*/
|
|
1033
|
+
export function emptyForType(type) {
|
|
1034
|
+
if (type.type === 'dict')
|
|
1035
|
+
return {};
|
|
1036
|
+
if (type.type === 'ordered')
|
|
1037
|
+
return createOrdered([]);
|
|
1038
|
+
if (type.type === 'tuple')
|
|
1039
|
+
return createTuple([]);
|
|
1040
|
+
return {};
|
|
1041
|
+
}
|
|
858
1042
|
/** Check if a key name is reserved */
|
|
859
1043
|
export function isReservedMethod(name) {
|
|
860
1044
|
return RESERVED_DICT_METHODS.includes(name);
|
|
@@ -879,4 +1063,32 @@ export function isRillIterator(value) {
|
|
|
879
1063
|
return false;
|
|
880
1064
|
return true;
|
|
881
1065
|
}
|
|
882
|
-
|
|
1066
|
+
/**
|
|
1067
|
+
* Deep copy a RillValue, producing a new independent value.
|
|
1068
|
+
* Handles primitives, arrays, plain dicts, and null.
|
|
1069
|
+
* Special markers (closures, tuples, ordered, vectors, type values) are returned
|
|
1070
|
+
* as-is since they are immutable by contract.
|
|
1071
|
+
*/
|
|
1072
|
+
export function deepCopyRillValue(value) {
|
|
1073
|
+
if (value === null || typeof value !== 'object') {
|
|
1074
|
+
return value;
|
|
1075
|
+
}
|
|
1076
|
+
if (Array.isArray(value)) {
|
|
1077
|
+
return value.map(deepCopyRillValue);
|
|
1078
|
+
}
|
|
1079
|
+
// Plain dict: copy recursively. Special markers (RillTuple, RillOrdered, etc.)
|
|
1080
|
+
// carry __rill_* own properties and are treated as immutable; return as-is.
|
|
1081
|
+
if (!('__rill_tuple' in value) &&
|
|
1082
|
+
!('__rill_ordered' in value) &&
|
|
1083
|
+
!('__rill_vector' in value) &&
|
|
1084
|
+
!('__rill_type' in value) &&
|
|
1085
|
+
!('__type' in value) &&
|
|
1086
|
+
!('__rill_field_descriptor' in value)) {
|
|
1087
|
+
const copy = {};
|
|
1088
|
+
for (const [k, v] of Object.entries(value)) {
|
|
1089
|
+
copy[k] = deepCopyRillValue(v);
|
|
1090
|
+
}
|
|
1091
|
+
return copy;
|
|
1092
|
+
}
|
|
1093
|
+
return value;
|
|
1094
|
+
}
|