@malloydata/malloy 0.0.391 → 0.0.393
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.
- package/dist/api/asynchronous.js +0 -3
- package/dist/api/foundation/compile.d.ts +1 -1
- package/dist/api/foundation/config.d.ts +80 -8
- package/dist/api/foundation/config.js +151 -69
- package/dist/api/foundation/config_compile.js +27 -35
- package/dist/api/foundation/config_discover.js +5 -9
- package/dist/api/foundation/config_overlays.d.ts +6 -0
- package/dist/api/foundation/config_overlays.js +12 -0
- package/dist/api/foundation/config_resolve.d.ts +4 -1
- package/dist/api/foundation/config_resolve.js +64 -4
- package/dist/api/foundation/core.d.ts +75 -2
- package/dist/api/foundation/core.js +104 -6
- package/dist/api/foundation/index.d.ts +2 -0
- package/dist/api/foundation/readers.js +1 -1
- package/dist/api/foundation/runtime.d.ts +68 -2
- package/dist/api/foundation/runtime.js +212 -10
- package/dist/api/foundation/types.d.ts +2 -1
- package/dist/index.d.ts +3 -1
- package/dist/lang/ast/ast-utils.js +0 -1
- package/dist/lang/ast/expressions/expr-aggregate-function.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-aggregate-function.js +9 -8
- package/dist/lang/ast/expressions/expr-coalesce.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-coalesce.js +2 -3
- package/dist/lang/ast/expressions/expr-count-distinct.js +1 -1
- package/dist/lang/ast/expressions/expr-count.js +6 -4
- package/dist/lang/ast/expressions/expr-filter-expr.js +0 -1
- package/dist/lang/ast/expressions/expr-func.js +9 -4
- package/dist/lang/ast/expressions/expr-given.d.ts +18 -0
- package/dist/lang/ast/expressions/expr-given.js +69 -0
- package/dist/lang/ast/expressions/expr-granular-time.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-id-reference.js +3 -2
- package/dist/lang/ast/expressions/expr-now.js +0 -1
- package/dist/lang/ast/expressions/expr-props.d.ts +132 -132
- package/dist/lang/ast/expressions/expr-props.js +2 -2
- package/dist/lang/ast/expressions/expr-ungroup.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-ungroup.js +4 -4
- package/dist/lang/ast/expressions/for-range.d.ts +1 -1
- package/dist/lang/ast/expressions/function-ordering.d.ts +1 -1
- package/dist/lang/ast/expressions/function-ordering.js +2 -2
- package/dist/lang/ast/expressions/time-literal.d.ts +3 -3
- package/dist/lang/ast/field-space/include-utils.js +2 -2
- package/dist/lang/ast/field-space/index-field-space.js +18 -23
- package/dist/lang/ast/field-space/passthrough-space.d.ts +1 -1
- package/dist/lang/ast/field-space/query-spaces.d.ts +6 -2
- package/dist/lang/ast/field-space/query-spaces.js +29 -19
- package/dist/lang/ast/field-space/reference-field.js +1 -1
- package/dist/lang/ast/field-space/rename-space-field.d.ts +1 -1
- package/dist/lang/ast/field-space/rename-space-field.js +2 -2
- package/dist/lang/ast/field-space/struct-space-field-base.js +2 -3
- package/dist/lang/ast/index.d.ts +2 -0
- package/dist/lang/ast/index.js +2 -0
- package/dist/lang/ast/query-builders/index-builder.d.ts +1 -1
- package/dist/lang/ast/query-builders/index-builder.js +4 -3
- package/dist/lang/ast/query-builders/reduce-builder.d.ts +2 -2
- package/dist/lang/ast/query-builders/reduce-builder.js +4 -5
- package/dist/lang/ast/query-elements/query-arrow.js +3 -2
- package/dist/lang/ast/query-elements/query-base.d.ts +1 -1
- package/dist/lang/ast/query-elements/query-base.js +1 -1
- package/dist/lang/ast/query-elements/query-refine.js +3 -1
- package/dist/lang/ast/query-items/field-declaration.js +2 -2
- package/dist/lang/ast/query-properties/drill.js +6 -6
- package/dist/lang/ast/query-properties/filters.js +2 -2
- package/dist/lang/ast/query-properties/nest.js +3 -3
- package/dist/lang/ast/source-elements/composite-source.js +5 -3
- package/dist/lang/ast/source-elements/named-source.js +4 -0
- package/dist/lang/ast/source-elements/sql-source.js +2 -2
- package/dist/lang/ast/source-elements/table-source.js +3 -1
- package/dist/lang/ast/source-properties/join.js +4 -4
- package/dist/lang/ast/source-query-elements/sq-reference.js +2 -1
- package/dist/lang/ast/statements/define-given.d.ts +23 -0
- package/dist/lang/ast/statements/define-given.js +163 -0
- package/dist/lang/ast/statements/import-statement.js +72 -9
- package/dist/lang/ast/typedesc-utils.d.ts +3 -1
- package/dist/lang/ast/typedesc-utils.js +4 -47
- package/dist/lang/ast/types/expr-value.js +2 -3
- package/dist/lang/ast/types/expression-def.d.ts +2 -2
- package/dist/lang/ast/types/expression-def.js +2 -2
- package/dist/lang/ast/types/malloy-element.d.ts +5 -15
- package/dist/lang/ast/types/malloy-element.js +113 -1
- package/dist/lang/ast/types/space-field.js +7 -9
- package/dist/lang/ast/view-elements/reference-view.js +6 -5
- package/dist/lang/ast/view-elements/refine-utils.js +1 -1
- package/dist/lang/composite-source-utils.d.ts +30 -15
- package/dist/lang/composite-source-utils.js +234 -64
- package/dist/lang/lib/Malloy/MalloyLexer.d.ts +171 -169
- package/dist/lang/lib/Malloy/MalloyLexer.js +1194 -1178
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +408 -334
- package/dist/lang/lib/Malloy/MalloyParser.js +3062 -2561
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +68 -0
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +43 -0
- package/dist/lang/malloy-to-ast.d.ts +13 -1
- package/dist/lang/malloy-to-ast.js +90 -11
- package/dist/lang/parse-log.d.ts +8 -0
- package/dist/lang/prettify/filter-type.d.ts +3 -0
- package/dist/lang/prettify/filter-type.js +38 -0
- package/dist/lang/prettify/formatter.js +6 -0
- package/dist/lang/prettify/inline-renderer.js +20 -0
- package/dist/lang/prettify/rules.d.ts +1 -1
- package/dist/lang/prettify/rules.js +1 -0
- package/dist/lang/prettify/sections.js +2 -0
- package/dist/lang/prettify/tokens.js +2 -0
- package/dist/lang/test/expr-to-str.js +2 -0
- package/dist/lang/test/parse-expects.d.ts +1 -0
- package/dist/lang/test/parse-expects.js +27 -10
- package/dist/model/constant_expression_compiler.js +1 -0
- package/dist/model/expression_compiler.d.ts +2 -1
- package/dist/model/expression_compiler.js +41 -1
- package/dist/model/given_binding.d.ts +2 -0
- package/dist/model/given_binding.js +204 -0
- package/dist/model/index.d.ts +1 -1
- package/dist/model/index.js +2 -1
- package/dist/model/malloy_types.d.ts +163 -36
- package/dist/model/malloy_types.js +97 -0
- package/dist/model/query_model_contract.d.ts +2 -1
- package/dist/model/query_model_impl.d.ts +2 -1
- package/dist/model/query_model_impl.js +7 -0
- package/dist/model/query_node.d.ts +2 -1
- package/dist/model/source_def_utils.d.ts +2 -1
- package/dist/model/source_def_utils.js +4 -0
- package/dist/model/utils.d.ts +14 -1
- package/dist/model/utils.js +41 -0
- package/dist/to_stable.js +1 -1
- package/dist/util/closest_match.d.ts +9 -0
- package/dist/util/closest_match.js +47 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -22,6 +22,7 @@ import { FilterString_stubContext } from "./MalloyParser";
|
|
|
22
22
|
import { ExprNowContext } from "./MalloyParser";
|
|
23
23
|
import { NestDefContext } from "./MalloyParser";
|
|
24
24
|
import { ExprFieldPathContext } from "./MalloyParser";
|
|
25
|
+
import { ExprGivenRefContext } from "./MalloyParser";
|
|
25
26
|
import { ExprLiteralContext } from "./MalloyParser";
|
|
26
27
|
import { ExprArrayLiteralContext } from "./MalloyParser";
|
|
27
28
|
import { ExprLiteralRecordContext } from "./MalloyParser";
|
|
@@ -100,6 +101,11 @@ import { UserTypeShapeContext } from "./MalloyParser";
|
|
|
100
101
|
import { UserTypeFieldContext } from "./MalloyParser";
|
|
101
102
|
import { UserTypeFieldTypeContext } from "./MalloyParser";
|
|
102
103
|
import { DefineQueryContext } from "./MalloyParser";
|
|
104
|
+
import { DefineGivenStatementContext } from "./MalloyParser";
|
|
105
|
+
import { GivenDefListContext } from "./MalloyParser";
|
|
106
|
+
import { GivenDefContext } from "./MalloyParser";
|
|
107
|
+
import { GivenNameDefContext } from "./MalloyParser";
|
|
108
|
+
import { GivenTypeContext } from "./MalloyParser";
|
|
103
109
|
import { TopLevelAnonQueryDefContext } from "./MalloyParser";
|
|
104
110
|
import { AnnotationContext } from "./MalloyParser";
|
|
105
111
|
import { TagsContext } from "./MalloyParser";
|
|
@@ -546,6 +552,18 @@ export interface MalloyParserListener extends ParseTreeListener {
|
|
|
546
552
|
* @param ctx the parse tree
|
|
547
553
|
*/
|
|
548
554
|
exitExprFieldPath?: (ctx: ExprFieldPathContext) => void;
|
|
555
|
+
/**
|
|
556
|
+
* Enter a parse tree produced by the `exprGivenRef`
|
|
557
|
+
* labeled alternative in `MalloyParser.fieldExpr`.
|
|
558
|
+
* @param ctx the parse tree
|
|
559
|
+
*/
|
|
560
|
+
enterExprGivenRef?: (ctx: ExprGivenRefContext) => void;
|
|
561
|
+
/**
|
|
562
|
+
* Exit a parse tree produced by the `exprGivenRef`
|
|
563
|
+
* labeled alternative in `MalloyParser.fieldExpr`.
|
|
564
|
+
* @param ctx the parse tree
|
|
565
|
+
*/
|
|
566
|
+
exitExprGivenRef?: (ctx: ExprGivenRefContext) => void;
|
|
549
567
|
/**
|
|
550
568
|
* Enter a parse tree produced by the `exprLiteral`
|
|
551
569
|
* labeled alternative in `MalloyParser.fieldExpr`.
|
|
@@ -1458,6 +1476,56 @@ export interface MalloyParserListener extends ParseTreeListener {
|
|
|
1458
1476
|
* @param ctx the parse tree
|
|
1459
1477
|
*/
|
|
1460
1478
|
exitDefineQuery?: (ctx: DefineQueryContext) => void;
|
|
1479
|
+
/**
|
|
1480
|
+
* Enter a parse tree produced by `MalloyParser.defineGivenStatement`.
|
|
1481
|
+
* @param ctx the parse tree
|
|
1482
|
+
*/
|
|
1483
|
+
enterDefineGivenStatement?: (ctx: DefineGivenStatementContext) => void;
|
|
1484
|
+
/**
|
|
1485
|
+
* Exit a parse tree produced by `MalloyParser.defineGivenStatement`.
|
|
1486
|
+
* @param ctx the parse tree
|
|
1487
|
+
*/
|
|
1488
|
+
exitDefineGivenStatement?: (ctx: DefineGivenStatementContext) => void;
|
|
1489
|
+
/**
|
|
1490
|
+
* Enter a parse tree produced by `MalloyParser.givenDefList`.
|
|
1491
|
+
* @param ctx the parse tree
|
|
1492
|
+
*/
|
|
1493
|
+
enterGivenDefList?: (ctx: GivenDefListContext) => void;
|
|
1494
|
+
/**
|
|
1495
|
+
* Exit a parse tree produced by `MalloyParser.givenDefList`.
|
|
1496
|
+
* @param ctx the parse tree
|
|
1497
|
+
*/
|
|
1498
|
+
exitGivenDefList?: (ctx: GivenDefListContext) => void;
|
|
1499
|
+
/**
|
|
1500
|
+
* Enter a parse tree produced by `MalloyParser.givenDef`.
|
|
1501
|
+
* @param ctx the parse tree
|
|
1502
|
+
*/
|
|
1503
|
+
enterGivenDef?: (ctx: GivenDefContext) => void;
|
|
1504
|
+
/**
|
|
1505
|
+
* Exit a parse tree produced by `MalloyParser.givenDef`.
|
|
1506
|
+
* @param ctx the parse tree
|
|
1507
|
+
*/
|
|
1508
|
+
exitGivenDef?: (ctx: GivenDefContext) => void;
|
|
1509
|
+
/**
|
|
1510
|
+
* Enter a parse tree produced by `MalloyParser.givenNameDef`.
|
|
1511
|
+
* @param ctx the parse tree
|
|
1512
|
+
*/
|
|
1513
|
+
enterGivenNameDef?: (ctx: GivenNameDefContext) => void;
|
|
1514
|
+
/**
|
|
1515
|
+
* Exit a parse tree produced by `MalloyParser.givenNameDef`.
|
|
1516
|
+
* @param ctx the parse tree
|
|
1517
|
+
*/
|
|
1518
|
+
exitGivenNameDef?: (ctx: GivenNameDefContext) => void;
|
|
1519
|
+
/**
|
|
1520
|
+
* Enter a parse tree produced by `MalloyParser.givenType`.
|
|
1521
|
+
* @param ctx the parse tree
|
|
1522
|
+
*/
|
|
1523
|
+
enterGivenType?: (ctx: GivenTypeContext) => void;
|
|
1524
|
+
/**
|
|
1525
|
+
* Exit a parse tree produced by `MalloyParser.givenType`.
|
|
1526
|
+
* @param ctx the parse tree
|
|
1527
|
+
*/
|
|
1528
|
+
exitGivenType?: (ctx: GivenTypeContext) => void;
|
|
1461
1529
|
/**
|
|
1462
1530
|
* Enter a parse tree produced by `MalloyParser.topLevelAnonQueryDef`.
|
|
1463
1531
|
* @param ctx the parse tree
|
|
@@ -22,6 +22,7 @@ import { FilterString_stubContext } from "./MalloyParser";
|
|
|
22
22
|
import { ExprNowContext } from "./MalloyParser";
|
|
23
23
|
import { NestDefContext } from "./MalloyParser";
|
|
24
24
|
import { ExprFieldPathContext } from "./MalloyParser";
|
|
25
|
+
import { ExprGivenRefContext } from "./MalloyParser";
|
|
25
26
|
import { ExprLiteralContext } from "./MalloyParser";
|
|
26
27
|
import { ExprArrayLiteralContext } from "./MalloyParser";
|
|
27
28
|
import { ExprLiteralRecordContext } from "./MalloyParser";
|
|
@@ -100,6 +101,11 @@ import { UserTypeShapeContext } from "./MalloyParser";
|
|
|
100
101
|
import { UserTypeFieldContext } from "./MalloyParser";
|
|
101
102
|
import { UserTypeFieldTypeContext } from "./MalloyParser";
|
|
102
103
|
import { DefineQueryContext } from "./MalloyParser";
|
|
104
|
+
import { DefineGivenStatementContext } from "./MalloyParser";
|
|
105
|
+
import { GivenDefListContext } from "./MalloyParser";
|
|
106
|
+
import { GivenDefContext } from "./MalloyParser";
|
|
107
|
+
import { GivenNameDefContext } from "./MalloyParser";
|
|
108
|
+
import { GivenTypeContext } from "./MalloyParser";
|
|
103
109
|
import { TopLevelAnonQueryDefContext } from "./MalloyParser";
|
|
104
110
|
import { AnnotationContext } from "./MalloyParser";
|
|
105
111
|
import { TagsContext } from "./MalloyParser";
|
|
@@ -434,6 +440,13 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
|
|
|
434
440
|
* @return the visitor result
|
|
435
441
|
*/
|
|
436
442
|
visitExprFieldPath?: (ctx: ExprFieldPathContext) => Result;
|
|
443
|
+
/**
|
|
444
|
+
* Visit a parse tree produced by the `exprGivenRef`
|
|
445
|
+
* labeled alternative in `MalloyParser.fieldExpr`.
|
|
446
|
+
* @param ctx the parse tree
|
|
447
|
+
* @return the visitor result
|
|
448
|
+
*/
|
|
449
|
+
visitExprGivenRef?: (ctx: ExprGivenRefContext) => Result;
|
|
437
450
|
/**
|
|
438
451
|
* Visit a parse tree produced by the `exprLiteral`
|
|
439
452
|
* labeled alternative in `MalloyParser.fieldExpr`.
|
|
@@ -968,6 +981,36 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
|
|
|
968
981
|
* @return the visitor result
|
|
969
982
|
*/
|
|
970
983
|
visitDefineQuery?: (ctx: DefineQueryContext) => Result;
|
|
984
|
+
/**
|
|
985
|
+
* Visit a parse tree produced by `MalloyParser.defineGivenStatement`.
|
|
986
|
+
* @param ctx the parse tree
|
|
987
|
+
* @return the visitor result
|
|
988
|
+
*/
|
|
989
|
+
visitDefineGivenStatement?: (ctx: DefineGivenStatementContext) => Result;
|
|
990
|
+
/**
|
|
991
|
+
* Visit a parse tree produced by `MalloyParser.givenDefList`.
|
|
992
|
+
* @param ctx the parse tree
|
|
993
|
+
* @return the visitor result
|
|
994
|
+
*/
|
|
995
|
+
visitGivenDefList?: (ctx: GivenDefListContext) => Result;
|
|
996
|
+
/**
|
|
997
|
+
* Visit a parse tree produced by `MalloyParser.givenDef`.
|
|
998
|
+
* @param ctx the parse tree
|
|
999
|
+
* @return the visitor result
|
|
1000
|
+
*/
|
|
1001
|
+
visitGivenDef?: (ctx: GivenDefContext) => Result;
|
|
1002
|
+
/**
|
|
1003
|
+
* Visit a parse tree produced by `MalloyParser.givenNameDef`.
|
|
1004
|
+
* @param ctx the parse tree
|
|
1005
|
+
* @return the visitor result
|
|
1006
|
+
*/
|
|
1007
|
+
visitGivenNameDef?: (ctx: GivenNameDefContext) => Result;
|
|
1008
|
+
/**
|
|
1009
|
+
* Visit a parse tree produced by `MalloyParser.givenType`.
|
|
1010
|
+
* @param ctx the parse tree
|
|
1011
|
+
* @return the visitor result
|
|
1012
|
+
*/
|
|
1013
|
+
visitGivenType?: (ctx: GivenTypeContext) => Result;
|
|
971
1014
|
/**
|
|
972
1015
|
* Visit a parse tree produced by `MalloyParser.topLevelAnonQueryDef`.
|
|
973
1016
|
* @param ctx the parse tree
|
|
@@ -8,7 +8,7 @@ import type { LogMessageOptions, MessageCode, MessageLogger, MessageParameterTyp
|
|
|
8
8
|
import type { MalloyParseInfo } from './malloy-parse-info';
|
|
9
9
|
import type { FieldDeclarationConstructor } from './ast';
|
|
10
10
|
import type { HasString, HasID } from './parse-utils';
|
|
11
|
-
import type { AccessModifierLabel, AtomicTypeDef, BasicAtomicTypeDef, DocumentLocation, DocumentRange, Note } from '../model/malloy_types';
|
|
11
|
+
import type { AccessModifierLabel, AtomicTypeDef, BasicAtomicTypeDef, DocumentLocation, DocumentRange, FilterExprType, GivenTypeDef, Note } from '../model/malloy_types';
|
|
12
12
|
import type { Tag } from '@malloydata/malloy-tag';
|
|
13
13
|
import type * as Malloy from '@malloydata/malloy-interfaces';
|
|
14
14
|
import { Timer } from '../timing';
|
|
@@ -89,6 +89,17 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
|
|
|
89
89
|
protected getIsNotes(cx: parse.IsDefineContext): Note[];
|
|
90
90
|
visitMalloyDocument(pcx: parse.MalloyDocumentContext): ast.Document;
|
|
91
91
|
visitDefineSourceStatement(pcx: parse.DefineSourceStatementContext): ast.DefineSourceList;
|
|
92
|
+
visitDefineGivenStatement(pcx: parse.DefineGivenStatementContext): ast.DefineGivens;
|
|
93
|
+
visitGivenDef(pcx: parse.GivenDefContext): ast.GivenDeclaration;
|
|
94
|
+
/**
|
|
95
|
+
* Parse the TYPE inside `filter<TYPE>`. Returns the filter type on
|
|
96
|
+
* success; logs `illegal-filter-type` and returns undefined when TYPE
|
|
97
|
+
* is not a filterable type. `getBasicMalloyType` already logs for
|
|
98
|
+
* invalid basic types, so on its `'error'` path we stay silent and
|
|
99
|
+
* return undefined.
|
|
100
|
+
*/
|
|
101
|
+
protected getFilterType(basicCx: parse.MalloyBasicTypeContext): FilterExprType | undefined;
|
|
102
|
+
getGivenType(pcx: parse.GivenTypeContext): GivenTypeDef;
|
|
92
103
|
visitDefineUserTypeStatement(pcx: parse.DefineUserTypeStatementContext): ast.DefineUserTypeList;
|
|
93
104
|
visitUserTypeDefinition(pcx: parse.UserTypeDefinitionContext): ast.DefineUserType;
|
|
94
105
|
getUserTypeShapeExpr(cx: parse.UserTypeExprContext): ast.UserTypeShape;
|
|
@@ -185,6 +196,7 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
|
|
|
185
196
|
visitExprNow(_pcx: parse.ExprNowContext): ast.ExprNow;
|
|
186
197
|
visitExprNumber(pcx: parse.ExprNumberContext): ast.ExprNumber;
|
|
187
198
|
visitExprFieldPath(pcx: parse.ExprFieldPathContext): ast.ExprIdReference;
|
|
199
|
+
visitExprGivenRef(pcx: parse.ExprGivenRefContext): ast.GivenReference;
|
|
188
200
|
visitExprNULL(_pcx: parse.ExprNULLContext): ast.ExprNULL;
|
|
189
201
|
visitExprExpr(pcx: parse.ExprExprContext): ast.ExprParens;
|
|
190
202
|
visitExprMinus(pcx: parse.ExprMinusContext): ast.ExprMinus;
|
|
@@ -86,6 +86,7 @@ function isIndirectUserType(t) {
|
|
|
86
86
|
return 'namedUserType' in t;
|
|
87
87
|
}
|
|
88
88
|
const DEFAULT_COMPILER_FLAGS = [];
|
|
89
|
+
const LEGAL_FILTER_TYPES = 'string, number, boolean, date, timestamp, timestamptz';
|
|
89
90
|
/**
|
|
90
91
|
* ANTLR visitor pattern parse tree traversal. Generates a Malloy
|
|
91
92
|
* AST from an ANTLR parse tree.
|
|
@@ -286,6 +287,79 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
286
287
|
defList.extendNote({ blockNotes });
|
|
287
288
|
return defList;
|
|
288
289
|
}
|
|
290
|
+
visitDefineGivenStatement(pcx) {
|
|
291
|
+
this.inExperiment('givens', pcx);
|
|
292
|
+
const defsCx = pcx.givenDefList().givenDef();
|
|
293
|
+
const givens = defsCx.map(dcx => this.visitGivenDef(dcx));
|
|
294
|
+
const blockNotes = this.getNotes(pcx.tags());
|
|
295
|
+
const block = new ast.DefineGivens(givens);
|
|
296
|
+
for (const g of givens) {
|
|
297
|
+
g.extendNote({ blockNotes });
|
|
298
|
+
}
|
|
299
|
+
return this.astAt(block, pcx);
|
|
300
|
+
}
|
|
301
|
+
visitGivenDef(pcx) {
|
|
302
|
+
const name = (0, parse_utils_1.getId)(pcx.givenNameDef());
|
|
303
|
+
const typeDef = this.getGivenType(pcx.givenType());
|
|
304
|
+
const defaultCx = pcx.fieldExpr();
|
|
305
|
+
let defVal;
|
|
306
|
+
if (defaultCx) {
|
|
307
|
+
defVal = this.astAt(new ast.ConstantExpression(this.getFieldExpr(defaultCx)), defaultCx);
|
|
308
|
+
}
|
|
309
|
+
const isCx = pcx.isDefine();
|
|
310
|
+
if (isCx) {
|
|
311
|
+
// We accept the `tags IS tags` shape syntactically so we can give a
|
|
312
|
+
// targeted error here instead of a confusing parse-level one. Tags
|
|
313
|
+
// belong above the declaration; nothing should sit between `is` and
|
|
314
|
+
// the default expression.
|
|
315
|
+
const afterIs = isCx._afterIs;
|
|
316
|
+
if (afterIs && afterIs.annotation().length > 0) {
|
|
317
|
+
this.contextError(afterIs, 'given-no-tags-after-is', 'Annotations are not allowed between `is` and the default value of a given; place them above the declaration');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const decl = new ast.GivenDeclaration(name, typeDef, defVal);
|
|
321
|
+
decl.extendNote({ notes: this.getNotes(pcx.tags()) });
|
|
322
|
+
return this.astAt(decl, pcx);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Parse the TYPE inside `filter<TYPE>`. Returns the filter type on
|
|
326
|
+
* success; logs `illegal-filter-type` and returns undefined when TYPE
|
|
327
|
+
* is not a filterable type. `getBasicMalloyType` already logs for
|
|
328
|
+
* invalid basic types, so on its `'error'` path we stay silent and
|
|
329
|
+
* return undefined.
|
|
330
|
+
*/
|
|
331
|
+
getFilterType(basicCx) {
|
|
332
|
+
const inner = this.getBasicMalloyType(basicCx);
|
|
333
|
+
if (inner.type === 'error')
|
|
334
|
+
return undefined;
|
|
335
|
+
if ((0, malloy_filter_1.isFilterable)(inner.type)) {
|
|
336
|
+
return inner.type;
|
|
337
|
+
}
|
|
338
|
+
this.contextError(basicCx, 'illegal-filter-type', `\`filter<${basicCx.text}>\` is not allowed; filtering is only supported for ${LEGAL_FILTER_TYPES}`);
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
getGivenType(pcx) {
|
|
342
|
+
if (pcx.FILTER()) {
|
|
343
|
+
const basicCx = pcx.malloyBasicType();
|
|
344
|
+
if (basicCx) {
|
|
345
|
+
const filterType = this.getFilterType(basicCx);
|
|
346
|
+
if (filterType)
|
|
347
|
+
return { type: 'filter expression', filterType };
|
|
348
|
+
}
|
|
349
|
+
return { type: 'error' };
|
|
350
|
+
}
|
|
351
|
+
const mtcx = pcx.malloyType();
|
|
352
|
+
if (mtcx) {
|
|
353
|
+
return this.getMalloyType(mtcx);
|
|
354
|
+
}
|
|
355
|
+
// Unreachable from valid grammar input: `givenType` is exactly
|
|
356
|
+
// `malloyType | FILTER LT malloyBasicType GT`, so one of the branches
|
|
357
|
+
// above must have matched. Surfacing a real error here (rather than
|
|
358
|
+
// throwing) keeps the translator running and gives any AI or human
|
|
359
|
+
// reading the log a hint that the parser and AST builder have drifted.
|
|
360
|
+
this.contextError(pcx, 'unexpected-malloy-type', `\`${pcx.text}\` was not recognized as a legal type. This is likely a compiler bug — the grammar admits cases the translator doesn't handle.`);
|
|
361
|
+
return { type: 'error' };
|
|
362
|
+
}
|
|
289
363
|
visitDefineUserTypeStatement(pcx) {
|
|
290
364
|
this.inExperiment('virtual_source', pcx);
|
|
291
365
|
const defsCx = pcx.userTypePropertyList().userTypeDefinition();
|
|
@@ -385,21 +459,20 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
385
459
|
let pType;
|
|
386
460
|
const typeCx = pcx.legalParamType();
|
|
387
461
|
if (typeCx) {
|
|
388
|
-
const typeDef = this.getBasicMalloyType(typeCx.malloyBasicType());
|
|
389
|
-
const t = typeDef.type;
|
|
390
462
|
if (typeCx.FILTER()) {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
else {
|
|
395
|
-
this.contextError(typeCx, 'parameter-illegal-default-type', `Unknown filter type ${t}`);
|
|
463
|
+
const filterType = this.getFilterType(typeCx.malloyBasicType());
|
|
464
|
+
if (filterType) {
|
|
465
|
+
pType = { type: 'filter expression', filterType };
|
|
396
466
|
}
|
|
397
467
|
}
|
|
398
|
-
else if (!(0, malloy_types_1.isParameterType)(t)) {
|
|
399
|
-
this.contextError(typeCx, 'parameter-illegal-default-type', `Unknown parameter type ${t}`);
|
|
400
|
-
}
|
|
401
468
|
else {
|
|
402
|
-
|
|
469
|
+
const t = this.getBasicMalloyType(typeCx.malloyBasicType()).type;
|
|
470
|
+
if (!(0, malloy_types_1.isParameterType)(t)) {
|
|
471
|
+
this.contextError(typeCx, 'parameter-illegal-default-type', `Unknown parameter type ${t}`);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
pType = { type: t };
|
|
475
|
+
}
|
|
403
476
|
}
|
|
404
477
|
}
|
|
405
478
|
const defaultCx = pcx.fieldExpr();
|
|
@@ -1048,6 +1121,12 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1048
1121
|
const idRef = new ast.ExprIdReference(this.getFieldPath(pcx.fieldPath(), ast.ExpressionFieldReference));
|
|
1049
1122
|
return this.astAt(idRef, pcx);
|
|
1050
1123
|
}
|
|
1124
|
+
visitExprGivenRef(pcx) {
|
|
1125
|
+
this.inExperiment('givens', pcx);
|
|
1126
|
+
// GIVEN_REF token text is `$NAME`; strip the leading `$`.
|
|
1127
|
+
const name = pcx.GIVEN_REF().text.slice(1);
|
|
1128
|
+
return this.astAt(new ast.GivenReference(name), pcx);
|
|
1129
|
+
}
|
|
1051
1130
|
visitExprNULL(_pcx) {
|
|
1052
1131
|
return new ast.ExprNULL();
|
|
1053
1132
|
}
|
package/dist/lang/parse-log.d.ts
CHANGED
|
@@ -265,6 +265,7 @@ type MessageParameterTypes = {
|
|
|
265
265
|
'query-definition-from-non-query': string;
|
|
266
266
|
'source-definition-name-conflict': string;
|
|
267
267
|
'user-type-definition-name-conflict': string;
|
|
268
|
+
'given-definition-name-conflict': string;
|
|
268
269
|
'virtual-source-not-yet-implemented': string;
|
|
269
270
|
'virtual-source-missing-user-type-refs': string;
|
|
270
271
|
'virtual-source-unknown-dialect': string;
|
|
@@ -279,6 +280,8 @@ type MessageParameterTypes = {
|
|
|
279
280
|
'selective-import-not-found': string;
|
|
280
281
|
'name-conflict-on-indiscriminate-import': string;
|
|
281
282
|
'failed-import': string;
|
|
283
|
+
'unsatisfied-given-in-query': string;
|
|
284
|
+
'given-alias-collision': string;
|
|
282
285
|
'failed-to-compute-output-schema': string;
|
|
283
286
|
'invalid-timeframe-for-time-offset': string;
|
|
284
287
|
'time-comparison-type-mismatch': string;
|
|
@@ -286,6 +289,11 @@ type MessageParameterTypes = {
|
|
|
286
289
|
'time-offset-type-mismatch': string;
|
|
287
290
|
'unexpected-binary-operator': string;
|
|
288
291
|
'illegal-reference-in-parameter-default': string;
|
|
292
|
+
'given-reference-not-implemented': string;
|
|
293
|
+
'given-not-found': string;
|
|
294
|
+
'given-no-tags-after-is': string;
|
|
295
|
+
'illegal-filter-type': string;
|
|
296
|
+
'invalid-source-from-given': string;
|
|
289
297
|
'aggregate-analytic-in-select': string;
|
|
290
298
|
'refinement-of-raw-query': string;
|
|
291
299
|
'illegal-multistage-refinement-operation': string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright Contributors to the Malloy project
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* RULE: FILTER TYPE — `filter<T>`
|
|
7
|
+
*
|
|
8
|
+
* `givenType` and `legalParamType` both have a `FILTER LT malloyBasicType GT`
|
|
9
|
+
* alternative. The default leaf walker treats LT/GT as binary operators
|
|
10
|
+
* (spaces both sides), which renders this as `filter < string >`. This rule
|
|
11
|
+
* intercepts the two contexts and emits the four-token sequence as a glued
|
|
12
|
+
* unit.
|
|
13
|
+
*
|
|
14
|
+
* Falls through to default child recursion when the context is the non-FILTER
|
|
15
|
+
* alternative (a plain malloy type), so the type's own formatting still runs.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.formatFilterTypeOrFallback = formatFilterTypeOrFallback;
|
|
19
|
+
const tokens_1 = require("./tokens");
|
|
20
|
+
const leaf_1 = require("./leaf");
|
|
21
|
+
function formatFilterTypeOrFallback(f, ctx) {
|
|
22
|
+
const filterTok = ctx.FILTER();
|
|
23
|
+
if (!filterTok) {
|
|
24
|
+
for (let i = 0; i < ctx.childCount; i++)
|
|
25
|
+
f.format(ctx.getChild(i));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const action = (0, tokens_1.leadingAction)(f.lastEmittedType, tokens_1.L.FILTER);
|
|
29
|
+
if (action === 'glue')
|
|
30
|
+
f.o.trimTrailingSpace();
|
|
31
|
+
else if (action === 'space')
|
|
32
|
+
f.o.space();
|
|
33
|
+
const typeCtx = ctx.malloyBasicType();
|
|
34
|
+
f.o.text(`filter<${typeCtx.text}>`);
|
|
35
|
+
const gtTok = ctx.GT().symbol;
|
|
36
|
+
(0, leaf_1.note)(f, tokens_1.L.GT, gtTok.tokenIndex, gtTok);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=filter-type.js.map
|
|
@@ -61,6 +61,7 @@ const field_properties_1 = require("./field-properties");
|
|
|
61
61
|
const pick_case_1 = require("./pick-case");
|
|
62
62
|
const binary_chain_1 = require("./binary-chain");
|
|
63
63
|
const import_select_1 = require("./import-select");
|
|
64
|
+
const filter_type_1 = require("./filter-type");
|
|
64
65
|
class Formatter {
|
|
65
66
|
constructor(src, tokens) {
|
|
66
67
|
this.src = src;
|
|
@@ -128,6 +129,11 @@ class Formatter {
|
|
|
128
129
|
if (node instanceof parser.ImportSelectContext) {
|
|
129
130
|
return (0, import_select_1.formatImportSelect)(this, node);
|
|
130
131
|
}
|
|
132
|
+
// RULE: FILTER TYPE — `filter<T>` rendered glued, not as `filter < T >`.
|
|
133
|
+
if (node instanceof parser.GivenTypeContext ||
|
|
134
|
+
node instanceof parser.LegalParamTypeContext) {
|
|
135
|
+
return (0, filter_type_1.formatFilterTypeOrFallback)(this, node);
|
|
136
|
+
}
|
|
131
137
|
// RULE: PICK / CASE / BINARY CHAIN.
|
|
132
138
|
if (node instanceof parser.PickStatementContext)
|
|
133
139
|
return (0, pick_case_1.formatPickStatement)(this, node);
|
|
@@ -30,6 +30,10 @@ function renderItemInline(f, ctx) {
|
|
|
30
30
|
var _a;
|
|
31
31
|
let buf = '';
|
|
32
32
|
let lastType = null;
|
|
33
|
+
// True between the LT and matching GT of a `filter<T>` window (LT
|
|
34
|
+
// immediately follows FILTER). All four tokens render glued; mirrors
|
|
35
|
+
// formatFilterTypeOrFallback in the leaf walker.
|
|
36
|
+
let inFilterType = false;
|
|
33
37
|
// Coalescing space: skip if buffer is empty or last char already provides
|
|
34
38
|
// separation. Mirrors Out.space() (./out) minus the newline check, since
|
|
35
39
|
// this renderer never emits a newline.
|
|
@@ -83,6 +87,22 @@ function renderItemInline(f, ctx) {
|
|
|
83
87
|
lastType = t.type;
|
|
84
88
|
continue;
|
|
85
89
|
}
|
|
90
|
+
// filter<T>: glue all four tokens.
|
|
91
|
+
if (t.type === tokens_1.L.LT && lastType === tokens_1.L.FILTER) {
|
|
92
|
+
trim();
|
|
93
|
+
buf += '<';
|
|
94
|
+
inFilterType = true;
|
|
95
|
+
lastType = t.type;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (inFilterType) {
|
|
99
|
+
trim();
|
|
100
|
+
buf += text;
|
|
101
|
+
if (t.type === tokens_1.L.GT)
|
|
102
|
+
inFilterType = false;
|
|
103
|
+
lastType = t.type;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
86
106
|
// Everything else: classifier-driven leading separator + text + (if a
|
|
87
107
|
// binary op) trailing space. Same shape as the leaf walker's default.
|
|
88
108
|
const action = (0, tokens_1.leadingAction)(lastType, t.type);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
export type ItemKind = 'fieldEntry' | 'nestEntry' | 'fieldDef' | 'fieldName' | 'collectionMember' | 'orderBySpec' | 'fieldExpr' | 'joinDef' | 'includeField' | 'indexElement';
|
|
2
|
+
export type ItemKind = 'fieldEntry' | 'nestEntry' | 'fieldDef' | 'fieldName' | 'collectionMember' | 'orderBySpec' | 'fieldExpr' | 'joinDef' | 'includeField' | 'indexElement' | 'givenDef';
|
|
3
3
|
export interface SectionRule {
|
|
4
4
|
ctxClass: new (...args: never[]) => ParserRuleContext;
|
|
5
5
|
keywordTypes: number[];
|
|
@@ -87,6 +87,7 @@ exports.SECTION_STATEMENT_RULES = [
|
|
|
87
87
|
// findKeyword in ./sections handles that nested case.
|
|
88
88
|
rule(parser.IncludeItemContext, [tokens_1.L.PUBLIC, tokens_1.L.PRIVATE, tokens_1.L.INTERNAL], c => c.includeList(), 'includeField'),
|
|
89
89
|
rule(parser.IndexStatementContext, [tokens_1.L.INDEX], c => c.indexFields(), 'indexElement'),
|
|
90
|
+
rule(parser.DefineGivenStatementContext, [tokens_1.L.GIVEN], c => c.givenDefList(), 'givenDef'),
|
|
90
91
|
];
|
|
91
92
|
// Coarse statement-kind labels for the same-kind-no-blank rule in block
|
|
92
93
|
// bodies. Different kinds preserve a single user-supplied blank line.
|
|
@@ -156,6 +156,8 @@ function listItems(listCtx, itemKind) {
|
|
|
156
156
|
return c instanceof parser.IncludeFieldContext;
|
|
157
157
|
case 'indexElement':
|
|
158
158
|
return c instanceof parser.IndexElementContext;
|
|
159
|
+
case 'givenDef':
|
|
160
|
+
return c instanceof parser.GivenDefContext;
|
|
159
161
|
}
|
|
160
162
|
};
|
|
161
163
|
const out = [];
|
|
@@ -67,6 +67,8 @@ exports.TOP_LEVEL_STARTERS = new Set([
|
|
|
67
67
|
exports.L.QUERY,
|
|
68
68
|
exports.L.RUN,
|
|
69
69
|
exports.L.IMPORT,
|
|
70
|
+
exports.L.GIVEN,
|
|
71
|
+
exports.L.TYPE,
|
|
70
72
|
]);
|
|
71
73
|
// Token types after which an immediately following `(` or `[` is a call /
|
|
72
74
|
// subscript and should hug (no leading space). Anything else (binary ops,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable no-console */
|
|
3
2
|
/*
|
|
4
3
|
* Copyright 2023 Google LLC
|
|
5
4
|
*
|
|
@@ -241,18 +240,36 @@ expect.extend({
|
|
|
241
240
|
if (!badRefs.pass) {
|
|
242
241
|
return badRefs;
|
|
243
242
|
}
|
|
244
|
-
const actual = bx.generated().
|
|
243
|
+
const actual = (0, model_1.fieldUsageFrom)(bx.generated().refSummary);
|
|
245
244
|
const actualPaths = actual.filter(u => (0, model_1.bareFieldUsage)(u)).map(u => u.path);
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
245
|
+
return comparePathSets(this, actualPaths, paths);
|
|
246
|
+
},
|
|
247
|
+
hasExpandedFieldUsage: function (segment, paths) {
|
|
248
|
+
var _a;
|
|
249
|
+
if (!(0, model_1.isQuerySegment)(segment) && !(0, model_1.isIndexSegment)(segment)) {
|
|
250
|
+
return {
|
|
251
|
+
pass: false,
|
|
252
|
+
message: () => 'hasExpandedFieldUsage: receiver is not a query or index segment',
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
const actualPaths = ((_a = segment.expandedFieldUsage) !== null && _a !== void 0 ? _a : [])
|
|
256
|
+
.filter(u => (0, model_1.bareFieldUsage)(u))
|
|
257
|
+
.map(u => u.path);
|
|
258
|
+
return comparePathSets(this, actualPaths, paths);
|
|
254
259
|
},
|
|
255
260
|
});
|
|
261
|
+
// Field-usage entries have no order or duplication guarantee. Compare as
|
|
262
|
+
// sets of `path.join('.')` strings so equality is purely set membership.
|
|
263
|
+
function comparePathSets(ctx, actualPaths, expectedPaths) {
|
|
264
|
+
const toKey = (p) => p.join('.');
|
|
265
|
+
const actualSet = new Set(actualPaths.map(toKey));
|
|
266
|
+
const expectedSet = new Set(expectedPaths.map(toKey));
|
|
267
|
+
const pass = ctx.equals(actualSet, expectedSet);
|
|
268
|
+
const msg = pass
|
|
269
|
+
? `Matched: ${[...actualSet].sort().join(', ')}`
|
|
270
|
+
: ctx.utils.diff([...expectedSet].sort(), [...actualSet].sort());
|
|
271
|
+
return { pass, message: () => `${msg}` };
|
|
272
|
+
}
|
|
256
273
|
function problemSpecSummary(s) {
|
|
257
274
|
return `${s.severity} '${'message' in s ? s.message : s.code}' ${s.data !== undefined ? (0, test_translator_1.pretty)(s.data) : ''}`;
|
|
258
275
|
}
|
|
@@ -87,6 +87,7 @@ class ConstantQueryStruct extends query_node_1.QueryStruct {
|
|
|
87
87
|
// Create minimal model with empty structs map
|
|
88
88
|
const minimalModel = {
|
|
89
89
|
structs: new Map(),
|
|
90
|
+
givens: {},
|
|
90
91
|
};
|
|
91
92
|
// Create minimal prepare result options with eventStream
|
|
92
93
|
const minimalPrepareOptions = { eventStream };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Expr, FunctionCallNode, FunctionOverloadDef, FunctionOrderBy, FieldnameNode, OutputFieldNode, GenericSQLExpr, FilteredExpr, UngroupNode, ParameterNode, AggregateExpr, SourceReferenceNode, CaseExpr } from './malloy_types';
|
|
1
|
+
import type { Expr, FunctionCallNode, FunctionOverloadDef, FunctionOrderBy, GivenRefNode, FieldnameNode, OutputFieldNode, GenericSQLExpr, FilteredExpr, UngroupNode, ParameterNode, AggregateExpr, SourceReferenceNode, CaseExpr } from './malloy_types';
|
|
2
2
|
import { type FieldInstanceResult } from './field_instance';
|
|
3
3
|
import { GenerateState } from './utils';
|
|
4
4
|
import type { QueryStruct } from './query_node';
|
|
@@ -11,6 +11,7 @@ export declare function generateFunctionCallExpression(resultSet: FieldInstanceR
|
|
|
11
11
|
export declare function generateFieldFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FieldnameNode, state: GenerateState): string;
|
|
12
12
|
export declare function generateOutputFieldFragment(resultSet: FieldInstanceResult, _context: QueryStruct, frag: OutputFieldNode, _state: GenerateState): string;
|
|
13
13
|
export declare function generateParameterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: ParameterNode, state: GenerateState): string;
|
|
14
|
+
export declare function generateGivenFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: GivenRefNode, state: GenerateState): string;
|
|
14
15
|
export declare function generateFilterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FilteredExpr, state: GenerateState): string;
|
|
15
16
|
export declare function generateDimFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: Expr, state: GenerateState): string;
|
|
16
17
|
export declare function generateUngroupedFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: UngroupNode, state: GenerateState): string;
|