@malloydata/malloy 0.0.203-dev241023170054 → 0.0.203-dev241024163815

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.
@@ -7,7 +7,7 @@ export declare abstract class BinaryBoolean<opType extends BinaryMalloyOperator>
7
7
  readonly op: opType;
8
8
  readonly right: ExpressionDef;
9
9
  elementType: string;
10
- legalChildTypes: import("../../../model/malloy_types").TypeDesc[];
10
+ legalChildTypes: import("../../..").TypeDesc[];
11
11
  constructor(left: ExpressionDef, op: opType, right: ExpressionDef);
12
12
  getExpression(fs: FieldSpace): ExprValue;
13
13
  }
@@ -23,10 +23,10 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.BinaryBoolean = void 0;
26
- const malloy_types_1 = require("../../../model/malloy_types");
27
26
  const ast_utils_1 = require("../ast-utils");
28
27
  const fragtype_utils_1 = require("../fragtype-utils");
29
28
  const binary_operators_1 = require("../types/binary_operators");
29
+ const expr_value_1 = require("../types/expr-value");
30
30
  const expression_def_1 = require("../types/expression-def");
31
31
  class BinaryBoolean extends expression_def_1.ExpressionDef {
32
32
  constructor(left, op, right) {
@@ -41,16 +41,14 @@ class BinaryBoolean extends expression_def_1.ExpressionDef {
41
41
  const left = this.left.getExpression(fs);
42
42
  const right = this.right.getExpression(fs);
43
43
  if (this.typeCheck(this.left, left) && this.typeCheck(this.right, right)) {
44
- const evalSpace = (0, malloy_types_1.mergeEvalSpaces)(left.evalSpace, right.evalSpace);
45
- return {
44
+ return (0, expr_value_1.computedExprValue)({
46
45
  dataType: 'boolean',
47
- expressionType: (0, malloy_types_1.maxExpressionType)(left.expressionType, right.expressionType),
48
46
  value: {
49
47
  node: (0, binary_operators_1.getExprNode)(this.op),
50
48
  kids: { left: left.value, right: right.value },
51
49
  },
52
- evalSpace,
53
- };
50
+ from: [left, right],
51
+ });
54
52
  }
55
53
  return (0, ast_utils_1.errorFor)('logial required boolean');
56
54
  }
@@ -7,10 +7,10 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.CaseWhen = exports.Case = void 0;
10
+ const expr_value_1 = require("../types/expr-value");
10
11
  const expression_def_1 = require("../types/expression-def");
11
12
  const malloy_element_1 = require("../types/malloy-element");
12
13
  const fragtype_utils_1 = require("../fragtype-utils");
13
- const model_1 = require("../../../model");
14
14
  function typeCoalesce(ev1, ev2) {
15
15
  return ev1 === undefined ||
16
16
  ev1.dataType === 'null' ||
@@ -36,13 +36,11 @@ class Case extends expression_def_1.ExpressionDef {
36
36
  caseThen: [],
37
37
  },
38
38
  };
39
- let expressionType = 'scalar';
40
- let evalSpace = 'constant';
39
+ const dependents = [];
41
40
  let value = undefined;
42
41
  if (this.value) {
43
42
  value = this.value.getExpression(fs);
44
- expressionType = (0, model_1.maxExpressionType)(expressionType, value.expressionType);
45
- evalSpace = (0, model_1.mergeEvalSpaces)(evalSpace, value.evalSpace);
43
+ dependents.push(value);
46
44
  resultExpr.kids.caseValue = value.value;
47
45
  }
48
46
  const choiceValues = [];
@@ -50,6 +48,7 @@ class Case extends expression_def_1.ExpressionDef {
50
48
  const when = c.when.getExpression(fs);
51
49
  const then = c.then.getExpression(fs);
52
50
  choiceValues.push({ when, then });
51
+ dependents.push(when, then);
53
52
  }
54
53
  let returnType;
55
54
  for (const aChoice of choiceValues) {
@@ -75,8 +74,6 @@ class Case extends expression_def_1.ExpressionDef {
75
74
  });
76
75
  }
77
76
  returnType = typeCoalesce(returnType, aChoice.then);
78
- expressionType = (0, model_1.maxExpressionType)(expressionType, (0, model_1.maxExpressionType)(aChoice.then.expressionType, aChoice.when.expressionType));
79
- evalSpace = (0, model_1.mergeEvalSpaces)(evalSpace, aChoice.then.evalSpace, aChoice.when.evalSpace);
80
77
  resultExpr.kids.caseWhen.push(aChoice.when.value);
81
78
  resultExpr.kids.caseThen.push(aChoice.then.value);
82
79
  }
@@ -89,16 +86,14 @@ class Case extends expression_def_1.ExpressionDef {
89
86
  });
90
87
  }
91
88
  returnType = typeCoalesce(returnType, elseValue);
92
- expressionType = (0, model_1.maxExpressionType)(expressionType, elseValue.expressionType);
93
- evalSpace = (0, model_1.mergeEvalSpaces)(evalSpace, elseValue.evalSpace);
89
+ dependents.push(elseValue);
94
90
  resultExpr.kids.caseElse = elseValue.value;
95
91
  }
96
- return {
92
+ return (0, expr_value_1.computedExprValue)({
97
93
  value: resultExpr,
98
94
  dataType: (_a = returnType === null || returnType === void 0 ? void 0 : returnType.dataType) !== null && _a !== void 0 ? _a : 'null',
99
- expressionType,
100
- evalSpace,
101
- };
95
+ from: dependents,
96
+ });
102
97
  }
103
98
  }
104
99
  exports.Case = Case;
@@ -23,7 +23,7 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprAlternationTree = void 0;
26
- const malloy_types_1 = require("../../../model/malloy_types");
26
+ const expr_value_1 = require("../types/expr-value");
27
27
  const expression_def_1 = require("../types/expression-def");
28
28
  const binary_operators_1 = require("../types/binary_operators");
