@malloydata/malloy 0.0.393 → 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
@@ -7,12 +7,13 @@ import { extendNoteMethod } from '../types/noteable';
7
7
  export declare class GivenDeclaration extends MalloyElement implements DocStatement, Noteable {
8
8
  readonly name: string;
9
9
  readonly typeDef: GivenTypeDef;
10
+ readonly inline: boolean;
10
11
  elementType: string;
11
12
  readonly isNoteableObj = true;
12
13
  extendNote: typeof extendNoteMethod;
13
14
  note?: Annotation;
14
15
  readonly default?: ConstantExpression;
15
- constructor(name: string, typeDef: GivenTypeDef, defaultExpr?: ConstantExpression);
16
+ constructor(name: string, typeDef: GivenTypeDef, defaultExpr?: ConstantExpression, inline?: boolean);
16
17
  protected varInfo(): string;
17
18
  execute(doc: Document): void;
18
19
  }
@@ -6,6 +6,7 @@
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");
@@ -20,11 +21,43 @@ function filterTypeMismatch(declared, constVal) {
20
21
  return ((declared.type === 'filter expression') !==
21
22
  (constVal.type === 'filter expression'));
22
23
  }
24
+ /**
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.
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
+ }
23
55
  class GivenDeclaration extends malloy_element_1.MalloyElement {
24
- constructor(name, typeDef, defaultExpr) {
56
+ constructor(name, typeDef, defaultExpr, inline = false) {
25
57
  super();
26
58
  this.name = name;
27
59
  this.typeDef = typeDef;
60
+ this.inline = inline;
28
61
  this.elementType = 'given';
29
62
  this.isNoteableObj = true;
30
63
  this.extendNote = noteable_1.extendNoteMethod;
@@ -44,6 +77,12 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
44
77
  this.logError('given-definition-name-conflict', `Cannot redefine '${this.name}'`);
45
78
  return;
46
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
+ }
47
86
  // Default expression. ConstantExpression evaluates through a
48
87
  // ConstantFieldSpace that errors on every name lookup, so any
49
88
  // non-constant subexpression (field refs, aggregates, etc.) gets
@@ -112,6 +151,17 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
112
151
  }
113
152
  givenUsage = closure;
114
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
+ }
115
165
  }
116
166
  }
117
167
  const id = (0, source_def_utils_1.mkGivenID)(this.name, (_c = this.location) === null || _c === void 0 ? void 0 : _c.url);
@@ -124,6 +174,7 @@ class GivenDeclaration extends malloy_element_1.MalloyElement {
124
174
  givenUsage,
125
175
  location: this.location,
126
176
  annotation: this.note,
177
+ ...(this.inline ? { inline: true } : {}),
127
178
  };
128
179
  doc.documentGivens.set(id, givenIR);
129
180
  const entry = { type: 'given', name: this.name, id };
@@ -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
  }