@tsonic/emitter 0.0.62 → 0.0.64
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/adapter-generator.d.ts +5 -15
- package/dist/adapter-generator.d.ts.map +1 -1
- package/dist/adapter-generator.js +60 -53
- package/dist/adapter-generator.js.map +1 -1
- package/dist/contracts/backend-adapter.d.ts +36 -0
- package/dist/contracts/backend-adapter.d.ts.map +1 -0
- package/dist/contracts/backend-adapter.js +9 -0
- package/dist/contracts/backend-adapter.js.map +1 -0
- package/dist/contracts/emitter-contract.d.ts +54 -0
- package/dist/contracts/emitter-contract.d.ts.map +1 -0
- package/dist/contracts/emitter-contract.js +8 -0
- package/dist/contracts/emitter-contract.js.map +1 -0
- package/dist/contracts/import-classifier.d.ts +36 -0
- package/dist/contracts/import-classifier.d.ts.map +1 -0
- package/dist/contracts/import-classifier.js +9 -0
- package/dist/contracts/import-classifier.js.map +1 -0
- package/dist/core/{attributes.d.ts → format/attributes.d.ts} +9 -14
- package/dist/core/format/attributes.d.ts.map +1 -0
- package/dist/core/format/attributes.js +190 -0
- package/dist/core/format/attributes.js.map +1 -0
- package/dist/core/format/attributes.test.d.ts.map +1 -0
- package/dist/core/{attributes.test.js → format/attributes.test.js} +70 -32
- package/dist/core/format/attributes.test.js.map +1 -0
- package/dist/core/format/backend-ast/index.d.ts +7 -0
- package/dist/core/format/backend-ast/index.d.ts.map +1 -0
- package/dist/core/format/backend-ast/index.js +6 -0
- package/dist/core/format/backend-ast/index.js.map +1 -0
- package/dist/core/format/backend-ast/printer.d.ts +33 -0
- package/dist/core/format/backend-ast/printer.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer.js +1151 -0
- package/dist/core/format/backend-ast/printer.js.map +1 -0
- package/dist/core/format/backend-ast/types.d.ts +504 -0
- package/dist/core/format/backend-ast/types.d.ts.map +1 -0
- package/dist/core/format/backend-ast/types.js +13 -0
- package/dist/core/format/backend-ast/types.js.map +1 -0
- package/dist/core/format/backend-ast/utils.d.ts +26 -0
- package/dist/core/format/backend-ast/utils.d.ts.map +1 -0
- package/dist/core/format/backend-ast/utils.js +65 -0
- package/dist/core/format/backend-ast/utils.js.map +1 -0
- package/dist/core/{exports.d.ts → format/exports.d.ts} +2 -2
- package/dist/core/format/exports.d.ts.map +1 -0
- package/dist/core/format/exports.js +22 -0
- package/dist/core/format/exports.js.map +1 -0
- package/dist/core/format/index.d.ts +9 -0
- package/dist/core/format/index.d.ts.map +1 -0
- package/dist/core/format/index.js +9 -0
- package/dist/core/format/index.js.map +1 -0
- package/dist/core/{local-names.d.ts → format/local-names.d.ts} +1 -1
- package/dist/core/format/local-names.d.ts.map +1 -0
- package/dist/core/{local-names.js → format/local-names.js} +1 -1
- package/dist/core/format/local-names.js.map +1 -0
- package/dist/core/format/module-emitter/assembly.d.ts +27 -0
- package/dist/core/format/module-emitter/assembly.d.ts.map +1 -0
- package/dist/core/format/module-emitter/assembly.js +44 -0
- package/dist/core/format/module-emitter/assembly.js.map +1 -0
- package/dist/core/{module-emitter → format/module-emitter}/header.d.ts +1 -1
- package/dist/core/format/module-emitter/header.d.ts.map +1 -0
- package/dist/core/{module-emitter → format/module-emitter}/header.js +1 -1
- package/dist/core/format/module-emitter/header.js.map +1 -0
- package/dist/core/format/module-emitter/index.d.ts.map +1 -0
- package/dist/core/format/module-emitter/index.js.map +1 -0
- package/dist/core/format/module-emitter/namespace.d.ts +21 -0
- package/dist/core/format/module-emitter/namespace.d.ts.map +1 -0
- package/dist/core/format/module-emitter/namespace.js +58 -0
- package/dist/core/format/module-emitter/namespace.js.map +1 -0
- package/dist/core/{module-emitter → format/module-emitter}/orchestrator.d.ts +1 -1
- package/dist/core/format/module-emitter/orchestrator.d.ts.map +1 -0
- package/dist/core/{module-emitter → format/module-emitter}/orchestrator.js +19 -19
- package/dist/core/format/module-emitter/orchestrator.js.map +1 -0
- package/dist/core/format/module-emitter/separation.d.ts.map +1 -0
- package/dist/core/format/module-emitter/separation.js.map +1 -0
- package/dist/core/{module-emitter → format/module-emitter}/static-container.d.ts +8 -3
- package/dist/core/format/module-emitter/static-container.d.ts.map +1 -0
- package/dist/core/format/module-emitter/static-container.js +202 -0
- package/dist/core/format/module-emitter/static-container.js.map +1 -0
- package/dist/core/format/module-emitter.d.ts.map +1 -0
- package/dist/core/format/module-emitter.js.map +1 -0
- package/dist/core/{options.d.ts → format/options.d.ts} +1 -1
- package/dist/core/format/options.d.ts.map +1 -0
- package/dist/core/format/options.js.map +1 -0
- package/dist/core/index.d.ts +2 -7
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -7
- package/dist/core/index.js.map +1 -1
- package/dist/core/semantic/boolean-context.d.ts +44 -0
- package/dist/core/semantic/boolean-context.d.ts.map +1 -0
- package/dist/core/semantic/boolean-context.js +717 -0
- package/dist/core/semantic/boolean-context.js.map +1 -0
- package/dist/core/semantic/boolean-context.test.d.ts.map +1 -0
- package/dist/core/{boolean-context.test.js → semantic/boolean-context.test.js} +86 -109
- package/dist/core/semantic/boolean-context.test.js.map +1 -0
- package/dist/core/{imports.d.ts → semantic/imports.d.ts} +1 -5
- package/dist/core/semantic/imports.d.ts.map +1 -0
- package/dist/core/{imports.js → semantic/imports.js} +56 -74
- package/dist/core/semantic/imports.js.map +1 -0
- package/dist/core/semantic/imports.test.d.ts.map +1 -0
- package/dist/core/semantic/imports.test.js +229 -0
- package/dist/core/semantic/imports.test.js.map +1 -0
- package/dist/core/semantic/index.d.ts +15 -0
- package/dist/core/semantic/index.d.ts.map +1 -0
- package/dist/core/semantic/index.js +15 -0
- package/dist/core/semantic/index.js.map +1 -0
- package/dist/core/{local-types.d.ts → semantic/local-types.d.ts} +1 -1
- package/dist/core/semantic/local-types.d.ts.map +1 -0
- package/dist/core/semantic/local-types.js.map +1 -0
- package/dist/core/{module-map.d.ts → semantic/module-map.d.ts} +1 -1
- package/dist/core/semantic/module-map.d.ts.map +1 -0
- package/dist/core/semantic/module-map.js.map +1 -0
- package/dist/core/semantic/module-map.test.d.ts.map +1 -0
- package/dist/core/semantic/module-map.test.js.map +1 -0
- package/dist/core/semantic/naming-collisions.d.ts.map +1 -0
- package/dist/core/{naming-collisions.js → semantic/naming-collisions.js} +1 -1
- package/dist/core/semantic/naming-collisions.js.map +1 -0
- package/dist/core/{type-alias-index.d.ts → semantic/type-alias-index.d.ts} +1 -1
- package/dist/core/semantic/type-alias-index.d.ts.map +1 -0
- package/dist/core/semantic/type-alias-index.js.map +1 -0
- package/dist/core/semantic/type-compatibility.d.ts.map +1 -0
- package/dist/core/semantic/type-compatibility.js.map +1 -0
- package/dist/core/{type-member-index.d.ts → semantic/type-member-index.d.ts} +1 -1
- package/dist/core/semantic/type-member-index.d.ts.map +1 -0
- package/dist/core/semantic/type-member-index.js.map +1 -0
- package/dist/core/semantic/type-params.d.ts.map +1 -0
- package/dist/core/semantic/type-params.js.map +1 -0
- package/dist/core/{type-resolution.d.ts → semantic/type-resolution.d.ts} +3 -6
- package/dist/core/semantic/type-resolution.d.ts.map +1 -0
- package/dist/core/{type-resolution.js → semantic/type-resolution.js} +15 -25
- package/dist/core/semantic/type-resolution.js.map +1 -0
- package/dist/core/semantic/type-resolution.test.d.ts.map +1 -0
- package/dist/core/{type-resolution.test.js → semantic/type-resolution.test.js} +11 -19
- package/dist/core/semantic/type-resolution.test.js.map +1 -0
- package/dist/core/semantic/unsafe.d.ts.map +1 -0
- package/dist/core/semantic/unsafe.js.map +1 -0
- package/dist/emitter-types/core.d.ts +6 -12
- package/dist/emitter-types/core.d.ts.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/emitter.d.ts +1 -1
- package/dist/emitter.d.ts.map +1 -1
- package/dist/emitter.js +9 -8
- package/dist/emitter.js.map +1 -1
- package/dist/expression-emitter.d.ts +10 -5
- package/dist/expression-emitter.d.ts.map +1 -1
- package/dist/expression-emitter.js +333 -117
- package/dist/expression-emitter.js.map +1 -1
- package/dist/expressions/access.d.ts +4 -3
- package/dist/expressions/access.d.ts.map +1 -1
- package/dist/expressions/access.js +252 -102
- package/dist/expressions/access.js.map +1 -1
- package/dist/expressions/calls/call-analysis.d.ts +86 -0
- package/dist/expressions/calls/call-analysis.d.ts.map +1 -0
- package/dist/expressions/calls/call-analysis.js +284 -0
- package/dist/expressions/calls/call-analysis.js.map +1 -0
- package/dist/expressions/calls/call-emitter.d.ts +13 -0
- package/dist/expressions/calls/call-emitter.d.ts.map +1 -0
- package/dist/expressions/calls/call-emitter.js +1048 -0
- package/dist/expressions/calls/call-emitter.js.map +1 -0
- package/dist/expressions/calls/new-emitter.d.ts +13 -0
- package/dist/expressions/calls/new-emitter.d.ts.map +1 -0
- package/dist/expressions/calls/new-emitter.js +641 -0
- package/dist/expressions/calls/new-emitter.js.map +1 -0
- package/dist/expressions/calls.d.ts +2 -14
- package/dist/expressions/calls.d.ts.map +1 -1
- package/dist/expressions/calls.js +2 -909
- package/dist/expressions/calls.js.map +1 -1
- package/dist/expressions/collections.d.ts +6 -16
- package/dist/expressions/collections.d.ts.map +1 -1
- package/dist/expressions/collections.js +318 -217
- package/dist/expressions/collections.js.map +1 -1
- package/dist/expressions/functions.d.ts +6 -5
- package/dist/expressions/functions.d.ts.map +1 -1
- package/dist/expressions/functions.js +57 -62
- package/dist/expressions/functions.js.map +1 -1
- package/dist/expressions/identifiers.d.ts +11 -6
- package/dist/expressions/identifiers.d.ts.map +1 -1
- package/dist/expressions/identifiers.js +76 -25
- package/dist/expressions/identifiers.js.map +1 -1
- package/dist/expressions/index.d.ts +1 -1
- package/dist/expressions/index.d.ts.map +1 -1
- package/dist/expressions/index.js +1 -1
- package/dist/expressions/index.js.map +1 -1
- package/dist/expressions/index.test.js +605 -0
- package/dist/expressions/index.test.js.map +1 -1
- package/dist/expressions/literals.d.ts +4 -3
- package/dist/expressions/literals.d.ts.map +1 -1
- package/dist/expressions/literals.js +25 -17
- package/dist/expressions/literals.js.map +1 -1
- package/dist/expressions/literals.test.js +18 -18
- package/dist/expressions/literals.test.js.map +1 -1
- package/dist/expressions/operators/assignment-emitter.d.ts +16 -0
- package/dist/expressions/operators/assignment-emitter.d.ts.map +1 -0
- package/dist/expressions/operators/assignment-emitter.js +118 -0
- package/dist/expressions/operators/assignment-emitter.js.map +1 -0
- package/dist/expressions/operators/binary-emitter.d.ts +33 -0
- package/dist/expressions/operators/binary-emitter.d.ts.map +1 -0
- package/dist/expressions/operators/binary-emitter.js +398 -0
- package/dist/expressions/operators/binary-emitter.js.map +1 -0
- package/dist/expressions/operators/conditional-emitter.d.ts +17 -0
- package/dist/expressions/operators/conditional-emitter.d.ts.map +1 -0
- package/dist/expressions/operators/conditional-emitter.js +306 -0
- package/dist/expressions/operators/conditional-emitter.js.map +1 -0
- package/dist/expressions/operators/helpers.d.ts +37 -0
- package/dist/expressions/operators/helpers.d.ts.map +1 -0
- package/dist/expressions/operators/helpers.js +136 -0
- package/dist/expressions/operators/helpers.js.map +1 -0
- package/dist/expressions/operators/logical-emitter.d.ts +23 -0
- package/dist/expressions/operators/logical-emitter.d.ts.map +1 -0
- package/dist/expressions/operators/logical-emitter.js +73 -0
- package/dist/expressions/operators/logical-emitter.js.map +1 -0
- package/dist/expressions/operators/unary-emitter.d.ts +30 -0
- package/dist/expressions/operators/unary-emitter.d.ts.map +1 -0
- package/dist/expressions/operators/unary-emitter.js +244 -0
- package/dist/expressions/operators/unary-emitter.js.map +1 -0
- package/dist/expressions/operators.d.ts +5 -81
- package/dist/expressions/operators.d.ts.map +1 -1
- package/dist/expressions/operators.js +5 -949
- package/dist/expressions/operators.js.map +1 -1
- package/dist/expressions/other.d.ts +15 -11
- package/dist/expressions/other.d.ts.map +1 -1
- package/dist/expressions/other.js +51 -36
- package/dist/expressions/other.js.map +1 -1
- package/dist/expressions/precedence.test.js +1 -1
- package/dist/expressions/precedence.test.js.map +1 -1
- package/dist/generator-exchange.d.ts +10 -3
- package/dist/generator-exchange.d.ts.map +1 -1
- package/dist/generator-exchange.js +57 -54
- package/dist/generator-exchange.js.map +1 -1
- package/dist/generator-wrapper.d.ts +17 -65
- package/dist/generator-wrapper.d.ts.map +1 -1
- package/dist/generator-wrapper.js +396 -220
- package/dist/generator-wrapper.js.map +1 -1
- package/dist/generator-wrapper.test.js +22 -14
- package/dist/generator-wrapper.test.js.map +1 -1
- package/dist/integration.test.js +169 -1
- package/dist/integration.test.js.map +1 -1
- package/dist/patterns.d.ts +18 -88
- package/dist/patterns.d.ts.map +1 -1
- package/dist/patterns.js +540 -304
- package/dist/patterns.js.map +1 -1
- package/dist/patterns.test.js +5 -4
- package/dist/patterns.test.js.map +1 -1
- package/dist/specialization/generation.d.ts +7 -3
- package/dist/specialization/generation.d.ts.map +1 -1
- package/dist/specialization/generation.js +31 -15
- package/dist/specialization/generation.js.map +1 -1
- package/dist/specialization/type-aliases.test.js +47 -2
- package/dist/specialization/type-aliases.test.js.map +1 -1
- package/dist/statement-emitter.d.ts +15 -4
- package/dist/statement-emitter.d.ts.map +1 -1
- package/dist/statement-emitter.js +54 -47
- package/dist/statement-emitter.js.map +1 -1
- package/dist/statements/blocks.d.ts +24 -16
- package/dist/statements/blocks.d.ts.map +1 -1
- package/dist/statements/blocks.js +242 -65
- package/dist/statements/blocks.js.map +1 -1
- package/dist/statements/classes/index.d.ts +1 -1
- package/dist/statements/classes/index.d.ts.map +1 -1
- package/dist/statements/classes/index.js +1 -1
- package/dist/statements/classes/index.js.map +1 -1
- package/dist/statements/classes/inline-types.d.ts +4 -3
- package/dist/statements/classes/inline-types.d.ts.map +1 -1
- package/dist/statements/classes/inline-types.js +21 -21
- package/dist/statements/classes/inline-types.js.map +1 -1
- package/dist/statements/classes/members/constructors.d.ts +4 -3
- package/dist/statements/classes/members/constructors.d.ts.map +1 -1
- package/dist/statements/classes/members/constructors.js +57 -58
- package/dist/statements/classes/members/constructors.js.map +1 -1
- package/dist/statements/classes/members/methods.d.ts +4 -3
- package/dist/statements/classes/members/methods.d.ts.map +1 -1
- package/dist/statements/classes/members/methods.js +106 -101
- package/dist/statements/classes/members/methods.js.map +1 -1
- package/dist/statements/classes/members/orchestrator.d.ts +4 -3
- package/dist/statements/classes/members/orchestrator.d.ts.map +1 -1
- package/dist/statements/classes/members/orchestrator.js +2 -2
- package/dist/statements/classes/members/orchestrator.js.map +1 -1
- package/dist/statements/classes/members/properties.d.ts +4 -3
- package/dist/statements/classes/members/properties.d.ts.map +1 -1
- package/dist/statements/classes/members/properties.js +105 -88
- package/dist/statements/classes/members/properties.js.map +1 -1
- package/dist/statements/classes/members/shadowing.test.js +7 -2
- package/dist/statements/classes/members/shadowing.test.js.map +1 -1
- package/dist/statements/classes/members/static-readonly-properties.test.js +4 -1
- package/dist/statements/classes/members/static-readonly-properties.test.js.map +1 -1
- package/dist/statements/classes/parameters.d.ts +8 -10
- package/dist/statements/classes/parameters.d.ts.map +1 -1
- package/dist/statements/classes/parameters.js +30 -26
- package/dist/statements/classes/parameters.js.map +1 -1
- package/dist/statements/classes/properties.d.ts +4 -3
- package/dist/statements/classes/properties.d.ts.map +1 -1
- package/dist/statements/classes/properties.js +76 -50
- package/dist/statements/classes/properties.js.map +1 -1
- package/dist/statements/classes.d.ts +1 -1
- package/dist/statements/classes.d.ts.map +1 -1
- package/dist/statements/classes.js +1 -1
- package/dist/statements/classes.js.map +1 -1
- package/dist/statements/control/conditionals/guard-analysis.d.ts +169 -0
- package/dist/statements/control/conditionals/guard-analysis.d.ts.map +1 -0
- package/dist/statements/control/conditionals/guard-analysis.js +591 -0
- package/dist/statements/control/conditionals/guard-analysis.js.map +1 -0
- package/dist/statements/control/conditionals/if-emitter.d.ts +14 -0
- package/dist/statements/control/conditionals/if-emitter.d.ts.map +1 -0
- package/dist/statements/control/conditionals/if-emitter.js +725 -0
- package/dist/statements/control/conditionals/if-emitter.js.map +1 -0
- package/dist/statements/control/conditionals/switch-emitter.d.ts +13 -0
- package/dist/statements/control/conditionals/switch-emitter.d.ts.map +1 -0
- package/dist/statements/control/conditionals/switch-emitter.js +60 -0
- package/dist/statements/control/conditionals/switch-emitter.js.map +1 -0
- package/dist/statements/control/conditionals.d.ts +3 -15
- package/dist/statements/control/conditionals.d.ts.map +1 -1
- package/dist/statements/control/conditionals.js +3 -1152
- package/dist/statements/control/conditionals.js.map +1 -1
- package/dist/statements/control/exceptions.d.ts +8 -6
- package/dist/statements/control/exceptions.d.ts.map +1 -1
- package/dist/statements/control/exceptions.js +35 -23
- package/dist/statements/control/exceptions.js.map +1 -1
- package/dist/statements/control/index.d.ts +3 -3
- package/dist/statements/control/index.d.ts.map +1 -1
- package/dist/statements/control/index.js +3 -3
- package/dist/statements/control/index.js.map +1 -1
- package/dist/statements/control/loops.d.ts +14 -12
- package/dist/statements/control/loops.d.ts.map +1 -1
- package/dist/statements/control/loops.js +147 -82
- package/dist/statements/control/loops.js.map +1 -1
- package/dist/statements/control.d.ts +1 -1
- package/dist/statements/control.d.ts.map +1 -1
- package/dist/statements/control.js +1 -1
- package/dist/statements/control.js.map +1 -1
- package/dist/statements/declarations/classes.d.ts +7 -3
- package/dist/statements/declarations/classes.d.ts.map +1 -1
- package/dist/statements/declarations/classes.js +107 -83
- package/dist/statements/declarations/classes.js.map +1 -1
- package/dist/statements/declarations/enums.d.ts +4 -3
- package/dist/statements/declarations/enums.d.ts.map +1 -1
- package/dist/statements/declarations/enums.js +16 -15
- package/dist/statements/declarations/enums.js.map +1 -1
- package/dist/statements/declarations/functions.d.ts +18 -2
- package/dist/statements/declarations/functions.d.ts.map +1 -1
- package/dist/statements/declarations/functions.js +633 -162
- package/dist/statements/declarations/functions.js.map +1 -1
- package/dist/statements/declarations/index.d.ts +2 -2
- package/dist/statements/declarations/index.d.ts.map +1 -1
- package/dist/statements/declarations/index.js +2 -2
- package/dist/statements/declarations/index.js.map +1 -1
- package/dist/statements/declarations/interfaces.d.ts +7 -3
- package/dist/statements/declarations/interfaces.d.ts.map +1 -1
- package/dist/statements/declarations/interfaces.js +138 -105
- package/dist/statements/declarations/interfaces.js.map +1 -1
- package/dist/statements/declarations/type-aliases.d.ts +7 -3
- package/dist/statements/declarations/type-aliases.d.ts.map +1 -1
- package/dist/statements/declarations/type-aliases.js +122 -82
- package/dist/statements/declarations/type-aliases.js.map +1 -1
- package/dist/statements/declarations/variables.d.ts +12 -2
- package/dist/statements/declarations/variables.d.ts.map +1 -1
- package/dist/statements/declarations/variables.js +541 -428
- package/dist/statements/declarations/variables.js.map +1 -1
- package/dist/statements/declarations.d.ts +1 -1
- package/dist/statements/declarations.d.ts.map +1 -1
- package/dist/statements/declarations.js +1 -1
- package/dist/statements/declarations.js.map +1 -1
- package/dist/statements/index.d.ts +3 -3
- package/dist/statements/index.d.ts.map +1 -1
- package/dist/statements/index.js +5 -5
- package/dist/statements/index.js.map +1 -1
- package/dist/statements/index.test.js +307 -0
- package/dist/statements/index.test.js.map +1 -1
- package/dist/type-emitter.d.ts +1 -1
- package/dist/type-emitter.d.ts.map +1 -1
- package/dist/type-emitter.js +1 -1
- package/dist/type-emitter.js.map +1 -1
- package/dist/types/arrays.d.ts +3 -2
- package/dist/types/arrays.d.ts.map +1 -1
- package/dist/types/arrays.js +7 -5
- package/dist/types/arrays.js.map +1 -1
- package/dist/types/dictionaries.d.ts +6 -3
- package/dist/types/dictionaries.d.ts.map +1 -1
- package/dist/types/dictionaries.js +22 -10
- package/dist/types/dictionaries.js.map +1 -1
- package/dist/types/emitter.d.ts +8 -2
- package/dist/types/emitter.d.ts.map +1 -1
- package/dist/types/emitter.js +20 -6
- package/dist/types/emitter.js.map +1 -1
- package/dist/types/functions.d.ts +3 -2
- package/dist/types/functions.d.ts.map +1 -1
- package/dist/types/functions.js +36 -13
- package/dist/types/functions.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/index.test.js +137 -0
- package/dist/types/index.test.js.map +1 -1
- package/dist/types/intersections.d.ts +3 -2
- package/dist/types/intersections.d.ts.map +1 -1
- package/dist/types/intersections.js +2 -2
- package/dist/types/intersections.js.map +1 -1
- package/dist/types/literals.d.ts +9 -2
- package/dist/types/literals.d.ts.map +1 -1
- package/dist/types/literals.js +11 -5
- package/dist/types/literals.js.map +1 -1
- package/dist/types/objects.d.ts +3 -2
- package/dist/types/objects.d.ts.map +1 -1
- package/dist/types/objects.js +1 -1
- package/dist/types/objects.js.map +1 -1
- package/dist/types/parameters.d.ts +6 -5
- package/dist/types/parameters.d.ts.map +1 -1
- package/dist/types/parameters.js +88 -29
- package/dist/types/parameters.js.map +1 -1
- package/dist/types/parameters.test.js +9 -4
- package/dist/types/parameters.test.js.map +1 -1
- package/dist/types/primitives.d.ts +5 -4
- package/dist/types/primitives.d.ts.map +1 -1
- package/dist/types/primitives.js +14 -13
- package/dist/types/primitives.js.map +1 -1
- package/dist/types/references.d.ts +3 -2
- package/dist/types/references.d.ts.map +1 -1
- package/dist/types/references.js +135 -111
- package/dist/types/references.js.map +1 -1
- package/dist/types/tuples.d.ts +3 -2
- package/dist/types/tuples.d.ts.map +1 -1
- package/dist/types/tuples.js +25 -11
- package/dist/types/tuples.js.map +1 -1
- package/dist/types/unions.d.ts +3 -2
- package/dist/types/unions.d.ts.map +1 -1
- package/dist/types/unions.js +36 -21
- package/dist/types/unions.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 +2 -2
- package/dist/core/attributes.d.ts.map +0 -1
- package/dist/core/attributes.js +0 -141
- package/dist/core/attributes.js.map +0 -1
- package/dist/core/attributes.test.d.ts.map +0 -1
- package/dist/core/attributes.test.js.map +0 -1
- package/dist/core/boolean-context.d.ts +0 -42
- package/dist/core/boolean-context.d.ts.map +0 -1
- package/dist/core/boolean-context.js +0 -442
- package/dist/core/boolean-context.js.map +0 -1
- package/dist/core/boolean-context.test.d.ts.map +0 -1
- package/dist/core/boolean-context.test.js.map +0 -1
- package/dist/core/exports.d.ts.map +0 -1
- package/dist/core/exports.js +0 -28
- package/dist/core/exports.js.map +0 -1
- package/dist/core/imports.d.ts.map +0 -1
- package/dist/core/imports.js.map +0 -1
- package/dist/core/imports.test.d.ts.map +0 -1
- package/dist/core/imports.test.js +0 -79
- package/dist/core/imports.test.js.map +0 -1
- package/dist/core/local-names.d.ts.map +0 -1
- package/dist/core/local-names.js.map +0 -1
- package/dist/core/local-types.d.ts.map +0 -1
- package/dist/core/local-types.js.map +0 -1
- package/dist/core/module-emitter/assembly.d.ts +0 -24
- package/dist/core/module-emitter/assembly.d.ts.map +0 -1
- package/dist/core/module-emitter/assembly.js +0 -69
- package/dist/core/module-emitter/assembly.js.map +0 -1
- package/dist/core/module-emitter/header.d.ts.map +0 -1
- package/dist/core/module-emitter/header.js.map +0 -1
- package/dist/core/module-emitter/index.d.ts.map +0 -1
- package/dist/core/module-emitter/index.js.map +0 -1
- package/dist/core/module-emitter/namespace.d.ts +0 -14
- package/dist/core/module-emitter/namespace.d.ts.map +0 -1
- package/dist/core/module-emitter/namespace.js +0 -26
- package/dist/core/module-emitter/namespace.js.map +0 -1
- package/dist/core/module-emitter/orchestrator.d.ts.map +0 -1
- package/dist/core/module-emitter/orchestrator.js.map +0 -1
- package/dist/core/module-emitter/separation.d.ts.map +0 -1
- package/dist/core/module-emitter/separation.js.map +0 -1
- package/dist/core/module-emitter/static-container.d.ts.map +0 -1
- package/dist/core/module-emitter/static-container.js +0 -139
- package/dist/core/module-emitter/static-container.js.map +0 -1
- package/dist/core/module-emitter.d.ts.map +0 -1
- package/dist/core/module-emitter.js.map +0 -1
- package/dist/core/module-map.d.ts.map +0 -1
- package/dist/core/module-map.js.map +0 -1
- package/dist/core/module-map.test.d.ts.map +0 -1
- package/dist/core/module-map.test.js.map +0 -1
- package/dist/core/naming-collisions.d.ts.map +0 -1
- package/dist/core/naming-collisions.js.map +0 -1
- package/dist/core/options.d.ts.map +0 -1
- package/dist/core/options.js.map +0 -1
- package/dist/core/type-alias-index.d.ts.map +0 -1
- package/dist/core/type-alias-index.js.map +0 -1
- package/dist/core/type-compatibility.d.ts.map +0 -1
- package/dist/core/type-compatibility.js.map +0 -1
- package/dist/core/type-member-index.d.ts.map +0 -1
- package/dist/core/type-member-index.js.map +0 -1
- package/dist/core/type-params.d.ts.map +0 -1
- package/dist/core/type-params.js.map +0 -1
- package/dist/core/type-resolution.d.ts.map +0 -1
- package/dist/core/type-resolution.js.map +0 -1
- package/dist/core/type-resolution.test.d.ts.map +0 -1
- package/dist/core/type-resolution.test.js.map +0 -1
- package/dist/core/unsafe.d.ts.map +0 -1
- package/dist/core/unsafe.js.map +0 -1
- /package/dist/core/{attributes.test.d.ts → format/attributes.test.d.ts} +0 -0
- /package/dist/core/{module-emitter → format/module-emitter}/index.d.ts +0 -0
- /package/dist/core/{module-emitter → format/module-emitter}/index.js +0 -0
- /package/dist/core/{module-emitter → format/module-emitter}/separation.d.ts +0 -0
- /package/dist/core/{module-emitter → format/module-emitter}/separation.js +0 -0
- /package/dist/core/{module-emitter.d.ts → format/module-emitter.d.ts} +0 -0
- /package/dist/core/{module-emitter.js → format/module-emitter.js} +0 -0
- /package/dist/core/{options.js → format/options.js} +0 -0
- /package/dist/core/{boolean-context.test.d.ts → semantic/boolean-context.test.d.ts} +0 -0
- /package/dist/core/{imports.test.d.ts → semantic/imports.test.d.ts} +0 -0
- /package/dist/core/{local-types.js → semantic/local-types.js} +0 -0
- /package/dist/core/{module-map.js → semantic/module-map.js} +0 -0
- /package/dist/core/{module-map.test.d.ts → semantic/module-map.test.d.ts} +0 -0
- /package/dist/core/{module-map.test.js → semantic/module-map.test.js} +0 -0
- /package/dist/core/{naming-collisions.d.ts → semantic/naming-collisions.d.ts} +0 -0
- /package/dist/core/{type-alias-index.js → semantic/type-alias-index.js} +0 -0
- /package/dist/core/{type-compatibility.d.ts → semantic/type-compatibility.d.ts} +0 -0
- /package/dist/core/{type-compatibility.js → semantic/type-compatibility.js} +0 -0
- /package/dist/core/{type-member-index.js → semantic/type-member-index.js} +0 -0
- /package/dist/core/{type-params.d.ts → semantic/type-params.d.ts} +0 -0
- /package/dist/core/{type-params.js → semantic/type-params.js} +0 -0
- /package/dist/core/{type-resolution.test.d.ts → semantic/type-resolution.test.d.ts} +0 -0
- /package/dist/core/{unsafe.d.ts → semantic/unsafe.d.ts} +0 -0
- /package/dist/core/{unsafe.js → semantic/unsafe.js} +0 -0
|
@@ -0,0 +1,1151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend AST Printer
|
|
3
|
+
*
|
|
4
|
+
* Converts typed C# AST nodes into deterministic C# source text.
|
|
5
|
+
* Pure and stateless - no parsing, no string heuristics.
|
|
6
|
+
*
|
|
7
|
+
* Parenthesization is derived from operator precedence tables,
|
|
8
|
+
* not from advisory metadata on fragments.
|
|
9
|
+
*/
|
|
10
|
+
// ============================================================
|
|
11
|
+
// C# reserved keywords for identifier escaping
|
|
12
|
+
// ============================================================
|
|
13
|
+
const CSHARP_KEYWORDS = new Set([
|
|
14
|
+
"abstract",
|
|
15
|
+
"as",
|
|
16
|
+
"bool",
|
|
17
|
+
"break",
|
|
18
|
+
"byte",
|
|
19
|
+
"case",
|
|
20
|
+
"catch",
|
|
21
|
+
"char",
|
|
22
|
+
"checked",
|
|
23
|
+
"class",
|
|
24
|
+
"const",
|
|
25
|
+
"continue",
|
|
26
|
+
"decimal",
|
|
27
|
+
"default",
|
|
28
|
+
"delegate",
|
|
29
|
+
"do",
|
|
30
|
+
"double",
|
|
31
|
+
"else",
|
|
32
|
+
"enum",
|
|
33
|
+
"event",
|
|
34
|
+
"explicit",
|
|
35
|
+
"extern",
|
|
36
|
+
"finally",
|
|
37
|
+
"fixed",
|
|
38
|
+
"float",
|
|
39
|
+
"for",
|
|
40
|
+
"foreach",
|
|
41
|
+
"goto",
|
|
42
|
+
"if",
|
|
43
|
+
"implicit",
|
|
44
|
+
"in",
|
|
45
|
+
"int",
|
|
46
|
+
"interface",
|
|
47
|
+
"internal",
|
|
48
|
+
"is",
|
|
49
|
+
"lock",
|
|
50
|
+
"long",
|
|
51
|
+
"namespace",
|
|
52
|
+
"new",
|
|
53
|
+
"null",
|
|
54
|
+
"object",
|
|
55
|
+
"operator",
|
|
56
|
+
"out",
|
|
57
|
+
"override",
|
|
58
|
+
"params",
|
|
59
|
+
"private",
|
|
60
|
+
"protected",
|
|
61
|
+
"public",
|
|
62
|
+
"readonly",
|
|
63
|
+
"ref",
|
|
64
|
+
"return",
|
|
65
|
+
"sbyte",
|
|
66
|
+
"sealed",
|
|
67
|
+
"short",
|
|
68
|
+
"sizeof",
|
|
69
|
+
"stackalloc",
|
|
70
|
+
"static",
|
|
71
|
+
"string",
|
|
72
|
+
"struct",
|
|
73
|
+
"switch",
|
|
74
|
+
"throw",
|
|
75
|
+
"try",
|
|
76
|
+
"typeof",
|
|
77
|
+
"uint",
|
|
78
|
+
"ulong",
|
|
79
|
+
"unchecked",
|
|
80
|
+
"unsafe",
|
|
81
|
+
"ushort",
|
|
82
|
+
"using",
|
|
83
|
+
"virtual",
|
|
84
|
+
"void",
|
|
85
|
+
"volatile",
|
|
86
|
+
"while",
|
|
87
|
+
]);
|
|
88
|
+
/**
|
|
89
|
+
* C# predefined type keywords that should NOT be escaped with @
|
|
90
|
+
* when used in type position (they are the type name itself).
|
|
91
|
+
*/
|
|
92
|
+
const PREDEFINED_TYPE_KEYWORDS = new Set([
|
|
93
|
+
"bool",
|
|
94
|
+
"byte",
|
|
95
|
+
"char",
|
|
96
|
+
"decimal",
|
|
97
|
+
"double",
|
|
98
|
+
"float",
|
|
99
|
+
"int",
|
|
100
|
+
"long",
|
|
101
|
+
"object",
|
|
102
|
+
"sbyte",
|
|
103
|
+
"short",
|
|
104
|
+
"string",
|
|
105
|
+
"uint",
|
|
106
|
+
"ulong",
|
|
107
|
+
"ushort",
|
|
108
|
+
"void",
|
|
109
|
+
"nint",
|
|
110
|
+
"nuint",
|
|
111
|
+
]);
|
|
112
|
+
/**
|
|
113
|
+
* Escape a C# identifier if it's a keyword.
|
|
114
|
+
* Preserves predefined type keywords when used as types.
|
|
115
|
+
*/
|
|
116
|
+
const escapeIdentifier = (name) => CSHARP_KEYWORDS.has(name) ? `@${name}` : name;
|
|
117
|
+
/**
|
|
118
|
+
* Escape segments in a qualified name (e.g. "global::Foo.stackalloc.Bar").
|
|
119
|
+
* The "global::" prefix and predefined type keywords are preserved.
|
|
120
|
+
*/
|
|
121
|
+
const escapeQualifiedName = (name, preservePredefinedTypeKeywords = false) => {
|
|
122
|
+
const globalPrefix = "global::";
|
|
123
|
+
const hasGlobal = name.startsWith(globalPrefix);
|
|
124
|
+
const body = hasGlobal ? name.slice(globalPrefix.length) : name;
|
|
125
|
+
const escaped = body
|
|
126
|
+
.split(".")
|
|
127
|
+
.map((segment) => CSHARP_KEYWORDS.has(segment) &&
|
|
128
|
+
!(preservePredefinedTypeKeywords && PREDEFINED_TYPE_KEYWORDS.has(segment))
|
|
129
|
+
? `@${segment}`
|
|
130
|
+
: segment)
|
|
131
|
+
.join(".");
|
|
132
|
+
return hasGlobal ? `${globalPrefix}${escaped}` : escaped;
|
|
133
|
+
};
|
|
134
|
+
// ============================================================
|
|
135
|
+
// Operator precedence for parenthesization
|
|
136
|
+
// ============================================================
|
|
137
|
+
/**
|
|
138
|
+
* C# operator precedence levels (higher = binds tighter).
|
|
139
|
+
* Used by the printer to insert parentheses only when necessary.
|
|
140
|
+
*/
|
|
141
|
+
const getOperatorPrecedence = (op) => {
|
|
142
|
+
switch (op) {
|
|
143
|
+
// Assignment operators (lowest)
|
|
144
|
+
case "=":
|
|
145
|
+
case "+=":
|
|
146
|
+
case "-=":
|
|
147
|
+
case "*=":
|
|
148
|
+
case "/=":
|
|
149
|
+
case "%=":
|
|
150
|
+
case "&=":
|
|
151
|
+
case "|=":
|
|
152
|
+
case "^=":
|
|
153
|
+
case "<<=":
|
|
154
|
+
case ">>=":
|
|
155
|
+
case "??=":
|
|
156
|
+
return 1;
|
|
157
|
+
// Conditional ternary
|
|
158
|
+
// (handled separately, not via this function)
|
|
159
|
+
// Null-coalescing
|
|
160
|
+
case "??":
|
|
161
|
+
return 3;
|
|
162
|
+
// Logical OR
|
|
163
|
+
case "||":
|
|
164
|
+
return 4;
|
|
165
|
+
// Logical AND
|
|
166
|
+
case "&&":
|
|
167
|
+
return 5;
|
|
168
|
+
// Bitwise OR
|
|
169
|
+
case "|":
|
|
170
|
+
return 6;
|
|
171
|
+
// Bitwise XOR
|
|
172
|
+
case "^":
|
|
173
|
+
return 7;
|
|
174
|
+
// Bitwise AND
|
|
175
|
+
case "&":
|
|
176
|
+
return 8;
|
|
177
|
+
// Equality
|
|
178
|
+
case "==":
|
|
179
|
+
case "!=":
|
|
180
|
+
return 9;
|
|
181
|
+
// Relational (includes is, as - handled separately)
|
|
182
|
+
case "<":
|
|
183
|
+
case ">":
|
|
184
|
+
case "<=":
|
|
185
|
+
case ">=":
|
|
186
|
+
return 10;
|
|
187
|
+
// Shift
|
|
188
|
+
case "<<":
|
|
189
|
+
case ">>":
|
|
190
|
+
return 11;
|
|
191
|
+
// Additive
|
|
192
|
+
case "+":
|
|
193
|
+
case "-":
|
|
194
|
+
return 12;
|
|
195
|
+
// Multiplicative
|
|
196
|
+
case "*":
|
|
197
|
+
case "/":
|
|
198
|
+
case "%":
|
|
199
|
+
return 13;
|
|
200
|
+
default:
|
|
201
|
+
return 0;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Get the effective precedence of an expression for parenthesization decisions.
|
|
206
|
+
*/
|
|
207
|
+
const getExpressionPrecedence = (expr) => {
|
|
208
|
+
switch (expr.kind) {
|
|
209
|
+
case "assignmentExpression":
|
|
210
|
+
return 1;
|
|
211
|
+
case "conditionalExpression":
|
|
212
|
+
return 2;
|
|
213
|
+
case "binaryExpression":
|
|
214
|
+
return getOperatorPrecedence(expr.operatorToken);
|
|
215
|
+
case "isExpression":
|
|
216
|
+
case "asExpression":
|
|
217
|
+
return 10; // Relational level
|
|
218
|
+
case "prefixUnaryExpression":
|
|
219
|
+
return 14; // Unary prefix
|
|
220
|
+
case "postfixUnaryExpression":
|
|
221
|
+
return 15; // Unary postfix
|
|
222
|
+
case "castExpression":
|
|
223
|
+
return 14; // Cast is at unary level
|
|
224
|
+
case "awaitExpression":
|
|
225
|
+
return 14; // Await is at unary level
|
|
226
|
+
// Primary expressions (highest precedence)
|
|
227
|
+
case "literalExpression":
|
|
228
|
+
case "identifierExpression":
|
|
229
|
+
case "parenthesizedExpression":
|
|
230
|
+
case "memberAccessExpression":
|
|
231
|
+
case "conditionalMemberAccessExpression":
|
|
232
|
+
case "elementAccessExpression":
|
|
233
|
+
case "conditionalElementAccessExpression":
|
|
234
|
+
case "invocationExpression":
|
|
235
|
+
case "objectCreationExpression":
|
|
236
|
+
case "arrayCreationExpression":
|
|
237
|
+
case "stackAllocArrayCreationExpression":
|
|
238
|
+
case "defaultExpression":
|
|
239
|
+
case "typeofExpression":
|
|
240
|
+
case "interpolatedStringExpression":
|
|
241
|
+
case "suppressNullableWarningExpression":
|
|
242
|
+
case "switchExpression":
|
|
243
|
+
return 16;
|
|
244
|
+
case "argumentModifierExpression":
|
|
245
|
+
return 16; // Argument modifier is used in argument position only
|
|
246
|
+
case "tupleExpression":
|
|
247
|
+
return 16; // Tuple literals are primary expressions
|
|
248
|
+
case "lambdaExpression":
|
|
249
|
+
return 0; // Lambda needs parens almost everywhere
|
|
250
|
+
case "throwExpression":
|
|
251
|
+
return 0; // Throw expression is very low precedence
|
|
252
|
+
default:
|
|
253
|
+
return 0;
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Whether an expression needs parenthesization when used as an operand
|
|
258
|
+
* of a binary expression with the given parent precedence.
|
|
259
|
+
*/
|
|
260
|
+
const needsParensInBinary = (child, parentPrecedence, isRightOperand) => {
|
|
261
|
+
const childPrec = getExpressionPrecedence(child);
|
|
262
|
+
if (childPrec < parentPrecedence)
|
|
263
|
+
return true;
|
|
264
|
+
// For same-precedence, right-associative operators (assignment)
|
|
265
|
+
// don't need parens on the right side
|
|
266
|
+
if (childPrec === parentPrecedence && isRightOperand) {
|
|
267
|
+
// Assignment is right-associative
|
|
268
|
+
if (child.kind === "assignmentExpression") {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
// Associative operators at exclusive precedence levels: grouping doesn't
|
|
272
|
+
// change semantics, so right-side parens are unnecessary.
|
|
273
|
+
// Each of these operators is the sole occupant of its precedence level,
|
|
274
|
+
// so same-prec right child must be the same operator.
|
|
275
|
+
if (child.kind === "binaryExpression" &&
|
|
276
|
+
(child.operatorToken === "&&" ||
|
|
277
|
+
child.operatorToken === "||" ||
|
|
278
|
+
child.operatorToken === "|" ||
|
|
279
|
+
child.operatorToken === "&" ||
|
|
280
|
+
child.operatorToken === "^")) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
// Left-associative (and ?? for readability): right operand at same precedence needs parens
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* Wrap expression text in parens if needed for the given context.
|
|
290
|
+
*/
|
|
291
|
+
const parenthesizeIfNeeded = (expr, parentPrecedence, isRightOperand) => {
|
|
292
|
+
const text = printExpression(expr);
|
|
293
|
+
return needsParensInBinary(expr, parentPrecedence, isRightOperand)
|
|
294
|
+
? `(${text})`
|
|
295
|
+
: text;
|
|
296
|
+
};
|
|
297
|
+
// ============================================================
|
|
298
|
+
// Type Printer
|
|
299
|
+
// ============================================================
|
|
300
|
+
export const printType = (type) => {
|
|
301
|
+
switch (type.kind) {
|
|
302
|
+
case "predefinedType":
|
|
303
|
+
return type.keyword;
|
|
304
|
+
case "identifierType": {
|
|
305
|
+
const name = escapeQualifiedName(type.name, true);
|
|
306
|
+
if (!type.typeArguments || type.typeArguments.length === 0) {
|
|
307
|
+
return name;
|
|
308
|
+
}
|
|
309
|
+
const args = type.typeArguments.map(printType).join(", ");
|
|
310
|
+
return `${name}<${args}>`;
|
|
311
|
+
}
|
|
312
|
+
case "nullableType":
|
|
313
|
+
return `${printType(type.underlyingType)}?`;
|
|
314
|
+
case "arrayType": {
|
|
315
|
+
const elem = printType(type.elementType);
|
|
316
|
+
if (type.rank === 1) {
|
|
317
|
+
return `${elem}[]`;
|
|
318
|
+
}
|
|
319
|
+
const commas = ",".repeat(type.rank - 1);
|
|
320
|
+
return `${elem}[${commas}]`;
|
|
321
|
+
}
|
|
322
|
+
case "pointerType":
|
|
323
|
+
return `${printType(type.elementType)}*`;
|
|
324
|
+
case "tupleType": {
|
|
325
|
+
const elems = type.elements
|
|
326
|
+
.map((e) => e.name ? `${printType(e.type)} ${e.name}` : printType(e.type))
|
|
327
|
+
.join(", ");
|
|
328
|
+
return `(${elems})`;
|
|
329
|
+
}
|
|
330
|
+
case "varType":
|
|
331
|
+
return "var";
|
|
332
|
+
default: {
|
|
333
|
+
const exhaustiveCheck = type;
|
|
334
|
+
throw new Error(`ICE: Unhandled type AST kind: ${exhaustiveCheck.kind}`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
// ============================================================
|
|
339
|
+
// Expression Printer
|
|
340
|
+
// ============================================================
|
|
341
|
+
export const printExpression = (expr) => {
|
|
342
|
+
switch (expr.kind) {
|
|
343
|
+
case "literalExpression":
|
|
344
|
+
return expr.text;
|
|
345
|
+
case "identifierExpression":
|
|
346
|
+
return escapeIdentifier(expr.identifier);
|
|
347
|
+
case "parenthesizedExpression":
|
|
348
|
+
return `(${printExpression(expr.expression)})`;
|
|
349
|
+
case "memberAccessExpression":
|
|
350
|
+
return `${printPrimaryExpression(expr.expression)}.${escapeIdentifier(expr.memberName)}`;
|
|
351
|
+
case "conditionalMemberAccessExpression":
|
|
352
|
+
return `${printPrimaryExpression(expr.expression)}?.${escapeIdentifier(expr.memberName)}`;
|
|
353
|
+
case "elementAccessExpression": {
|
|
354
|
+
const args = expr.arguments.map(printExpression).join(", ");
|
|
355
|
+
return `${printPrimaryExpression(expr.expression)}[${args}]`;
|
|
356
|
+
}
|
|
357
|
+
case "conditionalElementAccessExpression": {
|
|
358
|
+
const args = expr.arguments.map(printExpression).join(", ");
|
|
359
|
+
return `${printPrimaryExpression(expr.expression)}?[${args}]`;
|
|
360
|
+
}
|
|
361
|
+
case "invocationExpression": {
|
|
362
|
+
const callee = printPrimaryExpression(expr.expression);
|
|
363
|
+
const typeArgs = expr.typeArguments && expr.typeArguments.length > 0
|
|
364
|
+
? `<${expr.typeArguments.map(printType).join(", ")}>`
|
|
365
|
+
: "";
|
|
366
|
+
const args = expr.arguments.map(printExpression).join(", ");
|
|
367
|
+
return `${callee}${typeArgs}(${args})`;
|
|
368
|
+
}
|
|
369
|
+
case "objectCreationExpression": {
|
|
370
|
+
const typeName = printType(expr.type);
|
|
371
|
+
const args = expr.arguments.map(printExpression).join(", ");
|
|
372
|
+
const init = expr.initializer && expr.initializer.length > 0
|
|
373
|
+
? ` { ${expr.initializer.map(printExpression).join(", ")} }`
|
|
374
|
+
: "";
|
|
375
|
+
// Omit () when using collection/object initializer with no constructor args
|
|
376
|
+
// (C# allows `new List<T> { ... }` without parentheses)
|
|
377
|
+
const argsSection = expr.initializer && expr.initializer.length > 0 && args.length === 0
|
|
378
|
+
? ""
|
|
379
|
+
: `(${args})`;
|
|
380
|
+
return `new ${typeName}${argsSection}${init}`;
|
|
381
|
+
}
|
|
382
|
+
case "arrayCreationExpression": {
|
|
383
|
+
// varType element type → implicitly-typed new[] { ... }
|
|
384
|
+
const isImplicit = expr.elementType.kind === "varType";
|
|
385
|
+
const elemType = isImplicit ? "" : ` ${printType(expr.elementType)}`;
|
|
386
|
+
if (expr.initializer && expr.initializer.length > 0) {
|
|
387
|
+
const elems = expr.initializer.map(printExpression).join(", ");
|
|
388
|
+
if (expr.sizeExpression) {
|
|
389
|
+
return `new${elemType}[${printExpression(expr.sizeExpression)}] { ${elems} }`;
|
|
390
|
+
}
|
|
391
|
+
return `new${elemType}[] { ${elems} }`;
|
|
392
|
+
}
|
|
393
|
+
if (expr.sizeExpression) {
|
|
394
|
+
return `new${elemType}[${printExpression(expr.sizeExpression)}]`;
|
|
395
|
+
}
|
|
396
|
+
return `new${elemType}[0]`;
|
|
397
|
+
}
|
|
398
|
+
case "stackAllocArrayCreationExpression":
|
|
399
|
+
return `stackalloc ${printType(expr.elementType)}[${printExpression(expr.sizeExpression)}]`;
|
|
400
|
+
case "assignmentExpression": {
|
|
401
|
+
const left = printExpression(expr.left);
|
|
402
|
+
const right = printExpression(expr.right);
|
|
403
|
+
return `${left} ${expr.operatorToken} ${right}`;
|
|
404
|
+
}
|
|
405
|
+
case "binaryExpression": {
|
|
406
|
+
const prec = getOperatorPrecedence(expr.operatorToken);
|
|
407
|
+
const left = parenthesizeIfNeeded(expr.left, prec, false);
|
|
408
|
+
const right = parenthesizeIfNeeded(expr.right, prec, true);
|
|
409
|
+
return `${left} ${expr.operatorToken} ${right}`;
|
|
410
|
+
}
|
|
411
|
+
case "prefixUnaryExpression": {
|
|
412
|
+
const operand = printUnaryOperand(expr.operand, true);
|
|
413
|
+
// Operators like ++ and -- need no space, but ! and - do if operand starts with same char
|
|
414
|
+
if ((expr.operatorToken === "-" && operand.startsWith("-")) ||
|
|
415
|
+
(expr.operatorToken === "+" && operand.startsWith("+"))) {
|
|
416
|
+
return `${expr.operatorToken} ${operand}`;
|
|
417
|
+
}
|
|
418
|
+
return `${expr.operatorToken}${operand}`;
|
|
419
|
+
}
|
|
420
|
+
case "postfixUnaryExpression":
|
|
421
|
+
return `${printUnaryOperand(expr.operand, false)}${expr.operatorToken}`;
|
|
422
|
+
case "conditionalExpression": {
|
|
423
|
+
const cond = printExpression(expr.condition);
|
|
424
|
+
const whenTrue = printExpression(expr.whenTrue);
|
|
425
|
+
const whenFalse = printExpression(expr.whenFalse);
|
|
426
|
+
return `${cond} ? ${whenTrue} : ${whenFalse}`;
|
|
427
|
+
}
|
|
428
|
+
case "castExpression": {
|
|
429
|
+
const typeName = printType(expr.type);
|
|
430
|
+
const operand = printCastOperand(expr.expression);
|
|
431
|
+
return `(${typeName})${operand}`;
|
|
432
|
+
}
|
|
433
|
+
case "asExpression": {
|
|
434
|
+
const inner = printExpression(expr.expression);
|
|
435
|
+
return `${inner} as ${printType(expr.type)}`;
|
|
436
|
+
}
|
|
437
|
+
case "isExpression": {
|
|
438
|
+
const inner = printExpression(expr.expression);
|
|
439
|
+
const pattern = printPattern(expr.pattern);
|
|
440
|
+
return `${inner} is ${pattern}`;
|
|
441
|
+
}
|
|
442
|
+
case "defaultExpression":
|
|
443
|
+
return expr.type ? `default(${printType(expr.type)})` : "default";
|
|
444
|
+
case "awaitExpression":
|
|
445
|
+
return `await ${printUnaryOperand(expr.expression, true)}`;
|
|
446
|
+
case "lambdaExpression":
|
|
447
|
+
return printLambdaExpression(expr);
|
|
448
|
+
case "interpolatedStringExpression":
|
|
449
|
+
return printInterpolatedString(expr.parts);
|
|
450
|
+
case "throwExpression":
|
|
451
|
+
return `throw ${printExpression(expr.expression)}`;
|
|
452
|
+
case "suppressNullableWarningExpression":
|
|
453
|
+
return `${printPrimaryExpression(expr.expression)}!`;
|
|
454
|
+
case "typeofExpression":
|
|
455
|
+
return `typeof(${printType(expr.type)})`;
|
|
456
|
+
case "switchExpression":
|
|
457
|
+
return printSwitchExpression(expr);
|
|
458
|
+
case "argumentModifierExpression":
|
|
459
|
+
return `${expr.modifier} ${printExpression(expr.expression)}`;
|
|
460
|
+
case "tupleExpression": {
|
|
461
|
+
const elems = expr.elements.map(printExpression).join(", ");
|
|
462
|
+
return `(${elems})`;
|
|
463
|
+
}
|
|
464
|
+
default: {
|
|
465
|
+
const exhaustiveCheck = expr;
|
|
466
|
+
throw new Error(`ICE: Unhandled expression AST kind: ${exhaustiveCheck.kind}`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Print an expression that appears in a "primary" position
|
|
472
|
+
* (before `.member`, `[index]`, `(args)`, etc.).
|
|
473
|
+
* Wraps in parens if needed.
|
|
474
|
+
*/
|
|
475
|
+
const printPrimaryExpression = (expr) => {
|
|
476
|
+
const text = printExpression(expr);
|
|
477
|
+
const prec = getExpressionPrecedence(expr);
|
|
478
|
+
// Primary position requires precedence >= 15 (postfix and primary)
|
|
479
|
+
// or the expression is already a parenthesized/literal/identifier
|
|
480
|
+
if (prec >= 15)
|
|
481
|
+
return text;
|
|
482
|
+
if (expr.kind === "parenthesizedExpression" ||
|
|
483
|
+
expr.kind === "literalExpression" ||
|
|
484
|
+
expr.kind === "identifierExpression" ||
|
|
485
|
+
expr.kind === "defaultExpression" ||
|
|
486
|
+
expr.kind === "typeofExpression" ||
|
|
487
|
+
expr.kind === "interpolatedStringExpression" ||
|
|
488
|
+
expr.kind === "objectCreationExpression" ||
|
|
489
|
+
expr.kind === "arrayCreationExpression") {
|
|
490
|
+
return text;
|
|
491
|
+
}
|
|
492
|
+
return `(${text})`;
|
|
493
|
+
};
|
|
494
|
+
/**
|
|
495
|
+
* Print an expression that appears as a unary operand.
|
|
496
|
+
*/
|
|
497
|
+
const printUnaryOperand = (expr, isPrefix) => {
|
|
498
|
+
const text = printExpression(expr);
|
|
499
|
+
const prec = getExpressionPrecedence(expr);
|
|
500
|
+
if (isPrefix) {
|
|
501
|
+
// Prefix unary needs operand to be at least unary precedence
|
|
502
|
+
return prec >= 14 ? text : `(${text})`;
|
|
503
|
+
}
|
|
504
|
+
// Postfix unary needs primary expression
|
|
505
|
+
return prec >= 15 ? text : `(${text})`;
|
|
506
|
+
};
|
|
507
|
+
/**
|
|
508
|
+
* Print an expression that appears as a cast operand.
|
|
509
|
+
* Special rules: unary minus after cast needs parens to avoid ambiguity.
|
|
510
|
+
*/
|
|
511
|
+
const printCastOperand = (expr) => {
|
|
512
|
+
const text = printExpression(expr);
|
|
513
|
+
// Cast operand needs at least unary precedence
|
|
514
|
+
if (getExpressionPrecedence(expr) < 14) {
|
|
515
|
+
return `(${text})`;
|
|
516
|
+
}
|
|
517
|
+
// Special case: negative literals after cast need parens
|
|
518
|
+
// (int)-1 is ambiguous: could be cast or subtraction
|
|
519
|
+
if (expr.kind === "prefixUnaryExpression" && expr.operatorToken === "-") {
|
|
520
|
+
return `(${text})`;
|
|
521
|
+
}
|
|
522
|
+
if (expr.kind === "literalExpression" && text.startsWith("-")) {
|
|
523
|
+
return `(${text})`;
|
|
524
|
+
}
|
|
525
|
+
return text;
|
|
526
|
+
};
|
|
527
|
+
const printLambdaExpression = (expr) => {
|
|
528
|
+
const asyncPrefix = expr.isAsync ? "async " : "";
|
|
529
|
+
const params = printLambdaParameters(expr.parameters);
|
|
530
|
+
if (expr.body.kind === "blockStatement") {
|
|
531
|
+
if (expr.bodyIndent != null) {
|
|
532
|
+
// Multi-line block body with flat-block convention (braces + body at same indent)
|
|
533
|
+
return `${asyncPrefix}${params} =>\n${printStatementFlatBlock(expr.body, expr.bodyIndent)}`;
|
|
534
|
+
}
|
|
535
|
+
// Inline single-line block body: () => { stmt1; stmt2; }
|
|
536
|
+
const stmts = expr.body.statements
|
|
537
|
+
.map((s) => printStatement(s, ""))
|
|
538
|
+
.join(" ");
|
|
539
|
+
return `${asyncPrefix}${params} => { ${stmts} }`;
|
|
540
|
+
}
|
|
541
|
+
return `${asyncPrefix}${params} => ${printExpression(expr.body)}`;
|
|
542
|
+
};
|
|
543
|
+
const printLambdaParameters = (params) => {
|
|
544
|
+
const sole = params.length === 1 ? params[0] : undefined;
|
|
545
|
+
if (sole && !sole.type && !sole.modifier) {
|
|
546
|
+
return escapeIdentifier(sole.name);
|
|
547
|
+
}
|
|
548
|
+
const parts = params.map((p) => {
|
|
549
|
+
const mod = p.modifier ? `${p.modifier} ` : "";
|
|
550
|
+
return p.type
|
|
551
|
+
? `${mod}${printType(p.type)} ${escapeIdentifier(p.name)}`
|
|
552
|
+
: `${mod}${escapeIdentifier(p.name)}`;
|
|
553
|
+
});
|
|
554
|
+
return `(${parts.join(", ")})`;
|
|
555
|
+
};
|
|
556
|
+
const printInterpolatedString = (parts) => {
|
|
557
|
+
const inner = parts
|
|
558
|
+
.map((part) => {
|
|
559
|
+
if (part.kind === "text")
|
|
560
|
+
return part.text;
|
|
561
|
+
const exprText = printExpression(part.expression);
|
|
562
|
+
// Wrap in parens if the expression text contains ':' to prevent
|
|
563
|
+
// C# from interpreting it as a format specifier delimiter.
|
|
564
|
+
// Common case: global::Namespace.Type, ternary a ? b : c
|
|
565
|
+
const safeText = exprText.includes(":") ? `(${exprText})` : exprText;
|
|
566
|
+
return part.formatClause
|
|
567
|
+
? `{${safeText}:${part.formatClause}}`
|
|
568
|
+
: `{${safeText}}`;
|
|
569
|
+
})
|
|
570
|
+
.join("");
|
|
571
|
+
return `$"${inner}"`;
|
|
572
|
+
};
|
|
573
|
+
const printSwitchExpression = (expr) => {
|
|
574
|
+
const gov = printExpression(expr.governingExpression);
|
|
575
|
+
const arms = expr.arms.map(printSwitchExpressionArm).join(", ");
|
|
576
|
+
return `${gov} switch { ${arms} }`;
|
|
577
|
+
};
|
|
578
|
+
const printSwitchExpressionArm = (arm) => {
|
|
579
|
+
const pattern = printPattern(arm.pattern);
|
|
580
|
+
const whenClause = arm.whenClause
|
|
581
|
+
? ` when ${printExpression(arm.whenClause)}`
|
|
582
|
+
: "";
|
|
583
|
+
const result = printExpression(arm.expression);
|
|
584
|
+
return `${pattern}${whenClause} => ${result}`;
|
|
585
|
+
};
|
|
586
|
+
// ============================================================
|
|
587
|
+
// Pattern Printer
|
|
588
|
+
// ============================================================
|
|
589
|
+
export const printPattern = (pattern) => {
|
|
590
|
+
switch (pattern.kind) {
|
|
591
|
+
case "typePattern":
|
|
592
|
+
return printType(pattern.type);
|
|
593
|
+
case "declarationPattern":
|
|
594
|
+
return `${printType(pattern.type)} ${escapeIdentifier(pattern.designation)}`;
|
|
595
|
+
case "varPattern":
|
|
596
|
+
return `var ${escapeIdentifier(pattern.designation)}`;
|
|
597
|
+
case "constantPattern":
|
|
598
|
+
return printExpression(pattern.expression);
|
|
599
|
+
case "discardPattern":
|
|
600
|
+
return "_";
|
|
601
|
+
case "negatedPattern":
|
|
602
|
+
return `not ${printPattern(pattern.pattern)}`;
|
|
603
|
+
default: {
|
|
604
|
+
const exhaustiveCheck = pattern;
|
|
605
|
+
throw new Error(`ICE: Unhandled pattern AST kind: ${exhaustiveCheck.kind}`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
// ============================================================
|
|
610
|
+
// Statement Printer
|
|
611
|
+
// ============================================================
|
|
612
|
+
export const printStatement = (stmt, indent) => {
|
|
613
|
+
switch (stmt.kind) {
|
|
614
|
+
case "blockStatement":
|
|
615
|
+
return printBlockStatement(stmt, indent);
|
|
616
|
+
case "localDeclarationStatement": {
|
|
617
|
+
const mods = stmt.modifiers.length > 0 ? `${stmt.modifiers.join(" ")} ` : "";
|
|
618
|
+
const typeStr = printType(stmt.type);
|
|
619
|
+
const decls = stmt.declarators
|
|
620
|
+
.map((d) => d.initializer
|
|
621
|
+
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer)}`
|
|
622
|
+
: escapeIdentifier(d.name))
|
|
623
|
+
.join(", ");
|
|
624
|
+
return `${indent}${mods}${typeStr} ${decls};`;
|
|
625
|
+
}
|
|
626
|
+
case "localFunctionStatement": {
|
|
627
|
+
const mods = stmt.modifiers.length > 0 ? `${stmt.modifiers.join(" ")} ` : "";
|
|
628
|
+
const ret = printType(stmt.returnType);
|
|
629
|
+
const typeParams = stmt.typeParameters && stmt.typeParameters.length > 0
|
|
630
|
+
? `<${stmt.typeParameters.join(", ")}>`
|
|
631
|
+
: "";
|
|
632
|
+
const params = stmt.parameters.map(printParameter).join(", ");
|
|
633
|
+
const body = printBlockStatement(stmt.body, indent);
|
|
634
|
+
return `${indent}${mods}${ret} ${escapeIdentifier(stmt.name)}${typeParams}(${params})\n${body}`;
|
|
635
|
+
}
|
|
636
|
+
case "expressionStatement":
|
|
637
|
+
return `${indent}${printExpression(stmt.expression)};`;
|
|
638
|
+
case "ifStatement":
|
|
639
|
+
return printIfStatement(stmt, indent);
|
|
640
|
+
case "whileStatement": {
|
|
641
|
+
const cond = printExpression(stmt.condition);
|
|
642
|
+
const body = printStatement(stmt.body, indent);
|
|
643
|
+
return `${indent}while (${cond})\n${body}`;
|
|
644
|
+
}
|
|
645
|
+
case "forStatement":
|
|
646
|
+
return printForStatement(stmt, indent);
|
|
647
|
+
case "foreachStatement": {
|
|
648
|
+
const awaitStr = stmt.isAwait ? "await " : "";
|
|
649
|
+
const typeStr = printType(stmt.type);
|
|
650
|
+
const ident = escapeIdentifier(stmt.identifier);
|
|
651
|
+
const collection = printExpression(stmt.expression);
|
|
652
|
+
const body = printStatement(stmt.body, indent);
|
|
653
|
+
return `${indent}${awaitStr}foreach (${typeStr} ${ident} in ${collection})\n${body}`;
|
|
654
|
+
}
|
|
655
|
+
case "switchStatement":
|
|
656
|
+
return printSwitchStatement(stmt, indent);
|
|
657
|
+
case "tryStatement":
|
|
658
|
+
return printTryStatement(stmt, indent);
|
|
659
|
+
case "throwStatement":
|
|
660
|
+
return stmt.expression
|
|
661
|
+
? `${indent}throw ${printExpression(stmt.expression)};`
|
|
662
|
+
: `${indent}throw;`;
|
|
663
|
+
case "returnStatement":
|
|
664
|
+
return stmt.expression
|
|
665
|
+
? `${indent}return ${printExpression(stmt.expression)};`
|
|
666
|
+
: `${indent}return;`;
|
|
667
|
+
case "breakStatement":
|
|
668
|
+
return `${indent}break;`;
|
|
669
|
+
case "continueStatement":
|
|
670
|
+
return `${indent}continue;`;
|
|
671
|
+
case "emptyStatement":
|
|
672
|
+
return `${indent};`;
|
|
673
|
+
case "yieldStatement":
|
|
674
|
+
if (stmt.isBreak) {
|
|
675
|
+
return `${indent}yield break;`;
|
|
676
|
+
}
|
|
677
|
+
return stmt.expression
|
|
678
|
+
? `${indent}yield return ${printExpression(stmt.expression)};`
|
|
679
|
+
: `${indent}yield return;`;
|
|
680
|
+
default: {
|
|
681
|
+
const exhaustiveCheck = stmt;
|
|
682
|
+
throw new Error(`ICE: Unhandled statement AST kind: ${exhaustiveCheck.kind}`);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
const printBlockStatement = (block, indent) => {
|
|
687
|
+
const innerIndent = indent + " ";
|
|
688
|
+
const stmts = block.statements
|
|
689
|
+
.map((s) => printStatement(s, innerIndent))
|
|
690
|
+
.join("\n");
|
|
691
|
+
return `${indent}{\n${stmts}\n${indent}}`;
|
|
692
|
+
};
|
|
693
|
+
const printIfStatement = (stmt, indent) => {
|
|
694
|
+
const cond = printExpression(stmt.condition);
|
|
695
|
+
const thenBody = printStatement(stmt.thenStatement, indent);
|
|
696
|
+
if (!stmt.elseStatement) {
|
|
697
|
+
return `${indent}if (${cond})\n${thenBody}`;
|
|
698
|
+
}
|
|
699
|
+
// Else-if chain: don't add extra indentation
|
|
700
|
+
if (stmt.elseStatement.kind === "ifStatement") {
|
|
701
|
+
const elseIfText = printIfStatement(stmt.elseStatement, indent);
|
|
702
|
+
// Strip the indent from the else-if since we're adding "else " prefix
|
|
703
|
+
const elseIfBody = elseIfText.slice(indent.length);
|
|
704
|
+
return `${indent}if (${cond})\n${thenBody}\n${indent}else ${elseIfBody}`;
|
|
705
|
+
}
|
|
706
|
+
const elseBody = printStatement(stmt.elseStatement, indent);
|
|
707
|
+
return `${indent}if (${cond})\n${thenBody}\n${indent}else\n${elseBody}`;
|
|
708
|
+
};
|
|
709
|
+
const printForStatement = (stmt, indent) => {
|
|
710
|
+
const parts = [];
|
|
711
|
+
// Initializer
|
|
712
|
+
if (stmt.declaration) {
|
|
713
|
+
const typeStr = printType(stmt.declaration.type);
|
|
714
|
+
const decls = stmt.declaration.declarators
|
|
715
|
+
.map((d) => d.initializer
|
|
716
|
+
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer)}`
|
|
717
|
+
: escapeIdentifier(d.name))
|
|
718
|
+
.join(", ");
|
|
719
|
+
parts.push(`${typeStr} ${decls}`);
|
|
720
|
+
}
|
|
721
|
+
else if (stmt.initializers && stmt.initializers.length > 0) {
|
|
722
|
+
parts.push(stmt.initializers.map(printExpression).join(", "));
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
parts.push("");
|
|
726
|
+
}
|
|
727
|
+
// Condition
|
|
728
|
+
parts.push(stmt.condition ? printExpression(stmt.condition) : "");
|
|
729
|
+
// Incrementors
|
|
730
|
+
parts.push(stmt.incrementors.map(printExpression).join(", "));
|
|
731
|
+
const header = parts.join("; ");
|
|
732
|
+
const body = printStatement(stmt.body, indent);
|
|
733
|
+
return `${indent}for (${header})\n${body}`;
|
|
734
|
+
};
|
|
735
|
+
const printSwitchStatement = (stmt, indent) => {
|
|
736
|
+
const expr = printExpression(stmt.expression);
|
|
737
|
+
const innerIndent = indent + " ";
|
|
738
|
+
const sections = stmt.sections
|
|
739
|
+
.map((s) => printSwitchSection(s, innerIndent))
|
|
740
|
+
.join("\n");
|
|
741
|
+
return `${indent}switch (${expr})\n${indent}{\n${sections}\n${indent}}`;
|
|
742
|
+
};
|
|
743
|
+
const printSwitchSection = (section, indent) => {
|
|
744
|
+
const labels = section.labels
|
|
745
|
+
.map((l) => printSwitchLabel(l, indent))
|
|
746
|
+
.join("\n");
|
|
747
|
+
const stmtIndent = indent + " ";
|
|
748
|
+
const stmts = section.statements
|
|
749
|
+
.map((s) => printStatement(s, stmtIndent))
|
|
750
|
+
.join("\n");
|
|
751
|
+
return `${labels}\n${stmts}`;
|
|
752
|
+
};
|
|
753
|
+
const printSwitchLabel = (label, indent) => {
|
|
754
|
+
switch (label.kind) {
|
|
755
|
+
case "caseSwitchLabel":
|
|
756
|
+
return `${indent}case ${printExpression(label.value)}:`;
|
|
757
|
+
case "casePatternSwitchLabel": {
|
|
758
|
+
const pattern = printPattern(label.pattern);
|
|
759
|
+
const when = label.whenClause
|
|
760
|
+
? ` when ${printExpression(label.whenClause)}`
|
|
761
|
+
: "";
|
|
762
|
+
return `${indent}case ${pattern}${when}:`;
|
|
763
|
+
}
|
|
764
|
+
case "defaultSwitchLabel":
|
|
765
|
+
return `${indent}default:`;
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
const printTryStatement = (stmt, indent) => {
|
|
769
|
+
const tryBody = printBlockStatement(stmt.body, indent);
|
|
770
|
+
const catches = stmt.catches
|
|
771
|
+
.map((c) => printCatchClause(c, indent))
|
|
772
|
+
.join("\n");
|
|
773
|
+
const finallyStr = stmt.finallyBody
|
|
774
|
+
? `\n${indent}finally\n${printBlockStatement(stmt.finallyBody, indent)}`
|
|
775
|
+
: "";
|
|
776
|
+
return `${indent}try\n${tryBody}\n${catches}${finallyStr}`;
|
|
777
|
+
};
|
|
778
|
+
const printCatchClause = (clause, indent) => {
|
|
779
|
+
const body = printBlockStatement(clause.body, indent);
|
|
780
|
+
if (!clause.type) {
|
|
781
|
+
return `${indent}catch\n${body}`;
|
|
782
|
+
}
|
|
783
|
+
const typeName = printType(clause.type);
|
|
784
|
+
const ident = clause.identifier
|
|
785
|
+
? ` ${escapeIdentifier(clause.identifier)}`
|
|
786
|
+
: "";
|
|
787
|
+
const filter = clause.filter
|
|
788
|
+
? ` when (${printExpression(clause.filter)})`
|
|
789
|
+
: "";
|
|
790
|
+
return `${indent}catch (${typeName}${ident})${filter}\n${body}`;
|
|
791
|
+
};
|
|
792
|
+
export const printParameter = (param) => {
|
|
793
|
+
const attrPrefix = param.attributes && param.attributes.length > 0
|
|
794
|
+
? param.attributes
|
|
795
|
+
.map((a) => {
|
|
796
|
+
const targetPrefix = a.target ? `${a.target}: ` : "";
|
|
797
|
+
const args = a.arguments && a.arguments.length > 0
|
|
798
|
+
? `(${a.arguments.map(printExpression).join(", ")})`
|
|
799
|
+
: "";
|
|
800
|
+
return `[${targetPrefix}${printType(a.type)}${args}]`;
|
|
801
|
+
})
|
|
802
|
+
.join("") + " "
|
|
803
|
+
: "";
|
|
804
|
+
const mods = param.modifiers && param.modifiers.length > 0
|
|
805
|
+
? `${param.modifiers.join(" ")} `
|
|
806
|
+
: "";
|
|
807
|
+
const typeName = printType(param.type);
|
|
808
|
+
const name = escapeIdentifier(param.name);
|
|
809
|
+
const defaultVal = param.defaultValue
|
|
810
|
+
? ` = ${printExpression(param.defaultValue)}`
|
|
811
|
+
: "";
|
|
812
|
+
return `${attrPrefix}${mods}${typeName} ${name}${defaultVal}`;
|
|
813
|
+
};
|
|
814
|
+
// ============================================================
|
|
815
|
+
// Declaration Printer
|
|
816
|
+
// ============================================================
|
|
817
|
+
export const printMember = (member, indent) => {
|
|
818
|
+
switch (member.kind) {
|
|
819
|
+
case "fieldDeclaration": {
|
|
820
|
+
const attrs = printAttributes(member.attributes, indent);
|
|
821
|
+
const mods = member.modifiers.length > 0 ? `${member.modifiers.join(" ")} ` : "";
|
|
822
|
+
const typeName = printType(member.type);
|
|
823
|
+
const name = escapeIdentifier(member.name);
|
|
824
|
+
const init = member.initializer
|
|
825
|
+
? ` = ${printExpression(member.initializer)}`
|
|
826
|
+
: "";
|
|
827
|
+
return `${attrs}${indent}${mods}${typeName} ${name}${init};`;
|
|
828
|
+
}
|
|
829
|
+
case "propertyDeclaration": {
|
|
830
|
+
const attrs = printAttributes(member.attributes, indent);
|
|
831
|
+
const mods = member.modifiers.length > 0 ? `${member.modifiers.join(" ")} ` : "";
|
|
832
|
+
const typeName = printType(member.type);
|
|
833
|
+
const name = escapeIdentifier(member.name);
|
|
834
|
+
if (member.isAutoProperty) {
|
|
835
|
+
const getStr = member.hasGetter ? "get; " : "";
|
|
836
|
+
const setStr = member.hasInit
|
|
837
|
+
? "init; "
|
|
838
|
+
: member.hasSetter
|
|
839
|
+
? "set; "
|
|
840
|
+
: "";
|
|
841
|
+
const accessors = ` { ${getStr}${setStr}}`;
|
|
842
|
+
const init = member.initializer
|
|
843
|
+
? ` = ${printExpression(member.initializer)};`
|
|
844
|
+
: "";
|
|
845
|
+
return `${attrs}${indent}${mods}${typeName} ${name}${accessors}${init}`;
|
|
846
|
+
}
|
|
847
|
+
// Explicit property accessors
|
|
848
|
+
const bodyIndent = indent + " ";
|
|
849
|
+
const accessorIndent = bodyIndent + " ";
|
|
850
|
+
const lines = [];
|
|
851
|
+
lines.push(`${attrs}${indent}${mods}${typeName} ${name}`);
|
|
852
|
+
lines.push(`${bodyIndent}{`);
|
|
853
|
+
if (member.getterBody) {
|
|
854
|
+
lines.push(`${bodyIndent}get`);
|
|
855
|
+
lines.push(printBlockStatement(member.getterBody, accessorIndent));
|
|
856
|
+
}
|
|
857
|
+
if (member.setterBody) {
|
|
858
|
+
lines.push(`${bodyIndent}set`);
|
|
859
|
+
lines.push(printBlockStatement(member.setterBody, accessorIndent));
|
|
860
|
+
}
|
|
861
|
+
lines.push(`${bodyIndent}}`);
|
|
862
|
+
return lines.join("\n");
|
|
863
|
+
}
|
|
864
|
+
case "methodDeclaration": {
|
|
865
|
+
const attrs = printAttributes(member.attributes, indent);
|
|
866
|
+
const mods = member.modifiers.length > 0 ? `${member.modifiers.join(" ")} ` : "";
|
|
867
|
+
const ret = printType(member.returnType);
|
|
868
|
+
const typeParams = printTypeParameters(member.typeParameters);
|
|
869
|
+
const params = member.parameters.map(printParameter).join(", ");
|
|
870
|
+
const constraints = printConstraints(member.constraints, indent);
|
|
871
|
+
if (member.expressionBody) {
|
|
872
|
+
return `${attrs}${indent}${mods}${ret} ${escapeIdentifier(member.name)}${typeParams}(${params})${constraints} => ${printExpression(member.expressionBody)};`;
|
|
873
|
+
}
|
|
874
|
+
if (member.body) {
|
|
875
|
+
return `${attrs}${indent}${mods}${ret} ${escapeIdentifier(member.name)}${typeParams}(${params})${constraints}\n${printBlockStatement(member.body, indent)}`;
|
|
876
|
+
}
|
|
877
|
+
// Abstract/interface method (no body)
|
|
878
|
+
return `${attrs}${indent}${mods}${ret} ${escapeIdentifier(member.name)}${typeParams}(${params})${constraints};`;
|
|
879
|
+
}
|
|
880
|
+
case "constructorDeclaration": {
|
|
881
|
+
const attrs = printAttributes(member.attributes, indent);
|
|
882
|
+
const mods = member.modifiers.length > 0 ? `${member.modifiers.join(" ")} ` : "";
|
|
883
|
+
const params = member.parameters.map(printParameter).join(", ");
|
|
884
|
+
const baseCall = member.baseArguments !== undefined
|
|
885
|
+
? ` : base(${member.baseArguments.map(printExpression).join(", ")})`
|
|
886
|
+
: "";
|
|
887
|
+
return `${attrs}${indent}${mods}${escapeIdentifier(member.name)}(${params})${baseCall}\n${printBlockStatement(member.body, indent)}`;
|
|
888
|
+
}
|
|
889
|
+
case "delegateDeclaration": {
|
|
890
|
+
const mods = member.modifiers.length > 0 ? `${member.modifiers.join(" ")} ` : "";
|
|
891
|
+
const ret = printType(member.returnType);
|
|
892
|
+
const params = member.parameters.map(printParameter).join(", ");
|
|
893
|
+
return `${indent}${mods}delegate ${ret} ${escapeIdentifier(member.name)}(${params});`;
|
|
894
|
+
}
|
|
895
|
+
default: {
|
|
896
|
+
const exhaustiveCheck = member;
|
|
897
|
+
throw new Error(`ICE: Unhandled member AST kind: ${exhaustiveCheck.kind}`);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
export const printTypeDeclaration = (decl, indent) => {
|
|
902
|
+
switch (decl.kind) {
|
|
903
|
+
case "classDeclaration":
|
|
904
|
+
case "structDeclaration":
|
|
905
|
+
case "interfaceDeclaration": {
|
|
906
|
+
const keyword = decl.kind === "classDeclaration"
|
|
907
|
+
? "class"
|
|
908
|
+
: decl.kind === "structDeclaration"
|
|
909
|
+
? "struct"
|
|
910
|
+
: "interface";
|
|
911
|
+
const attrs = printAttributes(decl.attributes, indent);
|
|
912
|
+
const mods = decl.modifiers.length > 0 ? `${decl.modifiers.join(" ")} ` : "";
|
|
913
|
+
const typeParams = printTypeParameters(decl.typeParameters);
|
|
914
|
+
const baseTypes = [];
|
|
915
|
+
if (decl.kind === "classDeclaration" && decl.baseType) {
|
|
916
|
+
baseTypes.push(printType(decl.baseType));
|
|
917
|
+
}
|
|
918
|
+
baseTypes.push(...decl.interfaces.map(printType));
|
|
919
|
+
const baseClause = baseTypes.length > 0 ? ` : ${baseTypes.join(", ")}` : "";
|
|
920
|
+
const constraints = printConstraints(decl.constraints, indent);
|
|
921
|
+
const innerIndent = indent + " ";
|
|
922
|
+
const members = decl.members
|
|
923
|
+
.map((m) => printMember(m, innerIndent))
|
|
924
|
+
.join("\n\n");
|
|
925
|
+
return `${attrs}${indent}${mods}${keyword} ${escapeIdentifier(decl.name)}${typeParams}${baseClause}${constraints}\n${indent}{\n${members}\n${indent}}`;
|
|
926
|
+
}
|
|
927
|
+
case "enumDeclaration": {
|
|
928
|
+
const attrs = printAttributes(decl.attributes, indent);
|
|
929
|
+
const mods = decl.modifiers.length > 0 ? `${decl.modifiers.join(" ")} ` : "";
|
|
930
|
+
const innerIndent = indent + " ";
|
|
931
|
+
const members = decl.members
|
|
932
|
+
.map((m) => printEnumMember(m, innerIndent))
|
|
933
|
+
.join(",\n");
|
|
934
|
+
return `${attrs}${indent}${mods}enum ${escapeIdentifier(decl.name)}\n${indent}{\n${members}\n${indent}}`;
|
|
935
|
+
}
|
|
936
|
+
default: {
|
|
937
|
+
const exhaustiveCheck = decl;
|
|
938
|
+
throw new Error(`ICE: Unhandled type declaration AST kind: ${exhaustiveCheck.kind}`);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
};
|
|
942
|
+
const printEnumMember = (member, indent) => member.value
|
|
943
|
+
? `${indent}${escapeIdentifier(member.name)} = ${printExpression(member.value)}`
|
|
944
|
+
: `${indent}${escapeIdentifier(member.name)}`;
|
|
945
|
+
const printTypeParameters = (typeParams) => {
|
|
946
|
+
if (!typeParams || typeParams.length === 0)
|
|
947
|
+
return "";
|
|
948
|
+
return `<${typeParams.map((tp) => tp.name).join(", ")}>`;
|
|
949
|
+
};
|
|
950
|
+
const printConstraints = (constraints, indent) => {
|
|
951
|
+
if (!constraints || constraints.length === 0)
|
|
952
|
+
return "";
|
|
953
|
+
const printConstraint = (constraint) => {
|
|
954
|
+
switch (constraint.kind) {
|
|
955
|
+
case "typeConstraint":
|
|
956
|
+
return printType(constraint.type);
|
|
957
|
+
case "classConstraint":
|
|
958
|
+
return "class";
|
|
959
|
+
case "structConstraint":
|
|
960
|
+
return "struct";
|
|
961
|
+
case "constructorConstraint":
|
|
962
|
+
return "new()";
|
|
963
|
+
default: {
|
|
964
|
+
const exhaustiveCheck = constraint;
|
|
965
|
+
throw new Error(`ICE: Unhandled type parameter constraint kind: ${exhaustiveCheck.kind}`);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
return constraints
|
|
970
|
+
.map((c) => `\n${indent} where ${escapeIdentifier(c.typeParameter)} : ${c.constraints
|
|
971
|
+
.map(printConstraint)
|
|
972
|
+
.join(", ")}`)
|
|
973
|
+
.join("");
|
|
974
|
+
};
|
|
975
|
+
export const printAttributes = (attrs, indent) => {
|
|
976
|
+
if (attrs.length === 0)
|
|
977
|
+
return "";
|
|
978
|
+
return attrs
|
|
979
|
+
.map((a) => {
|
|
980
|
+
const targetPrefix = a.target ? `${a.target}: ` : "";
|
|
981
|
+
const args = a.arguments && a.arguments.length > 0
|
|
982
|
+
? `(${a.arguments.map(printExpression).join(", ")})`
|
|
983
|
+
: "";
|
|
984
|
+
return `${indent}[${targetPrefix}${printType(a.type)}${args}]\n`;
|
|
985
|
+
})
|
|
986
|
+
.join("");
|
|
987
|
+
};
|
|
988
|
+
// ============================================================
|
|
989
|
+
// Compilation Unit Printer
|
|
990
|
+
// ============================================================
|
|
991
|
+
export const printCompilationUnit = (unit) => {
|
|
992
|
+
const parts = [];
|
|
993
|
+
if (unit.header) {
|
|
994
|
+
parts.push(unit.header);
|
|
995
|
+
}
|
|
996
|
+
const usings = unit.usings
|
|
997
|
+
.map((u) => `using ${escapeQualifiedName(u.namespace, false)};`)
|
|
998
|
+
.join("\n");
|
|
999
|
+
if (usings) {
|
|
1000
|
+
parts.push(usings);
|
|
1001
|
+
parts.push("");
|
|
1002
|
+
}
|
|
1003
|
+
const members = unit.members
|
|
1004
|
+
.map((m) => {
|
|
1005
|
+
if (m.kind === "namespaceDeclaration") {
|
|
1006
|
+
return printNamespaceDeclaration(m);
|
|
1007
|
+
}
|
|
1008
|
+
return printTypeDeclaration(m, "");
|
|
1009
|
+
})
|
|
1010
|
+
.join("\n\n");
|
|
1011
|
+
if (members) {
|
|
1012
|
+
parts.push(members);
|
|
1013
|
+
}
|
|
1014
|
+
return parts.join("\n");
|
|
1015
|
+
};
|
|
1016
|
+
const printNamespaceDeclaration = (ns) => {
|
|
1017
|
+
const name = escapeQualifiedName(ns.name, false);
|
|
1018
|
+
const members = ns.members
|
|
1019
|
+
.map((m) => printTypeDeclaration(m, " "))
|
|
1020
|
+
.join("\n\n");
|
|
1021
|
+
return `namespace ${name}\n{\n${members}\n}`;
|
|
1022
|
+
};
|
|
1023
|
+
// ============================================================
|
|
1024
|
+
// Flat Block Printer
|
|
1025
|
+
// ============================================================
|
|
1026
|
+
/**
|
|
1027
|
+
* Print a statement with "flat block" convention:
|
|
1028
|
+
* block braces and inner statements share the same indent level.
|
|
1029
|
+
*
|
|
1030
|
+
* Used by the static container's __TopLevel method and other contexts
|
|
1031
|
+
* where block bodies need Tsonic's flat-block formatting (braces at same
|
|
1032
|
+
* indent as inner statements, not C#-standard nested convention).
|
|
1033
|
+
*
|
|
1034
|
+
* For compound statements (if/while/for/foreach/switch/try), body blocks
|
|
1035
|
+
* are printed at indent+4 with flat block convention (braces and inner
|
|
1036
|
+
* statements at the same level).
|
|
1037
|
+
*/
|
|
1038
|
+
export const printStatementFlatBlock = (stmt, indent) => {
|
|
1039
|
+
const bodyIndent = indent + " ";
|
|
1040
|
+
switch (stmt.kind) {
|
|
1041
|
+
case "blockStatement": {
|
|
1042
|
+
const inner = stmt.statements
|
|
1043
|
+
.map((s) => printStatementFlatBlock(s, indent))
|
|
1044
|
+
.join("\n");
|
|
1045
|
+
return `${indent}{\n${inner}\n${indent}}`;
|
|
1046
|
+
}
|
|
1047
|
+
case "ifStatement": {
|
|
1048
|
+
const cond = printExpression(stmt.condition);
|
|
1049
|
+
const thenBody = printStatementFlatBlock(stmt.thenStatement, bodyIndent);
|
|
1050
|
+
if (!stmt.elseStatement) {
|
|
1051
|
+
return `${indent}if (${cond})\n${thenBody}`;
|
|
1052
|
+
}
|
|
1053
|
+
// Else-if chain
|
|
1054
|
+
if (stmt.elseStatement.kind === "ifStatement") {
|
|
1055
|
+
const elseIfText = printStatementFlatBlock(stmt.elseStatement, indent);
|
|
1056
|
+
const elseIfBody = elseIfText.slice(indent.length);
|
|
1057
|
+
return `${indent}if (${cond})\n${thenBody}\n${indent}else ${elseIfBody}`;
|
|
1058
|
+
}
|
|
1059
|
+
const elseBody = printStatementFlatBlock(stmt.elseStatement, bodyIndent);
|
|
1060
|
+
return `${indent}if (${cond})\n${thenBody}\n${indent}else\n${elseBody}`;
|
|
1061
|
+
}
|
|
1062
|
+
case "whileStatement": {
|
|
1063
|
+
const cond = printExpression(stmt.condition);
|
|
1064
|
+
const body = printStatementFlatBlock(stmt.body, bodyIndent);
|
|
1065
|
+
return `${indent}while (${cond})\n${body}`;
|
|
1066
|
+
}
|
|
1067
|
+
case "forStatement": {
|
|
1068
|
+
const parts = [];
|
|
1069
|
+
if (stmt.declaration) {
|
|
1070
|
+
const typeStr = printType(stmt.declaration.type);
|
|
1071
|
+
const decls = stmt.declaration.declarators
|
|
1072
|
+
.map((d) => d.initializer
|
|
1073
|
+
? `${escapeIdentifier(d.name)} = ${printExpression(d.initializer)}`
|
|
1074
|
+
: escapeIdentifier(d.name))
|
|
1075
|
+
.join(", ");
|
|
1076
|
+
parts.push(`${typeStr} ${decls}`);
|
|
1077
|
+
}
|
|
1078
|
+
else if (stmt.initializers && stmt.initializers.length > 0) {
|
|
1079
|
+
parts.push(stmt.initializers.map(printExpression).join(", "));
|
|
1080
|
+
}
|
|
1081
|
+
else {
|
|
1082
|
+
parts.push("");
|
|
1083
|
+
}
|
|
1084
|
+
parts.push(stmt.condition ? printExpression(stmt.condition) : "");
|
|
1085
|
+
parts.push(stmt.incrementors.map(printExpression).join(", "));
|
|
1086
|
+
const header = parts.join("; ");
|
|
1087
|
+
const body = printStatementFlatBlock(stmt.body, bodyIndent);
|
|
1088
|
+
return `${indent}for (${header})\n${body}`;
|
|
1089
|
+
}
|
|
1090
|
+
case "foreachStatement": {
|
|
1091
|
+
const awaitStr = stmt.isAwait ? "await " : "";
|
|
1092
|
+
const typeStr = printType(stmt.type);
|
|
1093
|
+
const ident = escapeIdentifier(stmt.identifier);
|
|
1094
|
+
const collection = printExpression(stmt.expression);
|
|
1095
|
+
const body = printStatementFlatBlock(stmt.body, bodyIndent);
|
|
1096
|
+
return `${indent}${awaitStr}foreach (${typeStr} ${ident} in ${collection})\n${body}`;
|
|
1097
|
+
}
|
|
1098
|
+
case "switchStatement": {
|
|
1099
|
+
const expr = printExpression(stmt.expression);
|
|
1100
|
+
const sections = stmt.sections
|
|
1101
|
+
.map((s) => {
|
|
1102
|
+
const labels = s.labels
|
|
1103
|
+
.map((l) => printSwitchLabel(l, bodyIndent))
|
|
1104
|
+
.join("\n");
|
|
1105
|
+
const stmtInd = bodyIndent + " ";
|
|
1106
|
+
const sectionStmts = s.statements
|
|
1107
|
+
.map((st) => printStatementFlatBlock(st, stmtInd))
|
|
1108
|
+
.join("\n");
|
|
1109
|
+
return `${labels}\n${sectionStmts}`;
|
|
1110
|
+
})
|
|
1111
|
+
.join("\n");
|
|
1112
|
+
return `${indent}switch (${expr})\n${indent}{\n${sections}\n${indent}}`;
|
|
1113
|
+
}
|
|
1114
|
+
case "tryStatement": {
|
|
1115
|
+
// Try/catch/finally bodies are at the SAME indent as the keyword
|
|
1116
|
+
// (the old text emitter did NOT call indent() for try/catch bodies)
|
|
1117
|
+
const tryBody = printStatementFlatBlock(stmt.body, indent);
|
|
1118
|
+
const catches = stmt.catches
|
|
1119
|
+
.map((c) => {
|
|
1120
|
+
const catchBody = printStatementFlatBlock(c.body, indent);
|
|
1121
|
+
if (!c.type) {
|
|
1122
|
+
return `${indent}catch\n${catchBody}`;
|
|
1123
|
+
}
|
|
1124
|
+
const typeName = printType(c.type);
|
|
1125
|
+
const ident = c.identifier
|
|
1126
|
+
? ` ${escapeIdentifier(c.identifier)}`
|
|
1127
|
+
: "";
|
|
1128
|
+
const filter = c.filter ? ` when (${printExpression(c.filter)})` : "";
|
|
1129
|
+
return `${indent}catch (${typeName}${ident})${filter}\n${catchBody}`;
|
|
1130
|
+
})
|
|
1131
|
+
.join("\n");
|
|
1132
|
+
const finallyStr = stmt.finallyBody
|
|
1133
|
+
? `\n${indent}finally\n${printStatementFlatBlock(stmt.finallyBody, indent)}`
|
|
1134
|
+
: "";
|
|
1135
|
+
return `${indent}try\n${tryBody}\n${catches}${finallyStr}`;
|
|
1136
|
+
}
|
|
1137
|
+
case "localFunctionStatement": {
|
|
1138
|
+
const mods = stmt.modifiers.length > 0 ? `${stmt.modifiers.join(" ")} ` : "";
|
|
1139
|
+
const ret = printType(stmt.returnType);
|
|
1140
|
+
const typeParams = stmt.typeParameters && stmt.typeParameters.length > 0
|
|
1141
|
+
? `<${stmt.typeParameters.join(", ")}>`
|
|
1142
|
+
: "";
|
|
1143
|
+
const params = stmt.parameters.map(printParameter).join(", ");
|
|
1144
|
+
const body = printBlockStatement(stmt.body, indent);
|
|
1145
|
+
return `${indent}${mods}${ret} ${escapeIdentifier(stmt.name)}${typeParams}(${params})\n${body}`;
|
|
1146
|
+
}
|
|
1147
|
+
default:
|
|
1148
|
+
return printStatement(stmt, indent);
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
//# sourceMappingURL=printer.js.map
|