@malloydata/malloy 0.0.22-dev230117223957 → 0.0.22-dev230119001546

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.
@@ -22,215 +22,19 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.Pick = exports.PickWhen = exports.Range = 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.BinaryBoolean = exports.Boolean = exports.ExprNot = exports.ExprTime = exports.ExprRegEx = exports.ExprNumber = exports.ExprString = exports.TypeMistmatch = exports.FieldDeclaration = exports.ConstantSubExpression = exports.ExpressionDef = void 0;
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
31
  const field_space_1 = require("../field-space");
32
- const index_1 = require("./index");
32
+ const ast_main_1 = require("./ast-main");
33
+ const ast_types_1 = require("./ast-types");
33
34
  const apply_expr_1 = require("./apply-expr");
34
35
  const space_field_1 = require("../space-field");
35
36
  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 {
37
+ class ExprString extends ast_main_1.ExpressionDef {
234
38
  constructor(src) {
235
39
  super();
236
40
  this.elementType = "string literal";
@@ -240,7 +44,7 @@ class ExprString extends ExpressionDef {
240
44
  }
241
45
  getExpression(_fs) {
242
46
  return {
243
- ...index_1.FT.stringT,
47
+ ...ast_types_1.FT.stringT,
244
48
  value: [
245
49
  {
246
50
  type: "dialect",
@@ -252,7 +56,7 @@ class ExprString extends ExpressionDef {
252
56
  }
253
57
  }
254
58
  exports.ExprString = ExprString;
255
- class ExprNumber extends ExpressionDef {
59
+ class ExprNumber extends ast_main_1.ExpressionDef {
256
60
  constructor(n) {
257
61
  super();
258
62
  this.n = n;
@@ -262,11 +66,11 @@ class ExprNumber extends ExpressionDef {
262
66
  return this.constantExpression();
263
67
  }
264
68
  constantExpression() {
265
- return { ...index_1.FT.numberT, value: [this.n] };
69
+ return { ...ast_types_1.FT.numberT, value: [this.n] };
266
70
  }
267
71
  }
268
72
  exports.ExprNumber = ExprNumber;
269
- class ExprRegEx extends ExpressionDef {
73
+ class ExprRegEx extends ast_main_1.ExpressionDef {
270
74
  constructor(regex) {
271
75
  super();
272
76
  this.regex = regex;
@@ -281,40 +85,7 @@ class ExprRegEx extends ExpressionDef {
281
85
  }
282
86
  }
283
87
  exports.ExprRegEx = ExprRegEx;
284
- class ExprTime extends ExpressionDef {
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 {
88
+ class Unary extends ast_main_1.ExpressionDef {
318
89
  constructor(expr) {
319
90
  super({ expr });
320
91
  this.expr = expr;
@@ -324,7 +95,7 @@ class ExprNot extends Unary {
324
95
  constructor(expr) {
325
96
  super(expr);
326
97
  this.elementType = "not";
327
- this.legalChildTypes = [index_1.FT.boolT, index_1.FT.nullT];
98
+ this.legalChildTypes = [ast_types_1.FT.boolT, ast_types_1.FT.nullT];
328
99
  }
329
100
  getExpression(fs) {
330
101
  const notThis = this.expr.getExpression(fs);
@@ -335,53 +106,30 @@ class ExprNot extends Unary {
335
106
  value: (0, apply_expr_1.nullsafeNot)(notThis.value),
336
107
  };
337
108
  }
338
- return (0, index_1.errorFor)("not requires boolean");
109
+ return (0, ast_types_1.errorFor)("not requires boolean");
339
110
  }
340
111
  }
341
112
  exports.ExprNot = ExprNot;
342
- class Boolean extends ExpressionDef {
113
+ class Boolean extends ast_main_1.ExpressionDef {
343
114
  constructor(value) {
344
115
  super();
345
116
  this.value = value;
346
117
  this.elementType = "boolean literal";
347
118
  }
348
119
  getExpression() {
349
- return { ...index_1.FT.boolT, value: [this.value] };
120
+ return { ...ast_types_1.FT.boolT, value: [this.value] };
350
121
  }
351
122
  }
352
123
  exports.Boolean = Boolean;
353
- class BinaryBoolean extends ExpressionDef {
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 {
124
+ class ExprLogicalOp extends ast_main_1.BinaryBoolean {
377
125
  constructor() {
378
126
  super(...arguments);
379
127
  this.elementType = "logical operator";
380
- this.legalChildTypes = [index_1.FT.boolT, { ...index_1.FT.boolT, aggregate: true }];
128
+ this.legalChildTypes = [ast_types_1.FT.boolT, { ...ast_types_1.FT.boolT, aggregate: true }];
381
129
  }
382
130
  }
383
131
  exports.ExprLogicalOp = ExprLogicalOp;
384
- class ExprIdReference extends ExpressionDef {
132
+ class ExprIdReference extends ast_main_1.ExpressionDef {
385
133
  constructor(fieldReference) {
386
134
  super();
387
135
  this.fieldReference = fieldReference;
@@ -402,7 +150,7 @@ class ExprIdReference extends ExpressionDef {
402
150
  return { dataType, expressionType, value };
403
151
  }
404
152
  this.log(def.error);
405
- return (0, index_1.errorFor)(def.error);
153
+ return (0, ast_types_1.errorFor)(def.error);
406
154
  }
407
155
  apply(fs, op, expr) {
408
156
  const entry = this.fieldReference.getField(fs).found;
@@ -427,7 +175,7 @@ class ExprIdReference extends ExpressionDef {
427
175
  }
428
176
  }
429
177
  exports.ExprIdReference = ExprIdReference;
430
- class ExprNULL extends ExpressionDef {
178
+ class ExprNULL extends ast_main_1.ExpressionDef {
431
179
  constructor() {
432
180
  super(...arguments);
433
181
  this.elementType = "NULL";
@@ -441,7 +189,7 @@ class ExprNULL extends ExpressionDef {
441
189
  }
442
190
  }
443
191
  exports.ExprNULL = ExprNULL;
444
- class ExprParens extends ExpressionDef {
192
+ class ExprParens extends ast_main_1.ExpressionDef {
445
193
  constructor(expr) {
446
194
  super({ expr });
447
195
  this.expr = expr;
@@ -456,12 +204,12 @@ class ExprParens extends ExpressionDef {
456
204
  }
457
205
  }
458
206
  exports.ExprParens = ExprParens;
459
- class ExprMinus extends ExpressionDef {
207
+ class ExprMinus extends ast_main_1.ExpressionDef {
460
208
  constructor(expr) {
461
209
  super({ expr });
462
210
  this.expr = expr;
463
211
  this.elementType = "unary minus";
464
- this.legalChildTypes = [index_1.FT.numberT];
212
+ this.legalChildTypes = [ast_types_1.FT.numberT];
465
213
  }
466
214
  getExpression(fs) {
467
215
  const expr = this.expr.getExpression(fs);
@@ -471,18 +219,18 @@ class ExprMinus extends ExpressionDef {
471
219
  }
472
220
  return { ...expr, value: ["-", ...expr.value] };
473
221
  }
474
- return (0, index_1.errorFor)("negate requires number");
222
+ return (0, ast_types_1.errorFor)("negate requires number");
475
223
  }
476
224
  }
477
225
  exports.ExprMinus = ExprMinus;
478
- class BinaryNumeric extends ExpressionDef {
226
+ class BinaryNumeric extends ast_main_1.ExpressionDef {
479
227
  constructor(left, op, right) {
480
228
  super({ left, right });
481
229
  this.left = left;
482
230
  this.op = op;
483
231
  this.right = right;
484
232
  this.elementType = "numeric binary abstract";
485
- this.legalChildTypes = [index_1.FT.numberT];
233
+ this.legalChildTypes = [ast_types_1.FT.numberT];
486
234
  }
487
235
  getExpression(fs) {
488
236
  return this.right.apply(fs, this.op, this.left);
@@ -503,7 +251,7 @@ class ExprMulDiv extends BinaryNumeric {
503
251
  }
504
252
  }
505
253
  exports.ExprMulDiv = ExprMulDiv;
506
- class ExprAlternationTree extends BinaryBoolean {
254
+ class ExprAlternationTree extends ast_main_1.BinaryBoolean {
507
255
  constructor(left, op, right) {
508
256
  super(left, op, right);
509
257
  this.elementType = "alternation";
@@ -515,7 +263,7 @@ class ExprAlternationTree extends BinaryBoolean {
515
263
  return {
516
264
  dataType: "boolean",
517
265
  expressionType: (0, malloy_types_1.maxExpressionType)(choice1.expressionType, choice2.expressionType),
518
- value: (0, index_1.compose)(choice1.value, this.op === "&" ? "and" : "or", choice2.value),
266
+ value: (0, ast_types_1.compose)(choice1.value, this.op === "&" ? "and" : "or", choice2.value),
519
267
  };
520
268
  }
521
269
  requestExpression(_fs) {
@@ -523,15 +271,15 @@ class ExprAlternationTree extends BinaryBoolean {
523
271
  }
524
272
  getExpression(_fs) {
525
273
  this.log(`Alternation tree has no value`);
526
- return (0, index_1.errorFor)("no value from alternation tree");
274
+ return (0, ast_types_1.errorFor)("no value from alternation tree");
527
275
  }
528
276
  }
529
277
  exports.ExprAlternationTree = ExprAlternationTree;
530
- class ExprAggregateFunction extends ExpressionDef {
278
+ class ExprAggregateFunction extends ast_main_1.ExpressionDef {
531
279
  constructor(func, expr) {
532
280
  super();
533
281
  this.func = func;
534
- this.legalChildTypes = [index_1.FT.numberT];
282
+ this.legalChildTypes = [ast_types_1.FT.numberT];
535
283
  this.elementType = func;
536
284
  if (expr) {
537
285
  this.expr = expr;
@@ -560,18 +308,18 @@ class ExprAggregateFunction extends ExpressionDef {
560
308
  else {
561
309
  if (!(sourceFoot instanceof space_field_1.StructSpaceField)) {
562
310
  this.log(`Aggregate source cannot be a ${footType.type}`);
563
- return (0, index_1.errorFor)(`Aggregate source cannot be a ${footType.type}`);
311
+ return (0, ast_types_1.errorFor)(`Aggregate source cannot be a ${footType.type}`);
564
312
  }
565
313
  }
566
314
  }
567
315
  else {
568
316
  this.log(`Reference to undefined value ${this.source.refString}`);
569
- return (0, index_1.errorFor)(`Reference to undefined value ${this.source.refString}`);
317
+ return (0, ast_types_1.errorFor)(`Reference to undefined value ${this.source.refString}`);
570
318
  }
571
319
  }
572
320
  if (exprVal === undefined) {
573
321
  this.log("Missing expression for aggregate function");
574
- return (0, index_1.errorFor)("agggregate without expression");
322
+ return (0, ast_types_1.errorFor)("agggregate without expression");
575
323
  }
576
324
  if (this.typeCheck(this.expr || this, {
577
325
  ...exprVal,
@@ -591,13 +339,13 @@ class ExprAggregateFunction extends ExpressionDef {
591
339
  value: [f],
592
340
  };
593
341
  }
594
- return (0, index_1.errorFor)("aggregate type check");
342
+ return (0, ast_types_1.errorFor)("aggregate type check");
595
343
  }
596
344
  }
597
345
  class ExprMin extends ExprAggregateFunction {
598
346
  constructor(expr) {
599
347
  super("min", expr);
600
- this.legalChildTypes = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
348
+ this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
601
349
  }
602
350
  returns(forExpression) {
603
351
  return forExpression.dataType;
@@ -607,7 +355,7 @@ exports.ExprMin = ExprMin;
607
355
  class ExprMax extends ExprAggregateFunction {
608
356
  constructor(expr) {
609
357
  super("max", expr);
610
- this.legalChildTypes = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
358
+ this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
611
359
  }
612
360
  returns(forExpression) {
613
361
  return forExpression.dataType;
@@ -617,7 +365,7 @@ exports.ExprMax = ExprMax;
617
365
  class ExprCountDistinct extends ExprAggregateFunction {
618
366
  constructor(expr) {
619
367
  super("count_distinct", expr);
620
- this.legalChildTypes = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
368
+ this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
621
369
  }
622
370
  }
623
371
  exports.ExprCountDistinct = ExprCountDistinct;
@@ -686,13 +434,13 @@ class ExprSum extends ExprAsymmetric {
686
434
  }
687
435
  }
688
436
  exports.ExprSum = ExprSum;
689
- class ExprUngroup extends ExpressionDef {
437
+ class ExprUngroup extends ast_main_1.ExpressionDef {
690
438
  constructor(control, expr, fields) {
691
439
  super({ expr, fields });
692
440
  this.control = control;
693
441
  this.expr = expr;
694
442
  this.fields = fields;
695
- this.legalChildTypes = index_1.FT.anyAtomicT;
443
+ this.legalChildTypes = ast_types_1.FT.anyAtomicT;
696
444
  this.elementType = "ungroup";
697
445
  }
698
446
  returns(_forExpression) {
@@ -702,7 +450,7 @@ class ExprUngroup extends ExpressionDef {
702
450
  const exprVal = this.expr.getExpression(fs);
703
451
  if (!(0, malloy_types_1.expressionIsAggregate)(exprVal.expressionType)) {
704
452
  this.expr.log(`${this.control}() expression must be an aggregate`);
705
- return (0, index_1.errorFor)("ungrouped scalar");
453
+ return (0, ast_types_1.errorFor)("ungrouped scalar");
706
454
  }
707
455
  const ungroup = { type: this.control, e: exprVal.value };
708
456
  if (this.typeCheck(this.expr, { ...exprVal, expressionType: "scalar" })) {
@@ -713,7 +461,7 @@ class ExprUngroup extends ExpressionDef {
713
461
  }
714
462
  if (!(qs instanceof field_space_1.QuerySpace)) {
715
463
  this.log(`${this.control}() must be in a query -- weird internal error`);
716
- return (0, index_1.errorFor)("ungroup query check");
464
+ return (0, ast_types_1.errorFor)("ungroup query check");
717
465
  }
718
466
  const output = qs.result;
719
467
  const dstFields = [];
@@ -733,11 +481,11 @@ class ExprUngroup extends ExpressionDef {
733
481
  };
734
482
  }
735
483
  this.log(`${this.control}() incompatible type`);
736
- return (0, index_1.errorFor)("ungrouped type check");
484
+ return (0, ast_types_1.errorFor)("ungrouped type check");
737
485
  }
738
486
  }
739
487
  exports.ExprUngroup = ExprUngroup;
740
- class WhenClause extends ExpressionDef {
488
+ class WhenClause extends ast_main_1.ExpressionDef {
741
489
  constructor(whenThis, thenThis) {
742
490
  super({ whenThis, thenThis });
743
491
  this.whenThis = whenThis;
@@ -749,7 +497,7 @@ class WhenClause extends ExpressionDef {
749
497
  }
750
498
  }
751
499
  exports.WhenClause = WhenClause;
752
- class ExprCase extends ExpressionDef {
500
+ class ExprCase extends ast_main_1.ExpressionDef {
753
501
  constructor(when, elseClause) {
754
502
  super({ when });
755
503
  this.when = when;
@@ -766,9 +514,9 @@ class ExprCase extends ExpressionDef {
766
514
  const thenExpr = clause.thenThis.getExpression(fs);
767
515
  expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, (0, malloy_types_1.maxExpressionType)(whenExpr.expressionType, thenExpr.expressionType));
768
516
  if (thenExpr.dataType !== "null") {
769
- if (retType && !index_1.FT.typeEq(retType, thenExpr)) {
770
- this.log(`Mismatched THEN clause types, ${index_1.FT.inspect(retType, thenExpr)}`);
771
- return (0, index_1.errorFor)("then typecheck");
517
+ if (retType && !ast_types_1.FT.typeEq(retType, thenExpr)) {
518
+ this.log(`Mismatched THEN clause types, ${ast_types_1.FT.inspect(retType, thenExpr)}`);
519
+ return (0, ast_types_1.errorFor)("then typecheck");
772
520
  }
773
521
  else {
774
522
  retType = thenExpr;
@@ -781,9 +529,9 @@ class ExprCase extends ExpressionDef {
781
529
  expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, elseExpr.expressionType);
782
530
  caseExpr.push(" ELSE ", ...elseExpr.value);
783
531
  if (elseExpr.dataType !== "null") {
784
- if (retType && !index_1.FT.typeEq(retType, elseExpr)) {
785
- this.log(`Mismatched ELSE clause type, ${index_1.FT.inspect(retType, elseExpr)}`);
786
- return (0, index_1.errorFor)("else typecheck");
532
+ if (retType && !ast_types_1.FT.typeEq(retType, elseExpr)) {
533
+ this.log(`Mismatched ELSE clause type, ${ast_types_1.FT.inspect(retType, elseExpr)}`);
534
+ return (0, ast_types_1.errorFor)("else typecheck");
787
535
  }
788
536
  else {
789
537
  retType = elseExpr;
@@ -792,7 +540,7 @@ class ExprCase extends ExpressionDef {
792
540
  }
793
541
  if (retType === undefined) {
794
542
  this.log("case statement type not computable");
795
- return (0, index_1.errorFor)("typeless case");
543
+ return (0, ast_types_1.errorFor)("typeless case");
796
544
  }
797
545
  caseExpr.push(" END");
798
546
  return {
@@ -803,13 +551,13 @@ class ExprCase extends ExpressionDef {
803
551
  }
804
552
  }
805
553
  exports.ExprCase = ExprCase;
806
- class ExprFilter extends ExpressionDef {
554
+ class ExprFilter extends ast_main_1.ExpressionDef {
807
555
  constructor(expr, filter) {
808
556
  super({ expr, filter });
809
557
  this.expr = expr;
810
558
  this.filter = filter;
811
559
  this.elementType = "filtered expression";
812
- this.legalChildTypes = index_1.FT.anyAtomicT;
560
+ this.legalChildTypes = ast_types_1.FT.anyAtomicT;
813
561
  }
814
562
  getExpression(fs) {
815
563
  const testList = this.filter.getFilterList(fs);
@@ -817,7 +565,7 @@ class ExprFilter extends ExpressionDef {
817
565
  for (const cond of testList) {
818
566
  if ((0, malloy_types_1.expressionIsCalculation)(cond.expressionType)) {
819
567
  this.filter.log("Cannot filter a field with an aggregate or analytical computation");
820
- return (0, index_1.errorFor)("no filter on aggregate");
568
+ return (0, ast_types_1.errorFor)("no filter on aggregate");
821
569
  }
822
570
  }
823
571
  if (resultExpr.expressionType === "scalar") {
@@ -838,7 +586,7 @@ class ExprFilter extends ExpressionDef {
838
586
  };
839
587
  }
840
588
  this.expr.log(`Cannot filter '${resultExpr.dataType}' data`);
841
- return (0, index_1.errorFor)("cannot filter type");
589
+ return (0, ast_types_1.errorFor)("cannot filter type");
842
590
  }
843
591
  }
844
592
  exports.ExprFilter = ExprFilter;
@@ -846,7 +594,7 @@ function isCastType(t) {
846
594
  return ["string", "number", "boolean", "date", "timestamp"].includes(t);
847
595
  }
848
596
  exports.isCastType = isCastType;
849
- class ExprCast extends ExpressionDef {
597
+ class ExprCast extends ast_main_1.ExpressionDef {
850
598
  constructor(expr, castType, safe = false) {
851
599
  super({ expr });
852
600
  this.expr = expr;
@@ -859,83 +607,33 @@ class ExprCast extends ExpressionDef {
859
607
  return {
860
608
  dataType: this.castType,
861
609
  expressionType: expr.expressionType,
862
- value: (0, index_1.compressExpr)((0, time_utils_1.castTo)(this.castType, expr.value, this.safe)),
610
+ value: (0, ast_types_1.compressExpr)((0, time_utils_1.castTo)(this.castType, expr.value, this.safe)),
863
611
  };
864
612
  }
865
613
  }
866
614
  exports.ExprCast = ExprCast;
867
- class TopBy extends index_1.MalloyElement {
615
+ class TopBy extends ast_main_1.MalloyElement {
868
616
  constructor(by) {
869
617
  super();
870
618
  this.by = by;
871
619
  this.elementType = "topBy";
872
- if (by instanceof ExpressionDef) {
620
+ if (by instanceof ast_main_1.ExpressionDef) {
873
621
  this.has({ by });
874
622
  }
875
623
  }
876
624
  getBy(fs) {
877
- if (this.by instanceof ExpressionDef) {
625
+ if (this.by instanceof ast_main_1.ExpressionDef) {
878
626
  const byExpr = this.by.getExpression(fs);
879
627
  if (!(0, malloy_types_1.expressionIsAggregate)(byExpr.expressionType)) {
880
628
  this.log("top by expression must be an aggregate");
881
629
  }
882
- return { by: "expression", e: (0, index_1.compressExpr)(byExpr.value) };
630
+ return { by: "expression", e: (0, ast_types_1.compressExpr)(byExpr.value) };
883
631
  }
884
632
  return { by: "name", name: this.by };
885
633
  }
886
634
  }
887
635
  exports.TopBy = TopBy;
888
- class Range extends ExpressionDef {
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 {
636
+ class PickWhen extends ast_main_1.MalloyElement {
939
637
  constructor(pick, when) {
940
638
  super({ when });
941
639
  this.pick = pick;
@@ -945,7 +643,7 @@ class PickWhen extends index_1.MalloyElement {
945
643
  }
946
644
  }
947
645
  exports.PickWhen = PickWhen;
948
- class Pick extends ExpressionDef {
646
+ class Pick extends ast_main_1.ExpressionDef {
949
647
  constructor(choices, elsePick) {
950
648
  super({ choices });
951
649
  this.choices = choices;
@@ -982,10 +680,10 @@ class Pick extends ExpressionDef {
982
680
  : expr.getExpression(fs);
983
681
  anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(whenExpr.expressionType, thenExpr.expressionType));
984
682
  if (returnType) {
985
- if (!index_1.FT.typeEq(returnType, thenExpr, true)) {
986
- const whenType = index_1.FT.inspect(thenExpr);
683
+ if (!ast_types_1.FT.typeEq(returnType, thenExpr, true)) {
684
+ const whenType = ast_types_1.FT.inspect(thenExpr);
987
685
  this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
988
- return (0, index_1.errorFor)("pick when type");
686
+ return (0, ast_types_1.errorFor)("pick when type");
989
687
  }
990
688
  }
991
689
  else {
@@ -996,32 +694,32 @@ class Pick extends ExpressionDef {
996
694
  const elsePart = this.elsePick || expr;
997
695
  const elseVal = elsePart.getExpression(fs);
998
696
  returnType || (returnType = elseVal);
999
- if (!index_1.FT.typeEq(returnType, elseVal, true)) {
697
+ if (!ast_types_1.FT.typeEq(returnType, elseVal, true)) {
1000
698
  const errSrc = this.elsePick ? "else" : "pick default";
1001
- this.log(`${errSrc} type '${index_1.FT.inspect(elseVal)}', expected '${returnType.dataType}'`);
1002
- return (0, index_1.errorFor)("pick else type");
699
+ this.log(`${errSrc} type '${ast_types_1.FT.inspect(elseVal)}', expected '${returnType.dataType}'`);
700
+ return (0, ast_types_1.errorFor)("pick else type");
1003
701
  }
1004
702
  return {
1005
703
  dataType: returnType.dataType,
1006
704
  expressionType: (0, malloy_types_1.maxExpressionType)(anyExpressionType, elseVal.expressionType),
1007
- value: (0, index_1.compressExpr)([...caseValue, " ELSE ", ...elseVal.value, " END"]),
705
+ value: (0, ast_types_1.compressExpr)([...caseValue, " ELSE ", ...elseVal.value, " END"]),
1008
706
  };
1009
707
  }
1010
708
  getExpression(fs) {
1011
709
  if (this.elsePick === undefined) {
1012
710
  this.log("pick incomplete, missing 'else'");
1013
- return (0, index_1.errorFor)("no value for partial pick");
711
+ return (0, ast_types_1.errorFor)("no value for partial pick");
1014
712
  }
1015
713
  const choiceValues = [];
1016
714
  for (const c of this.choices) {
1017
715
  if (c.pick === undefined) {
1018
716
  this.log("pick with no value can only be used with apply");
1019
- return (0, index_1.errorFor)("no value for partial pick");
717
+ return (0, ast_types_1.errorFor)("no value for partial pick");
1020
718
  }
1021
719
  const pickWhen = c.when.requestExpression(fs);
1022
720
  if (pickWhen === undefined) {
1023
721
  this.log("pick with partial when can only be used with apply");
1024
- return (0, index_1.errorFor)("partial when");
722
+ return (0, ast_types_1.errorFor)("partial when");
1025
723
  }
1026
724
  choiceValues.push({
1027
725
  pick: c.pick.getExpression(fs),
@@ -1032,31 +730,54 @@ class Pick extends ExpressionDef {
1032
730
  const caseValue = ["CASE"];
1033
731
  let anyExpressionType = returnType.expressionType;
1034
732
  for (const aChoice of choiceValues) {
1035
- if (!index_1.FT.typeEq(aChoice.when, index_1.FT.boolT)) {
1036
- this.log(`when expression must be boolean, not '${index_1.FT.inspect(aChoice.when)}`);
1037
- return (0, index_1.errorFor)("pick when type");
733
+ if (!ast_types_1.FT.typeEq(aChoice.when, ast_types_1.FT.boolT)) {
734
+ this.log(`when expression must be boolean, not '${ast_types_1.FT.inspect(aChoice.when)}`);
735
+ return (0, ast_types_1.errorFor)("pick when type");
1038
736
  }
1039
- if (!index_1.FT.typeEq(returnType, aChoice.pick, true)) {
1040
- const whenType = index_1.FT.inspect(aChoice.pick);
737
+ if (!ast_types_1.FT.typeEq(returnType, aChoice.pick, true)) {
738
+ const whenType = ast_types_1.FT.inspect(aChoice.pick);
1041
739
  this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
1042
- return (0, index_1.errorFor)("pick value type");
740
+ return (0, ast_types_1.errorFor)("pick value type");
1043
741
  }
1044
742
  anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(aChoice.pick.expressionType, aChoice.when.expressionType));
1045
743
  caseValue.push(" WHEN ", ...aChoice.when.value, " THEN ", ...aChoice.pick.value);
1046
744
  }
1047
745
  const defVal = this.elsePick.getExpression(fs);
1048
746
  anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, defVal.expressionType);
1049
- if (!index_1.FT.typeEq(returnType, defVal, true)) {
1050
- this.elsePick.log(`else type '${index_1.FT.inspect(defVal)}', expected '${returnType.dataType}'`);
1051
- return (0, index_1.errorFor)("pick value type mismatch");
747
+ if (!ast_types_1.FT.typeEq(returnType, defVal, true)) {
748
+ this.elsePick.log(`else type '${ast_types_1.FT.inspect(defVal)}', expected '${returnType.dataType}'`);
749
+ return (0, ast_types_1.errorFor)("pick value type mismatch");
1052
750
  }
1053
751
  caseValue.push(" ELSE ", ...defVal.value, " END");
1054
752
  return {
1055
753
  dataType: returnType.dataType,
1056
754
  expressionType: anyExpressionType,
1057
- value: (0, index_1.compressExpr)(caseValue),
755
+ value: (0, ast_types_1.compressExpr)(caseValue),
1058
756
  };
1059
757
  }
1060
758
  }
1061
759
  exports.Pick = Pick;
760
+ function nullCompare(left, op, right) {
761
+ const not = op === "!=" || op === "!~";
762
+ if (left.dataType === "null" || right.dataType === "null") {
763
+ const maybeNot = not ? " NOT" : "";
764
+ if (left.dataType !== "null") {
765
+ return [...left.value, ` IS${maybeNot} NULL`];
766
+ }
767
+ if (right.dataType !== "null") {
768
+ return [...right.value, `IS${maybeNot} NULL`];
769
+ }
770
+ return [not ? "false" : "true"];
771
+ }
772
+ return undefined;
773
+ }
774
+ class Apply extends ast_main_1.ExprCompare {
775
+ constructor(left, right) {
776
+ super(left, "=", right);
777
+ this.left = left;
778
+ this.right = right;
779
+ this.elementType = "apply";
780
+ }
781
+ }
782
+ exports.Apply = Apply;
1062
783
  //# sourceMappingURL=ast-expr.js.map