@tsonic/emitter 0.0.6 → 0.0.13

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 (223) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/array.test.js +5 -5
  3. package/dist/array.test.js.map +1 -1
  4. package/dist/core/attributes.d.ts +43 -0
  5. package/dist/core/attributes.d.ts.map +1 -0
  6. package/dist/core/attributes.js +128 -0
  7. package/dist/core/attributes.js.map +1 -0
  8. package/dist/core/attributes.test.d.ts +5 -0
  9. package/dist/core/attributes.test.d.ts.map +1 -0
  10. package/dist/core/attributes.test.js +296 -0
  11. package/dist/core/attributes.test.js.map +1 -0
  12. package/dist/core/imports.test.js +6 -3
  13. package/dist/core/imports.test.js.map +1 -1
  14. package/dist/core/index.d.ts +2 -0
  15. package/dist/core/index.d.ts.map +1 -1
  16. package/dist/core/index.js +2 -0
  17. package/dist/core/index.js.map +1 -1
  18. package/dist/core/module-emitter/static-container.d.ts.map +1 -1
  19. package/dist/core/module-emitter/static-container.js +50 -1
  20. package/dist/core/module-emitter/static-container.js.map +1 -1
  21. package/dist/core/module-emitter.test.js +2 -1
  22. package/dist/core/module-emitter.test.js.map +1 -1
  23. package/dist/core/module-map.d.ts.map +1 -1
  24. package/dist/core/module-map.js +5 -1
  25. package/dist/core/module-map.js.map +1 -1
  26. package/dist/core/module-map.test.d.ts +8 -0
  27. package/dist/core/module-map.test.d.ts.map +1 -0
  28. package/dist/core/module-map.test.js +94 -0
  29. package/dist/core/module-map.test.js.map +1 -0
  30. package/dist/core/type-compatibility.d.ts +31 -0
  31. package/dist/core/type-compatibility.d.ts.map +1 -0
  32. package/dist/core/type-compatibility.js +99 -0
  33. package/dist/core/type-compatibility.js.map +1 -0
  34. package/dist/core/type-resolution.d.ts +83 -3
  35. package/dist/core/type-resolution.d.ts.map +1 -1
  36. package/dist/core/type-resolution.js +262 -4
  37. package/dist/core/type-resolution.js.map +1 -1
  38. package/dist/core/type-resolution.test.js +110 -1
  39. package/dist/core/type-resolution.test.js.map +1 -1
  40. package/dist/emitter-types/context.d.ts.map +1 -1
  41. package/dist/emitter-types/context.js +21 -1
  42. package/dist/emitter-types/context.js.map +1 -1
  43. package/dist/emitter-types/core.d.ts +26 -0
  44. package/dist/emitter-types/core.d.ts.map +1 -1
  45. package/dist/emitter-types/identifiers.d.ts.map +1 -1
  46. package/dist/emitter-types/identifiers.js +4 -43
  47. package/dist/emitter-types/identifiers.js.map +1 -1
  48. package/dist/emitter-types/index.d.ts +1 -1
  49. package/dist/emitter-types/index.d.ts.map +1 -1
  50. package/dist/emitter-types/index.js.map +1 -1
  51. package/dist/emitter.d.ts.map +1 -1
  52. package/dist/emitter.js +47 -1
  53. package/dist/emitter.js.map +1 -1
  54. package/dist/expression-emitter.d.ts.map +1 -1
  55. package/dist/expression-emitter.js +51 -3
  56. package/dist/expression-emitter.js.map +1 -1
  57. package/dist/expressions/access.d.ts.map +1 -1
  58. package/dist/expressions/access.js +138 -23
  59. package/dist/expressions/access.js.map +1 -1
  60. package/dist/expressions/calls.d.ts.map +1 -1
  61. package/dist/expressions/calls.js +90 -13
  62. package/dist/expressions/calls.js.map +1 -1
  63. package/dist/expressions/collections.d.ts +3 -2
  64. package/dist/expressions/collections.d.ts.map +1 -1
  65. package/dist/expressions/collections.js +251 -52
  66. package/dist/expressions/collections.js.map +1 -1
  67. package/dist/expressions/functions.d.ts +2 -2
  68. package/dist/expressions/functions.d.ts.map +1 -1
  69. package/dist/expressions/functions.js +81 -38
  70. package/dist/expressions/functions.js.map +1 -1
  71. package/dist/expressions/identifiers.d.ts.map +1 -1
  72. package/dist/expressions/identifiers.js +28 -7
  73. package/dist/expressions/identifiers.js.map +1 -1
  74. package/dist/expressions/index.test.js +191 -4
  75. package/dist/expressions/index.test.js.map +1 -1
  76. package/dist/expressions/literals.d.ts +7 -17
  77. package/dist/expressions/literals.d.ts.map +1 -1
  78. package/dist/expressions/literals.js +27 -87
  79. package/dist/expressions/literals.js.map +1 -1
  80. package/dist/expressions/literals.test.js +52 -2
  81. package/dist/expressions/literals.test.js.map +1 -1
  82. package/dist/expressions/operators.d.ts +29 -11
  83. package/dist/expressions/operators.d.ts.map +1 -1
  84. package/dist/expressions/operators.js +244 -67
  85. package/dist/expressions/operators.js.map +1 -1
  86. package/dist/expressions/other.d.ts +3 -0
  87. package/dist/expressions/other.d.ts.map +1 -1
  88. package/dist/expressions/other.js +27 -3
  89. package/dist/expressions/other.js.map +1 -1
  90. package/dist/generator-exchange.d.ts +1 -1
  91. package/dist/generator-exchange.d.ts.map +1 -1
  92. package/dist/generator-exchange.js +15 -4
  93. package/dist/generator-exchange.js.map +1 -1
  94. package/dist/generator-wrapper.d.ts +84 -0
  95. package/dist/generator-wrapper.d.ts.map +1 -0
  96. package/dist/generator-wrapper.js +312 -0
  97. package/dist/generator-wrapper.js.map +1 -0
  98. package/dist/generator-wrapper.test.d.ts +12 -0
  99. package/dist/generator-wrapper.test.d.ts.map +1 -0
  100. package/dist/generator-wrapper.test.js +179 -0
  101. package/dist/generator-wrapper.test.js.map +1 -0
  102. package/dist/generator.test.js +596 -6
  103. package/dist/generator.test.js.map +1 -1
  104. package/dist/golden-tests/config-parser.d.ts.map +1 -1
  105. package/dist/golden-tests/config-parser.js +81 -11
  106. package/dist/golden-tests/config-parser.js.map +1 -1
  107. package/dist/golden-tests/discovery.d.ts +14 -3
  108. package/dist/golden-tests/discovery.d.ts.map +1 -1
  109. package/dist/golden-tests/discovery.js +105 -12
  110. package/dist/golden-tests/discovery.js.map +1 -1
  111. package/dist/golden-tests/index.d.ts +1 -1
  112. package/dist/golden-tests/index.d.ts.map +1 -1
  113. package/dist/golden-tests/index.js.map +1 -1
  114. package/dist/golden-tests/runner.d.ts +1 -0
  115. package/dist/golden-tests/runner.d.ts.map +1 -1
  116. package/dist/golden-tests/runner.js +83 -25
  117. package/dist/golden-tests/runner.js.map +1 -1
  118. package/dist/golden-tests/types.d.ts +18 -1
  119. package/dist/golden-tests/types.d.ts.map +1 -1
  120. package/dist/golden.test.d.ts +12 -5
  121. package/dist/golden.test.d.ts.map +1 -1
  122. package/dist/golden.test.js +40 -21
  123. package/dist/golden.test.js.map +1 -1
  124. package/dist/hierarchical-bindings.test.js +2 -2
  125. package/dist/hierarchical-bindings.test.js.map +1 -1
  126. package/dist/integration.test.js +57 -10
  127. package/dist/integration.test.js.map +1 -1
  128. package/dist/invariants/emitter-globals-subset.test.d.ts +15 -0
  129. package/dist/invariants/emitter-globals-subset.test.d.ts.map +1 -0
  130. package/dist/invariants/emitter-globals-subset.test.js +137 -0
  131. package/dist/invariants/emitter-globals-subset.test.js.map +1 -0
  132. package/dist/invariants/numeric-proof-contract.test.d.ts +19 -0
  133. package/dist/invariants/numeric-proof-contract.test.d.ts.map +1 -0
  134. package/dist/invariants/numeric-proof-contract.test.js +565 -0
  135. package/dist/invariants/numeric-proof-contract.test.js.map +1 -0
  136. package/dist/specialization/generic-functions.test.js +376 -0
  137. package/dist/specialization/generic-functions.test.js.map +1 -1
  138. package/dist/specialization/interfaces.test.js +6 -6
  139. package/dist/specialization/interfaces.test.js.map +1 -1
  140. package/dist/specialization/substitution.d.ts.map +1 -1
  141. package/dist/specialization/substitution.js +7 -0
  142. package/dist/specialization/substitution.js.map +1 -1
  143. package/dist/specialization/type-aliases.test.js +88 -5
  144. package/dist/specialization/type-aliases.test.js.map +1 -1
  145. package/dist/statement-emitter.d.ts.map +1 -1
  146. package/dist/statement-emitter.js +5 -1
  147. package/dist/statement-emitter.js.map +1 -1
  148. package/dist/statements/blocks.d.ts +39 -1
  149. package/dist/statements/blocks.d.ts.map +1 -1
  150. package/dist/statements/blocks.js +129 -3
  151. package/dist/statements/blocks.js.map +1 -1
  152. package/dist/statements/classes/members/methods.d.ts.map +1 -1
  153. package/dist/statements/classes/members/methods.js +16 -5
  154. package/dist/statements/classes/members/methods.js.map +1 -1
  155. package/dist/statements/classes/members/properties.d.ts.map +1 -1
  156. package/dist/statements/classes/members/properties.js +10 -1
  157. package/dist/statements/classes/members/properties.js.map +1 -1
  158. package/dist/statements/classes/properties.d.ts.map +1 -1
  159. package/dist/statements/classes/properties.js +4 -0
  160. package/dist/statements/classes/properties.js.map +1 -1
  161. package/dist/statements/control/conditionals.d.ts.map +1 -1
  162. package/dist/statements/control/conditionals.js +352 -1
  163. package/dist/statements/control/conditionals.js.map +1 -1
  164. package/dist/statements/control/loops.d.ts +6 -0
  165. package/dist/statements/control/loops.d.ts.map +1 -1
  166. package/dist/statements/control/loops.js +9 -2
  167. package/dist/statements/control/loops.js.map +1 -1
  168. package/dist/statements/declarations/classes.d.ts.map +1 -1
  169. package/dist/statements/declarations/classes.js +20 -6
  170. package/dist/statements/declarations/classes.js.map +1 -1
  171. package/dist/statements/declarations/functions.d.ts.map +1 -1
  172. package/dist/statements/declarations/functions.js +98 -26
  173. package/dist/statements/declarations/functions.js.map +1 -1
  174. package/dist/statements/declarations/interfaces.d.ts.map +1 -1
  175. package/dist/statements/declarations/interfaces.js +11 -1
  176. package/dist/statements/declarations/interfaces.js.map +1 -1
  177. package/dist/statements/declarations/structs.test.js +7 -5
  178. package/dist/statements/declarations/structs.test.js.map +1 -1
  179. package/dist/statements/declarations/type-aliases.d.ts.map +1 -1
  180. package/dist/statements/declarations/type-aliases.js +18 -9
  181. package/dist/statements/declarations/type-aliases.js.map +1 -1
  182. package/dist/statements/declarations/variables.d.ts.map +1 -1
  183. package/dist/statements/declarations/variables.js +54 -2
  184. package/dist/statements/declarations/variables.js.map +1 -1
  185. package/dist/statements/index.test.js +164 -3
  186. package/dist/statements/index.test.js.map +1 -1
  187. package/dist/types/arrays.d.ts +10 -1
  188. package/dist/types/arrays.d.ts.map +1 -1
  189. package/dist/types/arrays.js +16 -1
  190. package/dist/types/arrays.js.map +1 -1
  191. package/dist/types/dictionaries.d.ts +3 -2
  192. package/dist/types/dictionaries.d.ts.map +1 -1
  193. package/dist/types/dictionaries.js +14 -8
  194. package/dist/types/dictionaries.js.map +1 -1
  195. package/dist/types/emitter.d.ts.map +1 -1
  196. package/dist/types/emitter.js +3 -0
  197. package/dist/types/emitter.js.map +1 -1
  198. package/dist/types/index.test.js +5 -2
  199. package/dist/types/index.test.js.map +1 -1
  200. package/dist/types/parameters.d.ts.map +1 -1
  201. package/dist/types/parameters.js +29 -0
  202. package/dist/types/parameters.js.map +1 -1
  203. package/dist/types/primitives.d.ts +12 -1
  204. package/dist/types/primitives.d.ts.map +1 -1
  205. package/dist/types/primitives.js +14 -1
  206. package/dist/types/primitives.js.map +1 -1
  207. package/dist/types/references.d.ts.map +1 -1
  208. package/dist/types/references.js +136 -30
  209. package/dist/types/references.js.map +1 -1
  210. package/dist/types/references.test.d.ts +11 -0
  211. package/dist/types/references.test.d.ts.map +1 -0
  212. package/dist/types/references.test.js +382 -0
  213. package/dist/types/references.test.js.map +1 -0
  214. package/dist/types/tuples.d.ts +23 -0
  215. package/dist/types/tuples.d.ts.map +1 -0
  216. package/dist/types/tuples.js +54 -0
  217. package/dist/types/tuples.js.map +1 -0
  218. package/dist/types/unions.test.js +62 -15
  219. package/dist/types/unions.test.js.map +1 -1
  220. package/dist/types.d.ts +1 -1
  221. package/dist/types.d.ts.map +1 -1
  222. package/dist/types.js.map +1 -1
  223. package/package.json +7 -3
