@malloydata/malloy 0.0.56-dev230710182711 → 0.0.56-dev230710205111

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.
@@ -52,7 +52,6 @@ const ast = __importStar(require("./ast"));
52
52
  const Interval_1 = require("antlr4ts/misc/Interval");
53
53
  const ast_1 = require("./ast");
54
54
  const parse_utils_1 = require("./parse-utils");
55
- const ENABLE_M4_WARNINGS = false;
56
55
  class IgnoredElement extends ast.MalloyElement {
57
56
  constructor(src) {
58
57
  super();
@@ -69,6 +68,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
69
68
  super();
70
69
  this.parse = parse;
71
70
  this.msgLog = msgLog;
71
+ this.compilerFlags = {};
72
72
  }
73
73
  /**
74
74
  * Mostly used to flag a case where the grammar and the type system are
@@ -115,14 +115,17 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
115
115
  }
116
116
  return acceptable;
117
117
  }
118
+ m4WarningsEnabled() {
119
+ return !!this.compilerFlags['m4warnings'];
120
+ }
118
121
  getNumber(term) {
119
122
  return Number.parseInt(term.text);
120
123
  }
121
124
  getFieldName(cx) {
122
- return this.astAt(new ast.FieldName((0, parse_utils_1.getId)(cx)), cx);
125
+ return this.astAt(new ast.FieldName((0, parse_utils_1.getId)(cx)), cx.id());
123
126
  }
124
127
  getModelEntryName(cx) {
125
- return this.astAt(new ast.ModelEntryReference((0, parse_utils_1.getId)(cx)), cx);
128
+ return this.astAt(new ast.ModelEntryReference((0, parse_utils_1.getId)(cx)), cx.id());
126
129
  }
127
130
  defaultResult() {
128
131
  return new ast.Unimplemented();
@@ -162,13 +165,6 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
162
165
  const el = this.getFilterElement(cx.fieldExpr());
163
166
  return new ast.Filter([el]);
164
167
  }
165
- getExploreSource(pcx) {
166
- const element = this.visit(pcx);
167
- if (element instanceof ast.Source) {
168
- return element;
169
- }
170
- throw this.internalError(pcx, `'${element.elementType}': illegal source`);
171
- }
172
168
  getPlainString(cx) {
173
169
  const shortStr = (0, parse_utils_1.getStringIfShort)(cx);
174
170
  if (shortStr) {
@@ -191,6 +187,13 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
191
187
  // string: shortString | sqlString; So this will never happen
192
188
  return '';
193
189
  }
190
+ getSource(pcx) {
191
+ const source = this.visit(pcx);
192
+ if (source instanceof ast.Source) {
193
+ return source;
194
+ }
195
+ throw this.internalError(pcx, `Source expected, but ${source.elementType} found`);
196
+ }
194
197
  makeSqlString(pcx, sqlStr) {
195
198
  for (const part of (0, parse_utils_1.getStringParts)(pcx)) {
196
199
  if (part instanceof antlr4ts_1.ParserRuleContext) {
@@ -232,18 +235,89 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
232
235
  return defList;
233
236
  }
234
237
  visitSourceDefinition(pcx) {
235
- const exploreDef = new ast.DefineSource((0, parse_utils_1.getId)(pcx.sourceNameDef()), this.visitExplore(pcx.explore()), true, []);
238
+ const exploreDef = new ast.DefineSource((0, parse_utils_1.getId)(pcx.sourceNameDef()), this.getSource(pcx.explore()), true, []);
236
239
  const notes = (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
237
240
  exploreDef.extendNote({ notes });
238
241
  return this.astAt(exploreDef, pcx);
239
242
  }
240
- visitExplore(pcx) {
241
- const source = this.getExploreSource(pcx.exploreSource());
242
- const refineCx = pcx.exploreProperties();
243
- if (refineCx) {
244
- return this.astAt(new ast.RefinedSource(source, this.visitExploreProperties(refineCx)), pcx);
243
+ visitQueryFromSQLSource(pcx) {
244
+ const query = new ast.FullQuery(this.visitSqlSource(pcx.sqlSource()));
245
+ return this.astAt(query, pcx);
246
+ }
247
+ visitQueryFromSource(pcx) {
248
+ const root = this.visitUnextendableSource(pcx.unextendableSource());
249
+ const query = new ast.FullQuery(root);
250
+ query.addSegments(...this.getSegments(pcx.pipeElement()));
251
+ return this.astAt(query, pcx);
252
+ }
253
+ getQueryRefinements(pcx) {
254
+ const properties = this.astAt(this.visitQueryProperties(pcx.queryProperties()), pcx);
255
+ if (this.m4WarningsEnabled() && pcx.REFINE() === undefined) {
256
+ this.astError(properties, 'Implicit query refinement is deprecated, use the `refine` operator.', 'warn');
257
+ }
258
+ return properties;
259
+ }
260
+ visitRefinedQuery(pcx) {
261
+ const base = this.visit(pcx.refinableQuery());
262
+ if (ast.isQueryElement(base)) {
263
+ const rcx = pcx.queryRefinement();
264
+ if (rcx) {
265
+ const properties = this.getQueryRefinements(rcx);
266
+ base.refineHead(properties);
267
+ }
268
+ return base;
269
+ }
270
+ throw this.internalError(pcx, `Query expected, but ${base.elementType} found`);
271
+ }
272
+ visitQueryByTurtleName(pcx) {
273
+ const source = this.visitUnextendableSource(pcx.unextendableSource());
274
+ const query = new ast.FullQuery(source);
275
+ query.turtleName = this.getFieldName(pcx);
276
+ return this.astAt(query, pcx);
277
+ }
278
+ visitQueryByName(pcx) {
279
+ const query = new ast.ExistingQuery();
280
+ query.head = this.getModelEntryName(pcx);
281
+ return this.astAt(query, pcx);
282
+ }
283
+ getSourceExtensions(pcx) {
284
+ const extensions = pcx === null || pcx === void 0 ? void 0 : pcx.exploreProperties();
285
+ const sourceDesc = this.astAt(this.visitExploreProperties(extensions), pcx);
286
+ if (this.m4WarningsEnabled() && pcx.EXTEND() === undefined) {
287
+ this.astError(sourceDesc, 'Implicit source extension is deprecated, use the `extend` operator.', 'warn');
288
+ }
289
+ return sourceDesc;
290
+ }
291
+ visitUnextendableSource(pcx) {
292
+ const unextendedSource = this.visit(pcx.extendableSource());
293
+ if (unextendedSource instanceof ast.Source) {
294
+ const ecx = pcx.sourceExtension();
295
+ if (ecx) {
296
+ const sourceDesc = this.getSourceExtensions(ecx);
297
+ return new ast.RefinedSource(unextendedSource, sourceDesc);
298
+ }
299
+ else {
300
+ return unextendedSource;
301
+ }
302
+ }
303
+ throw this.internalError(pcx, `Source expected, but ${unextendedSource.elementType} found`);
304
+ }
305
+ visitNormalQuery(pcx) {
306
+ const query = this.visit(pcx.unrefinableQuery());
307
+ if (ast.isQueryElement(query)) {
308
+ query.addSegments(...this.getSegments(pcx.pipeElement()));
309
+ return this.astAt(query, pcx);
310
+ }
311
+ throw this.internalError(pcx, `Expected query, but ${query.elementType} found`);
312
+ }
313
+ visitExtendedQuery(pcx) {
314
+ const query = this.visit(pcx.query());
315
+ if (!ast.isQueryElement(query)) {
316
+ throw this.internalError(pcx, `Query expected, but ${query.elementType} found`);
245
317
  }
246
- return source;
318
+ const source = new ast.QuerySource(query);
319
+ const sourceDesc = this.getSourceExtensions(pcx.sourceExtension());
320
+ return this.astAt(new ast.RefinedSource(source, sourceDesc), pcx);
247
321
  }
248
322
  visitExploreProperties(pcx) {
249
323
  const filterCx = pcx.filterShortcut();
@@ -257,7 +331,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
257
331
  visitTableFunction(pcx) {
258
332
  const tableURI = this.getPlainString(pcx.tableURI());
259
333
  const el = this.astAt(new ast.TableFunctionSource(tableURI), pcx);
260
- if (ENABLE_M4_WARNINGS) {
334
+ if (this.m4WarningsEnabled()) {
261
335
  this.astError(el, "`table('connection_name:table_path')` is deprecated; use `connection_name.table('table_path')`", 'warn');
262
336
  }
263
337
  return el;
@@ -279,7 +353,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
279
353
  const name = this.getModelEntryName(pcx.sqlExploreNameRef());
280
354
  return this.astAt(new ast.FromSQLSource(name), pcx);
281
355
  }
282
- visitSQLSource(pcx) {
356
+ visitSqlSource(pcx) {
283
357
  const connId = pcx.connectionId();
284
358
  const connectionName = this.astAt(this.getModelEntryName(connId), connId);
285
359
  const sqlStr = new ast.SQLString();
@@ -360,7 +434,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
360
434
  }
361
435
  getJoinSource(name, ecx) {
362
436
  if (ecx) {
363
- const joinSrc = this.visitExplore(ecx.explore());
437
+ const joinSrc = this.getSource(ecx.explore());
364
438
  const notes = (0, parse_utils_1.getNotes)(ecx._before_is).concat((0, parse_utils_1.getNotes)(ecx._after_is));
365
439
  return { joinFrom: joinSrc, notes };
366
440
  }
@@ -368,7 +442,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
368
442
  }
369
443
  visitQueryJoinStatement(pcx) {
370
444
  const result = this.astAt(this.visit(pcx.joinStatement()), pcx);
371
- if (ENABLE_M4_WARNINGS) {
445
+ if (this.m4WarningsEnabled()) {
372
446
  this.astError(result, 'Joins in queries are deprecated, move into an `extend:` block.', 'warn');
373
447
  }
374
448
  return result;
@@ -434,7 +508,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
434
508
  const defs = this.getFieldDefs(pcx.defList().fieldDef(), ast.DeclareFieldDeclaration);
435
509
  const stmt = new ast.DeclareFields(defs);
436
510
  const result = this.astAt(stmt, pcx);
437
- if (ENABLE_M4_WARNINGS) {
511
+ if (this.m4WarningsEnabled()) {
438
512
  this.astError(result, '`declare:` is deprecated; use `dimension:` or `measure:` inside a source or `extend:` block', 'warn');
439
513
  }
440
514
  return result;
@@ -669,32 +743,16 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
669
743
  const propsCx = firstCx.queryProperties();
670
744
  if (propsCx) {
671
745
  const queryDesc = this.visitQueryProperties(propsCx);
672
- if (nameCx) {
673
- pipe.refineHead(queryDesc);
674
- }
675
- else {
676
- pipe.addSegments(queryDesc);
677
- }
746
+ pipe.addSegments(queryDesc);
747
+ }
748
+ const rcx = firstCx.queryRefinement();
749
+ if (rcx) {
750
+ const queryDesc = this.getQueryRefinements(rcx);
751
+ pipe.refineHead(queryDesc);
678
752
  }
679
753
  const tail = this.getSegments(pipeCx.pipeElement());
680
754
  pipe.addSegments(...tail);
681
755
  }
682
- visitExploreArrowQuery(pcx) {
683
- const root = this.visitExplore(pcx.explore());
684
- const query = new ast.FullQuery(root);
685
- this.buildPipelineFromName(query, pcx.pipelineFromName());
686
- return this.astAt(query, pcx);
687
- }
688
- visitArrowQuery(pcx) {
689
- const query = new ast.ExistingQuery();
690
- query.head = this.getModelEntryName(pcx.queryName());
691
- const refCx = pcx.queryProperties();
692
- if (refCx) {
693
- query.refineHead(this.visitQueryProperties(refCx));
694
- }
695
- query.addSegments(...this.getSegments(pcx.pipeElement()));
696
- return this.astAt(query, pcx);
697
- }
698
756
  visitTopLevelQueryDefs(pcx) {
699
757
  const stmts = pcx
700
758
  .topLevelQueryDef()
@@ -719,32 +777,27 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
719
777
  const defCx = pcx.topLevelAnonQueryDef();
720
778
  const query = this.visit(defCx.query());
721
779
  if (ast.isQueryElement(query)) {
722
- const theQuery = new ast.AnonymousQuery(query);
780
+ const theQuery = this.astAt(new ast.AnonymousQuery(query), defCx);
723
781
  const notes = (0, parse_utils_1.getNotes)(pcx.topLevelAnonQueryDef().tags());
724
782
  const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
725
783
  theQuery.extendNote({ notes, blockNotes });
726
- if (ENABLE_M4_WARNINGS) {
784
+ if (this.m4WarningsEnabled()) {
727
785
  this.astError(theQuery, 'Anonymous `query:` statements are deprecated, use `run:` instead', 'warn');
728
786
  }
729
787
  return this.astAt(theQuery, pcx);
730
788
  }
731
789
  throw this.internalError(pcx, `Anonymous query matched, but ${query.elementType} found`);
732
790
  }
733
- visitRunStatementDef(pcx) {
791
+ visitRunStatement(pcx) {
734
792
  const query = this.visit(pcx.topLevelAnonQueryDef().query());
735
793
  if (ast.isQueryElement(query)) {
736
- const el = new ast.RunQueryDef(query);
794
+ const el = new ast.RunQuery(query);
737
795
  el.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx._blockTags) });
738
796
  el.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx._noteTags) });
739
797
  return this.astAt(el, pcx);
740
798
  }
741
799
  throw this.internalError(pcx, `Run query matched, but ${query.elementType} found`);
742
800
  }
743
- visitRunStatementRef(pcx) {
744
- const name = this.getModelEntryName(pcx.queryName());
745
- const el = this.astAt(new ast.RunQueryRef(name), pcx.queryName());
746
- return this.astAt(el, pcx);
747
- }
748
801
  visitNestStatement(pcx) {
749
802
  const nests = this.visitNestedQueryList(pcx.nestedQueryList());
750
803
  nests.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
@@ -755,11 +808,11 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
755
808
  }
756
809
  visitNestExisting(pcx) {
757
810
  const name = this.getFieldName(pcx.queryName());
758
- const propsCx = pcx.queryProperties();
811
+ const rcx = pcx.queryRefinement();
759
812
  const notes = (0, parse_utils_1.getNotes)(pcx.tags());
760
- if (propsCx) {
813
+ if (rcx) {
761
814
  const nestRefine = new ast.NestRefinement(name);
762
- const queryDesc = this.visitQueryProperties(propsCx);
815
+ const queryDesc = this.getQueryRefinements(rcx);
763
816
  nestRefine.refineHead(queryDesc);
764
817
  nestRefine.extendNote({ notes });
765
818
  return this.astAt(nestRefine, pcx);
@@ -1023,7 +1076,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1023
1076
  }
1024
1077
  return new ast.Pick(picks);
1025
1078
  }
1026
- visitNamedSource(pcx) {
1079
+ visitSourceFromNamedModelEntry(pcx) {
1027
1080
  const name = this.getModelEntryName(pcx.sourceID());
1028
1081
  // Parameters ... coming ...
1029
1082
  // const paramListCx = pcx.isParam();
@@ -1036,7 +1089,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1036
1089
  // }
1037
1090
  // return this.astAt(new ast.NamedSource(name, paramInit), pcx);
1038
1091
  // }
1039
- return this.astAt(new ast.NamedSource(name), pcx);
1092
+ const source = new ast.NamedSourceOrQuery(name);
1093
+ return this.astAt(source, pcx);
1040
1094
  }
1041
1095
  visitExprFilter(pcx) {
1042
1096
  const filters = this.visit(pcx.filteredBy());
@@ -1097,7 +1151,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1097
1151
  }
1098
1152
  stmt.is = blockName;
1099
1153
  const result = this.astAt(stmt, pcx);
1100
- if (ENABLE_M4_WARNINGS) {
1154
+ if (this.m4WarningsEnabled()) {
1101
1155
  this.astError(result, '`sql:` statement is deprecated, use `connection_name.sql(...)` instead', 'warn');
1102
1156
  }
1103
1157
  return result;
@@ -1116,7 +1170,9 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1116
1170
  }
1117
1171
  visitDocAnnotations(pcx) {
1118
1172
  const allNotes = pcx.DOC_ANNOTATION().map(note => note.text);
1119
- return new ast.ModelAnnotation(allNotes);
1173
+ const tags = new ast.ModelAnnotation(allNotes);
1174
+ this.compilerFlags = tags.getCompilerFlags(this.compilerFlags);
1175
+ return tags;
1120
1176
  }
1121
1177
  visitIgnoredObjectAnnotations(pcx) {
1122
1178
  return new IgnoredElement(pcx.text);
@@ -5,6 +5,7 @@ import { LogMessage, MessageLog } from './parse-log';
5
5
  import { Zone, ZoneData } from './zone';
6
6
  import { ReferenceList } from './reference-list';
7
7
  import { ASTResponse, CompletionsResponse, DataRequestResponse, ProblemResponse, FatalResponse, FinalResponse, HelpContextResponse, MetadataResponse, ModelDataRequest, NeedURLData, TranslateResponse } from './translate-response';
8
+ import { MalloyTagProperties } from '../tags';
8
9
  export declare type StepResponses = DataRequestResponse | ASTResponse | TranslateResponse | ParseResponse | MetadataResponse;
9
10
  /**
10
11
  * A Translation is a series of translation steps. Each step can depend
@@ -170,6 +171,7 @@ export declare class MalloyTranslator extends MalloyTranslation {
170
171
  importZone: Zone<string>;
171
172
  sqlQueryZone: Zone<SQLBlockStructDef>;
172
173
  logger: MessageLog;
174
+ compilerFlags: MalloyTagProperties;
173
175
  readonly root: MalloyTranslator;
174
176
  constructor(rootURL: string, preload?: ParseUpdate | null);
175
177
  update(dd: ParseUpdate): void;
@@ -291,6 +291,7 @@ class ASTStep {
291
291
  }
292
292
  const secondPass = new malloy_to_ast_1.MalloyToAST(parse, that.root.logger);
293
293
  const newAst = secondPass.visit(parse.root);
294
+ that.root.compilerFlags = secondPass.compilerFlags;
294
295
  if (that.root.logger.hasErrors()) {
295
296
  this.response = that.fatalResponse();
296
297
  return this.response;
@@ -750,6 +751,7 @@ class MalloyTranslator extends MalloyTranslation {
750
751
  this.importZone = new zone_1.Zone();
751
752
  this.sqlQueryZone = new zone_1.Zone();
752
753
  this.logger = new parse_log_1.MessageLog();
754
+ this.compilerFlags = {};
753
755
  this.root = this;
754
756
  if (preload) {
755
757
  this.update(preload);
@@ -54,7 +54,7 @@ class DocumentSymbolWalker {
54
54
  });
55
55
  this.blockRange = undefined;
56
56
  }
57
- enterRunStatementDef(pcx) {
57
+ enterRunStatement(pcx) {
58
58
  this.symbols.push({
59
59
  range: this.translator.rangeFromContext(pcx.topLevelAnonQueryDef()),
60
60
  name: 'unnamed_query',
@@ -63,15 +63,6 @@ class DocumentSymbolWalker {
63
63
  lensRange: this.translator.rangeFromContext(pcx),
64
64
  });
65
65
  }
66
- enterRunStatementRef(pcx) {
67
- this.symbols.push({
68
- range: this.translator.rangeFromContext(pcx.queryName()),
69
- name: pcx.queryName().id().text,
70
- type: 'query',
71
- children: [],
72
- lensRange: this.translator.rangeFromContext(pcx),
73
- });
74
- }
75
66
  enterAnonymousQuery(pcx) {
76
67
  this.symbols.push({
77
68
  range: this.translator.rangeFromContext(pcx.topLevelAnonQueryDef().query()),
@@ -71,7 +71,7 @@ test('run (def) symbols are included', () => {
71
71
  });
72
72
  test('run (ref) symbols are included', () => {
73
73
  testSymbol((0, test_translator_1.markSource) `query: by_carrier is flights -> by_carrier
74
- run: ${'by_carrier'}`, 'by_carrier', 'query', [1]);
74
+ run: ${'by_carrier'}`, 'unnamed_query', 'unnamed_query', [1]);
75
75
  });
76
76
  test('expression field defs are included', () => {
77
77
  testSymbol((0, test_translator_1.markSource) `