@malloydata/malloy 0.0.392 → 0.0.394

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.
@@ -278,10 +278,6 @@ export declare class Model implements Taggable {
278
278
  * The givens this model surfaces, keyed by caller-facing surface name.
279
279
  * Used by whole-model parameter-editor UIs to render input widgets for
280
280
  * every given the model can accept.
281
- *
282
- * Internal-only givens (declared but never surfaced into the namespace,
283
- * resolved purely via defaults) are NOT in this map — the caller has no
284
- * way to set them, so listing them would mislead a UI.
285
281
  */
286
282
  get givens(): ReadonlyMap<string, Given>;
287
283
  tagParse(spec?: TagParseSpec): MalloyTagParse;
@@ -782,10 +782,6 @@ class Model {
782
782
  * The givens this model surfaces, keyed by caller-facing surface name.
783
783
  * Used by whole-model parameter-editor UIs to render input widgets for
784
784
  * every given the model can accept.
785
- *
786
- * Internal-only givens (declared but never surfaced into the namespace,
787
- * resolved purely via defaults) are NOT in this map — the caller has no
788
- * way to set them, so listing them would mislead a UI.
789
785
  */
790
786
  get givens() {
791
787
  var _a, _b;
@@ -799,9 +795,9 @@ class Model {
799
795
  if ((_b = (_a = this.runtimeContext) === null || _a === void 0 ? void 0 : _a.finalizedGivens) === null || _b === void 0 ? void 0 : _b.has(surfaceName))
800
796
  continue;
801
797
  const decl = givens[entry.id];
802
- if (!decl)
803
- continue;
804
- out.set(surfaceName, new Given(surfaceName, entry.id, decl));
798
+ if (decl && !decl.inline) {
799
+ out.set(surfaceName, new Given(surfaceName, entry.id, decl));
800
+ }
805
801
  }
806
802
  return out;
807
803
  }
@@ -1197,11 +1193,18 @@ class PreparedQuery {
1197
1193
  */
1198
1194
  getPreparedResult(options) {
1199
1195
  const queryModel = this._model.queryModel;
1196
+ // Build the resolved-givens map in two phases:
1197
+ // 1. caller-supplied values (resolveSuppliedGivens)
1198
+ // 2. inline-given defaults eager-evaluated against the map
1199
+ // Result is undefined when no values land — preserves the previous
1200
+ // "no givens path" downstream.
1201
+ const resolved = (options === null || options === void 0 ? void 0 : options.givens)
1202
+ ? (0, given_binding_1.resolveSuppliedGivens)(options.givens, this._modelDef)
1203
+ : new Map();
1204
+ (0, given_binding_1.evaluateInlineGivens)(resolved, this._modelDef);
1200
1205
  const prepareResultOptions = {
1201
1206
  ...options,
1202
- resolvedGivens: (options === null || options === void 0 ? void 0 : options.givens)
1203
- ? (0, given_binding_1.resolveSuppliedGivens)(options.givens, this._modelDef)
1204
- : undefined,
1207
+ resolvedGivens: resolved.size > 0 ? resolved : undefined,
1205
1208
  };
1206
1209
  const translatedQuery = queryModel.compileQuery(this._query, prepareResultOptions);
1207
1210
  return new PreparedResult({
@@ -3,6 +3,7 @@ import type { ExprValue } from '../types/expr-value';
3
3
  import { ExpressionDef } from '../types/expression-def';
4
4
  import type { FieldSpace } from '../types/field-space';
5
5
  import { BinaryBoolean } from './binary-boolean';
6
+ import type { GivenReference } from './expr-given';
6
7
  export declare class ExprCompare extends BinaryBoolean<CompareMalloyOperator> {
7
8
  elementType: string;
8
9
  constructor(left: ExpressionDef, op: CompareMalloyOperator, right: ExpressionDef);
@@ -28,3 +29,17 @@ export declare class ExprLegacyIn extends ExpressionDef {
28
29
  constructor(expr: ExpressionDef, notIn: boolean, choices: ExpressionDef[]);
29
30
  getExpression(fs: FieldSpace): ExprValue;
30
31
  }
32
+ /**
33
+ * `expr in $ARRAY_GIVEN` — runtime test of a basic-typed expression
34
+ * against the elements of a runtime-bound array given. The translator
35
+ * verifies the given is `T[]` and the LHS is the same basic `T`; SQL
36
+ * emission expands the bound array's elements at compile time.
37
+ */
38
+ export declare class ExprInGiven extends ExpressionDef {
39
+ readonly expr: ExpressionDef;
40
+ readonly notIn: boolean;
41
+ readonly givenRef: GivenReference;
42
+ elementType: string;
43
+ constructor(expr: ExpressionDef, notIn: boolean, givenRef: GivenReference);
44
+ getExpression(fs: FieldSpace): ExprValue;
45
+ }
@@ -55,9 +55,12 @@ var __importStar = (this && this.__importStar) || (function () {
55
55
  };
56
56
  })();
57
57
  Object.defineProperty(exports, "__esModule", { value: true });
58
- exports.ExprLegacyIn = exports.ExprEquality = exports.ExprCompare = void 0;
58
+ exports.ExprInGiven = exports.ExprLegacyIn = exports.ExprEquality = exports.ExprCompare = void 0;
59
+ const malloy_types_1 = require("../../../model/malloy_types");
60
+ const utils_1 = require("../../../model/utils");
59
61
  const TDU = __importStar(require("../typedesc-utils"));
60
62
  const expr_value_1 = require("../types/expr-value");
63
+ const expr_value_2 = require("../types/expr-value");
61
64
  const expression_def_1 = require("../types/expression-def");
62
65
  const binary_boolean_1 = require("./binary-boolean");
63
66
  const compareTypes = {
@@ -112,7 +115,7 @@ class ExprLegacyIn extends expression_def_1.ExpressionDef {
112
115
  getExpression(fs) {
113
116
  const lookFor = this.expr.getExpression(fs);
114
117
  const oneOf = this.choices.map(e => e.getExpression(fs));
115
- return (0, expr_value_1.computedExprValue)({
118
+ return (0, expr_value_2.computedExprValue)({
116
119
  dataType: { type: 'boolean' },
117
120
  value: {
118
121
  node: 'in',
@@ -124,4 +127,81 @@ class ExprLegacyIn extends expression_def_1.ExpressionDef {
124
127
  }
125
128
  }
126
129
  exports.ExprLegacyIn = ExprLegacyIn;
130
+ /**
131
+ * `expr in $ARRAY_GIVEN` — runtime test of a basic-typed expression
132
+ * against the elements of a runtime-bound array given. The translator
133
+ * verifies the given is `T[]` and the LHS is the same basic `T`; SQL
134
+ * emission expands the bound array's elements at compile time.
135
+ */
136
+ class ExprInGiven extends expression_def_1.ExpressionDef {
137
+ constructor(expr, notIn, givenRef) {
138
+ super();
139
+ this.expr = expr;
140
+ this.notIn = notIn;
141
+ this.givenRef = givenRef;
142
+ this.elementType = 'inGiven';
143
+ this.has({ expr, givenRef });
144
+ }
145
+ getExpression(fs) {
146
+ const lookFor = this.expr.getExpression(fs);
147
+ const givenVal = this.givenRef.getExpression(fs);
148
+ // `in` is logically a boolean — every error path returns a
149
+ // boolean-typed error so a `where:` clause around us doesn't pile a
150
+ // "filter must be boolean" complaint on top of our own diagnostic.
151
+ const boolError = () => (0, expr_value_1.computedErrorExprValue)({
152
+ dataType: { type: 'boolean' },
153
+ error: 'in-given type error',
154
+ from: [lookFor, givenVal],
155
+ });
156
+ if (lookFor.type === 'error' || givenVal.type === 'error') {
157
+ return boolError();
158
+ }
159
+ // GivenReference only ever returns a `given` ExprValue on the
160
+ // success path; the error branch is filtered above. No other case
161
+ // is reachable here.
162
+ const givenNode = givenVal.value;
163
+ if (givenNode.node !== 'given') {
164
+ throw this.internalError(`expected GivenReference to produce a 'given' node, got '${givenNode.node}'`);
165
+ }
166
+ if (!malloy_types_1.TD.isAtomic(givenVal) || givenVal.type !== 'array') {
167
+ this.logError('in-given-rhs-not-array', {
168
+ givenName: this.givenRef.name,
169
+ actualType: malloy_types_1.TD.isAtomic(givenVal)
170
+ ? (0, utils_1.typeDefToString)(givenVal)
171
+ : givenVal.type,
172
+ });
173
+ return boolError();
174
+ }
175
+ if ((0, malloy_types_1.isRepeatedRecord)(givenVal)) {
176
+ this.logError('in-given-rhs-not-basic-array', {
177
+ givenName: this.givenRef.name,
178
+ elementType: (0, utils_1.typeDefToString)(givenVal),
179
+ });
180
+ return boolError();
181
+ }
182
+ // givenVal is BasicArrayTypeDef-shaped — the union for array
183
+ // AtomicTypeDefs is BasicArray | RepeatedRecord, and the
184
+ // RepeatedRecord branch returned above.
185
+ const elemType = givenVal.elementTypeDef;
186
+ if (!malloy_types_1.TD.isBasicAtomic(lookFor) || lookFor.type !== elemType.type) {
187
+ this.logError('in-given-type-mismatch', {
188
+ lhsType: malloy_types_1.TD.isAtomic(lookFor) ? (0, utils_1.typeDefToString)(lookFor) : lookFor.type,
189
+ elementType: (0, utils_1.typeDefToString)(elemType),
190
+ });
191
+ return boolError();
192
+ }
193
+ const inGivenNode = {
194
+ node: 'inGiven',
195
+ not: this.notIn,
196
+ givenRef: givenNode,
197
+ e: lookFor.value,
198
+ };
199
+ return (0, expr_value_2.computedExprValue)({
200
+ dataType: { type: 'boolean' },
201
+ value: inGivenNode,
202
+ from: [lookFor, givenVal],
203
+ });
204
+ }
205
+ }
206
+ exports.ExprInGiven = ExprInGiven;
127
207
  //# sourceMappingURL=expr-compare.js.map
@@ -4,24 +4,19 @@ import type { DocStatement, Document } from '../types/malloy-element';
4
4
  import { DocStatementList, MalloyElement } from '../types/malloy-element';
5
5
  import type { Noteable } from '../types/noteable';
6
6
  import { extendNoteMethod } from '../types/noteable';
7
- /**
8
- * One named given declaration: `NAME :: TYPE [is EXPR]`.
9
- */
10
7
  export declare class GivenDeclaration extends MalloyElement implements DocStatement, Noteable {
11
8
  readonly name: string;
12
9
  readonly typeDef: GivenTypeDef;
10
+ readonly inline: boolean;
13
11
  elementType: string;
14
12
  readonly isNoteableObj = true;
15
13
  extendNote: typeof extendNoteMethod;
16
14
  note?: Annotation;
17
15
  readonly default?: ConstantExpression;
18
- constructor(name: string, typeDef: GivenTypeDef, defaultExpr?: ConstantExpression);
16
+ constructor(name: string, typeDef: GivenTypeDef, defaultExpr?: ConstantExpression, inline?: boolean);
19
17
  protected varInfo(): string;
20
18
  execute(doc: Document): void;
21
19
  }
22
- /**
23
- * Top-level `given:` block — a sequence of given declarations.
24
- */
25
20
  export declare class DefineGivens extends DocStatementList {
26
21
  elementType: string;
27
22
  readonly givens: GivenDeclaration[];
@@ -6,30 +6,58 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.DefineGivens = exports.GivenDeclaration = void 0;
8
8
  const malloy_types_1 = require("../../../model/malloy_types");
9
+ const inline_expr_1 = require("../../../model/inline_expr");
9
10
  const source_def_utils_1 = require("../../../model/source_def_utils");
10
11
  const utils_1 = require("../../../model/utils");
11
12
  const expression_def_1 = require("../types/expression-def");
12
13
  const malloy_element_1 = require("../types/malloy-element");
13
14
  const noteable_1 = require("../types/noteable");
14
- /**
15
- * True when exactly one of `declared` and `constVal` is filter-typed.
16
- * Catches `filter<T>` declared with a non-filter default (and vice versa)
17
- * at definition time. Inner-content validation of `filter<T>` defaults
18
- * (syntax + compatibility with `T`) is the filter machinery's job at the
19
- * use site; we don't try to do it here.
20
- */
15
+ // `filter<T>` defaults can't be type-checked via TD.eq — the filter
16
+ // expression value shape doesn't match an atomic typeDef. Catch only
17
+ // the gross kind mismatch here; inner-content validation (filter
18
+ // syntax + T compatibility) belongs to the filter machinery at use
19
+ // site.
21
20
  function filterTypeMismatch(declared, constVal) {
22
21
  return ((declared.type === 'filter expression') !==
23
22
  (constVal.type === 'filter expression'));
24
23
  }
25
24
  /**
26
- * One named given declaration: `NAME :: TYPE [is EXPR]`.
25
+ * Walk an Expr tree and collect every node string that isn't in the
26
+ * allowed inline operator/leaf sets.
27
+ *
28
+ * The translator caller is gated on a clean translation of the default
29
+ * (`constVal.type !== 'error'`): we don't pile bad-operator errors on
30
+ * top of a default that didn't translate cleanly for more fundamental
31
+ * reasons (an unknown `$REF`, a type mismatch, etc.). Every bad node
32
+ * is collected so the author sees the full list in one diagnostic.
27
33
  */
34
+ function collectInlineBadOps(e, bad) {
35
+ if (!inline_expr_1.INLINE_OPS.has(e.node) && !inline_expr_1.INLINE_LEAVES.has(e.node)) {
36
+ bad.add(e.node);
37
+ }
38
+ if ((0, malloy_types_1.exprHasE)(e)) {
39
+ collectInlineBadOps(e.e, bad);
40
+ }
41
+ else if ((0, malloy_types_1.exprHasKids)(e)) {
42
+ for (const kid of Object.values(e.kids)) {
43
+ if (kid === null)
44
+ continue;
45
+ if (Array.isArray(kid)) {
46
+ for (const k of kid)
47
+ collectInlineBadOps(k, bad);
48
+ }
49
+ else {
50
+ collectInlineBadOps(kid, bad);
51
+ }
52
+ }
53
+ }
54
+ }
28
55
  class GivenDeclaration extends malloy_element_1.MalloyElement {
29
- constructor(name, typeDef, defaultExpr) {
56
+ constructor(name, typeDef, defaultExpr, inline = false) {
30
57
  super();
31
58
  this.name = name;
32
59
  this.typeDef = typeDef;
60
+ this.inline = inline;
33
61
  this.elementType = 'given';
34
62
  this.isNoteableObj = true;
35
63
  this.extendNote = noteable_1.extendNoteMethod;
@@ -42,13 +70,19 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
42
70
  return ` ${this.name} :: ${(0, utils_1.typeDefToString)(this.typeDef)}`;
43
71
  }
44
72
  execute(doc) {
45
- var _a, _b, _c, _d;
73
+ var _a, _b, _c, _d, _e;
46
74
  if (this.typeDef.type === 'error')
47
75
  return;
48
76
  if (doc.modelEntry(this.name)) {
49
77
  this.logError('given-definition-name-conflict', `Cannot redefine '${this.name}'`);
50
78
  return;
51
79
  }
80
+ // An inline given with no default has nothing to evaluate at bind
81
+ // time. Log and keep going — the given still registers in the
82
+ // namespace so downstream errors don't cascade pointlessly.
83
+ if (this.inline && !this.default) {
84
+ this.logError('inline-no-default', { name: this.name });
85
+ }
52
86
  // Default expression. ConstantExpression evaluates through a
53
87
  // ConstantFieldSpace that errors on every name lookup, so any
54
88
  // non-constant subexpression (field refs, aggregates, etc.) gets
@@ -60,11 +94,19 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
60
94
  if (this.default) {
61
95
  const constVal = this.default.constantValue();
62
96
  if (constVal.type !== 'error') {
97
+ // `X :: timestamp is @2024-01-01` works because date literals
98
+ // carry a morphic.timestamp. Date/timestamp are the only
99
+ // MorphicType targets — other declared types fall through to
100
+ // the TD.eq check below.
101
+ const morphed = this.typeDef.type === 'date' || this.typeDef.type === 'timestamp'
102
+ ? (0, expression_def_1.getMorphicValue)(constVal, this.typeDef.type)
103
+ : undefined;
63
104
  // `filter<T>` defaults are filter-expression literals — their
64
105
  // shape doesn't match an atomic typeDef, so type-check there is
65
106
  // owned by the filter machinery, not us. `null` is implicitly
66
107
  // accepted for any declared type.
67
108
  if (constVal.type !== 'null' &&
109
+ morphed === undefined &&
68
110
  (filterTypeMismatch(this.typeDef, constVal) ||
69
111
  !malloy_types_1.TD.eq(this.typeDef, constVal))) {
70
112
  const actual = malloy_types_1.TD.isAtomic(constVal)
@@ -79,7 +121,7 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
79
121
  // again at use site. Catches bad filter syntax early.
80
122
  (0, expression_def_1.checkFilterExpression)(this.default, this.typeDef.filterType, constVal.value);
81
123
  }
82
- defaultExpr = constVal.value;
124
+ defaultExpr = (_a = morphed === null || morphed === void 0 ? void 0 : morphed.value) !== null && _a !== void 0 ? _a : constVal.value;
83
125
  // Build the transitive closure of givens reachable through this
84
126
  // default's expression. We only include direct refs PLUS each
85
127
  // referenced given's already-precomputed transitive (which is
@@ -100,7 +142,7 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
100
142
  seen.add(g.id);
101
143
  closure.push(g);
102
144
  const refDecl = doc.documentGivens.get(g.id);
103
- for (const t of (_a = refDecl === null || refDecl === void 0 ? void 0 : refDecl.givenUsage) !== null && _a !== void 0 ? _a : []) {
145
+ for (const t of (_b = refDecl === null || refDecl === void 0 ? void 0 : refDecl.givenUsage) !== null && _b !== void 0 ? _b : []) {
104
146
  if (seen.has(t.id))
105
147
  continue;
106
148
  seen.add(t.id);
@@ -109,10 +151,21 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
109
151
  }
110
152
  givenUsage = closure;
111
153
  }
154
+ // Ensure inline expression is resolveable at compile time.
155
+ if (this.inline) {
156
+ const bad = new Set();
157
+ collectInlineBadOps(defaultExpr, bad);
158
+ if (bad.size > 0) {
159
+ this.default.logError('inline-bad-operator', {
160
+ name: this.name,
161
+ operators: [...bad].sort().join(', '),
162
+ });
163
+ }
164
+ }
112
165
  }
113
166
  }
114
- const id = (0, source_def_utils_1.mkGivenID)(this.name, (_b = this.location) === null || _b === void 0 ? void 0 : _b.url);
115
- const defaultText = defaultExpr !== undefined ? (_c = this.default) === null || _c === void 0 ? void 0 : _c.code : undefined;
167
+ const id = (0, source_def_utils_1.mkGivenID)(this.name, (_c = this.location) === null || _c === void 0 ? void 0 : _c.url);
168
+ const defaultText = defaultExpr !== undefined ? (_d = this.default) === null || _d === void 0 ? void 0 : _d.code : undefined;
116
169
  const givenIR = {
117
170
  name: this.name,
118
171
  type: this.typeDef,
@@ -121,6 +174,7 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
121
174
  givenUsage,
122
175
  location: this.location,
123
176
  annotation: this.note,
177
+ ...(this.inline ? { inline: true } : {}),
124
178
  };
125
179
  doc.documentGivens.set(id, givenIR);
126
180
  const entry = { type: 'given', name: this.name, id };
@@ -132,7 +186,7 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
132
186
  this.addReference({
133
187
  type: 'givenReference',
134
188
  text: this.name,
135
- location: (_d = this.location) !== null && _d !== void 0 ? _d : {
189
+ location: (_e = this.location) !== null && _e !== void 0 ? _e : {
136
190
  url: '',
137
191
  range: {
138
192
  start: { line: 0, character: 0 },
@@ -149,9 +203,6 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
149
203
  }
150
204
  }
151
205
  exports.GivenDeclaration = GivenDeclaration;
152
- /**
153
- * Top-level `given:` block — a sequence of given declarations.
154
- */
155
206
  class DefineGivens extends malloy_element_1.DocStatementList {
156
207
  constructor(givens) {
157
208
  super(givens);
@@ -239,10 +239,12 @@ class MalloyElement {
239
239
  const kiddle = this.children[kidLabel];
240
240
  if (kiddle instanceof MalloyElement) {
241
241
  yield kiddle;
242
+ yield* kiddle.walk();
242
243
  }
243
244
  else {
244
245
  for (const k of kiddle) {
245
246
  yield k;
247
+ yield* k.walk();
246
248
  }
247
249
  }
248
250
  }