@elaraai/east 0.0.1-beta.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.
Files changed (251) hide show
  1. package/LICENSE.md +682 -0
  2. package/README.md +276 -0
  3. package/dist/src/analyze.d.ts +95 -0
  4. package/dist/src/analyze.d.ts.map +1 -0
  5. package/dist/src/analyze.js +1110 -0
  6. package/dist/src/analyze.js.map +1 -0
  7. package/dist/src/ast.d.ts +263 -0
  8. package/dist/src/ast.d.ts.map +1 -0
  9. package/dist/src/ast.js +151 -0
  10. package/dist/src/ast.js.map +1 -0
  11. package/dist/src/ast_to_ir.d.ts +24 -0
  12. package/dist/src/ast_to_ir.d.ts.map +1 -0
  13. package/dist/src/ast_to_ir.js +834 -0
  14. package/dist/src/ast_to_ir.js.map +1 -0
  15. package/dist/src/builtins.d.ts +18 -0
  16. package/dist/src/builtins.d.ts.map +1 -0
  17. package/dist/src/builtins.js +1105 -0
  18. package/dist/src/builtins.js.map +1 -0
  19. package/dist/src/comparison.d.ts +28 -0
  20. package/dist/src/comparison.d.ts.map +1 -0
  21. package/dist/src/comparison.js +1017 -0
  22. package/dist/src/comparison.js.map +1 -0
  23. package/dist/src/compile.d.ts +22 -0
  24. package/dist/src/compile.d.ts.map +1 -0
  25. package/dist/src/compile.js +3260 -0
  26. package/dist/src/compile.js.map +1 -0
  27. package/dist/src/containers/ref.d.ts +106 -0
  28. package/dist/src/containers/ref.d.ts.map +1 -0
  29. package/dist/src/containers/ref.js +100 -0
  30. package/dist/src/containers/ref.js.map +1 -0
  31. package/dist/src/containers/sortedmap.d.ts +165 -0
  32. package/dist/src/containers/sortedmap.d.ts.map +1 -0
  33. package/dist/src/containers/sortedmap.js +237 -0
  34. package/dist/src/containers/sortedmap.js.map +1 -0
  35. package/dist/src/containers/sortedset.d.ts +185 -0
  36. package/dist/src/containers/sortedset.d.ts.map +1 -0
  37. package/dist/src/containers/sortedset.js +312 -0
  38. package/dist/src/containers/sortedset.js.map +1 -0
  39. package/dist/src/containers/variant.d.ts +131 -0
  40. package/dist/src/containers/variant.d.ts.map +1 -0
  41. package/dist/src/containers/variant.js +68 -0
  42. package/dist/src/containers/variant.js.map +1 -0
  43. package/dist/src/datetime_format/parse.d.ts +50 -0
  44. package/dist/src/datetime_format/parse.d.ts.map +1 -0
  45. package/dist/src/datetime_format/parse.js +908 -0
  46. package/dist/src/datetime_format/parse.js.map +1 -0
  47. package/dist/src/datetime_format/print.d.ts +35 -0
  48. package/dist/src/datetime_format/print.d.ts.map +1 -0
  49. package/dist/src/datetime_format/print.js +157 -0
  50. package/dist/src/datetime_format/print.js.map +1 -0
  51. package/dist/src/datetime_format/tokenize.d.ts +76 -0
  52. package/dist/src/datetime_format/tokenize.d.ts.map +1 -0
  53. package/dist/src/datetime_format/tokenize.js +271 -0
  54. package/dist/src/datetime_format/tokenize.js.map +1 -0
  55. package/dist/src/datetime_format/types.d.ts +99 -0
  56. package/dist/src/datetime_format/types.d.ts.map +1 -0
  57. package/dist/src/datetime_format/types.js +103 -0
  58. package/dist/src/datetime_format/types.js.map +1 -0
  59. package/dist/src/datetime_format/validate.d.ts +51 -0
  60. package/dist/src/datetime_format/validate.d.ts.map +1 -0
  61. package/dist/src/datetime_format/validate.js +208 -0
  62. package/dist/src/datetime_format/validate.js.map +1 -0
  63. package/dist/src/default.d.ts +21 -0
  64. package/dist/src/default.d.ts.map +1 -0
  65. package/dist/src/default.js +82 -0
  66. package/dist/src/default.js.map +1 -0
  67. package/dist/src/eastir.d.ts +33 -0
  68. package/dist/src/eastir.d.ts.map +1 -0
  69. package/dist/src/eastir.js +92 -0
  70. package/dist/src/eastir.js.map +1 -0
  71. package/dist/src/error.d.ts +13 -0
  72. package/dist/src/error.d.ts.map +1 -0
  73. package/dist/src/error.js +8 -0
  74. package/dist/src/error.js.map +1 -0
  75. package/dist/src/expr/array.d.ts +1711 -0
  76. package/dist/src/expr/array.d.ts.map +1 -0
  77. package/dist/src/expr/array.js +1805 -0
  78. package/dist/src/expr/array.js.map +1 -0
  79. package/dist/src/expr/ast.d.ts +17 -0
  80. package/dist/src/expr/ast.d.ts.map +1 -0
  81. package/dist/src/expr/ast.js +302 -0
  82. package/dist/src/expr/ast.js.map +1 -0
  83. package/dist/src/expr/blob.d.ts +141 -0
  84. package/dist/src/expr/blob.d.ts.map +1 -0
  85. package/dist/src/expr/blob.js +198 -0
  86. package/dist/src/expr/blob.js.map +1 -0
  87. package/dist/src/expr/block.d.ts +201 -0
  88. package/dist/src/expr/block.d.ts.map +1 -0
  89. package/dist/src/expr/block.js +1505 -0
  90. package/dist/src/expr/block.js.map +1 -0
  91. package/dist/src/expr/boolean.d.ts +207 -0
  92. package/dist/src/expr/boolean.d.ts.map +1 -0
  93. package/dist/src/expr/boolean.js +261 -0
  94. package/dist/src/expr/boolean.js.map +1 -0
  95. package/dist/src/expr/datetime.d.ts +544 -0
  96. package/dist/src/expr/datetime.d.ts.map +1 -0
  97. package/dist/src/expr/datetime.js +980 -0
  98. package/dist/src/expr/datetime.js.map +1 -0
  99. package/dist/src/expr/dict.d.ts +1242 -0
  100. package/dist/src/expr/dict.d.ts.map +1 -0
  101. package/dist/src/expr/dict.js +1492 -0
  102. package/dist/src/expr/dict.js.map +1 -0
  103. package/dist/src/expr/expr.d.ts +95 -0
  104. package/dist/src/expr/expr.d.ts.map +1 -0
  105. package/dist/src/expr/expr.js +171 -0
  106. package/dist/src/expr/expr.js.map +1 -0
  107. package/dist/src/expr/float.d.ts +357 -0
  108. package/dist/src/expr/float.d.ts.map +1 -0
  109. package/dist/src/expr/float.js +637 -0
  110. package/dist/src/expr/float.js.map +1 -0
  111. package/dist/src/expr/function.d.ts +46 -0
  112. package/dist/src/expr/function.d.ts.map +1 -0
  113. package/dist/src/expr/function.js +58 -0
  114. package/dist/src/expr/function.js.map +1 -0
  115. package/dist/src/expr/index.d.ts +450 -0
  116. package/dist/src/expr/index.d.ts.map +1 -0
  117. package/dist/src/expr/index.js +423 -0
  118. package/dist/src/expr/index.js.map +1 -0
  119. package/dist/src/expr/integer.d.ts +256 -0
  120. package/dist/src/expr/integer.d.ts.map +1 -0
  121. package/dist/src/expr/integer.js +311 -0
  122. package/dist/src/expr/integer.js.map +1 -0
  123. package/dist/src/expr/libs/array.d.ts +106 -0
  124. package/dist/src/expr/libs/array.d.ts.map +1 -0
  125. package/dist/src/expr/libs/array.js +140 -0
  126. package/dist/src/expr/libs/array.js.map +1 -0
  127. package/dist/src/expr/libs/blob.d.ts +42 -0
  128. package/dist/src/expr/libs/blob.d.ts.map +1 -0
  129. package/dist/src/expr/libs/blob.js +70 -0
  130. package/dist/src/expr/libs/blob.js.map +1 -0
  131. package/dist/src/expr/libs/datetime.d.ts +479 -0
  132. package/dist/src/expr/libs/datetime.d.ts.map +1 -0
  133. package/dist/src/expr/libs/datetime.js +624 -0
  134. package/dist/src/expr/libs/datetime.js.map +1 -0
  135. package/dist/src/expr/libs/dict.d.ts +66 -0
  136. package/dist/src/expr/libs/dict.d.ts.map +1 -0
  137. package/dist/src/expr/libs/dict.js +77 -0
  138. package/dist/src/expr/libs/dict.js.map +1 -0
  139. package/dist/src/expr/libs/float.d.ts +299 -0
  140. package/dist/src/expr/libs/float.d.ts.map +1 -0
  141. package/dist/src/expr/libs/float.js +564 -0
  142. package/dist/src/expr/libs/float.js.map +1 -0
  143. package/dist/src/expr/libs/integer.d.ts +228 -0
  144. package/dist/src/expr/libs/integer.d.ts.map +1 -0
  145. package/dist/src/expr/libs/integer.js +398 -0
  146. package/dist/src/expr/libs/integer.js.map +1 -0
  147. package/dist/src/expr/libs/set.d.ts +59 -0
  148. package/dist/src/expr/libs/set.d.ts.map +1 -0
  149. package/dist/src/expr/libs/set.js +69 -0
  150. package/dist/src/expr/libs/set.js.map +1 -0
  151. package/dist/src/expr/libs/string.d.ts +71 -0
  152. package/dist/src/expr/libs/string.d.ts.map +1 -0
  153. package/dist/src/expr/libs/string.js +75 -0
  154. package/dist/src/expr/libs/string.js.map +1 -0
  155. package/dist/src/expr/never.d.ts +15 -0
  156. package/dist/src/expr/never.d.ts.map +1 -0
  157. package/dist/src/expr/never.js +12 -0
  158. package/dist/src/expr/never.js.map +1 -0
  159. package/dist/src/expr/null.d.ts +15 -0
  160. package/dist/src/expr/null.d.ts.map +1 -0
  161. package/dist/src/expr/null.js +12 -0
  162. package/dist/src/expr/null.js.map +1 -0
  163. package/dist/src/expr/ref.d.ts +103 -0
  164. package/dist/src/expr/ref.d.ts.map +1 -0
  165. package/dist/src/expr/ref.js +131 -0
  166. package/dist/src/expr/ref.js.map +1 -0
  167. package/dist/src/expr/regex_validation.d.ts +25 -0
  168. package/dist/src/expr/regex_validation.d.ts.map +1 -0
  169. package/dist/src/expr/regex_validation.js +130 -0
  170. package/dist/src/expr/regex_validation.js.map +1 -0
  171. package/dist/src/expr/set.d.ts +1071 -0
  172. package/dist/src/expr/set.d.ts.map +1 -0
  173. package/dist/src/expr/set.js +1137 -0
  174. package/dist/src/expr/set.js.map +1 -0
  175. package/dist/src/expr/string.d.ts +414 -0
  176. package/dist/src/expr/string.d.ts.map +1 -0
  177. package/dist/src/expr/string.js +683 -0
  178. package/dist/src/expr/string.js.map +1 -0
  179. package/dist/src/expr/struct.d.ts +48 -0
  180. package/dist/src/expr/struct.d.ts.map +1 -0
  181. package/dist/src/expr/struct.js +65 -0
  182. package/dist/src/expr/struct.js.map +1 -0
  183. package/dist/src/expr/types.d.ts +68 -0
  184. package/dist/src/expr/types.d.ts.map +1 -0
  185. package/dist/src/expr/types.js +6 -0
  186. package/dist/src/expr/types.js.map +1 -0
  187. package/dist/src/expr/variant.d.ts +137 -0
  188. package/dist/src/expr/variant.d.ts.map +1 -0
  189. package/dist/src/expr/variant.js +105 -0
  190. package/dist/src/expr/variant.js.map +1 -0
  191. package/dist/src/fuzz.d.ts +80 -0
  192. package/dist/src/fuzz.d.ts.map +1 -0
  193. package/dist/src/fuzz.js +300 -0
  194. package/dist/src/fuzz.js.map +1 -0
  195. package/dist/src/index.d.ts +21 -0
  196. package/dist/src/index.d.ts.map +1 -0
  197. package/dist/src/index.js +21 -0
  198. package/dist/src/index.js.map +1 -0
  199. package/dist/src/internal.d.ts +36 -0
  200. package/dist/src/internal.d.ts.map +1 -0
  201. package/dist/src/internal.js +11 -0
  202. package/dist/src/internal.js.map +1 -0
  203. package/dist/src/ir.d.ts +1571 -0
  204. package/dist/src/ir.d.ts.map +1 -0
  205. package/dist/src/ir.js +56 -0
  206. package/dist/src/ir.js.map +1 -0
  207. package/dist/src/location.d.ts +48 -0
  208. package/dist/src/location.d.ts.map +1 -0
  209. package/dist/src/location.js +62 -0
  210. package/dist/src/location.js.map +1 -0
  211. package/dist/src/platform.d.ts +21 -0
  212. package/dist/src/platform.d.ts.map +1 -0
  213. package/dist/src/platform.js +8 -0
  214. package/dist/src/platform.js.map +1 -0
  215. package/dist/src/serialization/beast.d.ts +39 -0
  216. package/dist/src/serialization/beast.d.ts.map +1 -0
  217. package/dist/src/serialization/beast.js +555 -0
  218. package/dist/src/serialization/beast.js.map +1 -0
  219. package/dist/src/serialization/beast2-stream.d.ts +38 -0
  220. package/dist/src/serialization/beast2-stream.d.ts.map +1 -0
  221. package/dist/src/serialization/beast2-stream.js +665 -0
  222. package/dist/src/serialization/beast2-stream.js.map +1 -0
  223. package/dist/src/serialization/beast2.d.ts +41 -0
  224. package/dist/src/serialization/beast2.d.ts.map +1 -0
  225. package/dist/src/serialization/beast2.js +489 -0
  226. package/dist/src/serialization/beast2.js.map +1 -0
  227. package/dist/src/serialization/binary-utils.d.ts +151 -0
  228. package/dist/src/serialization/binary-utils.d.ts.map +1 -0
  229. package/dist/src/serialization/binary-utils.js +929 -0
  230. package/dist/src/serialization/binary-utils.js.map +1 -0
  231. package/dist/src/serialization/east.d.ts +84 -0
  232. package/dist/src/serialization/east.d.ts.map +1 -0
  233. package/dist/src/serialization/east.js +1802 -0
  234. package/dist/src/serialization/east.js.map +1 -0
  235. package/dist/src/serialization/index.d.ts +11 -0
  236. package/dist/src/serialization/index.d.ts.map +1 -0
  237. package/dist/src/serialization/index.js +12 -0
  238. package/dist/src/serialization/index.js.map +1 -0
  239. package/dist/src/serialization/json.d.ts +36 -0
  240. package/dist/src/serialization/json.d.ts.map +1 -0
  241. package/dist/src/serialization/json.js +849 -0
  242. package/dist/src/serialization/json.js.map +1 -0
  243. package/dist/src/type_of_type.d.ts +115 -0
  244. package/dist/src/type_of_type.d.ts.map +1 -0
  245. package/dist/src/type_of_type.js +362 -0
  246. package/dist/src/type_of_type.js.map +1 -0
  247. package/dist/src/types.d.ts +648 -0
  248. package/dist/src/types.d.ts.map +1 -0
  249. package/dist/src/types.js +1631 -0
  250. package/dist/src/types.js.map +1 -0
  251. package/package.json +87 -0
