@malloydata/malloy 0.0.262 → 0.0.263-dev250414184158

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 (40) hide show
  1. package/dist/lang/ast/expressions/expr-filter-expr.d.ts +0 -3
  2. package/dist/lang/ast/expressions/expr-filter-expr.js +7 -59
  3. package/dist/lang/ast/expressions/expr-func.js +3 -0
  4. package/dist/lang/ast/expressions/pick-when.js +6 -0
  5. package/dist/lang/ast/field-space/dynamic-space.js +1 -1
  6. package/dist/lang/ast/field-space/join-space-field.js +1 -1
  7. package/dist/lang/ast/index.d.ts +1 -0
  8. package/dist/lang/ast/index.js +1 -0
  9. package/dist/lang/ast/parameters/has-parameter.d.ts +6 -3
  10. package/dist/lang/ast/parameters/has-parameter.js +28 -9
  11. package/dist/lang/ast/query-items/field-declaration.d.ts +1 -2
  12. package/dist/lang/ast/query-items/field-declaration.js +0 -4
  13. package/dist/lang/ast/source-elements/named-source.js +6 -0
  14. package/dist/lang/ast/source-properties/join.d.ts +3 -3
  15. package/dist/lang/ast/source-properties/join.js +2 -2
  16. package/dist/lang/ast/types/expression-def.d.ts +2 -1
  17. package/dist/lang/ast/types/expression-def.js +79 -17
  18. package/dist/lang/ast/types/space-param.d.ts +1 -3
  19. package/dist/lang/ast/types/space-param.js +8 -8
  20. package/dist/lang/lib/Malloy/MalloyLexer.d.ts +114 -113
  21. package/dist/lang/lib/Malloy/MalloyLexer.js +1272 -1266
  22. package/dist/lang/lib/Malloy/MalloyParser.d.ts +253 -239
  23. package/dist/lang/lib/Malloy/MalloyParser.js +2244 -2142
  24. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +11 -0
  25. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +7 -0
  26. package/dist/lang/malloy-to-ast.d.ts +1 -1
  27. package/dist/lang/malloy-to-ast.js +38 -12
  28. package/dist/lang/test/expr-to-str.js +3 -20
  29. package/dist/model/filter_compilers.d.ts +27 -0
  30. package/dist/model/filter_compilers.js +335 -3
  31. package/dist/model/malloy_query.d.ts +2 -1
  32. package/dist/model/malloy_query.js +45 -10
  33. package/dist/model/malloy_types.d.ts +18 -6
  34. package/dist/model/malloy_types.js +6 -2
  35. package/dist/to_stable.js +19 -5
  36. package/dist/version.d.ts +1 -1
  37. package/dist/version.js +1 -1
  38. package/package.json +4 -4
  39. package/dist/model/filter_temporal_compiler.d.ts +0 -29
  40. package/dist/model/filter_temporal_compiler.js +0 -343
@@ -1,11 +1,8 @@
1
- import type { BinaryMalloyOperator } from '../types/binary_operators';
2
1
  import type { ExprValue } from '../types/expr-value';
3
2
  import { ExpressionDef } from '../types/expression-def';
4
- import type { FieldSpace } from '../types/field-space';
5
3
  export declare class ExprFilterExpression extends ExpressionDef {
6
4
  readonly filterText: string;
7
5
  elementType: string;
8
6
  constructor(filterText: string);
9
7
  getExpression(): ExprValue;
10
- apply(fs: FieldSpace, op: BinaryMalloyOperator, left: ExpressionDef, _warnOnComplexTree?: boolean): ExprValue;
11
8
  }
@@ -7,9 +7,7 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.ExprFilterExpression = void 0;
10
- const expr_value_1 = require("../types/expr-value");
11
10
  const expression_def_1 = require("../types/expression-def");
