@malloydata/malloy 0.0.427 → 0.0.428

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.
Files changed (90) hide show
  1. package/dist/lang/ast/expressions/apply.d.ts +1 -1
  2. package/dist/lang/ast/expressions/apply.js +2 -2
  3. package/dist/lang/ast/expressions/binary-boolean.d.ts +1 -1
  4. package/dist/lang/ast/expressions/binary-boolean.js +1 -1
  5. package/dist/lang/ast/expressions/binary-numeric.d.ts +1 -1
  6. package/dist/lang/ast/expressions/binary-numeric.js +1 -1
  7. package/dist/lang/ast/expressions/boolean.d.ts +1 -1
  8. package/dist/lang/ast/expressions/boolean.js +1 -1
  9. package/dist/lang/ast/expressions/case.d.ts +1 -1
  10. package/dist/lang/ast/expressions/case.js +1 -1
  11. package/dist/lang/ast/expressions/constant-expression.d.ts +2 -1
  12. package/dist/lang/ast/expressions/constant-expression.js +6 -1
  13. package/dist/lang/ast/expressions/expr-aggregate-function.d.ts +1 -1
  14. package/dist/lang/ast/expressions/expr-aggregate-function.js +14 -7
  15. package/dist/lang/ast/expressions/expr-alternation-tree.d.ts +1 -1
  16. package/dist/lang/ast/expressions/expr-alternation-tree.js +1 -1
  17. package/dist/lang/ast/expressions/expr-array-literal.d.ts +1 -1
  18. package/dist/lang/ast/expressions/expr-array-literal.js +1 -1
  19. package/dist/lang/ast/expressions/expr-cast.d.ts +1 -1
  20. package/dist/lang/ast/expressions/expr-cast.js +1 -1
  21. package/dist/lang/ast/expressions/expr-coalesce.d.ts +1 -1
  22. package/dist/lang/ast/expressions/expr-coalesce.js +1 -1
  23. package/dist/lang/ast/expressions/expr-compare.d.ts +4 -4
  24. package/dist/lang/ast/expressions/expr-compare.js +4 -4
  25. package/dist/lang/ast/expressions/expr-count.d.ts +1 -1
  26. package/dist/lang/ast/expressions/expr-count.js +1 -1
  27. package/dist/lang/ast/expressions/expr-filter-expr.d.ts +1 -1
  28. package/dist/lang/ast/expressions/expr-filter-expr.js +1 -1
  29. package/dist/lang/ast/expressions/expr-func.d.ts +1 -1
  30. package/dist/lang/ast/expressions/expr-func.js +1 -1
  31. package/dist/lang/ast/expressions/expr-given.d.ts +1 -1
  32. package/dist/lang/ast/expressions/expr-given.js +1 -1
  33. package/dist/lang/ast/expressions/expr-granular-time.d.ts +1 -1
  34. package/dist/lang/ast/expressions/expr-granular-time.js +1 -1
  35. package/dist/lang/ast/expressions/expr-id-reference.d.ts +1 -1
  36. package/dist/lang/ast/expressions/expr-id-reference.js +1 -1
  37. package/dist/lang/ast/expressions/expr-minus.d.ts +1 -1
  38. package/dist/lang/ast/expressions/expr-minus.js +1 -1
  39. package/dist/lang/ast/expressions/expr-not.d.ts +1 -1
  40. package/dist/lang/ast/expressions/expr-not.js +1 -1
  41. package/dist/lang/ast/expressions/expr-now.d.ts +1 -1
  42. package/dist/lang/ast/expressions/expr-now.js +1 -1
  43. package/dist/lang/ast/expressions/expr-null.d.ts +3 -3
  44. package/dist/lang/ast/expressions/expr-null.js +14 -9
  45. package/dist/lang/ast/expressions/expr-number.d.ts +1 -1
  46. package/dist/lang/ast/expressions/expr-number.js +1 -1
  47. package/dist/lang/ast/expressions/expr-parens.d.ts +1 -1
  48. package/dist/lang/ast/expressions/expr-parens.js +5 -2
  49. package/dist/lang/ast/expressions/expr-props.d.ts +1 -1
  50. package/dist/lang/ast/expressions/expr-props.js +1 -1
  51. package/dist/lang/ast/expressions/expr-record-literal.d.ts +1 -1
  52. package/dist/lang/ast/expressions/expr-record-literal.js +1 -1
  53. package/dist/lang/ast/expressions/expr-regex.d.ts +1 -1
  54. package/dist/lang/ast/expressions/expr-regex.js +1 -1
  55. package/dist/lang/ast/expressions/expr-string.d.ts +1 -1
  56. package/dist/lang/ast/expressions/expr-string.js +1 -1
  57. package/dist/lang/ast/expressions/expr-time-extract.d.ts +1 -1
  58. package/dist/lang/ast/expressions/expr-time-extract.js +1 -1
  59. package/dist/lang/ast/expressions/expr-time.d.ts +1 -1
  60. package/dist/lang/ast/expressions/expr-time.js +1 -1
  61. package/dist/lang/ast/expressions/expr-ungroup.d.ts +1 -1
  62. package/dist/lang/ast/expressions/expr-ungroup.js +1 -1
  63. package/dist/lang/ast/expressions/for-range.d.ts +1 -1
  64. package/dist/lang/ast/expressions/for-range.js +1 -1
  65. package/dist/lang/ast/expressions/partial-compare.d.ts +1 -1
  66. package/dist/lang/ast/expressions/partial-compare.js +1 -1
  67. package/dist/lang/ast/expressions/pick-when.d.ts +1 -1
  68. package/dist/lang/ast/expressions/pick-when.js +1 -1
  69. package/dist/lang/ast/expressions/range.d.ts +1 -1
  70. package/dist/lang/ast/expressions/range.js +1 -1
  71. package/dist/lang/ast/expressions/time-literal.d.ts +2 -2
  72. package/dist/lang/ast/expressions/time-literal.js +2 -2
  73. package/dist/lang/ast/field-space/parameter-space.d.ts +1 -0
  74. package/dist/lang/ast/field-space/parameter-space.js +6 -0
  75. package/dist/lang/ast/field-space/passthrough-space.d.ts +1 -0
  76. package/dist/lang/ast/field-space/passthrough-space.js +3 -0
  77. package/dist/lang/ast/field-space/static-space.d.ts +8 -0
  78. package/dist/lang/ast/field-space/static-space.js +14 -0
  79. package/dist/lang/ast/query-builders/index-builder.js +1 -1
  80. package/dist/lang/ast/query-properties/drill.d.ts +1 -1
  81. package/dist/lang/ast/query-properties/drill.js +1 -1
  82. package/dist/lang/ast/types/expression-def.d.ts +50 -23
  83. package/dist/lang/ast/types/expression-def.js +127 -65
  84. package/dist/lang/ast/types/field-space.d.ts +14 -0
  85. package/dist/lang/ast/types/field-space.js +36 -0
  86. package/dist/model/malloy_types.d.ts +0 -13
  87. package/dist/model/malloy_types.js +0 -19
  88. package/dist/version.d.ts +1 -1
  89. package/dist/version.js +1 -1
  90. package/package.json +4 -4
