@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.
@@ -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.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
- const field_space_1 = require("../field-space");
32
- const index_1 = require("./index");
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
- ...index_1.FT.stringT,
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 { ...index_1.FT.numberT, value: [this.n] };
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 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 {
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 = [index_1.FT.boolT, index_1.FT.nullT];
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, index_1.errorFor)("not requires boolean");
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 { ...index_1.FT.boolT, value: [this.value] };
118
+ return { ...ast_types_1.FT.boolT, value: [this.value] };
350
119
  }
351
120
  }
352
121
  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 {
122
+ class ExprLogicalOp extends ast_main_1.BinaryBoolean {
377
123
  constructor() {
378
124
  super(...arguments);
379
125
  this.elementType = "logical operator";
380
- this.legalChildTypes = [index_1.FT.boolT, { ...index_1.FT.boolT, aggregate: true }];
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, index_1.errorFor)(def.error);
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 space_field_1.SpaceParam) {
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 = [index_1.FT.numberT];
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, index_1.errorFor)("negate requires number");
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 = [index_1.FT.numberT];
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, index_1.compose)(choice1.value, this.op === "&" ? "and" : "or", choice2.value),
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, index_1.errorFor)("no value from alternation tree");
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 = [index_1.FT.numberT];
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 space_field_1.StructSpaceField)) {
307
+ if (!(sourceFoot instanceof ast_main_1.StructSpaceField)) {
562
308
  this.log(`Aggregate source cannot be a ${footType.type}`);
563
- return (0, index_1.errorFor)(`Aggregate source cannot be a ${footType.type}`);
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, index_1.errorFor)(`Reference to undefined value ${this.source.refString}`);
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, index_1.errorFor)("agggregate without expression");
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, index_1.errorFor)("aggregate type check");
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 = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
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 = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
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 = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
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 = index_1.FT.anyAtomicT;
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, index_1.errorFor)("ungrouped scalar");
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 field_space_1.DefSpace) {
457
+ if (fs instanceof ast_main_1.DefSpace) {
712
458
  qs = fs.realFS;
713
459
  }
714
- if (!(qs instanceof field_space_1.QuerySpace)) {
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, index_1.errorFor)("ungroup query check");
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, index_1.errorFor)("ungrouped type check");
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 && !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");
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 && !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");
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, index_1.errorFor)("typeless case");
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 = index_1.FT.anyAtomicT;
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, index_1.errorFor)("no filter on aggregate");
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, index_1.errorFor)("cannot filter type");
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, index_1.compressExpr)((0, time_utils_1.castTo)(this.castType, expr.value, this.safe)),
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 index_1.MalloyElement {
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, index_1.compressExpr)(byExpr.value) };
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 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 {
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 (!index_1.FT.typeEq(returnType, thenExpr, true)) {
986
- const whenType = index_1.FT.inspect(thenExpr);
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, index_1.errorFor)("pick when type");
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 (!index_1.FT.typeEq(returnType, elseVal, true)) {
695
+ if (!ast_types_1.FT.typeEq(returnType, elseVal, true)) {
1000
696
  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");
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, index_1.compressExpr)([...caseValue, " ELSE ", ...elseVal.value, " END"]),
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, index_1.errorFor)("no value for partial pick");
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, index_1.errorFor)("no value for partial pick");
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, index_1.errorFor)("partial when");
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 (!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");
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 (!index_1.FT.typeEq(returnType, aChoice.pick, true)) {
1040
- const whenType = index_1.FT.inspect(aChoice.pick);
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, index_1.errorFor)("pick value type");
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 (!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");
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, index_1.compressExpr)(caseValue),
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