@@ -84,10 +84,10 @@ describe("Generator Emission", () => {
84
84
  expect(code).to.include("public sealed class counter_exchange");
85
85
  expect(code).to.include("public object? Input { get; set; }");
86
86
  expect(code).to.include("public double Output { get; set; }");
87
- // Should have IEnumerable return type
88
- expect(code).to.include("public static IEnumerable<counter_exchange> counter()");
89
- // Should use System.Collections.Generic
90
- expect(code).to.include("using System.Collections.Generic");
87
+ // Should have IEnumerable return type with fully-qualified name
88
+ expect(code).to.include("counter_exchange> counter()");
89
+ // Should NOT use using directives - all types use global:: FQN
90
+ expect(code).to.not.include("using System.Collections.Generic");
91
91
  // Should initialize exchange variable
92
92
  expect(code).to.include("var exchange = new counter_exchange()");
93
93
  // Should emit yield with exchange object pattern
@@ -170,8 +170,598 @@ describe("Generator Emission", () => {
170
170
  const code = emitModule(module);
171
171
  // Should contain exchange class
172
172
  expect(code).to.include("public sealed class asyncCounter_exchange");
173
- // Should have IAsyncEnumerable return type with async
174
- expect(code).to.include("public static async IAsyncEnumerable<asyncCounter_exchange> asyncCounter()");
173
+ // Should have IAsyncEnumerable return type with async and global:: FQN
174
+ expect(code).to.include("public static async global::System.Collections.Generic.IAsyncEnumerable<asyncCounter_exchange> asyncCounter()");
175
+ });
176
+ describe("Bidirectional Generators", () => {
177
+ it("should generate wrapper class for bidirectional generator", () => {
178
+ const module = {
179
+ kind: "module",
180
+ filePath: "/test/accumulator.ts",
181
+ namespace: "Test",
182
+ className: "accumulator",
183
+ isStaticContainer: true,
184
+ imports: [],
185
+ exports: [],
186
+ body: [
187
+ {
188
+ kind: "functionDeclaration",
189
+ name: "accumulator",
190
+ parameters: [
191
+ {
192
+ kind: "parameter",
193
+ pattern: { kind: "identifierPattern", name: "start" },
194
+ type: { kind: "primitiveType", name: "number" },
195
+ isOptional: false,
196
+ isRest: false,
197
+ passing: "value",
198
+ },
199
+ ],
200
+ returnType: {
201
+ kind: "referenceType",
202
+ name: "Generator",
203
+ typeArguments: [
204
+ { kind: "primitiveType", name: "number" }, // Yield
205
+ { kind: "voidType" }, // Return
206
+ { kind: "primitiveType", name: "number" }, // Next (bidirectional!)
207
+ ],
208
+ },
209
+ body: {
210
+ kind: "blockStatement",
211
+ statements: [
212
+ {
213
+ kind: "variableDeclaration",
214
+ declarationKind: "let",
215
+ isExported: false,
216
+ declarations: [
217
+ {
218
+ kind: "variableDeclarator",
219
+ name: { kind: "identifierPattern", name: "total" },
220
+ type: { kind: "primitiveType", name: "number" },
221
+ initializer: { kind: "identifier", name: "start" },
222
+ },
223
+ ],
224
+ },
225
+ {
226
+ kind: "whileStatement",
227
+ condition: { kind: "literal", value: true },
228
+ body: {
229
+ kind: "blockStatement",
230
+ statements: [
231
+ // Using yieldStatement (lowered form)
232
+ {
233
+ kind: "yieldStatement",
234
+ output: { kind: "identifier", name: "total" },
235
+ delegate: false,
236
+ receiveTarget: {
237
+ kind: "identifierPattern",
238
+ name: "received",
239
+ },
240
+ receivedType: { kind: "primitiveType", name: "number" },
241
+ },
242
+ {
243
+ kind: "expressionStatement",
244
+ expression: {
245
+ kind: "assignment",
246
+ operator: "=",
247
+ left: { kind: "identifier", name: "total" },
248
+ right: {
249
+ kind: "binary",
250
+ operator: "+",
251
+ left: { kind: "identifier", name: "total" },
252
+ right: { kind: "identifier", name: "received" },
253
+ },
254
+ },
255
+ },
256
+ ],
257
+ },
258
+ },
259
+ ],
260
+ },
261
+ isAsync: false,
262
+ isGenerator: true,
263
+ isExported: true,
264
+ },
265
+ ],
266
+ };
267
+ const code = emitModule(module);
268
+ // Note: IteratorResult<T> is now in Tsonic.Runtime, not emitted per-module
269
+ // Should generate exchange class
270
+ expect(code).to.include("public sealed class accumulator_exchange");
271
+ expect(code).to.include("public double? Input { get; set; }");
272
+ expect(code).to.include("public double Output { get; set; }");
273
+ // Should generate wrapper class
274
+ expect(code).to.include("public sealed class accumulator_Generator");
275
+ expect(code).to.include("IEnumerator<accumulator_exchange> _enumerator");
276
+ expect(code).to.include("accumulator_exchange _exchange");
277
+ // next() method with nullable parameter
278
+ expect(code).to.include("global::Tsonic.Runtime.IteratorResult<double> next(double? value");
279
+ expect(code).to.include("_exchange.Input = value");
280
+ expect(code).to.include("MoveNext()");
281
+ // return() and throw() methods
282
+ expect(code).to.include("global::Tsonic.Runtime.IteratorResult<double> @return(");
283
+ expect(code).to.include("global::Tsonic.Runtime.IteratorResult<double> @throw(object e)");
284
+ // Function should return wrapper type
285
+ expect(code).to.include("accumulator_Generator accumulator(");
286
+ // Should use local iterator pattern
287
+ expect(code).to.include("__iterator()");
288
+ expect(code).to.include("return new accumulator_Generator(__iterator(), exchange)");
289
+ });
290
+ it("should emit yieldStatement with receiveTarget", () => {
291
+ const module = {
292
+ kind: "module",
293
+ filePath: "/test/receiver.ts",
294
+ namespace: "Test",
295
+ className: "receiver",
296
+ isStaticContainer: true,
297
+ imports: [],
298
+ exports: [],
299
+ body: [
300
+ {
301
+ kind: "functionDeclaration",
302
+ name: "receiver",
303
+ parameters: [],
304
+ returnType: {
305
+ kind: "referenceType",
306
+ name: "Generator",
307
+ typeArguments: [
308
+ { kind: "primitiveType", name: "number" },
309
+ { kind: "voidType" },
310
+ { kind: "primitiveType", name: "string" },
311
+ ],
312
+ },
313
+ body: {
314
+ kind: "blockStatement",
315
+ statements: [
316
+ {
317
+ kind: "yieldStatement",
318
+ output: { kind: "literal", value: 42 },
319
+ delegate: false,
320
+ receiveTarget: { kind: "identifierPattern", name: "msg" },
321
+ receivedType: { kind: "primitiveType", name: "string" },
322
+ },
323
+ ],
324
+ },
325
+ isAsync: false,
326
+ isGenerator: true,
327
+ isExported: true,
328
+ },
329
+ ],
330
+ };
331
+ const code = emitModule(module);
332
+ // Should emit yield output - integer literal emits as-is
333
+ expect(code).to.include("exchange.Output = 42");
334
+ expect(code).to.include("yield return exchange");
335
+ // Should emit receive pattern with null coalescing
336
+ expect(code).to.include("var msg = exchange.Input ?? default!");
337
+ });
338
+ it("should handle unidirectional generator without wrapper", () => {
339
+ const module = {
340
+ kind: "module",
341
+ filePath: "/test/unidirectional.ts",
342
+ namespace: "Test",
343
+ className: "unidirectional",
344
+ isStaticContainer: true,
345
+ imports: [],
346
+ exports: [],
347
+ body: [
348
+ {
349
+ kind: "functionDeclaration",
350
+ name: "range",
351
+ parameters: [],
352
+ returnType: {
353
+ kind: "referenceType",
354
+ name: "Generator",
355
+ typeArguments: [
356
+ { kind: "primitiveType", name: "number" },
357
+ { kind: "voidType" },
358
+ { kind: "primitiveType", name: "undefined" }, // No TNext!
359
+ ],
360
+ },
361
+ body: {
362
+ kind: "blockStatement",
363
+ statements: [
364
+ {
365
+ kind: "expressionStatement",
366
+ expression: {
367
+ kind: "yield",
368
+ expression: { kind: "literal", value: 1 },
369
+ delegate: false,
370
+ },
371
+ },
372
+ ],
373
+ },
374
+ isAsync: false,
375
+ isGenerator: true,
376
+ isExported: true,
377
+ },
378
+ ],
379
+ };
380
+ const code = emitModule(module);
381
+ // Should NOT generate wrapper class for unidirectional
382
+ expect(code).to.not.include("range_Generator");
383
+ expect(code).to.not.include("IteratorResult<");
384
+ // Should use IEnumerable return type
385
+ expect(code).to.include("IEnumerable<range_exchange> range()");
386
+ // Should generate exchange class
387
+ expect(code).to.include("public sealed class range_exchange");
388
+ });
389
+ it("should handle async bidirectional generator", () => {
390
+ const module = {
391
+ kind: "module",
392
+ filePath: "/test/asyncBidir.ts",
393
+ namespace: "Test",
394
+ className: "asyncBidir",
395
+ isStaticContainer: true,
396
+ imports: [],
397
+ exports: [],
398
+ body: [
399
+ {
400
+ kind: "functionDeclaration",
401
+ name: "asyncAccumulator",
402
+ parameters: [],
403
+ returnType: {
404
+ kind: "referenceType",
405
+ name: "AsyncGenerator",
406
+ typeArguments: [
407
+ { kind: "primitiveType", name: "number" },
408
+ { kind: "voidType" },
409
+ { kind: "primitiveType", name: "number" },
410
+ ],
411
+ },
412
+ body: {
413
+ kind: "blockStatement",
414
+ statements: [
415
+ {
416
+ kind: "yieldStatement",
417
+ output: { kind: "literal", value: 0 },
418
+ delegate: false,
419
+ receiveTarget: { kind: "identifierPattern", name: "val" },
420
+ },
421
+ ],
422
+ },
423
+ isAsync: true,
424
+ isGenerator: true,
425
+ isExported: true,
426
+ },
427
+ ],
428
+ };
429
+ const code = emitModule(module);
430
+ // Should generate async wrapper
431
+ expect(code).to.include("asyncAccumulator_Generator");
432
+ expect(code).to.include("IAsyncEnumerator<asyncAccumulator_exchange>");
433
+ expect(code).to.include("async global::System.Threading.Tasks.Task<global::Tsonic.Runtime.IteratorResult<double>> next(");
434
+ expect(code).to.include("await _enumerator.MoveNextAsync()");
435
+ });
436
+ describe("Edge Cases", () => {
437
+ it("should handle string TNext type (non-number)", () => {
438
+ // Generator<number, void, string> - receives strings
439
+ const module = {
440
+ kind: "module",
441
+ filePath: "/test/stringNext.ts",
442
+ namespace: "Test",
443
+ className: "stringNext",
444
+ isStaticContainer: true,
445
+ imports: [],
446
+ exports: [],
447
+ body: [
448
+ {
449
+ kind: "functionDeclaration",
450
+ name: "stringReceiver",
451
+ parameters: [],
452
+ returnType: {
453
+ kind: "referenceType",
454
+ name: "Generator",
455
+ typeArguments: [
456
+ { kind: "primitiveType", name: "number" },
457
+ { kind: "voidType" },
458
+ { kind: "primitiveType", name: "string" }, // TNext is string
459
+ ],
460
+ },
461
+ body: {
462
+ kind: "blockStatement",
463
+ statements: [
464
+ {
465
+ kind: "yieldStatement",
466
+ output: { kind: "literal", value: 42 },
467
+ delegate: false,
468
+ receiveTarget: { kind: "identifierPattern", name: "msg" },
469
+ },
470
+ ],
471
+ },
472
+ isAsync: false,
473
+ isGenerator: true,
474
+ isExported: true,
475
+ },
476
+ ],
477
+ };
478
+ const code = emitModule(module);
479
+ // Should generate wrapper with string? Input
480
+ expect(code).to.include("public string? Input { get; set; }");
481
+ // next() method should accept string?
482
+ expect(code).to.include("next(string? value = default)");
483
+ });
484
+ it("should use await foreach for async yield* delegation", () => {
485
+ // Async generator with yield* should use await foreach
486
+ const module = {
487
+ kind: "module",
488
+ filePath: "/test/asyncYieldStar.ts",
489
+ namespace: "Test",
490
+ className: "asyncYieldStar",
491
+ isStaticContainer: true,
492
+ imports: [],
493
+ exports: [],
494
+ body: [
495
+ {
496
+ kind: "functionDeclaration",
497
+ name: "asyncDelegate",
498
+ parameters: [],
499
+ returnType: {
500
+ kind: "referenceType",
501
+ name: "AsyncGenerator",
502
+ typeArguments: [
503
+ { kind: "primitiveType", name: "number" },
504
+ { kind: "voidType" },
505
+ { kind: "primitiveType", name: "number" },
506
+ ],
507
+ },
508
+ body: {
509
+ kind: "blockStatement",
510
+ statements: [
511
+ {
512
+ kind: "yieldStatement",
513
+ output: { kind: "identifier", name: "otherGen" },
514
+ delegate: true, // yield*
515
+ },
516
+ ],
517
+ },
518
+ isAsync: true,
519
+ isGenerator: true,
520
+ isExported: true,
521
+ },
522
+ ],
523
+ };
524
+ const code = emitModule(module);
525
+ // Should use await foreach, not just foreach
526
+ expect(code).to.include("await foreach");
527
+ expect(code).to.include("(var item in otherGen)");
528
+ });
529
+ });
530
+ describe("Pattern receiveTargets", () => {
531
+ it("should emit array destructuring from yield", () => {
532
+ // const [a, b] = yield expr;
533
+ const module = {
534
+ kind: "module",
535
+ filePath: "/test/arrayPattern.ts",
536
+ namespace: "Test",
537
+ className: "arrayPattern",
538
+ isStaticContainer: true,
539
+ imports: [],
540
+ exports: [],
541
+ body: [
542
+ {
543
+ kind: "functionDeclaration",
544
+ name: "arrayDestructure",
545
+ parameters: [],
546
+ returnType: {
547
+ kind: "referenceType",
548
+ name: "Generator",
549
+ typeArguments: [
550
+ { kind: "primitiveType", name: "number" },
551
+ { kind: "voidType" },
552
+ {
553
+ kind: "arrayType",
554
+ elementType: { kind: "primitiveType", name: "number" },
555
+ },
556
+ ],
557
+ },
558
+ body: {
559
+ kind: "blockStatement",
560
+ statements: [
561
+ {
562
+ kind: "yieldStatement",
563
+ output: { kind: "literal", value: 1 },
564
+ delegate: false,
565
+ receiveTarget: {
566
+ kind: "arrayPattern",
567
+ elements: [
568
+ { kind: "identifierPattern", name: "a" },
569
+ { kind: "identifierPattern", name: "b" },
570
+ ],
571
+ },
572
+ },
573
+ ],
574
+ },
575
+ isAsync: false,
576
+ isGenerator: true,
577
+ isExported: true,
578
+ },
579
+ ],
580
+ };
581
+ const code = emitModule(module);
582
+ // Should emit array destructuring pattern
583
+ expect(code).to.include("var __input = exchange.Input");
584
+ expect(code).to.include("var a = __input[0]");
585
+ expect(code).to.include("var b = __input[1]");
586
+ });
587
+ it("should emit object destructuring from yield", () => {
588
+ // const {x, y} = yield expr;
589
+ // Note: We use a reference type (Point) for TNext since inline object types
590
+ // are not supported by the emitter (TSN7403)
591
+ const module = {
592
+ kind: "module",
593
+ filePath: "/test/objectPattern.ts",
594
+ namespace: "Test",
595
+ className: "objectPattern",
596
+ isStaticContainer: true,
597
+ imports: [],
598
+ exports: [],
599
+ body: [
600
+ {
601
+ kind: "functionDeclaration",
602
+ name: "objectDestructure",
603
+ parameters: [],
604
+ returnType: {
605
+ kind: "referenceType",
606
+ name: "Generator",
607
+ typeArguments: [
608
+ { kind: "primitiveType", name: "number" },
609
+ { kind: "voidType" },
610
+ // Use a reference type for TNext since inline object types
611
+ // aren't supported. The test focuses on pattern emission,
612
+ // not type resolution.
613
+ {
614
+ kind: "referenceType",
615
+ name: "Point",
616
+ typeArguments: [],
617
+ resolvedClrType: "Point",
618
+ },
619
+ ],
620
+ },
621
+ body: {
622
+ kind: "blockStatement",
623
+ statements: [
624
+ {
625
+ kind: "yieldStatement",
626
+ output: { kind: "literal", value: 42 },
627
+ delegate: false,
628
+ receiveTarget: {
629
+ kind: "objectPattern",
630
+ properties: [
631
+ {
632
+ kind: "property",
633
+ key: "x",
634
+ value: { kind: "identifierPattern", name: "x" },
635
+ shorthand: true,
636
+ },
637
+ {
638
+ kind: "property",
639
+ key: "y",
640
+ value: { kind: "identifierPattern", name: "y" },
641
+ shorthand: true,
642
+ },
643
+ ],
644
+ },
645
+ },
646
+ ],
647
+ },
648
+ isAsync: false,
649
+ isGenerator: true,
650
+ isExported: true,
651
+ },
652
+ ],
653
+ };
654
+ const code = emitModule(module);
655
+ // Should emit object destructuring pattern
656
+ expect(code).to.include("var __input = exchange.Input");
657
+ expect(code).to.include("var x = __input.x");
658
+ expect(code).to.include("var y = __input.y");
659
+ });
660
+ });
661
+ describe("Generator Return Statement", () => {
662
+ it("should emit __returnValue assignment and yield break for generatorReturnStatement", () => {
663
+ const module = {
664
+ kind: "module",
665
+ filePath: "/test/generatorReturn.ts",
666
+ namespace: "Test",
667
+ className: "generatorReturn",
668
+ isStaticContainer: true,
669
+ imports: [],
670
+ exports: [],
671
+ body: [
672
+ {
673
+ kind: "functionDeclaration",
674
+ name: "genWithReturn",
675
+ parameters: [],
676
+ returnType: {
677
+ kind: "referenceType",
678
+ name: "Generator",
679
+ typeArguments: [
680
+ { kind: "primitiveType", name: "number" },
681
+ { kind: "primitiveType", name: "string" }, // TReturn is string, not void
682
+ { kind: "primitiveType", name: "number" },
683
+ ],
684
+ },
685
+ body: {
686
+ kind: "blockStatement",
687
+ statements: [
688
+ {
689
+ kind: "yieldStatement",
690
+ output: { kind: "literal", value: 1 },
691
+ delegate: false,
692
+ },
693
+ {
694
+ kind: "generatorReturnStatement",
695
+ expression: { kind: "literal", value: "done" },
696
+ },
697
+ ],
698
+ },
699
+ isAsync: false,
700
+ isGenerator: true,
701
+ isExported: true,
702
+ },
703
+ ],
704
+ };
705
+ const code = emitModule(module);
706
+ // Should emit __returnValue assignment
707
+ expect(code).to.include('__returnValue = "done"');
708
+ // Should emit yield break to terminate iterator
709
+ expect(code).to.include("yield break;");
710
+ // Wrapper should declare __returnValue
711
+ expect(code).to.include("string __returnValue = default!");
712
+ // Wrapper should use _getReturnValue
713
+ expect(code).to.include("_getReturnValue");
714
+ });
715
+ it("should emit bare yield break for generatorReturnStatement without expression", () => {
716
+ const module = {
717
+ kind: "module",
718
+ filePath: "/test/bareReturn.ts",
719
+ namespace: "Test",
720
+ className: "bareReturn",
721
+ isStaticContainer: true,
722
+ imports: [],
723
+ exports: [],
724
+ body: [
725
+ {
726
+ kind: "functionDeclaration",
727
+ name: "genBareReturn",
728
+ parameters: [],
729
+ returnType: {
730
+ kind: "referenceType",
731
+ name: "Generator",
732
+ typeArguments: [
733
+ { kind: "primitiveType", name: "number" },
734
+ { kind: "voidType" }, // TReturn is void
735
+ { kind: "primitiveType", name: "number" },
736
+ ],
737
+ },
738
+ body: {
739
+ kind: "blockStatement",
740
+ statements: [
741
+ {
742
+ kind: "yieldStatement",
743
+ output: { kind: "literal", value: 1 },
744
+ delegate: false,
745
+ },
746
+ {
747
+ kind: "generatorReturnStatement",
748
+ expression: undefined, // bare return
749
+ },
750
+ ],
751
+ },
752
+ isAsync: false,
753
+ isGenerator: true,
754
+ isExported: true,
755
+ },
756
+ ],
757
+ };
758
+ const code = emitModule(module);
759
+ // Should emit yield break (no __returnValue assignment)
760
+ expect(code).to.include("yield break;");
761
+ // Should NOT have _getReturnValue for void return
762
+ expect(code).not.to.include("_getReturnValue");
763
+ });
764
+ });
175
765
  });
176
766
  });
177
767
  //# sourceMappingURL=generator.test.js.map