@tsonic/emitter 0.0.6 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/array.test.js +6 -6
- package/dist/array.test.js.map +1 -1
- package/dist/core/imports.test.js +6 -3
- package/dist/core/imports.test.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/type-compatibility.d.ts +26 -0
- package/dist/core/type-compatibility.d.ts.map +1 -0
- package/dist/core/type-compatibility.js +109 -0
- package/dist/core/type-compatibility.js.map +1 -0
- package/dist/core/type-resolution.d.ts +81 -1
- package/dist/core/type-resolution.d.ts.map +1 -1
- package/dist/core/type-resolution.js +258 -0
- package/dist/core/type-resolution.js.map +1 -1
- package/dist/core/type-resolution.test.js +110 -1
- package/dist/core/type-resolution.test.js.map +1 -1
- package/dist/emitter-types/context.d.ts.map +1 -1
- package/dist/emitter-types/context.js +21 -1
- package/dist/emitter-types/context.js.map +1 -1
- package/dist/emitter-types/core.d.ts +26 -0
- package/dist/emitter-types/core.d.ts.map +1 -1
- package/dist/emitter-types/identifiers.d.ts.map +1 -1
- package/dist/emitter-types/identifiers.js +4 -43
- package/dist/emitter-types/identifiers.js.map +1 -1
- package/dist/emitter-types/index.d.ts +1 -1
- package/dist/emitter-types/index.d.ts.map +1 -1
- package/dist/emitter-types/index.js.map +1 -1
- package/dist/expression-emitter.d.ts.map +1 -1
- package/dist/expression-emitter.js +48 -0
- package/dist/expression-emitter.js.map +1 -1
- package/dist/expressions/access.d.ts.map +1 -1
- package/dist/expressions/access.js +97 -13
- package/dist/expressions/access.js.map +1 -1
- package/dist/expressions/calls.d.ts.map +1 -1
- package/dist/expressions/calls.js +5 -1
- package/dist/expressions/calls.js.map +1 -1
- package/dist/expressions/collections.d.ts +3 -2
- package/dist/expressions/collections.d.ts.map +1 -1
- package/dist/expressions/collections.js +214 -24
- package/dist/expressions/collections.js.map +1 -1
- package/dist/expressions/functions.d.ts +2 -2
- package/dist/expressions/functions.d.ts.map +1 -1
- package/dist/expressions/functions.js +81 -38
- package/dist/expressions/functions.js.map +1 -1
- package/dist/expressions/identifiers.d.ts.map +1 -1
- package/dist/expressions/identifiers.js +27 -7
- package/dist/expressions/identifiers.js.map +1 -1
- package/dist/expressions/index.test.js +189 -4
- package/dist/expressions/index.test.js.map +1 -1
- package/dist/expressions/literals.d.ts +4 -6
- package/dist/expressions/literals.d.ts.map +1 -1
- package/dist/expressions/literals.js +41 -17
- package/dist/expressions/literals.js.map +1 -1
- package/dist/expressions/literals.test.js +41 -0
- package/dist/expressions/literals.test.js.map +1 -1
- package/dist/expressions/operators.d.ts +4 -0
- package/dist/expressions/operators.d.ts.map +1 -1
- package/dist/expressions/operators.js +145 -12
- package/dist/expressions/operators.js.map +1 -1
- package/dist/expressions/other.d.ts.map +1 -1
- package/dist/expressions/other.js +9 -2
- package/dist/expressions/other.js.map +1 -1
- package/dist/generator-exchange.d.ts +1 -1
- package/dist/generator-exchange.d.ts.map +1 -1
- package/dist/generator-exchange.js +15 -4
- package/dist/generator-exchange.js.map +1 -1
- package/dist/generator-wrapper.d.ts +84 -0
- package/dist/generator-wrapper.d.ts.map +1 -0
- package/dist/generator-wrapper.js +312 -0
- package/dist/generator-wrapper.js.map +1 -0
- package/dist/generator-wrapper.test.d.ts +12 -0
- package/dist/generator-wrapper.test.d.ts.map +1 -0
- package/dist/generator-wrapper.test.js +179 -0
- package/dist/generator-wrapper.test.js.map +1 -0
- package/dist/generator.test.js +596 -6
- package/dist/generator.test.js.map +1 -1
- package/dist/golden-tests/config-parser.d.ts.map +1 -1
- package/dist/golden-tests/config-parser.js +81 -11
- package/dist/golden-tests/config-parser.js.map +1 -1
- package/dist/golden-tests/discovery.d.ts.map +1 -1
- package/dist/golden-tests/discovery.js +15 -5
- package/dist/golden-tests/discovery.js.map +1 -1
- package/dist/golden-tests/runner.d.ts.map +1 -1
- package/dist/golden-tests/runner.js +62 -7
- package/dist/golden-tests/runner.js.map +1 -1
- package/dist/golden-tests/types.d.ts +11 -1
- package/dist/golden-tests/types.d.ts.map +1 -1
- package/dist/hierarchical-bindings.test.js +2 -2
- package/dist/hierarchical-bindings.test.js.map +1 -1
- package/dist/integration.test.js +49 -2
- package/dist/integration.test.js.map +1 -1
- package/dist/invariants/emitter-globals-subset.test.d.ts +15 -0
- package/dist/invariants/emitter-globals-subset.test.d.ts.map +1 -0
- package/dist/invariants/emitter-globals-subset.test.js +137 -0
- package/dist/invariants/emitter-globals-subset.test.js.map +1 -0
- package/dist/invariants/numeric-proof-contract.test.d.ts +19 -0
- package/dist/invariants/numeric-proof-contract.test.d.ts.map +1 -0
- package/dist/invariants/numeric-proof-contract.test.js +560 -0
- package/dist/invariants/numeric-proof-contract.test.js.map +1 -0
- package/dist/specialization/generic-functions.test.js +10 -0
- package/dist/specialization/generic-functions.test.js.map +1 -1
- package/dist/specialization/substitution.d.ts.map +1 -1
- package/dist/specialization/substitution.js +7 -0
- package/dist/specialization/substitution.js.map +1 -1
- package/dist/statement-emitter.d.ts.map +1 -1
- package/dist/statement-emitter.js +5 -1
- package/dist/statement-emitter.js.map +1 -1
- package/dist/statements/blocks.d.ts +39 -1
- package/dist/statements/blocks.d.ts.map +1 -1
- package/dist/statements/blocks.js +129 -3
- package/dist/statements/blocks.js.map +1 -1
- package/dist/statements/classes/members/methods.d.ts.map +1 -1
- package/dist/statements/classes/members/methods.js +3 -1
- package/dist/statements/classes/members/methods.js.map +1 -1
- package/dist/statements/control/conditionals.d.ts.map +1 -1
- package/dist/statements/control/conditionals.js +215 -1
- package/dist/statements/control/conditionals.js.map +1 -1
- package/dist/statements/control/loops.d.ts +6 -0
- package/dist/statements/control/loops.d.ts.map +1 -1
- package/dist/statements/control/loops.js +9 -2
- package/dist/statements/control/loops.js.map +1 -1
- package/dist/statements/declarations/classes.d.ts.map +1 -1
- package/dist/statements/declarations/classes.js +13 -5
- package/dist/statements/declarations/classes.js.map +1 -1
- package/dist/statements/declarations/functions.d.ts.map +1 -1
- package/dist/statements/declarations/functions.js +91 -25
- package/dist/statements/declarations/functions.js.map +1 -1
- package/dist/statements/declarations/interfaces.d.ts.map +1 -1
- package/dist/statements/declarations/interfaces.js +11 -1
- package/dist/statements/declarations/interfaces.js.map +1 -1
- package/dist/statements/declarations/type-aliases.d.ts.map +1 -1
- package/dist/statements/declarations/type-aliases.js +11 -1
- package/dist/statements/declarations/type-aliases.js.map +1 -1
- package/dist/statements/index.test.js +165 -3
- package/dist/statements/index.test.js.map +1 -1
- package/dist/types/arrays.d.ts +10 -1
- package/dist/types/arrays.d.ts.map +1 -1
- package/dist/types/arrays.js +16 -1
- package/dist/types/arrays.js.map +1 -1
- package/dist/types/dictionaries.d.ts +3 -2
- package/dist/types/dictionaries.d.ts.map +1 -1
- package/dist/types/dictionaries.js +14 -8
- package/dist/types/dictionaries.js.map +1 -1
- package/dist/types/emitter.d.ts.map +1 -1
- package/dist/types/emitter.js +3 -0
- package/dist/types/emitter.js.map +1 -1
- package/dist/types/index.test.js +5 -2
- package/dist/types/index.test.js.map +1 -1
- package/dist/types/references.d.ts.map +1 -1
- package/dist/types/references.js +128 -29
- package/dist/types/references.js.map +1 -1
- package/dist/types/references.test.d.ts +11 -0
- package/dist/types/references.test.d.ts.map +1 -0
- package/dist/types/references.test.js +384 -0
- package/dist/types/references.test.js.map +1 -0
- package/dist/types/tuples.d.ts +23 -0
- package/dist/types/tuples.d.ts.map +1 -0
- package/dist/types/tuples.js +54 -0
- package/dist/types/tuples.js.map +1 -0
- package/dist/types/unions.test.js +62 -15
- package/dist/types/unions.test.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
package/dist/generator.test.js
CHANGED
|
@@ -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("
|
|
89
|
-
// Should use
|
|
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
|
|
333
|
+
expect(code).to.include("exchange.Output = 42.0");
|
|
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
|