@@ -0,0 +1,1137 @@
1
+ import { get_location } from "../location.js";
2
+ import { SetType, BooleanType, FunctionType, IntegerType, NullType, NeverType, DictType, printType, FloatType, isTypeEqual, ArrayType, VariantType } from "../types.js";
3
+ import { valueOrExprToAst, valueOrExprToAstTyped } from "./ast.js";
4
+ import { AstSymbol, Expr, TypeSymbol } from "./expr.js";
5
+ import { none, some } from "../containers/variant.js";
6
+ /**
7
+ * Expression representing set (sorted unique collection) values and operations.
8
+ *
9
+ * SetExpr provides methods for working with sorted sets including membership testing, insertion,
10
+ * deletion, iteration, mapping, filtering, set operations (union, intersection, difference), and
11
+ * aggregation operations. Sets maintain their elements sorted by key using East's total ordering
12
+ * and guarantee uniqueness.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Creating and manipulating sets
17
+ * const buildSet = East.function([ArrayType(StringType)], SetType(StringType), ($, items) => {
18
+ * const uniqueItems = Expr.from(new Set(), SetType(StringType));
19
+ * $(items.forEach(($, item) => {
20
+ * $(uniqueItems.tryInsert(item));
21
+ * }));
22
+ * $.return(uniqueItems);
23
+ * });
24
+ * const compiled = East.compile(buildSet.toIR(), []);
25
+ * compiled(["apple", "banana", "apple", "cherry"]); // Set(["apple", "banana", "cherry"])
26
+ * ```
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * // Set operations
31
+ * const unionSets = East.function([SetType(IntegerType), SetType(IntegerType)], SetType(IntegerType), ($, set1, set2) => {
32
+ * $.return(set1.union(set2));
33
+ * });
34
+ * const compiled = East.compile(unionSets.toIR(), []);
35
+ * compiled(new Set([1n, 2n, 3n]), new Set([3n, 4n, 5n])); // Set([1n, 2n, 3n, 4n, 5n])
36
+ * ```
37
+ */
38
+ export class SetExpr extends Expr {
39
+ key_type;
40
+ constructor(key_type, ast, createExpr) {
41
+ super(ast.type, ast, createExpr);
42
+ this.key_type = key_type;
43
+ }
44
+ /**
45
+ * Returns the number of elements in the set.
46
+ *
47
+ * @returns An IntegerExpr representing the count of elements
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const getSize = East.function([SetType(StringType)], IntegerType, ($, set) => {
52
+ * $.return(set.size());
53
+ * });
54
+ * const compiled = East.compile(getSize.toIR(), []);
55
+ * compiled(new Set(["a", "b", "c"])); // 3n
56
+ * compiled(new Set()); // 0n
57
+ * ```
58
+ */
59
+ size() {
60
+ return Expr.fromAst({
61
+ ast_type: "Builtin",
62
+ type: IntegerType,
63
+ location: get_location(2),
64
+ builtin: "SetSize",
65
+ type_parameters: [this.key_type],
66
+ arguments: [this[AstSymbol]],
67
+ });
68
+ }
69
+ /**
70
+ * Checks if an element exists in the set.
71
+ *
72
+ * @param key - The element to search for
73
+ * @returns A BooleanExpr that is true if the element exists, false otherwise
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const hasElement = East.function([SetType(StringType), StringType], BooleanType, ($, set, element) => {
78
+ * $.return(set.has(element));
79
+ * });
80
+ * const compiled = East.compile(hasElement.toIR(), []);
81
+ * const set = new Set(["a", "b", "c"]);
82
+ * compiled(set, "b"); // true
83
+ * compiled(set, "d"); // false
84
+ * ```
85
+ */
86
+ has(key) {
87
+ const valueAst = valueOrExprToAstTyped(key, this.key_type);
88
+ return Expr.fromAst({
89
+ ast_type: "Builtin",
90
+ type: BooleanType,
91
+ location: get_location(2),
92
+ builtin: "SetHas",
93
+ type_parameters: [this.key_type],
94
+ arguments: [this[AstSymbol], valueAst],
95
+ });
96
+ }
97
+ /**
98
+ * Inserts a new element into the set.
99
+ *
100
+ * @param key - The element to insert
101
+ * @returns A NullExpr
102
+ *
103
+ * @throws East runtime error if the element already exists in the set
104
+ *
105
+ * @see {@link tryInsert} for a version that doesn't error on duplicates
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * const insertElement = East.function([SetType(StringType), StringType], NullType, ($, set, element) => {
110
+ * $(set.insert(element));
111
+ * $.return(null);
112
+ * });
113
+ * const compiled = East.compile(insertElement.toIR(), []);
114
+ * const set = new Set(["a", "b"]);
115
+ * compiled(set, "c"); // set now has Set(["a", "b", "c"])
116
+ * // compiled(set, "a") would throw error (duplicate element)
117
+ * ```
118
+ */
119
+ insert(key) {
120
+ const location = get_location(2);
121
+ const keyAst = valueOrExprToAstTyped(key, this.key_type);
122
+ return Expr.fromAst({
123
+ ast_type: "Builtin",
124
+ type: NullType,
125
+ location,
126
+ builtin: "SetInsert",
127
+ type_parameters: [this.key_type],
128
+ arguments: [this[AstSymbol], keyAst],
129
+ });
130
+ }
131
+ /**
132
+ * Tries to insert an element into the set, returning whether it was inserted.
133
+ *
134
+ * @param key - The element to insert
135
+ * @returns A BooleanExpr that is true if the element was inserted, false if it already existed
136
+ *
137
+ * @see {@link insert} for a version that errors on duplicates
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * const tryInsertElement = East.function([SetType(StringType), StringType], BooleanType, ($, set, element) => {
142
+ * $.return(set.tryInsert(element));
143
+ * });
144
+ * const compiled = East.compile(tryInsertElement.toIR(), []);
145
+ * const set = new Set(["a", "b"]);
146
+ * compiled(set, "c"); // true (set now has Set(["a", "b", "c"]))
147
+ * compiled(set, "a"); // false (element already exists, set unchanged)
148
+ * ```
149
+ */
150
+ tryInsert(key) {
151
+ const keyAst = valueOrExprToAstTyped(key, this.key_type);
152
+ return Expr.fromAst({
153
+ ast_type: "Builtin",
154
+ type: BooleanType,
155
+ location: get_location(2),
156
+ builtin: "SetTryInsert",
157
+ type_parameters: [this.key_type],
158
+ arguments: [this[AstSymbol], keyAst],
159
+ });
160
+ }
161
+ /**
162
+ * Deletes an element from the set.
163
+ *
164
+ * @param key - The element to delete
165
+ * @returns A NullExpr
166
+ *
167
+ * @throws East runtime error if the element does not exist
168
+ *
169
+ * @see {@link tryDelete} for a version that doesn't error on missing elements
170
+ * @see {@link clear} to remove all elements
171
+ *
172
+ * @example
173
+ * ```ts
174
+ * const deleteElement = East.function([SetType(StringType), StringType], NullType, ($, set, element) => {
175
+ * $(set.delete(element));
176
+ * $.return(null);
177
+ * });
178
+ * const compiled = East.compile(deleteElement.toIR(), []);
179
+ * const set = new Set(["a", "b", "c"]);
180
+ * compiled(set, "b"); // set now has Set(["a", "c"])
181
+ * // compiled(set, "d") would throw error (element not found)
182
+ * ```
183
+ */
184
+ delete(key) {
185
+ const location = get_location(2);
186
+ const keyAst = valueOrExprToAstTyped(key, this.key_type);
187
+ return Expr.fromAst({
188
+ ast_type: "Builtin",
189
+ type: NullType,
190
+ location,
191
+ builtin: "SetDelete",
192
+ type_parameters: [this.key_type],
193
+ arguments: [this[AstSymbol], keyAst],
194
+ });
195
+ }
196
+ /**
197
+ * Tries to delete an element from the set, returning whether it was deleted.
198
+ *
199
+ * @param key - The element to delete
200
+ * @returns A BooleanExpr that is true if the element was deleted, false if it didn't exist
201
+ *
202
+ * @see {@link delete} for a version that errors on missing elements
203
+ *
204
+ * @example
205
+ * ```ts
206
+ * const tryDeleteElement = East.function([SetType(StringType), StringType], BooleanType, ($, set, element) => {
207
+ * $.return(set.tryDelete(element));
208
+ * });
209
+ * const compiled = East.compile(tryDeleteElement.toIR(), []);
210
+ * const set = new Set(["a", "b", "c"]);
211
+ * compiled(set, "b"); // true (set now has Set(["a", "c"]))
212
+ * compiled(set, "d"); // false (element not found, set unchanged)
213
+ * ```
214
+ */
215
+ tryDelete(key) {
216
+ const keyAst = valueOrExprToAstTyped(key, this.key_type);
217
+ return Expr.fromAst({
218
+ ast_type: "Builtin",
219
+ type: BooleanType,
220
+ location: get_location(2),
221
+ builtin: "SetTryDelete",
222
+ type_parameters: [this.key_type],
223
+ arguments: [this[AstSymbol], keyAst],
224
+ });
225
+ }
226
+ /**
227
+ * Removes all elements from the set.
228
+ *
229
+ * @returns A NullExpr
230
+ *
231
+ * @see {@link delete} or {@link tryDelete} to remove individual elements
232
+ *
233
+ * @example
234
+ * ```ts
235
+ * const clearSet = East.function([SetType(StringType)], NullType, ($, set) => {
236
+ * $(set.clear());
237
+ * $.return(null);
238
+ * });
239
+ * const compiled = East.compile(clearSet.toIR(), []);
240
+ * const set = new Set(["a", "b", "c"]);
241
+ * compiled(set); // set is now Set([])
242
+ * ```
243
+ */
244
+ clear() {
245
+ return Expr.fromAst({
246
+ ast_type: "Builtin",
247
+ type: NullType,
248
+ location: get_location(2),
249
+ builtin: "SetClear",
250
+ type_parameters: [this.key_type],
251
+ arguments: [this[AstSymbol]],
252
+ });
253
+ }
254
+ /**
255
+ * Unions another set into this one in place.
256
+ *
257
+ * @param other - The set whose elements to add to this set
258
+ * @returns A NullExpr
259
+ *
260
+ * @see {@link union} for a version that returns a new set
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * const unionInPlace = East.function([SetType(IntegerType), SetType(IntegerType)], NullType, ($, set1, set2) => {
265
+ * $(set1.unionInPlace(set2));
266
+ * $.return(null);
267
+ * });
268
+ * const compiled = East.compile(unionInPlace.toIR(), []);
269
+ * const set1 = new Set([1n, 2n, 3n]);
270
+ * const set2 = new Set([3n, 4n, 5n]);
271
+ * compiled(set1, set2); // set1 now has Set([1n, 2n, 3n, 4n, 5n])
272
+ * ```
273
+ */
274
+ unionInPlace(other) {
275
+ const otherAst = valueOrExprToAstTyped(other, this[TypeSymbol]);
276
+ return Expr.fromAst({
277
+ ast_type: "Builtin",
278
+ type: NullType,
279
+ location: get_location(2),
280
+ builtin: "SetUnionInPlace",
281
+ type_parameters: [this.key_type],
282
+ arguments: [this[AstSymbol], otherAst],
283
+ });
284
+ }
285
+ /**
286
+ * Returns the union of two sets (all elements from both sets).
287
+ *
288
+ * @param other - The set to union with this set
289
+ * @returns A new SetExpr containing all elements from both sets
290
+ *
291
+ * @see {@link unionInPlace} to modify this set in place
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * const unionSets = East.function([SetType(IntegerType), SetType(IntegerType)], SetType(IntegerType), ($, set1, set2) => {
296
+ * $.return(set1.union(set2));
297
+ * });
298
+ * const compiled = East.compile(unionSets.toIR(), []);
299
+ * compiled(new Set([1n, 2n, 3n]), new Set([3n, 4n, 5n])); // Set([1n, 2n, 3n, 4n, 5n])
300
+ * ```
301
+ */
302
+ union(other) {
303
+ const otherAst = valueOrExprToAstTyped(other, this[TypeSymbol]);
304
+ return Expr.fromAst({
305
+ ast_type: "Builtin",
306
+ type: this[TypeSymbol],
307
+ location: get_location(2),
308
+ builtin: "SetUnion",
309
+ type_parameters: [this.key_type],
310
+ arguments: [this[AstSymbol], otherAst],
311
+ });
312
+ }
313
+ /**
314
+ * Returns the intersection of two sets (elements common to both).
315
+ *
316
+ * @param other - The set to intersect with this set
317
+ * @returns A new SetExpr containing only elements present in both sets
318
+ *
319
+ * @example
320
+ * ```ts
321
+ * const intersectSets = East.function([SetType(IntegerType), SetType(IntegerType)], SetType(IntegerType), ($, set1, set2) => {
322
+ * $.return(set1.intersection(set2));
323
+ * });
324
+ * const compiled = East.compile(intersectSets.toIR(), []);
325
+ * compiled(new Set([1n, 2n, 3n]), new Set([2n, 3n, 4n])); // Set([2n, 3n])
326
+ * ```
327
+ */
328
+ intersection(other) {
329
+ const otherAst = valueOrExprToAstTyped(other, this[TypeSymbol]);
330
+ return Expr.fromAst({
331
+ ast_type: "Builtin",
332
+ type: this[TypeSymbol],
333
+ location: get_location(2),
334
+ builtin: "SetIntersect",
335
+ type_parameters: [this.key_type],
336
+ arguments: [this[AstSymbol], otherAst],
337
+ });
338
+ }
339
+ /**
340
+ * Returns the difference between two sets (elements in this set but not in the other).
341
+ *
342
+ * @param other - The set to subtract from this set
343
+ * @returns A new SetExpr containing elements in this set but not in the other
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * const diffSets = East.function([SetType(IntegerType), SetType(IntegerType)], SetType(IntegerType), ($, set1, set2) => {
348
+ * $.return(set1.difference(set2));
349
+ * });
350
+ * const compiled = East.compile(diffSets.toIR(), []);
351
+ * compiled(new Set([1n, 2n, 3n]), new Set([2n, 3n, 4n])); // Set([1n])
352
+ * ```
353
+ */
354
+ difference(other) {
355
+ const otherAst = valueOrExprToAstTyped(other, this[TypeSymbol]);
356
+ return Expr.fromAst({
357
+ ast_type: "Builtin",
358
+ type: this[TypeSymbol],
359
+ location: get_location(2),
360
+ builtin: "SetDiff",
361
+ type_parameters: [this.key_type],
362
+ arguments: [this[AstSymbol], otherAst],
363
+ });
364
+ }
365
+ /**
366
+ * Returns the symmetric difference between two sets (elements in either set but not in both).
367
+ *
368
+ * @param other - The set to compute symmetric difference with
369
+ * @returns A new SetExpr containing elements in either set but not in both
370
+ *
371
+ * @example
372
+ * ```ts
373
+ * const symDiffSets = East.function([SetType(IntegerType), SetType(IntegerType)], SetType(IntegerType), ($, set1, set2) => {
374
+ * $.return(set1.symmetricDifference(set2));
375
+ * });
376
+ * const compiled = East.compile(symDiffSets.toIR(), []);
377
+ * compiled(new Set([1n, 2n, 3n]), new Set([2n, 3n, 4n])); // Set([1n, 4n])
378
+ * ```
379
+ */
380
+ symmetricDifference(other) {
381
+ const otherAst = valueOrExprToAstTyped(other, this[TypeSymbol]);
382
+ return Expr.fromAst({
383
+ ast_type: "Builtin",
384
+ type: this[TypeSymbol],
385
+ location: get_location(2),
386
+ builtin: "SetSymDiff",
387
+ type_parameters: [this.key_type],
388
+ arguments: [this[AstSymbol], otherAst],
389
+ });
390
+ }
391
+ /**
392
+ * Checks if this set is a subset of another set (all elements in this set are in the other).
393
+ *
394
+ * @param other - The set to check against
395
+ * @returns A BooleanExpr that is true if this set is a subset of the other
396
+ *
397
+ * @example
398
+ * ```ts
399
+ * const checkSubset = East.function([SetType(IntegerType), SetType(IntegerType)], BooleanType, ($, set1, set2) => {
400
+ * $.return(set1.isSubsetOf(set2));
401
+ * });
402
+ * const compiled = East.compile(checkSubset.toIR(), []);
403
+ * compiled(new Set([1n, 2n]), new Set([1n, 2n, 3n])); // true
404
+ * compiled(new Set([1n, 4n]), new Set([1n, 2n, 3n])); // false
405
+ * ```
406
+ */
407
+ isSubsetOf(other) {
408
+ const otherAst = valueOrExprToAstTyped(other, this[TypeSymbol]);
409
+ return Expr.fromAst({
410
+ ast_type: "Builtin",
411
+ type: BooleanType,
412
+ location: get_location(2),
413
+ builtin: "SetIsSubset",
414
+ type_parameters: [this.key_type],
415
+ arguments: [this[AstSymbol], otherAst],
416
+ });
417
+ }
418
+ /**
419
+ * Checks if this set is a superset of another set (all elements in the other set are in this set).
420
+ *
421
+ * @param other - The set to check against
422
+ * @returns A BooleanExpr that is true if this set is a superset of the other
423
+ *
424
+ * @example
425
+ * ```ts
426
+ * const checkSuperset = East.function([SetType(IntegerType), SetType(IntegerType)], BooleanType, ($, set1, set2) => {
427
+ * $.return(set1.isSupersetOf(set2));
428
+ * });
429
+ * const compiled = East.compile(checkSuperset.toIR(), []);
430
+ * compiled(new Set([1n, 2n, 3n]), new Set([1n, 2n])); // true
431
+ * compiled(new Set([1n, 2n]), new Set([1n, 2n, 3n])); // false
432
+ * ```
433
+ */
434
+ isSupersetOf(other) {
435
+ const otherAst = valueOrExprToAstTyped(other, this[TypeSymbol]);
436
+ return Expr.fromAst({
437
+ ast_type: "Builtin",
438
+ type: BooleanType,
439
+ location: get_location(2),
440
+ builtin: "SetIsSubset",
441
+ type_parameters: [this.key_type],
442
+ arguments: [otherAst, this[AstSymbol]], // Note: arguments swapped for superset
443
+ });
444
+ }
445
+ /**
446
+ * Checks if this set is disjoint from another set (no common elements).
447
+ *
448
+ * @param other - The set to check against
449
+ * @returns A BooleanExpr that is true if the sets have no elements in common
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * const checkDisjoint = East.function([SetType(IntegerType), SetType(IntegerType)], BooleanType, ($, set1, set2) => {
454
+ * $.return(set1.isDisjointFrom(set2));
455
+ * });
456
+ * const compiled = East.compile(checkDisjoint.toIR(), []);
457
+ * compiled(new Set([1n, 2n]), new Set([3n, 4n])); // true
458
+ * compiled(new Set([1n, 2n]), new Set([2n, 3n])); // false
459
+ * ```
460
+ */
461
+ isDisjointFrom(other) {
462
+ const otherAst = valueOrExprToAstTyped(other, this[TypeSymbol]);
463
+ return Expr.fromAst({
464
+ ast_type: "Builtin",
465
+ type: BooleanType,
466
+ location: get_location(2),
467
+ builtin: "SetIsDisjoint",
468
+ type_parameters: [this.key_type],
469
+ arguments: [this[AstSymbol], otherAst],
470
+ });
471
+ }
472
+ /**
473
+ * Creates a shallow copy of the set.
474
+ *
475
+ * @returns A new SetExpr containing the same elements
476
+ *
477
+ * @example
478
+ * ```ts
479
+ * const copySet = East.function([SetType(StringType)], SetType(StringType), ($, set) => {
480
+ * $.return(set.copy());
481
+ * });
482
+ * const compiled = East.compile(copySet.toIR(), []);
483
+ * const set = new Set(["a", "b", "c"]);
484
+ * const copy = compiled(set); // Set(["a", "b", "c"])
485
+ * // Modifying copy doesn't affect set
486
+ * ```
487
+ */
488
+ copy() {
489
+ // Note that keys are immutable so shallow and deep copy are the same
490
+ return Expr.fromAst({
491
+ ast_type: "Builtin",
492
+ type: this[TypeSymbol],
493
+ location: get_location(2),
494
+ builtin: "SetCopy",
495
+ type_parameters: [this.key_type],
496
+ arguments: [this[AstSymbol]],
497
+ });
498
+ }
499
+ /**
500
+ * Filters the set using a predicate function.
501
+ *
502
+ * @param pred - Function that returns true to keep an element, false to discard it
503
+ * @returns A new SetExpr containing only elements for which the predicate returned true
504
+ *
505
+ * @example
506
+ * ```ts
507
+ * const filterEven = East.function([SetType(IntegerType)], SetType(IntegerType), ($, set) => {
508
+ * $.return(set.filter(($, x) => x.modulo(2n).equal(0n)));
509
+ * });
510
+ * const compiled = East.compile(filterEven.toIR(), []);
511
+ * compiled(new Set([1n, 2n, 3n, 4n, 5n, 6n])); // Set([2n, 4n, 6n])
512
+ * ```
513
+ */
514
+ filter(pred) {
515
+ const predExpr = Expr.from(pred, FunctionType([this.key_type], BooleanType, null));
516
+ return Expr.fromAst({
517
+ ast_type: "Builtin",
518
+ type: this[TypeSymbol],
519
+ location: get_location(2),
520
+ builtin: "SetFilter",
521
+ type_parameters: [this.key_type],
522
+ arguments: [this[AstSymbol], Expr.ast(predExpr)],
523
+ });
524
+ }
525
+ filterMap(fn) {
526
+ let fnExpr;
527
+ if (typeof fn === "function") {
528
+ fnExpr = Expr.function([this.key_type], undefined, fn);
529
+ }
530
+ else {
531
+ fnExpr = fn;
532
+ }
533
+ const fnType = fnExpr[TypeSymbol];
534
+ const returnType = fnType.output;
535
+ // Extract V2 from the option type
536
+ if (returnType.type !== "Variant" || !("some" in returnType.cases)) {
537
+ throw new Error(`filterMap function must return an option type (variant with 'none' and 'some'), got ${printType(returnType)}`);
538
+ }
539
+ const valueType = returnType.cases.some;
540
+ return Expr.fromAst({
541
+ ast_type: "Builtin",
542
+ type: DictType(this.key_type, valueType),
543
+ location: get_location(2),
544
+ builtin: "SetFilterMap",
545
+ type_parameters: [this.key_type, valueType],
546
+ arguments: [this[AstSymbol], Expr.ast(fnExpr)],
547
+ });
548
+ }
549
+ firstMap(fn) {
550
+ const fnAst = valueOrExprToAstTyped(fn, FunctionType([this.key_type], undefined, null));
551
+ const returnType = fnAst.type.output;
552
+ if (returnType.type !== "Variant") {
553
+ throw new Error(`Expected Function to return an Option type, got ${printType(returnType)}`);
554
+ }
555
+ if (!Object.keys(returnType.cases).every(k => k === "none" || k === "some")) {
556
+ throw new Error(`Expected Function to return an Option type, got ${printType(returnType)}`);
557
+ }
558
+ const someType = returnType.cases["some"] ?? NeverType;
559
+ return Expr.fromAst({
560
+ ast_type: "Builtin",
561
+ type: returnType,
562
+ location: get_location(2),
563
+ builtin: "SetFirstMap",
564
+ type_parameters: [this.key_type, someType],
565
+ arguments: [this[AstSymbol], fnAst],
566
+ });
567
+ }
568
+ /**
569
+ * Iterates over each element in the set, applying a function to each.
570
+ *
571
+ * @param fn - Function to apply to each element
572
+ * @returns A NullExpr
573
+ *
574
+ * @example
575
+ * ```ts
576
+ * const printElements = East.function([SetType(StringType)], NullType, ($, set) => {
577
+ * $(set.forEach(($, element) => {
578
+ * // In a real platform, you could use a platform function to log
579
+ * }));
580
+ * $.return(null);
581
+ * });
582
+ * const compiled = East.compile(printElements.toIR(), []);
583
+ * compiled(new Set(["a", "b", "c"])); // Iterates over all elements
584
+ * ```
585
+ */
586
+ forEach(fn) {
587
+ const fnExpr = Expr.function([this.key_type], undefined, fn);
588
+ const fnType = fnExpr[TypeSymbol];
589
+ const returnType = fnType.output;
590
+ return Expr.fromAst({
591
+ ast_type: "Builtin",
592
+ type: NullType,
593
+ location: get_location(2),
594
+ builtin: "SetForEach",
595
+ type_parameters: [this.key_type, returnType],
596
+ arguments: [this[AstSymbol], Expr.ast(fnExpr)],
597
+ });
598
+ }
599
+ map(fn) {
600
+ let fnExpr;
601
+ if (typeof fn === "function") {
602
+ fnExpr = Expr.function([this.key_type], undefined, fn);
603
+ }
604
+ else {
605
+ fnExpr = fn;
606
+ }
607
+ const fnType = fnExpr[TypeSymbol];
608
+ const returnType = fnType.output;
609
+ return Expr.fromAst({
610
+ ast_type: "Builtin",
611
+ type: DictType(this.key_type, returnType),
612
+ location: get_location(2),
613
+ builtin: "SetMap",
614
+ type_parameters: [this.key_type, returnType],
615
+ arguments: [this[AstSymbol], Expr.ast(fnExpr)],
616
+ });
617
+ }
618
+ mapReduce(mapFn, combineFn) {
619
+ const mapAst = valueOrExprToAstTyped(mapFn, FunctionType([this.key_type], undefined, null));
620
+ const mapType = mapAst.type.output;
621
+ const combineAst = valueOrExprToAstTyped(combineFn, FunctionType([mapType, mapType], mapType, null));
622
+ return Expr.fromAst({
623
+ ast_type: "Builtin",
624
+ type: mapType,
625
+ location: get_location(2),
626
+ builtin: "SetMapReduce",
627
+ type_parameters: [this.key_type, mapType],
628
+ arguments: [this[AstSymbol], mapAst, combineAst],
629
+ });
630
+ }
631
+ /**
632
+ * Reduces the set to a single value using an accumulator function.
633
+ *
634
+ * @param fn - Function accepting (accumulator, element) and returning the new accumulator value
635
+ * @param init - Initial value for the accumulator
636
+ * @returns The final accumulated value
637
+ *
638
+ * @see {@link mapReduce} for a version that projects elements before combining
639
+ *
640
+ * @example
641
+ * ```ts
642
+ * const sumSet = East.function([SetType(IntegerType)], IntegerType, ($, set) => {
643
+ * $.return(set.reduce(($, acc, element) => acc.add(element), 0n));
644
+ * });
645
+ * const compiled = East.compile(sumSet.toIR(), []);
646
+ * compiled(new Set([1n, 2n, 3n, 4n])); // 10n
647
+ * ```
648
+ */
649
+ reduce(fn, init) {
650
+ const initAst = valueOrExprToAst(init);
651
+ const returnType = initAst.type;
652
+ const fnExpr = Expr.from(fn, FunctionType([returnType, this.key_type], returnType, null));
653
+ return Expr.fromAst({
654
+ ast_type: "Builtin",
655
+ type: returnType,
656
+ location: get_location(2),
657
+ builtin: "SetReduce",
658
+ type_parameters: [this.key_type, returnType],
659
+ arguments: [this[AstSymbol], Expr.ast(fnExpr), initAst],
660
+ });
661
+ }
662
+ toArray(fn) {
663
+ let fnExpr;
664
+ if (fn === undefined) {
665
+ // Identity function
666
+ fnExpr = Expr.function([this.key_type], this.key_type, ($, key) => key);
667
+ }
668
+ else if (typeof fn === "function") {
669
+ fnExpr = Expr.function([this.key_type], undefined, fn);
670
+ }
671
+ else {
672
+ fnExpr = fn;
673
+ }
674
+ const fnType = fnExpr[TypeSymbol];
675
+ const returnType = fnType.output;
676
+ return Expr.fromAst({
677
+ ast_type: "Builtin",
678
+ type: ArrayType(returnType),
679
+ location: get_location(2),
680
+ builtin: "SetToArray",
681
+ type_parameters: [this.key_type, returnType],
682
+ arguments: [this[AstSymbol], Expr.ast(fnExpr)],
683
+ });
684
+ }
685
+ toSet(keyFn) {
686
+ let keyFnAst;
687
+ if (keyFn !== undefined) {
688
+ let fnExpr;
689
+ if (typeof keyFn === "function") {
690
+ fnExpr = Expr.function([this.key_type], undefined, keyFn);
691
+ }
692
+ else {
693
+ fnExpr = keyFn;
694
+ }
695
+ keyFnAst = Expr.ast(fnExpr);
696
+ }
697
+ else {
698
+ // Identity function
699
+ const identityFunction = Expr.function([this.key_type], this.key_type, ($, key) => key);
700
+ keyFnAst = Expr.ast(identityFunction);
701
+ }
702
+ const keyType = keyFnAst.type.output;
703
+ return Expr.fromAst({
704
+ ast_type: "Builtin",
705
+ type: SetType(keyType),
706
+ location: get_location(2),
707
+ builtin: "SetToSet",
708
+ type_parameters: [this.key_type, this.key_type],
709
+ arguments: [this[AstSymbol], keyFnAst],
710
+ });
711
+ }
712
+ toDict(keyFn, valueFn, onConflictFn) {
713
+ const keyFnAst = valueOrExprToAstTyped(keyFn ?? ((_$, x, i) => i), FunctionType([this.key_type], undefined, null));
714
+ const keyType = keyFnAst.type.output;
715
+ const valueFnAst = valueOrExprToAstTyped(valueFn ?? ((_$, x) => x), FunctionType([this.key_type], undefined, null));
716
+ const valueType = valueFnAst.type.output;
717
+ let onConflictAst;
718
+ if (onConflictFn === undefined) {
719
+ const location = get_location(2);
720
+ const onConflictFunction = Expr.function([valueType, valueType, keyType], valueType, ($, existing, value, key) => $.error(Expr.str `Cannot insert duplicate key ${key} into dict`, location));
721
+ onConflictAst = Expr.ast(onConflictFunction);
722
+ }
723
+ else {
724
+ onConflictAst = valueOrExprToAstTyped(onConflictFn, FunctionType([valueType, valueType, keyType], valueType, null));
725
+ }
726
+ return Expr.fromAst({
727
+ ast_type: "Builtin",
728
+ type: DictType(keyType, valueType),
729
+ location: get_location(2),
730
+ builtin: "SetToDict",
731
+ type_parameters: [this.key_type, keyType, valueType],
732
+ arguments: [this[AstSymbol], keyFnAst, valueFnAst, onConflictAst],
733
+ });
734
+ }
735
+ flattenToArray(fn) {
736
+ const fnAst = valueOrExprToAstTyped(fn, FunctionType([this.key_type], undefined, null));
737
+ const returnType = fnAst.type.output;
738
+ if (returnType.type !== "Array") {
739
+ throw new Error(`Expected Function to return an Array type, got ${printType(returnType)}`);
740
+ }
741
+ const elementType = returnType.value;
742
+ return Expr.fromAst({
743
+ ast_type: "Builtin",
744
+ type: ArrayType(elementType),
745
+ location: get_location(2),
746
+ builtin: "SetFlattenToArray",
747
+ type_parameters: [this.key_type, elementType],
748
+ arguments: [this[AstSymbol], fnAst],
749
+ });
750
+ }
751
+ flattenToSet(fn) {
752
+ const fnAst = valueOrExprToAstTyped(fn, FunctionType([this.key_type], undefined, null));
753
+ const returnType = fnAst.type.output;
754
+ if (returnType.type !== "Set") {
755
+ throw new Error(`Expected Function to return a Set type, got ${printType(returnType)}`);
756
+ }
757
+ const elementType = returnType.key;
758
+ return Expr.fromAst({
759
+ ast_type: "Builtin",
760
+ type: SetType(elementType),
761
+ location: get_location(2),
762
+ builtin: "SetFlattenToSet",
763
+ type_parameters: [this.key_type, elementType],
764
+ arguments: [this[AstSymbol], fnAst],
765
+ });
766
+ }
767
+ flattenToDict(fn, onConflictFn) {
768
+ const fnAst = valueOrExprToAstTyped(fn, FunctionType([this.key_type], undefined, null));
769
+ const returnType = fnAst.type.output;
770
+ if (returnType.type !== "Dict") {
771
+ throw new Error(`Expected Function to return a Dict type, got ${printType(returnType)}`);
772
+ }
773
+ const keyType = returnType.key;
774
+ const valueType = returnType.value;
775
+ let onConflictAst;
776
+ if (onConflictFn === undefined) {
777
+ const location = get_location(2);
778
+ const onConflictFunction = Expr.function([valueType, valueType, keyType], valueType, ($, existing, value, key) => $.error(Expr.str `Cannot insert duplicate key ${key} into dict`, location));
779
+ onConflictAst = Expr.ast(onConflictFunction);
780
+ }
781
+ else {
782
+ onConflictAst = valueOrExprToAstTyped(onConflictFn, FunctionType([valueType, valueType, keyType], valueType, null));
783
+ }
784
+ return Expr.fromAst({
785
+ ast_type: "Builtin",
786
+ type: DictType(keyType, valueType),
787
+ location: get_location(2),
788
+ builtin: "SetFlattenToDict",
789
+ type_parameters: [this.key_type, keyType, valueType],
790
+ arguments: [this[AstSymbol], fnAst, onConflictAst],
791
+ });
792
+ }
793
+ groupReduce(keyFn, initFn, reduceFn) {
794
+ const keyFnAst = valueOrExprToAstTyped(keyFn, FunctionType([this.key_type], undefined, null));
795
+ const keyType = keyFnAst.type.output;
796
+ const initFnAst = valueOrExprToAstTyped(initFn, FunctionType([keyType], undefined, null));
797
+ const initType = initFnAst.type.output;
798
+ const reduceFnAst = valueOrExprToAstTyped(reduceFn, FunctionType([initType, this.key_type], initType, null));
799
+ return Expr.fromAst({
800
+ ast_type: "Builtin",
801
+ type: DictType(keyType, initType),
802
+ location: get_location(2),
803
+ builtin: "SetGroupFold",
804
+ type_parameters: [this.key_type, keyType, initType],
805
+ arguments: [this[AstSymbol], keyFnAst, initFnAst, reduceFnAst],
806
+ });
807
+ }
808
+ groupToArrays(keyFn, valueFn) {
809
+ const keyFnAst = valueOrExprToAstTyped(keyFn, FunctionType([this.key_type], undefined, null));
810
+ const valueFnAst = valueOrExprToAstTyped(valueFn ?? ((_$, x) => x), FunctionType([this.key_type], undefined, null));
811
+ const keyFnExpr = Expr.fromAst(keyFnAst);
812
+ const valueFnExpr = Expr.fromAst(valueFnAst);
813
+ const valueType = valueFnAst.type.output;
814
+ return this.groupReduce(((_$, key) => keyFnExpr(key)), ((_$, _groupKey) => Expr.from([], ArrayType(valueType))), (($, acc, key) => {
815
+ const val = valueFnExpr(key);
816
+ $(acc.pushLast(val));
817
+ return acc;
818
+ }));
819
+ }
820
+ groupToSets(keyFn, valueFn) {
821
+ const keyFnAst = valueOrExprToAstTyped(keyFn, FunctionType([this.key_type], undefined, null));
822
+ const valueFnAst = valueOrExprToAstTyped(valueFn ?? ((_$, x) => x), FunctionType([this.key_type], undefined, null));
823
+ const keyFnExpr = Expr.fromAst(keyFnAst);
824
+ const valueFnExpr = Expr.fromAst(valueFnAst);
825
+ const valueType = valueFnAst.type.output;
826
+ return this.groupReduce(((_$, key) => keyFnExpr(key)), ((_$, _groupKey) => Expr.from(new Set(), SetType(valueType))), (($, acc, key) => {
827
+ const val = valueFnExpr(key);
828
+ $(acc.tryInsert(val));
829
+ return acc;
830
+ }));
831
+ }
832
+ groupToDicts(keyFn, keyFn2, valueFn, combineFn) {
833
+ const keyFnAst = valueOrExprToAstTyped(keyFn, FunctionType([this.key_type], undefined, null));
834
+ const keyFn2Ast = valueOrExprToAstTyped(keyFn2, FunctionType([this.key_type], undefined, null));
835
+ const valueFnAst = valueOrExprToAstTyped(valueFn ?? ((_$, x) => x), FunctionType([this.key_type], undefined, null));
836
+ const keyFnExpr = Expr.fromAst(keyFnAst);
837
+ const keyFn2Expr = Expr.fromAst(keyFn2Ast);
838
+ const valueFnExpr = Expr.fromAst(valueFnAst);
839
+ const key2Type = keyFn2Ast.type.output;
840
+ const valueType = valueFnAst.type.output;
841
+ if (combineFn !== undefined) {
842
+ // With conflict resolution - use tryGet + match to check existence, then insert or combine
843
+ const combineFnAst = valueOrExprToAstTyped(combineFn, FunctionType([valueType, valueType], valueType, null));
844
+ const combineFnExpr = Expr.fromAst(combineFnAst);
845
+ return this.groupReduce(((_$, key) => keyFnExpr(key)), ((_$, _key) => Expr.from(new Map(), DictType(key2Type, valueType))), (($, dict, key) => {
846
+ const innerKey = keyFn2Expr(key);
847
+ const val = valueFnExpr(key);
848
+ $.match(dict.tryGet(innerKey), {
849
+ some: ($, existing) => {
850
+ const combined = combineFnExpr(existing, val);
851
+ $(dict.update(innerKey, combined));
852
+ },
853
+ none: ($) => {
854
+ $(dict.insert(innerKey, val));
855
+ }
856
+ });
857
+ return dict;
858
+ }));
859
+ }
860
+ else {
861
+ // Without conflict resolution - use insert (errors on duplicate)
862
+ return this.groupReduce(((_$, key) => keyFnExpr(key)), ((_$, _key) => Expr.from(new Map(), DictType(key2Type, valueType))), (($, dict, key) => {
863
+ const innerKey = keyFn2Expr(key);
864
+ const val = valueFnExpr(key);
865
+ $(dict.insert(innerKey, val));
866
+ return dict;
867
+ }));
868
+ }
869
+ }
870
+ groupSize(keyFn) {
871
+ const keyFnAst = valueOrExprToAstTyped(keyFn ?? ((_$, x) => x), FunctionType([this.key_type], undefined, null));
872
+ return this.toDict(((_$, key) => Expr.fromAst(keyFnAst)(key)), ((_$) => 1n), ((_$, a, b) => a.add(b)));
873
+ }
874
+ groupEvery(keyFn, predFn) {
875
+ const keyFnAst = valueOrExprToAstTyped(keyFn, FunctionType([this.key_type], undefined, null));
876
+ const predFnAst = valueOrExprToAstTyped(predFn, FunctionType([this.key_type], BooleanType, null));
877
+ return this.groupReduce(((_$, key) => Expr.fromAst(keyFnAst)(key)), (() => true), ((_$, acc, key) => {
878
+ const pred = Expr.fromAst(predFnAst)(key);
879
+ return acc.and(() => pred);
880
+ }));
881
+ }
882
+ groupSome(keyFn, predFn) {
883
+ const keyFnAst = valueOrExprToAstTyped(keyFn, FunctionType([this.key_type], undefined, null));
884
+ const predFnAst = valueOrExprToAstTyped(predFn, FunctionType([this.key_type], BooleanType, null));
885
+ return this.groupReduce(((_$, key) => Expr.fromAst(keyFnAst)(key)), (() => false), ((_$, acc, key) => {
886
+ const pred = Expr.fromAst(predFnAst)(key);
887
+ return acc.or(() => pred);
888
+ }));
889
+ }
890
+ groupSum(keyFn, valueFn) {
891
+ const keyFnAst = valueOrExprToAstTyped(keyFn, FunctionType([this.key_type], undefined, null));
892
+ const valueFnAst = valueOrExprToAstTyped(valueFn ?? ((_$, x) => x), FunctionType([this.key_type], undefined, null));
893
+ const valueType = valueFnAst.type.output;
894
+ const isInteger = isTypeEqual(valueType, IntegerType);
895
+ const isFloat = isTypeEqual(valueType, FloatType);
896
+ if (!isInteger && !isFloat) {
897
+ throw new Error(`Can only perform groupSum on Integer or Float values, got ${printType(valueType)}`);
898
+ }
899
+ return this.toDict(((_$, key) => Expr.fromAst(keyFnAst)(key)), ((_$, key) => Expr.fromAst(valueFnAst)(key)), ((_$, a, b) => a.add(b)));
900
+ }
901
+ groupMean(keyFn, valueFn) {
902
+ const keyFnAst = valueOrExprToAstTyped(keyFn, FunctionType([this.key_type], undefined, null));
903
+ const valueFnAst = valueOrExprToAstTyped(valueFn ?? ((_$, x) => x), FunctionType([this.key_type], undefined, null));
904
+ const valueType = valueFnAst.type.output;
905
+ const isInteger = isTypeEqual(valueType, IntegerType);
906
+ const isFloat = isTypeEqual(valueType, FloatType);
907
+ if (!isInteger && !isFloat) {
908
+ throw new Error(`Can only perform groupMean on Integer or Float values, got ${printType(valueType)}`);
909
+ }
910
+ return this.toDict(((_$, key) => Expr.fromAst(keyFnAst)(key)), ((_$, key) => {
911
+ const val = Expr.fromAst(valueFnAst)(key);
912
+ return { sum: isInteger ? val.toFloat() : val, count: 1n };
913
+ }), ((_$, a, b) => ({ sum: a.sum.add(b.sum), count: a.count.add(b.count) }))).map(((_$, v) => v.sum.divide(v.count.toFloat())));
914
+ }
915
+ // Common reducers are provided, based on reduce
916
+ /**
917
+ * Returns true if all elements satisfy a condition (or are true for boolean sets).
918
+ *
919
+ * @param fn - Optional predicate function to test each element (required for non-boolean sets)
920
+ * @returns A BooleanExpr that is true if all elements pass the test, false otherwise
921
+ *
922
+ * @remarks
923
+ * - Empty sets always return true
924
+ * - Short-circuits on the first false element for efficiency
925
+ * - For boolean sets, the function parameter can be omitted
926
+ *
927
+ * @see {@link some} to check if at least one element satisfies the condition
928
+ *
929
+ * @example
930
+ * ```ts
931
+ * // Check if all numbers are positive
932
+ * const allPositive = East.function([SetType(IntegerType)], BooleanType, ($, numbers) => {
933
+ * $.return(numbers.every(($, n) => n.greaterThan(0n)));
934
+ * });
935
+ * const compiled = East.compile(allPositive.toIR(), []);
936
+ * compiled(new Set([1n, 2n, 3n])); // true
937
+ * compiled(new Set([1n, -2n, 3n])); // false
938
+ * compiled(new Set([])); // true (empty set)
939
+ * ```
940
+ *
941
+ * @example
942
+ * ```ts
943
+ * // For boolean sets, no function needed
944
+ * const allTrue = East.function([SetType(BooleanType)], BooleanType, ($, flags) => {
945
+ * $.return(flags.every());
946
+ * });
947
+ * const compiled = East.compile(allTrue.toIR(), []);
948
+ * compiled(new Set([true, true])); // true
949
+ * compiled(new Set([true, false])); // false
950
+ * ```
951
+ */
952
+ every(fn) {
953
+ if (fn === undefined) {
954
+ if (!isTypeEqual(this.key_type, BooleanType)) {
955
+ throw new Error(`Can only perform every on set of booleans, got ${printType(this.key_type)}`);
956
+ }
957
+ // Short-circuit on first false value - use explicit function AST to avoid type inference issues
958
+ const optionType = VariantType({ none: NullType, some: NullType });
959
+ const paramVariable = {
960
+ ast_type: "Variable",
961
+ type: this.key_type,
962
+ location: get_location(2),
963
+ mutable: false,
964
+ };
965
+ // Check if boolean is NOT true, then return some(null) to stop, otherwise return none to continue
966
+ const notCondition = {
967
+ ast_type: "Builtin",
968
+ type: BooleanType,
969
+ location: get_location(2),
970
+ builtin: "BooleanNot",
971
+ type_parameters: [],
972
+ arguments: [paramVariable]
973
+ };
974
+ const checkFnAst = {
975
+ ast_type: "Function",
976
+ type: FunctionType([this.key_type], optionType, []),
977
+ location: get_location(2),
978
+ parameters: [paramVariable],
979
+ body: {
980
+ ast_type: "IfElse",
981
+ type: optionType,
982
+ location: get_location(2),
983
+ ifs: [{
984
+ predicate: notCondition,
985
+ body: { ast_type: "Variant", type: optionType, location: get_location(2), case: "some", value: { ast_type: "Value", type: NullType, location: get_location(2), value: null } }
986
+ }],
987
+ else_body: { ast_type: "Variant", type: optionType, location: get_location(2), case: "none", value: { ast_type: "Value", type: NullType, location: get_location(2), value: null } }
988
+ }
989
+ };
990
+ const result = Expr.fromAst({
991
+ ast_type: "Builtin",
992
+ type: optionType,
993
+ location: get_location(2),
994
+ builtin: "SetFirstMap",
995
+ type_parameters: [this.key_type, NullType],
996
+ arguments: [this[AstSymbol], checkFnAst],
997
+ });
998
+ return Expr.match(result, { some: () => false, none: () => true });
999
+ }
1000
+ const fnAst = valueOrExprToAstTyped(fn, FunctionType([this.key_type], BooleanType, null));
1001
+ // Short-circuit on first false value
1002
+ const result = this.firstMap(($, k) => {
1003
+ const result = Expr.fromAst(fnAst)(k);
1004
+ return result.not().ifElse(() => some(null), () => none);
1005
+ });
1006
+ return Expr.match(result, { some: () => false, none: () => true });
1007
+ }
1008
+ /**
1009
+ * Returns true if at least one element satisfies a condition (or is true for boolean sets).
1010
+ *
1011
+ * @param fn - Optional predicate function to test each element (required for non-boolean sets)
1012
+ * @returns A BooleanExpr that is true if any element passes the test, false otherwise
1013
+ *
1014
+ * @remarks
1015
+ * - Empty sets always return false
1016
+ * - Short-circuits on the first true element for efficiency
1017
+ * - For boolean sets, the function parameter can be omitted
1018
+ *
1019
+ * @see {@link every} to check if all elements satisfy the condition
1020
+ *
1021
+ * @example
1022
+ * ```ts
1023
+ * // Check if any number is negative
1024
+ * const hasNegative = East.function([SetType(IntegerType)], BooleanType, ($, numbers) => {
1025
+ * $.return(numbers.some(($, n) => n.lessThan(0n)));
1026
+ * });
1027
+ * const compiled = East.compile(hasNegative.toIR(), []);
1028
+ * compiled(new Set([1n, 2n, 3n])); // false
1029
+ * compiled(new Set([1n, -2n, 3n])); // true
1030
+ * compiled(new Set([])); // false (empty set)
1031
+ * ```
1032
+ *
1033
+ * @example
1034
+ * ```ts
1035
+ * // For boolean sets, no function needed
1036
+ * const anyTrue = East.function([SetType(BooleanType)], BooleanType, ($, flags) => {
1037
+ * $.return(flags.some());
1038
+ * });
1039
+ * const compiled = East.compile(anyTrue.toIR(), []);
1040
+ * compiled(new Set([false, false])); // false
1041
+ * compiled(new Set([false, true])); // true
1042
+ * ```
1043
+ */
1044
+ some(fn) {
1045
+ if (fn === undefined) {
1046
+ if (!isTypeEqual(this.key_type, BooleanType)) {
1047
+ throw new Error(`Can only perform some on set of booleans, got ${printType(this.key_type)}`);
1048
+ }
1049
+ // Short-circuit on first true value - use explicit function AST to avoid type inference issues
1050
+ const optionType = VariantType({ none: NullType, some: NullType });
1051
+ const paramVariable = {
1052
+ ast_type: "Variable",
1053
+ type: this.key_type,
1054
+ location: get_location(2),
1055
+ mutable: false,
1056
+ };
1057
+ // Check if boolean is true, then return some(null) to stop, otherwise return none to continue
1058
+ const checkFnAst = {
1059
+ ast_type: "Function",
1060
+ type: FunctionType([this.key_type], optionType, []),
1061
+ location: get_location(2),
1062
+ parameters: [paramVariable],
1063
+ body: {
1064
+ ast_type: "IfElse",
1065
+ type: optionType,
1066
+ location: get_location(2),
1067
+ ifs: [{
1068
+ predicate: paramVariable,
1069
+ body: { ast_type: "Variant", type: optionType, location: get_location(2), case: "some", value: { ast_type: "Value", type: NullType, location: get_location(2), value: null } }
1070
+ }],
1071
+ else_body: { ast_type: "Variant", type: optionType, location: get_location(2), case: "none", value: { ast_type: "Value", type: NullType, location: get_location(2), value: null } }
1072
+ }
1073
+ };
1074
+ const result = Expr.fromAst({
1075
+ ast_type: "Builtin",
1076
+ type: optionType,
1077
+ location: get_location(2),
1078
+ builtin: "SetFirstMap",
1079
+ type_parameters: [this.key_type, NullType],
1080
+ arguments: [this[AstSymbol], checkFnAst],
1081
+ });
1082
+ return Expr.match(result, { some: () => true, none: () => false });
1083
+ }
1084
+ const fnAst = valueOrExprToAstTyped(fn, FunctionType([this.key_type], BooleanType, null));
1085
+ // Short-circuit on first true value
1086
+ const result = this.firstMap(($, k) => {
1087
+ const result = Expr.fromAst(fnAst)(k);
1088
+ return result.ifElse(() => some(null), () => none);
1089
+ });
1090
+ return Expr.match(result, { some: () => true, none: () => false });
1091
+ }
1092
+ sum(fn) {
1093
+ if (fn === undefined) {
1094
+ if (!(isTypeEqual(this.key_type, IntegerType) || isTypeEqual(this.key_type, FloatType))) {
1095
+ throw new Error(`Can only perform sum on set of numbers (Integer or Float), got ${printType(this.key_type)}`);
1096
+ }
1097
+ const zero = isTypeEqual(this.key_type, IntegerType) ? 0n : 0.0;
1098
+ return this.reduce(($, previous, value) => previous.add(value), zero);
1099
+ }
1100
+ else {
1101
+ const fnAst = valueOrExprToAstTyped(fn, FunctionType([this.key_type], undefined, null));
1102
+ const returnType = fnAst.type.output;
1103
+ if (!(isTypeEqual(returnType, IntegerType) || isTypeEqual(returnType, FloatType))) {
1104
+ throw new Error(`Can only perform sum on array of numbers (Integer or Float), got ${printType(returnType)}`);
1105
+ }
1106
+ const zero = isTypeEqual(returnType, IntegerType) ? 0n : 0.0;
1107
+ return this.reduce(($, previous, key) => previous.add(Expr.fromAst(fnAst)(key)), zero);
1108
+ }
1109
+ }
1110
+ mean(fn) {
1111
+ if (fn === undefined) {
1112
+ if (isTypeEqual(this.key_type, IntegerType)) {
1113
+ return this.reduce(($, previous, value) => previous.add(value.toFloat()), 0.0).divide(this.size().toFloat());
1114
+ }
1115
+ else if (isTypeEqual(this.key_type, FloatType)) {
1116
+ return this.reduce(($, previous, value) => previous.add(value), 0.0).divide(this.size().toFloat());
1117
+ }
1118
+ else {
1119
+ throw new Error(`Can only perform mean on set of numbers (Integer or Float), got ${printType(this.key_type)}`);
1120
+ }
1121
+ }
1122
+ else {
1123
+ const fnAst = valueOrExprToAstTyped(fn, FunctionType([this.key_type], undefined, null));
1124
+ const returnType = fnAst.type.output;
1125
+ if (isTypeEqual(returnType, IntegerType)) {
1126
+ return this.reduce(($, previous, key) => previous.add(Expr.fromAst(fnAst)(key).toFloat()), 0.0).divide(this.size().toFloat());
1127
+ }
1128
+ else if (isTypeEqual(returnType, FloatType)) {
1129
+ return this.reduce(($, previous, key) => previous.add(Expr.fromAst(fnAst)(key)), 0.0).divide(this.size().toFloat());
1130
+ }
1131
+ else {
1132
+ throw new Error(`Can only perform mean on set of numbers (Integer or Float), got ${printType(returnType)}`);
1133
+ }
1134
+ }
1135
+ }
1136
+ }
1137
+ //# sourceMappingURL=set.js.map