12
- const malloy_filter_1 = require("@malloydata/malloy-filter");
13
11
  class ExprFilterExpression extends expression_def_1.ExpressionDef {
14
12
  constructor(filterText) {
15
13
  super();
@@ -17,63 +15,13 @@ class ExprFilterExpression extends expression_def_1.ExpressionDef {
17
15
  this.elementType = 'filter expression literal';
18
16
  }
19
17
  getExpression() {
20
- return this.loggedErrorExpr('filter-expression-type', 'Filter expression illegal here');
21
- }
22
- apply(fs, op, left, _warnOnComplexTree = false) {
23
- var _a;
24
- if (op === '~' || op === '!~') {
25
- const matchExpr = left.getExpression(fs);
26
- if (matchExpr.type === 'error') {
27
- return matchExpr;
28
- }
29
- let fParse;
30
- switch (matchExpr.type) {
31
- case 'string':
32
- fParse = malloy_filter_1.StringFilterExpression.parse(this.filterText);
33
- break;
34
- case 'number':
35
- fParse = malloy_filter_1.NumberFilterExpression.parse(this.filterText);
36
- break;
37
- case 'boolean':
38
- if ((_a = fs.dialectObj()) === null || _a === void 0 ? void 0 : _a.booleanAsNumbers) {
39
- return this.loggedErrorExpr('filter-expression-type', 'Boolean filters not supported on this connection type');
40
- }
41
- fParse = malloy_filter_1.BooleanFilterExpression.parse(this.filterText);
42
- break;
43
- case 'date':
44
- case 'timestamp':
45
- fParse = malloy_filter_1.TemporalFilterExpression.parse(this.filterText);
46
- break;
47
- default:
48
- return left.loggedErrorExpr('filter-expression-type', `Cannot use filter expressions with type '${matchExpr.type}'`);
49
- }
50
- if (fParse.log.length > 0) {
51
- for (const err of fParse.log) {
52
- // Current parser only ever returns one error, it doesn't recover
53
- // Theoretically possible to user the startIndex to point to the
54
- // error inside the filter string, but I don't know if this is an
55
- // f' string or an f''' string, and I think the startOffset is from
56
- // the first non blank space in the filter (it was at one point)
57
- // so for now, we just flag the entire filter source token.
58
- return this.loggedErrorExpr('filter-expression-error', `Filter parse error: ${err.message}`);
59
- }
60
- }
61
- const filterMatch = {
62
- node: 'filterMatch',
63
- dataType: matchExpr.type,
64
- filter: fParse.parsed,
65
- e: matchExpr.value,
66
- };
67
- if (op === '!~') {
68
- filterMatch.notMatch = true;
69
- }
70
- return (0, expr_value_1.computedExprValue)({
71
- value: filterMatch,
72
- dataType: { type: 'boolean' },
73
- from: [matchExpr],
74
- });
75
- }
76
- return this.loggedErrorExpr('filter-expression-type', `Cannot use the '${op}' operator with a filter expression`);
18
+ return {
19
+ type: 'filter expression',
20
+ value: { node: 'filterLiteral', filterSrc: this.filterText },
21
+ expressionType: 'scalar',
22
+ evalSpace: 'constant',
23
+ compositeFieldUsage: { fields: [], joinedUsage: {} },
24
+ };
77
25
  }
78
26
  }
79
27
  exports.ExprFilterExpression = ExprFilterExpression;
@@ -309,6 +309,9 @@ class ExprFunc extends expression_def_1.ExpressionDef {
309
309
  if (result.found === undefined) {
310
310
  return this.loggedErrorExpr('sql-function-interpolation-not-found', `Invalid interpolation: ${result.error.message}`);
311
311
  }
312
+ if (result.found.typeDesc().type === 'filter expression') {
313
+ return this.loggedErrorExpr('filter-expression-error', 'Filter expressions cannot be used in sql_ functions');
314
+ }
312
315
  if (result.found.refType === 'parameter') {
313
316
  expr.push({ node: 'parameter', path: [part.name] });
314
317
  }
@@ -129,6 +129,9 @@ class Pick extends expression_def_1.ExpressionDef {
129
129
  });
130
130
  }