29
29
  /**
@@ -76,21 +76,15 @@ class ExprAlternationTree extends expression_def_1.ExpressionDef {
76
76
  if (inList.length > 0 && (applyOp === '=' || applyOp === '!=')) {
77
77
  const isIn = expr.getExpression(fs);
78
78
  const values = inList.map(v => v.getExpression(fs));
79
- let { evalSpace, expressionType } = isIn;
80
- for (const value of values) {
81
- evalSpace = (0, malloy_types_1.mergeEvalSpaces)(evalSpace, value.evalSpace);
82
- expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, value.expressionType);
83
- }
84
- return {
79
+ return (0, expr_value_1.computedExprValue)({
85
80
  dataType: 'boolean',
86
- evalSpace,
87
- expressionType,
88
81
  value: {
89
82
  node: 'in',
90
83
  not: applyOp === '!=',
91
84
  kids: { e: isIn.value, oneOf: values.map(v => v.value) },
92
85
  },
93
- };
86
+ from: [isIn, ...values],
87
+ });
94
88
  }
95
89
  if (inList.length === 0 && warnOnComplexTree) {
96
90
  this.logWarning('or-choices-only', `Only | seperated values are legal when used with ${applyOp} operator`);
@@ -98,15 +92,14 @@ class ExprAlternationTree extends expression_def_1.ExpressionDef {
98
92
  }
99
93
  const choice1 = this.left.apply(fs, applyOp, expr);
100
94
  const choice2 = this.right.apply(fs, applyOp, expr);
101
- return {
95
+ return (0, expr_value_1.computedExprValue)({
102
96
  dataType: 'boolean',
103
- expressionType: (0, malloy_types_1.maxExpressionType)(choice1.expressionType, choice2.expressionType),
104
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(choice1.evalSpace, choice2.evalSpace),
105
97
  value: {
106
98
  node: this.op === '&' ? 'and' : 'or',
107
99
  kids: { left: choice1.value, right: choice2.value },
108
100
  },
109
- };
101
+ from: [choice1, choice2],
102
+ });
110
103
  }
111
104
  requestExpression(_fs) {
112
105
  return undefined;
@@ -24,6 +24,7 @@
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprCast = void 0;
26
26
  const time_utils_1 = require("../time-utils");
27
+ const expr_value_1 = require("../types/expr-value");
27
28
  const expression_def_1 = require("../types/expression-def");
28
29
  class ExprCast extends expression_def_1.ExpressionDef {
29
30
  constructor(expr, castType, safe = false) {
@@ -55,12 +56,11 @@ class ExprCast extends expression_def_1.ExpressionDef {
55
56
  }
56
57
  }
57
58
  }
58
- return {
59
+ return (0, expr_value_1.computedExprValue)({
59
60
  dataType,
60
- expressionType: expr.expressionType,
61
61
  value: (0, time_utils_1.castTo)(this.castType, expr.value, expr.dataType, this.safe),
62
- evalSpace: expr.evalSpace,
63
- };
62
+ from: [expr],
63
+ });
64
64
  }
65
65
  }
66
66
  exports.ExprCast = ExprCast;
@@ -26,6 +26,7 @@ exports.ExprFunc = void 0;
26
26
  const malloy_types_1 = require("../../../model/malloy_types");
27
27
  const ast_utils_1 = require("../ast-utils");
28
28
  const struct_space_field_base_1 = require("../field-space/struct-space-field-base");
29
+ const expr_value_1 = require("../types/expr-value");
29
30
  const expression_def_1 = require("../types/expression-def");
30
31
  const field_space_1 = require("../types/field-space");
31
32
  const utils_1 = require("../../../model/utils");
@@ -78,11 +79,9 @@ class ExprFunc extends expression_def_1.ExpressionDef {
78
79
  var _a, _b, _c, _d;
79
80
  const argExprsWithoutImplicit = this.args.map(arg => arg.getExpression(fs));
80
81
  if (this.isRaw) {
81
- let expressionType = 'scalar';
82
82
  let collectType;
83
83
  const funcCall = [`${this.name}(`];
84
84
  for (const expr of argExprsWithoutImplicit) {
85
- expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, expr.expressionType);
86
85
  if (collectType) {
87
86
  funcCall.push(',');
88
87
  }
@@ -93,12 +92,11 @@ class ExprFunc extends expression_def_1.ExpressionDef {
93
92
  }
94
93
  funcCall.push(')');
95
94
  const dataType = (_b = (_a = this.rawType) !== null && _a !== void 0 ? _a : collectType) !== null && _b !== void 0 ? _b : 'number';
96
- return {
95
+ return (0, expr_value_1.computedExprValue)({
97
96
  dataType,
98
- expressionType,
99
97
  value: (0, utils_1.composeSQLExpr)(funcCall),
100
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(...argExprsWithoutImplicit.map(e => e.evalSpace)),
101
- };
98
+ from: argExprsWithoutImplicit,
99
+ });
102
100
  }
103
101
  const dialect = (_c = fs.dialectObj()) === null || _c === void 0 ? void 0 : _c.name;
104
102
  const { found: func, error } = this.findFunctionDef(dialect);
@@ -110,7 +108,8 @@ class ExprFunc extends expression_def_1.ExpressionDef {
110
108
  let implicitExpr = undefined;
111
109
  let structPath = (_d = this.source) === null || _d === void 0 ? void 0 : _d.path;
112
110
  if (this.source) {
113
- const sourceFoot = this.source.getField(fs).found;
111
+ const lookup = this.source.getField(fs);
112
+ const sourceFoot = lookup.found;
114
113
  if (sourceFoot) {
115
114
  const footType = sourceFoot.typeDesc();
116
115
  if ((0, malloy_types_1.isAtomicFieldType)(footType.dataType)) {
@@ -306,6 +305,8 @@ class ExprFunc extends expression_def_1.ExpressionDef {
306
305
  : (0, malloy_types_1.expressionIsScalar)(expressionType)
307
306
  ? maxEvalSpace
308
307
  : 'output';
308
+ // TODO consider if I can use `computedExprValue` here...
309
+ // seems like the rules for the evalSpace is a bit different from normal though
309
310
  return {
310
311
  dataType: type.dataType,
311
312
  expressionType,
@@ -102,12 +102,12 @@ class ExprGranularTime extends expression_def_1.ExpressionDef {
102
102
  const one = { node: 'numberLiteral', literal: '1' };
103
103
  if (begin.dataType === 'timestamp') {
104
104
  const beginTS = expr_time_1.ExprTime.fromValue('timestamp', begin);
105
- const endTS = new expr_time_1.ExprTime('timestamp', (0, time_utils_1.timeOffset)('timestamp', begin.value, '+', one, this.units), begin.expressionType);
105
+ const endTS = new expr_time_1.ExprTime('timestamp', (0, time_utils_1.timeOffset)('timestamp', begin.value, '+', one, this.units), [begin]);
106
106
  return new range_1.Range(beginTS, endTS);
107
107
  }
108
- const beginDate = new expr_time_1.ExprTime('date', begin.value, begin.expressionType);
108
+ const beginDate = new expr_time_1.ExprTime('date', begin.value, [begin]);
109
109
  const endAt = (0, time_utils_1.timeOffset)('date', begin.value, '+', one, this.units);
110
- const endDate = new expr_time_1.ExprTime('date', endAt, begin.expressionType);
110
+ const endDate = new expr_time_1.ExprTime('date', endAt, [begin]);
111
111
  return new range_1.Range(beginDate, endDate);
112
112
  }
113
113
  }
@@ -42,6 +42,7 @@ class ExprIdReference extends expression_def_1.ExpressionDef {
42
42
  if (def.isOutputField) {
43
43
  return {
44
44
  ...td,
45
+ // TODO what about literal??
45
46
  evalSpace: td.evalSpace === 'constant' ? 'constant' : 'output',
46
47
  value: { node: 'outputField', name: this.refString },
47
48
  };
@@ -23,6 +23,7 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprNULL = void 0;
26
+ const expr_value_1 = require("../types/expr-value");
26
27
  const expression_def_1 = require("../types/expression-def");
27
28
  class ExprNULL extends expression_def_1.ExpressionDef {
28
29
  constructor() {
@@ -30,12 +31,10 @@ class ExprNULL extends expression_def_1.ExpressionDef {
30
31
  this.elementType = 'NULL';
31
32
  }
32
33
  getExpression() {
33
- return {
34
+ return (0, expr_value_1.literalExprValue)({
34
35
  dataType: 'null',
35
36
  value: { node: 'null' },
36
- expressionType: 'scalar',
37
- evalSpace: 'literal',
38
- };
37
+ });
39
38
  }
40
39
  }
41
40
  exports.ExprNULL = ExprNULL;
@@ -23,7 +23,7 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprNumber = void 0;
26
- const fragtype_utils_1 = require("../fragtype-utils");
26
+ const expr_value_1 = require("../types/expr-value");
27
27
  const expression_def_1 = require("../types/expression-def");
28
28
  class ExprNumber extends expression_def_1.ExpressionDef {
29
29
  constructor(n) {
@@ -35,11 +35,10 @@ class ExprNumber extends expression_def_1.ExpressionDef {
35
35
  return this.constantExpression();
36
36
  }
37
37
  constantExpression() {
38
- return {
39
- ...fragtype_utils_1.FT.numberT,
40
- evalSpace: 'literal',
38
+ return (0, expr_value_1.literalExprValue)({
39
+ dataType: 'number',
41
40
  value: { node: 'numberLiteral', literal: this.n },
42
- };
41
+ });
43
42
  }
44
43
  }
45
44
  exports.ExprNumber = ExprNumber;
@@ -32,10 +32,10 @@ class RecordLiteral extends expression_def_1.ExpressionDef {
32
32
  // node: 'recordLiteral',
33
33
  // kids: {},
34
34
  // };
35
- // let resultExprType: ExpressionType = 'scalar';
35
+ // const dependents: ExprValue[] = [];
36
36
  // for (const el of this.pairs) {
37
37
  // const xVal = el.value.getExpression(fs);
38
- // const expr: TypedExpr = {typeDef: 'error', ...xVal.value};
38
+ // const expr: TypedExpr = {typeDef: {type: 'error'}, ...xVal.value};
39
39
  // if (TD.isError(expr.typeDef) && isAtomicFieldType(xVal.dataType)) {
40
40
  // expr.typeDef = xVal.dataType;
41
41
  // }
@@ -46,14 +46,13 @@ class RecordLiteral extends expression_def_1.ExpressionDef {
46
46
  // );
47
47
  // }
48
48
  // recLit.kids[el.key] = expr;
49
- // resultExprType = maxExpressionType(xVal.expressionType, resultExprType);
49
+ // dependents.push(xVal);
50
50
  // }
51
- // return {
51
+ // return computedExprValue({
52
52
  // dataType: 'record',
53
53
  // value: recLit,
54
- // expressionType: resultExprType,
55
- // evalSpace: 'literal',
56
- // };
54
+ // from: dependents,
55
+ // });
57
56
  }
58
57
  }
59
58
  exports.RecordLiteral = RecordLiteral;
@@ -23,6 +23,7 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprRegEx = void 0;
26
+ const expr_value_1 = require("../types/expr-value");
26
27
  const expression_def_1 = require("../types/expression-def");
27
28
  class ExprRegEx extends expression_def_1.ExpressionDef {
28
29
  constructor(regex) {
@@ -31,12 +32,10 @@ class ExprRegEx extends expression_def_1.ExpressionDef {
31
32
  this.elementType = 'regular expression literal';
32
33
  }
33
34
  getExpression() {
34
- return {
35
+ return (0, expr_value_1.literalExprValue)({
35
36
  dataType: 'regular expression',
36
- expressionType: 'scalar',
37
37
  value: { node: 'regexpLiteral', literal: this.regex },
38
- evalSpace: 'literal',
39
- };
38
+ });
40
39
  }
41
40
  }
42
41
  exports.ExprRegEx = ExprRegEx;
@@ -24,7 +24,7 @@
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprString = void 0;
26
26
  const expression_def_1 = require("../types/expression-def");
27
- const fragtype_utils_1 = require("../fragtype-utils");
27
+ const expr_value_1 = require("../types/expr-value");
28
28
  class ExprString extends expression_def_1.ExpressionDef {
29
29
  constructor(src) {
30
30
  super();
@@ -32,11 +32,10 @@ class ExprString extends expression_def_1.ExpressionDef {
32
32
  this.value = src;
33
33
  }
34
34
  getExpression(_fs) {
35
- return {
36
- ...fragtype_utils_1.FT.stringT,
35
+ return (0, expr_value_1.literalExprValue)({
36
+ dataType: 'string',
37
37
  value: { node: 'stringLiteral', literal: this.value },
38
- evalSpace: 'literal',
39
- };
38
+ });
40
39
  }
41
40
  }
42
41
  exports.ExprString = ExprString;
@@ -24,7 +24,7 @@
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprTimeExtract = void 0;
26
26
  const malloy_types_1 = require("../../../model/malloy_types");
27
- const ast_utils_1 = require("../ast-utils");
27
+ const expr_value_1 = require("../types/expr-value");
28
28
  const expression_def_1 = require("../types/expression-def");
29
29
  const range_1 = require("./range");
30
30
  class ExprTimeExtract extends expression_def_1.ExpressionDef {
@@ -53,15 +53,12 @@ class ExprTimeExtract extends expression_def_1.ExpressionDef {
53
53
  if (from instanceof range_1.Range) {
54
54
  let first = from.first.getExpression(fs);
55
55
  let last = from.last.getExpression(fs);
56
- const expressionType = (0, malloy_types_1.maxExpressionType)(first.expressionType, last.expressionType);
57
- const evalSpace = (0, malloy_types_1.mergeEvalSpaces)(first.evalSpace, last.evalSpace);
58
56
  if (first.dataType === 'error' || last.dataType === 'error') {
59
- return {
57
+ return (0, expr_value_1.computedErrorExprValue)({
60
58
  dataType: 'number',
61
- expressionType,
62
- evalSpace,
63
- value: (0, ast_utils_1.errorFor)('extract from error').value,
64
- };
59
+ error: 'extract from error',
60
+ from: [first, last],
61
+ });
65
62
  }
66
63
  if (!(0, malloy_types_1.isTemporalField)(first.dataType)) {
67
64
  return from.first.loggedErrorExpr('invalid-type-for-time-extraction', `Can't extract ${extractTo} from '${first.dataType}'`);
@@ -97,10 +94,8 @@ class ExprTimeExtract extends expression_def_1.ExpressionDef {
97
94
  if (!(0, malloy_types_1.isTimestampUnit)(extractTo)) {
98
95
  return this.loggedErrorExpr('invalid-time-extraction-unit', `Cannot extract ${extractTo} from a range`);
99
96
  }
100
- return {
97
+ return (0, expr_value_1.computedExprValue)({
101
98
  dataType: 'number',
102
- expressionType,
103
- evalSpace,
104
99
  value: {
105
100
  node: 'timeDiff',
106
101
  units: extractTo,
@@ -109,32 +104,30 @@ class ExprTimeExtract extends expression_def_1.ExpressionDef {
109
104
  right: (0, malloy_types_1.mkTemporal)(last.value, valueType),
110
105
  },
111
106
  },
112
- };
107
+ from: [first, last],
108
+ });
113
109
  }
114
110
  else {
115
111
  const argV = from.getExpression(fs);
116
112
  if ((0, malloy_types_1.isTemporalField)(argV.dataType)) {
117
- return {
113
+ return (0, expr_value_1.computedExprValue)({
118
114
  dataType: 'number',
119
- expressionType: argV.expressionType,
120
- evalSpace: argV.evalSpace,
121
115
  value: {
122
116
  node: 'extract',
123
117
  e: (0, malloy_types_1.mkTemporal)(argV.value, argV.dataType),
124
118
  units: extractTo,
125
119
  },
126
- };
120
+ from: [argV],
121
+ });
127
122
  }
128
123
  if (argV.dataType !== 'error') {
129
124
  this.logError('unsupported-type-for-time-extraction', `${this.extractText}() requires time type, not '${argV.dataType}'`);
130
125
  }
131
- return {
126
+ return (0, expr_value_1.computedErrorExprValue)({
132
127
  dataType: 'number',
133
- expressionType: argV.expressionType,
134
- evalSpace: argV.evalSpace,
135
- value: (0, ast_utils_1.errorFor)(`${this.extractText} bad type ${argV.dataType}`)
136
- .value,
137
- };
128
+ error: `${this.extractText} bad type ${argV.dataType}`,
129
+ from: [argV],
130
+ });
138
131
  }
139
132
  }
140
133
  throw this.internalError(`Illegal extraction unit '${this.extractText}'`);
@@ -1,11 +1,11 @@
1
- import { Expr, ExpressionType, TemporalFieldType } from '../../../model/malloy_types';
1
+ import { Expr, TemporalFieldType } from '../../../model/malloy_types';
2
2
  import { FieldSpace } from '../types/field-space';
3
3
  import { ExprValue } from '../types/expr-value';
4
4
  import { ExpressionDef } from '../types/expression-def';
5
5
  export declare class ExprTime extends ExpressionDef {
6
6
  elementType: string;
7
7
  readonly translationValue: ExprValue;
8
- constructor(timeType: TemporalFieldType, value: Expr, expressionType?: ExpressionType);
8
+ constructor(timeType: TemporalFieldType, value: Expr, from?: ExprValue[]);
9
9
  getExpression(_fs: FieldSpace): ExprValue;
10
10
  static fromValue(timeType: TemporalFieldType, expr: ExprValue): ExprTime;
11
11
  }
@@ -24,18 +24,18 @@
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprTime = void 0;
26
26
  const malloy_types_1 = require("../../../model/malloy_types");
27
+ const expr_value_1 = require("../types/expr-value");
27
28
  const expression_def_1 = require("../types/expression-def");
28
29
  class ExprTime extends expression_def_1.ExpressionDef {
29
- constructor(timeType, value, expressionType = 'scalar') {
30
+ constructor(timeType, value, from) {
30
31
  super();
31
32
  this.elementType = 'timestampOrDate';
32
33
  this.elementType = timeType;
33
- this.translationValue = {
34
+ this.translationValue = (0, expr_value_1.computedExprValue)({
34
35
  dataType: timeType,
35
- expressionType,
36
36
  value,
37
- evalSpace: 'constant',
38
- };
37
+ from: from !== null && from !== void 0 ? from : [],
38
+ });
39
39
  }
40
40
  getExpression(_fs) {
41
41
  return this.translationValue;
@@ -54,7 +54,7 @@ class ExprTime extends expression_def_1.ExpressionDef {
54
54
  }
55
55
  value = toTs;
56
56
  }
57
- return new ExprTime(timeType, value, expr.expressionType);
57
+ return new ExprTime(timeType, value, [expr]);
58
58
  }
59
59
  }
60
60
  exports.ExprTime = ExprTime;
@@ -8,7 +8,7 @@ export declare class ForRange extends ExpressionDef {
8
8
  readonly duration: ExpressionDef;
9
9
  readonly timeframe: Timeframe;
10
10
  elementType: string;
11
- legalChildTypes: import("../../../model").TypeDesc[];
11
+ legalChildTypes: import("../../..").TypeDesc[];
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;
@@ -23,10 +23,10 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ForRange = void 0;
26
- const model_1 = require("../../../model");
27
26
  const ast_utils_1 = require("../ast-utils");
28
27
  const fragtype_utils_1 = require("../fragtype-utils");
29
28
  const time_utils_1 = require("../time-utils");
29
+ const expr_value_1 = require("../types/expr-value");
30
30
  const expression_def_1 = require("../types/expression-def");
31
31
  const expr_time_1 = require("./expr-time");
32
32
  const range_1 = require("./range");
@@ -50,12 +50,11 @@ class ForRange extends expression_def_1.ExpressionDef {
50
50
  if (nV.dataType !== 'error') {
51
51
  this.logError('invalid-duration-quantity', `FOR duration count must be a number, not '${nV.dataType}'`);
52
52
  }
53
- return {
53
+ return (0, expr_value_1.computedErrorExprValue)({
54
54
  dataType: 'boolean',
55
- evalSpace: (0, model_1.mergeEvalSpaces)(startV.evalSpace, checkV.evalSpace),
56
- expressionType: (0, model_1.maxExpressionType)(startV.expressionType, checkV.expressionType),
57
- value: (0, ast_utils_1.errorFor)('for not number').value,
58
- };
55
+ error: 'for not number',
56
+ from: [startV, checkV],
57
+ });
59
58
  }
60
59
  const units = this.timeframe.text;
61
60
  // If the duration resolution is smaller than date, we have
@@ -86,10 +85,10 @@ class ForRange extends expression_def_1.ExpressionDef {
86
85
  else {
87
86
  from = (0, time_utils_1.castTo)('timestamp', from, 'date');
88
87
  }
89
- rangeStart = new expr_time_1.ExprTime('timestamp', from, startV.expressionType);
88
+ rangeStart = new expr_time_1.ExprTime('timestamp', from, [startV]);
90
89
  }
91
90
  const to = (0, time_utils_1.timeOffset)('timestamp', from, '+', nV.value, units);
92
- const rangeEnd = new expr_time_1.ExprTime('timestamp', to, startV.expressionType);
91
+ const rangeEnd = new expr_time_1.ExprTime('timestamp', to, [startV, nV]);
93
92
  return new range_1.Range(rangeStart, rangeEnd).apply(fs, op, applyTo);
94
93
  }
95
94
  requestExpression(_fs) {
@@ -23,8 +23,8 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.PickWhen = exports.Pick = void 0;
26
- const malloy_types_1 = require("../../../model/malloy_types");
27
26
  const fragtype_utils_1 = require("../fragtype-utils");
27
+ const expr_value_1 = require("../types/expr-value");
28
28
  const expression_def_1 = require("../types/expression-def");
29
29
  const malloy_element_1 = require("../types/malloy-element");
30
30
  function typeCoalesce(ev1, ev2) {
@@ -61,6 +61,7 @@ class Pick extends expression_def_1.ExpressionDef {
61
61
  return this.getExpression(fs);
62
62
  }
63
63
  apply(fs, op, expr) {
64
+ var _a;
64
65
  const caseValue = {
65
66
  node: 'case',
66
67
  kids: {
@@ -69,15 +70,13 @@ class Pick extends expression_def_1.ExpressionDef {
69
70
  },
70
71
  };
71
72
  let returnType;
72
- let anyExpressionType = 'scalar';
73
- let anyEvalSpace = 'constant';
73
+ const dependents = [];
74
74
  for (const choice of this.choices) {
75
75
  const whenExpr = choice.when.apply(fs, '=', expr);
76
76
  const thenExpr = choice.pick
77
77
  ? choice.pick.getExpression(fs)
78
78
  : expr.getExpression(fs);
79
- anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(whenExpr.expressionType, thenExpr.expressionType));
80
- anyEvalSpace = (0, malloy_types_1.mergeEvalSpaces)(anyEvalSpace, whenExpr.evalSpace, thenExpr.evalSpace);
79
+ dependents.push(whenExpr, thenExpr);
81
80
  if (returnType && !fragtype_utils_1.FT.typeEq(returnType, thenExpr, true)) {
82
81
  return this.loggedErrorExpr('pick-type-does-not-match', {
83
82
  pickType: thenExpr.dataType,
@@ -88,30 +87,33 @@ class Pick extends expression_def_1.ExpressionDef {
88
87
  caseValue.kids.caseWhen.push(whenExpr.value);
89
88
  caseValue.kids.caseThen.push(thenExpr.value);
90
89
  }
91
- const elsePart = this.elsePick || expr;
92
- const elseVal = elsePart.getExpression(fs);
93
- returnType = typeCoalesce(returnType, elseVal);
94
- if (!fragtype_utils_1.FT.typeEq(returnType, elseVal, true)) {
90
+ const elseVal = (_a = this.elsePick) === null || _a === void 0 ? void 0 : _a.getExpression(fs);
91
+ const exprVal = expr.getExpression(fs);
92
+ dependents.push(exprVal);
93
+ if (elseVal)
94
+ dependents.push(elseVal);
95
+ const defaultVal = elseVal !== null && elseVal !== void 0 ? elseVal : exprVal;
96
+ returnType = typeCoalesce(returnType, defaultVal);
97
+ if (!fragtype_utils_1.FT.typeEq(returnType, defaultVal, true)) {
95
98
  if (this.elsePick) {
96
99
  return this.loggedErrorExpr('pick-else-type-does-not-match', {
97
- elseType: elseVal.dataType,
100
+ elseType: defaultVal.dataType,
98
101
  returnType: returnType.dataType,
99
102
  });
100
103
  }
101
104
  else {
102
105
  return this.loggedErrorExpr('pick-default-type-does-not-match', {
103
- defaultType: elseVal.dataType,
106
+ defaultType: defaultVal.dataType,
104
107
  returnType: returnType.dataType,
105
108
  });
106
109
  }
107
110
  }
108
- caseValue.kids.caseElse = elseVal.value;
109
- return {
111
+ caseValue.kids.caseElse = defaultVal.value;
112
+ return (0, expr_value_1.computedExprValue)({
110
113
  dataType: returnType.dataType,
111
- expressionType: (0, malloy_types_1.maxExpressionType)(anyExpressionType, elseVal.expressionType),
112
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(anyEvalSpace, elseVal.evalSpace),
113
114
  value: caseValue,
114
- };
115
+ from: dependents,
116
+ });
115
117
  }
116
118
  getExpression(fs) {
117
119
  const pick = {
@@ -125,6 +127,7 @@ class Pick extends expression_def_1.ExpressionDef {
125
127
  return this.loggedErrorExpr('pick-missing-else', "pick incomplete, missing 'else'");
126
128
  }
127
129
  const choiceValues = [];
130
+ const dependents = [];
128
131
  for (const c of this.choices) {
129
132
  if (c.pick === undefined) {
130
133
  return this.loggedErrorExpr('pick-missing-value', 'pick with no value can only be used with apply');
@@ -133,14 +136,12 @@ class Pick extends expression_def_1.ExpressionDef {
133
136
  if (caseWhen === undefined) {
134
137
  this.loggedErrorExpr('pick-illegal-partial', 'pick with partial when can only be used with apply');
135
138
  }
136
- choiceValues.push({
137
- pick: c.pick.getExpression(fs),
138
- when: c.when.getExpression(fs),
139
- });
139
+ const pick = c.pick.getExpression(fs);
140
+ const when = c.when.getExpression(fs);
141
+ choiceValues.push({ pick, when });
142
+ dependents.push(pick, when);
140
143
  }
141
144
  let returnType;
142
- let anyExpressionType = 'scalar';
143
- let anyEvalSpace = 'constant';
144
145
  for (const aChoice of choiceValues) {
145
146
  if (!fragtype_utils_1.FT.typeEq(aChoice.when, fragtype_utils_1.FT.boolT)) {
146
147
  return this.loggedErrorExpr('pick-when-must-be-boolean', {
@@ -154,14 +155,11 @@ class Pick extends expression_def_1.ExpressionDef {
154
155
  });
155
156
  }
156
157
  returnType = typeCoalesce(returnType, aChoice.pick);
157
- anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(aChoice.pick.expressionType, aChoice.when.expressionType));
158
- anyEvalSpace = (0, malloy_types_1.mergeEvalSpaces)(anyEvalSpace, aChoice.pick.evalSpace, aChoice.when.evalSpace);
159
158
  pick.kids.caseWhen.push(aChoice.when.value);
160
159
  pick.kids.caseThen.push(aChoice.pick.value);
161
160
  }
162
161
  const defVal = this.elsePick.getExpression(fs);
163
- anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, defVal.expressionType);
164
- anyEvalSpace = (0, malloy_types_1.mergeEvalSpaces)(anyEvalSpace, defVal.evalSpace);
162
+ dependents.push(defVal);
165
163
  returnType = typeCoalesce(returnType, defVal);
166
164
  if (!fragtype_utils_1.FT.typeEq(returnType, defVal, true)) {
167
165
  return this.elsePick.loggedErrorExpr('pick-else-type-does-not-match', {
@@ -170,12 +168,11 @@ class Pick extends expression_def_1.ExpressionDef {
170
168
  });
171
169
  }
172
170
  pick.kids.caseElse = defVal.value;
173
- return {
171
+ return (0, expr_value_1.computedExprValue)({
174
172
  dataType: returnType.dataType,
175
- expressionType: anyExpressionType,
176
173
  value: pick,
177
- evalSpace: anyEvalSpace,
178
- };
174
+ from: dependents,
175
+ });
179
176
  }
180
177
  }
181
178
  exports.Pick = Pick;
@@ -23,8 +23,8 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.Range = void 0;
26
- const malloy_types_1 = require("../../../model/malloy_types");
27
26
  const ast_utils_1 = require("../ast-utils");
27
+ const expr_value_1 = require("../types/expr-value");
28
28
  const expression_def_1 = require("../types/expression-def");
29
29
  class Range extends expression_def_1.ExpressionDef {
30
30
  constructor(first, last) {
@@ -42,15 +42,14 @@ class Range extends expression_def_1.ExpressionDef {
42
42
  const op3 = op === '=' ? '<' : '>=';
43
43
  const fromValue = this.first.apply(fs, op1, expr);
44
44
  const toValue = this.last.apply(fs, op3, expr);
45
- return {
45
+ return (0, expr_value_1.computedExprValue)({
46
46
  dataType: 'boolean',
47
- expressionType: (0, malloy_types_1.maxExpressionType)(fromValue.expressionType, toValue.expressionType),
48
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(fromValue.evalSpace, toValue.evalSpace),
49
47
  value: {
50
48
  node: op2,
51
49
  kids: { left: fromValue.value, right: toValue.value },
52
50
  },
53
- };
51
+ from: [fromValue, toValue],
52
+ });
54
53
  }
55
54
  /**
56
55
  * This is a little surprising, but is actually how you comapre a
@@ -25,6 +25,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.LiteralYear = exports.LiteralQuarter = exports.LiteralMonth = exports.LiteralWeek = exports.LiteralDay = exports.LiteralHour = exports.LiteralTimestamp = exports.TimeFormatError = void 0;
26
26
  const luxon_1 = require("luxon");
27
27
  const malloy_types_1 = require("../../../model/malloy_types");
28
+ const expr_value_1 = require("../types/expr-value");
28
29
  const range_1 = require("./range");
29
30
  const expr_time_1 = require("./expr-time");
30
31
  const expression_def_1 = require("../types/expression-def");
@@ -80,19 +81,8 @@ class TimeLiteral extends expression_def_1.ExpressionDef {
80
81
  return timeFrag;
81
82
  }
82
83
  makeValue(val, dataType) {
83
- const timeFrag = this.makeLiteral(val, dataType);
84
- const expressionType = 'scalar';
85
- const value = timeFrag;
86
- if (this.units) {
87
- return {
88
- dataType,
89
- expressionType,
90
- value,
91
- timeframe: this.units,
92
- evalSpace: 'literal',
93
- };
94
- }
95
- return { dataType, expressionType, value, evalSpace: 'literal' };
84
+ const value = this.makeLiteral(val, dataType);
85
+ return (0, expr_value_1.literalTimeResult)({ value, dataType, timeframe: this.units });
96
86
  }
97
87
  getExpression(_fs) {
98
88
  return this.makeValue(this.literalPart, this.timeType);
@@ -1,3 +1,54 @@
1
+ import { Expr, FieldValueType, TemporalFieldType, TimestampUnit } from '../../../model';
1
2
  import { ExprResult } from './expr-result';
2
3
  import { TimeResult } from './time-result';
3
4
  export type ExprValue = ExprResult | TimeResult;
5
+ export declare function computedExprValue({ value, dataType, rawType, from, }: {
6
+ value: Expr;
7
+ dataType: FieldValueType;
8
+ rawType?: string;
9
+ from: ExprValue[];
10
+ }): ExprValue;
11
+ export declare function computedTimeResult({ value, dataType, rawType, from, timeframe, }: {
12
+ value: Expr;
13
+ rawType?: string;
14
+ dataType: TemporalFieldType;
15
+ timeframe?: TimestampUnit;
16
+ from: ExprValue[];
17
+ }): {
18
+ timeframe: TimestampUnit | undefined;
19
+ value: Expr;
20
+ morphic?: {
21
+ [x: string]: Expr;
22
+ } | undefined;
23
+ dataType: FieldValueType;
24
+ expressionType: import("../../../model").ExpressionType;
25
+ rawType?: string | undefined;
26
+ evalSpace: import("../../../model").EvalSpace;
27
+ } | {
28
+ timeframe: TimestampUnit | undefined;
29
+ dataType: TemporalFieldType;
30
+ value: Expr;
31
+ morphic?: {
32
+ [x: string]: Expr;
33
+ } | undefined;
34
+ expressionType: import("../../../model").ExpressionType;
35
+ rawType?: string | undefined;
36
+ evalSpace: import("../../../model").EvalSpace;
37
+ };
38
+ export declare function computedErrorExprValue({ dataType, rawType, from, error, }: {
39
+ error: string;
40
+ rawType?: string;
41
+ dataType?: FieldValueType;
42
+ from: ExprValue[];
43
+ }): ExprValue;
44
+ export declare function literalExprValue(options: {
45
+ value: Expr;
46
+ rawType?: string;
47
+ dataType: FieldValueType;
48
+ }): ExprValue;
49
+ export declare function literalTimeResult({ value, dataType, rawType, timeframe, }: {
50
+ value: Expr;
51
+ rawType?: string;
52
+ dataType: TemporalFieldType;
53
+ timeframe?: TimestampUnit;
54
+ }): TimeResult;
@@ -22,4 +22,42 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.literalTimeResult = exports.literalExprValue = exports.computedErrorExprValue = exports.computedTimeResult = exports.computedExprValue = void 0;
26
+ const model_1 = require("../../../model");
27
+ function computedExprValue({ value, dataType, rawType, from, }) {
28
+ return {
29
+ value,
30
+ dataType,
31
+ rawType,
32
+ expressionType: (0, model_1.maxOfExpressionTypes)(from.map(e => e.expressionType)),
33
+ evalSpace: (0, model_1.mergeEvalSpaces)(...from.map(e => e.evalSpace)),
34
+ };
35
+ }
36
+ exports.computedExprValue = computedExprValue;
37
+ function computedTimeResult({ value, dataType, rawType, from, timeframe, }) {
38
+ return { ...computedExprValue({ value, dataType, rawType, from }), timeframe };
39
+ }
40
+ exports.computedTimeResult = computedTimeResult;
41
+ function computedErrorExprValue({ dataType, rawType, from, error, }) {
42
+ return computedExprValue({
43
+ dataType: dataType || 'error',
44
+ rawType,
45
+ value: { node: 'error', message: error },
46
+ from,
47
+ });
48
+ }
49
+ exports.computedErrorExprValue = computedErrorExprValue;
50
+ function literalExprValue(options) {
51
+ // Makes literal, output, scalar because from is empty
52
+ return computedExprValue({ ...options, from: [] });
53
+ }
54
+ exports.literalExprValue = literalExprValue;
55
+ function literalTimeResult({ value, dataType, rawType, timeframe, }) {
56
+ return {
57
+ ...computedExprValue({ value, dataType, rawType, from: [] }),
58
+ dataType,
59
+ timeframe,
60
+ };
61
+ }
62
+ exports.literalTimeResult = literalTimeResult;
25
63
  //# sourceMappingURL=expr-value.js.map
@@ -67,7 +67,7 @@ export declare class ExprDuration extends ExpressionDef {
67
67
  legalChildTypes: import("../../../model/malloy_types").TypeDesc[];
68
68
  constructor(n: ExpressionDef, timeframe: TimestampUnit);
69
69
  apply(fs: FieldSpace, op: BinaryMalloyOperator, left: ExpressionDef): ExprValue;
70
- getExpression(_fs: FieldSpace): ExprValue;
70
+ getExpression(fs: FieldSpace): ExprValue;
71
71
  }
72
72
  export declare function getMorphicValue(mv: ExprValue, mt: FieldValueType): ExprValue | undefined;
73
73
  /**
@@ -26,6 +26,7 @@ exports.applyBinary = exports.getMorphicValue = exports.ExprDuration = exports.E
26
26
  const malloy_types_1 = require("../../../model/malloy_types");
27
27
  const ast_utils_1 = require("../ast-utils");
28
28
  const fragtype_utils_1 = require("../fragtype-utils");
29
+ const expr_value_1 = require("./expr-value");
29
30
  const time_utils_1 = require("../time-utils");
30
31
  const granular_result_1 = require("./granular-result");
31
32
  const malloy_element_1 = require("./malloy-element");
@@ -143,36 +144,25 @@ class ExprDuration extends ExpressionDef {
143
144
  if ((0, granular_result_1.isGranularResult)(lhs) && lhs.timeframe === this.timeframe) {
144
145
  resultGranularity = lhs.timeframe;
145
146
  }
146
- if (lhs.dataType === 'timestamp') {
147
- const result = (0, time_utils_1.timeOffset)('timestamp', lhs.value, op, num.value, this.timeframe);
148
- return (0, time_utils_1.mkTimeResult)({
149
- dataType: 'timestamp',
150
- expressionType: (0, malloy_types_1.maxExpressionType)(lhs.expressionType, num.expressionType),
151
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(lhs.evalSpace, num.evalSpace),
152
- value: result,
153
- }, resultGranularity);
154
- }
155
- if ((0, malloy_types_1.isDateUnit)(this.timeframe)) {
156
- return (0, time_utils_1.mkTimeResult)({
157
- dataType: 'date',
158
- expressionType: (0, malloy_types_1.maxExpressionType)(lhs.expressionType, num.expressionType),
159
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(lhs.evalSpace, num.evalSpace),
160
- value: (0, time_utils_1.timeOffset)('date', lhs.value, op, num.value, this.timeframe),
161
- }, resultGranularity);
162
- }
163
- else {
147
+ if (lhs.dataType === 'date' && !(0, malloy_types_1.isDateUnit)(this.timeframe)) {
164
148
  return this.loggedErrorExpr('invalid-timeframe-for-time-offset', `Cannot offset date by ${this.timeframe}`);
165
149
  }
150
+ return (0, expr_value_1.computedTimeResult)({
151
+ dataType: lhs.dataType,
152
+ value: (0, time_utils_1.timeOffset)(lhs.dataType, lhs.value, op, num.value, this.timeframe),
153
+ timeframe: resultGranularity,
154
+ from: [lhs, num],
155
+ });
166
156
  }
167
157
  return super.apply(fs, op, left);
168
158
  }
169
- getExpression(_fs) {
170
- return {
159
+ getExpression(fs) {
160
+ const num = this.n.getExpression(fs);
161
+ return (0, expr_value_1.computedErrorExprValue)({
171
162
  dataType: 'duration',
172
- expressionType: 'scalar',
173
- value: { node: 'error', message: 'Duration is not a value' },
174
- evalSpace: 'constant',
175
- };
163
+ error: 'Duration is not a value',
164
+ from: [num],
165
+ });
176
166
  }
177
167
  }
178
168
  exports.ExprDuration = ExprDuration;
@@ -301,12 +291,11 @@ function equality(fs, left, op, right) {
301
291
  }
302
292
  }
303
293
  }
304
- return {
294
+ return (0, expr_value_1.computedExprValue)({
305
295
  dataType: 'boolean',
306
- expressionType: (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType),
307
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(lhs.evalSpace, rhs.evalSpace),
308
296
  value,
309
- };
297
+ from: [lhs, rhs],
298
+ });
310
299
  }
311
300
  function compare(fs, left, op, right) {
312
301
  const lhs = left.getExpression(fs);
@@ -314,7 +303,6 @@ function compare(fs, left, op, right) {
314
303
  const err = errorCascade('boolean', lhs, rhs);
315
304
  if (err)
316
305
  return err;
317
- const expressionType = (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType);
318
306
  const noCompare = unsupportError(left, lhs, right, rhs);
319
307
  if (noCompare) {
320
308
  return { ...noCompare, dataType: 'boolean' };
@@ -323,12 +311,11 @@ function compare(fs, left, op, right) {
323
311
  node: (0, binary_operators_1.getExprNode)(op),
324
312
  kids: { left: lhs.value, right: rhs.value },
325
313
  };
326
- return {
314
+ return (0, expr_value_1.computedExprValue)({
327
315
  dataType: 'boolean',
328
- expressionType,
329
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(lhs.evalSpace, rhs.evalSpace),
330
- value: value,
331
- };
316
+ value,
317
+ from: [lhs, rhs],
318
+ });
332
319
  }
333
320
  function numeric(fs, left, op, right) {
334
321
  const lhs = left.getExpression(fs);
@@ -339,7 +326,6 @@ function numeric(fs, left, op, right) {
339
326
  const noGo = unsupportError(left, lhs, right, rhs);
340
327
  if (noGo)
341
328
  return noGo;
342
- const expressionType = (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType);
343
329
  if (lhs.dataType !== 'number') {
344
330
  left.logError('arithmetic-operation-type-mismatch', `The '${op}' operator requires a number, not a '${lhs.dataType}'`);
345
331
  }
@@ -347,12 +333,11 @@ function numeric(fs, left, op, right) {
347
333
  right.logError('arithmetic-operation-type-mismatch', `The '${op}' operator requires a number, not a '${rhs.dataType}'`);
348
334
  }
349
335
  else {
350
- return {
336
+ return (0, expr_value_1.computedExprValue)({
351
337
  dataType: 'number',
352
- expressionType,
353
338
  value: { node: op, kids: { left: lhs.value, right: rhs.value } },
354
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(lhs.evalSpace, rhs.evalSpace),
355
- };
339
+ from: [lhs, rhs],
340
+ });
356
341
  }
357
342
  return (0, ast_utils_1.errorFor)('numbers required');
358
343
  }
@@ -428,12 +413,11 @@ function applyBinary(fs, left, op, right) {
428
413
  node: op,
429
414
  kids: { left: num.value, right: denom.value },
430
415
  };
431
- return {
416
+ return (0, expr_value_1.computedExprValue)({
432
417
  dataType: 'number',
433
- expressionType: (0, malloy_types_1.maxExpressionType)(num.expressionType, denom.expressionType),
434
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(num.evalSpace, denom.evalSpace),
435
418
  value: divmod,
436
- };
419
+ from: [num, denom],
420
+ });
437
421
  }
438
422
  return (0, ast_utils_1.errorFor)('divide type mismatch');
439
423
  }
@@ -442,24 +426,22 @@ function applyBinary(fs, left, op, right) {
442
426
  exports.applyBinary = applyBinary;
443
427
  function errorCascade(dataType, ...es) {
444
428
  if (es.some(e => e.dataType === 'error')) {
445
- return {
429
+ return (0, expr_value_1.computedExprValue)({
446
430
  dataType,
447
- expressionType: (0, malloy_types_1.maxOfExpressionTypes)(es.map(e => e.expressionType)),
448
431
  value: { node: 'error', message: 'cascading error' },
449
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(...es.map(e => e.evalSpace)),
450
- };
432
+ from: es,
433
+ });
451
434
  }
452
435
  }
453
436
  /**
454
437
  * Return an error if a binary operation includes unsupported types.
455
438
  */
