@rcrsr/rill 0.14.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 -11
- 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 +50 -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 -40
- 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 -31
- 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 -69
- 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 +263 -16
- 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 -200
- 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 -8
- package/dist/runtime/core/values.js +338 -36
- 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 -4
- 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
|
@@ -35,7 +35,11 @@ export function isTypeValue(value) {
|
|
|
35
35
|
'__rill_type' in value &&
|
|
36
36
|
value.__rill_type === true);
|
|
37
37
|
}
|
|
38
|
-
/**
|
|
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
|
+
*/
|
|
39
43
|
export function createOrdered(entries) {
|
|
40
44
|
return Object.freeze({ __rill_ordered: true, entries: [...entries] });
|
|
41
45
|
}
|
|
@@ -93,15 +97,112 @@ export function inferElementType(elements) {
|
|
|
93
97
|
if (elements.length === 0)
|
|
94
98
|
return { type: 'any' };
|
|
95
99
|
const firstElem = elements[0];
|
|
96
|
-
|
|
100
|
+
let accType = inferStructuralType(firstElem);
|
|
97
101
|
for (let i = 1; i < elements.length; i++) {
|
|
98
102
|
const elem = elements[i];
|
|
99
103
|
const elemType = inferStructuralType(elem);
|
|
100
|
-
|
|
101
|
-
|
|
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 };
|
|
102
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 };
|
|
103
183
|
}
|
|
104
|
-
|
|
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 };
|
|
188
|
+
}
|
|
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;
|
|
105
206
|
}
|
|
106
207
|
/** Compare two structural types for equality. */
|
|
107
208
|
export function structuralTypeEquals(a, b) {
|
|
@@ -124,6 +225,15 @@ export function structuralTypeEquals(a, b) {
|
|
|
124
225
|
return structuralTypeEquals(a.element, b.element);
|
|
125
226
|
}
|
|
126
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
|
|
127
237
|
if (a.fields === undefined && b.fields === undefined)
|
|
128
238
|
return true;
|
|
129
239
|
if (a.fields === undefined || b.fields === undefined)
|
|
@@ -138,12 +248,29 @@ export function structuralTypeEquals(a, b) {
|
|
|
138
248
|
return false;
|
|
139
249
|
const aField = a.fields[key];
|
|
140
250
|
const bField = b.fields[key];
|
|
141
|
-
|
|
251
|
+
const aHasDefault = aField.defaultValue !== undefined;
|
|
252
|
+
const bHasDefault = bField.defaultValue !== undefined;
|
|
253
|
+
if (aHasDefault !== bHasDefault)
|
|
142
254
|
return false;
|
|
255
|
+
if (!structuralTypeEquals(aField.type, bField.type))
|
|
256
|
+
return false;
|
|
257
|
+
if (aHasDefault && bHasDefault) {
|
|
258
|
+
if (!deepEquals(aField.defaultValue, bField.defaultValue))
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
143
261
|
}
|
|
144
262
|
return true;
|
|
145
263
|
}
|
|
146
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
|
|
147
274
|
if (a.elements === undefined && b.elements === undefined)
|
|
148
275
|
return true;
|
|
149
276
|
if (a.elements === undefined || b.elements === undefined)
|
|
@@ -151,12 +278,31 @@ export function structuralTypeEquals(a, b) {
|
|
|
151
278
|
if (a.elements.length !== b.elements.length)
|
|
152
279
|
return false;
|
|
153
280
|
for (let i = 0; i < a.elements.length; i++) {
|
|
154
|
-
|
|
281
|
+
const aElem = a.elements[i];
|
|
282
|
+
const bElem = b.elements[i];
|
|
283
|
+
if (!structuralTypeEquals(aElem.type, bElem.type))
|
|
284
|
+
return false;
|
|
285
|
+
const aDefault = aElem.defaultValue;
|
|
286
|
+
const bDefault = bElem.defaultValue;
|
|
287
|
+
if (aDefault === undefined && bDefault === undefined)
|
|
288
|
+
continue;
|
|
289
|
+
if (aDefault === undefined || bDefault === undefined)
|
|
290
|
+
return false;
|
|
291
|
+
if (!deepEquals(aDefault, bDefault))
|
|
155
292
|
return false;
|
|
156
293
|
}
|
|
157
294
|
return true;
|
|
158
295
|
}
|
|
159
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
|
|
160
306
|
if (a.fields === undefined && b.fields === undefined)
|
|
161
307
|
return true;
|
|
162
308
|
if (a.fields === undefined || b.fields === undefined)
|
|
@@ -166,9 +312,17 @@ export function structuralTypeEquals(a, b) {
|
|
|
166
312
|
for (let i = 0; i < a.fields.length; i++) {
|
|
167
313
|
const aField = a.fields[i];
|
|
168
314
|
const bField = b.fields[i];
|
|
169
|
-
if (aField
|
|
315
|
+
if (aField.name !== bField.name)
|
|
170
316
|
return false;
|
|
171
|
-
if (!structuralTypeEquals(aField
|
|
317
|
+
if (!structuralTypeEquals(aField.type, bField.type))
|
|
318
|
+
return false;
|
|
319
|
+
const aDefault = aField.defaultValue;
|
|
320
|
+
const bDefault = bField.defaultValue;
|
|
321
|
+
if (aDefault === undefined && bDefault === undefined)
|
|
322
|
+
continue;
|
|
323
|
+
if (aDefault === undefined || bDefault === undefined)
|
|
324
|
+
return false;
|
|
325
|
+
if (!deepEquals(aDefault, bDefault))
|
|
172
326
|
return false;
|
|
173
327
|
}
|
|
174
328
|
return true;
|
|
@@ -195,9 +349,17 @@ export function structuralTypeEquals(a, b) {
|
|
|
195
349
|
for (let i = 0; i < a.params.length; i++) {
|
|
196
350
|
const aParam = a.params[i];
|
|
197
351
|
const bParam = b.params[i];
|
|
198
|
-
if (aParam
|
|
352
|
+
if (aParam.name !== bParam.name)
|
|
353
|
+
return false;
|
|
354
|
+
if (!structuralTypeEquals(aParam.type, bParam.type))
|
|
355
|
+
return false;
|
|
356
|
+
const aDefault = aParam.defaultValue;
|
|
357
|
+
const bDefault = bParam.defaultValue;
|
|
358
|
+
if (aDefault === undefined && bDefault === undefined)
|
|
359
|
+
continue;
|
|
360
|
+
if (aDefault === undefined || bDefault === undefined)
|
|
199
361
|
return false;
|
|
200
|
-
if (!
|
|
362
|
+
if (!deepEquals(aDefault, bDefault))
|
|
201
363
|
return false;
|
|
202
364
|
}
|
|
203
365
|
}
|
|
@@ -229,23 +391,25 @@ export function inferStructuralType(value) {
|
|
|
229
391
|
if (isTuple(value)) {
|
|
230
392
|
return {
|
|
231
393
|
type: 'tuple',
|
|
232
|
-
elements: value.entries.map(
|
|
394
|
+
elements: value.entries.map((e) => ({
|
|
395
|
+
type: inferStructuralType(e),
|
|
396
|
+
})),
|
|
233
397
|
};
|
|
234
398
|
}
|
|
235
399
|
if (isOrdered(value)) {
|
|
236
400
|
return {
|
|
237
401
|
type: 'ordered',
|
|
238
|
-
fields: value.entries.map(([k, v]) =>
|
|
402
|
+
fields: value.entries.map(([k, v]) => ({
|
|
403
|
+
name: k,
|
|
404
|
+
type: inferStructuralType(v),
|
|
405
|
+
})),
|
|
239
406
|
};
|
|
240
407
|
}
|
|
241
408
|
if (isVector(value)) {
|
|
242
409
|
return { type: 'vector' };
|
|
243
410
|
}
|
|
244
411
|
if (isCallable(value)) {
|
|
245
|
-
const params = (value.params ?? []).map((p) =>
|
|
246
|
-
p.name,
|
|
247
|
-
p.type ?? { type: 'any' },
|
|
248
|
-
]);
|
|
412
|
+
const params = (value.params ?? []).map((p) => paramToFieldDef(p.name, p.type ?? { type: 'any' }, p.defaultValue));
|
|
249
413
|
const ret = value.returnType.structure;
|
|
250
414
|
return { type: 'closure', params, ret };
|
|
251
415
|
}
|
|
@@ -253,7 +417,7 @@ export function inferStructuralType(value) {
|
|
|
253
417
|
const dict = value;
|
|
254
418
|
const fields = {};
|
|
255
419
|
for (const [k, v] of Object.entries(dict)) {
|
|
256
|
-
fields[k] = inferStructuralType(v);
|
|
420
|
+
fields[k] = { type: inferStructuralType(v) };
|
|
257
421
|
}
|
|
258
422
|
return { type: 'dict', fields };
|
|
259
423
|
}
|
|
@@ -290,6 +454,11 @@ export function structuralTypeMatches(value, type) {
|
|
|
290
454
|
if (type.type === 'dict') {
|
|
291
455
|
if (!isDict(value))
|
|
292
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
|
+
}
|
|
293
462
|
// Absent fields sub-field: matches any dict value
|
|
294
463
|
if (type.fields === undefined)
|
|
295
464
|
return true;
|
|
@@ -299,9 +468,14 @@ export function structuralTypeMatches(value, type) {
|
|
|
299
468
|
return true;
|
|
300
469
|
const dict = value;
|
|
301
470
|
for (const key of dictKeys) {
|
|
302
|
-
if (!(key in dict))
|
|
471
|
+
if (!(key in dict)) {
|
|
472
|
+
const field = type.fields[key];
|
|
473
|
+
if (field.defaultValue !== undefined)
|
|
474
|
+
continue;
|
|
303
475
|
return false;
|
|
304
|
-
|
|
476
|
+
}
|
|
477
|
+
const field = type.fields[key];
|
|
478
|
+
if (!structuralTypeMatches(dict[key], field.type))
|
|
305
479
|
return false;
|
|
306
480
|
}
|
|
307
481
|
return true;
|
|
@@ -309,15 +483,28 @@ export function structuralTypeMatches(value, type) {
|
|
|
309
483
|
if (type.type === 'tuple') {
|
|
310
484
|
if (!isTuple(value))
|
|
311
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
|
+
}
|
|
312
490
|
// Absent elements sub-field: matches any tuple value
|
|
313
491
|
if (type.elements === undefined)
|
|
314
492
|
return true;
|
|
315
493
|
if (type.elements.length === 0)
|
|
316
494
|
return value.entries.length === 0;
|
|
317
|
-
if
|
|
495
|
+
// Reject if value has more entries than type elements
|
|
496
|
+
if (value.entries.length > type.elements.length)
|
|
318
497
|
return false;
|
|
319
|
-
|
|
320
|
-
|
|
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))
|
|
321
508
|
return false;
|
|
322
509
|
}
|
|
323
510
|
return true;
|
|
@@ -325,19 +512,32 @@ export function structuralTypeMatches(value, type) {
|
|
|
325
512
|
if (type.type === 'ordered') {
|
|
326
513
|
if (!isOrdered(value))
|
|
327
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
|
+
}
|
|
328
519
|
// Absent fields sub-field: matches any ordered value
|
|
329
520
|
if (type.fields === undefined)
|
|
330
521
|
return true;
|
|
331
522
|
if (type.fields.length === 0)
|
|
332
523
|
return value.entries.length === 0;
|
|
333
|
-
if
|
|
524
|
+
// Reject if value has more entries than type fields
|
|
525
|
+
if (value.entries.length > type.fields.length)
|
|
334
526
|
return false;
|
|
335
|
-
|
|
336
|
-
|
|
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];
|
|
337
537
|
const [actualName, actualValue] = value.entries[i];
|
|
338
|
-
if (actualName !==
|
|
538
|
+
if (actualName !== field.name)
|
|
339
539
|
return false;
|
|
340
|
-
if (!structuralTypeMatches(actualValue,
|
|
540
|
+
if (!structuralTypeMatches(actualValue, field.type))
|
|
341
541
|
return false;
|
|
342
542
|
}
|
|
343
543
|
return true;
|
|
@@ -352,12 +552,12 @@ export function structuralTypeMatches(value, type) {
|
|
|
352
552
|
if (valueParams.length !== type.params.length)
|
|
353
553
|
return false;
|
|
354
554
|
for (let i = 0; i < type.params.length; i++) {
|
|
355
|
-
const
|
|
555
|
+
const field = type.params[i];
|
|
356
556
|
const param = valueParams[i];
|
|
357
|
-
if (param.name !==
|
|
557
|
+
if (param.name !== field.name)
|
|
358
558
|
return false;
|
|
359
559
|
const paramType = param.type ?? { type: 'any' };
|
|
360
|
-
if (!structuralTypeEquals(paramType,
|
|
560
|
+
if (!structuralTypeEquals(paramType, field.type))
|
|
361
561
|
return false;
|
|
362
562
|
}
|
|
363
563
|
const retType = value.returnType.structure;
|
|
@@ -370,6 +570,27 @@ export function structuralTypeMatches(value, type) {
|
|
|
370
570
|
}
|
|
371
571
|
return false;
|
|
372
572
|
}
|
|
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;
|
|
579
|
+
}
|
|
580
|
+
/** Format a RillValue as a rill literal for use in type signatures. */
|
|
581
|
+
function formatRillLiteral(value) {
|
|
582
|
+
if (typeof value === 'string') {
|
|
583
|
+
const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
584
|
+
return `"${escaped}"`;
|
|
585
|
+
}
|
|
586
|
+
if (typeof value === 'number')
|
|
587
|
+
return String(value);
|
|
588
|
+
if (typeof value === 'boolean')
|
|
589
|
+
return value ? 'true' : 'false';
|
|
590
|
+
if (value === null)
|
|
591
|
+
return 'null';
|
|
592
|
+
return formatValue(value);
|
|
593
|
+
}
|
|
373
594
|
/** Format a structural type descriptor as a human-readable string. */
|
|
374
595
|
export function formatStructuralType(type) {
|
|
375
596
|
if (type.type === 'any' ||
|
|
@@ -386,30 +607,60 @@ export function formatStructuralType(type) {
|
|
|
386
607
|
return `list(${formatStructuralType(type.element)})`;
|
|
387
608
|
}
|
|
388
609
|
if (type.type === 'dict') {
|
|
610
|
+
if (type.valueType !== undefined && type.fields === undefined) {
|
|
611
|
+
return `dict(${formatStructuralType(type.valueType)})`;
|
|
612
|
+
}
|
|
389
613
|
if (type.fields === undefined)
|
|
390
614
|
return 'dict';
|
|
391
615
|
const parts = Object.keys(type.fields)
|
|
392
616
|
.sort()
|
|
393
|
-
.map((k) =>
|
|
617
|
+
.map((k) => {
|
|
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)}`;
|
|
623
|
+
});
|
|
394
624
|
return `dict(${parts.join(', ')})`;
|
|
395
625
|
}
|
|
396
626
|
if (type.type === 'tuple') {
|
|
627
|
+
if (type.valueType !== undefined && type.elements === undefined) {
|
|
628
|
+
return `tuple(${formatStructuralType(type.valueType)})`;
|
|
629
|
+
}
|
|
397
630
|
if (type.elements === undefined)
|
|
398
631
|
return 'tuple';
|
|
399
|
-
const parts = type.elements.map(
|
|
632
|
+
const parts = type.elements.map((field) => {
|
|
633
|
+
const base = formatStructuralType(field.type);
|
|
634
|
+
if (field.defaultValue === undefined)
|
|
635
|
+
return base;
|
|
636
|
+
return `${base} = ${formatRillLiteral(field.defaultValue)}`;
|
|
637
|
+
});
|
|
400
638
|
return `tuple(${parts.join(', ')})`;
|
|
401
639
|
}
|
|
402
640
|
if (type.type === 'ordered') {
|
|
641
|
+
if (type.valueType !== undefined && type.fields === undefined) {
|
|
642
|
+
return `ordered(${formatStructuralType(type.valueType)})`;
|
|
643
|
+
}
|
|
403
644
|
if (type.fields === undefined)
|
|
404
645
|
return 'ordered';
|
|
405
|
-
const parts = type.fields.map((
|
|
646
|
+
const parts = type.fields.map((field) => {
|
|
647
|
+
const base = `${field.name}: ${formatStructuralType(field.type)}`;
|
|
648
|
+
if (field.defaultValue === undefined)
|
|
649
|
+
return base;
|
|
650
|
+
return `${base} = ${formatRillLiteral(field.defaultValue)}`;
|
|
651
|
+
});
|
|
406
652
|
return `ordered(${parts.join(', ')})`;
|
|
407
653
|
}
|
|
408
654
|
if (type.type === 'closure') {
|
|
409
655
|
if (type.params === undefined)
|
|
410
656
|
return 'closure';
|
|
411
657
|
const params = type.params
|
|
412
|
-
.map((
|
|
658
|
+
.map((field) => {
|
|
659
|
+
const base = `${field.name}: ${formatStructuralType(field.type)}`;
|
|
660
|
+
if (field.defaultValue === undefined)
|
|
661
|
+
return base;
|
|
662
|
+
return `${base} = ${formatRillLiteral(field.defaultValue)}`;
|
|
663
|
+
})
|
|
413
664
|
.join(', ');
|
|
414
665
|
const ret = type.ret !== undefined ? formatStructuralType(type.ret) : 'any';
|
|
415
666
|
return `|${params}| :${ret}`;
|
|
@@ -765,6 +1016,29 @@ export function rillTypeToTypeValue(type) {
|
|
|
765
1016
|
structure: type,
|
|
766
1017
|
});
|
|
767
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
|
+
}
|
|
768
1042
|
/** Check if a key name is reserved */
|
|
769
1043
|
export function isReservedMethod(name) {
|
|
770
1044
|
return RESERVED_DICT_METHODS.includes(name);
|
|
@@ -789,4 +1063,32 @@ export function isRillIterator(value) {
|
|
|
789
1063
|
return false;
|
|
790
1064
|
return true;
|
|
791
1065
|
}
|
|
792
|
-
|
|
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
|
+
}
|