@soundor/expression 0.0.0-stage → 0.17.0

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/index.mjs ADDED
@@ -0,0 +1,334 @@
1
+ import { C as isExpression, S as UNARY_OPERATORS, _ as isFloatType, a as assertExpression, b as isNumericType, c as literalProblem, d as INTEGER_TYPES, f as NUMERIC_TYPES, g as isExpressionType, h as isBigIntType, i as MAX_NODES, l as FLOAT_TYPES, m as baseType, n as MAX_DEPTH, o as checkExpression, p as SCALAR_TYPES, r as MAX_FIXED_DIGITS, s as joinTypes, t as ExpressionError, u as INTEGERS, v as isIntegerType, x as BINARY_OPERATORS, y as isNullableType } from "./check-Db6XRMc8.mjs";
2
+ // src/builder.ts
3
+ function freeze(node) {
4
+ return Object.freeze(node);
5
+ }
6
+ function literal(type, value) {
7
+ let stored = value;
8
+ if (isBigIntType(baseType(type)) && typeof value === "bigint") stored = String(value);
9
+ if (typeof stored === "number" && Object.is(stored, -0)) stored = 0;
10
+ const problem = literalProblem(type, stored);
11
+ if (problem !== void 0) throw new TypeError(`Invalid literal: ${problem}`);
12
+ return freeze({
13
+ kind: "literal",
14
+ type,
15
+ value: stored
16
+ });
17
+ }
18
+ function text(value) {
19
+ if (typeof value === "string") return literal("string", value);
20
+ requireExpression(value, "string");
21
+ return value;
22
+ }
23
+ function requireExpression(value, what) {
24
+ if (!isExpression(value)) throw new TypeError(`Expected an expression (${what}), got ${String(value)}`);
25
+ }
26
+ /** Two operands, one possibly a literal that takes the other's type. */
27
+ function operands(name, a, b) {
28
+ if (isExpression(a) && isExpression(b)) {
29
+ if (a.type !== b.type) throw new TypeError(`${name}() takes operands of one type, got '${a.type}' and '${b.type}'; convert one explicitly`);
30
+ return [a, b];
31
+ }
32
+ if (isExpression(a)) return [a, literal(a.type, b)];
33
+ if (isExpression(b)) return [literal(b.type, a), b];
34
+ throw new TypeError(`${name}() needs at least one expression operand`);
35
+ }
36
+ function unary(operator, a, type) {
37
+ requireExpression(a, operator);
38
+ return freeze({
39
+ kind: "unary",
40
+ type: type ?? a.type,
41
+ operator,
42
+ operand: a
43
+ });
44
+ }
45
+ function binary(operator, a, b, result) {
46
+ const [left, right] = operands(operator, a, b);
47
+ return freeze({
48
+ kind: "binary",
49
+ type: result ?? left.type,
50
+ operator,
51
+ left,
52
+ right
53
+ });
54
+ }
55
+ function chain(operator, operands) {
56
+ if (operands.length === 0) throw new TypeError(`${operator}() needs an operand`);
57
+ return operands.reduce((left, right) => binary(operator, left, right, "boolean"));
58
+ }
59
+ function parse(textValue, type) {
60
+ if (!isNumericType(type)) throw new TypeError(`parse() reads a numeric type, not '${String(type)}'`);
61
+ return freeze({
62
+ kind: "parse",
63
+ type: `${type}?`,
64
+ operand: text(textValue)
65
+ });
66
+ }
67
+ /** How deep let and map bodies being built are: names their variables. */
68
+ let bindingDepth = 0;
69
+ function bind(type, body) {
70
+ if (typeof body !== "function") throw new TypeError("let() and map() take a function that builds the body");
71
+ const variable = `v${bindingDepth}`;
72
+ const value = freeze({
73
+ kind: "variable",
74
+ type,
75
+ name: variable
76
+ });
77
+ bindingDepth++;
78
+ let result;
79
+ try {
80
+ result = body(value);
81
+ } finally {
82
+ bindingDepth--;
83
+ }
84
+ requireExpression(result, "body");
85
+ return [variable, result];
86
+ }
87
+ const implementation = {
88
+ int8: (value) => literal("int8", value),
89
+ uint8: (value) => literal("uint8", value),
90
+ int16: (value) => literal("int16", value),
91
+ uint16: (value) => literal("uint16", value),
92
+ int32: (value) => literal("int32", value),
93
+ uint32: (value) => literal("uint32", value),
94
+ int64: (value) => literal("int64", value),
95
+ uint64: (value) => literal("uint64", value),
96
+ float32: (value) => literal("float32", value),
97
+ float64: (value) => literal("float64", value),
98
+ boolean: (value) => literal("boolean", value),
99
+ string: (value) => literal("string", value),
100
+ literal: (type, value) => literal(type, value),
101
+ null: (type) => {
102
+ if (!isNumericType(type)) throw new TypeError(`null() takes a numeric type, not '${String(type)}'`);
103
+ return literal(`${type}?`, null);
104
+ },
105
+ add: (a, b) => binary("add", a, b),
106
+ sub: (a, b) => binary("sub", a, b),
107
+ mul: (a, b) => binary("mul", a, b),
108
+ div: (a, b) => binary("div", a, b),
109
+ min: (a, b) => binary("min", a, b),
110
+ max: (a, b) => binary("max", a, b),
111
+ pow: (a, b) => binary("pow", a, b),
112
+ neg: (a) => unary("neg", a),
113
+ abs: (a) => unary("abs", a),
114
+ sqrt: (a) => unary("sqrt", a),
115
+ exp: (a) => unary("exp", a),
116
+ log: (a) => unary("log", a),
117
+ floor: (a) => unary("floor", a),
118
+ ceil: (a) => unary("ceil", a),
119
+ round: (a) => unary("round", a),
120
+ convert: (a, type) => {
121
+ requireExpression(a, "convert");
122
+ if (!isNumericType(type)) throw new TypeError(`convert() turns a number into a numeric type, not '${String(type)}'`);
123
+ return freeze({
124
+ kind: "convert",
125
+ type,
126
+ operand: a
127
+ });
128
+ },
129
+ eq: (a, b) => binary("eq", a, b, "boolean"),
130
+ ne: (a, b) => binary("ne", a, b, "boolean"),
131
+ lt: (a, b) => binary("lt", a, b, "boolean"),
132
+ lte: (a, b) => binary("lte", a, b, "boolean"),
133
+ gt: (a, b) => binary("gt", a, b, "boolean"),
134
+ gte: (a, b) => binary("gte", a, b, "boolean"),
135
+ and: (...operands) => chain("and", operands),
136
+ or: (...operands) => chain("or", operands),
137
+ not: (a) => unary("not", a, "boolean"),
138
+ if: (condition, then, otherwise) => {
139
+ requireExpression(condition, "if condition");
140
+ const a = typeof then === "string" ? literal("string", then) : then;
141
+ const b = typeof otherwise === "string" ? literal("string", otherwise) : otherwise;
142
+ requireExpression(a, "if branch");
143
+ requireExpression(b, "else branch");
144
+ const type = joinTypes(a.type, b.type);
145
+ if (type === void 0) throw new TypeError(`if() branches have different types, '${a.type}' and '${b.type}'`);
146
+ return freeze({
147
+ kind: "if",
148
+ type,
149
+ condition,
150
+ then: a,
151
+ else: b
152
+ });
153
+ },
154
+ fixed: (a, digits) => {
155
+ requireExpression(a, "fixed");
156
+ return freeze({
157
+ kind: "fixed",
158
+ type: "string",
159
+ operand: a,
160
+ digits
161
+ });
162
+ },
163
+ concat: (...parts) => {
164
+ if (parts.length === 0) throw new TypeError("concat() needs a part");
165
+ return freeze({
166
+ kind: "concat",
167
+ type: "string",
168
+ operands: Object.freeze(parts.map(text))
169
+ });
170
+ },
171
+ trim: (a) => unary("trim", text(a)),
172
+ lower: (a) => unary("lower", text(a)),
173
+ endsWith: (a, suffix) => binary("endsWith", text(a), text(suffix), "boolean"),
174
+ removeSuffix: (a, suffix) => binary("removeSuffix", text(a), text(suffix), "string"),
175
+ parse: (value, type) => parse(value, type),
176
+ parseInt8: (value) => parse(value, "int8"),
177
+ parseUint8: (value) => parse(value, "uint8"),
178
+ parseInt16: (value) => parse(value, "int16"),
179
+ parseUint16: (value) => parse(value, "uint16"),
180
+ parseInt32: (value) => parse(value, "int32"),
181
+ parseUint32: (value) => parse(value, "uint32"),
182
+ parseInt64: (value) => parse(value, "int64"),
183
+ parseUint64: (value) => parse(value, "uint64"),
184
+ parseFloat32: (value) => parse(value, "float32"),
185
+ parseFloat64: (value) => parse(value, "float64"),
186
+ isNull: (a) => {
187
+ requireExpression(a, "isNull");
188
+ return freeze({
189
+ kind: "isNull",
190
+ type: "boolean",
191
+ operand: a
192
+ });
193
+ },
194
+ coalesce: (a, fallback) => {
195
+ requireExpression(a, "coalesce");
196
+ if (!isNullableType(a.type)) throw new TypeError(`coalesce() takes a nullable value, not a '${a.type}'`);
197
+ const other = isExpression(fallback) ? fallback : literal(baseType(a.type), fallback);
198
+ return freeze({
199
+ kind: "coalesce",
200
+ type: baseType(a.type),
201
+ operand: a,
202
+ fallback: other
203
+ });
204
+ },
205
+ let: (value, body) => {
206
+ requireExpression(value, "let");
207
+ const [variable, result] = bind(value.type, body);
208
+ return freeze({
209
+ kind: "let",
210
+ type: result.type,
211
+ value,
212
+ variable,
213
+ body: result
214
+ });
215
+ },
216
+ map: (a, body) => {
217
+ requireExpression(a, "map");
218
+ if (!isNullableType(a.type)) throw new TypeError(`map() takes a nullable value, not a '${a.type}'`);
219
+ const [variable, result] = bind(baseType(a.type), body);
220
+ return freeze({
221
+ kind: "map",
222
+ type: isNullableType(result.type) ? result.type : `${result.type}?`,
223
+ operand: a,
224
+ variable,
225
+ body: result
226
+ });
227
+ }
228
+ };
229
+ /** The builder, without inputs. */
230
+ const expressions = Object.freeze(implementation);
231
+ /** An input of an expression context, such as `value`. */
232
+ function input(name, type) {
233
+ return freeze({
234
+ kind: "input",
235
+ type,
236
+ name
237
+ });
238
+ }
239
+ /**
240
+ * The builder with the context's inputs as properties: what a callback such
241
+ * as `format: (e) => …` receives.
242
+ */
243
+ function createContext(inputs) {
244
+ const context = { ...implementation };
245
+ for (const [name, type] of Object.entries(inputs)) {
246
+ if (name in implementation) throw new TypeError(`Input '${name}' would hide the builder's ${name}()`);
247
+ context[name] = input(name, type);
248
+ }
249
+ return Object.freeze(context);
250
+ }
251
+ // src/substitute.ts
252
+ /**
253
+ * `node` with each input named in `replacements` replaced by that
254
+ * expression, of the same type. The variables `node` binds are renamed (with
255
+ * `suffix`), so they never capture a variable of a replacement.
256
+ */
257
+ function substituteInputs(node, replacements, suffix = "s") {
258
+ return rewrite(node, replacements, suffix);
259
+ }
260
+ function rewrite(node, replacements, suffix) {
261
+ const go = (child) => rewrite(child, replacements, suffix);
262
+ let result;
263
+ switch (node.kind) {
264
+ case "literal": return node;
265
+ case "input": {
266
+ const replacement = replacements[node.name];
267
+ if (replacement === void 0) return node;
268
+ if (replacement.type !== node.type) throw new TypeError(`Input '${node.name}' is a '${node.type}', its replacement a '${replacement.type}'`);
269
+ return replacement;
270
+ }
271
+ case "variable":
272
+ result = {
273
+ ...node,
274
+ name: `${node.name}_${suffix}`
275
+ };
276
+ break;
277
+ case "unary":
278
+ case "convert":
279
+ case "fixed":
280
+ case "parse":
281
+ case "isNull":
282
+ result = {
283
+ ...node,
284
+ operand: go(node.operand)
285
+ };
286
+ break;
287
+ case "binary":
288
+ result = {
289
+ ...node,
290
+ left: go(node.left),
291
+ right: go(node.right)
292
+ };
293
+ break;
294
+ case "if":
295
+ result = {
296
+ ...node,
297
+ condition: go(node.condition),
298
+ then: go(node.then),
299
+ else: go(node.else)
300
+ };
301
+ break;
302
+ case "concat":
303
+ result = {
304
+ ...node,
305
+ operands: Object.freeze(node.operands.map(go))
306
+ };
307
+ break;
308
+ case "coalesce":
309
+ result = {
310
+ ...node,
311
+ operand: go(node.operand),
312
+ fallback: go(node.fallback)
313
+ };
314
+ break;
315
+ case "map":
316
+ result = {
317
+ ...node,
318
+ operand: go(node.operand),
319
+ variable: `${node.variable}_${suffix}`,
320
+ body: go(node.body)
321
+ };
322
+ break;
323
+ case "let": result = {
324
+ ...node,
325
+ value: go(node.value),
326
+ variable: `${node.variable}_${suffix}`,
327
+ body: go(node.body)
328
+ };
329
+ }
330
+ return Object.freeze(result);
331
+ }
332
+ export { BINARY_OPERATORS, ExpressionError, FLOAT_TYPES, INTEGERS, INTEGER_TYPES, MAX_DEPTH, MAX_FIXED_DIGITS, MAX_NODES, NUMERIC_TYPES, SCALAR_TYPES, UNARY_OPERATORS, assertExpression, baseType, checkExpression, createContext, expressions, input, isBigIntType, isExpression, isExpressionType, isFloatType, isIntegerType, isNullableType, isNumericType, substituteInputs };
333
+
334
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/builder.ts","../src/substitute.ts"],"sourcesContent":["/**\n * The typed builder: how expressions are written. Every function returns a\n * frozen {@link Expression} whose type TypeScript knows, so an `int32` cannot\n * be added to a `float32`, a parser of an `int32` cannot return a `float32?`,\n * and a mistake shows in the editor rather than at build time. The trees are\n * still checked when they are compiled (`checkExpression`).\n *\n * Operands of one operation have one type; numbers convert explicitly\n * (`convert`). Where one operand is an expression, the other may be a plain\n * literal (`e.mul(e.value, 1000)`), which takes the expression's type.\n */\n\nimport type {\n BinaryOperator,\n Expression,\n ExpressionNode,\n UnaryOperator,\n} from './ast';\nimport { isExpression } from './ast';\nimport { joinTypes, literalProblem } from './check';\nimport {\n baseType,\n isBigIntType,\n isNullableType,\n isNumericType,\n type BaseType,\n type BigIntType,\n type ExpressionType,\n type FloatType,\n type LiteralValue,\n type NullableType,\n type NumericType,\n type ScalarType,\n} from './types';\n\n/** A literal of a numeric type: a number, or a bigint for 64-bit integers. */\nexport type NumericLiteral<T extends NumericType> = T extends BigIntType\n ? bigint\n : number;\n\n/** An operand of type `T`: an expression, or a literal of it. */\nexport type Operand<T extends NumericType> = Expression<T> | NumericLiteral<T>;\n\n/** A string operand: an expression or a plain string. */\nexport type Text = Expression<'string'> | string;\n\n/** The type `map` gives: the body's type, nullable. */\nexport type MapResult<U extends NumericType | NullableType> =\n `${BaseType<U> & NumericType}?`;\n\n/** The types a branch may have when the other is an `A`: `A`, or a number and its nullable. */\nexport type IfBranch<A extends ExpressionType> =\n | A\n | (BaseType<A> extends NumericType ? BaseType<A> | `${BaseType<A>}?` : never);\n\n/** The type `if` gives for two branch types. */\nexport type IfResult<A extends ExpressionType, B extends ExpressionType> = [\n A,\n] extends [B]\n ? A\n : BaseType<A> extends BaseType<B>\n ? BaseType<B> extends BaseType<A>\n ? `${BaseType<A> & NumericType}?`\n : never\n : never;\n\n/** Functions that build expressions. */\nexport interface ExpressionBuilder {\n // ── Literals ──\n int8(value: number): Expression<'int8'>;\n uint8(value: number): Expression<'uint8'>;\n int16(value: number): Expression<'int16'>;\n uint16(value: number): Expression<'uint16'>;\n int32(value: number): Expression<'int32'>;\n uint32(value: number): Expression<'uint32'>;\n int64(value: bigint): Expression<'int64'>;\n uint64(value: bigint): Expression<'uint64'>;\n float32(value: number): Expression<'float32'>;\n float64(value: number): Expression<'float64'>;\n boolean(value: boolean): Expression<'boolean'>;\n string(value: string): Expression<'string'>;\n /** A literal of any scalar type. */\n literal<T extends ScalarType>(type: T, value: LiteralValue<T>): Expression<T>;\n /** `null`, of a nullable number type. */\n null<T extends NumericType>(type: T): Expression<`${T}?`>;\n\n // ── Arithmetic ──\n /** `a + b`. Integers wrap around (two's complement); floats round to their type. */\n add<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<T>;\n add<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<T>;\n sub<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<T>;\n sub<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<T>;\n mul<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<T>;\n mul<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<T>;\n /** `a / b`. Integers truncate toward zero, and an integer divided by zero is 0. */\n div<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<T>;\n div<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<T>;\n /** The smaller; NaN if either is NaN, and -0 is less than +0. */\n min<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<T>;\n min<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<T>;\n max<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<T>;\n max<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<T>;\n /** `a` to the power `b`. */\n pow<T extends FloatType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<T>;\n pow<T extends FloatType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<T>;\n neg<T extends NumericType>(a: Expression<T>): Expression<T>;\n abs<T extends NumericType>(a: Expression<T>): Expression<T>;\n sqrt<T extends FloatType>(a: Expression<T>): Expression<T>;\n /** e to the power `a`. */\n exp<T extends FloatType>(a: Expression<T>): Expression<T>;\n /** The natural logarithm. */\n log<T extends FloatType>(a: Expression<T>): Expression<T>;\n floor<T extends FloatType>(a: Expression<T>): Expression<T>;\n ceil<T extends FloatType>(a: Expression<T>): Expression<T>;\n /** To the nearest integer; halves away from zero (2.5 → 3, -2.5 → -3). */\n round<T extends FloatType>(a: Expression<T>): Expression<T>;\n /**\n * The number as another numeric type. To an integer: truncated toward\n * zero, saturated at the type's bounds, NaN → 0. Between integers: wrapped\n * (two's complement). To a float: the nearest value.\n */\n convert<T extends NumericType>(\n a: Expression<NumericType>,\n type: T,\n ): Expression<T>;\n\n // ── Comparison and logic ──\n eq<T extends ScalarType>(\n a: Expression<T>,\n b: NoInfer<Expression<T> | LiteralValue<T>>,\n ): Expression<'boolean'>;\n ne<T extends ScalarType>(\n a: Expression<T>,\n b: NoInfer<Expression<T> | LiteralValue<T>>,\n ): Expression<'boolean'>;\n lt<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<'boolean'>;\n lt<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<'boolean'>;\n lte<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<'boolean'>;\n lte<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<'boolean'>;\n gt<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<'boolean'>;\n gt<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<'boolean'>;\n gte<T extends NumericType>(\n a: Expression<T>,\n b: NoInfer<Operand<T>>,\n ): Expression<'boolean'>;\n gte<T extends NumericType>(\n a: NumericLiteral<NoInfer<T>>,\n b: Expression<T>,\n ): Expression<'boolean'>;\n and(\n ...operands: [Expression<'boolean'>, ...Expression<'boolean'>[]]\n ): Expression<'boolean'>;\n or(\n ...operands: [Expression<'boolean'>, ...Expression<'boolean'>[]]\n ): Expression<'boolean'>;\n not(a: Expression<'boolean'>): Expression<'boolean'>;\n /** `then` when `condition` holds, else `otherwise`. A number and its nullable join into the nullable. */\n if(\n condition: Expression<'boolean'>,\n then: Text,\n otherwise: Text,\n ): Expression<'string'>;\n if<A extends ExpressionType, B extends IfBranch<A>>(\n condition: Expression<'boolean'>,\n then: Expression<A>,\n otherwise: Expression<B>,\n ): Expression<IfResult<A, B>>;\n\n // ── Text ──\n /**\n * `a` in decimal with exactly `digits` decimals (0 to 15), rounded half\n * away from zero; never a negative zero (\"-0.00\" is \"0.00\").\n */\n fixed(a: Expression<NumericType>, digits: number): Expression<'string'>;\n concat(...parts: [Text, ...Text[]]): Expression<'string'>;\n /** Without leading and trailing ASCII whitespace. */\n trim(a: Text): Expression<'string'>;\n /** With ASCII letters in lower case. */\n lower(a: Text): Expression<'string'>;\n endsWith(a: Text, suffix: Text): Expression<'boolean'>;\n /** `a` without `suffix` when it ends with it; `a` otherwise. */\n removeSuffix(a: Text, suffix: Text): Expression<'string'>;\n /**\n * Text as a number of `type`, or null when it is not one: decimal\n * notation (`-12`, `0.5`, `1e3`; integers without a fraction or exponent),\n * surrounding ASCII whitespace ignored. An integer outside its type, or a\n * float outside its finite range, is null.\n */\n parse<T extends NumericType>(text: Text, type: T): Expression<`${T}?`>;\n parseInt8(text: Text): Expression<'int8?'>;\n parseUint8(text: Text): Expression<'uint8?'>;\n parseInt16(text: Text): Expression<'int16?'>;\n parseUint16(text: Text): Expression<'uint16?'>;\n parseInt32(text: Text): Expression<'int32?'>;\n parseUint32(text: Text): Expression<'uint32?'>;\n parseInt64(text: Text): Expression<'int64?'>;\n parseUint64(text: Text): Expression<'uint64?'>;\n parseFloat32(text: Text): Expression<'float32?'>;\n parseFloat64(text: Text): Expression<'float64?'>;\n\n // ── Nullable values ──\n isNull(a: Expression<NullableType>): Expression<'boolean'>;\n /** The value of `a`, or `fallback` when it is null. */\n coalesce<T extends NumericType>(\n a: Expression<`${T}?`>,\n fallback: NoInfer<Operand<T>>,\n ): Expression<T>;\n /** `body` of `value`, computed once however often the body uses it. */\n let<T extends ExpressionType, U extends ExpressionType>(\n value: Expression<T>,\n body: (value: Expression<T>) => Expression<U>,\n ): Expression<U>;\n /** null when `a` is null; otherwise `body` of its value. */\n map<T extends NumericType, U extends NumericType | NullableType>(\n a: Expression<`${T}?`>,\n body: (value: Expression<T>) => Expression<U>,\n ): Expression<MapResult<U>>;\n}\n\n/** A builder with a context's inputs: `e.value`, `e.text`. */\nexport type ExpressionContext<\n I extends Readonly<Record<string, ExpressionType>>,\n> = ExpressionBuilder & { readonly [K in keyof I]: Expression<I[K]> };\n\nfunction freeze<T extends ExpressionNode>(node: T): Expression<T['type']> {\n return Object.freeze(node) as unknown as Expression<T['type']>;\n}\n\nfunction literal<T extends ExpressionType>(\n type: T,\n value: unknown,\n): Expression<T> {\n let stored = value;\n if (isBigIntType(baseType(type)) && typeof value === 'bigint')\n stored = String(value);\n if (typeof stored === 'number' && Object.is(stored, -0)) stored = 0;\n const problem = literalProblem(type, stored);\n if (problem !== undefined) throw new TypeError(`Invalid literal: ${problem}`);\n return freeze({\n kind: 'literal',\n type,\n value: stored as never,\n }) as Expression<T>;\n}\n\nfunction text(value: Text): Expression<'string'> {\n if (typeof value === 'string') return literal('string', value);\n requireExpression(value, 'string');\n return value;\n}\n\nfunction requireExpression(\n value: unknown,\n what: string,\n): asserts value is Expression {\n if (!isExpression(value))\n throw new TypeError(\n `Expected an expression (${what}), got ${String(value)}`,\n );\n}\n\n/** Two operands, one possibly a literal that takes the other's type. */\nfunction operands(\n name: string,\n a: unknown,\n b: unknown,\n): [Expression, Expression] {\n if (isExpression(a) && isExpression(b)) {\n if (a.type !== b.type)\n throw new TypeError(\n `${name}() takes operands of one type, got '${a.type}' and '${b.type}'; convert one explicitly`,\n );\n return [a, b];\n }\n if (isExpression(a)) return [a, literal(a.type, b)];\n if (isExpression(b)) return [literal(b.type, a), b];\n throw new TypeError(`${name}() needs at least one expression operand`);\n}\n\nfunction unary(\n operator: UnaryOperator,\n a: unknown,\n type?: ExpressionType,\n): Expression {\n requireExpression(a, operator);\n return freeze({ kind: 'unary', type: type ?? a.type, operator, operand: a });\n}\n\nfunction binary(\n operator: BinaryOperator,\n a: unknown,\n b: unknown,\n result?: ExpressionType,\n): Expression {\n const [left, right] = operands(operator, a, b);\n return freeze({\n kind: 'binary',\n type: result ?? left.type,\n operator,\n left,\n right,\n });\n}\n\nfunction chain(\n operator: 'and' | 'or',\n operands: readonly Expression<'boolean'>[],\n): Expression<'boolean'> {\n if (operands.length === 0)\n throw new TypeError(`${operator}() needs an operand`);\n return operands.reduce(\n (left, right) =>\n binary(operator, left, right, 'boolean') as Expression<'boolean'>,\n );\n}\n\nfunction parse(textValue: Text, type: NumericType): Expression {\n if (!isNumericType(type))\n throw new TypeError(`parse() reads a numeric type, not '${String(type)}'`);\n return freeze({ kind: 'parse', type: `${type}?`, operand: text(textValue) });\n}\n\n/** How deep let and map bodies being built are: names their variables. */\nlet bindingDepth = 0;\n\nfunction bind(\n type: ExpressionType,\n body: (value: Expression) => Expression,\n): [string, Expression] {\n if (typeof body !== 'function')\n throw new TypeError('let() and map() take a function that builds the body');\n const variable = `v${bindingDepth}`;\n const value = freeze({ kind: 'variable', type, name: variable });\n bindingDepth++;\n let result: Expression;\n try {\n result = body(value);\n } finally {\n bindingDepth--;\n }\n requireExpression(result, 'body');\n return [variable, result];\n}\n\nconst implementation = {\n int8: (value: number) => literal('int8', value),\n uint8: (value: number) => literal('uint8', value),\n int16: (value: number) => literal('int16', value),\n uint16: (value: number) => literal('uint16', value),\n int32: (value: number) => literal('int32', value),\n uint32: (value: number) => literal('uint32', value),\n int64: (value: bigint) => literal('int64', value),\n uint64: (value: bigint) => literal('uint64', value),\n float32: (value: number) => literal('float32', value),\n float64: (value: number) => literal('float64', value),\n boolean: (value: boolean) => literal('boolean', value),\n string: (value: string) => literal('string', value),\n literal: (type: ScalarType, value: unknown) => literal(type, value),\n null: (type: NumericType) => {\n if (!isNumericType(type))\n throw new TypeError(`null() takes a numeric type, not '${String(type)}'`);\n return literal(`${type}?`, null);\n },\n\n add: (a: unknown, b: unknown) => binary('add', a, b),\n sub: (a: unknown, b: unknown) => binary('sub', a, b),\n mul: (a: unknown, b: unknown) => binary('mul', a, b),\n div: (a: unknown, b: unknown) => binary('div', a, b),\n min: (a: unknown, b: unknown) => binary('min', a, b),\n max: (a: unknown, b: unknown) => binary('max', a, b),\n pow: (a: unknown, b: unknown) => binary('pow', a, b),\n neg: (a: unknown) => unary('neg', a),\n abs: (a: unknown) => unary('abs', a),\n sqrt: (a: unknown) => unary('sqrt', a),\n exp: (a: unknown) => unary('exp', a),\n log: (a: unknown) => unary('log', a),\n floor: (a: unknown) => unary('floor', a),\n ceil: (a: unknown) => unary('ceil', a),\n round: (a: unknown) => unary('round', a),\n convert: (a: unknown, type: NumericType) => {\n requireExpression(a, 'convert');\n if (!isNumericType(type))\n throw new TypeError(\n `convert() turns a number into a numeric type, not '${String(type)}'`,\n );\n return freeze({ kind: 'convert', type, operand: a });\n },\n\n eq: (a: unknown, b: unknown) => binary('eq', a, b, 'boolean'),\n ne: (a: unknown, b: unknown) => binary('ne', a, b, 'boolean'),\n lt: (a: unknown, b: unknown) => binary('lt', a, b, 'boolean'),\n lte: (a: unknown, b: unknown) => binary('lte', a, b, 'boolean'),\n gt: (a: unknown, b: unknown) => binary('gt', a, b, 'boolean'),\n gte: (a: unknown, b: unknown) => binary('gte', a, b, 'boolean'),\n and: (...operands: Expression<'boolean'>[]) => chain('and', operands),\n or: (...operands: Expression<'boolean'>[]) => chain('or', operands),\n not: (a: unknown) => unary('not', a, 'boolean'),\n if: (condition: unknown, then: unknown, otherwise: unknown) => {\n requireExpression(condition, 'if condition');\n const a = typeof then === 'string' ? literal('string', then) : then;\n const b =\n typeof otherwise === 'string' ? literal('string', otherwise) : otherwise;\n requireExpression(a, 'if branch');\n requireExpression(b, 'else branch');\n const type = joinTypes(a.type, b.type);\n if (type === undefined)\n throw new TypeError(\n `if() branches have different types, '${a.type}' and '${b.type}'`,\n );\n return freeze({ kind: 'if', type, condition, then: a, else: b });\n },\n\n fixed: (a: unknown, digits: number) => {\n requireExpression(a, 'fixed');\n return freeze({ kind: 'fixed', type: 'string', operand: a, digits });\n },\n concat: (...parts: Text[]) => {\n if (parts.length === 0) throw new TypeError('concat() needs a part');\n return freeze({\n kind: 'concat',\n type: 'string',\n operands: Object.freeze(parts.map(text)),\n });\n },\n trim: (a: Text) => unary('trim', text(a)),\n lower: (a: Text) => unary('lower', text(a)),\n endsWith: (a: Text, suffix: Text) =>\n binary('endsWith', text(a), text(suffix), 'boolean'),\n removeSuffix: (a: Text, suffix: Text) =>\n binary('removeSuffix', text(a), text(suffix), 'string'),\n parse: (value: Text, type: NumericType) => parse(value, type),\n parseInt8: (value: Text) => parse(value, 'int8'),\n parseUint8: (value: Text) => parse(value, 'uint8'),\n parseInt16: (value: Text) => parse(value, 'int16'),\n parseUint16: (value: Text) => parse(value, 'uint16'),\n parseInt32: (value: Text) => parse(value, 'int32'),\n parseUint32: (value: Text) => parse(value, 'uint32'),\n parseInt64: (value: Text) => parse(value, 'int64'),\n parseUint64: (value: Text) => parse(value, 'uint64'),\n parseFloat32: (value: Text) => parse(value, 'float32'),\n parseFloat64: (value: Text) => parse(value, 'float64'),\n\n isNull: (a: unknown) => {\n requireExpression(a, 'isNull');\n return freeze({ kind: 'isNull', type: 'boolean', operand: a });\n },\n coalesce: (a: unknown, fallback: unknown) => {\n requireExpression(a, 'coalesce');\n if (!isNullableType(a.type))\n throw new TypeError(\n `coalesce() takes a nullable value, not a '${a.type}'`,\n );\n const other = isExpression(fallback)\n ? fallback\n : literal(baseType(a.type), fallback);\n return freeze({\n kind: 'coalesce',\n type: baseType(a.type),\n operand: a,\n fallback: other,\n });\n },\n let: (value: unknown, body: (value: Expression) => Expression) => {\n requireExpression(value, 'let');\n const [variable, result] = bind(value.type, body);\n return freeze({\n kind: 'let',\n type: result.type,\n value,\n variable,\n body: result,\n });\n },\n map: (a: unknown, body: (value: Expression) => Expression) => {\n requireExpression(a, 'map');\n if (!isNullableType(a.type))\n throw new TypeError(`map() takes a nullable value, not a '${a.type}'`);\n const [variable, result] = bind(baseType(a.type), body);\n const type = isNullableType(result.type) ? result.type : `${result.type}?`;\n return freeze({\n kind: 'map',\n type: type as NullableType,\n operand: a,\n variable,\n body: result,\n });\n },\n};\n\n/** The builder, without inputs. */\nexport const expressions: ExpressionBuilder = Object.freeze(\n implementation,\n) as unknown as ExpressionBuilder;\n\n/** An input of an expression context, such as `value`. */\nexport function input<T extends ExpressionType>(\n name: string,\n type: T,\n): Expression<T> {\n return freeze({ kind: 'input', type, name }) as Expression<T>;\n}\n\n/**\n * The builder with the context's inputs as properties: what a callback such\n * as `format: (e) => …` receives.\n */\nexport function createContext<\n const I extends Readonly<Record<string, ExpressionType>>,\n>(inputs: I): ExpressionContext<I> {\n const context: Record<string, unknown> = { ...implementation };\n for (const [name, type] of Object.entries(inputs)) {\n if (name in implementation)\n throw new TypeError(`Input '${name}' would hide the builder's ${name}()`);\n context[name] = input(name, type);\n }\n return Object.freeze(context) as unknown as ExpressionContext<I>;\n}\n","import type { Expression, ExpressionNode } from './ast';\n\n/**\n * `node` with each input named in `replacements` replaced by that\n * expression, of the same type. The variables `node` binds are renamed (with\n * `suffix`), so they never capture a variable of a replacement.\n */\nexport function substituteInputs<T extends Expression>(\n node: T,\n replacements: Readonly<Record<string, Expression>>,\n suffix = 's',\n): T {\n return rewrite(node, replacements, suffix) as T;\n}\n\nfunction rewrite(\n node: ExpressionNode,\n replacements: Readonly<Record<string, Expression>>,\n suffix: string,\n): ExpressionNode {\n const go = (child: ExpressionNode) => rewrite(child, replacements, suffix);\n let result: ExpressionNode;\n switch (node.kind) {\n case 'literal':\n return node;\n case 'input': {\n const replacement = replacements[node.name];\n if (replacement === undefined) return node;\n if (replacement.type !== node.type)\n throw new TypeError(\n `Input '${node.name}' is a '${node.type}', its replacement a '${replacement.type}'`,\n );\n return replacement;\n }\n case 'variable':\n result = { ...node, name: `${node.name}_${suffix}` };\n break;\n case 'unary':\n case 'convert':\n case 'fixed':\n case 'parse':\n case 'isNull':\n result = { ...node, operand: go(node.operand) } as ExpressionNode;\n break;\n case 'binary':\n result = { ...node, left: go(node.left), right: go(node.right) };\n break;\n case 'if':\n result = {\n ...node,\n condition: go(node.condition),\n then: go(node.then),\n else: go(node.else),\n };\n break;\n case 'concat':\n result = { ...node, operands: Object.freeze(node.operands.map(go)) };\n break;\n case 'coalesce':\n result = {\n ...node,\n operand: go(node.operand),\n fallback: go(node.fallback),\n };\n break;\n case 'map':\n result = {\n ...node,\n operand: go(node.operand),\n variable: `${node.variable}_${suffix}`,\n body: go(node.body),\n };\n break;\n case 'let':\n result = {\n ...node,\n value: go(node.value),\n variable: `${node.variable}_${suffix}`,\n body: go(node.body),\n };\n break;\n }\n return Object.freeze(result);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,48 @@
1
1
  {
2
2
  "name": "@soundor/expression",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.17.0",
4
+ "description": "A small, typed, portable expression language and its C++ and JavaScript compilers.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/soundor/soundor.git",
9
+ "directory": "packages/expression"
10
+ },
11
+ "files": [
12
+ "README.md",
13
+ "dist"
14
+ ],
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "main": "./dist/index.mjs",
18
+ "module": "./dist/index.mjs",
19
+ "types": "./dist/index.d.mts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.mts",
23
+ "import": "./dist/index.mjs"
24
+ },
25
+ "./compiler/cpp": {
26
+ "types": "./dist/compiler/cpp.d.mts",
27
+ "import": "./dist/compiler/cpp.mjs"
28
+ },
29
+ "./compiler/js": {
30
+ "types": "./dist/compiler/js.d.mts",
31
+ "import": "./dist/compiler/js.mjs"
32
+ }
33
+ },
34
+ "devDependencies": {
35
+ "@soundor/tsdown-config": "^0.0.0",
36
+ "@soundor/typescript-config": "^0.0.0",
37
+ "@types/node": "^24.19.2",
38
+ "tsdown": "^0.23.7",
39
+ "typescript": "^7.0.2",
40
+ "vitest": "^5.1.0"
41
+ },
42
+ "scripts": {
43
+ "build": "tsc -b && tsdown --clean",
44
+ "dev": "tsdown --watch",
45
+ "test": "vitest run",
46
+ "test:watch": "vitest watch"
47
+ }
6
48
  }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.