ol 8.1.1-dev.1694687206621 → 8.1.1-dev.1694712969002
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/ol.js +2 -2
- package/dist/ol.js.map +1 -1
- package/expr/cpu.js +2 -8
- package/expr/expression.d.ts +18 -3
- package/expr/expression.d.ts.map +1 -1
- package/expr/expression.js +420 -59
- package/package.json +1 -1
- package/render/webgl/MixedGeometryBatch.d.ts +51 -3
- package/render/webgl/MixedGeometryBatch.d.ts.map +1 -1
- package/render/webgl/MixedGeometryBatch.js +145 -42
- package/render/webgl/VectorStyleRenderer.d.ts +16 -5
- package/render/webgl/VectorStyleRenderer.d.ts.map +1 -1
- package/render/webgl/VectorStyleRenderer.js +29 -7
- package/render/webgl/constants.d.ts +2 -2
- package/render/webgl/constants.js +2 -2
- package/render/webgl/renderinstructions.js +1 -1
- package/renderer/webgl/PointsLayer.d.ts +0 -7
- package/renderer/webgl/PointsLayer.d.ts.map +1 -1
- package/renderer/webgl/PointsLayer.js +9 -34
- package/renderer/webgl/VectorLayer.d.ts +26 -18
- package/renderer/webgl/VectorLayer.d.ts.map +1 -1
- package/renderer/webgl/VectorLayer.js +104 -38
- package/renderer/webgl/VectorTileLayer.d.ts +12 -0
- package/renderer/webgl/VectorTileLayer.d.ts.map +1 -1
- package/renderer/webgl/VectorTileLayer.js +10 -1
- package/renderer/webgl/worldUtil.d.ts +8 -0
- package/renderer/webgl/worldUtil.d.ts.map +1 -0
- package/renderer/webgl/worldUtil.js +27 -0
- package/util.js +1 -1
- package/webgl/ShaderBuilder.d.ts.map +1 -1
- package/webgl/ShaderBuilder.js +1 -0
package/expr/cpu.js
CHANGED
|
@@ -187,14 +187,8 @@ function compileAssertionExpression(expression, context) {
|
|
|
187
187
|
* @return {ExpressionEvaluator} The evaluator function.
|
|
188
188
|
*/
|
|
189
189
|
function compileAccessorExpression(expression, context) {
|
|
190
|
-
const nameExpression = expression.args[0];
|
|
191
|
-
|
|
192
|
-
throw new Error('Expected literal name');
|
|
193
|
-
}
|
|
194
|
-
const name = nameExpression.value;
|
|
195
|
-
if (typeof name !== 'string') {
|
|
196
|
-
throw new Error('Expected string name');
|
|
197
|
-
}
|
|
190
|
+
const nameExpression = /** @type {LiteralExpression} */ (expression.args[0]);
|
|
191
|
+
const name = /** @type {string} */ (nameExpression.value);
|
|
198
192
|
switch (expression.operator) {
|
|
199
193
|
case Ops.Get: {
|
|
200
194
|
return (context) => context.properties[name];
|
package/expr/expression.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export function isType(type: number, expected: number): boolean;
|
|
|
29
29
|
* @typedef {Object} ParsingContext
|
|
30
30
|
* @property {Set<string>} variables Variables referenced with the 'var' operator.
|
|
31
31
|
* @property {Set<string>} properties Properties referenced with the 'get' operator.
|
|
32
|
+
* @property {import("../style/literal").LiteralStyle} style The style being parsed
|
|
32
33
|
*/
|
|
33
34
|
/**
|
|
34
35
|
* @return {ParsingContext} A new parsing context.
|
|
@@ -40,9 +41,10 @@ export function newParsingContext(): ParsingContext;
|
|
|
40
41
|
/**
|
|
41
42
|
* @param {EncodedExpression} encoded The encoded expression.
|
|
42
43
|
* @param {ParsingContext} context The parsing context.
|
|
44
|
+
* @param {number} [typeHint] Optional type hint
|
|
43
45
|
* @return {Expression} The parsed expression result.
|
|
44
46
|
*/
|
|
45
|
-
export function parse(encoded: EncodedExpression, context: ParsingContext): Expression;
|
|
47
|
+
export function parse(encoded: EncodedExpression, context: ParsingContext, typeHint?: number | undefined): Expression;
|
|
46
48
|
export const NoneType: 0;
|
|
47
49
|
export const BooleanType: number;
|
|
48
50
|
export const NumberType: number;
|
|
@@ -89,9 +91,22 @@ export type ParsingContext = {
|
|
|
89
91
|
* Properties referenced with the 'get' operator.
|
|
90
92
|
*/
|
|
91
93
|
properties: Set<string>;
|
|
94
|
+
/**
|
|
95
|
+
* The style being parsed
|
|
96
|
+
*/
|
|
97
|
+
style: import("../style/literal").LiteralStyle;
|
|
92
98
|
};
|
|
93
99
|
export type EncodedExpression = LiteralValue | any[];
|
|
94
|
-
|
|
100
|
+
/**
|
|
101
|
+
* An argument validator applies various checks to an encoded expression arguments
|
|
102
|
+
* Returns the parsed arguments if any.
|
|
103
|
+
* Third argument is the array of parsed arguments from previous validators
|
|
104
|
+
* Fourth argument is an optional type hint
|
|
105
|
+
*/
|
|
106
|
+
export type ArgValidator = (arg0: Array<EncodedExpression>, arg1: ParsingContext, arg2: Array<Expression>, arg3: number | null) => Array<Expression> | void;
|
|
95
107
|
export type LiteralValue = boolean | number | string | Array<number>;
|
|
96
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Third argument is a type hint
|
|
110
|
+
*/
|
|
111
|
+
export type Parser = (arg0: any[], arg1: ParsingContext, arg2: number) => Expression;
|
|
97
112
|
//# sourceMappingURL=expression.d.ts.map
|
package/expr/expression.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["expression.js"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,+BAHW,MAAM,GACL,MAAM,CAgBjB;AAED;;;;GAIG;AACH,oCAJW,MAAM,YACN,MAAM,GACL,OAAO,CAIlB;AAED;;;;GAIG;AACH,sCAJW,MAAM,aACN,MAAM,GACL,OAAO,CAIlB;AAED;;;;GAIG;AACH,6BAJW,MAAM,YACN,MAAM,GACL,OAAO,CAIlB;AA8BD;;GAEG;AAEH
|
|
1
|
+
{"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["expression.js"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,+BAHW,MAAM,GACL,MAAM,CAgBjB;AAED;;;;GAIG;AACH,oCAJW,MAAM,YACN,MAAM,GACL,OAAO,CAIlB;AAED;;;;GAIG;AACH,sCAJW,MAAM,aACN,MAAM,GACL,OAAO,CAIlB;AAED;;;;GAIG;AACH,6BAJW,MAAM,YACN,MAAM,GACL,OAAO,CAIlB;AA8BD;;GAEG;AAEH;;;;;GAKG;AAEH;;GAEG;AACH,qCAFY,cAAc,CAQzB;AAED;;GAEG;AAEH;;;;;GAKG;AACH,+BALW,iBAAiB,WACjB,cAAc,kCAEb,UAAU,CA8CrB;AA1KD,yBAA0B;AAC1B,iCAA2C;AAC3C,gCAA0C;AAC1C,gCAA0C;AAC1C,+BAAyC;AACzC,qCAA+C;AAC/C,6BAAiD;AA4DjD;;GAEG;AAEH;IACE;;;OAGG;IACH,kBAHW,MAAM,SACN,YAAY,EAKtB;IAFC,aAAgB;IAChB,oBAAkB;CAErB;AAED;IACE;;;;OAIG;IACH,kBAJW,MAAM,YACN,MAAM,WACH,UAAU,IAMvB;IAHC,aAAgB;IAChB,iBAAwB;IACxB,mBAAgB;CAEnB;AAgFD;;GAEG;AACH;QAFiB,MAAM,GAAE,MAAM;EA0C7B;yBAxHW,iBAAiB,GAAC,cAAc;;;;;eAK/B,IAAI,MAAM,CAAC;;;;gBACX,IAAI,MAAM,CAAC;;;;WACX,OAAO,kBAAkB,EAAE,YAAY;;gCAexC,YAAY,QAAM;;;;;;;kCA2TT,MAAM,iBAAiB,CAAC,QAAE,cAAc,QAAE,MAAM,UAAU,CAAC,QAAE,MAAM,YAAG,MAAM,UAAU,CAAC,GAAC,IAAI;2BA7WrG,OAAO,GAAC,MAAM,GAAC,MAAM,GAAC,MAAM,MAAM,CAAC;;;;yCAuJnB,cAAc,QAAE,MAAM,KAAE,UAAU"}
|
package/expr/expression.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module ol/expr/expression
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
4
|
import {ascending} from '../array.js';
|
|
5
|
+
import {isStringColor} from '../color.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @fileoverview This module includes types and functions for parsing array encoded expressions.
|
|
@@ -114,6 +114,7 @@ export class CallExpression {
|
|
|
114
114
|
* @typedef {Object} ParsingContext
|
|
115
115
|
* @property {Set<string>} variables Variables referenced with the 'var' operator.
|
|
116
116
|
* @property {Set<string>} properties Properties referenced with the 'get' operator.
|
|
117
|
+
* @property {import("../style/literal").LiteralStyle} style The style being parsed
|
|
117
118
|
*/
|
|
118
119
|
|
|
119
120
|
/**
|
|
@@ -123,6 +124,7 @@ export function newParsingContext() {
|
|
|
123
124
|
return {
|
|
124
125
|
variables: new Set(),
|
|
125
126
|
properties: new Set(),
|
|
127
|
+
style: {},
|
|
126
128
|
};
|
|
127
129
|
}
|
|
128
130
|
|
|
@@ -133,9 +135,10 @@ export function newParsingContext() {
|
|
|
133
135
|
/**
|
|
134
136
|
* @param {EncodedExpression} encoded The encoded expression.
|
|
135
137
|
* @param {ParsingContext} context The parsing context.
|
|
138
|
+
* @param {number} [typeHint] Optional type hint
|
|
136
139
|
* @return {Expression} The parsed expression result.
|
|
137
140
|
*/
|
|
138
|
-
export function parse(encoded, context) {
|
|
141
|
+
export function parse(encoded, context, typeHint) {
|
|
139
142
|
switch (typeof encoded) {
|
|
140
143
|
case 'boolean': {
|
|
141
144
|
return new LiteralExpression(BooleanType, encoded);
|
|
@@ -144,7 +147,11 @@ export function parse(encoded, context) {
|
|
|
144
147
|
return new LiteralExpression(NumberType, encoded);
|
|
145
148
|
}
|
|
146
149
|
case 'string': {
|
|
147
|
-
|
|
150
|
+
let type = StringType;
|
|
151
|
+
if (isStringColor(encoded)) {
|
|
152
|
+
type |= ColorType;
|
|
153
|
+
}
|
|
154
|
+
return new LiteralExpression(type, encoded);
|
|
148
155
|
}
|
|
149
156
|
default: {
|
|
150
157
|
// pass
|
|
@@ -160,7 +167,7 @@ export function parse(encoded, context) {
|
|
|
160
167
|
}
|
|
161
168
|
|
|
162
169
|
if (typeof encoded[0] === 'string') {
|
|
163
|
-
return parseCallExpression(encoded, context);
|
|
170
|
+
return parseCallExpression(encoded, context, typeHint);
|
|
164
171
|
}
|
|
165
172
|
|
|
166
173
|
for (const item of encoded) {
|
|
@@ -181,14 +188,15 @@ export function parse(encoded, context) {
|
|
|
181
188
|
* @type {Object<string, string>}
|
|
182
189
|
*/
|
|
183
190
|
export const Ops = {
|
|
184
|
-
Number: 'number',
|
|
185
|
-
String: 'string',
|
|
186
191
|
Get: 'get',
|
|
187
192
|
Var: 'var',
|
|
193
|
+
GeometryType: 'geometry-type',
|
|
188
194
|
Any: 'any',
|
|
189
195
|
All: 'all',
|
|
190
196
|
Not: '!',
|
|
191
197
|
Resolution: 'resolution',
|
|
198
|
+
Zoom: 'zoom',
|
|
199
|
+
Time: 'time',
|
|
192
200
|
Equal: '==',
|
|
193
201
|
NotEqual: '!=',
|
|
194
202
|
GreaterThan: '>',
|
|
@@ -211,65 +219,242 @@ export const Ops = {
|
|
|
211
219
|
Atan: 'atan',
|
|
212
220
|
Sqrt: 'sqrt',
|
|
213
221
|
Match: 'match',
|
|
222
|
+
Between: 'between',
|
|
223
|
+
Interpolate: 'interpolate',
|
|
224
|
+
Case: 'case',
|
|
225
|
+
In: 'in',
|
|
226
|
+
Number: 'number',
|
|
227
|
+
String: 'string',
|
|
228
|
+
Array: 'array',
|
|
229
|
+
Color: 'color',
|
|
214
230
|
};
|
|
215
231
|
|
|
216
232
|
/**
|
|
217
|
-
* @typedef {function(Array, ParsingContext):Expression} Parser
|
|
233
|
+
* @typedef {function(Array, ParsingContext, number):Expression} Parser
|
|
234
|
+
* Third argument is a type hint
|
|
218
235
|
*/
|
|
219
236
|
|
|
220
237
|
/**
|
|
221
238
|
* @type {Object<string, Parser>}
|
|
222
239
|
*/
|
|
223
240
|
const parsers = {
|
|
224
|
-
[Ops.
|
|
225
|
-
[Ops.
|
|
226
|
-
[Ops.
|
|
227
|
-
[Ops.
|
|
228
|
-
[Ops.
|
|
229
|
-
[Ops.
|
|
230
|
-
[Ops.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
241
|
+
[Ops.Get]: createParser(AnyType, withArgsCount(1, 1), withGetArgs),
|
|
242
|
+
[Ops.Var]: createParser(AnyType, withArgsCount(1, 1), withVarArgs),
|
|
243
|
+
[Ops.GeometryType]: createParser(StringType, withNoArgs),
|
|
244
|
+
[Ops.Resolution]: createParser(NumberType, withNoArgs),
|
|
245
|
+
[Ops.Zoom]: createParser(NumberType, withNoArgs),
|
|
246
|
+
[Ops.Time]: createParser(NumberType, withNoArgs),
|
|
247
|
+
[Ops.Any]: createParser(
|
|
248
|
+
BooleanType,
|
|
249
|
+
withArgsCount(2, Infinity),
|
|
250
|
+
parseArgsOfType(BooleanType)
|
|
251
|
+
),
|
|
252
|
+
[Ops.All]: createParser(
|
|
253
|
+
BooleanType,
|
|
254
|
+
withArgsCount(2, Infinity),
|
|
255
|
+
parseArgsOfType(BooleanType)
|
|
256
|
+
),
|
|
257
|
+
[Ops.Not]: createParser(
|
|
258
|
+
BooleanType,
|
|
259
|
+
withArgsCount(1, 1),
|
|
260
|
+
parseArgsOfType(BooleanType)
|
|
261
|
+
),
|
|
262
|
+
[Ops.Equal]: createParser(
|
|
263
|
+
BooleanType,
|
|
264
|
+
withArgsCount(2, 2),
|
|
265
|
+
parseArgsOfType(AnyType),
|
|
266
|
+
narrowArgsType
|
|
267
|
+
),
|
|
268
|
+
[Ops.NotEqual]: createParser(
|
|
269
|
+
BooleanType,
|
|
270
|
+
withArgsCount(2, 2),
|
|
271
|
+
parseArgsOfType(AnyType),
|
|
272
|
+
narrowArgsType
|
|
273
|
+
),
|
|
274
|
+
[Ops.GreaterThan]: createParser(
|
|
275
|
+
BooleanType,
|
|
276
|
+
withArgsCount(2, 2),
|
|
277
|
+
parseArgsOfType(AnyType),
|
|
278
|
+
narrowArgsType
|
|
279
|
+
),
|
|
235
280
|
[Ops.GreaterThanOrEqualTo]: createParser(
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
[Ops.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
[Ops.
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
[Ops.
|
|
254
|
-
|
|
255
|
-
|
|
281
|
+
BooleanType,
|
|
282
|
+
withArgsCount(2, 2),
|
|
283
|
+
parseArgsOfType(AnyType),
|
|
284
|
+
narrowArgsType
|
|
285
|
+
),
|
|
286
|
+
[Ops.LessThan]: createParser(
|
|
287
|
+
BooleanType,
|
|
288
|
+
withArgsCount(2, 2),
|
|
289
|
+
parseArgsOfType(AnyType),
|
|
290
|
+
narrowArgsType
|
|
291
|
+
),
|
|
292
|
+
[Ops.LessThanOrEqualTo]: createParser(
|
|
293
|
+
BooleanType,
|
|
294
|
+
withArgsCount(2, 2),
|
|
295
|
+
parseArgsOfType(AnyType),
|
|
296
|
+
narrowArgsType
|
|
297
|
+
),
|
|
298
|
+
[Ops.Multiply]: createParser(
|
|
299
|
+
(parsedArgs) => {
|
|
300
|
+
let outputType = NumberType | ColorType;
|
|
301
|
+
for (let i = 0; i < parsedArgs.length; i++) {
|
|
302
|
+
outputType &= parsedArgs[i].type;
|
|
303
|
+
}
|
|
304
|
+
return outputType;
|
|
305
|
+
},
|
|
306
|
+
withArgsCount(2, Infinity),
|
|
307
|
+
parseArgsOfType(NumberType | ColorType),
|
|
308
|
+
narrowArgsType
|
|
309
|
+
),
|
|
310
|
+
[Ops.Divide]: createParser(
|
|
311
|
+
NumberType,
|
|
312
|
+
withArgsCount(2, 2),
|
|
313
|
+
parseArgsOfType(NumberType)
|
|
314
|
+
),
|
|
315
|
+
[Ops.Add]: createParser(
|
|
316
|
+
NumberType,
|
|
317
|
+
withArgsCount(2, Infinity),
|
|
318
|
+
parseArgsOfType(NumberType)
|
|
319
|
+
),
|
|
320
|
+
[Ops.Subtract]: createParser(
|
|
321
|
+
NumberType,
|
|
322
|
+
withArgsCount(2, 2),
|
|
323
|
+
parseArgsOfType(NumberType)
|
|
324
|
+
),
|
|
325
|
+
[Ops.Clamp]: createParser(
|
|
326
|
+
NumberType,
|
|
327
|
+
withArgsCount(3, 3),
|
|
328
|
+
parseArgsOfType(NumberType)
|
|
329
|
+
),
|
|
330
|
+
[Ops.Mod]: createParser(
|
|
331
|
+
NumberType,
|
|
332
|
+
withArgsCount(2, 2),
|
|
333
|
+
parseArgsOfType(NumberType)
|
|
334
|
+
),
|
|
335
|
+
[Ops.Pow]: createParser(
|
|
336
|
+
NumberType,
|
|
337
|
+
withArgsCount(2, 2),
|
|
338
|
+
parseArgsOfType(NumberType)
|
|
339
|
+
),
|
|
340
|
+
[Ops.Abs]: createParser(
|
|
341
|
+
NumberType,
|
|
342
|
+
withArgsCount(1, 1),
|
|
343
|
+
parseArgsOfType(NumberType)
|
|
344
|
+
),
|
|
345
|
+
[Ops.Floor]: createParser(
|
|
346
|
+
NumberType,
|
|
347
|
+
withArgsCount(1, 1),
|
|
348
|
+
parseArgsOfType(NumberType)
|
|
349
|
+
),
|
|
350
|
+
[Ops.Ceil]: createParser(
|
|
351
|
+
NumberType,
|
|
352
|
+
withArgsCount(1, 1),
|
|
353
|
+
parseArgsOfType(NumberType)
|
|
354
|
+
),
|
|
355
|
+
[Ops.Round]: createParser(
|
|
356
|
+
NumberType,
|
|
357
|
+
withArgsCount(1, 1),
|
|
358
|
+
parseArgsOfType(NumberType)
|
|
359
|
+
),
|
|
360
|
+
[Ops.Sin]: createParser(
|
|
361
|
+
NumberType,
|
|
362
|
+
withArgsCount(1, 1),
|
|
363
|
+
parseArgsOfType(NumberType)
|
|
364
|
+
),
|
|
365
|
+
[Ops.Cos]: createParser(
|
|
366
|
+
NumberType,
|
|
367
|
+
withArgsCount(1, 1),
|
|
368
|
+
parseArgsOfType(NumberType)
|
|
369
|
+
),
|
|
370
|
+
[Ops.Atan]: createParser(
|
|
371
|
+
NumberType,
|
|
372
|
+
withArgsCount(1, 2),
|
|
373
|
+
parseArgsOfType(NumberType)
|
|
374
|
+
),
|
|
375
|
+
[Ops.Sqrt]: createParser(
|
|
376
|
+
NumberType,
|
|
377
|
+
withArgsCount(1, 1),
|
|
378
|
+
parseArgsOfType(NumberType)
|
|
379
|
+
),
|
|
256
380
|
[Ops.Match]: createParser(
|
|
257
|
-
|
|
258
|
-
|
|
381
|
+
(parsedArgs) => {
|
|
382
|
+
let type = AnyType;
|
|
383
|
+
for (let i = 2; i < parsedArgs.length; i += 2) {
|
|
384
|
+
type &= parsedArgs[i].type;
|
|
385
|
+
}
|
|
386
|
+
type &= parsedArgs[parsedArgs.length - 1].type;
|
|
387
|
+
return type;
|
|
388
|
+
},
|
|
389
|
+
withArgsCount(4, Infinity),
|
|
390
|
+
withEvenArgs,
|
|
391
|
+
parseMatchArgs
|
|
392
|
+
),
|
|
393
|
+
[Ops.Between]: createParser(
|
|
394
|
+
BooleanType,
|
|
395
|
+
withArgsCount(3, 3),
|
|
396
|
+
parseArgsOfType(NumberType)
|
|
397
|
+
),
|
|
398
|
+
[Ops.Interpolate]: createParser(
|
|
399
|
+
(parsedArgs) => {
|
|
400
|
+
let type = ColorType | NumberType;
|
|
401
|
+
for (let i = 3; i < parsedArgs.length; i += 2) {
|
|
402
|
+
type &= parsedArgs[i].type;
|
|
403
|
+
}
|
|
404
|
+
return type;
|
|
405
|
+
},
|
|
406
|
+
withArgsCount(6, Infinity),
|
|
407
|
+
withEvenArgs,
|
|
408
|
+
parseInterpolateArgs
|
|
409
|
+
),
|
|
410
|
+
[Ops.Case]: createParser(
|
|
411
|
+
(parsedArgs) => {
|
|
412
|
+
let type = AnyType;
|
|
413
|
+
for (let i = 1; i < parsedArgs.length; i += 2) {
|
|
414
|
+
type &= parsedArgs[i].type;
|
|
415
|
+
}
|
|
416
|
+
type &= parsedArgs[parsedArgs.length - 1].type;
|
|
417
|
+
return type;
|
|
418
|
+
},
|
|
419
|
+
withArgsCount(3, Infinity),
|
|
420
|
+
withOddArgs,
|
|
421
|
+
parseCaseArgs
|
|
422
|
+
),
|
|
423
|
+
[Ops.In]: createParser(BooleanType, withArgsCount(2, 2), parseInArgs),
|
|
424
|
+
[Ops.Number]: createParser(
|
|
425
|
+
NumberType,
|
|
426
|
+
withArgsCount(1, Infinity),
|
|
427
|
+
parseArgsOfType(AnyType)
|
|
428
|
+
),
|
|
429
|
+
[Ops.String]: createParser(
|
|
430
|
+
StringType,
|
|
431
|
+
withArgsCount(1, Infinity),
|
|
432
|
+
parseArgsOfType(AnyType)
|
|
433
|
+
),
|
|
434
|
+
[Ops.Array]: createParser(
|
|
435
|
+
NumberArrayType,
|
|
436
|
+
withArgsCount(1, Infinity),
|
|
437
|
+
parseArgsOfType(NumberType)
|
|
438
|
+
),
|
|
439
|
+
[Ops.Color]: createParser(
|
|
440
|
+
ColorType,
|
|
441
|
+
withArgsCount(3, 4),
|
|
442
|
+
parseArgsOfType(NumberType)
|
|
259
443
|
),
|
|
260
444
|
};
|
|
261
445
|
|
|
262
446
|
/**
|
|
263
|
-
* @typedef {function(Array,
|
|
447
|
+
* @typedef {function(Array<EncodedExpression>, ParsingContext, Array<Expression>, number?):Array<Expression>|void} ArgValidator
|
|
448
|
+
* An argument validator applies various checks to an encoded expression arguments
|
|
449
|
+
* Returns the parsed arguments if any.
|
|
450
|
+
* Third argument is the array of parsed arguments from previous validators
|
|
451
|
+
* Fourth argument is an optional type hint
|
|
264
452
|
*/
|
|
265
453
|
|
|
266
454
|
/**
|
|
267
455
|
* @type ArgValidator
|
|
268
456
|
*/
|
|
269
457
|
function withGetArgs(encoded, context) {
|
|
270
|
-
if (encoded.length !== 2) {
|
|
271
|
-
throw new Error('Expected 1 argument for get operation');
|
|
272
|
-
}
|
|
273
458
|
const arg = parse(encoded[1], context);
|
|
274
459
|
if (!(arg instanceof LiteralExpression)) {
|
|
275
460
|
throw new Error('Expected a literal argument for get operation');
|
|
@@ -285,9 +470,6 @@ function withGetArgs(encoded, context) {
|
|
|
285
470
|
* @type ArgValidator
|
|
286
471
|
*/
|
|
287
472
|
function withVarArgs(encoded, context) {
|
|
288
|
-
if (encoded.length !== 2) {
|
|
289
|
-
throw new Error('Expected 1 argument for var operation');
|
|
290
|
-
}
|
|
291
473
|
const arg = parse(encoded[1], context);
|
|
292
474
|
if (!(arg instanceof LiteralExpression)) {
|
|
293
475
|
throw new Error('Expected a literal argument for var operation');
|
|
@@ -313,10 +495,9 @@ function withNoArgs(encoded, context) {
|
|
|
313
495
|
/**
|
|
314
496
|
* @param {number} minArgs The minimum number of arguments.
|
|
315
497
|
* @param {number} maxArgs The maximum number of arguments.
|
|
316
|
-
* @param {number} argType The argument type.
|
|
317
498
|
* @return {ArgValidator} The argument validator
|
|
318
499
|
*/
|
|
319
|
-
function
|
|
500
|
+
function withArgsCount(minArgs, maxArgs) {
|
|
320
501
|
return function (encoded, context) {
|
|
321
502
|
const operation = encoded[0];
|
|
322
503
|
const argCount = encoded.length - 1;
|
|
@@ -332,13 +513,23 @@ function withArgs(minArgs, maxArgs, argType) {
|
|
|
332
513
|
`Expected ${minArgs} to ${maxArgs} arguments for operation ${operation}, got ${argCount}`
|
|
333
514
|
);
|
|
334
515
|
}
|
|
516
|
+
};
|
|
517
|
+
}
|
|
335
518
|
|
|
519
|
+
/**
|
|
520
|
+
* @param {number} argType The argument type.
|
|
521
|
+
* @return {ArgValidator} The argument validator
|
|
522
|
+
*/
|
|
523
|
+
function parseArgsOfType(argType) {
|
|
524
|
+
return function (encoded, context, parsedArgs, typeHint) {
|
|
525
|
+
const operation = encoded[0];
|
|
526
|
+
const argCount = encoded.length - 1;
|
|
336
527
|
/**
|
|
337
528
|
* @type {Array<Expression>}
|
|
338
529
|
*/
|
|
339
530
|
const args = new Array(argCount);
|
|
340
531
|
for (let i = 0; i < argCount; ++i) {
|
|
341
|
-
const expression = parse(encoded[i + 1], context);
|
|
532
|
+
const expression = parse(encoded[i + 1], context, typeHint);
|
|
342
533
|
if (!overlapsType(argType, expression.type)) {
|
|
343
534
|
const gotType = typeName(argType);
|
|
344
535
|
const expectedType = typeName(expression.type);
|
|
@@ -349,35 +540,205 @@ function withArgs(minArgs, maxArgs, argType) {
|
|
|
349
540
|
}
|
|
350
541
|
args[i] = expression;
|
|
351
542
|
}
|
|
352
|
-
|
|
353
543
|
return args;
|
|
354
544
|
};
|
|
355
545
|
}
|
|
356
546
|
|
|
357
547
|
/**
|
|
358
|
-
* @
|
|
359
|
-
|
|
548
|
+
* @type {ArgValidator}
|
|
549
|
+
*/
|
|
550
|
+
function narrowArgsType(encoded, context, parsedArgs, typeHint) {
|
|
551
|
+
const operation = encoded[0];
|
|
552
|
+
const argCount = encoded.length - 1;
|
|
553
|
+
|
|
554
|
+
// first pass to determine a narrowed down type
|
|
555
|
+
let sameType = typeHint !== undefined ? typeHint : AnyType;
|
|
556
|
+
for (let i = 0; i < parsedArgs.length; ++i) {
|
|
557
|
+
sameType &= parsedArgs[i].type;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
if (sameType === NoneType) {
|
|
561
|
+
throw new Error(
|
|
562
|
+
`No common type could be found for arguments of ${operation} operation`
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// re-parse args
|
|
567
|
+
const args = new Array(argCount);
|
|
568
|
+
for (let i = 0; i < argCount; ++i) {
|
|
569
|
+
args[i] = parse(encoded[i + 1], context, sameType);
|
|
570
|
+
}
|
|
571
|
+
return args;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* @type {ArgValidator}
|
|
576
|
+
*/
|
|
577
|
+
function withOddArgs(encoded, context) {
|
|
578
|
+
const operation = encoded[0];
|
|
579
|
+
const argCount = encoded.length - 1;
|
|
580
|
+
if (argCount % 2 === 0) {
|
|
581
|
+
throw new Error(
|
|
582
|
+
`An odd amount of arguments was expected for operation ${operation}, got ${JSON.stringify(
|
|
583
|
+
argCount
|
|
584
|
+
)} instead`
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* @type {ArgValidator}
|
|
591
|
+
*/
|
|
592
|
+
function withEvenArgs(encoded, context) {
|
|
593
|
+
const operation = encoded[0];
|
|
594
|
+
const argCount = encoded.length - 1;
|
|
595
|
+
if (argCount % 2 === 1) {
|
|
596
|
+
throw new Error(
|
|
597
|
+
`An even amount of arguments was expected for operation ${operation}, got ${JSON.stringify(
|
|
598
|
+
argCount
|
|
599
|
+
)} instead`
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* @type ArgValidator
|
|
606
|
+
*/
|
|
607
|
+
function parseMatchArgs(encoded, context, typeHint) {
|
|
608
|
+
const argsCount = encoded.length - 1;
|
|
609
|
+
|
|
610
|
+
const input = parse(encoded[1], context);
|
|
611
|
+
let inputType = input.type;
|
|
612
|
+
const fallback = parse(encoded[encoded.length - 1], context);
|
|
613
|
+
|
|
614
|
+
const args = new Array(argsCount - 2);
|
|
615
|
+
for (let i = 0; i < argsCount - 2; i += 2) {
|
|
616
|
+
const match = parse(encoded[i + 2], context);
|
|
617
|
+
const output = parse(encoded[i + 3], context);
|
|
618
|
+
inputType &= match.type;
|
|
619
|
+
args[i] = match;
|
|
620
|
+
args[i + 1] = output;
|
|
621
|
+
}
|
|
622
|
+
const expectedInputType = StringType | NumberType | BooleanType;
|
|
623
|
+
if (!overlapsType(expectedInputType, inputType)) {
|
|
624
|
+
throw new Error(
|
|
625
|
+
`Expected an input of type ${typeName(
|
|
626
|
+
expectedInputType
|
|
627
|
+
)} for the interpolate operation` + ` : got ${inputType} instead`
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return [input, ...args, fallback];
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* @type ArgValidator
|
|
636
|
+
*/
|
|
637
|
+
function parseInterpolateArgs(encoded, context) {
|
|
638
|
+
const interpolationType = encoded[1];
|
|
639
|
+
let interpolation;
|
|
640
|
+
switch (interpolationType[0]) {
|
|
641
|
+
case 'linear':
|
|
642
|
+
interpolation = 1;
|
|
643
|
+
break;
|
|
644
|
+
case 'exponential':
|
|
645
|
+
interpolation = interpolationType[1];
|
|
646
|
+
break;
|
|
647
|
+
default:
|
|
648
|
+
interpolation = null;
|
|
649
|
+
}
|
|
650
|
+
if (!interpolation) {
|
|
651
|
+
throw new Error(
|
|
652
|
+
`Invalid interpolation type: ${JSON.stringify(interpolationType)}`
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
const parsedArgs = [
|
|
657
|
+
parse(interpolation, context),
|
|
658
|
+
...encoded.slice(2).map((arg) => parse(arg, context)),
|
|
659
|
+
];
|
|
660
|
+
|
|
661
|
+
// check input types
|
|
662
|
+
const input = parsedArgs[0];
|
|
663
|
+
if (!overlapsType(NumberType, input.type)) {
|
|
664
|
+
throw new Error(
|
|
665
|
+
`Expected an input of type number for the interpolate operation` +
|
|
666
|
+
` : got ${typeName(input.type)} instead`
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
return parsedArgs;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* @type ArgValidator
|
|
675
|
+
*/
|
|
676
|
+
function parseCaseArgs(encoded, context) {
|
|
677
|
+
const parsedArgs = encoded.slice(1).map((arg) => parse(arg, context));
|
|
678
|
+
|
|
679
|
+
// check condition types
|
|
680
|
+
for (let i = 0; i < parsedArgs.length - 1; i += 2) {
|
|
681
|
+
if (!overlapsType(BooleanType, parsedArgs[i].type)) {
|
|
682
|
+
throw new Error(
|
|
683
|
+
`Expected all conditions in the case operation to be of type boolean` +
|
|
684
|
+
` : got ${typeName(parsedArgs[i].type)} at position ${i} instead`
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
return encoded.slice(1).map((arg) => parse(arg, context));
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* @type ArgValidator
|
|
694
|
+
*/
|
|
695
|
+
function parseInArgs(encoded, context) {
|
|
696
|
+
return encoded.slice(1).map((arg) => parse(arg, context));
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* @param {number|function(Array<Expression>):number} returnType The return type of the operator; can be a fixed value or a callback taking the parsed
|
|
701
|
+
* arguments
|
|
702
|
+
* @param {Array<ArgValidator>} argValidators A chain of argument validators; the return value of the last validator
|
|
703
|
+
* will be used as parsed arguments
|
|
360
704
|
* @return {Parser} The parser.
|
|
361
705
|
*/
|
|
362
|
-
function createParser(
|
|
363
|
-
return function (encoded, context) {
|
|
706
|
+
function createParser(returnType, ...argValidators) {
|
|
707
|
+
return function (encoded, context, typeHint) {
|
|
364
708
|
const operator = encoded[0];
|
|
365
|
-
|
|
366
|
-
|
|
709
|
+
let parsedArgs = [];
|
|
710
|
+
for (let i = 0; i < argValidators.length; i++) {
|
|
711
|
+
parsedArgs =
|
|
712
|
+
argValidators[i](encoded, context, parsedArgs, typeHint) || parsedArgs;
|
|
713
|
+
}
|
|
714
|
+
let actualType =
|
|
715
|
+
typeof returnType === 'function' ? returnType(parsedArgs) : returnType;
|
|
716
|
+
if (typeHint !== undefined) {
|
|
717
|
+
actualType &= typeHint;
|
|
718
|
+
}
|
|
719
|
+
if (actualType === NoneType) {
|
|
720
|
+
throw new Error(
|
|
721
|
+
`No matching type was found for the following expression: ${JSON.stringify(
|
|
722
|
+
encoded
|
|
723
|
+
)}`
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
return new CallExpression(actualType, operator, ...parsedArgs);
|
|
367
727
|
};
|
|
368
728
|
}
|
|
369
729
|
|
|
370
730
|
/**
|
|
371
731
|
* @param {Array} encoded The encoded expression.
|
|
372
732
|
* @param {ParsingContext} context The parsing context.
|
|
733
|
+
* @param {number} [typeHint] Optional type hint
|
|
373
734
|
* @return {Expression} The parsed expression.
|
|
374
735
|
*/
|
|
375
|
-
function parseCallExpression(encoded, context) {
|
|
736
|
+
function parseCallExpression(encoded, context, typeHint) {
|
|
376
737
|
const operator = encoded[0];
|
|
377
738
|
|
|
378
739
|
const parser = parsers[operator];
|
|
379
740
|
if (!parser) {
|
|
380
741
|
throw new Error(`Unknown operator: ${operator}`);
|
|
381
742
|
}
|
|
382
|
-
return parser(encoded, context);
|
|
743
|
+
return parser(encoded, context, typeHint);
|
|
383
744
|
}
|