456
439
  function unsupportError(l, lhs, r, rhs) {
457
- const ret = {
440
+ const ret = (0, expr_value_1.computedExprValue)({
458
441
  dataType: lhs.dataType,
459
- expressionType: (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType),
460
442
  value: { node: 'error', message: 'sql-native unsupported' },
461
- evalSpace: (0, malloy_types_1.mergeEvalSpaces)(lhs.evalSpace, rhs.evalSpace),
462
- };
443
+ from: [lhs, rhs],
444
+ });
463
445
  if (lhs.dataType === 'sql native') {
464
446
  l.logError('sql-native-not-allowed-in-expression', { rawType: lhs.rawType });
465
447
  ret.dataType = rhs.dataType;
@@ -337,7 +337,10 @@ function isLiteral(evalSpace) {
337
337
  }
338
338
  exports.isLiteral = isLiteral;
339
339
  function mergeEvalSpaces(...evalSpaces) {
340
- if (evalSpaces.every(e => e === 'constant' || e === 'literal')) {
340
+ if (evalSpaces.length <= 1 && evalSpaces.every(e => e === 'literal')) {
341
+ return 'literal';
342
+ }
343
+ else if (evalSpaces.every(e => e === 'constant' || e === 'literal')) {
341
344
  return 'constant';
342
345
  }
343
346
  else if (evalSpaces.every(e => e === 'output' || e === 'constant' || e === 'literal')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.203-dev241023170054",
3
+ "version": "0.0.203-dev241024163815",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",