@elaraai/east 0.0.1-beta.25 → 0.0.1-beta.27
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/src/analyze.d.ts +3 -0
- package/dist/src/analyze.d.ts.map +1 -1
- package/dist/src/analyze.js +30 -9
- package/dist/src/analyze.js.map +1 -1
- package/dist/src/ast.d.ts +1 -0
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/ast_to_ir.d.ts.map +1 -1
- package/dist/src/ast_to_ir.js +2 -1
- package/dist/src/ast_to_ir.js.map +1 -1
- package/dist/src/builtins.d.ts +1 -1
- package/dist/src/builtins.d.ts.map +1 -1
- package/dist/src/builtins.js +22 -0
- package/dist/src/builtins.js.map +1 -1
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +54 -3
- package/dist/src/compile.js.map +1 -1
- package/dist/src/datetime_format/types.d.ts +23 -23
- package/dist/src/expr/array.d.ts +8 -0
- package/dist/src/expr/array.d.ts.map +1 -1
- package/dist/src/expr/array.js +11 -0
- package/dist/src/expr/array.js.map +1 -1
- package/dist/src/expr/blob.d.ts +8 -0
- package/dist/src/expr/blob.d.ts.map +1 -1
- package/dist/src/expr/blob.js +11 -0
- package/dist/src/expr/blob.js.map +1 -1
- package/dist/src/expr/block.d.ts +179 -1
- package/dist/src/expr/block.d.ts.map +1 -1
- package/dist/src/expr/block.js +468 -1
- package/dist/src/expr/block.js.map +1 -1
- package/dist/src/expr/boolean.d.ts +8 -0
- package/dist/src/expr/boolean.d.ts.map +1 -1
- package/dist/src/expr/boolean.js +11 -0
- package/dist/src/expr/boolean.js.map +1 -1
- package/dist/src/expr/datetime.d.ts +28 -0
- package/dist/src/expr/datetime.d.ts.map +1 -1
- package/dist/src/expr/datetime.js +31 -0
- package/dist/src/expr/datetime.js.map +1 -1
- package/dist/src/expr/dict.d.ts +8 -0
- package/dist/src/expr/dict.d.ts.map +1 -1
- package/dist/src/expr/dict.js +11 -0
- package/dist/src/expr/dict.js.map +1 -1
- package/dist/src/expr/float.d.ts +46 -0
- package/dist/src/expr/float.d.ts.map +1 -1
- package/dist/src/expr/float.js +52 -0
- package/dist/src/expr/float.js.map +1 -1
- package/dist/src/expr/index.d.ts +162 -2
- package/dist/src/expr/index.d.ts.map +1 -1
- package/dist/src/expr/index.js +168 -2
- package/dist/src/expr/index.js.map +1 -1
- package/dist/src/expr/integer.d.ts +73 -0
- package/dist/src/expr/integer.d.ts.map +1 -1
- package/dist/src/expr/integer.js +52 -0
- package/dist/src/expr/integer.js.map +1 -1
- package/dist/src/expr/set.d.ts +8 -0
- package/dist/src/expr/set.d.ts.map +1 -1
- package/dist/src/expr/set.js +11 -0
- package/dist/src/expr/set.js.map +1 -1
- package/dist/src/expr/string.d.ts +28 -0
- package/dist/src/expr/string.d.ts.map +1 -1
- package/dist/src/expr/string.js +31 -0
- package/dist/src/expr/string.js.map +1 -1
- package/dist/src/expr/variant.d.ts +8 -0
- package/dist/src/expr/variant.d.ts.map +1 -1
- package/dist/src/expr/variant.js +11 -0
- package/dist/src/expr/variant.js.map +1 -1
- package/dist/src/fuzz.d.ts +36 -2
- package/dist/src/fuzz.d.ts.map +1 -1
- package/dist/src/fuzz.js +344 -77
- package/dist/src/fuzz.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/internal.d.ts +5 -0
- package/dist/src/internal.d.ts.map +1 -1
- package/dist/src/internal.js +6 -0
- package/dist/src/internal.js.map +1 -1
- package/dist/src/ir.d.ts +1406 -1371
- package/dist/src/ir.d.ts.map +1 -1
- package/dist/src/ir.js +1 -1
- package/dist/src/ir.js.map +1 -1
- package/dist/src/patch/apply.d.ts +15 -0
- package/dist/src/patch/apply.d.ts.map +1 -0
- package/dist/src/patch/apply.js +380 -0
- package/dist/src/patch/apply.js.map +1 -0
- package/dist/src/patch/compose.d.ts +15 -0
- package/dist/src/patch/compose.d.ts.map +1 -0
- package/dist/src/patch/compose.js +480 -0
- package/dist/src/patch/compose.js.map +1 -0
- package/dist/src/patch/diff.d.ts +15 -0
- package/dist/src/patch/diff.d.ts.map +1 -0
- package/dist/src/patch/diff.js +328 -0
- package/dist/src/patch/diff.js.map +1 -0
- package/dist/src/patch/fuzz.d.ts +73 -0
- package/dist/src/patch/fuzz.d.ts.map +1 -0
- package/dist/src/patch/fuzz.js +159 -0
- package/dist/src/patch/fuzz.js.map +1 -0
- package/dist/src/patch/index.d.ts +18 -0
- package/dist/src/patch/index.d.ts.map +1 -0
- package/dist/src/patch/index.js +20 -0
- package/dist/src/patch/index.js.map +1 -0
- package/dist/src/patch/invert.d.ts +15 -0
- package/dist/src/patch/invert.d.ts.map +1 -0
- package/dist/src/patch/invert.js +302 -0
- package/dist/src/patch/invert.js.map +1 -0
- package/dist/src/patch/type_of_patch.d.ts +17 -0
- package/dist/src/patch/type_of_patch.d.ts.map +1 -0
- package/dist/src/patch/type_of_patch.js +143 -0
- package/dist/src/patch/type_of_patch.js.map +1 -0
- package/dist/src/patch/types.d.ts +166 -0
- package/dist/src/patch/types.d.ts.map +1 -0
- package/dist/src/patch/types.js +69 -0
- package/dist/src/patch/types.js.map +1 -0
- package/dist/src/platform.d.ts +6 -0
- package/dist/src/platform.d.ts.map +1 -1
- package/dist/src/serialization/csv.d.ts +17 -17
- package/dist/src/type_of_type.d.ts +34 -34
- package/dist/src/type_of_type.js +1 -1
- package/dist/src/type_of_type.js.map +1 -1
- package/dist/src/types.d.ts +8 -8
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/package.json +1 -2
package/dist/src/expr/block.js
CHANGED
|
@@ -23,8 +23,10 @@ import { RecursiveExpr } from "./recursive.js";
|
|
|
23
23
|
import { createFunctionExpr, FunctionExpr } from "./function.js";
|
|
24
24
|
import { valueOrExprToAst, valueOrExprToAstTyped } from "./ast.js";
|
|
25
25
|
import { toEastTypeValue } from "../type_of_type.js";
|
|
26
|
+
import { isVariant } from "../containers/variant.js";
|
|
26
27
|
import { RefExpr } from "./ref.js";
|
|
27
28
|
import { AsyncFunctionExpr, createAsyncFunctionExpr } from "./asyncfunction.js";
|
|
29
|
+
import { PatchType } from "../patch/index.js";
|
|
28
30
|
/** A factory function to help build `Expr` from AST.
|
|
29
31
|
* We inject this into each concrete `Expr` type so they can create new expressions recursively, without having circular dependencies between JavaScript modules.
|
|
30
32
|
*/
|
|
@@ -833,6 +835,37 @@ export function greaterEqual(left, right) {
|
|
|
833
835
|
arguments: [Expr.ast(left), rightAst],
|
|
834
836
|
});
|
|
835
837
|
}
|
|
838
|
+
// ============================================================================
|
|
839
|
+
// Aliases for standalone comparison functions
|
|
840
|
+
// ============================================================================
|
|
841
|
+
/** Alias for {@link equal} */
|
|
842
|
+
export const equals = equal;
|
|
843
|
+
/** Alias for {@link equal} */
|
|
844
|
+
export const eq = equal;
|
|
845
|
+
/** Alias for {@link notEqual} */
|
|
846
|
+
export const notEquals = notEqual;
|
|
847
|
+
/** Alias for {@link notEqual} */
|
|
848
|
+
export const ne = notEqual;
|
|
849
|
+
/** Alias for {@link less} */
|
|
850
|
+
export const lessThan = less;
|
|
851
|
+
/** Alias for {@link less} */
|
|
852
|
+
export const lt = less;
|
|
853
|
+
/** Alias for {@link lessEqual} */
|
|
854
|
+
export const lessThanOrEqual = lessEqual;
|
|
855
|
+
/** Alias for {@link lessEqual} */
|
|
856
|
+
export const lte = lessEqual;
|
|
857
|
+
/** Alias for {@link lessEqual} */
|
|
858
|
+
export const le = lessEqual;
|
|
859
|
+
/** Alias for {@link greater} */
|
|
860
|
+
export const greaterThan = greater;
|
|
861
|
+
/** Alias for {@link greater} */
|
|
862
|
+
export const gt = greater;
|
|
863
|
+
/** Alias for {@link greaterEqual} */
|
|
864
|
+
export const greaterThanOrEqual = greaterEqual;
|
|
865
|
+
/** Alias for {@link greaterEqual} */
|
|
866
|
+
export const gte = greaterEqual;
|
|
867
|
+
/** Alias for {@link greaterEqual} */
|
|
868
|
+
export const ge = greaterEqual;
|
|
836
869
|
/** Test if the first value is the same object the second.
|
|
837
870
|
* For mutable collections, such as arrays, this means that they are the same object in memory.
|
|
838
871
|
* For immutable data types, such as integers and strings, this is equivalent to equality.
|
|
@@ -860,6 +893,77 @@ export function print(value) {
|
|
|
860
893
|
arguments: [valueAst],
|
|
861
894
|
});
|
|
862
895
|
}
|
|
896
|
+
// ============================================================================
|
|
897
|
+
// Patch Operations
|
|
898
|
+
// ============================================================================
|
|
899
|
+
/** Compute the difference between two values of the same type.
|
|
900
|
+
* Returns a patch that, when applied to `before`, produces `after`.
|
|
901
|
+
*/
|
|
902
|
+
export function diff(before, after) {
|
|
903
|
+
const beforeAst = Expr.ast(before);
|
|
904
|
+
const afterAst = Expr.ast(after);
|
|
905
|
+
const valueType = beforeAst.type;
|
|
906
|
+
const patchType = PatchType(valueType);
|
|
907
|
+
return fromAst({
|
|
908
|
+
ast_type: "Builtin",
|
|
909
|
+
type: patchType,
|
|
910
|
+
location: get_location(2),
|
|
911
|
+
builtin: "Diff",
|
|
912
|
+
type_parameters: [valueType, patchType],
|
|
913
|
+
arguments: [beforeAst, afterAst],
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
/** Apply a patch to a value, producing the modified value.
|
|
917
|
+
* @throws East runtime error if the patch conflicts with the value (e.g., deleting a non-existent key)
|
|
918
|
+
*/
|
|
919
|
+
export function applyPatch(value, patch) {
|
|
920
|
+
const valueAst = Expr.ast(value);
|
|
921
|
+
const patchAst = Expr.ast(patch);
|
|
922
|
+
const valueType = valueAst.type;
|
|
923
|
+
const patchType = patchAst.type;
|
|
924
|
+
return fromAst({
|
|
925
|
+
ast_type: "Builtin",
|
|
926
|
+
type: valueType,
|
|
927
|
+
location: get_location(2),
|
|
928
|
+
builtin: "ApplyPatch",
|
|
929
|
+
type_parameters: [valueType, patchType],
|
|
930
|
+
arguments: [valueAst, patchAst],
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
/** Compose two patches into a single patch.
|
|
934
|
+
* The result is a patch that has the same effect as applying `first` then `second`.
|
|
935
|
+
* @throws East runtime error if the patches are incompatible (second expects different intermediate state)
|
|
936
|
+
*/
|
|
937
|
+
export function composePatch(first, second, type) {
|
|
938
|
+
const firstAst = Expr.ast(first);
|
|
939
|
+
const secondAst = Expr.ast(second);
|
|
940
|
+
const valueType = type;
|
|
941
|
+
const patchType = PatchType(valueType);
|
|
942
|
+
return fromAst({
|
|
943
|
+
ast_type: "Builtin",
|
|
944
|
+
type: patchType,
|
|
945
|
+
location: get_location(2),
|
|
946
|
+
builtin: "ComposePatch",
|
|
947
|
+
type_parameters: [valueType, patchType],
|
|
948
|
+
arguments: [firstAst, secondAst],
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
/** Invert a patch, producing a patch that undoes the original.
|
|
952
|
+
* Applying the inverted patch to the "after" value produces the "before" value.
|
|
953
|
+
*/
|
|
954
|
+
export function invertPatch(patch, type) {
|
|
955
|
+
const patchAst = Expr.ast(patch);
|
|
956
|
+
const valueType = type;
|
|
957
|
+
const patchType = PatchType(valueType);
|
|
958
|
+
return fromAst({
|
|
959
|
+
ast_type: "Builtin",
|
|
960
|
+
type: patchType,
|
|
961
|
+
location: get_location(2),
|
|
962
|
+
builtin: "InvertPatch",
|
|
963
|
+
type_parameters: [valueType, patchType],
|
|
964
|
+
arguments: [patchAst],
|
|
965
|
+
});
|
|
966
|
+
}
|
|
863
967
|
/** Create a callable helper to invoke a synchronous platform function.
|
|
864
968
|
*
|
|
865
969
|
* Platform functions provide access to external capabilities (logging, I/O, database access, etc.)
|
|
@@ -921,6 +1025,7 @@ export function platform(name, input_types, output_type) {
|
|
|
921
1025
|
type: output_type,
|
|
922
1026
|
location: get_location(2),
|
|
923
1027
|
name: name,
|
|
1028
|
+
type_parameters: [],
|
|
924
1029
|
arguments: argAsts,
|
|
925
1030
|
async: false,
|
|
926
1031
|
});
|
|
@@ -1010,6 +1115,7 @@ export function asyncPlatform(name, input_types, output_type) {
|
|
|
1010
1115
|
type: output_type,
|
|
1011
1116
|
location: get_location(2),
|
|
1012
1117
|
name: name,
|
|
1118
|
+
type_parameters: [],
|
|
1013
1119
|
arguments: argAsts,
|
|
1014
1120
|
async: true,
|
|
1015
1121
|
});
|
|
@@ -1039,6 +1145,347 @@ export function asyncPlatform(name, input_types, output_type) {
|
|
|
1039
1145
|
};
|
|
1040
1146
|
return fn;
|
|
1041
1147
|
}
|
|
1148
|
+
// Runtime type substitution function
|
|
1149
|
+
function applyTypeArgs(typeArgs, t) {
|
|
1150
|
+
if (typeof t === 'string') {
|
|
1151
|
+
const ret = typeArgs[t];
|
|
1152
|
+
if (ret === undefined) {
|
|
1153
|
+
throw new Error(`Unexpected type argument ${t}`);
|
|
1154
|
+
}
|
|
1155
|
+
return ret;
|
|
1156
|
+
}
|
|
1157
|
+
else if (t.type === "Ref") {
|
|
1158
|
+
return { type: "Ref", value: applyTypeArgs(typeArgs, t.value) };
|
|
1159
|
+
}
|
|
1160
|
+
else if (t.type === "Array") {
|
|
1161
|
+
return { type: "Array", value: applyTypeArgs(typeArgs, t.value) };
|
|
1162
|
+
}
|
|
1163
|
+
else if (t.type === "Set") {
|
|
1164
|
+
return { type: "Set", key: applyTypeArgs(typeArgs, t.key) };
|
|
1165
|
+
}
|
|
1166
|
+
else if (t.type === "Dict") {
|
|
1167
|
+
return { type: "Dict", key: applyTypeArgs(typeArgs, t.key), value: applyTypeArgs(typeArgs, t.value) };
|
|
1168
|
+
}
|
|
1169
|
+
else if (t.type === "Struct") {
|
|
1170
|
+
const newFields = {};
|
|
1171
|
+
for (const k in t.fields) {
|
|
1172
|
+
newFields[k] = applyTypeArgs(typeArgs, t.fields[k]);
|
|
1173
|
+
}
|
|
1174
|
+
return { type: "Struct", fields: newFields };
|
|
1175
|
+
}
|
|
1176
|
+
else if (t.type === "Variant") {
|
|
1177
|
+
const newCases = {};
|
|
1178
|
+
for (const k in t.cases) {
|
|
1179
|
+
newCases[k] = applyTypeArgs(typeArgs, t.cases[k]);
|
|
1180
|
+
}
|
|
1181
|
+
return { type: "Variant", cases: newCases };
|
|
1182
|
+
}
|
|
1183
|
+
else if (t.type === "Function") {
|
|
1184
|
+
const newInputs = t.inputs.map((inputType) => applyTypeArgs(typeArgs, inputType));
|
|
1185
|
+
const newOutput = applyTypeArgs(typeArgs, t.output);
|
|
1186
|
+
return { type: "Function", inputs: newInputs, output: newOutput };
|
|
1187
|
+
}
|
|
1188
|
+
else if (t.type === "Recursive") {
|
|
1189
|
+
if (t.node === undefined) {
|
|
1190
|
+
// RecursiveTypeMarker (self-reference) - leave alone
|
|
1191
|
+
return t;
|
|
1192
|
+
}
|
|
1193
|
+
return { type: "Recursive", node: applyTypeArgs(typeArgs, t.node) };
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1196
|
+
return t;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
/** Create a callable helper to invoke a generic (polymorphic) platform function.
|
|
1200
|
+
*
|
|
1201
|
+
* Generic platform functions allow you to define platform functions with type parameters,
|
|
1202
|
+
* similar to how builtins work. The type parameters are passed at call time and flow
|
|
1203
|
+
* through to the implementation.
|
|
1204
|
+
*
|
|
1205
|
+
* @param name - The name of the platform function
|
|
1206
|
+
* @param typeParams - Array of type parameter names (e.g., `["T", "U"]`)
|
|
1207
|
+
* @param inputs - Array of input types, can contain string placeholders like `"T"`
|
|
1208
|
+
* @param output - Output type, can be a string placeholder like `"T"`
|
|
1209
|
+
* @returns A callable function that creates Platform AST nodes when invoked
|
|
1210
|
+
*
|
|
1211
|
+
* @example
|
|
1212
|
+
* ```ts
|
|
1213
|
+
* // Define a generic log function
|
|
1214
|
+
* const log = East.genericPlatform(
|
|
1215
|
+
* "log",
|
|
1216
|
+
* ["T"],
|
|
1217
|
+
* ["T"], // Input is type parameter T
|
|
1218
|
+
* NullType
|
|
1219
|
+
* );
|
|
1220
|
+
*
|
|
1221
|
+
* // Use it in East code - type args as array, then value args
|
|
1222
|
+
* const myFunction = East.function([StringType], NullType, ($, s) => {
|
|
1223
|
+
* $(log([StringType], s));
|
|
1224
|
+
* });
|
|
1225
|
+
*
|
|
1226
|
+
* // Implementation receives type params as a factory
|
|
1227
|
+
* const platform = [
|
|
1228
|
+
* log.implement((T) => (value) => {
|
|
1229
|
+
* console.log(printFor(T)(value));
|
|
1230
|
+
* return null;
|
|
1231
|
+
* }),
|
|
1232
|
+
* ];
|
|
1233
|
+
* ```
|
|
1234
|
+
*
|
|
1235
|
+
* @example
|
|
1236
|
+
* ```ts
|
|
1237
|
+
* // Define a generic map function with 2 type parameters
|
|
1238
|
+
* const map = East.genericPlatform(
|
|
1239
|
+
* "map",
|
|
1240
|
+
* ["T", "U"],
|
|
1241
|
+
* ["T", FunctionType(["T"], "U")], // String placeholders in nested types
|
|
1242
|
+
* "U"
|
|
1243
|
+
* );
|
|
1244
|
+
*
|
|
1245
|
+
* // Call with type args array, then value arguments
|
|
1246
|
+
* map([StringType, IntegerType], myString, myMapperFn)
|
|
1247
|
+
* ```
|
|
1248
|
+
*/
|
|
1249
|
+
export function genericPlatform(name, typeParams, inputs, output) {
|
|
1250
|
+
const numTypeParams = typeParams.length;
|
|
1251
|
+
const fn = (type_args, ...valueArgs) => {
|
|
1252
|
+
// Validate type args array
|
|
1253
|
+
if (!Array.isArray(type_args)) {
|
|
1254
|
+
throw new Error(`Generic platform function '${name}' expects type arguments as an array, ` +
|
|
1255
|
+
`got ${typeof type_args}`);
|
|
1256
|
+
}
|
|
1257
|
+
// Validate type args count
|
|
1258
|
+
if (type_args.length !== numTypeParams) {
|
|
1259
|
+
throw new Error(`Generic platform function '${name}' expects ${numTypeParams} type parameters, ` +
|
|
1260
|
+
`got ${type_args.length}`);
|
|
1261
|
+
}
|
|
1262
|
+
// Validate type args are EastTypes
|
|
1263
|
+
for (let i = 0; i < numTypeParams; i++) {
|
|
1264
|
+
const typeArg = type_args[i];
|
|
1265
|
+
if (!typeArg || typeof typeArg !== 'object' || !('type' in typeArg)) {
|
|
1266
|
+
throw new Error(`Generic platform function '${name}' expects type parameter ${i + 1} ` +
|
|
1267
|
+
`(${typeParams[i]}) to be an EastType`);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
// Build type argument map
|
|
1271
|
+
const typeArgMap = {};
|
|
1272
|
+
typeParams.forEach((param, idx) => {
|
|
1273
|
+
typeArgMap[param] = type_args[idx];
|
|
1274
|
+
});
|
|
1275
|
+
// Apply type substitution to get concrete input/output types
|
|
1276
|
+
const inputTypes = inputs.map(t => applyTypeArgs(typeArgMap, t));
|
|
1277
|
+
const outputType = applyTypeArgs(typeArgMap, output);
|
|
1278
|
+
// Validate value args count
|
|
1279
|
+
if (valueArgs.length !== inputTypes.length) {
|
|
1280
|
+
throw new Error(`Generic platform function '${name}' expects ${inputTypes.length} ` +
|
|
1281
|
+
`value arguments, got ${valueArgs.length}`);
|
|
1282
|
+
}
|
|
1283
|
+
// Convert value args to AST with type validation and implicit casts
|
|
1284
|
+
const argAsts = valueArgs.map((arg, index) => {
|
|
1285
|
+
const expectedType = inputTypes[index];
|
|
1286
|
+
let ast = valueOrExprToAstTyped(arg, expectedType);
|
|
1287
|
+
if (ast.type.type === "Never") {
|
|
1288
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got Never type`);
|
|
1289
|
+
}
|
|
1290
|
+
if (!isTypeEqual(ast.type, expectedType)) {
|
|
1291
|
+
if (!isSubtype(ast.type, expectedType)) {
|
|
1292
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got ${printType(ast.type)}`);
|
|
1293
|
+
}
|
|
1294
|
+
// Insert implicit cast
|
|
1295
|
+
ast = {
|
|
1296
|
+
ast_type: "As",
|
|
1297
|
+
type: expectedType,
|
|
1298
|
+
location: get_location(2),
|
|
1299
|
+
value: ast,
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
return ast;
|
|
1303
|
+
});
|
|
1304
|
+
// Create PlatformAST with type_parameters
|
|
1305
|
+
return fromAst({
|
|
1306
|
+
ast_type: "Platform",
|
|
1307
|
+
type: outputType,
|
|
1308
|
+
location: get_location(2),
|
|
1309
|
+
name: name,
|
|
1310
|
+
type_parameters: type_args,
|
|
1311
|
+
arguments: argAsts,
|
|
1312
|
+
async: false,
|
|
1313
|
+
});
|
|
1314
|
+
};
|
|
1315
|
+
fn.implement = (factory) => {
|
|
1316
|
+
return {
|
|
1317
|
+
name,
|
|
1318
|
+
type_parameters: [...typeParams],
|
|
1319
|
+
inputs: [], // Computed at call time via inputsFn
|
|
1320
|
+
output: toEastTypeValue(NullType), // Placeholder
|
|
1321
|
+
inputsFn: (...tps) => {
|
|
1322
|
+
const typeArgMap = {};
|
|
1323
|
+
typeParams.forEach((param, idx) => {
|
|
1324
|
+
typeArgMap[param] = tps[idx];
|
|
1325
|
+
});
|
|
1326
|
+
return inputs.map(t => {
|
|
1327
|
+
if (typeof t === 'string')
|
|
1328
|
+
return typeArgMap[t];
|
|
1329
|
+
let result = applyTypeArgs(typeArgMap, t);
|
|
1330
|
+
if (!isVariant(result))
|
|
1331
|
+
result = toEastTypeValue(result);
|
|
1332
|
+
return result;
|
|
1333
|
+
});
|
|
1334
|
+
},
|
|
1335
|
+
outputsFn: (...tps) => {
|
|
1336
|
+
const typeArgMap = {};
|
|
1337
|
+
typeParams.forEach((param, idx) => {
|
|
1338
|
+
typeArgMap[param] = tps[idx];
|
|
1339
|
+
});
|
|
1340
|
+
if (typeof output === 'string')
|
|
1341
|
+
return typeArgMap[output];
|
|
1342
|
+
let result = applyTypeArgs(typeArgMap, output);
|
|
1343
|
+
if (!isVariant(result))
|
|
1344
|
+
result = toEastTypeValue(result);
|
|
1345
|
+
return result;
|
|
1346
|
+
},
|
|
1347
|
+
type: 'sync',
|
|
1348
|
+
fn: factory,
|
|
1349
|
+
};
|
|
1350
|
+
};
|
|
1351
|
+
return fn;
|
|
1352
|
+
}
|
|
1353
|
+
/** Create a callable helper to invoke an asynchronous generic (polymorphic) platform function.
|
|
1354
|
+
*
|
|
1355
|
+
* This is the async variant of `genericPlatform`. The implementation factory should return
|
|
1356
|
+
* an async function.
|
|
1357
|
+
*
|
|
1358
|
+
* @param name - The name of the platform function
|
|
1359
|
+
* @param typeParams - Array of type parameter names (e.g., `["T", "U"]`)
|
|
1360
|
+
* @param inputs - Array of input types, can contain string placeholders like `"T"`
|
|
1361
|
+
* @param output - Output type, can be a string placeholder like `"T"`
|
|
1362
|
+
* @returns A callable function that creates Platform AST nodes when invoked
|
|
1363
|
+
*
|
|
1364
|
+
* @see {@link genericPlatform} for synchronous generic platform functions
|
|
1365
|
+
*
|
|
1366
|
+
* @example
|
|
1367
|
+
* ```ts
|
|
1368
|
+
* // Define an async generic fetch function
|
|
1369
|
+
* const fetchAs = East.asyncGenericPlatform(
|
|
1370
|
+
* "fetchAs",
|
|
1371
|
+
* ["T"],
|
|
1372
|
+
* [StringType], // URL input
|
|
1373
|
+
* "T" // Returns parsed value of type T
|
|
1374
|
+
* );
|
|
1375
|
+
*
|
|
1376
|
+
* // Implementation receives type params and returns async function
|
|
1377
|
+
* const platform = [
|
|
1378
|
+
* fetchAs.implement((T) => async (url) => {
|
|
1379
|
+
* const response = await fetch(url);
|
|
1380
|
+
* return parseFor(T)(await response.text());
|
|
1381
|
+
* }),
|
|
1382
|
+
* ];
|
|
1383
|
+
* ```
|
|
1384
|
+
*/
|
|
1385
|
+
export function asyncGenericPlatform(name, typeParams, inputs, output) {
|
|
1386
|
+
const numTypeParams = typeParams.length;
|
|
1387
|
+
const fn = (type_args, ...valueArgs) => {
|
|
1388
|
+
// Validate type args array
|
|
1389
|
+
if (!Array.isArray(type_args)) {
|
|
1390
|
+
throw new Error(`Generic platform function '${name}' expects type arguments as an array, ` +
|
|
1391
|
+
`got ${typeof type_args}`);
|
|
1392
|
+
}
|
|
1393
|
+
// Validate type args count
|
|
1394
|
+
if (type_args.length !== numTypeParams) {
|
|
1395
|
+
throw new Error(`Generic platform function '${name}' expects ${numTypeParams} type parameters, ` +
|
|
1396
|
+
`got ${type_args.length}`);
|
|
1397
|
+
}
|
|
1398
|
+
// Validate type args are EastTypes
|
|
1399
|
+
for (let i = 0; i < numTypeParams; i++) {
|
|
1400
|
+
const typeArg = type_args[i];
|
|
1401
|
+
if (!typeArg || typeof typeArg !== 'object' || !('type' in typeArg)) {
|
|
1402
|
+
throw new Error(`Generic platform function '${name}' expects type parameter ${i + 1} ` +
|
|
1403
|
+
`(${typeParams[i]}) to be an EastType`);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
// Build type argument map
|
|
1407
|
+
const typeArgMap = {};
|
|
1408
|
+
typeParams.forEach((param, idx) => {
|
|
1409
|
+
typeArgMap[param] = type_args[idx];
|
|
1410
|
+
});
|
|
1411
|
+
// Apply type substitution to get concrete input/output types
|
|
1412
|
+
const inputTypes = inputs.map(t => applyTypeArgs(typeArgMap, t));
|
|
1413
|
+
const outputType = applyTypeArgs(typeArgMap, output);
|
|
1414
|
+
// Validate value args count
|
|
1415
|
+
if (valueArgs.length !== inputTypes.length) {
|
|
1416
|
+
throw new Error(`Generic platform function '${name}' expects ${inputTypes.length} ` +
|
|
1417
|
+
`value arguments, got ${valueArgs.length}`);
|
|
1418
|
+
}
|
|
1419
|
+
// Convert value args to AST with type validation and implicit casts
|
|
1420
|
+
const argAsts = valueArgs.map((arg, index) => {
|
|
1421
|
+
const expectedType = inputTypes[index];
|
|
1422
|
+
let ast = valueOrExprToAstTyped(arg, expectedType);
|
|
1423
|
+
if (ast.type.type === "Never") {
|
|
1424
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got Never type`);
|
|
1425
|
+
}
|
|
1426
|
+
if (!isTypeEqual(ast.type, expectedType)) {
|
|
1427
|
+
if (!isSubtype(ast.type, expectedType)) {
|
|
1428
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got ${printType(ast.type)}`);
|
|
1429
|
+
}
|
|
1430
|
+
// Insert implicit cast
|
|
1431
|
+
ast = {
|
|
1432
|
+
ast_type: "As",
|
|
1433
|
+
type: expectedType,
|
|
1434
|
+
location: get_location(2),
|
|
1435
|
+
value: ast,
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
return ast;
|
|
1439
|
+
});
|
|
1440
|
+
// Create PlatformAST with type_parameters and async: true
|
|
1441
|
+
return fromAst({
|
|
1442
|
+
ast_type: "Platform",
|
|
1443
|
+
type: outputType,
|
|
1444
|
+
location: get_location(2),
|
|
1445
|
+
name: name,
|
|
1446
|
+
type_parameters: type_args,
|
|
1447
|
+
arguments: argAsts,
|
|
1448
|
+
async: true,
|
|
1449
|
+
});
|
|
1450
|
+
};
|
|
1451
|
+
fn.implement = (factory) => {
|
|
1452
|
+
return {
|
|
1453
|
+
name,
|
|
1454
|
+
type_parameters: [...typeParams],
|
|
1455
|
+
inputs: [], // Computed at call time via inputsFn
|
|
1456
|
+
output: toEastTypeValue(NullType), // Placeholder
|
|
1457
|
+
inputsFn: (...tps) => {
|
|
1458
|
+
const typeArgMap = {};
|
|
1459
|
+
typeParams.forEach((param, idx) => {
|
|
1460
|
+
typeArgMap[param] = tps[idx];
|
|
1461
|
+
});
|
|
1462
|
+
return inputs.map(t => {
|
|
1463
|
+
if (typeof t === 'string')
|
|
1464
|
+
return typeArgMap[t];
|
|
1465
|
+
let result = applyTypeArgs(typeArgMap, t);
|
|
1466
|
+
if (!isVariant(result))
|
|
1467
|
+
result = toEastTypeValue(result);
|
|
1468
|
+
return result;
|
|
1469
|
+
});
|
|
1470
|
+
},
|
|
1471
|
+
outputsFn: (...tps) => {
|
|
1472
|
+
const typeArgMap = {};
|
|
1473
|
+
typeParams.forEach((param, idx) => {
|
|
1474
|
+
typeArgMap[param] = tps[idx];
|
|
1475
|
+
});
|
|
1476
|
+
if (typeof output === 'string')
|
|
1477
|
+
return typeArgMap[output];
|
|
1478
|
+
let result = applyTypeArgs(typeArgMap, output);
|
|
1479
|
+
if (!isVariant(result))
|
|
1480
|
+
result = toEastTypeValue(result);
|
|
1481
|
+
return result;
|
|
1482
|
+
},
|
|
1483
|
+
type: 'async',
|
|
1484
|
+
fn: factory,
|
|
1485
|
+
};
|
|
1486
|
+
};
|
|
1487
|
+
return fn;
|
|
1488
|
+
}
|
|
1042
1489
|
export const BlockBuilder = (return_type) => {
|
|
1043
1490
|
const statements = [];
|
|
1044
1491
|
const $ = ((expr) => {
|
|
@@ -1757,6 +2204,26 @@ Object.assign(Expr, {
|
|
|
1757
2204
|
greater,
|
|
1758
2205
|
greaterEqual,
|
|
1759
2206
|
is,
|
|
1760
|
-
match: matchExpr
|
|
2207
|
+
match: matchExpr,
|
|
2208
|
+
// Comparison aliases
|
|
2209
|
+
equals,
|
|
2210
|
+
eq,
|
|
2211
|
+
notEquals,
|
|
2212
|
+
ne,
|
|
2213
|
+
lessThan,
|
|
2214
|
+
lt,
|
|
2215
|
+
lessThanOrEqual,
|
|
2216
|
+
lte,
|
|
2217
|
+
le,
|
|
2218
|
+
greaterThan,
|
|
2219
|
+
gt,
|
|
2220
|
+
greaterThanOrEqual,
|
|
2221
|
+
gte,
|
|
2222
|
+
ge,
|
|
2223
|
+
// Patch operations
|
|
2224
|
+
diff,
|
|
2225
|
+
applyPatch,
|
|
2226
|
+
composePatch,
|
|
2227
|
+
invertPatch,
|
|
1761
2228
|
});
|
|
1762
2229
|
//# sourceMappingURL=block.js.map
|