@scriptc/compiler 0.0.0 → 0.0.1

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 (206) hide show
  1. package/LICENSE +202 -0
  2. package/ambient/package.json +3 -0
  3. package/ambient/scriptc-node-fallback.d.ts +3001 -0
  4. package/ambient/scriptc-overrides.d.ts +95 -0
  5. package/ambient/scriptc.d.ts +74 -0
  6. package/dist/backend/cc.d.ts +169 -0
  7. package/dist/backend/cc.js +897 -0
  8. package/dist/backend/cc.js.map +1 -0
  9. package/dist/backend/emission/emit-async.d.ts +145 -0
  10. package/dist/backend/emission/emit-async.js +996 -0
  11. package/dist/backend/emission/emit-async.js.map +1 -0
  12. package/dist/backend/emission/emit-exprs.d.ts +3 -0
  13. package/dist/backend/emission/emit-exprs.js +5947 -0
  14. package/dist/backend/emission/emit-exprs.js.map +1 -0
  15. package/dist/backend/emission/emit-island.d.ts +45 -0
  16. package/dist/backend/emission/emit-island.js +271 -0
  17. package/dist/backend/emission/emit-island.js.map +1 -0
  18. package/dist/backend/emission/emit-shapes.d.ts +142 -0
  19. package/dist/backend/emission/emit-shapes.js +575 -0
  20. package/dist/backend/emission/emit-shapes.js.map +1 -0
  21. package/dist/backend/emission/emit-stmts.d.ts +78 -0
  22. package/dist/backend/emission/emit-stmts.js +960 -0
  23. package/dist/backend/emission/emit-stmts.js.map +1 -0
  24. package/dist/backend/emission/emit-types.d.ts +65 -0
  25. package/dist/backend/emission/emit-types.js +652 -0
  26. package/dist/backend/emission/emit-types.js.map +1 -0
  27. package/dist/backend/emission/emit-walkers.d.ts +154 -0
  28. package/dist/backend/emission/emit-walkers.js +1587 -0
  29. package/dist/backend/emission/emit-walkers.js.map +1 -0
  30. package/dist/backend/emission/emitter.d.ts +452 -0
  31. package/dist/backend/emission/emitter.js +1249 -0
  32. package/dist/backend/emission/emitter.js.map +1 -0
  33. package/dist/backend/emission/may-throw.d.ts +15 -0
  34. package/dist/backend/emission/may-throw.js +250 -0
  35. package/dist/backend/emission/may-throw.js.map +1 -0
  36. package/dist/backend/llvm/blocks.d.ts +21 -0
  37. package/dist/backend/llvm/blocks.js +68 -0
  38. package/dist/backend/llvm/blocks.js.map +1 -0
  39. package/dist/backend/llvm/classes.d.ts +84 -0
  40. package/dist/backend/llvm/classes.js +438 -0
  41. package/dist/backend/llvm/classes.js.map +1 -0
  42. package/dist/backend/llvm/dyn.d.ts +123 -0
  43. package/dist/backend/llvm/dyn.js +2624 -0
  44. package/dist/backend/llvm/dyn.js.map +1 -0
  45. package/dist/backend/llvm/emitter.d.ts +3 -0
  46. package/dist/backend/llvm/emitter.js +10087 -0
  47. package/dist/backend/llvm/emitter.js.map +1 -0
  48. package/dist/backend/llvm/shapes.d.ts +78 -0
  49. package/dist/backend/llvm/shapes.js +754 -0
  50. package/dist/backend/llvm/shapes.js.map +1 -0
  51. package/dist/backend/llvm/unsupported.d.ts +6 -0
  52. package/dist/backend/llvm/unsupported.js +12 -0
  53. package/dist/backend/llvm/unsupported.js.map +1 -0
  54. package/dist/backend/llvm/walkers.d.ts +58 -0
  55. package/dist/backend/llvm/walkers.js +793 -0
  56. package/dist/backend/llvm/walkers.js.map +1 -0
  57. package/dist/backend/mangle.d.ts +124 -0
  58. package/dist/backend/mangle.js +232 -0
  59. package/dist/backend/mangle.js.map +1 -0
  60. package/dist/coverage/report.d.ts +64 -0
  61. package/dist/coverage/report.js +226 -0
  62. package/dist/coverage/report.js.map +1 -0
  63. package/dist/diagnostics/diagnostic.d.ts +140 -0
  64. package/dist/diagnostics/diagnostic.js +458 -0
  65. package/dist/diagnostics/diagnostic.js.map +1 -0
  66. package/dist/diagnostics/render.d.ts +11 -0
  67. package/dist/diagnostics/render.js +58 -0
  68. package/dist/diagnostics/render.js.map +1 -0
  69. package/dist/frontend/cjs-lexer.d.ts +20 -0
  70. package/dist/frontend/cjs-lexer.js +813 -0
  71. package/dist/frontend/cjs-lexer.js.map +1 -0
  72. package/dist/frontend/lowering/http2-constants.d.ts +1 -0
  73. package/dist/frontend/lowering/http2-constants.js +251 -0
  74. package/dist/frontend/lowering/http2-constants.js.map +1 -0
  75. package/dist/frontend/lowering/lib-boundary.d.ts +6 -0
  76. package/dist/frontend/lowering/lib-boundary.js +143 -0
  77. package/dist/frontend/lowering/lib-boundary.js.map +1 -0
  78. package/dist/frontend/lowering/lower-assert.d.ts +18 -0
  79. package/dist/frontend/lowering/lower-assert.js +1269 -0
  80. package/dist/frontend/lowering/lower-assert.js.map +1 -0
  81. package/dist/frontend/lowering/lower-builtins.d.ts +511 -0
  82. package/dist/frontend/lowering/lower-builtins.js +5249 -0
  83. package/dist/frontend/lowering/lower-builtins.js.map +1 -0
  84. package/dist/frontend/lowering/lower-calls.d.ts +581 -0
  85. package/dist/frontend/lowering/lower-calls.js +6281 -0
  86. package/dist/frontend/lowering/lower-calls.js.map +1 -0
  87. package/dist/frontend/lowering/lower-classes.d.ts +727 -0
  88. package/dist/frontend/lowering/lower-classes.js +4701 -0
  89. package/dist/frontend/lowering/lower-classes.js.map +1 -0
  90. package/dist/frontend/lowering/lower-comptime.d.ts +53 -0
  91. package/dist/frontend/lowering/lower-comptime.js +244 -0
  92. package/dist/frontend/lowering/lower-comptime.js.map +1 -0
  93. package/dist/frontend/lowering/lower-containers.d.ts +483 -0
  94. package/dist/frontend/lowering/lower-containers.js +6281 -0
  95. package/dist/frontend/lowering/lower-containers.js.map +1 -0
  96. package/dist/frontend/lowering/lower-dgram.d.ts +20 -0
  97. package/dist/frontend/lowering/lower-dgram.js +319 -0
  98. package/dist/frontend/lowering/lower-dgram.js.map +1 -0
  99. package/dist/frontend/lowering/lower-emitter.d.ts +10 -0
  100. package/dist/frontend/lowering/lower-emitter.js +688 -0
  101. package/dist/frontend/lowering/lower-emitter.js.map +1 -0
  102. package/dist/frontend/lowering/lower-enums.d.ts +22 -0
  103. package/dist/frontend/lowering/lower-enums.js +235 -0
  104. package/dist/frontend/lowering/lower-enums.js.map +1 -0
  105. package/dist/frontend/lowering/lower-expando.d.ts +35 -0
  106. package/dist/frontend/lowering/lower-expando.js +276 -0
  107. package/dist/frontend/lowering/lower-expando.js.map +1 -0
  108. package/dist/frontend/lowering/lower-exprs.d.ts +524 -0
  109. package/dist/frontend/lowering/lower-exprs.js +8099 -0
  110. package/dist/frontend/lowering/lower-exprs.js.map +1 -0
  111. package/dist/frontend/lowering/lower-generators.d.ts +50 -0
  112. package/dist/frontend/lowering/lower-generators.js +421 -0
  113. package/dist/frontend/lowering/lower-generators.js.map +1 -0
  114. package/dist/frontend/lowering/lower-inspect.d.ts +20 -0
  115. package/dist/frontend/lowering/lower-inspect.js +1069 -0
  116. package/dist/frontend/lowering/lower-inspect.js.map +1 -0
  117. package/dist/frontend/lowering/lower-island.d.ts +108 -0
  118. package/dist/frontend/lowering/lower-island.js +650 -0
  119. package/dist/frontend/lowering/lower-island.js.map +1 -0
  120. package/dist/frontend/lowering/lower-mixins.d.ts +96 -0
  121. package/dist/frontend/lowering/lower-mixins.js +534 -0
  122. package/dist/frontend/lowering/lower-mixins.js.map +1 -0
  123. package/dist/frontend/lowering/lower-modules.d.ts +135 -0
  124. package/dist/frontend/lowering/lower-modules.js +1613 -0
  125. package/dist/frontend/lowering/lower-modules.js.map +1 -0
  126. package/dist/frontend/lowering/lower-namespaces.d.ts +168 -0
  127. package/dist/frontend/lowering/lower-namespaces.js +706 -0
  128. package/dist/frontend/lowering/lower-namespaces.js.map +1 -0
  129. package/dist/frontend/lowering/lower-server.d.ts +90 -0
  130. package/dist/frontend/lowering/lower-server.js +3471 -0
  131. package/dist/frontend/lowering/lower-server.js.map +1 -0
  132. package/dist/frontend/lowering/lower-stmts.d.ts +361 -0
  133. package/dist/frontend/lowering/lower-stmts.js +5341 -0
  134. package/dist/frontend/lowering/lower-stmts.js.map +1 -0
  135. package/dist/frontend/lowering/lower-stream.d.ts +88 -0
  136. package/dist/frontend/lowering/lower-stream.js +1533 -0
  137. package/dist/frontend/lowering/lower-stream.js.map +1 -0
  138. package/dist/frontend/lowering/lower-test.d.ts +27 -0
  139. package/dist/frontend/lowering/lower-test.js +353 -0
  140. package/dist/frontend/lowering/lower-test.js.map +1 -0
  141. package/dist/frontend/lowering/lowerer.d.ts +1748 -0
  142. package/dist/frontend/lowering/lowerer.js +6256 -0
  143. package/dist/frontend/lowering/lowerer.js.map +1 -0
  144. package/dist/frontend/lowering/surfaces.d.ts +272 -0
  145. package/dist/frontend/lowering/surfaces.js +1096 -0
  146. package/dist/frontend/lowering/surfaces.js.map +1 -0
  147. package/dist/frontend/npm-static.d.ts +55 -0
  148. package/dist/frontend/npm-static.js +300 -0
  149. package/dist/frontend/npm-static.js.map +1 -0
  150. package/dist/frontend/npm.d.ts +330 -0
  151. package/dist/frontend/npm.js +1259 -0
  152. package/dist/frontend/npm.js.map +1 -0
  153. package/dist/frontend/program.d.ts +186 -0
  154. package/dist/frontend/program.js +2172 -0
  155. package/dist/frontend/program.js.map +1 -0
  156. package/dist/frontend/provenance-registry.d.ts +48 -0
  157. package/dist/frontend/provenance-registry.js +87 -0
  158. package/dist/frontend/provenance-registry.js.map +1 -0
  159. package/dist/frontend/provenance.d.ts +6 -0
  160. package/dist/frontend/provenance.js +459 -0
  161. package/dist/frontend/provenance.js.map +1 -0
  162. package/dist/frontend/resolve.d.ts +56 -0
  163. package/dist/frontend/resolve.js +682 -0
  164. package/dist/frontend/resolve.js.map +1 -0
  165. package/dist/frontend/shared.d.ts +60 -0
  166. package/dist/frontend/shared.js +232 -0
  167. package/dist/frontend/shared.js.map +1 -0
  168. package/dist/frontend/ts7/adapter.d.ts +7 -0
  169. package/dist/frontend/ts7/adapter.js +54 -0
  170. package/dist/frontend/ts7/adapter.js.map +1 -0
  171. package/dist/frontend/ts7/ast.d.ts +50 -0
  172. package/dist/frontend/ts7/ast.js +211 -0
  173. package/dist/frontend/ts7/ast.js.map +1 -0
  174. package/dist/frontend/ts7/census-check.d.ts +1 -0
  175. package/dist/frontend/ts7/census-check.js +12 -0
  176. package/dist/frontend/ts7/census-check.js.map +1 -0
  177. package/dist/frontend/ts7/checker.d.ts +140 -0
  178. package/dist/frontend/ts7/checker.js +544 -0
  179. package/dist/frontend/ts7/checker.js.map +1 -0
  180. package/dist/frontend/ts7/enums.d.ts +18 -0
  181. package/dist/frontend/ts7/enums.js +43 -0
  182. package/dist/frontend/ts7/enums.js.map +1 -0
  183. package/dist/frontend/ts7/program.d.ts +99 -0
  184. package/dist/frontend/ts7/program.js +278 -0
  185. package/dist/frontend/ts7/program.js.map +1 -0
  186. package/dist/frontend/ts7/world-check.d.ts +3 -0
  187. package/dist/frontend/ts7/world-check.js +34 -0
  188. package/dist/frontend/ts7/world-check.js.map +1 -0
  189. package/dist/frontend/types.d.ts +205 -0
  190. package/dist/frontend/types.js +2485 -0
  191. package/dist/frontend/types.js.map +1 -0
  192. package/dist/index.d.ts +85 -0
  193. package/dist/index.js +424 -0
  194. package/dist/index.js.map +1 -0
  195. package/dist/ir/nodes.d.ts +4334 -0
  196. package/dist/ir/nodes.js +1906 -0
  197. package/dist/ir/nodes.js.map +1 -0
  198. package/dist/ir/serialize.d.ts +4 -0
  199. package/dist/ir/serialize.js +34 -0
  200. package/dist/ir/serialize.js.map +1 -0
  201. package/dist/ir/validate.d.ts +36 -0
  202. package/dist/ir/validate.js +4884 -0
  203. package/dist/ir/validate.js.map +1 -0
  204. package/package.json +30 -6
  205. package/README.md +0 -3
  206. package/index.js +0 -2