@@ -15,15 +15,18 @@ class ExprParens extends expression_def_1.ExpressionDef {
15
15
  requestExpression(fs) {
16
16
  return this.expr.requestExpression(fs);
17
17
  }
18
- getExpression(fs) {
18
+ computeExpression(fs) {
19
19
  const subExpr = this.expr.getExpression(fs);
20
20
  return { ...subExpr, value: { node: '()', e: subExpr.value } };
21
21
  }
22
22
  apply(fs, op, left, doWarn) {
23
23
  if (this.expr.atNodeType() === expression_def_1.ATNodeType.Or) {
24
+ // Parens are invisible to `?`/`=`, so hand the tree the operator and
25
+ // doWarn, which decides whether an un-collapsible `|` list is worth a
26
+ // warning. The base ignores doWarn, which is why it is not passed on.
24
27
  return this.expr.apply(fs, op, left, doWarn);
25
28
  }
26
- return (0, expression_def_1.applyBinary)(fs, left, op, this);
29
+ return super.apply(fs, op, left);
27
30
  }
28
31
  atNodeType() {
29
32
  return this.expr.atNodeType();
@@ -10,7 +10,7 @@ export declare class ExprProps extends ExpressionDef {
10
10
  legalChildTypes: import("../../..").TypeDesc[];
11
11
  constructor(expr: ExpressionDef, statements: FieldPropStatement[]);
12
12
  private getFilteredExpression;
13
- getExpression(fs: FieldSpace): ExprValue;
13
+ protected computeExpression(fs: FieldSpace): ExprValue;
14
14
  getGroupedBys(fs: FieldSpace, expr: ExprValue, groupedBys: GroupedBy[]): {
15
15
  requiresGroupBy: import("../../../model").RequiredGroupBy[] | undefined;
16
16
  type: "string";
@@ -87,7 +87,7 @@ class ExprProps extends expression_def_1.ExpressionDef {
87
87
  }
88
88
  return expr;
89
89
  }
90
- getExpression(fs) {
90
+ computeExpression(fs) {
91
91
  const partitionBys = [];
92
92
  let limit;
93
93
  const orderBys = [];
@@ -19,7 +19,7 @@ export declare class RecordLiteral extends ExpressionDef {
19
19
  readonly pairs: RecordElement[];
20
20
  elementType: string;
21
21
  constructor(pairs: RecordElement[]);
22
- getExpression(fs: FieldSpace): ExprValue;
22
+ protected computeExpression(fs: FieldSpace): ExprValue;
23
23
  getRecord(fs: FieldSpace, kidNames: string[]): ExprValue;
24
24
  getNextElement(fs: FieldSpace, headValue: ExprValue): ExprValue;
25
25
  }
@@ -70,7 +70,7 @@ class RecordLiteral extends expression_def_1.ExpressionDef {
70
70
  this.elementType = 'record literal';
71
71
  this.has({ pairs });
72
72
  }
73
- getExpression(fs) {
73
+ computeExpression(fs) {
74
74
  return this.getRecord(fs, []);
75
75
  }
76
76
  getRecord(fs, kidNames) {
@@ -4,5 +4,5 @@ export declare class ExprRegEx extends ExpressionDef {
4
4
  readonly regex: string;
5
5
  elementType: string;
6
6
  constructor(regex: string);
7
- getExpression(): ExprValue;
7
+ protected computeExpression(): ExprValue;
8
8
  }
@@ -13,7 +13,7 @@ class ExprRegEx extends expression_def_1.ExpressionDef {
13
13
  this.regex = regex;
14
14
  this.elementType = 'regular expression literal';
15
15
  }
16
- getExpression() {
16
+ computeExpression() {
17
17
  return (0, expr_value_1.literalExprValue)({
18
18
  dataType: { type: 'regular expression' },
19
19
  value: { node: 'regexpLiteral', literal: this.regex },
@@ -6,6 +6,6 @@ export declare class ExprString extends ExpressionDef {
6
6
  elementType: string;
7
7
  value: string;
8
8
  constructor(src: string);
9
- getExpression(_fs: FieldSpace): ExprValue;
9
+ protected computeExpression(_fs: FieldSpace): ExprValue;
10
10
  getStableLiteral(): Malloy.LiteralValue;
11
11
  }
@@ -13,7 +13,7 @@ class ExprString extends expression_def_1.ExpressionDef {
13
13
  this.elementType = 'string literal';
14
14
  this.value = src;
15
15
  }
16
- getExpression(_fs) {
16
+ computeExpression(_fs) {
17
17
  return (0, expr_value_1.literalExprValue)({
18
18
  dataType: { type: 'string' },
19
19
  value: { node: 'stringLiteral', literal: this.value },
@@ -9,5 +9,5 @@ export declare class ExprTimeExtract extends ExpressionDef {
9
9
  static pluralMap: Record<string, ExtractUnit>;
10
10
  static extractor(funcName: string): ExtractUnit | undefined;
11
11
  constructor(extractText: string, args: ExpressionDef[]);
12
- getExpression(fs: FieldSpace): ExprValue;
12
+ protected computeExpression(fs: FieldSpace): ExprValue;
13
13
  }
@@ -25,7 +25,7 @@ class ExprTimeExtract extends expression_def_1.ExpressionDef {
25
25
  this.args = args;
26
26
  this.elementType = 'timeExtract';
27
27
  }
28
- getExpression(fs) {
28
+ computeExpression(fs) {
29
29
  const extractTo = ExprTimeExtract.extractor(this.extractText);
30
30
  if (extractTo) {
31
31
  if (this.args.length !== 1) {
@@ -6,6 +6,6 @@ export declare class ExprTime extends ExpressionDef {
6
6
  elementType: string;
7
7
  readonly translationValue: ExprValue;
8
8
  constructor(timeType: TemporalFieldType, value: Expr, from?: ExprValue[]);
9
- getExpression(_fs: FieldSpace): ExprValue;
9
+ protected computeExpression(_fs: FieldSpace): ExprValue;
10
10
  static fromValue(timeType: TemporalFieldType, expr: ExprValue): ExprTime;
11
11
  }
@@ -19,7 +19,7 @@ class ExprTime extends expression_def_1.ExpressionDef {
19
19
  from: from !== null && from !== void 0 ? from : [],
20
20
  });
21
21
  }
22
- getExpression(_fs) {
22
+ computeExpression(_fs) {
23
23
  return this.translationValue;
24
24
  }
25
25
  static fromValue(timeType, expr) {
@@ -8,5 +8,5 @@ export declare class ExprUngroup extends ExpressionDef {
8
8
  legalChildTypes: import("../../..").TypeDesc[];
9
9
  elementType: string;
10
10
  constructor(control: 'all' | 'exclude', expr: ExpressionDef, fields: FieldName[]);
11
- getExpression(fs: FieldSpace): ExprValue;
11
+ protected computeExpression(fs: FieldSpace): ExprValue;
12
12
  }
@@ -52,7 +52,7 @@ class ExprUngroup extends expression_def_1.ExpressionDef {
52
52
  this.legalChildTypes = TDU.anyAtomicT;
53
53
  this.elementType = 'ungroup';
54
54
  }
55
- getExpression(fs) {
55
+ computeExpression(fs) {
56
56
  var _a;
57
57
  const exprVal = this.expr.getExpression(fs);
58
58
  if (!(0, malloy_types_1.expressionIsAggregate)(exprVal.expressionType)) {
@@ -12,5 +12,5 @@ export declare class ForRange extends ExpressionDef {
12
12
  constructor(from: ExpressionDef, duration: ExpressionDef, timeframe: Timeframe);
13
13
  apply(fs: FieldSpace, op: BinaryMalloyOperator, expr: ExpressionDef): ExprValue;
14
14
  requestExpression(_fs: FieldSpace): undefined;
15
- getExpression(_fs: FieldSpace): ExprValue;
15
+ protected computeExpression(_fs: FieldSpace): ExprValue;
16
16
  }
@@ -110,7 +110,7 @@ class ForRange extends expression_def_1.ExpressionDef {
110
110
  requestExpression(_fs) {
111
111
  return undefined;
112
112
  }
113
- getExpression(_fs) {
113
+ computeExpression(_fs) {
114
114
  return this.loggedErrorExpr('range-as-value', 'A Range is not a value');
115
115
  }
116
116
  }
@@ -10,6 +10,6 @@ export declare class PartialCompare extends ExpressionDef {
10
10
  granular(): boolean;
11
11
  apply(fs: FieldSpace, op: string, expr: ExpressionDef): ExprValue;
12
12
  requestExpression(_fs: FieldSpace): ExprValue | undefined;
13
- getExpression(_fs: FieldSpace): ExprValue;
13
+ protected computeExpression(_fs: FieldSpace): ExprValue;
14
14
  atNodeType(): ATNodeType;
15
15
  }
@@ -22,7 +22,7 @@ class PartialCompare extends expression_def_1.ExpressionDef {
22
22
  requestExpression(_fs) {
23
23
  return undefined;
24
24
  }
25
- getExpression(_fs) {
25
+ computeExpression(_fs) {
26
26
  return this.loggedErrorExpr('partial-as-value', 'Partial comparison does not have a value');
27
27
  }
28
28
  atNodeType() {
@@ -9,7 +9,7 @@ export declare class Pick extends ExpressionDef {
9
9
  constructor(choices: PickWhen[], elsePick?: ExpressionDef | undefined);
10
10
  requestExpression(fs: FieldSpace): ExprValue | undefined;
11
11
  apply(fs: FieldSpace, op: string, expr: ExpressionDef): ExprValue;
12
- getExpression(fs: FieldSpace): ExprValue;
12
+ protected computeExpression(fs: FieldSpace): ExprValue;
13
13
  }
14
14
  export declare class PickWhen extends MalloyElement {
15
15
  readonly pick: ExpressionDef | undefined;
@@ -138,7 +138,7 @@ class Pick extends expression_def_1.ExpressionDef {
138
138
  from: dependents,
139
139
  });
140
140
  }
141
- getExpression(fs) {
141
+ computeExpression(fs) {
142
142
  const pick = {
143
143
  node: 'case',
144
144
  kids: {
@@ -9,5 +9,5 @@ export declare class Range extends ExpressionDef {
9
9
  constructor(first: ExpressionDef, last: ExpressionDef);
10
10
  apply(fs: FieldSpace, op: BinaryMalloyOperator, expr: ExpressionDef): ExprValue;
11
11
  requestExpression(_fs: FieldSpace): undefined;
12
- getExpression(_fs: FieldSpace): ExprValue;
12
+ protected computeExpression(_fs: FieldSpace): ExprValue;
13
13
  }
@@ -56,7 +56,7 @@ class Range extends expression_def_1.ExpressionDef {
56
56
  requestExpression(_fs) {
57
57
  return undefined;
58
58
  }
59
- getExpression(_fs) {
59
+ computeExpression(_fs) {
60
60
  this.logError('range-as-value', 'A Range is not a value');
61
61
  return (0, ast_utils_1.errorFor)('a range is not a value');
62
62
  }
@@ -31,7 +31,7 @@ export declare abstract class TimeLiteral extends ExpressionDef {
31
31
  }) | (import("../../../model").TimestamptzTypeDef & import("../../../model").TypeInfo & import("../types/expr-result").WithValue & {
32
32
  timeframe?: TimestampUnit;
33
33
  });
34
- getExpression(fs: FieldSpace): ExprValue;
34
+ protected computeExpression(fs: FieldSpace): ExprValue;
35
35
  getNext(fs: FieldSpace): ExprValue | undefined;
36
36
  granular(): boolean;
37
37
  }
@@ -62,7 +62,7 @@ export declare class LiteralHour extends GranularLiteral {
62
62
  */
63
63
  declare abstract class DateBasedLiteral extends GranularLiteral {
64
64
  constructor(tm: TimeText, units: TimestampUnit, nextLit: string);
65
- getExpression(fs: FieldSpace): ExprValue;
65
+ protected computeExpression(fs: FieldSpace): ExprValue;
66
66
  getNext(fs: FieldSpace): ExprValue | undefined;
67
67
  }
68
68
  export declare class LiteralDay extends DateBasedLiteral {
@@ -107,7 +107,7 @@ class TimeLiteral extends expression_def_1.ExpressionDef {
107
107
  timeframe: this.units,
108
108
  });
109
109
  }
110
- getExpression(fs) {
110
+ computeExpression(fs) {
111
111
  return this.makeValue(fs, this.literalPart, this.timeType);
112
112
  }
113
113
  getNext(fs) {
@@ -249,7 +249,7 @@ class DateBasedLiteral extends GranularLiteral {
249
249
  constructor(tm, units, nextLit) {
250
250
  super(tm, units, 'date', nextLit);
251
251
  }
252
- getExpression(fs) {
252
+ computeExpression(fs) {
253
253
  const dateValue = this.makeValue(fs, this.literalPart, 'date');
254
254
  const timestamp = this.makeLiteral(fs, `${this.literalPart} 00:00:00`, 'timestamp', this.units);
255
255
  return { ...dateValue, morphic: { timestamp }, evalSpace: 'literal' };
@@ -18,4 +18,5 @@ export declare class ParameterSpace implements FieldSpace {
18
18
  dialectObj(): Dialect | undefined;
19
19
  isQueryFieldSpace(): this is QueryFieldSpace;
20
20
  accessProtectionLevel(): AccessModifierLabel;
21
+ generation(): number;
21
22
  }
@@ -5,6 +5,7 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.ParameterSpace = void 0;
8
+ const field_space_1 = require("../types/field-space");
8
9
  const space_param_1 = require("../types/space-param");
9
10
  class ParameterSpace {
10
11
  constructor(parameters) {
@@ -80,6 +81,11 @@ class ParameterSpace {
80
81
  accessProtectionLevel() {
81
82
  return 'private';
82
83
  }
84
+ // Bindings are fixed by the constructor and never change, so this space
85
+ // contributes no invalidation of its own.
86
+ generation() {
87
+ return (0, field_space_1.currentGeneration)();
88
+ }
83
89
  }
84
90
  exports.ParameterSpace = ParameterSpace;
85
91
  //# sourceMappingURL=parameter-space.js.map
@@ -19,4 +19,5 @@ export declare class PassthroughSpace implements FieldSpace {
19
19
  inputSpace(): import("..").SourceFieldSpace;
20
20
  accessProtectionLevel(): AccessModifierLabel;
21
21
  connectionName(): string;
22
+ generation(): number;
22
23
  }
@@ -52,6 +52,9 @@ class PassthroughSpace {
52
52
  connectionName() {
53
53
  return this.realFS.connectionName();
54
54
  }
55
+ generation() {
56
+ return this.realFS.generation();
57
+ }
55
58
  }
56
59
  exports.PassthroughSpace = PassthroughSpace;
57
60
  //# sourceMappingURL=passthrough-space.js.map
@@ -18,6 +18,14 @@ export declare class StaticSpace implements FieldSpace {
18
18
  defToSpaceField(from: FieldDef): SpaceField;
19
19
  private get map();
20
20
  accessProtectionLevel(): AccessModifierLabel;
21
+ /**
22
+ * StaticSpace itself never rebinds anything after construction, but
23
+ * DynamicSpace extends it and the three mutators below are the whole
24
+ * write surface for both -- `memoMap` is private, and every caller
25
+ * goes through these. That is what makes "every rebinding bumps the
26
+ * generation" checkable rather than a hope.
27
+ */
28
+ generation(): number;
21
29
  protected dropEntries(): void;
22
30
  protected dropEntry(name: string): void;
23
31
  entry(name: string): SpaceEntry | undefined;
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.StaticSourceSpace = exports.StructSpaceField = exports.StaticSpace = void 0;
8
8
  const dialect_map_1 = require("../../../dialect/dialect_map");
9
9
  const malloy_types_1 = require("../../../model/malloy_types");
10
+ const field_space_1 = require("../types/field-space");
10
11
  const space_param_1 = require("../types/space-param");
11
12
  const space_field_1 = require("../types/space-field");
12
13
  const struct_space_field_base_1 = require("./struct-space-field-base");
@@ -64,10 +65,22 @@ class StaticSpace {
64
65
  accessProtectionLevel() {
65
66
  return 'internal';
66
67
  }
68
+ /**
69
+ * StaticSpace itself never rebinds anything after construction, but
70
+ * DynamicSpace extends it and the three mutators below are the whole
71
+ * write surface for both -- `memoMap` is private, and every caller
72
+ * goes through these. That is what makes "every rebinding bumps the
73
+ * generation" checkable rather than a hope.
74
+ */
75
+ generation() {
76
+ return (0, field_space_1.currentGeneration)();
77
+ }
67
78
  dropEntries() {
79
+ (0, field_space_1.noteRebinding)();
68
80
  this.memoMap = new Map();
69
81
  }
70
82
  dropEntry(name) {
83
+ (0, field_space_1.noteRebinding)();
71
84
  this.map.delete(name);
72
85
  }
73
86
  // TODO this was protected
@@ -75,6 +88,7 @@ class StaticSpace {
75
88
  return this.map.get(name);
76
89
  }
77
90
  setEntry(name, value) {
91
+ (0, field_space_1.noteRebinding)();
78
92
  this.map.set(name, value);
79
93
  }
80
94
  entries() {
@@ -94,7 +94,7 @@ class IndexBuilder {
94
94
  path: [],
95
95
  uniqueKeyRequirement: { isCount: true },
96
96
  });
97
- (0, malloy_types_1.setFieldUsage)(indexSegment, fieldUsage);
97
+ indexSegment.refSummary = { ...indexSegment.refSummary, fieldUsage };
98
98
  return indexSegment;
99
99
  }
100
100
  }
@@ -13,7 +13,7 @@ export declare class DrillField extends ExpressionDef {
13
13
  readonly typeDesc: TypeDesc;
14
14
  elementType: string;
15
15
  constructor(expr: Expr, typeDesc: TypeDesc);
16
- getExpression(_fs: FieldSpace): ExprValue;
16
+ protected computeExpression(_fs: FieldSpace): ExprValue;
17
17
  }
18
18
  export declare class Drill extends Filter implements QueryPropertyInterface {
19
19
  elementType: string;
@@ -25,7 +25,7 @@ class DrillField extends expression_def_1.ExpressionDef {
25
25
  this.typeDesc = typeDesc;
26
26
  this.elementType = 'drillField';
27
27
  }
28
- getExpression(_fs) {
28
+ computeExpression(_fs) {
29
29
  return {
30
30
  value: this.expr,
31
31
  ...this.typeDesc,
@@ -13,20 +13,53 @@ export declare enum ATNodeType {
13
13
  }
14
14
  /**
15
15
  * Root node for any element in an expression. These essentially
16
- * create a sub-tree in the larger AST. Expression nodes know
17
- * how to write themselves as SQL (or rather, generate the
18
- * template for SQL required by the query writer)
16
+ * create a sub-tree in the larger AST. An ExpressionDef, when
17
+ * given a FieldSpace, can be evaluated to produce an ExprValue
18
+ * which is the IR for an Expr along with its type and other metadata.
19
19
  */
20
20
  export declare abstract class ExpressionDef extends MalloyElement {
21
21
  abstract elementType: string;
22
22
  granular(): boolean;
23
23
  /**
24
- * Returns the "translation" or template for SQL generation. When asking
24
+ * Returns the "translation" or Expr tree for SQL generation. When asking
25
25
  * for a translation you may pass the types you can accept, allowing
26
26
  * the translation code a chance to convert to match your expectations
27
27
  * @param space Namespace for looking up field references
28
+ *
29
+ * THE RETURNED ExprValue IS SHARED -- TREAT IT AS IMMUTABLE. Asking twice
30
+ * yields the same object, so to derive a value from one, build a new one:
31
+ * `{...operand, type: 'boolean'}` or `computedExprValue({…, from: [operand]})`.
32
+ *
33
+ * DO NOT OVERRIDE THIS. Nodes implement `computeExpression`; an override
34
+ * here bypasses the memo, which for `+`/`-` chains is the difference
35
+ * between linear and exponential compile time.
28
36
  */
29
- abstract getExpression(fs: FieldSpace): ExprValue;
37
+ getExpression(fs: FieldSpace): ExprValue;
38
+ /**
39
+ * The last value this node computed, and what it was computed against.
40
+ * Three states, distinguished by memoGen:
41
+ *
42
+ * memoFs undefined -- nothing computed, or abandoned
43
+ * memoFs set, memoGen undefined -- computing right now, and only that,
44
+ * since abandoning clears memoFs
45
+ * memoFs set, memoGen set -- memoValue is that computation's result
46
+ *
47
+ * Both halves of the stamp are needed: a node can be evaluated under more
48
+ * than one field space -- ConstantExpression evaluates its child against a
49
+ * ConstantFieldSpace whatever it was handed -- and a field space can rebind
50
+ * a name under us.
51
+ *
52
+ * One slot, not a map. A node which alternates between two field spaces
53
+ * simply misses and recomputes, which costs time and never correctness.
54
+ */
55
+ private memoFs?;
56
+ private memoGen?;
57
+ private memoValue?;
58
+ /**
59
+ * Evaluate this node. Implemented by every expression node; called only
60
+ * by `getExpression` above, never directly.
61
+ */
62
+ protected abstract computeExpression(fs: FieldSpace): ExprValue;
30
63
  legalChildTypes: import("../../..").TypeDesc[];
31
64
  /**
32
65
  * Some operators want to give the right hand value a chance to
@@ -45,13 +78,19 @@ export declare abstract class ExpressionDef extends MalloyElement {
45
78
  typeCheck(eNode: ExpressionDef, eVal: ExprValue): boolean;
46
79
  drillExpression(): Malloy.Expression | undefined;
47
80
  /**
48
- * This is the operation which makes partial comparison and value trees work
49
- * The default implementation merely constructs LEFT OP RIGHT, but specialized
50
- * nodes like alternation trees or or partial comparison can control how
51
- * the appplication gets generated
81
+ * This is the operation which makes partial comparison and value trees work.
82
+ * `this` is the RIGHT operand; the left arrives here as an argument. All of
83
+ * the magic of malloy expressions eventually flows through here, where an
84
+ * operator is applied to two values -- depending on the operator and the
85
+ * value types that may transform the values or even the operator.
86
+ *
87
+ * Specialized nodes like alternation trees and partial comparisons override
88
+ * this to control how the application gets generated. They are the reason
89
+ * the right operand is in charge: a partial has no bound left operand, and
90
+ * only learns it here.
52
91
  * @param fs The symbol table
53
92
  * @param op The operator being applied
54
- * @param expr The "other" (besdies 'this') value
93
+ * @param left The "other" (besides 'this') value
55
94
  * @return The translated expression
56
95
  */
57
96
  apply(fs: FieldSpace, op: BinaryMalloyOperator, left: ExpressionDef, _warnOnComplexTree?: boolean): ExprValue;
@@ -69,20 +108,8 @@ export declare class ExprDuration extends ExpressionDef {
69
108
  legalChildTypes: import("../../..").TypeDesc[];
70
109
  constructor(n: ExpressionDef, timeframe: TimestampUnit);
71
110
  apply(fs: FieldSpace, op: BinaryMalloyOperator, left: ExpressionDef): ExprValue;
72
- getExpression(fs: FieldSpace): ExprValue;
111
+ protected computeExpression(fs: FieldSpace): ExprValue;
73
112
  }
74
113
  export type MorphicType = 'date' | 'timestamp';
75
114
  export declare function getMorphicValue(mv: ExprValue, mt: MorphicType): ExprValue | undefined;
76
- /**
77
- * All of the magic of malloy expressions eventually flows to here,
78
- * where an operator is applied to two values. Depending on the
79
- * operator and value types this may involve transformations of
80
- * the values or even the operator.
81
- * @param fs FieldSpace for the symbols
82
- * @param left Left value
83
- * @param op The operator
84
- * @param right Right Value
85
- * @return ExprValue of the expression
86
- */
87
- export declare function applyBinary(fs: FieldSpace, left: ExpressionDef, op: BinaryMalloyOperator, right: ExpressionDef): ExprValue;
88
115
  export declare function checkFilterExpression(logTo: MalloyElement, ft: FilterExprType, fexpr: Expr): void;