@shwfed/nuxt 0.7.8 → 0.7.9
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/module.json +1 -1
- package/dist/runtime/components/app.d.vue.ts +0 -2
- package/dist/runtime/components/app.vue +1 -7
- package/dist/runtime/components/app.vue.d.ts +0 -2
- package/dist/runtime/components/fields.d.vue.ts +155 -0
- package/dist/runtime/components/fields.vue +312 -0
- package/dist/runtime/components/fields.vue.d.ts +155 -0
- package/dist/runtime/components/ui/button-group/ButtonGroupSeparator.vue +1 -1
- package/dist/runtime/components/ui/button-group/ButtonGroupText.vue +1 -1
- package/dist/runtime/components/ui/calendar/Calendar.d.vue.ts +5 -12
- package/dist/runtime/components/ui/calendar/Calendar.vue +77 -92
- package/dist/runtime/components/ui/calendar/Calendar.vue.d.ts +5 -12
- package/dist/runtime/components/ui/calendar/CalendarCellTrigger.vue +1 -1
- package/dist/runtime/components/ui/calendar/index.d.ts +1 -1
- package/dist/runtime/components/ui/command/CommandGroup.vue +4 -0
- package/dist/runtime/components/ui/dialog/DialogOverlay.vue +1 -1
- package/dist/runtime/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +1 -1
- package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +1 -1
- package/dist/runtime/components/ui/field/FieldDescription.vue +1 -1
- package/dist/runtime/components/ui/field/FieldError.vue +1 -1
- package/dist/runtime/components/ui/field/FieldLabel.vue +1 -1
- package/dist/runtime/components/ui/field/FieldSeparator.vue +1 -1
- package/dist/runtime/components/ui/field/index.js +7 -5
- package/dist/runtime/components/ui/input/Input.vue +1 -1
- package/dist/runtime/components/ui/input-group/InputGroup.vue +3 -0
- package/dist/runtime/components/ui/input-group/InputGroupCombobox.d.vue.ts +4 -1
- package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue +10 -4
- package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue.d.ts +4 -1
- package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.vue +3 -1
- package/dist/runtime/components/ui/input-group/InputGroupInput.vue +1 -1
- package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue +1 -1
- package/dist/runtime/components/ui/input-group/InputGroupText.vue +1 -1
- package/dist/runtime/components/ui/input-group/InputGroupTextarea.vue +1 -1
- package/dist/runtime/components/ui/input-group/index.js +1 -1
- package/dist/runtime/components/ui/label/Label.vue +1 -1
- package/dist/runtime/components/ui/native-select/NativeSelect.vue +3 -3
- package/dist/runtime/components/ui/navigation-menu/NavigationMenuLink.vue +1 -1
- package/dist/runtime/components/ui/navigation-menu/NavigationMenuViewport.vue +1 -1
- package/dist/runtime/components/ui/range-calendar/RangeCalendarCell.vue +1 -1
- package/dist/runtime/components/ui/range-calendar/RangeCalendarCellTrigger.vue +1 -1
- package/dist/runtime/components/ui/sheet/SheetOverlay.vue +1 -1
- package/dist/runtime/components/ui/switch/Switch.d.vue.ts +24 -0
- package/dist/runtime/components/ui/switch/Switch.vue +46 -0
- package/dist/runtime/components/ui/switch/Switch.vue.d.ts +24 -0
- package/dist/runtime/components/ui/switch/index.d.ts +1 -0
- package/dist/runtime/components/ui/switch/index.js +1 -0
- package/dist/runtime/components/ui/textarea/Textarea.vue +1 -1
- package/dist/runtime/plugins/cel/env.d.ts +2 -2
- package/dist/runtime/plugins/cel/env.js +5 -4
- package/dist/runtime/plugins/cel/index.d.ts +3 -3
- package/dist/runtime/plugins/cel/index.js +7 -3
- package/dist/runtime/plugins/markdown/index.d.ts +1 -1
- package/dist/runtime/utils/coders.d.ts +7 -0
- package/dist/runtime/utils/coders.js +39 -0
- package/dist/runtime/vendor/cel/index.d.ts +17 -0
- package/dist/runtime/vendor/cel/index.js +10 -0
- package/dist/runtime/vendor/cel-js/LICENSE +21 -0
- package/dist/runtime/vendor/cel-js/UPSTREAM.md +17 -0
- package/dist/runtime/vendor/cel-js/lib/errors.d.ts +21 -0
- package/dist/runtime/vendor/cel-js/lib/errors.js +97 -0
- package/dist/runtime/vendor/cel-js/lib/evaluator.d.ts +4 -0
- package/dist/runtime/vendor/cel-js/lib/evaluator.js +192 -0
- package/dist/runtime/vendor/cel-js/lib/functions.d.ts +53 -0
- package/dist/runtime/vendor/cel-js/lib/functions.js +513 -0
- package/dist/runtime/vendor/cel-js/lib/globals.d.ts +27 -0
- package/dist/runtime/vendor/cel-js/lib/globals.js +33 -0
- package/dist/runtime/vendor/cel-js/lib/index.d.ts +469 -0
- package/dist/runtime/vendor/cel-js/lib/index.js +18 -0
- package/dist/runtime/vendor/cel-js/lib/macros.d.ts +1 -0
- package/dist/runtime/vendor/cel-js/lib/macros.js +230 -0
- package/dist/runtime/vendor/cel-js/lib/operators.d.ts +117 -0
- package/dist/runtime/vendor/cel-js/lib/operators.js +739 -0
- package/dist/runtime/vendor/cel-js/lib/optional.d.ts +14 -0
- package/dist/runtime/vendor/cel-js/lib/optional.js +161 -0
- package/dist/runtime/vendor/cel-js/lib/options.d.ts +23 -0
- package/dist/runtime/vendor/cel-js/lib/options.js +47 -0
- package/dist/runtime/vendor/cel-js/lib/overloads.d.ts +1 -0
- package/dist/runtime/vendor/cel-js/lib/overloads.js +214 -0
- package/dist/runtime/vendor/cel-js/lib/parser.d.ts +56 -0
- package/dist/runtime/vendor/cel-js/lib/parser.js +827 -0
- package/dist/runtime/vendor/cel-js/lib/registry.d.ts +279 -0
- package/dist/runtime/vendor/cel-js/lib/registry.js +1596 -0
- package/dist/runtime/vendor/cel-js/lib/serialize.d.ts +1 -0
- package/dist/runtime/vendor/cel-js/lib/serialize.js +259 -0
- package/dist/runtime/vendor/cel-js/lib/type-checker.d.ts +26 -0
- package/dist/runtime/vendor/cel-js/lib/type-checker.js +81 -0
- package/package.json +7 -4
- package/dist/runtime/components/locale.d.vue.ts +0 -14
- package/dist/runtime/components/locale.vue +0 -89
- package/dist/runtime/components/locale.vue.d.ts +0 -14
- package/dist/runtime/components/query.d.vue.ts +0 -30
- package/dist/runtime/components/query.vue +0 -266
- package/dist/runtime/components/query.vue.d.ts +0 -30
- package/dist/runtime/utilities/query-config/global.d.ts +0 -4
- package/dist/runtime/utilities/query-config/global.js +0 -18
- package/dist/runtime/utilities/query-config/index.d.ts +0 -3
- package/dist/runtime/utilities/query-config/index.js +0 -14
- package/dist/runtime/utilities/query-config/schema.d.ts +0 -96
- package/dist/runtime/utilities/query-config/schema.js +0 -51
|
@@ -0,0 +1,739 @@
|
|
|
1
|
+
import {celTypes} from './registry.js'
|
|
2
|
+
import {objKeys, isArray} from './globals.js'
|
|
3
|
+
const dynType = celTypes.dyn
|
|
4
|
+
|
|
5
|
+
export class Base {
|
|
6
|
+
dynType = celTypes.dyn
|
|
7
|
+
optionalType = celTypes.optional
|
|
8
|
+
stringType = celTypes.string
|
|
9
|
+
intType = celTypes.int
|
|
10
|
+
doubleType = celTypes.double
|
|
11
|
+
boolType = celTypes.bool
|
|
12
|
+
nullType = celTypes.null
|
|
13
|
+
listType = celTypes.list
|
|
14
|
+
mapType = celTypes.map
|
|
15
|
+
|
|
16
|
+
constructor(opts) {
|
|
17
|
+
this.opts = opts.opts
|
|
18
|
+
this.registry = opts.registry
|
|
19
|
+
this.objectTypes = this.registry.objectTypes
|
|
20
|
+
this.objectTypesByConstructor = this.registry.objectTypesByConstructor
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get a TypeDeclaration instance for a type name
|
|
25
|
+
* @param {string} typeName - The type name (e.g., 'string', 'int', 'dyn')
|
|
26
|
+
* @returns {TypeDeclaration} The type declaration instance
|
|
27
|
+
*/
|
|
28
|
+
getType(typeName) {
|
|
29
|
+
return this.registry.getType(typeName)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
debugType(v) {
|
|
33
|
+
switch (typeof v) {
|
|
34
|
+
case 'string':
|
|
35
|
+
return this.stringType
|
|
36
|
+
case 'bigint':
|
|
37
|
+
return this.intType
|
|
38
|
+
case 'number':
|
|
39
|
+
return this.doubleType
|
|
40
|
+
case 'boolean':
|
|
41
|
+
return this.boolType
|
|
42
|
+
case 'object':
|
|
43
|
+
if (v === null) return this.nullType
|
|
44
|
+
switch (v.constructor) {
|
|
45
|
+
case undefined:
|
|
46
|
+
case Object:
|
|
47
|
+
case Map:
|
|
48
|
+
return this.mapType
|
|
49
|
+
case Array:
|
|
50
|
+
case Set:
|
|
51
|
+
return this.listType
|
|
52
|
+
default:
|
|
53
|
+
return (
|
|
54
|
+
this.objectTypesByConstructor.get(v.constructor)?.type ||
|
|
55
|
+
unsupportedType(this, v.constructor?.name || typeof v)
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
default:
|
|
59
|
+
unsupportedType(this, typeof v)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function unsupportedType(self, type) {
|
|
65
|
+
throw new self.Error(`Unsupported type: ${type}`)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const maybeAsyncArray = (a) => (Array.isArray(a) ? a.some((n) => n.maybeAsync) : false)
|
|
69
|
+
|
|
70
|
+
function maybeAsync(l, r, h) {
|
|
71
|
+
if (r === true || (r && (r?.maybeAsync || maybeAsyncArray(r)))) return maybeAsyncBoth(h)
|
|
72
|
+
if (l === true || (l && (l?.maybeAsync || maybeAsyncArray(l)))) return maybeAsyncFirst(h)
|
|
73
|
+
return h
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function maybeAsyncBoth(handler) {
|
|
77
|
+
return (handler.__asyncBoth ??= function handle(a, b, c, d) {
|
|
78
|
+
if (!(a instanceof Promise || b instanceof Promise)) return handler(a, b, c, d)
|
|
79
|
+
if (!(b instanceof Promise)) return a.then((_a) => handler(_a, b, c, d))
|
|
80
|
+
if (!(a instanceof Promise)) return b.then((_b) => handler(a, _b, c, d))
|
|
81
|
+
return Promise.all([a, b]).then((p) => handler(p[0], p[1], c, d))
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function maybeAsyncFirst(handler) {
|
|
86
|
+
return (handler.__asyncFirst ??= function handle(a, b, c, d) {
|
|
87
|
+
if (a instanceof Promise) return a.then((_a) => handler(_a, b, c, d))
|
|
88
|
+
return handler(a, b, c, d)
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function checkAccessNode(chk, ast, ctx) {
|
|
93
|
+
ast.right = ast.args[1]
|
|
94
|
+
const leftType = chk.check((ast.left = ast.args[0]), ctx)
|
|
95
|
+
if (ast.op === '[]') chk.check(ast.right, ctx)
|
|
96
|
+
|
|
97
|
+
ast.handle = maybeAsync(
|
|
98
|
+
ast.left,
|
|
99
|
+
ast.op === '[]' ? ast.right : false,
|
|
100
|
+
leftType !== dynType ? fieldAccessStatic : fieldAccess
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if (leftType.kind !== 'optional') return chk.checkAccessOnType(ast, ctx, leftType)
|
|
104
|
+
return chk.registry.getOptionalType(chk.checkAccessOnType(ast, ctx, leftType.valueType, true))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function checkOptionalAccessNode(chk, ast, ctx) {
|
|
108
|
+
ast.right = ast.args[1]
|
|
109
|
+
const leftType = chk.check((ast.left = ast.args[0]), ctx)
|
|
110
|
+
if (ast.op === '[?]') chk.check(ast.right, ctx)
|
|
111
|
+
|
|
112
|
+
ast.handle = maybeAsync(ast.left, ast.op === '[?]' ? ast.right : false, oFieldAccess)
|
|
113
|
+
|
|
114
|
+
const actualType = leftType.kind === 'optional' ? leftType.valueType : leftType
|
|
115
|
+
return chk.registry.getOptionalType(chk.checkAccessOnType(ast, ctx, actualType, true))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function checkElementHomogenous(chk, ctx, expected, el, m) {
|
|
119
|
+
const type = chk.check(el, ctx)
|
|
120
|
+
if (type === expected || expected.isEmpty()) return type
|
|
121
|
+
if (type.isEmpty()) return expected
|
|
122
|
+
|
|
123
|
+
let prefix
|
|
124
|
+
if (m === 0) prefix = 'List elements must have the same type,'
|
|
125
|
+
else if (m === 1) prefix = 'Map key uses wrong type,'
|
|
126
|
+
else if (m === 2) prefix = 'Map value uses wrong type,'
|
|
127
|
+
throw new chk.Error(
|
|
128
|
+
`${prefix} expected type '${chk.formatType(expected)}' but found '${chk.formatType(type)}'`,
|
|
129
|
+
el
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function checkElement(chk, ctx, expected, el) {
|
|
134
|
+
return expected.unify(chk.registry, chk.check(el, ctx)) || dynType
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function ternaryConditionError(ev, value, node) {
|
|
138
|
+
const type = ev.debugRuntimeType(value)
|
|
139
|
+
return new ev.Error(`${node.meta.label || 'Ternary condition must be bool'}, got '${type}'`, node)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function handleTernary(c, ev, ast, ctx) {
|
|
143
|
+
if (c === true) return ev.eval(ast.left, ctx)
|
|
144
|
+
if (c === false) return ev.eval(ast.right, ctx)
|
|
145
|
+
throw ternaryConditionError(ev, c, ast.condition)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function logicalOperandError(ev, value, node) {
|
|
149
|
+
const type = ev.debugRuntimeType(value)
|
|
150
|
+
return new ev.Error(`Logical operator requires bool operands, got '${type}'`, node)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function logicalValueOrErr(ev, v, node) {
|
|
154
|
+
if (v instanceof Error) return v
|
|
155
|
+
return logicalOperandError(ev, v, node)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function _logicalOp(exp, ev, ast, left, right) {
|
|
159
|
+
if (right === exp) return exp
|
|
160
|
+
if (right === !exp) {
|
|
161
|
+
if (left === right) return right
|
|
162
|
+
throw logicalValueOrErr(ev, left, ast.left)
|
|
163
|
+
}
|
|
164
|
+
if (right instanceof Promise) return right.then((r) => _logicalOpAsync(exp, ev, ast, left, r))
|
|
165
|
+
throw logicalOperandError(ev, right, ast.left)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function _logicalOpAsync(exp, ev, ast, left, right) {
|
|
169
|
+
if (right === exp) return exp
|
|
170
|
+
if (typeof right !== 'boolean') throw logicalOperandError(ev, right, ast.right)
|
|
171
|
+
if (typeof left !== 'boolean') throw logicalValueOrErr(ev, left, ast.left)
|
|
172
|
+
return !exp
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function checkLogicalOp(chk, ast, ctx) {
|
|
176
|
+
const leftType = chk.check((ast.left = ast.args[0]), ctx)
|
|
177
|
+
const rightType = chk.check((ast.right = ast.args[1]), ctx)
|
|
178
|
+
|
|
179
|
+
if (!leftType.isDynOrBool()) {
|
|
180
|
+
throw new chk.Error(
|
|
181
|
+
`Logical operator requires bool operands, got '${chk.formatType(leftType)}'`,
|
|
182
|
+
ast
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
if (!rightType.isDynOrBool()) {
|
|
186
|
+
throw new chk.Error(
|
|
187
|
+
`Logical operator requires bool operands, got '${chk.formatType(rightType)}'`,
|
|
188
|
+
ast
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return chk.boolType
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function checkUnary(chk, ast, ctx) {
|
|
196
|
+
const op = ast.op
|
|
197
|
+
const right = chk.check(ast.args, ctx)
|
|
198
|
+
ast.candidates = chk.registry.operatorCandidates(op)
|
|
199
|
+
|
|
200
|
+
if (right.kind === 'dyn') {
|
|
201
|
+
ast.handle = maybeAsync(ast.args, false, handleUnary)
|
|
202
|
+
return ast.candidates.returnType
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const overload = ast.candidates.findUnaryOverload(right)
|
|
206
|
+
if (!overload) throw new chk.Error(`no such overload: ${op[0]}${chk.formatType(right)}`, ast)
|
|
207
|
+
|
|
208
|
+
ast.handle = maybeAsync(ast.args, false, overload.handler)
|
|
209
|
+
return overload.returnType
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function handleUnary(left, ast, ev) {
|
|
213
|
+
const leftType = ev.debugRuntimeType(left, ast.args.checkedType)
|
|
214
|
+
const overload = ast.candidates.findUnaryOverload(leftType)
|
|
215
|
+
if (overload) return overload.handler(left)
|
|
216
|
+
throw new ev.Error(`no such overload: ${ast.op[0]}${leftType}`, ast)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function evaluateUnary(ev, ast, ctx) {
|
|
220
|
+
return ast.handle(ev.eval(ast.args, ctx), ast, ev)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function checkBinary(chk, ast, ctx) {
|
|
224
|
+
const op = ast.op
|
|
225
|
+
const left = chk.check((ast.left = ast.args[0]), ctx)
|
|
226
|
+
const right = chk.check((ast.right = ast.args[1]), ctx)
|
|
227
|
+
ast.candidates = chk.registry.operatorCandidates(op)
|
|
228
|
+
|
|
229
|
+
const overload =
|
|
230
|
+
left.hasDynType || right.hasDynType ? undefined : ast.candidates.findBinaryOverload(left, right)
|
|
231
|
+
|
|
232
|
+
ast.handle = maybeAsync(ast.left, ast.right, overload?.handler || handleBinary)
|
|
233
|
+
if (overload) return overload.returnType
|
|
234
|
+
|
|
235
|
+
const type = ast.candidates.checkBinaryOverload(left, right)
|
|
236
|
+
if (!left.hasDynType) ast.leftStaticType = left
|
|
237
|
+
if (!right.hasDynType) ast.rightStaticType = right
|
|
238
|
+
if (type) return type
|
|
239
|
+
|
|
240
|
+
throw new chk.Error(
|
|
241
|
+
`no such overload: ${chk.formatType(left)} ${op} ${chk.formatType(right)}`,
|
|
242
|
+
ast
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function evaluateBinary(ev, ast, ctx) {
|
|
247
|
+
return ast.handle(ev.eval(ast.left, ctx), ev.eval(ast.right, ctx), ast, ev)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function evaluateBinaryFirst(ev, ast, ctx) {
|
|
251
|
+
return ast.handle(ev.eval(ast.left, ctx), ast.right, ast, ev)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function handleBinary(left, right, ast, ev) {
|
|
255
|
+
const leftType = ast.leftStaticType || ev.debugTypeDeep(left).wrappedType
|
|
256
|
+
const rightType = ast.rightStaticType || ev.debugTypeDeep(right).wrappedType
|
|
257
|
+
const overload = ast.candidates.findBinaryOverload(leftType, rightType)
|
|
258
|
+
if (overload) return overload.handler(left, right, ast, ev)
|
|
259
|
+
throw new ev.Error(`no such overload: ${leftType} ${ast.op} ${rightType}`, ast)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function callFn(args, ast, ev) {
|
|
263
|
+
const argAst = ast.args[1]
|
|
264
|
+
const types = ast.argTypes
|
|
265
|
+
let i = argAst.length
|
|
266
|
+
while (i--) types[i] = ev.debugRuntimeType(args[i], argAst[i].checkedType)
|
|
267
|
+
|
|
268
|
+
const decl = ast.candidates.findFunction(types)
|
|
269
|
+
if (decl) return decl.handler.apply(ev, args)
|
|
270
|
+
throw new ev.Error(
|
|
271
|
+
`found no matching overload for '${ast.args[0]}(${types
|
|
272
|
+
.map((t) => t.unwrappedType)
|
|
273
|
+
.join(', ')})'`,
|
|
274
|
+
ast
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function callRecFn(args, ev, ast) {
|
|
279
|
+
const [, receiverAst, argAst] = ast.args
|
|
280
|
+
const types = ast.argTypes
|
|
281
|
+
for (let i = 0; i < types.length; i++)
|
|
282
|
+
types[i] = ev.debugRuntimeType(args[i + 1], argAst[i].checkedType)
|
|
283
|
+
|
|
284
|
+
const receiverType = ev.debugRuntimeType(args[0], receiverAst.checkedType)
|
|
285
|
+
const decl = ast.candidates.findFunction(types, receiverType)
|
|
286
|
+
if (decl) return decl.handler.apply(ev, args)
|
|
287
|
+
|
|
288
|
+
throw new ev.Error(
|
|
289
|
+
`found no matching overload for '${receiverType.type}.${ast.args[0]}(${types
|
|
290
|
+
.map((t) => t.unwrappedType)
|
|
291
|
+
.join(', ')})'`,
|
|
292
|
+
ast
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function resolveAstArray(ev, astArray, ctx, i = astArray.length) {
|
|
297
|
+
if (i === 0) return []
|
|
298
|
+
|
|
299
|
+
let async
|
|
300
|
+
const results = new Array(i)
|
|
301
|
+
while (i--) if ((results[i] = ev.eval(astArray[i], ctx)) instanceof Promise) async ??= true
|
|
302
|
+
return async ? Promise.all(results) : results
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function safeFromEntries(entries) {
|
|
306
|
+
const obj = {}
|
|
307
|
+
for (let i = 0; i < entries.length; i++) {
|
|
308
|
+
const [k, v] = entries[i]
|
|
309
|
+
if (k === '__proto__' || k === 'constructor' || k === 'prototype') continue
|
|
310
|
+
obj[k] = v
|
|
311
|
+
}
|
|
312
|
+
return obj
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function comprehensionElementType(chk, iterable, ctx) {
|
|
316
|
+
const iterType = chk.check(iterable, ctx)
|
|
317
|
+
if (iterType.kind === 'dyn') return iterType
|
|
318
|
+
if (iterType.kind === 'list') return iterType.valueType
|
|
319
|
+
if (iterType.kind === 'map') return iterType.keyType
|
|
320
|
+
throw new chk.Error(
|
|
321
|
+
`Expression of type '${chk.formatType(
|
|
322
|
+
iterType
|
|
323
|
+
)}' cannot be range of a comprehension (must be list, map, or dynamic).`,
|
|
324
|
+
iterable
|
|
325
|
+
)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function toIterable(ev, args, coll) {
|
|
329
|
+
if (coll instanceof Set) return [...coll]
|
|
330
|
+
if (coll instanceof Map) return [...coll.keys()]
|
|
331
|
+
if (coll && typeof coll === 'object') return objKeys(coll)
|
|
332
|
+
throw new ev.Error(
|
|
333
|
+
`Expression of type '${ev.debugType(
|
|
334
|
+
coll
|
|
335
|
+
)}' cannot be range of a comprehension (must be list, map, or dynamic).`,
|
|
336
|
+
args.iterable
|
|
337
|
+
)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function runQualifier(items, args, ev, ctx) {
|
|
341
|
+
if (!isArray(items)) items = toIterable(ev, args, items)
|
|
342
|
+
const accu = ev.eval(args.init, (ctx = args.iterCtx.reuse(ctx)))
|
|
343
|
+
ctx.accuValue = accu
|
|
344
|
+
if (ctx === args.iterCtx) return iterateQuantifier(ev, ctx, args, items, accu, 0)
|
|
345
|
+
return continueQuantifier(ev, ctx, args, items, accu, 0)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function runComprehension(items, args, ev, ctx) {
|
|
349
|
+
if (!isArray(items)) items = toIterable(ev, args, items)
|
|
350
|
+
const accu = ev.eval(args.init, (ctx = args.iterCtx.reuse(ctx)))
|
|
351
|
+
ctx.accuValue = accu
|
|
352
|
+
if (ctx === args.iterCtx) return iterateLoop(ev, ctx, args, items, accu, 0)
|
|
353
|
+
return continueLoop(ev, ctx, args, items, accu, 0)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function iterateLoop(ev, ctx, args, items, accu, i) {
|
|
357
|
+
const condition = args.condition
|
|
358
|
+
const step = args.step
|
|
359
|
+
const len = items.length
|
|
360
|
+
while (i < len) {
|
|
361
|
+
if (condition && !condition(accu)) break
|
|
362
|
+
accu = ev.eval(step, ctx.setIterValue(items[i++], ev))
|
|
363
|
+
if (accu instanceof Promise) return continueLoop(ev, ctx, args, items, accu, i)
|
|
364
|
+
}
|
|
365
|
+
return args.result(accu)
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async function continueLoop(ev, ctx, args, items, accu, i) {
|
|
369
|
+
if (ctx === args.iterCtx) ctx.async = true
|
|
370
|
+
const condition = args.condition
|
|
371
|
+
const step = args.step
|
|
372
|
+
const len = items.length
|
|
373
|
+
accu = await accu
|
|
374
|
+
while (i < len) {
|
|
375
|
+
if (condition && !condition(accu)) return args.result(accu)
|
|
376
|
+
accu = ev.eval(step, ctx.setIterValue(items[i++], ev))
|
|
377
|
+
if (accu instanceof Promise) accu = await accu
|
|
378
|
+
}
|
|
379
|
+
return args.result(accu)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function iterateQuantifier(ev, ctx, args, items, accu, i, error, stp) {
|
|
383
|
+
const condition = args.condition
|
|
384
|
+
const step = args.step
|
|
385
|
+
const len = items.length
|
|
386
|
+
while (i < len) {
|
|
387
|
+
if (!condition(accu)) return args.result(accu)
|
|
388
|
+
stp = ev.tryEval(step, ctx.setIterValue(items[i++], ev))
|
|
389
|
+
if (stp instanceof Promise) return continueQuantifier(ev, ctx, args, items, accu, i, error, stp)
|
|
390
|
+
if (stp instanceof Error && (error ??= stp)) continue
|
|
391
|
+
accu = stp
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (error && condition(accu)) throw error
|
|
395
|
+
return args.result(accu)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
async function continueQuantifier(ev, ctx, args, items, accu, i, error, stp) {
|
|
399
|
+
if (ctx === args.iterCtx) ctx.async = true
|
|
400
|
+
const condition = args.condition
|
|
401
|
+
const step = args.step
|
|
402
|
+
const len = items.length
|
|
403
|
+
|
|
404
|
+
stp = await stp
|
|
405
|
+
if (stp instanceof Error) error ??= stp
|
|
406
|
+
else accu = stp
|
|
407
|
+
|
|
408
|
+
while (i < len) {
|
|
409
|
+
if (!condition(accu)) return args.result(accu)
|
|
410
|
+
stp = ev.tryEval(step, ctx.setIterValue(items[i++], ev))
|
|
411
|
+
if (stp instanceof Promise) stp = await stp
|
|
412
|
+
if (stp instanceof Error && (error ??= stp)) continue
|
|
413
|
+
accu = stp
|
|
414
|
+
}
|
|
415
|
+
if (error && condition(accu)) throw error
|
|
416
|
+
return args.result(accu)
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function oFieldAccess(left, right, ast, ev) {
|
|
420
|
+
return ev.optionalType.field(left, right, ast, ev)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function fieldAccessStatic(left, right, ast, ev) {
|
|
424
|
+
return ast.left.checkedType.field(left, right, ast, ev)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function fieldAccess(left, right, ast, ev) {
|
|
428
|
+
switch (left?.constructor) {
|
|
429
|
+
case undefined:
|
|
430
|
+
case Object:
|
|
431
|
+
case Map:
|
|
432
|
+
return ev.mapType.field(left, right, ast, ev)
|
|
433
|
+
case Array:
|
|
434
|
+
case Set:
|
|
435
|
+
return ev.listType.field(left, right, ast, ev)
|
|
436
|
+
default:
|
|
437
|
+
const t = ev.objectTypesByConstructor.get(left.constructor)
|
|
438
|
+
if (t) return t.type.field(left, right, ast, ev)
|
|
439
|
+
if (typeof left === 'object') unsupportedType(ev, left.constructor.name)
|
|
440
|
+
}
|
|
441
|
+
return ev.nullType.field(left, right, ast, ev)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const emptyList = () => []
|
|
445
|
+
const emptyMap = () => ({})
|
|
446
|
+
|
|
447
|
+
export const OPERATORS = {
|
|
448
|
+
value: {
|
|
449
|
+
check(chk, ast) {
|
|
450
|
+
return chk.debugType(ast.args)
|
|
451
|
+
},
|
|
452
|
+
evaluate(_ev, ast) {
|
|
453
|
+
return ast.args
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
id: {
|
|
457
|
+
check(chk, ast, ctx) {
|
|
458
|
+
const variable = ctx.getVariable(ast.args)
|
|
459
|
+
if (!variable) throw new chk.Error(`Unknown variable: ${ast.args}`, ast)
|
|
460
|
+
if (variable.constant) {
|
|
461
|
+
const alternate = ast.clone(OPERATORS.value, variable.value)
|
|
462
|
+
ast.setMeta('alternate', alternate)
|
|
463
|
+
return chk.check(alternate, ctx)
|
|
464
|
+
}
|
|
465
|
+
return variable.type
|
|
466
|
+
},
|
|
467
|
+
evaluate(ev, ast, ctx) {
|
|
468
|
+
return ctx.getCheckedValue(ev, ast)
|
|
469
|
+
}
|
|
470
|
+
},
|
|
471
|
+
'.': {
|
|
472
|
+
alias: 'fieldAccess',
|
|
473
|
+
check: checkAccessNode,
|
|
474
|
+
evaluate: evaluateBinaryFirst
|
|
475
|
+
},
|
|
476
|
+
'.?': {
|
|
477
|
+
alias: 'optionalFieldAccess',
|
|
478
|
+
check: checkOptionalAccessNode,
|
|
479
|
+
evaluate: evaluateBinaryFirst
|
|
480
|
+
},
|
|
481
|
+
'[]': {
|
|
482
|
+
alias: 'bracketAccess',
|
|
483
|
+
check: checkAccessNode,
|
|
484
|
+
evaluate: evaluateBinary
|
|
485
|
+
},
|
|
486
|
+
'[?]': {
|
|
487
|
+
alias: 'optionalBracketAccess',
|
|
488
|
+
check: checkOptionalAccessNode,
|
|
489
|
+
evaluate: evaluateBinary
|
|
490
|
+
},
|
|
491
|
+
call: {
|
|
492
|
+
check(chk, ast, ctx) {
|
|
493
|
+
const [functionName, args] = ast.args
|
|
494
|
+
const candidates = (ast.candidates = chk.registry.functionCandidates(
|
|
495
|
+
false,
|
|
496
|
+
functionName,
|
|
497
|
+
args.length
|
|
498
|
+
))
|
|
499
|
+
|
|
500
|
+
const argTypes = (ast.argTypes = args.map((a) => chk.check(a, ctx)))
|
|
501
|
+
const decl = candidates.findFunction(argTypes)
|
|
502
|
+
|
|
503
|
+
if (!decl) {
|
|
504
|
+
throw new chk.Error(
|
|
505
|
+
`found no matching overload for '${functionName}(${chk.formatTypeList(argTypes)})'`,
|
|
506
|
+
ast
|
|
507
|
+
)
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const handle = argTypes.some((t) => t.hasDynType)
|
|
511
|
+
? callFn
|
|
512
|
+
: (decl.handler.__handle ??= (l, _ast, e) => decl.handler.apply(e, l))
|
|
513
|
+
|
|
514
|
+
ast.handle = maybeAsync(args, false, handle)
|
|
515
|
+
return decl.returnType
|
|
516
|
+
},
|
|
517
|
+
evaluate(ev, ast, ctx) {
|
|
518
|
+
return ast.handle(resolveAstArray(ev, ast.args[1], ctx), ast, ev)
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
rcall: {
|
|
522
|
+
check(chk, ast, ctx) {
|
|
523
|
+
const [methodName, receiver, args] = ast.args
|
|
524
|
+
const receiverType = chk.check(receiver, ctx)
|
|
525
|
+
const candidates = (ast.candidates = chk.registry.functionCandidates(
|
|
526
|
+
true,
|
|
527
|
+
methodName,
|
|
528
|
+
args.length
|
|
529
|
+
))
|
|
530
|
+
|
|
531
|
+
const argTypes = (ast.argTypes = args.map((a) => chk.check(a, ctx)))
|
|
532
|
+
ast.receiverWithArgs = [receiver, ...args]
|
|
533
|
+
ast.handle = maybeAsync(ast.receiverWithArgs, false, callRecFn)
|
|
534
|
+
|
|
535
|
+
if (receiverType.kind === 'dyn' && candidates.returnType) return candidates.returnType
|
|
536
|
+
const decl = candidates.findFunction(argTypes, receiverType)
|
|
537
|
+
|
|
538
|
+
if (!decl) {
|
|
539
|
+
throw new chk.Error(
|
|
540
|
+
`found no matching overload for '${receiverType.type}.${methodName}(${chk.formatTypeList(
|
|
541
|
+
argTypes
|
|
542
|
+
)})'`,
|
|
543
|
+
ast
|
|
544
|
+
)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (!receiverType.hasPlaceholderType && !argTypes.some((t) => t.hasDynType)) {
|
|
548
|
+
const handler = decl.handler
|
|
549
|
+
const handle = (handler.__handle ??= (a, ev) => handler.apply(ev, a))
|
|
550
|
+
ast.handle = maybeAsync(ast.receiverWithArgs, false, handle)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
return decl.returnType
|
|
554
|
+
},
|
|
555
|
+
evaluate(ev, ast, ctx) {
|
|
556
|
+
return ast.handle(resolveAstArray(ev, ast.receiverWithArgs, ctx), ev, ast)
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
list: {
|
|
560
|
+
check(chk, ast, ctx) {
|
|
561
|
+
const arr = ast.args
|
|
562
|
+
const arrLen = arr.length
|
|
563
|
+
if (arrLen === 0) return ast.setMeta('evaluate', emptyList) && chk.getType('list<T>')
|
|
564
|
+
|
|
565
|
+
let valueType = chk.check(arr[0], ctx)
|
|
566
|
+
const check = chk.opts.homogeneousAggregateLiterals ? checkElementHomogenous : checkElement
|
|
567
|
+
|
|
568
|
+
for (let i = 1; i < arrLen; i++) valueType = check(chk, ctx, valueType, arr[i], 0)
|
|
569
|
+
return chk.registry.getListType(valueType)
|
|
570
|
+
},
|
|
571
|
+
evaluate(ev, ast, ctx) {
|
|
572
|
+
return resolveAstArray(ev, ast.args, ctx)
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
map: {
|
|
576
|
+
check(chk, ast, ctx) {
|
|
577
|
+
const arr = ast.args
|
|
578
|
+
const arrLen = arr.length
|
|
579
|
+
if (arrLen === 0) return ast.setMeta('evaluate', emptyMap) && chk.getType('map<K, V>')
|
|
580
|
+
|
|
581
|
+
const check = chk.opts.homogeneousAggregateLiterals ? checkElementHomogenous : checkElement
|
|
582
|
+
let keyType = chk.check(arr[0][0], ctx)
|
|
583
|
+
let valueType = chk.check(arr[0][1], ctx)
|
|
584
|
+
for (let i = 1; i < arrLen; i++) {
|
|
585
|
+
const e = arr[i]
|
|
586
|
+
keyType = check(chk, ctx, keyType, e[0], 1)
|
|
587
|
+
valueType = check(chk, ctx, valueType, e[1], 2)
|
|
588
|
+
}
|
|
589
|
+
return chk.registry.getMapType(keyType, valueType)
|
|
590
|
+
},
|
|
591
|
+
evaluate(ev, ast, ctx) {
|
|
592
|
+
const astEntries = ast.args
|
|
593
|
+
const len = astEntries.length
|
|
594
|
+
const results = new Array(len)
|
|
595
|
+
let async
|
|
596
|
+
for (let i = 0; i < len; i++) {
|
|
597
|
+
const e = astEntries[i]
|
|
598
|
+
const k = ev.eval(e[0], ctx)
|
|
599
|
+
const v = ev.eval(e[1], ctx)
|
|
600
|
+
if (k instanceof Promise || v instanceof Promise) {
|
|
601
|
+
results[i] = Promise.all([k, v])
|
|
602
|
+
async ??= true
|
|
603
|
+
} else {
|
|
604
|
+
results[i] = [k, v]
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
if (async) return Promise.all(results).then(safeFromEntries)
|
|
608
|
+
return safeFromEntries(results)
|
|
609
|
+
}
|
|
610
|
+
},
|
|
611
|
+
comprehension: {
|
|
612
|
+
check(chk, ast, ctx) {
|
|
613
|
+
const args = ast.args
|
|
614
|
+
args.iterCtx = ctx
|
|
615
|
+
.forkWithVariable(args.iterVarName, comprehensionElementType(chk, args.iterable, ctx))
|
|
616
|
+
.setAccuType(chk.check(args.init, ctx))
|
|
617
|
+
|
|
618
|
+
const stepType = chk.check(args.step, args.iterCtx)
|
|
619
|
+
const handler = args.errorsAreFatal ? runComprehension : runQualifier
|
|
620
|
+
ast.handle = maybeAsync(args.iterable, false, handler)
|
|
621
|
+
if (args.kind === 'quantifier') return chk.boolType
|
|
622
|
+
return stepType
|
|
623
|
+
},
|
|
624
|
+
evaluate(ev, ast, ctx) {
|
|
625
|
+
return ast.handle(ev.eval(ast.args.iterable, ctx), ast.args, ev, ctx)
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
accuValue: {
|
|
629
|
+
check(_chk, _ast, ctx) {
|
|
630
|
+
return ctx.accuType
|
|
631
|
+
},
|
|
632
|
+
evaluate(_ev, _ast, ctx) {
|
|
633
|
+
return ctx.accuValue
|
|
634
|
+
}
|
|
635
|
+
},
|
|
636
|
+
accuInc: {
|
|
637
|
+
check(_chk, _ast, ctx) {
|
|
638
|
+
return ctx.accuType
|
|
639
|
+
},
|
|
640
|
+
evaluate(_ev, _ast, ctx) {
|
|
641
|
+
return (ctx.accuValue += 1)
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
accuPush: {
|
|
645
|
+
check(chk, ast, ctx) {
|
|
646
|
+
const listType = ctx.accuType
|
|
647
|
+
const itemType = chk.check(ast.args, ctx)
|
|
648
|
+
if (!ast.args.maybeAsync) ast.setMeta('evaluate', OPERATORS.accuPush.evaluateSync)
|
|
649
|
+
if (listType.kind === 'list' && listType.valueType.kind !== 'param') return listType
|
|
650
|
+
return chk.registry.getListType(itemType)
|
|
651
|
+
},
|
|
652
|
+
evaluateSync(ev, ast, ctx) {
|
|
653
|
+
return (ctx.accuValue.push(ev.eval(ast.args, ctx)), ctx.accuValue)
|
|
654
|
+
},
|
|
655
|
+
evaluate(ev, ast, ctx) {
|
|
656
|
+
const arr = ctx.accuValue
|
|
657
|
+
const el = ev.eval(ast.args, ctx)
|
|
658
|
+
if (el instanceof Promise) return el.then((_e) => arr.push(_e) && arr)
|
|
659
|
+
arr.push(el)
|
|
660
|
+
return arr
|
|
661
|
+
}
|
|
662
|
+
},
|
|
663
|
+
'?:': {
|
|
664
|
+
alias: 'ternary',
|
|
665
|
+
check(chk, ast, ctx) {
|
|
666
|
+
const condast = (ast.condition = ast.args[0])
|
|
667
|
+
const leftast = (ast.left = ast.args[1])
|
|
668
|
+
const rightast = (ast.right = ast.args[2])
|
|
669
|
+
const condType = chk.check(condast, ctx)
|
|
670
|
+
if (!condType.isDynOrBool()) {
|
|
671
|
+
throw new chk.Error(
|
|
672
|
+
`${condast.meta.label || 'Ternary condition must be bool'}, got '${chk.formatType(condType)}'`,
|
|
673
|
+
condast
|
|
674
|
+
)
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const leftType = chk.check(leftast, ctx)
|
|
678
|
+
const rightType = chk.check(rightast, ctx)
|
|
679
|
+
const unified = leftType.unify(chk.registry, rightType)
|
|
680
|
+
|
|
681
|
+
ast.handle = maybeAsync(condast, false, handleTernary)
|
|
682
|
+
if (unified) return unified
|
|
683
|
+
|
|
684
|
+
throw new chk.Error(
|
|
685
|
+
`Ternary branches must have the same type, got '${chk.formatType(
|
|
686
|
+
leftType
|
|
687
|
+
)}' and '${chk.formatType(rightType)}'`,
|
|
688
|
+
ast
|
|
689
|
+
)
|
|
690
|
+
},
|
|
691
|
+
evaluate(ev, ast, ctx) {
|
|
692
|
+
return ast.handle(ev.eval(ast.condition, ctx), ev, ast, ctx)
|
|
693
|
+
}
|
|
694
|
+
},
|
|
695
|
+
'||': {
|
|
696
|
+
check: checkLogicalOp,
|
|
697
|
+
evaluate(ev, ast, ctx) {
|
|
698
|
+
const l = ev.tryEval(ast.left, ctx)
|
|
699
|
+
if (l === true) return true
|
|
700
|
+
if (l === false) {
|
|
701
|
+
const right = ev.eval(ast.right, ctx)
|
|
702
|
+
if (typeof right === 'boolean') return right
|
|
703
|
+
return _logicalOp(true, ev, ast, l, right)
|
|
704
|
+
}
|
|
705
|
+
if (l instanceof Promise)
|
|
706
|
+
return l.then((_l) =>
|
|
707
|
+
_l === true ? _l : _logicalOp(true, ev, ast, _l, ev.eval(ast.right, ctx))
|
|
708
|
+
)
|
|
709
|
+
return _logicalOp(true, ev, ast, l, ev.eval(ast.right, ctx))
|
|
710
|
+
}
|
|
711
|
+
},
|
|
712
|
+
'&&': {
|
|
713
|
+
check: checkLogicalOp,
|
|
714
|
+
evaluate(ev, ast, ctx) {
|
|
715
|
+
const l = ev.tryEval(ast.left, ctx)
|
|
716
|
+
if (l === false) return false
|
|
717
|
+
if (l === true) {
|
|
718
|
+
const right = ev.eval(ast.right, ctx)
|
|
719
|
+
if (typeof right === 'boolean') return right
|
|
720
|
+
return _logicalOp(false, ev, ast, l, right)
|
|
721
|
+
}
|
|
722
|
+
if (l instanceof Promise)
|
|
723
|
+
return l.then((_l) =>
|
|
724
|
+
_l === false ? _l : _logicalOp(false, ev, ast, _l, ev.eval(ast.right, ctx))
|
|
725
|
+
)
|
|
726
|
+
return _logicalOp(false, ev, ast, l, ev.eval(ast.right, ctx))
|
|
727
|
+
}
|
|
728
|
+
},
|
|
729
|
+
'!_': {alias: 'unaryNot', check: checkUnary, evaluate: evaluateUnary},
|
|
730
|
+
'-_': {alias: 'unaryMinus', check: checkUnary, evaluate: evaluateUnary}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
const binaryOperators = ['!=', '==', 'in', '+', '-', '*', '/', '%', '<', '<=', '>', '>=']
|
|
734
|
+
for (const op of binaryOperators) OPERATORS[op] = {check: checkBinary, evaluate: evaluateBinary}
|
|
735
|
+
for (const op of objKeys(OPERATORS)) {
|
|
736
|
+
const obj = OPERATORS[op]
|
|
737
|
+
obj.name = op
|
|
738
|
+
if (obj.alias) OPERATORS[obj.alias] = obj
|
|
739
|
+
}
|