@@ -0,0 +1,688 @@
1
+ /* The node:events EventEmitter lowering (the spoke-module pattern, like
2
+ * lower-server.ts): every EMITTER_API_MEMBERS method call on a receiver
3
+ * whose class roots at %EventEmitter lands here, from
4
+ * lowerObjectMethodCall.
5
+ *
6
+ * THE TYPING STANCE. Node types EventEmitter untyped — `emit(name,
7
+ * ...args: any[])`, listeners `(...args: any[]) => void` — which has no
8
+ * static lowering. The honest model here is per-event monomorphization:
9
+ * event names must be compile-time string literals (the net/http/process
10
+ * precedent), and each event name gets ONE argument tuple, unified across
11
+ * the whole program (a pre-pass scans every emit site's argument types
12
+ * and every registered listener's annotated parameter types). Emit sites
13
+ * must supply exactly the tuple; listeners may declare any PREFIX of it
14
+ * (Node calls listeners with all arguments; extra parameters would read
15
+ * undefined and have no honest type). The table is program-global, not
16
+ * per-class: every emitter class shares the %EventEmitter root and
17
+ * upcasts alias freely, so per-class tables would be unsound. The JS
18
+ * lane's unannotated listeners (checker `any` — dyn) do not fence: they
19
+ * register through the checked-dynamic boundary (lowerDynListenerCall —
20
+ * emit arguments box to dyn, JS-exact arity, the original kept as the
21
+ * registry entry's identity). What the static model cannot carry is
22
+ * fenced with its own words: non-literal names, symbol names,
23
+ * conflicting tuples, the meta-events' listener-function argument (meta
24
+ * listeners take at most the event name; dyn meta listeners fence — Node
25
+ * passes the listener function second, which has no dyn conversion), and
26
+ * listeners()/rawListeners() of an event with any dyn-flavored
27
+ * registration (the bucket has no one honest element type).
28
+ *
29
+ * Two special names: 'error' is forced to the one-%Error tuple (emit
30
+ * routes through emitter.emitError — no listener means the payload
31
+ * THROWS, Node's contract — and subclass payloads upcast to the root);
32
+ * 'newListener'/'removeListener' are forced to the one-string tuple (the
33
+ * runtime emits them internally with the affected event's name). */
34
+ import * as ts from "../ts7/adapter.js";
35
+ import { dynFallbackType } from "./lowerer.js";
36
+ import { locOf } from "../program.js";
37
+ import { arrayOf, BOOL, canBoxFuncIntoDyn, canConvertToDyn, DYN, F64, isUnitType, STRING, typeEquals, typeKey, VOID } from "../../ir/nodes.js";
38
+ import { streamForcedTuple, streamSidesOf } from "./lower-stream.js";
39
+ /** True when the class descends from (or is) the runtime emitter. */
40
+ export function emitterRooted(L, info) {
41
+ for (let c = info ?? null; c; c = c.base) {
42
+ if (c.builtinEmitter)
43
+ return true;
44
+ }
45
+ return false;
46
+ }
47
+ const REGISTER_MEMBERS = new Set([
48
+ "on", "addListener", "once", "prependListener", "prependOnceListener",
49
+ ]);
50
+ const META_EVENTS = new Set(["newListener", "removeListener"]);
51
+ /** The program-wide event-signature table, built lazily on the first
52
+ * emitter lowering (class shapes are collected before any body lowers, so
53
+ * receiver classes resolve). The scan is DIAGNOSTIC-FREE: unmappable
54
+ * types and non-literal names are simply not candidates — the touching
55
+ * sites speak for themselves when they lower. */
56
+ function emitterEvents(L) {
57
+ const holder = L;
58
+ if (holder.emitterEventTable)
59
+ return holder.emitterEventTable;
60
+ const table = new Map();
61
+ const sigOf = (name) => {
62
+ let sig = table.get(name);
63
+ if (!sig)
64
+ table.set(name, (sig = { tuple: [], fromEmit: false, conflict: null, dynListener: false }));
65
+ return sig;
66
+ };
67
+ // The two forced tuples (see the header comment).
68
+ table.set("error", { tuple: [{ kind: "object", className: "%Error" }], fromEmit: true, conflict: null, dynListener: false });
69
+ table.set("newListener", { tuple: [STRING], fromEmit: true, conflict: null, dynListener: false });
70
+ table.set("removeListener", { tuple: [STRING], fromEmit: true, conflict: null, dynListener: false });
71
+ const fmt = (t) => L.fmt(t);
72
+ const mergeEmit = (name, args) => {
73
+ if (args.some((a) => a === null))
74
+ return; // its own site will diagnose
75
+ const tuple = args;
76
+ const sig = sigOf(name);
77
+ if (sig.conflict)
78
+ return;
79
+ if (!sig.fromEmit) {
80
+ // Listener prefixes seen so far must fit under this tuple.
81
+ if (sig.tuple.length > tuple.length) {
82
+ sig.conflict = `a listener declares ${sig.tuple.length} parameters but an emit supplies ${tuple.length} arguments`;
83
+ return;
84
+ }
85
+ for (let i = 0; i < sig.tuple.length; i++) {
86
+ if (!typeEquals(sig.tuple[i], tuple[i])) {
87
+ sig.conflict = `position ${i} is '${fmt(sig.tuple[i])}' at one site and '${fmt(tuple[i])}' at another`;
88
+ return;
89
+ }
90
+ }
91
+ sig.tuple = tuple;
92
+ sig.fromEmit = true;
93
+ return;
94
+ }
95
+ if (sig.tuple.length !== tuple.length) {
96
+ sig.conflict = `emit sites supply ${sig.tuple.length} and ${tuple.length} arguments`;
97
+ return;
98
+ }
99
+ for (let i = 0; i < tuple.length; i++) {
100
+ if (!typeEquals(sig.tuple[i], tuple[i])) {
101
+ sig.conflict = `position ${i} is '${fmt(sig.tuple[i])}' at one site and '${fmt(tuple[i])}' at another`;
102
+ return;
103
+ }
104
+ }
105
+ };
106
+ const mergeListener = (name, params) => {
107
+ if (params.some((p) => p === null))
108
+ return;
109
+ const prefix = params;
110
+ const sig = sigOf(name);
111
+ if (sig.conflict)
112
+ return;
113
+ if (sig.fromEmit) {
114
+ if (prefix.length > sig.tuple.length) {
115
+ sig.conflict = `a listener declares ${prefix.length} parameters but emits supply ${sig.tuple.length} arguments`;
116
+ return;
117
+ }
118
+ }
119
+ else if (prefix.length > sig.tuple.length) {
120
+ // The longest listener extends the provisional tuple.
121
+ for (let i = 0; i < sig.tuple.length; i++) {
122
+ if (!typeEquals(sig.tuple[i], prefix[i])) {
123
+ sig.conflict = `position ${i} is '${fmt(sig.tuple[i])}' at one site and '${fmt(prefix[i])}' at another`;
124
+ return;
125
+ }
126
+ }
127
+ sig.tuple = prefix;
128
+ return;
129
+ }
130
+ for (let i = 0; i < prefix.length; i++) {
131
+ if (!typeEquals(sig.tuple[i], prefix[i])) {
132
+ sig.conflict = `position ${i} is '${fmt(sig.tuple[i])}' at one site and '${fmt(prefix[i])}' at another`;
133
+ return;
134
+ }
135
+ }
136
+ };
137
+ for (const sf of L.program.getSourceFiles()) {
138
+ if (sf.isDeclarationFile)
139
+ continue;
140
+ const walk = (node) => {
141
+ ts.forEachChild(node, walk);
142
+ if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression))
143
+ return;
144
+ const member = node.expression.name.text;
145
+ const isEmit = member === "emit";
146
+ if (!isEmit && !REGISTER_MEMBERS.has(member))
147
+ return;
148
+ const arg0 = node.arguments[0];
149
+ if (!arg0)
150
+ return;
151
+ let recvT = null;
152
+ let nameT = null;
153
+ try {
154
+ recvT = L.mapTypeOf(L.typeOf(node.expression.expression));
155
+ nameT = L.typeOf(arg0);
156
+ }
157
+ catch {
158
+ return; // checker trouble is the lowering's business, not the scan's
159
+ }
160
+ if (recvT?.kind !== "object" || !emitterRooted(L, L.classes.get(recvT.className)))
161
+ return;
162
+ if (!nameT.isStringLiteralType())
163
+ return;
164
+ const name = nameT.value;
165
+ if (META_EVENTS.has(name) || name === "error")
166
+ return; // forced tuples
167
+ // Stream receivers' runtime-emitted events carry PER-BASE forced
168
+ // tuples (lower-stream.ts) — their sites never join the program-
169
+ // global table, so a stream's 'data' cannot collide with a user
170
+ // event named 'data' on a plain emitter.
171
+ if (streamForcedTuple(L, L.classes.get(recvT.className), name) !== null)
172
+ return;
173
+ try {
174
+ if (isEmit) {
175
+ mergeEmit(name, node.arguments.slice(1).map((a) => L.mapTypeOf(L.typeOf(a))));
176
+ }
177
+ else if (node.arguments[1]) {
178
+ const cbCt = L.typeOf(node.arguments[1]);
179
+ const cbT = L.mapTypeOf(cbCt) ?? dynFallbackType(L, node.arguments[1], cbCt);
180
+ // Dyn-flavored listeners (a checked-dynamic value, or a func
181
+ // with dyn parameters — the JS lane) register through the
182
+ // adapter and constrain nothing: a dyn parameter accepts any
183
+ // tuple position, and positions past the tuple read the boxed
184
+ // undefined (exactly JS's extra-parameter semantics).
185
+ if (cbT?.kind === "dyn" || (cbT?.kind === "func" && cbT.params.some((p) => p.kind === "dyn"))) {
186
+ sigOf(name).dynListener = true;
187
+ }
188
+ else if (cbT?.kind === "func") {
189
+ mergeListener(name, cbT.params);
190
+ }
191
+ }
192
+ }
193
+ catch {
194
+ /* not a candidate */
195
+ }
196
+ };
197
+ walk(sf);
198
+ }
199
+ holder.emitterEventTable = table;
200
+ return table;
201
+ }
202
+ /** The compile-time event name of the first argument, or a pointed fence
203
+ * (string-literal TYPE, so const bindings and literal unions of one
204
+ * member count — the staticHeaderKeyOf stance). */
205
+ function eventNameOf(L, member, arg) {
206
+ const t = L.typeOf(arg);
207
+ if (t.isStringLiteralType())
208
+ return t.value;
209
+ L.noLowering(`${member} with a non-literal event name`, arg, "event names must be compile-time string literals (each event's argument tuple is unified statically; symbol names have no lowering)");
210
+ }
211
+ const strLit = (value, loc) => ({ kind: "strLit", value, type: STRING, loc });
212
+ const boolLit = (value, loc) => ({ kind: "boolLit", value, type: BOOL, loc });
213
+ /** The event's unified tuple, with conflicts reported at this site. */
214
+ function tupleOf(L, table, name, blame) {
215
+ const sig = table.get(name);
216
+ if (!sig)
217
+ return [];
218
+ if (sig.conflict) {
219
+ L.noLowering(`the event '${name}' with conflicting argument types`, blame, `every emit site and listener of one event name must agree on one argument tuple — ${sig.conflict}`);
220
+ }
221
+ return sig.tuple;
222
+ }
223
+ /** How a listener argument is dyn-flavored: "dyn" for a checked-dynamic
224
+ * VALUE (a mustCall wrapper, a listener that rode an untyped binding),
225
+ * "func" for a function whose parameters include dyn (the JS lane's
226
+ * unannotated listeners — their checker type is any). Null for everything
227
+ * else (the static path, with its own diagnostics). */
228
+ function dynListenerFlavor(L, node) {
229
+ let t;
230
+ try {
231
+ const ct = L.typeOf(node);
232
+ // The JS declaration fallback is what the EXPRESSION lowering applies
233
+ // to inference residue (an inline `(a) => {}` maps null as a checker
234
+ // type but lowers as a dyn-parameter function) — classify by the same
235
+ // rule, so the flavor always matches what lowerExpr will produce.
236
+ t = L.mapTypeOf(ct) ?? dynFallbackType(L, node, ct);
237
+ }
238
+ catch {
239
+ return null;
240
+ }
241
+ if (t?.kind === "dyn")
242
+ return "dyn";
243
+ if (t?.kind === "func")
244
+ return t.params.some((p) => p.kind === "dyn") ? "func" : null;
245
+ // A statically-known NON-function listener (a literal number, a record,
246
+ // null): route it through the dyn path too — the registration helper's
247
+ // checkListener throws Node's exact ERR_INVALID_ARG_TYPE TypeError
248
+ // (the TS lane never reaches this: tsc rejects the argument first).
249
+ if (t && t.kind !== "jsval" && (isUnitType(t) || canConvertToDyn(t, (id) => L.shapes.get(id), (id) => L.unions.get(id)))) {
250
+ return "dyn";
251
+ }
252
+ return null;
253
+ }
254
+ /** A dyn-flavored listener registration/removal (the JS lane's unannotated
255
+ * listeners, and mustCall-style wrapped ones): the listener registers as a
256
+ * checked-dynamic value through an interned helper —
257
+ *
258
+ * %emitter.onDyn.<n>(recv, name, cb, once, prepend) {
259
+ * emitter.checkListener(cb); // Node's ERR_INVALID_ARG_TYPE
260
+ * const a: (tuple) => void = cb; // dynCheck: the boxing adapter
261
+ * return emitter.onDyn(recv, name, cb, a, once, prepend);
262
+ * }
263
+ *
264
+ * The dynCheck adapter boxes each emitted tuple argument to dyn and calls
265
+ * the original through the checked-dynamic call machinery — JS-exact
266
+ * arity (parameters past the tuple read undefined, extra arguments are
267
+ * ignored). The runtime entry registers the ADAPTER for dispatch but
268
+ * keeps the ORIGINAL (the dyn box's underlying closure) as the entry's
269
+ * identity, so off/removeListener and listenerCount(name, fn) match it.
270
+ * The helper shape exists because cb must evaluate ONCE and feed both
271
+ * roles. Fenced honestly: tuple positions that cannot box to dyn (class
272
+ * payloads — 'error' events), and the meta events (Node passes the
273
+ * listener FUNCTION second, which has no dyn conversion — a dyn listener
274
+ * reading it would see undefined). */
275
+ function lowerDynListenerCall(L, member, name, tuple, receiver, cbNode, flavor, registering, once, prepend, loc,
276
+ /** Stream 'data': the adapter registers through emitter.onDataDyn so
277
+ * the backend emits the two-slot DATA thunk (box by runtime tag); the
278
+ * tuple is [DYN] — the adapter passes the boxed chunk through. */
279
+ streamData) {
280
+ if (META_EVENTS.has(name)) {
281
+ L.noLowering(`'${member}' of '${name}' with a checked-dynamic listener`, cbNode, "Node passes the listener FUNCTION as the meta event's second argument, which has no dynamic conversion — annotate the listener's parameter as a string");
282
+ }
283
+ const getRecord = (id) => L.shapes.get(id);
284
+ const getUnion = (id) => L.unions.get(id);
285
+ for (let i = 0; i < tuple.length; i++) {
286
+ const p = tuple[i];
287
+ if (p.kind !== "dyn" && !canConvertToDyn(p, getRecord, getUnion)) {
288
+ L.noLowering(`'${member}' of '${name}' with a checked-dynamic listener`, cbNode, `the event's argument ${i} is '${L.fmt(p)}', which cannot box into a dynamic value — annotate the listener's parameters with the emitted types`);
289
+ }
290
+ }
291
+ let cbDyn;
292
+ if (flavor === "dyn") {
293
+ const v = L.lowerExpr(cbNode);
294
+ if (v.type.kind === "dyn") {
295
+ cbDyn = v;
296
+ }
297
+ else if (v.kind === "unitLit" || canConvertToDyn(v.type, getRecord, getUnion)) {
298
+ // A non-dyn residue the classification saw as dynamic (a literal
299
+ // null/undefined listener, a convertible scalar): box it — the
300
+ // checkListener call answers with Node's exact TypeError.
301
+ cbDyn = { kind: "dynFrom", value: v, type: DYN, loc };
302
+ }
303
+ else {
304
+ L.noLowering(`'${member}' with a non-function listener`, cbNode);
305
+ }
306
+ }
307
+ else {
308
+ const cb = L.lowerExpr(cbNode);
309
+ if (cb.type.kind !== "func" || !canBoxFuncIntoDyn(cb.type, getRecord, getUnion)) {
310
+ L.noLowering(`'${member}' with a listener of this signature`, cbNode, "a checked-dynamic listener's own parameters and return must box across the dynamic boundary");
311
+ }
312
+ cbDyn = { kind: "dynFrom", value: cb, type: DYN, loc };
313
+ }
314
+ const recvT = receiver.type;
315
+ const adapterT = { kind: "func", params: tuple, ret: VOID };
316
+ const onFn = streamData ? "emitter.onDataDyn" : "emitter.onDyn";
317
+ const key = registering
318
+ ? `${onFn}:${typeKey(recvT)}:${typeKey(adapterT)}`
319
+ : `emitter.offDyn:${typeKey(recvT)}`;
320
+ const existing = L.arrHofHelpers.get(key);
321
+ let helper = existing;
322
+ if (!helper) {
323
+ helper = `%emitter.${registering ? "onDyn" : "offDyn"}.${L.arrHofHelpers.size}`;
324
+ L.arrHofHelpers.set(key, helper);
325
+ const ref = (localId, type) => ({ kind: "varRef", localId, type, loc });
326
+ const check = {
327
+ kind: "exprStmt",
328
+ expr: { kind: "libCall", fn: "emitter.checkListener", args: [ref("cb.0", DYN)], type: VOID, loc },
329
+ loc,
330
+ };
331
+ const params = [
332
+ { localId: "r.0", name: "r", type: recvT },
333
+ { localId: "n.0", name: "n", type: STRING },
334
+ { localId: "cb.0", name: "cb", type: DYN },
335
+ ...(registering
336
+ ? [
337
+ { localId: "o.0", name: "o", type: BOOL },
338
+ { localId: "p.0", name: "p", type: BOOL },
339
+ ]
340
+ : []),
341
+ ];
342
+ const locals = params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false }));
343
+ let body;
344
+ if (registering) {
345
+ locals.push({ id: "a.0", name: "a", type: adapterT, mutable: false });
346
+ body = [
347
+ check,
348
+ { kind: "varDecl", localId: "a.0", init: { kind: "dynCheck", value: ref("cb.0", DYN), type: adapterT, loc }, loc },
349
+ {
350
+ kind: "return",
351
+ value: {
352
+ kind: "libCall",
353
+ fn: onFn,
354
+ args: [ref("r.0", recvT), ref("n.0", STRING), ref("cb.0", DYN), ref("a.0", adapterT), ref("o.0", BOOL), ref("p.0", BOOL)],
355
+ type: recvT,
356
+ loc,
357
+ },
358
+ loc,
359
+ },
360
+ ];
361
+ }
362
+ else {
363
+ body = [
364
+ check,
365
+ {
366
+ kind: "return",
367
+ value: {
368
+ kind: "libCall",
369
+ fn: "emitter.offDyn",
370
+ args: [ref("r.0", recvT), ref("n.0", STRING), ref("cb.0", DYN)],
371
+ type: recvT,
372
+ loc,
373
+ },
374
+ loc,
375
+ },
376
+ ];
377
+ }
378
+ L.liftedFns.push({ name: helper, params, returnType: recvT, locals, body, loc });
379
+ }
380
+ return {
381
+ kind: "call",
382
+ callee: helper,
383
+ args: registering
384
+ ? [receiver, strLit(name, loc), cbDyn, boolLit(once, loc), boolLit(prepend, loc)]
385
+ : [receiver, strLit(name, loc), cbDyn],
386
+ type: recvT,
387
+ loc,
388
+ };
389
+ }
390
+ /** A listener argument: lowered, checked void-returning, and its
391
+ * parameters checked as a typeEquals PREFIX of the event tuple. */
392
+ function lowerListenerArg(L, member, name, node, tuple) {
393
+ // Unannotated non-empty parameter lists have no static types (checker
394
+ // `any`; dyn in JS sources) — say so before the generic SC2001 speaks.
395
+ if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node)) && node.parameters.length > 0) {
396
+ for (const p of node.parameters) {
397
+ if (p.type === undefined && ts.isIdentifier(p.name)) {
398
+ const mapped = (() => {
399
+ try {
400
+ return L.mapTypeOf(L.typeOf(p.name));
401
+ }
402
+ catch {
403
+ return null;
404
+ }
405
+ })();
406
+ if (mapped === null || mapped.kind === "dyn" || mapped.kind === "jsval") {
407
+ L.noLowering(`'${member}' listeners with unannotated parameters`, p, "EventEmitter's declared listener type is (...args: any[]) — annotate each parameter with the emitted argument's type");
408
+ }
409
+ }
410
+ }
411
+ }
412
+ const cb = L.lowerExpr(node);
413
+ if (cb.type.kind !== "func") {
414
+ L.noLowering(`'${member}' with a non-function listener`, node);
415
+ }
416
+ const cbT = cb.type;
417
+ // Node ignores listener return values, so value-returning listeners
418
+ // (expression-body arrows, mustCall wrappers) register fine — the
419
+ // emitted invoke adapter calls through the listener's true signature
420
+ // and discards (releasing refcounted results). An async listener's
421
+ // promise is abandoned unobserved (SEMANTICS.md).
422
+ if (META_EVENTS.has(name) && cbT.params.length > 1) {
423
+ L.noLowering(`'${name}' listeners taking the listener-function argument`, node, "meta-event listeners take at most the event name (the listener argument has no unified static type)");
424
+ }
425
+ if (cbT.params.length > tuple.length) {
426
+ L.noLowering(`a '${name}' listener declaring ${cbT.params.length} parameters where the event's tuple has ${tuple.length}`, node, "listeners may declare a prefix of the event's emitted arguments");
427
+ }
428
+ for (let i = 0; i < cbT.params.length; i++) {
429
+ if (!typeEquals(cbT.params[i], tuple[i])) {
430
+ L.noLowering(`a '${name}' listener whose parameter ${i} is '${L.fmt(cbT.params[i])}' where the event's tuple has '${L.fmt(tuple[i])}'`, node, "every emit site and listener of one event name must agree on one argument tuple");
431
+ }
432
+ }
433
+ return cb;
434
+ }
435
+ /** `recv.<member>(...)` over an emitter-rooted receiver — the whole
436
+ * EventEmitter method surface. Returns null only for members this spoke
437
+ * does not own (the caller falls through to its own fences). */
438
+ export function lowerEmitterMethodCall(L, call, access, info) {
439
+ const member = access.name.text;
440
+ const loc = locOf(call);
441
+ const args = call.arguments;
442
+ // The class VALUE, not an instance (`EventEmitter.setMaxListeners(n)` —
443
+ // the receiver's checker type carries construct signatures; mapType
444
+ // answers the instance object for every EventEmitter-symbol type, so the
445
+ // instance dispatch conflated the two and handed the instance libCalls a
446
+ // receiver that lowers to the class value, the setMax ICE). The statics
447
+ // are a DIFFERENT surface: setMaxListeners(n) writes the process-wide
448
+ // defaultMaxListeners (validated at runtime — Node's ERR_OUT_OF_RANGE);
449
+ // everything else fences by its static name.
450
+ if (L.checker.getConstructSignatures(L.typeOf(access.expression)).length > 0) {
451
+ if (member === "setMaxListeners" && args.length === 1) {
452
+ const n = L.lowerExprExpecting(args[0], F64);
453
+ if (n.type.kind !== "f64") {
454
+ L.noLowering(`EventEmitter.setMaxListeners with a '${L.fmt(n.type)}' argument`, args[0], "the lowered form takes a number (Node throws ERR_INVALID_ARG_TYPE at runtime for other values)");
455
+ }
456
+ return { kind: "libCall", fn: "emitter.setDefaultMax", args: [n], type: VOID, loc };
457
+ }
458
+ if (member === "setMaxListeners") {
459
+ L.noLowering(`EventEmitter.setMaxListeners with ${args.length} arguments`, call, "the lowered static form is EventEmitter.setMaxListeners(n) — per-target application (…, ...eventTargets) has no lowering; call target.setMaxListeners(n) instead");
460
+ }
461
+ L.noLowering(`the static EventEmitter.${member} form`, call, "instance emitters lower this member; the class-value statics have no lowering yet");
462
+ }
463
+ const table = emitterEvents(L);
464
+ if (REGISTER_MEMBERS.has(member) || member === "off" || member === "removeListener") {
465
+ if (args.length !== 2) {
466
+ L.noLowering(`${member} with ${args.length} arguments`, call, "the supported form is (eventName, listener)");
467
+ }
468
+ const name = eventNameOf(L, member, args[0]);
469
+ const receiver = L.lowerExpr(access.expression);
470
+ const registering = REGISTER_MEMBERS.has(member);
471
+ const once = member === "once" || member === "prependOnceListener";
472
+ const prepend = member === "prependListener" || member === "prependOnceListener";
473
+ // Stream 'data' rides its own two-slot payload ABI (bytes + string —
474
+ // encoded streams deliver strings; scr_stream_emit_data): listeners
475
+ // on readable-sided receivers register through DATA thunks that
476
+ // unwrap the declared side (typed) or box by tag (dyn).
477
+ const sides = streamSidesOf(L, info);
478
+ if (name === "data" && (sides === "r" || sides === "rw")) {
479
+ const dynFlavor = dynListenerFlavor(L, args[1]);
480
+ if (dynFlavor !== null) {
481
+ return lowerDynListenerCall(L, member, name, [DYN], receiver, args[1], dynFlavor, registering, once, prepend, loc, true);
482
+ }
483
+ const cb = L.lowerExpr(args[1]);
484
+ if (cb.type.kind !== "func") {
485
+ L.noLowering(`'${member}' with a non-function listener`, args[1]);
486
+ }
487
+ const cbT = cb.type;
488
+ if (cbT.params.length > 1) {
489
+ L.noLowering(`a 'data' listener declaring ${cbT.params.length} parameters where the event carries one chunk`, args[1]);
490
+ }
491
+ const p = cbT.params[0];
492
+ if (p !== undefined && !(p.kind === "bytes" && p.elem === "u8") && p.kind !== "string") {
493
+ L.noLowering(`a 'data' listener whose chunk parameter is '${L.fmt(p)}'`, args[1], "chunks are Buffers — or strings once setEncoding/the encoding option applies");
494
+ }
495
+ if (!registering) {
496
+ return {
497
+ kind: "libCall",
498
+ fn: "emitter.off",
499
+ args: [receiver, strLit(name, loc), cb],
500
+ type: receiver.type,
501
+ loc,
502
+ };
503
+ }
504
+ return {
505
+ kind: "libCall",
506
+ fn: "emitter.onData",
507
+ args: [receiver, strLit(name, loc), cb, boolLit(once, loc), boolLit(prepend, loc)],
508
+ type: receiver.type,
509
+ loc,
510
+ };
511
+ }
512
+ // Stream-rooted receivers consult the per-base FORCED tuples first
513
+ // (runtime-emitted 'end'/'pipe'/... payloads); the dyn-listener check
514
+ // below then sees the forced tuple exactly like a table one.
515
+ const tuple = streamForcedTuple(L, info, name) ?? tupleOf(L, table, name, call);
516
+ const dynFlavor = dynListenerFlavor(L, args[1]);
517
+ if (dynFlavor !== null) {
518
+ return lowerDynListenerCall(L, member, name, tuple, receiver, args[1], dynFlavor, registering, once, prepend, loc, false);
519
+ }
520
+ const cb = lowerListenerArg(L, member, name, args[1], tuple);
521
+ return {
522
+ kind: "libCall",
523
+ fn: registering ? "emitter.on" : "emitter.off",
524
+ args: registering
525
+ ? [receiver, strLit(name, loc), cb, boolLit(once, loc), boolLit(prepend, loc)]
526
+ : [receiver, strLit(name, loc), cb],
527
+ type: receiver.type,
528
+ loc,
529
+ };
530
+ }
531
+ if (member === "emit") {
532
+ if (args.length === 0) {
533
+ L.noLowering("emit without an event name", call);
534
+ }
535
+ const name = eventNameOf(L, member, args[0]);
536
+ const receiver = L.lowerExpr(access.expression);
537
+ if (name === "error") {
538
+ // The special event: exactly one %Error-rooted payload; no listener
539
+ // means the runtime THROWS it (emitter.emitError, may-throw).
540
+ if (args.length !== 2) {
541
+ L.noLowering(`emit('error') with ${args.length - 1} payload arguments`, call, "the supported form is emit('error', err) with an Error-hierarchy payload (non-Error payloads would need Node's ERR_UNHANDLED_ERROR wrapping — no lowering yet)");
542
+ }
543
+ const err = L.lowerExpr(args[1]);
544
+ const rootsAtError = (t) => {
545
+ if (t.kind !== "object")
546
+ return false;
547
+ for (let c = L.classes.get(t.className) ?? null; c; c = c.base) {
548
+ if (c.def.name === "%Error")
549
+ return true;
550
+ }
551
+ return false;
552
+ };
553
+ if (!rootsAtError(err.type)) {
554
+ L.noLowering(`emit('error') with a '${L.fmt(err.type)}' payload`, args[1], "the supported payload is an Error-hierarchy instance");
555
+ }
556
+ return {
557
+ kind: "libCall",
558
+ fn: "emitter.emitError",
559
+ args: [receiver, strLit(name, loc), L.upcastTo(err, "%Error")],
560
+ type: BOOL,
561
+ loc,
562
+ };
563
+ }
564
+ // Stream 'data' rides the two-slot payload ABI: a user emit fills
565
+ // the chunk's slot (bytes or string), NULLs the other.
566
+ const emitSides = streamSidesOf(L, info);
567
+ if (name === "data" && (emitSides === "r" || emitSides === "rw")) {
568
+ if (args.length !== 2) {
569
+ L.noLowering(`emit('data') with ${args.length - 1} payload arguments`, call, "the event carries one chunk (a Buffer or string)");
570
+ }
571
+ const chunk = L.lowerExpr(args[1]);
572
+ if (!(chunk.type.kind === "bytes" && chunk.type.elem === "u8") && chunk.type.kind !== "string") {
573
+ L.noLowering(`emit('data') with a '${L.fmt(chunk.type)}' chunk`, args[1], "chunks are Buffers or strings");
574
+ }
575
+ return {
576
+ kind: "libCall",
577
+ fn: "emitter.emitData",
578
+ args: [receiver, strLit(name, loc), chunk],
579
+ type: BOOL,
580
+ loc,
581
+ };
582
+ }
583
+ const tuple = streamForcedTuple(L, info, name) ?? tupleOf(L, table, name, call);
584
+ if (args.length - 1 !== tuple.length) {
585
+ L.noLowering(`emit('${name}') with ${args.length - 1} arguments where the event's tuple has ${tuple.length}`, call, "every emit site of one event name must supply the same argument tuple (listeners may declare a prefix)");
586
+ }
587
+ const payload = args.slice(1).map((a, i) => L.lowerExprExpecting(a, tuple[i]));
588
+ return {
589
+ kind: "libCall",
590
+ fn: "emitter.emit",
591
+ args: [receiver, strLit(name, loc), ...payload],
592
+ type: BOOL,
593
+ loc,
594
+ };
595
+ }
596
+ // The pure-introspection members take ANY string-typed name — no tuple
597
+ // is involved, so the literal rule has nothing to protect (a meta
598
+ // listener naturally passes its name parameter along).
599
+ if (member === "removeAllListeners") {
600
+ if (args.length > 1) {
601
+ L.noLowering(`removeAllListeners with ${args.length} arguments`, call);
602
+ }
603
+ const all = args.length === 0;
604
+ const receiver = L.lowerExpr(access.expression);
605
+ const name = all ? strLit("", loc) : L.lowerExprExpecting(args[0], STRING);
606
+ if (name.type.kind !== "string") {
607
+ L.noLowering(`removeAllListeners with a '${L.fmt(name.type)}' event name`, args[0] ?? call);
608
+ }
609
+ return {
610
+ kind: "libCall",
611
+ fn: "emitter.removeAll",
612
+ args: [receiver, name, boolLit(all, loc)],
613
+ type: receiver.type,
614
+ loc,
615
+ };
616
+ }
617
+ if (member === "listenerCount") {
618
+ if (args.length !== 1 && args.length !== 2) {
619
+ L.noLowering(`listenerCount with ${args.length} arguments`, call);
620
+ }
621
+ const receiver = L.lowerExpr(access.expression);
622
+ const name = L.lowerExprExpecting(args[0], STRING);
623
+ if (name.type.kind !== "string") {
624
+ L.noLowering(`listenerCount with a '${L.fmt(name.type)}' event name`, args[0]);
625
+ }
626
+ if (args.length === 2) {
627
+ // The fn filter matches by identity — the listener's own type is
628
+ // its word; no tuple check is needed to count.
629
+ const cb = L.lowerExpr(args[1]);
630
+ if (cb.type.kind !== "func") {
631
+ L.noLowering(`listenerCount with a non-function filter`, args[1]);
632
+ }
633
+ return { kind: "libCall", fn: "emitter.countFn", args: [receiver, name, cb], type: F64, loc };
634
+ }
635
+ return { kind: "libCall", fn: "emitter.count", args: [receiver, name], type: F64, loc };
636
+ }
637
+ if (member === "listeners" || member === "rawListeners") {
638
+ // A fresh +1 closure array of the event's listeners in list order,
639
+ // element-typed by the event's unified tuple: every registered
640
+ // listener declared a typeEquals PREFIX of it, and calling one through
641
+ // the full-tuple signature delivers exactly what emit would (extra
642
+ // trailing arguments are ignored — JS's semantics, and the C calling
643
+ // convention's). The event NAME must be a compile-time literal — the
644
+ // element type depends on it. Both members answer the ORIGINALS: the
645
+ // once wrapper is runtime-internal, so rawListeners' wrapper identity
646
+ // is a documented divergence (SEMANTICS.md).
647
+ if (args.length !== 1) {
648
+ L.noLowering(`${member} with ${args.length} arguments`, call, "the supported form is (eventName)");
649
+ }
650
+ const name = eventNameOf(L, member, args[0]);
651
+ const sig = table.get(name);
652
+ if (sig?.dynListener) {
653
+ // A dyn-adapted registration means the runtime bucket can hold
654
+ // originals of MIXED signatures — no one honest element type.
655
+ L.noLowering(`${member} of the event '${name}'`, call, "a listener of this event is checked-dynamic (unannotated parameters), so the listener array has no one static element type — listenerCount(name) counts");
656
+ }
657
+ const tuple = tupleOf(L, table, name, call);
658
+ const receiver = L.lowerExpr(access.expression);
659
+ return {
660
+ kind: "libCall",
661
+ fn: "emitter.listeners",
662
+ args: [receiver, strLit(name, loc)],
663
+ type: arrayOf({ kind: "func", params: tuple, ret: { kind: "void" } }),
664
+ loc,
665
+ };
666
+ }
667
+ if (member === "eventNames") {
668
+ if (args.length !== 0)
669
+ L.noLowering(`eventNames with ${args.length} arguments`, call);
670
+ const receiver = L.lowerExpr(access.expression);
671
+ return { kind: "libCall", fn: "emitter.names", args: [receiver], type: arrayOf(STRING), loc };
672
+ }
673
+ if (member === "setMaxListeners") {
674
+ if (args.length !== 1)
675
+ L.noLowering(`setMaxListeners with ${args.length} arguments`, call);
676
+ const receiver = L.lowerExpr(access.expression);
677
+ const n = L.lowerExprExpecting(args[0], F64);
678
+ return { kind: "libCall", fn: "emitter.setMax", args: [receiver, n], type: receiver.type, loc };
679
+ }
680
+ if (member === "getMaxListeners") {
681
+ if (args.length !== 0)
682
+ L.noLowering(`getMaxListeners with ${args.length} arguments`, call);
683
+ const receiver = L.lowerExpr(access.expression);
684
+ return { kind: "libCall", fn: "emitter.getMax", args: [receiver], type: F64, loc };
685
+ }
686
+ return null;
687
+ }
688
+ //# sourceMappingURL=lower-emitter.js.map