131
131
  }
132
+ if (definedReturnType.type === 'filter expression') {
133
+ return this.loggedErrorExpr('filter-expression-error', 'Pick statments cannot have filter expression values');
134
+ }
132
135
  caseValue.kids.caseElse = defaultVal.value;
133
136
  return (0, expr_value_1.computedExprValue)({
134
137
  dataType: definedReturnType,
@@ -188,6 +191,9 @@ class Pick extends expression_def_1.ExpressionDef {
188
191
  returnType: definedReturnType.type,
189
192
  });
190
193
  }
194
+ if (definedReturnType.type === 'filter expression') {
195
+ return this.loggedErrorExpr('filter-expression-error', 'Pick statments cannot have filter expression values');
196
+ }
191
197
  pick.kids.caseElse = defVal.value;
192
198
  return (0, expr_value_1.computedExprValue)({
193
199
  dataType: definedReturnType,
@@ -134,7 +134,7 @@ class DynamicSpace extends static_space_1.StaticSpace {
134
134
  const parameterSpace = this.parameterSpace();
135
135
  for (const [name, field] of reorderFields) {
136
136
  if (field instanceof join_space_field_1.JoinSpaceField) {
137
- const joinStruct = field.join.structDef(parameterSpace);
137
+ const joinStruct = field.join.getStructDef(parameterSpace);
138
138
  if (!error_factory_1.ErrorFactory.didCreate(joinStruct)) {
139
139
  fieldIndices.set(name, this.sourceDef.fields.length);
140
140
  this.sourceDef.fields.push(joinStruct);
@@ -26,7 +26,7 @@ exports.JoinSpaceField = void 0;
26
26
  const static_space_1 = require("./static-space");
27
27
  class JoinSpaceField extends static_space_1.StructSpaceField {
28
28
  constructor(parameterSpace, join, forDialect) {
29
- super(join.structDef(parameterSpace), forDialect);
29
+ super(join.getStructDef(parameterSpace), forDialect);
30
30
  this.parameterSpace = parameterSpace;
31
31
  this.join = join;
32
32
  }
@@ -19,6 +19,7 @@ export * from './source-properties/timezone-statement';
19
19
  export * from './expressions/apply';
20
20
  export * from './expressions/binary-numeric';
21
21
  export * from './expressions/boolean';
22
+ export * from './expressions/constant-expression';
22
23
  export * from './expressions/function-ordering';
23
24
  export * from './expressions/expr-add-sub';
24
25
  export * from './expressions/expr-aggregate-function';
@@ -57,6 +57,7 @@ __exportStar(require("./source-properties/timezone-statement"), exports);
57
57
  __exportStar(require("./expressions/apply"), exports);
58
58
  __exportStar(require("./expressions/binary-numeric"), exports);
59
59
  __exportStar(require("./expressions/boolean"), exports);
60
+ __exportStar(require("./expressions/constant-expression"), exports);
60
61
  __exportStar(require("./expressions/function-ordering"), exports);
61
62
  __exportStar(require("./expressions/expr-add-sub"), exports);
62
63
  __exportStar(require("./expressions/expr-aggregate-function"), exports);
@@ -1,16 +1,19 @@
1
- import type { Parameter, CastType } from '../../../model/malloy_types';
1
+ import type { FilterableType } from '@malloydata/malloy-filter';
2
+ import type { Parameter, ParameterType } from '../../../model/malloy_types';
2
3
  import type { ConstantExpression } from '../expressions/constant-expression';
3
4
  import { MalloyElement } from '../types/malloy-element';
4
5
  interface HasInit {
5
6
  name: string;
6
- type?: CastType;
7
+ type?: ParameterType;
8
+ filterType?: FilterableType;
7
9
  default?: ConstantExpression;
8
10
  }
9
11
  export declare class HasParameter extends MalloyElement {
10
12
  elementType: string;
11
13
  readonly name: string;
12
- readonly type?: CastType;
14
+ readonly type?: ParameterType;
13
15
  readonly default?: ConstantExpression;
16
+ readonly filterType?: FilterableType;
14
17
  constructor(init: HasInit);
15
18
  parameter(): Parameter;
16
19
  }
@@ -25,21 +25,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.HasParameter = void 0;
26
26
  const malloy_types_1 = require("../../../model/malloy_types");
27
27
  const malloy_element_1 = require("../types/malloy-element");
28
+ const expression_def_1 = require("../types/expression-def");
28
29
  class HasParameter extends malloy_element_1.MalloyElement {
29
30
  constructor(init) {
30
31
  super();
31
32
  this.elementType = 'hasParameter';
32
33
  this.name = init.name;
33
- if (init.type && (0, malloy_types_1.isCastType)(init.type)) {
34
+ if (init.type && (0, malloy_types_1.isParameterType)(init.type)) {
34
35
  this.type = init.type;
35
36
  }
36
37
  if (init.default) {
37
38
  this.default = init.default;
38
39
  this.has({ default: this.default });
39
40
  }
41
+ if (init.filterType)
42
+ this.filterType = init.filterType;
40
43
  }
41
44
  parameter() {
42
45
  var _a;
46
+ let paramReturn;
43
47
  if (this.default !== undefined) {
44
48
  const constant = this.default.constantValue();
45
49
  if (this.type &&
@@ -65,6 +69,19 @@ class HasParameter extends malloy_element_1.MalloyElement {
65
69
  };
66
70
  }
67
71
  }
72
+ if (constant.type === 'filter expression') {
73
+ if (this.type !== 'filter expression') {
74
+ this.logError('parameter-missing-default-or-type', `Filter expression parameters must have expicit filter type, for example '${this.name}::filter<string>'`);
75
+ }
76
+ if (this.filterType) {
77
+ (0, expression_def_1.checkFilterExpression)(this, this.filterType, constant.value);
78
+ }
79
+ return {
80
+ value: constant.value,
81
+ name: this.name,
82
+ type: constant.type,
83
+ };
84
+ }
68
85
  if (!(0, malloy_types_1.isCastType)(constant.type) && constant.type !== 'error') {
69
86
  this.default.logError('parameter-illegal-default-type', `Default value cannot have type \`${constant.type}\``);
70
87
  return {
@@ -73,20 +90,22 @@ class HasParameter extends malloy_element_1.MalloyElement {
73
90
  type: 'error',
74
91
  };
75
92
  }
76
- return {
93
+ paramReturn = {
77
94
  value: constant.value,
78
95
  name: this.name,
79
96
  type: constant.type,
80
97
  };
81
98
  }
82
- if (this.type === undefined) {
83
- this.logError('parameter-missing-default-or-type', 'Parameter must have default value or declared type');
99
+ else {
100
+ if (this.type === undefined) {
101
+ this.logError('parameter-missing-default-or-type', 'Parameter must have default value or declared type');
102
+ }
103
+ paramReturn = { value: null, name: this.name, type: (_a = this.type) !== null && _a !== void 0 ? _a : 'error' };
104
+ }
105
+ if (paramReturn.type === 'filter expression' && this.filterType) {
106
+ paramReturn.filterType = this.filterType;
84
107
  }
85
- return {
86
- value: null,
87
- name: this.name,
88
- type: (_a = this.type) !== null && _a !== void 0 ? _a : 'error',
89
- };
108
+ return paramReturn;
90
109
  }
91
110
  }
92
111
  exports.HasParameter = HasParameter;
@@ -1,5 +1,5 @@
1
1
  import type { Dialect } from '../../../dialect/dialect';
2
- import type { Annotation, StructDef, TypeDesc, FieldDef, AtomicFieldDef, FieldDefType } from '../../../model/malloy_types';
2
+ import type { Annotation, StructDef, TypeDesc, FieldDef, AtomicFieldDef } from '../../../model/malloy_types';
3
3
  import type { ExprValue } from '../types/expr-value';
4
4
  import type { ExpressionDef } from '../types/expression-def';
5
5
  import type { FieldName, FieldSpace, QueryFieldSpace } from '../types/field-space';
@@ -87,5 +87,4 @@ export declare class FieldDefinitionValue extends SpaceField {
87
87
  private defInQuery?;
88
88
  getQueryFieldDef(fs: FieldSpace): AtomicFieldDef;
89
89
  typeDesc(): TypeDesc;
90
- entryType(): FieldDefType;
91
90
  }
@@ -316,10 +316,6 @@ class FieldDefinitionValue extends space_field_1.SpaceField {
316
316
  }
317
317
  throw new Error(`Can't get typeDesc for ${typeFrom.type}`);
318
318
  }
319
- entryType() {
320
- const typeFrom = this.defInQuery || this.fieldDef();
321
- return typeFrom.type;
322
- }
323
319
  }
324
320
  exports.FieldDefinitionValue = FieldDefinitionValue;
325
321
  //# sourceMappingURL=field-declaration.js.map
@@ -31,6 +31,7 @@ const time_utils_1 = require("../time-utils");
31
31
  const malloy_element_1 = require("../types/malloy-element");
32
32
  const expr_id_reference_1 = require("../expressions/expr-id-reference");
33
33
  const parameter_space_1 = require("../field-space/parameter-space");
34
+ const expression_def_1 = require("../types/expression-def");
34
35
  class NamedSource extends source_1.Source {
35
36
  constructor(ref, sourceArguments, args) {
36
37
  super();
@@ -140,6 +141,11 @@ class NamedSource extends source_1.Source {
140
141
  const paramSpace = parameterSpace !== null && parameterSpace !== void 0 ? parameterSpace : new parameter_space_1.ParameterSpace(parametersOut !== null && parametersOut !== void 0 ? parametersOut : []);
141
142
  const pVal = argument.value.getExpression(paramSpace);
142
143
  let value = pVal.value;
144
+ if (pVal.type === 'filter expression' &&
145
+ parameter.type === 'filter expression' &&
146
+ parameter.filterType) {
147
+ (0, expression_def_1.checkFilterExpression)(argument.value, parameter.filterType, value);
148
+ }
143
149
  if (pVal.type !== parameter.type && (0, malloy_types_1.isCastType)(parameter.type)) {
144
150
  value = (0, time_utils_1.castTo)(parameter.type, pVal.value, pVal.type, true);
145
151
  }
@@ -15,7 +15,7 @@ import type { QueryPropertyInterface } from '../types/query-property-interface';
15
15
  import { LegalRefinementStage } from '../types/query-property-interface';
16
16
  export declare abstract class Join extends MalloyElement implements Noteable, MakeEntry {
17
17
  abstract name: ModelEntryReference;
18
- abstract structDef(parameterSpace: ParameterSpace): JoinFieldDef;
18
+ abstract getStructDef(parameterSpace: ParameterSpace): JoinFieldDef;
19
19
  abstract fixupJoinOn(outer: FieldSpace, inStruct: JoinFieldDef): void;
20
20
  readonly isNoteableObj = true;
21
21
  extendNote: typeof extendNoteMethod;
@@ -31,7 +31,7 @@ export declare class KeyJoin extends Join {
31
31
  readonly keyExpr: ExpressionDef;
32
32
  elementType: string;
33
33
  constructor(name: ModelEntryReference, sourceExpr: SourceQueryElement, keyExpr: ExpressionDef);
34
- structDef(parameterSpace: ParameterSpace): JoinFieldDef;
34
+ getStructDef(parameterSpace: ParameterSpace): JoinFieldDef;
35
35
  fixupJoinOn(outer: FieldSpace, inStruct: JoinFieldDef): void;
36
36
  }
37
37
  export declare class ExpressionJoin extends Join {
@@ -45,7 +45,7 @@ export declare class ExpressionJoin extends Join {
45
45
  set joinOn(joinExpr: ExpressionDef | undefined);
46
46
  get joinOn(): ExpressionDef | undefined;
47
47
  fixupJoinOn(outer: FieldSpace, inStruct: JoinFieldDef): void;
48
- structDef(parameterSpace: ParameterSpace): JoinFieldDef;
48
+ getStructDef(parameterSpace: ParameterSpace): JoinFieldDef;
49
49
  }
50
50
  export declare class JoinStatement extends DefinitionList<Join> implements QueryPropertyInterface {
51
51
  readonly accessModifier: AccessModifierLabel | undefined;
@@ -60,7 +60,7 @@ class KeyJoin extends Join {
60
60
  this.keyExpr = keyExpr;
61
61
  this.elementType = 'joinOnKey';
62
62
  }
63
- structDef(parameterSpace) {
63
+ getStructDef(parameterSpace) {
64
64
  var _a;
65
65
  const sourceDef = this.getStructDefFromExpr(parameterSpace);
66
66
  if (!(0, malloy_types_1.isJoinable)(sourceDef)) {
@@ -143,7 +143,7 @@ class ExpressionJoin extends Join {
143
143
  inStruct.onExpression = exprX.value;
144
144
  inStruct.onCompositeFieldUsage = exprX.compositeFieldUsage;
145
145
  }
146
- structDef(parameterSpace) {
146
+ getStructDef(parameterSpace) {
147
147
  var _a;
148
148
  const source = this.sourceExpr.getSource();
149
149
  if (!source) {
@@ -1,4 +1,4 @@
1
- import type { TimestampUnit } from '../../../model/malloy_types';
1
+ import type { Expr, TimestampUnit } from '../../../model/malloy_types';
2
2
  import type { ExprValue } from './expr-value';
3
3
  import type { FieldSpace } from './field-space';
4
4
  import { MalloyElement } from './malloy-element';
@@ -83,3 +83,4 @@ export declare function getMorphicValue(mv: ExprValue, mt: MorphicType): ExprVal
83
83
  * @return ExprValue of the expression
84
84
  */
85
85
  export declare function applyBinary(fs: FieldSpace, left: ExpressionDef, op: BinaryMalloyOperator, right: ExpressionDef): ExprValue;
86
+ export declare function checkFilterExpression(logTo: MalloyElement, ft: string, fexpr: Expr): void;
@@ -45,7 +45,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
45
45
  return result;
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.applyBinary = exports.getMorphicValue = exports.ExprDuration = exports.ExpressionDef = exports.ATNodeType = void 0;
48
+ exports.checkFilterExpression = exports.applyBinary = exports.getMorphicValue = exports.ExprDuration = exports.ExpressionDef = exports.ATNodeType = void 0;
49
49
  const malloy_types_1 = require("../../../model/malloy_types");
50
50
  const TDU = __importStar(require("../typedesc-utils"));
51
51
  const ast_utils_1 = require("../ast-utils");
@@ -54,6 +54,7 @@ const time_utils_1 = require("../time-utils");
54
54
  const granular_result_1 = require("./granular-result");
55
55
  const malloy_element_1 = require("./malloy-element");
56
56
  const binary_operators_1 = require("./binary_operators");
57
+ const malloy_filter_1 = require("@malloydata/malloy-filter");
57
58
  class TypeMismatch extends Error {
58
59
  }
59
60
  /** Node types in an alternation tree */
@@ -270,24 +271,54 @@ function equality(fs, left, op, right) {
270
271
  }
271
272
  }
272
273
  }
273
- let value = timeCompare(left, lhs, op, rhs) || {
274
- node,
275
- kids: { left: lhs.value, right: rhs.value },
276
- };
277
- if (lhs.type !== 'error' &&
278
- rhs.type !== 'error' &&
279
- (op === '~' || op === '!~')) {
280
- if (lhs.type !== 'string' || rhs.type !== 'string') {
281
- let regexCmp = regexEqual(lhs, rhs);
282
- if (regexCmp) {
283
- if (op[0] === '!') {
284
- regexCmp = { node: 'not', e: { ...regexCmp } };
285
- }
274
+ let value;
275
+ if (rhs.type === 'filter expression') {
276
+ if (op !== '~' && op !== '!~') {
277
+ return right.loggedErrorExpr('filter-expression-error', `Cannot use the '${op}' operator with a filter expression`);
278
+ }
279
+ if ((0, malloy_filter_1.isFilterable)(lhs.type)) {
280
+ let actualFilter = rhs.value;
281
+ while (actualFilter.node === '()') {
282
+ actualFilter = actualFilter.e;
286
283
  }
287
- else {
288
- throw new TypeMismatch("Incompatible types for match('~') operator");
284
+ if (actualFilter.node !== 'parameter') {
285
+ // Parameters are checked when parameter value is parsed
286
+ checkFilterExpression(right, lhs.type, actualFilter);
287
+ }
288
+ const filterMatch = {
289
+ node: 'filterMatch',
290
+ dataType: lhs.type,
291
+ kids: { filterExpr: rhs.value, expr: lhs.value },
292
+ };
293
+ if (op === '!~') {
294
+ filterMatch.notMatch = true;
295
+ }
296
+ value = filterMatch;
297
+ }
298
+ else {
299
+ return left.loggedErrorExpr('filter-expression-type', `Cannot use filter expressions with type '${lhs.type}'`);
300
+ }
301
+ }
302
+ else {
303
+ value = timeCompare(left, lhs, op, rhs) || {
304
+ node,
305
+ kids: { left: lhs.value, right: rhs.value },
306
+ };
307
+ if (lhs.type !== 'error' &&
308
+ rhs.type !== 'error' &&
309
+ (op === '~' || op === '!~')) {
310
+ if (lhs.type !== 'string' || rhs.type !== 'string') {
311
+ let regexCmp = regexEqual(lhs, rhs);
312
+ if (regexCmp) {
313
+ if (op[0] === '!') {
314
+ regexCmp = { node: 'not', e: { ...regexCmp } };
315
+ }
316
+ }
317
+ else {
318
+ throw new TypeMismatch("Incompatible types for match('~') operator");
319
+ }
320
+ value = regexCmp;
289
321
  }
290
- value = regexCmp;
291
322
  }
292
323
  }
293
324
  return (0, expr_value_1.computedExprValue)({
@@ -452,4 +483,35 @@ function unsupportError(l, lhs, r, rhs) {
452
483
  }
453
484
  return undefined;
454
485
  }
486
+ function checkFilterExpression(logTo, ft, fexpr) {
487
+ var _a, _b, _c, _d;
488
+ while (fexpr.node === '()') {
489
+ fexpr = fexpr.e;
490
+ }
491
+ if (fexpr.node !== 'filterLiteral') {
492
+ logTo.logError('filter-expression-error', 'Expected a filter expression literal here');
493
+ return;
494
+ }
495
+ const fsrc = fexpr.filterSrc;
496
+ let err;
497
+ if (ft === 'date' || ft === 'timestamp') {
498
+ err = (_a = malloy_filter_1.TemporalFilterExpression.parse(fsrc).log[0]) === null || _a === void 0 ? void 0 : _a.message;
499
+ }
500
+ else if (ft === 'string') {
501
+ err = (_b = malloy_filter_1.StringFilterExpression.parse(fsrc).log[0]) === null || _b === void 0 ? void 0 : _b.message;
502
+ }
503
+ else if (ft === 'number') {
504
+ err = (_c = malloy_filter_1.NumberFilterExpression.parse(fsrc).log[0]) === null || _c === void 0 ? void 0 : _c.message;
505
+ }
506
+ else if (ft === 'boolean') {
507
+ err = (_d = malloy_filter_1.BooleanFilterExpression.parse(fsrc).log[0]) === null || _d === void 0 ? void 0 : _d.message;
508
+ }
509
+ else {
510
+ logTo.logError('filter-expression-type', `Cannot apply filter expression to type ${ft}`);
511
+ }
512
+ if (err !== undefined) {
513
+ logTo.logError('filter-expression-error', `Filter syntax error: ${err}`);
514
+ }
515
+ }
516
+ exports.checkFilterExpression = checkFilterExpression;
455
517
  //# sourceMappingURL=expression-def.js.map
@@ -1,4 +1,4 @@
1
- import type { FieldDefType, Parameter, TypeDesc } from '../../../model/malloy_types';
1
+ import { type Parameter, type TypeDesc } from '../../../model/malloy_types';
2
2
  import { SpaceEntry } from './space-entry';
3
3
  import type { HasParameter } from '../parameters/has-parameter';
4
4
  export declare abstract class SpaceParam extends SpaceEntry {
@@ -11,12 +11,10 @@ export declare class AbstractParameter extends SpaceParam {
11
11
  _parameter: Parameter | undefined;
12
12
  parameter(): Parameter;
13
13
  typeDesc(): TypeDesc;
14
- entryType(): FieldDefType;
15
14
  }
16
15
  export declare class DefinedParameter extends SpaceParam {
17
16
  readonly paramDef: Parameter;
18
17
  constructor(paramDef: Parameter);
19
18
  parameter(): Parameter;
20
19
  typeDesc(): TypeDesc;
21
- entryType(): FieldDefType;
22
20
  }
@@ -69,16 +69,16 @@ class AbstractParameter extends SpaceParam {
69
69
  return this._parameter;
70
70
  }
71
71
  typeDesc() {
72
+ const p = this.parameter();
73
+ const t = p.type;
74
+ const theType = t === 'filter expression' ? { type: t } : TDU.atomicDef(p);
72
75
  return {
73
- ...TDU.atomicDef(this.parameter()),
76
+ ...theType,
74
77
  expressionType: 'scalar',
75
78
  evalSpace: 'constant',
76
79
  compositeFieldUsage: (0, composite_source_utils_1.emptyCompositeFieldUsage)(),
77
80
  };
78
81
  }
79
- entryType() {
80
- return this.parameter().type;
81
- }
82
82
  }
83
83
  exports.AbstractParameter = AbstractParameter;
84
84
  class DefinedParameter extends SpaceParam {
@@ -90,8 +90,11 @@ class DefinedParameter extends SpaceParam {
90
90
  return this.paramDef;
91
91
  }
92
92
  typeDesc() {
93
+ const p = this.parameter();
94
+ const t = p.type;
95
+ const theType = t === 'filter expression' ? { type: t } : TDU.atomicDef(p);
93
96
  return {
94
- ...TDU.atomicDef(this.paramDef),
97
+ ...theType,
95
98
  expressionType: 'scalar',
96
99
  // TODO Not sure whether params are considered "input space". It seems like they
97
100
  // could be input or constant, depending on usage (same as above).
@@ -99,9 +102,6 @@ class DefinedParameter extends SpaceParam {
99
102
  compositeFieldUsage: (0, composite_source_utils_1.emptyCompositeFieldUsage)(),
100
103
  };
101
104
  }
102
- entryType() {
103
- return this.paramDef.type;
104
- }
105
105
  }
106
106
  exports.DefinedParameter = DefinedParameter;
107
107
  //# sourceMappingURL=space-param.js.map