@malloydata/malloy 0.0.22-dev230117232218 → 0.0.22-dev230119193053
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/lang/ast/apply-expr.d.ts +1 -14
- package/dist/lang/ast/apply-expr.js +1 -208
- package/dist/lang/ast/ast-expr.d.ts +9 -97
- package/dist/lang/ast/ast-expr.js +109 -390
- package/dist/lang/ast/ast-main.d.ts +396 -2
- package/dist/lang/ast/ast-main.js +1508 -22
- package/dist/lang/ast/ast-time-expr.d.ts +2 -42
- package/dist/lang/ast/ast-time-expr.js +36 -204
- package/dist/lang/space-field.d.ts +1 -106
- package/dist/lang/space-field.js +5 -234
- package/dist/lang/test/field-symbols.spec.js +21 -23
- package/dist/lang/test/parse.spec.js +3 -4
- package/package.json +1 -1
- package/dist/lang/field-space.d.ts +0 -159
- package/dist/lang/field-space.js +0 -641
|
@@ -22,215 +22,17 @@
|
|
|
22
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.
|
|
25
|
+
exports.Apply = exports.Pick = exports.PickWhen = exports.TopBy = exports.ExprCast = exports.isCastType = exports.ExprFilter = exports.ExprCase = exports.WhenClause = exports.ExprUngroup = exports.ExprSum = exports.ExprAvg = exports.ExprCount = exports.ExprCountDistinct = exports.ExprMax = exports.ExprMin = exports.ExprAlternationTree = exports.ExprMulDiv = exports.ExprAddSub = exports.BinaryNumeric = exports.ExprMinus = exports.ExprParens = exports.ExprNULL = exports.ExprIdReference = exports.ExprLogicalOp = exports.Boolean = exports.ExprNot = exports.ExprRegEx = exports.ExprNumber = exports.ExprString = void 0;
|
|
26
26
|
/*
|
|
27
27
|
** This file is the general framework for expression nodes and expression
|
|
28
28
|
** evaluation.
|
|
29
29
|
*/
|
|
30
30
|
const malloy_types_1 = require("../../model/malloy_types");
|
|
31
|
-
const
|
|
32
|
-
const
|
|
31
|
+
const ast_main_1 = require("./ast-main");
|
|
32
|
+
const ast_types_1 = require("./ast-types");
|
|
33
33
|
const apply_expr_1 = require("./apply-expr");
|
|
34
|
-
const space_field_1 = require("../space-field");
|
|
35
34
|
const time_utils_1 = require("./time-utils");
|
|
36
|
-
|
|
37
|
-
* Root node for any element in an expression. These essentially
|
|
38
|
-
* create a sub-tree in the larger AST. Expression nodes know
|
|
39
|
-
* how to write themselves as SQL (or rather, generate the
|
|
40
|
-
* template for SQL required by the query writer)
|
|
41
|
-
*/
|
|
42
|
-
class ExpressionDef extends index_1.MalloyElement {
|
|
43
|
-
constructor() {
|
|
44
|
-
super(...arguments);
|
|
45
|
-
this.legalChildTypes = index_1.FT.anyAtomicT;
|
|
46
|
-
}
|
|
47
|
-
granular() {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Some operators want to give the right hand value a chance to
|
|
52
|
-
* rewrite itself. This requests a translation for a rewrite,
|
|
53
|
-
* or returns undefined if that request should be denied.
|
|
54
|
-
* @param fs FieldSpace
|
|
55
|
-
* @returns Translated expression or undefined
|
|
56
|
-
*/
|
|
57
|
-
requestExpression(fs) {
|
|
58
|
-
return this.getExpression(fs);
|
|
59
|
-
}
|
|
60
|
-
defaultFieldName() {
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Check an expression for type compatibility
|
|
65
|
-
* @param _eNode currently unused, will be used to get error location
|
|
66
|
-
* @param eVal ...list of expressions that must match legalChildTypes
|
|
67
|
-
*/
|
|
68
|
-
typeCheck(eNode, eVal) {
|
|
69
|
-
if (!index_1.FT.in(eVal, this.legalChildTypes)) {
|
|
70
|
-
eNode.log(`'${this.elementType}' Can't use type ${index_1.FT.inspect(eVal)}`);
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* This is the operation which makes partial comparison and value trees work
|
|
77
|
-
* The default implemention merely constructs LEFT OP RIGHT, but specialized
|
|
78
|
-
* nodes like alternation trees or or partial comparison can control how
|
|
79
|
-
* the appplication gets generated
|
|
80
|
-
* @param fs The symbol table
|
|
81
|
-
* @param op The operator being applied
|
|
82
|
-
* @param expr The "other" (besdies 'this') value
|
|
83
|
-
* @returns The translated expression
|
|
84
|
-
*/
|
|
85
|
-
apply(fs, op, left) {
|
|
86
|
-
return (0, apply_expr_1.applyBinary)(fs, left, op, this);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
exports.ExpressionDef = ExpressionDef;
|
|
90
|
-
class DollarReference extends ExpressionDef {
|
|
91
|
-
constructor(refType) {
|
|
92
|
-
super();
|
|
93
|
-
this.refType = refType;
|
|
94
|
-
this.elementType = "$";
|
|
95
|
-
}
|
|
96
|
-
getExpression(_fs) {
|
|
97
|
-
return {
|
|
98
|
-
dataType: this.refType,
|
|
99
|
-
value: [{ type: "applyVal" }],
|
|
100
|
-
expressionType: "scalar",
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
class ConstantFieldSpace {
|
|
105
|
-
constructor() {
|
|
106
|
-
this.type = "fieldSpace";
|
|
107
|
-
}
|
|
108
|
-
structDef() {
|
|
109
|
-
throw new Error("ConstantFieldSpace cannot generate a structDef");
|
|
110
|
-
}
|
|
111
|
-
emptyStructDef() {
|
|
112
|
-
throw new Error("ConstantFieldSpace cannot generate a structDef");
|
|
113
|
-
}
|
|
114
|
-
lookup(_name) {
|
|
115
|
-
return {
|
|
116
|
-
error: "Only constants allowed in parameter expressions",
|
|
117
|
-
found: undefined,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
dialectObj() {
|
|
121
|
-
return undefined;
|
|
122
|
-
}
|
|
123
|
-
whenComplete(step) {
|
|
124
|
-
step();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
class ConstantSubExpression extends ExpressionDef {
|
|
128
|
-
constructor(expr) {
|
|
129
|
-
super({ expr });
|
|
130
|
-
this.expr = expr;
|
|
131
|
-
this.elementType = "constantExpression";
|
|
132
|
-
}
|
|
133
|
-
getExpression(_fs) {
|
|
134
|
-
return this.constantValue();
|
|
135
|
-
}
|
|
136
|
-
get constantFs() {
|
|
137
|
-
if (!this.cfs) {
|
|
138
|
-
this.cfs = new ConstantFieldSpace();
|
|
139
|
-
}
|
|
140
|
-
return this.cfs;
|
|
141
|
-
}
|
|
142
|
-
constantValue() {
|
|
143
|
-
return this.expr.getExpression(this.constantFs);
|
|
144
|
-
}
|
|
145
|
-
constantCondition(type) {
|
|
146
|
-
const compareAndContrast = new index_1.ExprCompare(new DollarReference(type), "=", this.expr);
|
|
147
|
-
const application = compareAndContrast.getExpression(this.constantFs);
|
|
148
|
-
return { ...application, value: (0, index_1.compressExpr)(application.value) };
|
|
149
|
-
}
|
|
150
|
-
apply(fs, op, expr) {
|
|
151
|
-
return this.expr.apply(fs, op, expr);
|
|
152
|
-
}
|
|
153
|
-
requestExpression(fs) {
|
|
154
|
-
return this.expr.requestExpression(fs);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
exports.ConstantSubExpression = ConstantSubExpression;
|
|
158
|
-
class FieldDeclaration extends index_1.MalloyElement {
|
|
159
|
-
constructor(expr, defineName, exprSrc) {
|
|
160
|
-
super({ expr });
|
|
161
|
-
this.expr = expr;
|
|
162
|
-
this.defineName = defineName;
|
|
163
|
-
this.exprSrc = exprSrc;
|
|
164
|
-
this.elementType = "fieldDeclaration";
|
|
165
|
-
}
|
|
166
|
-
fieldDef(fs, exprName) {
|
|
167
|
-
/*
|
|
168
|
-
* In an explore we cannot reference the thing we are defining, you need
|
|
169
|
-
* to use rename. In a query, the output space is a new thing, and expressions
|
|
170
|
-
* can reference the outer value in order to make a value with the new name,
|
|
171
|
-
* and it feels wrong that this is HERE and not somehow in the QueryOperation.
|
|
172
|
-
* For now, this stops the stack overflow, and passes all tests, but I think
|
|
173
|
-
* a refactor of QueryFieldSpace might someday be the place where this should
|
|
174
|
-
* happen.
|
|
175
|
-
*/
|
|
176
|
-
return this.queryFieldDef(new field_space_1.DefSpace(fs, this), exprName);
|
|
177
|
-
}
|
|
178
|
-
queryFieldDef(exprFS, exprName) {
|
|
179
|
-
let exprValue;
|
|
180
|
-
try {
|
|
181
|
-
exprValue = this.expr.getExpression(exprFS);
|
|
182
|
-
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
this.log(`Cannot define '${exprName}', ${error.message}`);
|
|
185
|
-
return {
|
|
186
|
-
name: `error_defining_${exprName}`,
|
|
187
|
-
type: "string",
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
const compressValue = (0, index_1.compressExpr)(exprValue.value);
|
|
191
|
-
const retType = exprValue.dataType;
|
|
192
|
-
if ((0, malloy_types_1.isAtomicFieldType)(retType)) {
|
|
193
|
-
const template = {
|
|
194
|
-
name: exprName,
|
|
195
|
-
type: retType,
|
|
196
|
-
location: this.location,
|
|
197
|
-
};
|
|
198
|
-
if (compressValue.length > 0) {
|
|
199
|
-
template.e = compressValue;
|
|
200
|
-
}
|
|
201
|
-
if (exprValue.expressionType) {
|
|
202
|
-
template.expressionType = exprValue.expressionType;
|
|
203
|
-
}
|
|
204
|
-
if (this.exprSrc) {
|
|
205
|
-
template.code = this.exprSrc;
|
|
206
|
-
}
|
|
207
|
-
// TODO this should work for dates too
|
|
208
|
-
if ((0, index_1.isGranularResult)(exprValue) && template.type === "timestamp") {
|
|
209
|
-
template.timeframe = exprValue.timeframe;
|
|
210
|
-
}
|
|
211
|
-
return template;
|
|
212
|
-
}
|
|
213
|
-
const circularDef = exprFS instanceof field_space_1.DefSpace && exprFS.foundCircle;
|
|
214
|
-
if (!circularDef) {
|
|
215
|
-
if (exprValue.dataType == "unknown") {
|
|
216
|
-
this.log(`Cannot define '${exprName}', value has unknown type`);
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
const badType = index_1.FT.inspect(exprValue);
|
|
220
|
-
this.log(`Cannot define '${exprName}', unexpected type: ${badType}`);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return {
|
|
224
|
-
name: `error_defining_${exprName}`,
|
|
225
|
-
type: "string",
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
exports.FieldDeclaration = FieldDeclaration;
|
|
230
|
-
class TypeMistmatch extends Error {
|
|
231
|
-
}
|
|
232
|
-
exports.TypeMistmatch = TypeMistmatch;
|
|
233
|
-
class ExprString extends ExpressionDef {
|
|
35
|
+
class ExprString extends ast_main_1.ExpressionDef {
|
|
234
36
|
constructor(src) {
|
|
235
37
|
super();
|
|
236
38
|
this.elementType = "string literal";
|
|
@@ -240,7 +42,7 @@ class ExprString extends ExpressionDef {
|
|
|
240
42
|
}
|
|
241
43
|
getExpression(_fs) {
|
|
242
44
|
return {
|
|
243
|
-
...
|
|
45
|
+
...ast_types_1.FT.stringT,
|
|
244
46
|
value: [
|
|
245
47
|
{
|
|
246
48
|
type: "dialect",
|
|
@@ -252,7 +54,7 @@ class ExprString extends ExpressionDef {
|
|
|
252
54
|
}
|
|
253
55
|
}
|
|
254
56
|
exports.ExprString = ExprString;
|
|
255
|
-
class ExprNumber extends ExpressionDef {
|
|
57
|
+
class ExprNumber extends ast_main_1.ExpressionDef {
|
|
256
58
|
constructor(n) {
|
|
257
59
|
super();
|
|
258
60
|
this.n = n;
|
|
@@ -262,11 +64,11 @@ class ExprNumber extends ExpressionDef {
|
|
|
262
64
|
return this.constantExpression();
|
|
263
65
|
}
|
|
264
66
|
constantExpression() {
|
|
265
|
-
return { ...
|
|
67
|
+
return { ...ast_types_1.FT.numberT, value: [this.n] };
|
|
266
68
|
}
|
|
267
69
|
}
|
|
268
70
|
exports.ExprNumber = ExprNumber;
|
|
269
|
-
class ExprRegEx extends ExpressionDef {
|
|
71
|
+
class ExprRegEx extends ast_main_1.ExpressionDef {
|
|
270
72
|
constructor(regex) {
|
|
271
73
|
super();
|
|
272
74
|
this.regex = regex;
|
|
@@ -281,40 +83,7 @@ class ExprRegEx extends ExpressionDef {
|
|
|
281
83
|
}
|
|
282
84
|
}
|
|
283
85
|
exports.ExprRegEx = ExprRegEx;
|
|
284
|
-
class
|
|
285
|
-
constructor(timeType, value, expressionType = "scalar") {
|
|
286
|
-
super();
|
|
287
|
-
this.elementType = "timestampOrDate";
|
|
288
|
-
this.elementType = timeType;
|
|
289
|
-
this.translationValue = {
|
|
290
|
-
dataType: timeType,
|
|
291
|
-
expressionType,
|
|
292
|
-
value: typeof value === "string" ? [value] : value,
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
getExpression(_fs) {
|
|
296
|
-
return this.translationValue;
|
|
297
|
-
}
|
|
298
|
-
static fromValue(timeType, expr) {
|
|
299
|
-
let value = expr.value;
|
|
300
|
-
if (timeType != expr.dataType) {
|
|
301
|
-
const toTs = {
|
|
302
|
-
type: "dialect",
|
|
303
|
-
function: "cast",
|
|
304
|
-
safe: false,
|
|
305
|
-
dstType: timeType,
|
|
306
|
-
expr: expr.value,
|
|
307
|
-
};
|
|
308
|
-
if ((0, malloy_types_1.isTimeFieldType)(expr.dataType)) {
|
|
309
|
-
toTs.srcType = expr.dataType;
|
|
310
|
-
}
|
|
311
|
-
value = (0, index_1.compressExpr)([toTs]);
|
|
312
|
-
}
|
|
313
|
-
return new ExprTime(timeType, value, expr.expressionType);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
exports.ExprTime = ExprTime;
|
|
317
|
-
class Unary extends ExpressionDef {
|
|
86
|
+
class Unary extends ast_main_1.ExpressionDef {
|
|
318
87
|
constructor(expr) {
|
|
319
88
|
super({ expr });
|
|
320
89
|
this.expr = expr;
|
|
@@ -324,7 +93,7 @@ class ExprNot extends Unary {
|
|
|
324
93
|
constructor(expr) {
|
|
325
94
|
super(expr);
|
|
326
95
|
this.elementType = "not";
|
|
327
|
-
this.legalChildTypes = [
|
|
96
|
+
this.legalChildTypes = [ast_types_1.FT.boolT, ast_types_1.FT.nullT];
|
|
328
97
|
}
|
|
329
98
|
getExpression(fs) {
|
|
330
99
|
const notThis = this.expr.getExpression(fs);
|
|
@@ -335,53 +104,30 @@ class ExprNot extends Unary {
|
|
|
335
104
|
value: (0, apply_expr_1.nullsafeNot)(notThis.value),
|
|
336
105
|
};
|
|
337
106
|
}
|
|
338
|
-
return (0,
|
|
107
|
+
return (0, ast_types_1.errorFor)("not requires boolean");
|
|
339
108
|
}
|
|
340
109
|
}
|
|
341
110
|
exports.ExprNot = ExprNot;
|
|
342
|
-
class Boolean extends ExpressionDef {
|
|
111
|
+
class Boolean extends ast_main_1.ExpressionDef {
|
|
343
112
|
constructor(value) {
|
|
344
113
|
super();
|
|
345
114
|
this.value = value;
|
|
346
115
|
this.elementType = "boolean literal";
|
|
347
116
|
}
|
|
348
117
|
getExpression() {
|
|
349
|
-
return { ...
|
|
118
|
+
return { ...ast_types_1.FT.boolT, value: [this.value] };
|
|
350
119
|
}
|
|
351
120
|
}
|
|
352
121
|
exports.Boolean = Boolean;
|
|
353
|
-
class
|
|
354
|
-
constructor(left, op, right) {
|
|
355
|
-
super({ left, right });
|
|
356
|
-
this.left = left;
|
|
357
|
-
this.op = op;
|
|
358
|
-
this.right = right;
|
|
359
|
-
this.elementType = "abstract boolean binary";
|
|
360
|
-
this.legalChildTypes = [index_1.FT.boolT];
|
|
361
|
-
}
|
|
362
|
-
getExpression(fs) {
|
|
363
|
-
const left = this.left.getExpression(fs);
|
|
364
|
-
const right = this.right.getExpression(fs);
|
|
365
|
-
if (this.typeCheck(this.left, left) && this.typeCheck(this.right, right)) {
|
|
366
|
-
return {
|
|
367
|
-
dataType: "boolean",
|
|
368
|
-
expressionType: (0, malloy_types_1.maxExpressionType)(left.expressionType, right.expressionType),
|
|
369
|
-
value: (0, index_1.compose)(left.value, this.op, right.value),
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
return (0, index_1.errorFor)("logial required boolean");
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
exports.BinaryBoolean = BinaryBoolean;
|
|
376
|
-
class ExprLogicalOp extends BinaryBoolean {
|
|
122
|
+
class ExprLogicalOp extends ast_main_1.BinaryBoolean {
|
|
377
123
|
constructor() {
|
|
378
124
|
super(...arguments);
|
|
379
125
|
this.elementType = "logical operator";
|
|
380
|
-
this.legalChildTypes = [
|
|
126
|
+
this.legalChildTypes = [ast_types_1.FT.boolT, { ...ast_types_1.FT.boolT, aggregate: true }];
|
|
381
127
|
}
|
|
382
128
|
}
|
|
383
129
|
exports.ExprLogicalOp = ExprLogicalOp;
|
|
384
|
-
class ExprIdReference extends ExpressionDef {
|
|
130
|
+
class ExprIdReference extends ast_main_1.ExpressionDef {
|
|
385
131
|
constructor(fieldReference) {
|
|
386
132
|
super();
|
|
387
133
|
this.fieldReference = fieldReference;
|
|
@@ -402,11 +148,11 @@ class ExprIdReference extends ExpressionDef {
|
|
|
402
148
|
return { dataType, expressionType, value };
|
|
403
149
|
}
|
|
404
150
|
this.log(def.error);
|
|
405
|
-
return (0,
|
|
151
|
+
return (0, ast_types_1.errorFor)(def.error);
|
|
406
152
|
}
|
|
407
153
|
apply(fs, op, expr) {
|
|
408
154
|
const entry = this.fieldReference.getField(fs).found;
|
|
409
|
-
if (entry instanceof
|
|
155
|
+
if (entry instanceof ast_main_1.SpaceParam) {
|
|
410
156
|
const cParam = entry.parameter();
|
|
411
157
|
if ((0, malloy_types_1.isConditionParameter)(cParam)) {
|
|
412
158
|
const lval = expr.getExpression(fs);
|
|
@@ -427,7 +173,7 @@ class ExprIdReference extends ExpressionDef {
|
|
|
427
173
|
}
|
|
428
174
|
}
|
|
429
175
|
exports.ExprIdReference = ExprIdReference;
|
|
430
|
-
class ExprNULL extends ExpressionDef {
|
|
176
|
+
class ExprNULL extends ast_main_1.ExpressionDef {
|
|
431
177
|
constructor() {
|
|
432
178
|
super(...arguments);
|
|
433
179
|
this.elementType = "NULL";
|
|
@@ -441,7 +187,7 @@ class ExprNULL extends ExpressionDef {
|
|
|
441
187
|
}
|
|
442
188
|
}
|
|
443
189
|
exports.ExprNULL = ExprNULL;
|
|
444
|
-
class ExprParens extends ExpressionDef {
|
|
190
|
+
class ExprParens extends ast_main_1.ExpressionDef {
|
|
445
191
|
constructor(expr) {
|
|
446
192
|
super({ expr });
|
|
447
193
|
this.expr = expr;
|
|
@@ -456,12 +202,12 @@ class ExprParens extends ExpressionDef {
|
|
|
456
202
|
}
|
|
457
203
|
}
|
|
458
204
|
exports.ExprParens = ExprParens;
|
|
459
|
-
class ExprMinus extends ExpressionDef {
|
|
205
|
+
class ExprMinus extends ast_main_1.ExpressionDef {
|
|
460
206
|
constructor(expr) {
|
|
461
207
|
super({ expr });
|
|
462
208
|
this.expr = expr;
|
|
463
209
|
this.elementType = "unary minus";
|
|
464
|
-
this.legalChildTypes = [
|
|
210
|
+
this.legalChildTypes = [ast_types_1.FT.numberT];
|
|
465
211
|
}
|
|
466
212
|
getExpression(fs) {
|
|
467
213
|
const expr = this.expr.getExpression(fs);
|
|
@@ -471,18 +217,18 @@ class ExprMinus extends ExpressionDef {
|
|
|
471
217
|
}
|
|
472
218
|
return { ...expr, value: ["-", ...expr.value] };
|
|
473
219
|
}
|
|
474
|
-
return (0,
|
|
220
|
+
return (0, ast_types_1.errorFor)("negate requires number");
|
|
475
221
|
}
|
|
476
222
|
}
|
|
477
223
|
exports.ExprMinus = ExprMinus;
|
|
478
|
-
class BinaryNumeric extends ExpressionDef {
|
|
224
|
+
class BinaryNumeric extends ast_main_1.ExpressionDef {
|
|
479
225
|
constructor(left, op, right) {
|
|
480
226
|
super({ left, right });
|
|
481
227
|
this.left = left;
|
|
482
228
|
this.op = op;
|
|
483
229
|
this.right = right;
|
|
484
230
|
this.elementType = "numeric binary abstract";
|
|
485
|
-
this.legalChildTypes = [
|
|
231
|
+
this.legalChildTypes = [ast_types_1.FT.numberT];
|
|
486
232
|
}
|
|
487
233
|
getExpression(fs) {
|
|
488
234
|
return this.right.apply(fs, this.op, this.left);
|
|
@@ -503,7 +249,7 @@ class ExprMulDiv extends BinaryNumeric {
|
|
|
503
249
|
}
|
|
504
250
|
}
|
|
505
251
|
exports.ExprMulDiv = ExprMulDiv;
|
|
506
|
-
class ExprAlternationTree extends BinaryBoolean {
|
|
252
|
+
class ExprAlternationTree extends ast_main_1.BinaryBoolean {
|
|
507
253
|
constructor(left, op, right) {
|
|
508
254
|
super(left, op, right);
|
|
509
255
|
this.elementType = "alternation";
|
|
@@ -515,7 +261,7 @@ class ExprAlternationTree extends BinaryBoolean {
|
|
|
515
261
|
return {
|
|
516
262
|
dataType: "boolean",
|
|
517
263
|
expressionType: (0, malloy_types_1.maxExpressionType)(choice1.expressionType, choice2.expressionType),
|
|
518
|
-
value: (0,
|
|
264
|
+
value: (0, ast_types_1.compose)(choice1.value, this.op === "&" ? "and" : "or", choice2.value),
|
|
519
265
|
};
|
|
520
266
|
}
|
|
521
267
|
requestExpression(_fs) {
|
|
@@ -523,15 +269,15 @@ class ExprAlternationTree extends BinaryBoolean {
|
|
|
523
269
|
}
|
|
524
270
|
getExpression(_fs) {
|
|
525
271
|
this.log(`Alternation tree has no value`);
|
|
526
|
-
return (0,
|
|
272
|
+
return (0, ast_types_1.errorFor)("no value from alternation tree");
|
|
527
273
|
}
|
|
528
274
|
}
|
|
529
275
|
exports.ExprAlternationTree = ExprAlternationTree;
|
|
530
|
-
class ExprAggregateFunction extends ExpressionDef {
|
|
276
|
+
class ExprAggregateFunction extends ast_main_1.ExpressionDef {
|
|
531
277
|
constructor(func, expr) {
|
|
532
278
|
super();
|
|
533
279
|
this.func = func;
|
|
534
|
-
this.legalChildTypes = [
|
|
280
|
+
this.legalChildTypes = [ast_types_1.FT.numberT];
|
|
535
281
|
this.elementType = func;
|
|
536
282
|
if (expr) {
|
|
537
283
|
this.expr = expr;
|
|
@@ -558,20 +304,20 @@ class ExprAggregateFunction extends ExpressionDef {
|
|
|
558
304
|
structPath = this.source.sourceString;
|
|
559
305
|
}
|
|
560
306
|
else {
|
|
561
|
-
if (!(sourceFoot instanceof
|
|
307
|
+
if (!(sourceFoot instanceof ast_main_1.StructSpaceField)) {
|
|
562
308
|
this.log(`Aggregate source cannot be a ${footType.type}`);
|
|
563
|
-
return (0,
|
|
309
|
+
return (0, ast_types_1.errorFor)(`Aggregate source cannot be a ${footType.type}`);
|
|
564
310
|
}
|
|
565
311
|
}
|
|
566
312
|
}
|
|
567
313
|
else {
|
|
568
314
|
this.log(`Reference to undefined value ${this.source.refString}`);
|
|
569
|
-
return (0,
|
|
315
|
+
return (0, ast_types_1.errorFor)(`Reference to undefined value ${this.source.refString}`);
|
|
570
316
|
}
|
|
571
317
|
}
|
|
572
318
|
if (exprVal === undefined) {
|
|
573
319
|
this.log("Missing expression for aggregate function");
|
|
574
|
-
return (0,
|
|
320
|
+
return (0, ast_types_1.errorFor)("agggregate without expression");
|
|
575
321
|
}
|
|
576
322
|
if (this.typeCheck(this.expr || this, {
|
|
577
323
|
...exprVal,
|
|
@@ -591,13 +337,13 @@ class ExprAggregateFunction extends ExpressionDef {
|
|
|
591
337
|
value: [f],
|
|
592
338
|
};
|
|
593
339
|
}
|
|
594
|
-
return (0,
|
|
340
|
+
return (0, ast_types_1.errorFor)("aggregate type check");
|
|
595
341
|
}
|
|
596
342
|
}
|
|
597
343
|
class ExprMin extends ExprAggregateFunction {
|
|
598
344
|
constructor(expr) {
|
|
599
345
|
super("min", expr);
|
|
600
|
-
this.legalChildTypes = [
|
|
346
|
+
this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
|
|
601
347
|
}
|
|
602
348
|
returns(forExpression) {
|
|
603
349
|
return forExpression.dataType;
|
|
@@ -607,7 +353,7 @@ exports.ExprMin = ExprMin;
|
|
|
607
353
|
class ExprMax extends ExprAggregateFunction {
|
|
608
354
|
constructor(expr) {
|
|
609
355
|
super("max", expr);
|
|
610
|
-
this.legalChildTypes = [
|
|
356
|
+
this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
|
|
611
357
|
}
|
|
612
358
|
returns(forExpression) {
|
|
613
359
|
return forExpression.dataType;
|
|
@@ -617,7 +363,7 @@ exports.ExprMax = ExprMax;
|
|
|
617
363
|
class ExprCountDistinct extends ExprAggregateFunction {
|
|
618
364
|
constructor(expr) {
|
|
619
365
|
super("count_distinct", expr);
|
|
620
|
-
this.legalChildTypes = [
|
|
366
|
+
this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
|
|
621
367
|
}
|
|
622
368
|
}
|
|
623
369
|
exports.ExprCountDistinct = ExprCountDistinct;
|
|
@@ -686,13 +432,13 @@ class ExprSum extends ExprAsymmetric {
|
|
|
686
432
|
}
|
|
687
433
|
}
|
|
688
434
|
exports.ExprSum = ExprSum;
|
|
689
|
-
class ExprUngroup extends ExpressionDef {
|
|
435
|
+
class ExprUngroup extends ast_main_1.ExpressionDef {
|
|
690
436
|
constructor(control, expr, fields) {
|
|
691
437
|
super({ expr, fields });
|
|
692
438
|
this.control = control;
|
|
693
439
|
this.expr = expr;
|
|
694
440
|
this.fields = fields;
|
|
695
|
-
this.legalChildTypes =
|
|
441
|
+
this.legalChildTypes = ast_types_1.FT.anyAtomicT;
|
|
696
442
|
this.elementType = "ungroup";
|
|
697
443
|
}
|
|
698
444
|
returns(_forExpression) {
|
|
@@ -702,18 +448,18 @@ class ExprUngroup extends ExpressionDef {
|
|
|
702
448
|
const exprVal = this.expr.getExpression(fs);
|
|
703
449
|
if (!(0, malloy_types_1.expressionIsAggregate)(exprVal.expressionType)) {
|
|
704
450
|
this.expr.log(`${this.control}() expression must be an aggregate`);
|
|
705
|
-
return (0,
|
|
451
|
+
return (0, ast_types_1.errorFor)("ungrouped scalar");
|
|
706
452
|
}
|
|
707
453
|
const ungroup = { type: this.control, e: exprVal.value };
|
|
708
454
|
if (this.typeCheck(this.expr, { ...exprVal, expressionType: "scalar" })) {
|
|
709
455
|
if (this.fields.length > 0) {
|
|
710
456
|
let qs = fs;
|
|
711
|
-
if (fs instanceof
|
|
457
|
+
if (fs instanceof ast_main_1.DefSpace) {
|
|
712
458
|
qs = fs.realFS;
|
|
713
459
|
}
|
|
714
|
-
if (!(qs instanceof
|
|
460
|
+
if (!(qs instanceof ast_main_1.QuerySpace)) {
|
|
715
461
|
this.log(`${this.control}() must be in a query -- weird internal error`);
|
|
716
|
-
return (0,
|
|
462
|
+
return (0, ast_types_1.errorFor)("ungroup query check");
|
|
717
463
|
}
|
|
718
464
|
const output = qs.result;
|
|
719
465
|
const dstFields = [];
|
|
@@ -733,11 +479,11 @@ class ExprUngroup extends ExpressionDef {
|
|
|
733
479
|
};
|
|
734
480
|
}
|
|
735
481
|
this.log(`${this.control}() incompatible type`);
|
|
736
|
-
return (0,
|
|
482
|
+
return (0, ast_types_1.errorFor)("ungrouped type check");
|
|
737
483
|
}
|
|
738
484
|
}
|
|
739
485
|
exports.ExprUngroup = ExprUngroup;
|
|
740
|
-
class WhenClause extends ExpressionDef {
|
|
486
|
+
class WhenClause extends ast_main_1.ExpressionDef {
|
|
741
487
|
constructor(whenThis, thenThis) {
|
|
742
488
|
super({ whenThis, thenThis });
|
|
743
489
|
this.whenThis = whenThis;
|
|
@@ -749,7 +495,7 @@ class WhenClause extends ExpressionDef {
|
|
|
749
495
|
}
|
|
750
496
|
}
|
|
751
497
|
exports.WhenClause = WhenClause;
|
|
752
|
-
class ExprCase extends ExpressionDef {
|
|
498
|
+
class ExprCase extends ast_main_1.ExpressionDef {
|
|
753
499
|
constructor(when, elseClause) {
|
|
754
500
|
super({ when });
|
|
755
501
|
this.when = when;
|
|
@@ -766,9 +512,9 @@ class ExprCase extends ExpressionDef {
|
|
|
766
512
|
const thenExpr = clause.thenThis.getExpression(fs);
|
|
767
513
|
expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, (0, malloy_types_1.maxExpressionType)(whenExpr.expressionType, thenExpr.expressionType));
|
|
768
514
|
if (thenExpr.dataType !== "null") {
|
|
769
|
-
if (retType && !
|
|
770
|
-
this.log(`Mismatched THEN clause types, ${
|
|
771
|
-
return (0,
|
|
515
|
+
if (retType && !ast_types_1.FT.typeEq(retType, thenExpr)) {
|
|
516
|
+
this.log(`Mismatched THEN clause types, ${ast_types_1.FT.inspect(retType, thenExpr)}`);
|
|
517
|
+
return (0, ast_types_1.errorFor)("then typecheck");
|
|
772
518
|
}
|
|
773
519
|
else {
|
|
774
520
|
retType = thenExpr;
|
|
@@ -781,9 +527,9 @@ class ExprCase extends ExpressionDef {
|
|
|
781
527
|
expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, elseExpr.expressionType);
|
|
782
528
|
caseExpr.push(" ELSE ", ...elseExpr.value);
|
|
783
529
|
if (elseExpr.dataType !== "null") {
|
|
784
|
-
if (retType && !
|
|
785
|
-
this.log(`Mismatched ELSE clause type, ${
|
|
786
|
-
return (0,
|
|
530
|
+
if (retType && !ast_types_1.FT.typeEq(retType, elseExpr)) {
|
|
531
|
+
this.log(`Mismatched ELSE clause type, ${ast_types_1.FT.inspect(retType, elseExpr)}`);
|
|
532
|
+
return (0, ast_types_1.errorFor)("else typecheck");
|
|
787
533
|
}
|
|
788
534
|
else {
|
|
789
535
|
retType = elseExpr;
|
|
@@ -792,7 +538,7 @@ class ExprCase extends ExpressionDef {
|
|
|
792
538
|
}
|
|
793
539
|
if (retType === undefined) {
|
|
794
540
|
this.log("case statement type not computable");
|
|
795
|
-
return (0,
|
|
541
|
+
return (0, ast_types_1.errorFor)("typeless case");
|
|
796
542
|
}
|
|
797
543
|
caseExpr.push(" END");
|
|
798
544
|
return {
|
|
@@ -803,13 +549,13 @@ class ExprCase extends ExpressionDef {
|
|
|
803
549
|
}
|
|
804
550
|
}
|
|
805
551
|
exports.ExprCase = ExprCase;
|
|
806
|
-
class ExprFilter extends ExpressionDef {
|
|
552
|
+
class ExprFilter extends ast_main_1.ExpressionDef {
|
|
807
553
|
constructor(expr, filter) {
|
|
808
554
|
super({ expr, filter });
|
|
809
555
|
this.expr = expr;
|
|
810
556
|
this.filter = filter;
|
|
811
557
|
this.elementType = "filtered expression";
|
|
812
|
-
this.legalChildTypes =
|
|
558
|
+
this.legalChildTypes = ast_types_1.FT.anyAtomicT;
|
|
813
559
|
}
|
|
814
560
|
getExpression(fs) {
|
|
815
561
|
const testList = this.filter.getFilterList(fs);
|
|
@@ -817,7 +563,7 @@ class ExprFilter extends ExpressionDef {
|
|
|
817
563
|
for (const cond of testList) {
|
|
818
564
|
if ((0, malloy_types_1.expressionIsCalculation)(cond.expressionType)) {
|
|
819
565
|
this.filter.log("Cannot filter a field with an aggregate or analytical computation");
|
|
820
|
-
return (0,
|
|
566
|
+
return (0, ast_types_1.errorFor)("no filter on aggregate");
|
|
821
567
|
}
|
|
822
568
|
}
|
|
823
569
|
if (resultExpr.expressionType === "scalar") {
|
|
@@ -838,7 +584,7 @@ class ExprFilter extends ExpressionDef {
|
|
|
838
584
|
};
|
|
839
585
|
}
|
|
840
586
|
this.expr.log(`Cannot filter '${resultExpr.dataType}' data`);
|
|
841
|
-
return (0,
|
|
587
|
+
return (0, ast_types_1.errorFor)("cannot filter type");
|
|
842
588
|
}
|
|
843
589
|
}
|
|
844
590
|
exports.ExprFilter = ExprFilter;
|
|
@@ -846,7 +592,7 @@ function isCastType(t) {
|
|
|
846
592
|
return ["string", "number", "boolean", "date", "timestamp"].includes(t);
|
|
847
593
|
}
|
|
848
594
|
exports.isCastType = isCastType;
|
|
849
|
-
class ExprCast extends ExpressionDef {
|
|
595
|
+
class ExprCast extends ast_main_1.ExpressionDef {
|
|
850
596
|
constructor(expr, castType, safe = false) {
|
|
851
597
|
super({ expr });
|
|
852
598
|
this.expr = expr;
|
|
@@ -859,83 +605,33 @@ class ExprCast extends ExpressionDef {
|
|
|
859
605
|
return {
|
|
860
606
|
dataType: this.castType,
|
|
861
607
|
expressionType: expr.expressionType,
|
|
862
|
-
value: (0,
|
|
608
|
+
value: (0, ast_types_1.compressExpr)((0, time_utils_1.castTo)(this.castType, expr.value, this.safe)),
|
|
863
609
|
};
|
|
864
610
|
}
|
|
865
611
|
}
|
|
866
612
|
exports.ExprCast = ExprCast;
|
|
867
|
-
class TopBy extends
|
|
613
|
+
class TopBy extends ast_main_1.MalloyElement {
|
|
868
614
|
constructor(by) {
|
|
869
615
|
super();
|
|
870
616
|
this.by = by;
|
|
871
617
|
this.elementType = "topBy";
|
|
872
|
-
if (by instanceof ExpressionDef) {
|
|
618
|
+
if (by instanceof ast_main_1.ExpressionDef) {
|
|
873
619
|
this.has({ by });
|
|
874
620
|
}
|
|
875
621
|
}
|
|
876
622
|
getBy(fs) {
|
|
877
|
-
if (this.by instanceof ExpressionDef) {
|
|
623
|
+
if (this.by instanceof ast_main_1.ExpressionDef) {
|
|
878
624
|
const byExpr = this.by.getExpression(fs);
|
|
879
625
|
if (!(0, malloy_types_1.expressionIsAggregate)(byExpr.expressionType)) {
|
|
880
626
|
this.log("top by expression must be an aggregate");
|
|
881
627
|
}
|
|
882
|
-
return { by: "expression", e: (0,
|
|
628
|
+
return { by: "expression", e: (0, ast_types_1.compressExpr)(byExpr.value) };
|
|
883
629
|
}
|
|
884
630
|
return { by: "name", name: this.by };
|
|
885
631
|
}
|
|
886
632
|
}
|
|
887
633
|
exports.TopBy = TopBy;
|
|
888
|
-
class
|
|
889
|
-
constructor(first, last) {
|
|
890
|
-
super({ first, last });
|
|
891
|
-
this.first = first;
|
|
892
|
-
this.last = last;
|
|
893
|
-
this.elementType = "range";
|
|
894
|
-
}
|
|
895
|
-
apply(fs, op, expr) {
|
|
896
|
-
switch (op) {
|
|
897
|
-
case "=":
|
|
898
|
-
case "!=": {
|
|
899
|
-
const op1 = op === "=" ? ">=" : "<";
|
|
900
|
-
const op2 = op === "=" ? "and" : "or";
|
|
901
|
-
const op3 = op === "=" ? "<" : ">=";
|
|
902
|
-
const fromValue = this.first.apply(fs, op1, expr);
|
|
903
|
-
const toValue = this.last.apply(fs, op3, expr);
|
|
904
|
-
return {
|
|
905
|
-
dataType: "boolean",
|
|
906
|
-
expressionType: (0, malloy_types_1.maxExpressionType)(fromValue.expressionType, toValue.expressionType),
|
|
907
|
-
value: (0, index_1.compose)(fromValue.value, op2, toValue.value),
|
|
908
|
-
};
|
|
909
|
-
}
|
|
910
|
-
/**
|
|
911
|
-
* This is a little surprising, but is actually how you comapre a
|
|
912
|
-
* value to a range ...
|
|
913
|
-
*
|
|
914
|
-
* val > begin to end val >= end
|
|
915
|
-
* val >= begin to end val >= begin
|
|
916
|
-
* val < begin to end val < begin
|
|
917
|
-
* val <= begin to end val < end
|
|
918
|
-
*/
|
|
919
|
-
case ">":
|
|
920
|
-
return this.last.apply(fs, ">=", expr);
|
|
921
|
-
case ">=":
|
|
922
|
-
return this.first.apply(fs, ">=", expr);
|
|
923
|
-
case "<":
|
|
924
|
-
return this.first.apply(fs, "<", expr);
|
|
925
|
-
case "<=":
|
|
926
|
-
return this.last.apply(fs, "<", expr);
|
|
927
|
-
}
|
|
928
|
-
throw new Error("mysterious error in range computation");
|
|
929
|
-
}
|
|
930
|
-
requestExpression(_fs) {
|
|
931
|
-
return undefined;
|
|
932
|
-
}
|
|
933
|
-
getExpression(_fs) {
|
|
934
|
-
return (0, index_1.errorFor)("a range is not a value");
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
exports.Range = Range;
|
|
938
|
-
class PickWhen extends index_1.MalloyElement {
|
|
634
|
+
class PickWhen extends ast_main_1.MalloyElement {
|
|
939
635
|
constructor(pick, when) {
|
|
940
636
|
super({ when });
|
|
941
637
|
this.pick = pick;
|
|
@@ -945,7 +641,7 @@ class PickWhen extends index_1.MalloyElement {
|
|
|
945
641
|
}
|
|
946
642
|
}
|
|
947
643
|
exports.PickWhen = PickWhen;
|
|
948
|
-
class Pick extends ExpressionDef {
|
|
644
|
+
class Pick extends ast_main_1.ExpressionDef {
|
|
949
645
|
constructor(choices, elsePick) {
|
|
950
646
|
super({ choices });
|
|
951
647
|
this.choices = choices;
|
|
@@ -982,10 +678,10 @@ class Pick extends ExpressionDef {
|
|
|
982
678
|
: expr.getExpression(fs);
|
|
983
679
|
anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(whenExpr.expressionType, thenExpr.expressionType));
|
|
984
680
|
if (returnType) {
|
|
985
|
-
if (!
|
|
986
|
-
const whenType =
|
|
681
|
+
if (!ast_types_1.FT.typeEq(returnType, thenExpr, true)) {
|
|
682
|
+
const whenType = ast_types_1.FT.inspect(thenExpr);
|
|
987
683
|
this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
|
|
988
|
-
return (0,
|
|
684
|
+
return (0, ast_types_1.errorFor)("pick when type");
|
|
989
685
|
}
|
|
990
686
|
}
|
|
991
687
|
else {
|
|
@@ -996,32 +692,32 @@ class Pick extends ExpressionDef {
|
|
|
996
692
|
const elsePart = this.elsePick || expr;
|
|
997
693
|
const elseVal = elsePart.getExpression(fs);
|
|
998
694
|
returnType || (returnType = elseVal);
|
|
999
|
-
if (!
|
|
695
|
+
if (!ast_types_1.FT.typeEq(returnType, elseVal, true)) {
|
|
1000
696
|
const errSrc = this.elsePick ? "else" : "pick default";
|
|
1001
|
-
this.log(`${errSrc} type '${
|
|
1002
|
-
return (0,
|
|
697
|
+
this.log(`${errSrc} type '${ast_types_1.FT.inspect(elseVal)}', expected '${returnType.dataType}'`);
|
|
698
|
+
return (0, ast_types_1.errorFor)("pick else type");
|
|
1003
699
|
}
|
|
1004
700
|
return {
|
|
1005
701
|
dataType: returnType.dataType,
|
|
1006
702
|
expressionType: (0, malloy_types_1.maxExpressionType)(anyExpressionType, elseVal.expressionType),
|
|
1007
|
-
value: (0,
|
|
703
|
+
value: (0, ast_types_1.compressExpr)([...caseValue, " ELSE ", ...elseVal.value, " END"]),
|
|
1008
704
|
};
|
|
1009
705
|
}
|
|
1010
706
|
getExpression(fs) {
|
|
1011
707
|
if (this.elsePick === undefined) {
|
|
1012
708
|
this.log("pick incomplete, missing 'else'");
|
|
1013
|
-
return (0,
|
|
709
|
+
return (0, ast_types_1.errorFor)("no value for partial pick");
|
|
1014
710
|
}
|
|
1015
711
|
const choiceValues = [];
|
|
1016
712
|
for (const c of this.choices) {
|
|
1017
713
|
if (c.pick === undefined) {
|
|
1018
714
|
this.log("pick with no value can only be used with apply");
|
|
1019
|
-
return (0,
|
|
715
|
+
return (0, ast_types_1.errorFor)("no value for partial pick");
|
|
1020
716
|
}
|
|
1021
717
|
const pickWhen = c.when.requestExpression(fs);
|
|
1022
718
|
if (pickWhen === undefined) {
|
|
1023
719
|
this.log("pick with partial when can only be used with apply");
|
|
1024
|
-
return (0,
|
|
720
|
+
return (0, ast_types_1.errorFor)("partial when");
|
|
1025
721
|
}
|
|
1026
722
|
choiceValues.push({
|
|
1027
723
|
pick: c.pick.getExpression(fs),
|
|
@@ -1032,31 +728,54 @@ class Pick extends ExpressionDef {
|
|
|
1032
728
|
const caseValue = ["CASE"];
|
|
1033
729
|
let anyExpressionType = returnType.expressionType;
|
|
1034
730
|
for (const aChoice of choiceValues) {
|
|
1035
|
-
if (!
|
|
1036
|
-
this.log(`when expression must be boolean, not '${
|
|
1037
|
-
return (0,
|
|
731
|
+
if (!ast_types_1.FT.typeEq(aChoice.when, ast_types_1.FT.boolT)) {
|
|
732
|
+
this.log(`when expression must be boolean, not '${ast_types_1.FT.inspect(aChoice.when)}`);
|
|
733
|
+
return (0, ast_types_1.errorFor)("pick when type");
|
|
1038
734
|
}
|
|
1039
|
-
if (!
|
|
1040
|
-
const whenType =
|
|
735
|
+
if (!ast_types_1.FT.typeEq(returnType, aChoice.pick, true)) {
|
|
736
|
+
const whenType = ast_types_1.FT.inspect(aChoice.pick);
|
|
1041
737
|
this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
|
|
1042
|
-
return (0,
|
|
738
|
+
return (0, ast_types_1.errorFor)("pick value type");
|
|
1043
739
|
}
|
|
1044
740
|
anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(aChoice.pick.expressionType, aChoice.when.expressionType));
|
|
1045
741
|
caseValue.push(" WHEN ", ...aChoice.when.value, " THEN ", ...aChoice.pick.value);
|
|
1046
742
|
}
|
|
1047
743
|
const defVal = this.elsePick.getExpression(fs);
|
|
1048
744
|
anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, defVal.expressionType);
|
|
1049
|
-
if (!
|
|
1050
|
-
this.elsePick.log(`else type '${
|
|
1051
|
-
return (0,
|
|
745
|
+
if (!ast_types_1.FT.typeEq(returnType, defVal, true)) {
|
|
746
|
+
this.elsePick.log(`else type '${ast_types_1.FT.inspect(defVal)}', expected '${returnType.dataType}'`);
|
|
747
|
+
return (0, ast_types_1.errorFor)("pick value type mismatch");
|
|
1052
748
|
}
|
|
1053
749
|
caseValue.push(" ELSE ", ...defVal.value, " END");
|
|
1054
750
|
return {
|
|
1055
751
|
dataType: returnType.dataType,
|
|
1056
752
|
expressionType: anyExpressionType,
|
|
1057
|
-
value: (0,
|
|
753
|
+
value: (0, ast_types_1.compressExpr)(caseValue),
|
|
1058
754
|
};
|
|
1059
755
|
}
|
|
1060
756
|
}
|
|
1061
757
|
exports.Pick = Pick;
|
|
758
|
+
function nullCompare(left, op, right) {
|
|
759
|
+
const not = op === "!=" || op === "!~";
|
|
760
|
+
if (left.dataType === "null" || right.dataType === "null") {
|
|
761
|
+
const maybeNot = not ? " NOT" : "";
|
|
762
|
+
if (left.dataType !== "null") {
|
|
763
|
+
return [...left.value, ` IS${maybeNot} NULL`];
|
|
764
|
+
}
|
|
765
|
+
if (right.dataType !== "null") {
|
|
766
|
+
return [...right.value, `IS${maybeNot} NULL`];
|
|
767
|
+
}
|
|
768
|
+
return [not ? "false" : "true"];
|
|
769
|
+
}
|
|
770
|
+
return undefined;
|
|
771
|
+
}
|
|
772
|
+
class Apply extends ast_main_1.ExprCompare {
|
|
773
|
+
constructor(left, right) {
|
|
774
|
+
super(left, "=", right);
|
|
775
|
+
this.left = left;
|
|
776
|
+
this.right = right;
|
|
777
|
+
this.elementType = "apply";
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
exports.Apply = Apply;
|
|
1062
781
|
//# sourceMappingURL=ast-expr.js.map
|