@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.
Files changed (520) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapter-generator.d.ts +5 -15
  3. package/dist/adapter-generator.d.ts.map +1 -1
  4. package/dist/adapter-generator.js +60 -53
  5. package/dist/adapter-generator.js.map +1 -1
  6. package/dist/contracts/backend-adapter.d.ts +36 -0
  7. package/dist/contracts/backend-adapter.d.ts.map +1 -0
  8. package/dist/contracts/backend-adapter.js +9 -0
  9. package/dist/contracts/backend-adapter.js.map +1 -0
  10. package/dist/contracts/emitter-contract.d.ts +54 -0
  11. package/dist/contracts/emitter-contract.d.ts.map +1 -0
  12. package/dist/contracts/emitter-contract.js +8 -0
  13. package/dist/contracts/emitter-contract.js.map +1 -0
  14. package/dist/contracts/import-classifier.d.ts +36 -0
  15. package/dist/contracts/import-classifier.d.ts.map +1 -0
  16. package/dist/contracts/import-classifier.js +9 -0
  17. package/dist/contracts/import-classifier.js.map +1 -0
  18. package/dist/core/{attributes.d.ts → format/attributes.d.ts} +9 -14
  19. package/dist/core/format/attributes.d.ts.map +1 -0
  20. package/dist/core/format/attributes.js +190 -0
  21. package/dist/core/format/attributes.js.map +1 -0
  22. package/dist/core/format/attributes.test.d.ts.map +1 -0
  23. package/dist/core/{attributes.test.js → format/attributes.test.js} +70 -32
  24. package/dist/core/format/attributes.test.js.map +1 -0
  25. package/dist/core/format/backend-ast/index.d.ts +7 -0
  26. package/dist/core/format/backend-ast/index.d.ts.map +1 -0
  27. package/dist/core/format/backend-ast/index.js +6 -0
  28. package/dist/core/format/backend-ast/index.js.map +1 -0
  29. package/dist/core/format/backend-ast/printer.d.ts +33 -0
  30. package/dist/core/format/backend-ast/printer.d.ts.map +1 -0
  31. package/dist/core/format/backend-ast/printer.js +1151 -0
  32. package/dist/core/format/backend-ast/printer.js.map +1 -0
  33. package/dist/core/format/backend-ast/types.d.ts +504 -0
  34. package/dist/core/format/backend-ast/types.d.ts.map +1 -0
  35. package/dist/core/format/backend-ast/types.js +13 -0
  36. package/dist/core/format/backend-ast/types.js.map +1 -0
  37. package/dist/core/format/backend-ast/utils.d.ts +26 -0
  38. package/dist/core/format/backend-ast/utils.d.ts.map +1 -0
  39. package/dist/core/format/backend-ast/utils.js +65 -0
  40. package/dist/core/format/backend-ast/utils.js.map +1 -0
  41. package/dist/core/{exports.d.ts → format/exports.d.ts} +2 -2
  42. package/dist/core/format/exports.d.ts.map +1 -0
  43. package/dist/core/format/exports.js +22 -0
  44. package/dist/core/format/exports.js.map +1 -0
  45. package/dist/core/format/index.d.ts +9 -0
  46. package/dist/core/format/index.d.ts.map +1 -0
  47. package/dist/core/format/index.js +9 -0
  48. package/dist/core/format/index.js.map +1 -0
  49. package/dist/core/{local-names.d.ts → format/local-names.d.ts} +1 -1
  50. package/dist/core/format/local-names.d.ts.map +1 -0
  51. package/dist/core/{local-names.js → format/local-names.js} +1 -1
  52. package/dist/core/format/local-names.js.map +1 -0
  53. package/dist/core/format/module-emitter/assembly.d.ts +27 -0
  54. package/dist/core/format/module-emitter/assembly.d.ts.map +1 -0
  55. package/dist/core/format/module-emitter/assembly.js +44 -0
  56. package/dist/core/format/module-emitter/assembly.js.map +1 -0
  57. package/dist/core/{module-emitter → format/module-emitter}/header.d.ts +1 -1
  58. package/dist/core/format/module-emitter/header.d.ts.map +1 -0
  59. package/dist/core/{module-emitter → format/module-emitter}/header.js +1 -1
  60. package/dist/core/format/module-emitter/header.js.map +1 -0
  61. package/dist/core/format/module-emitter/index.d.ts.map +1 -0
  62. package/dist/core/format/module-emitter/index.js.map +1 -0
  63. package/dist/core/format/module-emitter/namespace.d.ts +21 -0
  64. package/dist/core/format/module-emitter/namespace.d.ts.map +1 -0
  65. package/dist/core/format/module-emitter/namespace.js +58 -0
  66. package/dist/core/format/module-emitter/namespace.js.map +1 -0
  67. package/dist/core/{module-emitter → format/module-emitter}/orchestrator.d.ts +1 -1
  68. package/dist/core/format/module-emitter/orchestrator.d.ts.map +1 -0
  69. package/dist/core/{module-emitter → format/module-emitter}/orchestrator.js +19 -19
  70. package/dist/core/format/module-emitter/orchestrator.js.map +1 -0
  71. package/dist/core/format/module-emitter/separation.d.ts.map +1 -0
  72. package/dist/core/format/module-emitter/separation.js.map +1 -0
  73. package/dist/core/{module-emitter → format/module-emitter}/static-container.d.ts +8 -3
  74. package/dist/core/format/module-emitter/static-container.d.ts.map +1 -0
  75. package/dist/core/format/module-emitter/static-container.js +202 -0
  76. package/dist/core/format/module-emitter/static-container.js.map +1 -0
  77. package/dist/core/format/module-emitter.d.ts.map +1 -0
  78. package/dist/core/format/module-emitter.js.map +1 -0
  79. package/dist/core/{options.d.ts → format/options.d.ts} +1 -1
  80. package/dist/core/format/options.d.ts.map +1 -0
  81. package/dist/core/format/options.js.map +1 -0
  82. package/dist/core/index.d.ts +2 -7
  83. package/dist/core/index.d.ts.map +1 -1
  84. package/dist/core/index.js +2 -7
  85. package/dist/core/index.js.map +1 -1
  86. package/dist/core/semantic/boolean-context.d.ts +44 -0
  87. package/dist/core/semantic/boolean-context.d.ts.map +1 -0
  88. package/dist/core/semantic/boolean-context.js +717 -0
  89. package/dist/core/semantic/boolean-context.js.map +1 -0
  90. package/dist/core/semantic/boolean-context.test.d.ts.map +1 -0
  91. package/dist/core/{boolean-context.test.js → semantic/boolean-context.test.js} +86 -109
  92. package/dist/core/semantic/boolean-context.test.js.map +1 -0
  93. package/dist/core/{imports.d.ts → semantic/imports.d.ts} +1 -5
  94. package/dist/core/semantic/imports.d.ts.map +1 -0
  95. package/dist/core/{imports.js → semantic/imports.js} +56 -74
  96. package/dist/core/semantic/imports.js.map +1 -0
  97. package/dist/core/semantic/imports.test.d.ts.map +1 -0
  98. package/dist/core/semantic/imports.test.js +229 -0
  99. package/dist/core/semantic/imports.test.js.map +1 -0
  100. package/dist/core/semantic/index.d.ts +15 -0
  101. package/dist/core/semantic/index.d.ts.map +1 -0
  102. package/dist/core/semantic/index.js +15 -0
  103. package/dist/core/semantic/index.js.map +1 -0
  104. package/dist/core/{local-types.d.ts → semantic/local-types.d.ts} +1 -1
  105. package/dist/core/semantic/local-types.d.ts.map +1 -0
  106. package/dist/core/semantic/local-types.js.map +1 -0
  107. package/dist/core/{module-map.d.ts → semantic/module-map.d.ts} +1 -1
  108. package/dist/core/semantic/module-map.d.ts.map +1 -0
  109. package/dist/core/semantic/module-map.js.map +1 -0
  110. package/dist/core/semantic/module-map.test.d.ts.map +1 -0
  111. package/dist/core/semantic/module-map.test.js.map +1 -0
  112. package/dist/core/semantic/naming-collisions.d.ts.map +1 -0
  113. package/dist/core/{naming-collisions.js → semantic/naming-collisions.js} +1 -1
  114. package/dist/core/semantic/naming-collisions.js.map +1 -0
  115. package/dist/core/{type-alias-index.d.ts → semantic/type-alias-index.d.ts} +1 -1
  116. package/dist/core/semantic/type-alias-index.d.ts.map +1 -0
  117. package/dist/core/semantic/type-alias-index.js.map +1 -0
  118. package/dist/core/semantic/type-compatibility.d.ts.map +1 -0
  119. package/dist/core/semantic/type-compatibility.js.map +1 -0
  120. package/dist/core/{type-member-index.d.ts → semantic/type-member-index.d.ts} +1 -1
  121. package/dist/core/semantic/type-member-index.d.ts.map +1 -0
  122. package/dist/core/semantic/type-member-index.js.map +1 -0
  123. package/dist/core/semantic/type-params.d.ts.map +1 -0
  124. package/dist/core/semantic/type-params.js.map +1 -0
  125. package/dist/core/{type-resolution.d.ts → semantic/type-resolution.d.ts} +3 -6
  126. package/dist/core/semantic/type-resolution.d.ts.map +1 -0
  127. package/dist/core/{type-resolution.js → semantic/type-resolution.js} +15 -25
  128. package/dist/core/semantic/type-resolution.js.map +1 -0
  129. package/dist/core/semantic/type-resolution.test.d.ts.map +1 -0
  130. package/dist/core/{type-resolution.test.js → semantic/type-resolution.test.js} +11 -19
  131. package/dist/core/semantic/type-resolution.test.js.map +1 -0
  132. package/dist/core/semantic/unsafe.d.ts.map +1 -0
  133. package/dist/core/semantic/unsafe.js.map +1 -0
  134. package/dist/emitter-types/core.d.ts +6 -12
  135. package/dist/emitter-types/core.d.ts.map +1 -1
  136. package/dist/emitter-types/index.d.ts +1 -1
  137. package/dist/emitter-types/index.d.ts.map +1 -1
  138. package/dist/emitter-types/index.js.map +1 -1
  139. package/dist/emitter.d.ts +1 -1
  140. package/dist/emitter.d.ts.map +1 -1
  141. package/dist/emitter.js +9 -8
  142. package/dist/emitter.js.map +1 -1
  143. package/dist/expression-emitter.d.ts +10 -5
  144. package/dist/expression-emitter.d.ts.map +1 -1
  145. package/dist/expression-emitter.js +333 -117
  146. package/dist/expression-emitter.js.map +1 -1
  147. package/dist/expressions/access.d.ts +4 -3
  148. package/dist/expressions/access.d.ts.map +1 -1
  149. package/dist/expressions/access.js +252 -102
  150. package/dist/expressions/access.js.map +1 -1
  151. package/dist/expressions/calls/call-analysis.d.ts +86 -0
  152. package/dist/expressions/calls/call-analysis.d.ts.map +1 -0
  153. package/dist/expressions/calls/call-analysis.js +284 -0
  154. package/dist/expressions/calls/call-analysis.js.map +1 -0
  155. package/dist/expressions/calls/call-emitter.d.ts +13 -0
  156. package/dist/expressions/calls/call-emitter.d.ts.map +1 -0
  157. package/dist/expressions/calls/call-emitter.js +1048 -0
  158. package/dist/expressions/calls/call-emitter.js.map +1 -0
  159. package/dist/expressions/calls/new-emitter.d.ts +13 -0
  160. package/dist/expressions/calls/new-emitter.d.ts.map +1 -0
  161. package/dist/expressions/calls/new-emitter.js +641 -0
  162. package/dist/expressions/calls/new-emitter.js.map +1 -0
  163. package/dist/expressions/calls.d.ts +2 -14
  164. package/dist/expressions/calls.d.ts.map +1 -1
  165. package/dist/expressions/calls.js +2 -909
  166. package/dist/expressions/calls.js.map +1 -1
  167. package/dist/expressions/collections.d.ts +6 -16
  168. package/dist/expressions/collections.d.ts.map +1 -1
  169. package/dist/expressions/collections.js +318 -217
  170. package/dist/expressions/collections.js.map +1 -1
  171. package/dist/expressions/functions.d.ts +6 -5
  172. package/dist/expressions/functions.d.ts.map +1 -1
  173. package/dist/expressions/functions.js +57 -62
  174. package/dist/expressions/functions.js.map +1 -1
  175. package/dist/expressions/identifiers.d.ts +11 -6
  176. package/dist/expressions/identifiers.d.ts.map +1 -1
  177. package/dist/expressions/identifiers.js +76 -25
  178. package/dist/expressions/identifiers.js.map +1 -1
  179. package/dist/expressions/index.d.ts +1 -1
  180. package/dist/expressions/index.d.ts.map +1 -1
  181. package/dist/expressions/index.js +1 -1
  182. package/dist/expressions/index.js.map +1 -1
  183. package/dist/expressions/index.test.js +605 -0
  184. package/dist/expressions/index.test.js.map +1 -1
  185. package/dist/expressions/literals.d.ts +4 -3
  186. package/dist/expressions/literals.d.ts.map +1 -1
  187. package/dist/expressions/literals.js +25 -17
  188. package/dist/expressions/literals.js.map +1 -1
  189. package/dist/expressions/literals.test.js +18 -18
  190. package/dist/expressions/literals.test.js.map +1 -1
  191. package/dist/expressions/operators/assignment-emitter.d.ts +16 -0
  192. package/dist/expressions/operators/assignment-emitter.d.ts.map +1 -0
  193. package/dist/expressions/operators/assignment-emitter.js +118 -0
  194. package/dist/expressions/operators/assignment-emitter.js.map +1 -0
  195. package/dist/expressions/operators/binary-emitter.d.ts +33 -0
  196. package/dist/expressions/operators/binary-emitter.d.ts.map +1 -0
  197. package/dist/expressions/operators/binary-emitter.js +398 -0
  198. package/dist/expressions/operators/binary-emitter.js.map +1 -0
  199. package/dist/expressions/operators/conditional-emitter.d.ts +17 -0
  200. package/dist/expressions/operators/conditional-emitter.d.ts.map +1 -0
  201. package/dist/expressions/operators/conditional-emitter.js +306 -0
  202. package/dist/expressions/operators/conditional-emitter.js.map +1 -0
  203. package/dist/expressions/operators/helpers.d.ts +37 -0
  204. package/dist/expressions/operators/helpers.d.ts.map +1 -0
  205. package/dist/expressions/operators/helpers.js +136 -0
  206. package/dist/expressions/operators/helpers.js.map +1 -0
  207. package/dist/expressions/operators/logical-emitter.d.ts +23 -0
  208. package/dist/expressions/operators/logical-emitter.d.ts.map +1 -0
  209. package/dist/expressions/operators/logical-emitter.js +73 -0
  210. package/dist/expressions/operators/logical-emitter.js.map +1 -0
  211. package/dist/expressions/operators/unary-emitter.d.ts +30 -0
  212. package/dist/expressions/operators/unary-emitter.d.ts.map +1 -0
  213. package/dist/expressions/operators/unary-emitter.js +244 -0
  214. package/dist/expressions/operators/unary-emitter.js.map +1 -0
  215. package/dist/expressions/operators.d.ts +5 -81
  216. package/dist/expressions/operators.d.ts.map +1 -1
  217. package/dist/expressions/operators.js +5 -949
  218. package/dist/expressions/operators.js.map +1 -1
  219. package/dist/expressions/other.d.ts +15 -11
  220. package/dist/expressions/other.d.ts.map +1 -1
  221. package/dist/expressions/other.js +51 -36
  222. package/dist/expressions/other.js.map +1 -1
  223. package/dist/expressions/precedence.test.js +1 -1
  224. package/dist/expressions/precedence.test.js.map +1 -1
  225. package/dist/generator-exchange.d.ts +10 -3
  226. package/dist/generator-exchange.d.ts.map +1 -1
  227. package/dist/generator-exchange.js +57 -54
  228. package/dist/generator-exchange.js.map +1 -1
  229. package/dist/generator-wrapper.d.ts +17 -65
  230. package/dist/generator-wrapper.d.ts.map +1 -1
  231. package/dist/generator-wrapper.js +396 -220
  232. package/dist/generator-wrapper.js.map +1 -1
  233. package/dist/generator-wrapper.test.js +22 -14
  234. package/dist/generator-wrapper.test.js.map +1 -1
  235. package/dist/integration.test.js +169 -1
  236. package/dist/integration.test.js.map +1 -1
  237. package/dist/patterns.d.ts +18 -88
  238. package/dist/patterns.d.ts.map +1 -1
  239. package/dist/patterns.js +540 -304
  240. package/dist/patterns.js.map +1 -1
  241. package/dist/patterns.test.js +5 -4
  242. package/dist/patterns.test.js.map +1 -1
  243. package/dist/specialization/generation.d.ts +7 -3
  244. package/dist/specialization/generation.d.ts.map +1 -1
  245. package/dist/specialization/generation.js +31 -15
  246. package/dist/specialization/generation.js.map +1 -1
  247. package/dist/specialization/type-aliases.test.js +47 -2
  248. package/dist/specialization/type-aliases.test.js.map +1 -1
  249. package/dist/statement-emitter.d.ts +15 -4
  250. package/dist/statement-emitter.d.ts.map +1 -1
  251. package/dist/statement-emitter.js +54 -47
  252. package/dist/statement-emitter.js.map +1 -1
  253. package/dist/statements/blocks.d.ts +24 -16
  254. package/dist/statements/blocks.d.ts.map +1 -1
  255. package/dist/statements/blocks.js +242 -65
  256. package/dist/statements/blocks.js.map +1 -1
  257. package/dist/statements/classes/index.d.ts +1 -1
  258. package/dist/statements/classes/index.d.ts.map +1 -1
  259. package/dist/statements/classes/index.js +1 -1
  260. package/dist/statements/classes/index.js.map +1 -1
  261. package/dist/statements/classes/inline-types.d.ts +4 -3
  262. package/dist/statements/classes/inline-types.d.ts.map +1 -1
  263. package/dist/statements/classes/inline-types.js +21 -21
  264. package/dist/statements/classes/inline-types.js.map +1 -1
  265. package/dist/statements/classes/members/constructors.d.ts +4 -3
  266. package/dist/statements/classes/members/constructors.d.ts.map +1 -1
  267. package/dist/statements/classes/members/constructors.js +57 -58
  268. package/dist/statements/classes/members/constructors.js.map +1 -1
  269. package/dist/statements/classes/members/methods.d.ts +4 -3
  270. package/dist/statements/classes/members/methods.d.ts.map +1 -1
  271. package/dist/statements/classes/members/methods.js +106 -101
  272. package/dist/statements/classes/members/methods.js.map +1 -1
  273. package/dist/statements/classes/members/orchestrator.d.ts +4 -3
  274. package/dist/statements/classes/members/orchestrator.d.ts.map +1 -1
  275. package/dist/statements/classes/members/orchestrator.js +2 -2
  276. package/dist/statements/classes/members/orchestrator.js.map +1 -1
  277. package/dist/statements/classes/members/properties.d.ts +4 -3
  278. package/dist/statements/classes/members/properties.d.ts.map +1 -1
  279. package/dist/statements/classes/members/properties.js +105 -88
  280. package/dist/statements/classes/members/properties.js.map +1 -1
  281. package/dist/statements/classes/members/shadowing.test.js +7 -2
  282. package/dist/statements/classes/members/shadowing.test.js.map +1 -1
  283. package/dist/statements/classes/members/static-readonly-properties.test.js +4 -1
  284. package/dist/statements/classes/members/static-readonly-properties.test.js.map +1 -1
  285. package/dist/statements/classes/parameters.d.ts +8 -10
  286. package/dist/statements/classes/parameters.d.ts.map +1 -1
  287. package/dist/statements/classes/parameters.js +30 -26
  288. package/dist/statements/classes/parameters.js.map +1 -1
  289. package/dist/statements/classes/properties.d.ts +4 -3
  290. package/dist/statements/classes/properties.d.ts.map +1 -1
  291. package/dist/statements/classes/properties.js +76 -50
  292. package/dist/statements/classes/properties.js.map +1 -1
  293. package/dist/statements/classes.d.ts +1 -1
  294. package/dist/statements/classes.d.ts.map +1 -1
  295. package/dist/statements/classes.js +1 -1
  296. package/dist/statements/classes.js.map +1 -1
  297. package/dist/statements/control/conditionals/guard-analysis.d.ts +169 -0
  298. package/dist/statements/control/conditionals/guard-analysis.d.ts.map +1 -0
  299. package/dist/statements/control/conditionals/guard-analysis.js +591 -0
  300. package/dist/statements/control/conditionals/guard-analysis.js.map +1 -0
  301. package/dist/statements/control/conditionals/if-emitter.d.ts +14 -0
  302. package/dist/statements/control/conditionals/if-emitter.d.ts.map +1 -0
  303. package/dist/statements/control/conditionals/if-emitter.js +725 -0
  304. package/dist/statements/control/conditionals/if-emitter.js.map +1 -0
  305. package/dist/statements/control/conditionals/switch-emitter.d.ts +13 -0
  306. package/dist/statements/control/conditionals/switch-emitter.d.ts.map +1 -0
  307. package/dist/statements/control/conditionals/switch-emitter.js +60 -0
  308. package/dist/statements/control/conditionals/switch-emitter.js.map +1 -0
  309. package/dist/statements/control/conditionals.d.ts +3 -15
  310. package/dist/statements/control/conditionals.d.ts.map +1 -1
  311. package/dist/statements/control/conditionals.js +3 -1152
  312. package/dist/statements/control/conditionals.js.map +1 -1
  313. package/dist/statements/control/exceptions.d.ts +8 -6
  314. package/dist/statements/control/exceptions.d.ts.map +1 -1
  315. package/dist/statements/control/exceptions.js +35 -23
  316. package/dist/statements/control/exceptions.js.map +1 -1
  317. package/dist/statements/control/index.d.ts +3 -3
  318. package/dist/statements/control/index.d.ts.map +1 -1
  319. package/dist/statements/control/index.js +3 -3
  320. package/dist/statements/control/index.js.map +1 -1
  321. package/dist/statements/control/loops.d.ts +14 -12
  322. package/dist/statements/control/loops.d.ts.map +1 -1
  323. package/dist/statements/control/loops.js +147 -82
  324. package/dist/statements/control/loops.js.map +1 -1
  325. package/dist/statements/control.d.ts +1 -1
  326. package/dist/statements/control.d.ts.map +1 -1
  327. package/dist/statements/control.js +1 -1
  328. package/dist/statements/control.js.map +1 -1
  329. package/dist/statements/declarations/classes.d.ts +7 -3
  330. package/dist/statements/declarations/classes.d.ts.map +1 -1
  331. package/dist/statements/declarations/classes.js +107 -83
  332. package/dist/statements/declarations/classes.js.map +1 -1
  333. package/dist/statements/declarations/enums.d.ts +4 -3
  334. package/dist/statements/declarations/enums.d.ts.map +1 -1
  335. package/dist/statements/declarations/enums.js +16 -15
  336. package/dist/statements/declarations/enums.js.map +1 -1
  337. package/dist/statements/declarations/functions.d.ts +18 -2
  338. package/dist/statements/declarations/functions.d.ts.map +1 -1
  339. package/dist/statements/declarations/functions.js +633 -162
  340. package/dist/statements/declarations/functions.js.map +1 -1
  341. package/dist/statements/declarations/index.d.ts +2 -2
  342. package/dist/statements/declarations/index.d.ts.map +1 -1
  343. package/dist/statements/declarations/index.js +2 -2
  344. package/dist/statements/declarations/index.js.map +1 -1
  345. package/dist/statements/declarations/interfaces.d.ts +7 -3
  346. package/dist/statements/declarations/interfaces.d.ts.map +1 -1
  347. package/dist/statements/declarations/interfaces.js +138 -105
  348. package/dist/statements/declarations/interfaces.js.map +1 -1
  349. package/dist/statements/declarations/type-aliases.d.ts +7 -3
  350. package/dist/statements/declarations/type-aliases.d.ts.map +1 -1
  351. package/dist/statements/declarations/type-aliases.js +122 -82
  352. package/dist/statements/declarations/type-aliases.js.map +1 -1
  353. package/dist/statements/declarations/variables.d.ts +12 -2
  354. package/dist/statements/declarations/variables.d.ts.map +1 -1
  355. package/dist/statements/declarations/variables.js +541 -428
  356. package/dist/statements/declarations/variables.js.map +1 -1
  357. package/dist/statements/declarations.d.ts +1 -1
  358. package/dist/statements/declarations.d.ts.map +1 -1
  359. package/dist/statements/declarations.js +1 -1
  360. package/dist/statements/declarations.js.map +1 -1
  361. package/dist/statements/index.d.ts +3 -3
  362. package/dist/statements/index.d.ts.map +1 -1
  363. package/dist/statements/index.js +5 -5
  364. package/dist/statements/index.js.map +1 -1
  365. package/dist/statements/index.test.js +307 -0
  366. package/dist/statements/index.test.js.map +1 -1
  367. package/dist/type-emitter.d.ts +1 -1
  368. package/dist/type-emitter.d.ts.map +1 -1
  369. package/dist/type-emitter.js +1 -1
  370. package/dist/type-emitter.js.map +1 -1
  371. package/dist/types/arrays.d.ts +3 -2
  372. package/dist/types/arrays.d.ts.map +1 -1
  373. package/dist/types/arrays.js +7 -5
  374. package/dist/types/arrays.js.map +1 -1
  375. package/dist/types/dictionaries.d.ts +6 -3
  376. package/dist/types/dictionaries.d.ts.map +1 -1
  377. package/dist/types/dictionaries.js +22 -10
  378. package/dist/types/dictionaries.js.map +1 -1
  379. package/dist/types/emitter.d.ts +8 -2
  380. package/dist/types/emitter.d.ts.map +1 -1
  381. package/dist/types/emitter.js +20 -6
  382. package/dist/types/emitter.js.map +1 -1
  383. package/dist/types/functions.d.ts +3 -2
  384. package/dist/types/functions.d.ts.map +1 -1
  385. package/dist/types/functions.js +36 -13
  386. package/dist/types/functions.js.map +1 -1
  387. package/dist/types/index.d.ts +2 -2
  388. package/dist/types/index.d.ts.map +1 -1
  389. package/dist/types/index.js +2 -2
  390. package/dist/types/index.js.map +1 -1
  391. package/dist/types/index.test.js +137 -0
  392. package/dist/types/index.test.js.map +1 -1
  393. package/dist/types/intersections.d.ts +3 -2
  394. package/dist/types/intersections.d.ts.map +1 -1
  395. package/dist/types/intersections.js +2 -2
  396. package/dist/types/intersections.js.map +1 -1
  397. package/dist/types/literals.d.ts +9 -2
  398. package/dist/types/literals.d.ts.map +1 -1
  399. package/dist/types/literals.js +11 -5
  400. package/dist/types/literals.js.map +1 -1
  401. package/dist/types/objects.d.ts +3 -2
  402. package/dist/types/objects.d.ts.map +1 -1
  403. package/dist/types/objects.js +1 -1
  404. package/dist/types/objects.js.map +1 -1
  405. package/dist/types/parameters.d.ts +6 -5
  406. package/dist/types/parameters.d.ts.map +1 -1
  407. package/dist/types/parameters.js +88 -29
  408. package/dist/types/parameters.js.map +1 -1
  409. package/dist/types/parameters.test.js +9 -4
  410. package/dist/types/parameters.test.js.map +1 -1
  411. package/dist/types/primitives.d.ts +5 -4
  412. package/dist/types/primitives.d.ts.map +1 -1
  413. package/dist/types/primitives.js +14 -13
  414. package/dist/types/primitives.js.map +1 -1
  415. package/dist/types/references.d.ts +3 -2
  416. package/dist/types/references.d.ts.map +1 -1
  417. package/dist/types/references.js +135 -111
  418. package/dist/types/references.js.map +1 -1
  419. package/dist/types/tuples.d.ts +3 -2
  420. package/dist/types/tuples.d.ts.map +1 -1
  421. package/dist/types/tuples.js +25 -11
  422. package/dist/types/tuples.js.map +1 -1
  423. package/dist/types/unions.d.ts +3 -2
  424. package/dist/types/unions.d.ts.map +1 -1
  425. package/dist/types/unions.js +36 -21
  426. package/dist/types/unions.js.map +1 -1
  427. package/dist/types.d.ts +1 -1
  428. package/dist/types.d.ts.map +1 -1
  429. package/dist/types.js.map +1 -1
  430. package/package.json +2 -2
  431. package/dist/core/attributes.d.ts.map +0 -1
  432. package/dist/core/attributes.js +0 -141
  433. package/dist/core/attributes.js.map +0 -1
  434. package/dist/core/attributes.test.d.ts.map +0 -1
  435. package/dist/core/attributes.test.js.map +0 -1
  436. package/dist/core/boolean-context.d.ts +0 -42
  437. package/dist/core/boolean-context.d.ts.map +0 -1
  438. package/dist/core/boolean-context.js +0 -442
  439. package/dist/core/boolean-context.js.map +0 -1
  440. package/dist/core/boolean-context.test.d.ts.map +0 -1
  441. package/dist/core/boolean-context.test.js.map +0 -1
  442. package/dist/core/exports.d.ts.map +0 -1
  443. package/dist/core/exports.js +0 -28
  444. package/dist/core/exports.js.map +0 -1
  445. package/dist/core/imports.d.ts.map +0 -1
  446. package/dist/core/imports.js.map +0 -1
  447. package/dist/core/imports.test.d.ts.map +0 -1
  448. package/dist/core/imports.test.js +0 -79
  449. package/dist/core/imports.test.js.map +0 -1
  450. package/dist/core/local-names.d.ts.map +0 -1
  451. package/dist/core/local-names.js.map +0 -1
  452. package/dist/core/local-types.d.ts.map +0 -1
  453. package/dist/core/local-types.js.map +0 -1
  454. package/dist/core/module-emitter/assembly.d.ts +0 -24
  455. package/dist/core/module-emitter/assembly.d.ts.map +0 -1
  456. package/dist/core/module-emitter/assembly.js +0 -69
  457. package/dist/core/module-emitter/assembly.js.map +0 -1
  458. package/dist/core/module-emitter/header.d.ts.map +0 -1
  459. package/dist/core/module-emitter/header.js.map +0 -1
  460. package/dist/core/module-emitter/index.d.ts.map +0 -1
  461. package/dist/core/module-emitter/index.js.map +0 -1
  462. package/dist/core/module-emitter/namespace.d.ts +0 -14
  463. package/dist/core/module-emitter/namespace.d.ts.map +0 -1
  464. package/dist/core/module-emitter/namespace.js +0 -26
  465. package/dist/core/module-emitter/namespace.js.map +0 -1
  466. package/dist/core/module-emitter/orchestrator.d.ts.map +0 -1
  467. package/dist/core/module-emitter/orchestrator.js.map +0 -1
  468. package/dist/core/module-emitter/separation.d.ts.map +0 -1
  469. package/dist/core/module-emitter/separation.js.map +0 -1
  470. package/dist/core/module-emitter/static-container.d.ts.map +0 -1
  471. package/dist/core/module-emitter/static-container.js +0 -139
  472. package/dist/core/module-emitter/static-container.js.map +0 -1
  473. package/dist/core/module-emitter.d.ts.map +0 -1
  474. package/dist/core/module-emitter.js.map +0 -1
  475. package/dist/core/module-map.d.ts.map +0 -1
  476. package/dist/core/module-map.js.map +0 -1
  477. package/dist/core/module-map.test.d.ts.map +0 -1
  478. package/dist/core/module-map.test.js.map +0 -1
  479. package/dist/core/naming-collisions.d.ts.map +0 -1
  480. package/dist/core/naming-collisions.js.map +0 -1
  481. package/dist/core/options.d.ts.map +0 -1
  482. package/dist/core/options.js.map +0 -1
  483. package/dist/core/type-alias-index.d.ts.map +0 -1
  484. package/dist/core/type-alias-index.js.map +0 -1
  485. package/dist/core/type-compatibility.d.ts.map +0 -1
  486. package/dist/core/type-compatibility.js.map +0 -1
  487. package/dist/core/type-member-index.d.ts.map +0 -1
  488. package/dist/core/type-member-index.js.map +0 -1
  489. package/dist/core/type-params.d.ts.map +0 -1
  490. package/dist/core/type-params.js.map +0 -1
  491. package/dist/core/type-resolution.d.ts.map +0 -1
  492. package/dist/core/type-resolution.js.map +0 -1
  493. package/dist/core/type-resolution.test.d.ts.map +0 -1
  494. package/dist/core/type-resolution.test.js.map +0 -1
  495. package/dist/core/unsafe.d.ts.map +0 -1
  496. package/dist/core/unsafe.js.map +0 -1
  497. /package/dist/core/{attributes.test.d.ts → format/attributes.test.d.ts} +0 -0
  498. /package/dist/core/{module-emitter → format/module-emitter}/index.d.ts +0 -0
  499. /package/dist/core/{module-emitter → format/module-emitter}/index.js +0 -0
  500. /package/dist/core/{module-emitter → format/module-emitter}/separation.d.ts +0 -0
  501. /package/dist/core/{module-emitter → format/module-emitter}/separation.js +0 -0
  502. /package/dist/core/{module-emitter.d.ts → format/module-emitter.d.ts} +0 -0
  503. /package/dist/core/{module-emitter.js → format/module-emitter.js} +0 -0
  504. /package/dist/core/{options.js → format/options.js} +0 -0
  505. /package/dist/core/{boolean-context.test.d.ts → semantic/boolean-context.test.d.ts} +0 -0
  506. /package/dist/core/{imports.test.d.ts → semantic/imports.test.d.ts} +0 -0
  507. /package/dist/core/{local-types.js → semantic/local-types.js} +0 -0
  508. /package/dist/core/{module-map.js → semantic/module-map.js} +0 -0
  509. /package/dist/core/{module-map.test.d.ts → semantic/module-map.test.d.ts} +0 -0
  510. /package/dist/core/{module-map.test.js → semantic/module-map.test.js} +0 -0
  511. /package/dist/core/{naming-collisions.d.ts → semantic/naming-collisions.d.ts} +0 -0
  512. /package/dist/core/{type-alias-index.js → semantic/type-alias-index.js} +0 -0
  513. /package/dist/core/{type-compatibility.d.ts → semantic/type-compatibility.d.ts} +0 -0
  514. /package/dist/core/{type-compatibility.js → semantic/type-compatibility.js} +0 -0
  515. /package/dist/core/{type-member-index.js → semantic/type-member-index.js} +0 -0
  516. /package/dist/core/{type-params.d.ts → semantic/type-params.d.ts} +0 -0
  517. /package/dist/core/{type-params.js → semantic/type-params.js} +0 -0
  518. /package/dist/core/{type-resolution.test.d.ts → semantic/type-resolution.test.d.ts} +0 -0
  519. /package/dist/core/{unsafe.d.ts → semantic/unsafe.d.ts} +0 -0
  520. /package/dist/core/{unsafe.js → semantic/unsafe.js} +0 -0
@@ -6,953 +6,9 @@
6
6
  * - Integer casts only from IrCastExpression (not inferred from expectedType)
7
7
  * - Binary ops: int op int = int, double op anything = double (C# semantics)
8
8
  */
9
- import { emitExpression } from "../expression-emitter.js";
10
- import { emitType } from "../type-emitter.js";
11
- import { resolveTypeAlias, stripNullish, findUnionMemberIndex, getPropertyType, getAllPropertySignatures, isDefinitelyValueType, } from "../core/type-resolution.js";
12
- import { emitBooleanCondition } from "../core/boolean-context.js";
13
- import { emitRemappedLocalName } from "../core/local-names.js";
14
- import { lowerAssignmentPattern } from "../patterns.js";
15
- /**
16
- * Check if an expression has proven Int32 type from the numeric proof pass.
17
- * Mirrors the same check in access.ts for consistency.
18
- */
19
- const hasInt32Proof = (expr) => {
20
- if (expr.inferredType?.kind === "primitiveType" &&
21
- expr.inferredType.name === "int") {
22
- return true;
23
- }
24
- if (expr.inferredType?.kind === "referenceType" &&
25
- expr.inferredType.name === "int") {
26
- return true;
27
- }
28
- return false;
29
- };
30
- /**
31
- * Get operator precedence for proper parenthesization
32
- */
33
- const getPrecedence = (operator) => {
34
- const precedences = {
35
- "||": 5,
36
- // C# precedence: `??` binds less tightly than `||` / `&&` but more tightly than `?:`.
37
- "??": 4,
38
- "&&": 6,
39
- "|": 7,
40
- "^": 8,
41
- "&": 9,
42
- "==": 10,
43
- "!=": 10,
44
- "===": 10,
45
- "!==": 10,
46
- "<": 11,
47
- ">": 11,
48
- "<=": 11,
49
- ">=": 11,
50
- instanceof: 11,
51
- in: 11,
52
- "<<": 12,
53
- ">>": 12,
54
- ">>>": 12,
55
- "+": 13,
56
- "-": 13,
57
- "*": 14,
58
- "/": 14,
59
- "%": 14,
60
- "**": 15,
61
- };
62
- return precedences[operator] ?? 16;
63
- };
64
- /**
65
- * Check if an expression has char type (either from string indexer or a variable typed as char).
66
- * In C#, string[int] returns char, not string like in TypeScript.
67
- * The IR now correctly sets inferredType to char for string indexer access.
68
- */
69
- const isCharTyped = (expr) => {
70
- return ((expr.inferredType?.kind === "primitiveType" &&
71
- expr.inferredType.name === "char") ||
72
- (expr.inferredType?.kind === "referenceType" &&
73
- expr.inferredType.name === "char"));
74
- };
75
- const stripNullishFromType = (type) => {
76
- if (!type)
77
- return undefined;
78
- if (type.kind !== "unionType")
79
- return type;
80
- const nonNullish = type.types.filter((t) => !(t.kind === "primitiveType" &&
81
- (t.name === "null" || t.name === "undefined")));
82
- if (nonNullish.length === 1) {
83
- const only = nonNullish[0];
84
- return only ? stripNullishFromType(only) : undefined;
85
- }
86
- return type;
87
- };
88
- const isStringTyped = (expr) => {
89
- const type = stripNullishFromType(expr.inferredType);
90
- if (!type)
91
- return false;
92
- if (type.kind === "primitiveType")
93
- return type.name === "string";
94
- if (type.kind === "referenceType")
95
- return type.name === "string";
96
- if (type.kind === "intersectionType") {
97
- return type.types.some((part) => (part.kind === "primitiveType" && part.name === "string") ||
98
- (part.kind === "referenceType" && part.name === "string"));
99
- }
100
- return false;
101
- };
102
- /**
103
- * Check if an expression is a single-character string literal.
104
- * Returns the character if so, undefined otherwise.
105
- */
106
- const getSingleCharLiteral = (expr) => {
107
- if (expr.kind !== "literal")
108
- return undefined;
109
- if (typeof expr.value !== "string")
110
- return undefined;
111
- if (expr.value.length !== 1)
112
- return undefined;
113
- return expr.value;
114
- };
115
- /**
116
- * Escape a character for use in a C# char literal.
117
- * Handles special characters like quotes, backslash, newline, etc.
118
- */
119
- const escapeCharLiteral = (char) => {
120
- switch (char) {
121
- case "'":
122
- return "\\'";
123
- case "\\":
124
- return "\\\\";
125
- case "\n":
126
- return "\\n";
127
- case "\r":
128
- return "\\r";
129
- case "\t":
130
- return "\\t";
131
- case "\0":
132
- return "\\0";
133
- default:
134
- return char;
135
- }
136
- };
137
- /**
138
- * Emit a binary operator expression
139
- *
140
- * NEW NUMERIC SPEC: No contextual type propagation for numeric literals.
141
- * Literals use their raw lexeme - C# will naturally handle int + int = int,
142
- * int + double = double, etc.
143
- *
144
- * Explicit casts come from IrCastExpression nodes (generated by type-checker
145
- * when user intent allows int → double coercion).
146
- *
147
- * STRING INDEXER FIX: In C#, string[int] returns char, not string.
148
- * When comparing a string indexer result with a single-character string literal,
149
- * we emit the string as a char literal to avoid CS0019 (char == string).
150
- *
151
- * @param expr - The binary expression
152
- * @param context - Emitter context
153
- * @param _expectedType - Unused under new spec (kept for API compatibility)
154
- */
155
- export const emitBinary = (expr, context, _expectedType) => {
156
- // Map JavaScript operators to C# operators
157
- const operatorMap = {
158
- "===": "==",
159
- "!==": "!=",
160
- "==": "==", // Loose equality - needs special handling
161
- "!=": "!=", // Loose inequality - needs special handling
162
- instanceof: "is",
163
- in: "/* in */", // Needs special handling
164
- };
165
- const op = operatorMap[expr.operator] ?? expr.operator;
166
- const parentPrecedence = getPrecedence(expr.operator);
167
- // Handle `"prop" in x` (union narrowing / dictionary membership)
168
- if (expr.operator === "in") {
169
- // LHS must be a string literal for deterministic lowering.
170
- if (expr.left.kind !== "literal" || typeof expr.left.value !== "string") {
171
- throw new Error("ICE: Unsupported `in` operator form. Left-hand side must be a string literal.");
172
- }
173
- const rhsType = expr.right.inferredType;
174
- if (!rhsType) {
175
- throw new Error("ICE: `in` operator RHS missing inferredType.");
176
- }
177
- const [rhsFrag, rhsCtx] = emitExpression(expr.right, context);
178
- const rhsText = rhsFrag.text;
179
- const resolvedRhs = resolveTypeAlias(stripNullish(rhsType), rhsCtx);
180
- // Union<T1..Tn>: `"error" in auth` → auth.IsN() (where member N has the prop)
181
- if (resolvedRhs.kind === "unionType") {
182
- const propName = expr.left.value;
183
- const matchingMembers = [];
184
- for (let i = 0; i < resolvedRhs.types.length; i++) {
185
- const member = resolvedRhs.types[i];
186
- if (!member || member.kind !== "referenceType")
187
- continue;
188
- const localInfo = rhsCtx.localTypes?.get(member.name);
189
- if (localInfo?.kind === "interface") {
190
- const props = getAllPropertySignatures(member, rhsCtx);
191
- if (props?.some((p) => p.name === propName)) {
192
- matchingMembers.push(i + 1);
193
- }
194
- continue;
195
- }
196
- if (localInfo?.kind === "class") {
197
- if (localInfo.members.some((m) => (m.kind === "propertyDeclaration" ||
198
- m.kind === "methodDeclaration") &&
199
- m.name === propName)) {
200
- matchingMembers.push(i + 1);
201
- }
202
- continue;
203
- }
204
- // Cross-module union members: consult the batch type-member index.
205
- // This enables `"prop" in x` narrowing even when the union member types
206
- // are declared in a different TS module.
207
- const candidates = [];
208
- const stripGlobalPrefix = (name) => name.startsWith("global::") ? name.slice("global::".length) : name;
209
- if (member.resolvedClrType) {
210
- candidates.push(stripGlobalPrefix(member.resolvedClrType));
211
- }
212
- if (member.name.includes(".")) {
213
- candidates.push(member.name);
214
- }
215
- if (!member.name.includes(".") && rhsCtx.options.typeMemberIndex) {
216
- const matches = [];
217
- for (const fqn of rhsCtx.options.typeMemberIndex.keys()) {
218
- if (fqn.endsWith(`.${member.name}`) ||
219
- fqn.endsWith(`.${member.name}__Alias`)) {
220
- matches.push(fqn);
221
- }
222
- }
223
- if (matches.length === 1) {
224
- candidates.push(matches[0]);
225
- }
226
- else if (matches.length > 1) {
227
- const list = matches.sort().join(", ");
228
- throw new Error(`ICE: Ambiguous union member type '${member.name}' for \`in\` narrowing. Candidates: ${list}`);
229
- }
230
- }
231
- // Single-file fallback (no batch indexes): assume same namespace.
232
- if (rhsCtx.moduleNamespace) {
233
- candidates.push(`${rhsCtx.moduleNamespace}.${member.name}`);
234
- candidates.push(`${rhsCtx.moduleNamespace}.${member.name}__Alias`);
235
- }
236
- const hasMember = candidates.some((fqn) => {
237
- const perType = rhsCtx.options.typeMemberIndex?.get(fqn);
238
- return perType?.has(propName) ?? false;
239
- });
240
- if (hasMember) {
241
- matchingMembers.push(i + 1);
242
- }
243
- }
244
- if (matchingMembers.length === 0) {
245
- return [{ text: "false", precedence: parentPrecedence }, rhsCtx];
246
- }
247
- const checks = matchingMembers
248
- .map((n) => `${rhsText}.Is${n}()`)
249
- .join(" || ");
250
- // Lowering emits an `||` chain; wrap to preserve grouping in any surrounding expression.
251
- return [{ text: `(${checks})`, precedence: 16 }, rhsCtx];
252
- }
253
- // Dictionary<K,V>: `"k" in dict` → dict.ContainsKey("k")
254
- if (resolvedRhs.kind === "dictionaryType") {
255
- const keyType = stripNullish(resolvedRhs.keyType);
256
- const isStringKey = (keyType.kind === "primitiveType" && keyType.name === "string") ||
257
- (keyType.kind === "referenceType" && keyType.name === "string");
258
- if (!isStringKey) {
259
- throw new Error("ICE: Unsupported `in` operator on dictionary with non-string keys.");
260
- }
261
- const [keyFrag, keyCtx] = emitExpression(expr.left, rhsCtx);
262
- const text = `${rhsText}.ContainsKey(${keyFrag.text})`;
263
- return [{ text, precedence: parentPrecedence }, keyCtx];
264
- }
265
- throw new Error("ICE: Unsupported `in` operator. Only union shape guards and Dictionary<string, T> membership are supported.");
266
- }
267
- // Handle instanceof operator specially
268
- if (expr.operator === "instanceof") {
269
- const [leftFrag, leftContext] = emitExpression(expr.left, context);
270
- const [rightFrag, rightContext] = emitExpression(expr.right, leftContext);
271
- const text = `${leftFrag.text} is ${rightFrag.text}`;
272
- return [{ text, precedence: parentPrecedence }, rightContext];
273
- }
274
- // CHAR VS STRING COMPARISON FIX:
275
- // In C#, string[int] returns char, but in TypeScript it returns string.
276
- // The IR now sets inferredType to char for string indexer access.
277
- // When comparing a char-typed expression with a single-character string literal,
278
- // emit the string as a char literal to avoid CS0019 (operator == cannot be applied to char and string).
279
- const isComparisonOp = op === "==" ||
280
- op === "!=" ||
281
- op === "<" ||
282
- op === ">" ||
283
- op === "<=" ||
284
- op === ">=";
285
- if (isComparisonOp) {
286
- const leftIsChar = isCharTyped(expr.left);
287
- const rightIsChar = isCharTyped(expr.right);
288
- const leftSingleChar = getSingleCharLiteral(expr.left);
289
- const rightSingleChar = getSingleCharLiteral(expr.right);
290
- // Case 1: left is char-typed, right is single-char literal → emit right as char
291
- if (leftIsChar && rightSingleChar !== undefined) {
292
- const [leftFrag, leftContext] = emitExpression(expr.left, context);
293
- // Emit as char literal instead of string literal
294
- const charLiteral = `'${escapeCharLiteral(rightSingleChar)}'`;
295
- const text = `${leftFrag.text} ${op} ${charLiteral}`;
296
- return [{ text, precedence: parentPrecedence }, leftContext];
297
- }
298
- // Case 2: right is char-typed, left is single-char literal → emit left as char
299
- if (rightIsChar && leftSingleChar !== undefined) {
300
- const [rightFrag, rightContext] = emitExpression(expr.right, context);
301
- // Emit as char literal instead of string literal
302
- const charLiteral = `'${escapeCharLiteral(leftSingleChar)}'`;
303
- const text = `${charLiteral} ${op} ${rightFrag.text}`;
304
- return [{ text, precedence: parentPrecedence }, rightContext];
305
- }
306
- }
307
- // C# does not support relational operators directly on strings.
308
- // TypeScript's lexicographic ordering maps to ordinal string comparison.
309
- if (isComparisonOp &&
310
- (op === "<" || op === ">" || op === "<=" || op === ">=") &&
311
- isStringTyped(expr.left) &&
312
- isStringTyped(expr.right)) {
313
- const [leftFrag, leftContext] = emitExpression(expr.left, context);
314
- const [rightFrag, rightContext] = emitExpression(expr.right, leftContext);
315
- const compareExpr = `global::System.String.CompareOrdinal(${leftFrag.text}, ${rightFrag.text})`;
316
- const text = `${compareExpr} ${op} 0`;
317
- return [{ text, precedence: getPrecedence(expr.operator) }, rightContext];
318
- }
319
- // NULLISH COMPARISONS:
320
- //
321
- // Prefer `== null` / `!= null` for normal reference/nullable types so the result
322
- // is expression-tree friendly (EF Core query providers do not support pattern matching).
323
- //
324
- // For unconstrained generics (T), `== null` is not always valid, so we instead cast
325
- // to `object` to force reference-equality semantics and avoid operator overloads:
326
- // ((object)x) == null
327
- // This also avoids emitting pattern matching (`is null`) which is rejected inside
328
- // expression trees (EF Core query providers).
329
- //
330
- // TypeScript: x === undefined → C#: x == null
331
- // TypeScript: x !== undefined → C#: x != null
332
- // TypeScript: x === null → C#: x == null
333
- // TypeScript: x !== null → C#: x != null
334
- const isNullishLiteral = (e) => (e.kind === "literal" && (e.value === undefined || e.value === null)) ||
335
- (e.kind === "identifier" && (e.name === "undefined" || e.name === "null"));
336
- const leftIsNullish = isNullishLiteral(expr.left);
337
- const rightIsNullish = isNullishLiteral(expr.right);
338
- const isNullishComparison = isComparisonOp &&
339
- (op === "==" || op === "!=") &&
340
- (leftIsNullish || rightIsNullish);
341
- if (isNullishComparison) {
342
- // One side is null/undefined literal, emit the other side as a C# null check.
343
- // Clear narrowedBindings so we emit the raw identifier (not .Value)
344
- const nonNullishExpr = leftIsNullish ? expr.right : expr.left;
345
- const nullishExpr = leftIsNullish ? expr.left : expr.right;
346
- const isUndefinedLiteral = (nullishExpr.kind === "literal" && nullishExpr.value === undefined) ||
347
- (nullishExpr.kind === "identifier" && nullishExpr.name === "undefined");
348
- // JS dictionary-style access (`dict[key]`) with undefined comparison should
349
- // model key existence, not CLR value-type nullability.
350
- //
351
- // dict[key] === undefined -> !dict.ContainsKey(key)
352
- // dict[key] !== undefined -> dict.ContainsKey(key)
353
- //
354
- // This prevents miscompiles like folding `dict[key] !== undefined` to `true`
355
- // when value type is non-nullable, and preserves delete/lookup behavior.
356
- if (isUndefinedLiteral &&
357
- nonNullishExpr.kind === "memberAccess" &&
358
- nonNullishExpr.isComputed &&
359
- typeof nonNullishExpr.property !== "string" &&
360
- (nonNullishExpr.accessKind === "dictionary" ||
361
- nonNullishExpr.object.inferredType?.kind === "dictionaryType")) {
362
- const nonNullishContext = { ...context, narrowedBindings: undefined };
363
- const [dictFrag, dictContext] = emitExpression(nonNullishExpr.object, nonNullishContext);
364
- const [keyFrag, keyContext] = emitExpression(nonNullishExpr.property, dictContext);
365
- const containsExpr = `(${dictFrag.text}).ContainsKey(${keyFrag.text})`;
366
- const text = op === "==" ? `!${containsExpr}` : containsExpr;
367
- return [{ text, precedence: getPrecedence(expr.operator) }, keyContext];
368
- }
369
- const nonNullishContext = { ...context, narrowedBindings: undefined };
370
- const [nonNullishFrag, resultContext] = emitExpression(nonNullishExpr, nonNullishContext);
371
- const inferred = nonNullishExpr.inferredType;
372
- const base = inferred ? stripNullish(inferred) : undefined;
373
- const bareTypeParamName = (() => {
374
- if (!base)
375
- return undefined;
376
- if (base.kind === "typeParameterType")
377
- return base.name;
378
- if (base.kind === "referenceType" &&
379
- (resultContext.typeParameters?.has(base.name) ?? false) &&
380
- (!base.typeArguments || base.typeArguments.length === 0)) {
381
- return base.name;
382
- }
383
- return undefined;
384
- })();
385
- const isDefiniteNonUnionValueType = inferred !== undefined &&
386
- inferred.kind !== "unionType" &&
387
- isDefinitelyValueType(inferred);
388
- const typeParamConstraint = bareTypeParamName !== undefined
389
- ? (resultContext.typeParamConstraints?.get(bareTypeParamName) ??
390
- "unconstrained")
391
- : undefined;
392
- const needsObjectCastForTypeParam = bareTypeParamName !== undefined &&
393
- (typeParamConstraint === "unconstrained" ||
394
- typeParamConstraint === "struct");
395
- const needsObjectCastForValueType = isDefiniteNonUnionValueType;
396
- const nullOp = op === "==" ? "== null" : "!= null";
397
- const nullOperandText = (() => {
398
- switch (nonNullishExpr.kind) {
399
- case "identifier":
400
- case "memberAccess":
401
- case "call":
402
- case "new":
403
- case "this":
404
- case "literal":
405
- return nonNullishFrag.text;
406
- default:
407
- return `(${nonNullishFrag.text})`;
408
- }
409
- })();
410
- const text = needsObjectCastForTypeParam || needsObjectCastForValueType
411
- ? `((global::System.Object)(${nonNullishFrag.text})) ${nullOp}`
412
- : `${nullOperandText} ${nullOp}`;
413
- return [{ text, precedence: getPrecedence(expr.operator) }, resultContext];
414
- }
415
- // Standard emission path
416
- // Emit operands without contextual type propagation
417
- // Literals will emit using their raw lexeme (42 vs 42.0)
418
- const [leftFrag, leftContext] = emitExpression(expr.left, context);
419
- const [rightFrag, rightContext] = emitExpression(expr.right, leftContext);
420
- // Wrap child expressions in parentheses if their precedence is lower than parent
421
- // This preserves grouping: (x + y) * z should not become x + y * z
422
- const leftText = leftFrag.precedence !== undefined && leftFrag.precedence < parentPrecedence
423
- ? `(${leftFrag.text})`
424
- : leftFrag.text;
425
- // For right operand, also wrap if precedence is equal (right-to-left associativity issue)
426
- // Example: a - (b - c) should not become a - b - c
427
- const rightText = rightFrag.precedence !== undefined &&
428
- rightFrag.precedence <= parentPrecedence
429
- ? `(${rightFrag.text})`
430
- : rightFrag.text;
431
- const text = `${leftText} ${op} ${rightText}`;
432
- return [{ text, precedence: getPrecedence(expr.operator) }, rightContext];
433
- };
434
- /**
435
- * Check if an IR type is boolean
436
- */
437
- const isBooleanType = (type) => {
438
- if (!type)
439
- return false;
440
- return type.kind === "primitiveType" && type.name === "boolean";
441
- };
442
- /**
443
- * Emit a logical operator expression (&&, ||, ??)
444
- *
445
- * In TypeScript, || is used both for:
446
- * 1. Boolean OR (when operands are booleans)
447
- * 2. Nullish coalescing fallback (when left operand is nullable)
448
- *
449
- * In C#:
450
- * - || only works with booleans
451
- * - ?? is used for nullish coalescing
452
- *
453
- * We check if || is used with non-boolean operands and emit ?? instead.
454
- */
455
- export const emitLogical = (expr, context) => {
456
- const [leftFrag, leftContext] = emitExpression(expr.left, context);
457
- // If || is used with non-boolean left operand, use ?? instead for nullish coalescing
458
- const operator = expr.operator === "||" && !isBooleanType(expr.left.inferredType)
459
- ? "??"
460
- : expr.operator;
461
- const parentPrecedence = getPrecedence(operator);
462
- // If the left operand is a non-nullable value type, `??` is invalid in C# and the
463
- // fallback is unreachable. Emit only the left operand.
464
- if (operator === "??" &&
465
- expr.left.inferredType &&
466
- expr.left.inferredType.kind !== "unionType" &&
467
- isDefinitelyValueType(expr.left.inferredType) &&
468
- // Conditional access (`?.` / `?[`) produces nullable value types in C# even when the
469
- // underlying member type is non-nullable (e.g., `string?.Length` → `int?`).
470
- // In that case the fallback is still meaningful and must be preserved.
471
- !leftFrag.text.includes("?.") &&
472
- !leftFrag.text.includes("?[")) {
473
- return [leftFrag, leftContext];
474
- }
475
- const [rightFrag, rightContext] = emitExpression(expr.right, leftContext);
476
- const leftText = leftFrag.precedence !== undefined && leftFrag.precedence < parentPrecedence
477
- ? `(${leftFrag.text})`
478
- : leftFrag.text;
479
- const rightText = rightFrag.precedence !== undefined &&
480
- rightFrag.precedence <= parentPrecedence
481
- ? `(${rightFrag.text})`
482
- : rightFrag.text;
483
- const text = `${leftText} ${operator} ${rightText}`;
484
- return [{ text, precedence: getPrecedence(operator) }, rightContext];
485
- };
486
- /**
487
- * Emit a unary operator expression (-, +, !, ~, typeof, void, delete)
488
- *
489
- * NEW NUMERIC SPEC: No contextual type propagation for numeric literals.
490
- * Explicit casts come from IrCastExpression nodes.
491
- *
492
- * @param expr - The unary expression
493
- * @param context - Emitter context
494
- * @param _expectedType - Unused under new spec (kept for API compatibility)
495
- */
496
- export const emitUnary = (expr, context, expectedType) => {
497
- // In TypeScript, `!x` applies JS ToBoolean semantics to *any* operand.
498
- // In C#, `!` only works on booleans, so we must coerce to a boolean condition.
499
- if (expr.operator === "!") {
500
- const [condText, condCtx] = emitBooleanCondition(expr.expression, (e, ctx) => emitExpression(e, ctx), context);
501
- const text = `!(${condText})`;
502
- return [{ text, precedence: 15 }, condCtx];
503
- }
504
- if (expr.operator === "delete") {
505
- // JavaScript `delete obj[key]` maps to dictionary key removal in CLR:
506
- // delete dict[key] -> dict.Remove(key)
507
- // For unsupported targets we keep the existing no-op emission for now.
508
- const target = expr.expression;
509
- if (target.kind === "memberAccess" &&
510
- target.isComputed &&
511
- typeof target.property !== "string" &&
512
- (target.accessKind === "dictionary" ||
513
- target.object.inferredType?.kind === "dictionaryType")) {
514
- const [objectFrag, objectContext] = emitExpression(target.object, context);
515
- const [keyFrag, keyContext] = emitExpression(target.property, objectContext);
516
- const text = `${objectFrag.text}.Remove(${keyFrag.text})`;
517
- return [{ text }, keyContext];
518
- }
519
- const [targetFrag, newContext] = emitExpression(target, context);
520
- const text = `/* delete ${targetFrag.text} */`;
521
- return [{ text }, newContext];
522
- }
523
- const [operandFrag, newContext] = emitExpression(expr.expression, context);
524
- if (expr.operator === "typeof") {
525
- // typeof becomes global::Tsonic.Runtime.Operators.typeof()
526
- const text = `global::Tsonic.Runtime.Operators.@typeof(${operandFrag.text})`;
527
- return [{ text }, newContext];
528
- }
529
- if (expr.operator === "void") {
530
- // `void expr` evaluates `expr` and yields `undefined`.
531
- //
532
- // In expression position we must produce a value, so use an IIFE:
533
- // (() => { <eval expr>; return default(<T>); })()
534
- //
535
- // In statement position, emitExpressionStatement handles this separately
536
- // (so we don't pay this cost for the common `void x;` marker).
537
- const operand = expr.expression;
538
- // If the operand is a literal null/undefined, evaluation is a no-op and can be skipped.
539
- // This avoids generating invalid discard assignments like `_ = default;`.
540
- const isNoopOperand = (operand.kind === "literal" &&
541
- (operand.value === undefined || operand.value === null)) ||
542
- (operand.kind === "identifier" &&
543
- (operand.name === "undefined" || operand.name === "null"));
544
- let currentContext = newContext;
545
- const effectiveExpectedType = expectedType &&
546
- expectedType.kind !== "voidType" &&
547
- expectedType.kind !== "neverType"
548
- ? expectedType
549
- : undefined;
550
- let returnTypeText = "object?";
551
- let defaultText = "default";
552
- if (effectiveExpectedType) {
553
- try {
554
- const [typeText, next] = emitType(effectiveExpectedType, currentContext);
555
- currentContext = next;
556
- returnTypeText = typeText;
557
- defaultText = `default(${typeText})`;
558
- }
559
- catch {
560
- // Fall back to object? + default literal.
561
- }
562
- }
563
- const operandStatement = (() => {
564
- if (isNoopOperand)
565
- return "";
566
- // If the operand is already a valid statement-expression (call/new/assignment/
567
- // update/await), emit it directly. Otherwise, use a discard assignment.
568
- if (operand.kind === "call" ||
569
- operand.kind === "new" ||
570
- operand.kind === "assignment" ||
571
- operand.kind === "update" ||
572
- operand.kind === "await") {
573
- return `${operandFrag.text}; `;
574
- }
575
- return `_ = ${operandFrag.text}; `;
576
- })();
577
- if (operand.kind === "await") {
578
- if (!currentContext.isAsync) {
579
- throw new Error("ICE: `void await <expr>` reached emitter in a non-async context.");
580
- }
581
- const taskReturnType = `global::System.Threading.Tasks.Task<${returnTypeText}>`;
582
- const text = `await ((global::System.Func<${taskReturnType}>)(async () => { ${operandStatement}return ${defaultText}; }))()`;
583
- return [{ text }, currentContext];
584
- }
585
- const text = `((global::System.Func<${returnTypeText}>)(() => { ${operandStatement}return ${defaultText}; }))()`;
586
- return [{ text }, currentContext];
587
- }
588
- const text = `${expr.operator}${operandFrag.text}`;
589
- return [{ text, precedence: 15 }, newContext];
590
- };
591
- /**
592
- * Emit an update operator expression (++, --)
593
- */
594
- export const emitUpdate = (expr, context) => {
595
- // Narrowing maps (instanceof / nullable / union) apply to *reads*, not writes.
596
- // For update operators, the operand is written, so we must not rewrite the target
597
- // identifier to a narrowed binding (e.g., C# pattern var).
598
- const operandCtx = expr.expression.kind === "identifier" &&
599
- context.narrowedBindings?.has(expr.expression.name)
600
- ? (() => {
601
- const next = new Map(context.narrowedBindings);
602
- next.delete(expr.expression.name);
603
- return { ...context, narrowedBindings: next };
604
- })()
605
- : context;
606
- const [operandFrag, ctx] = emitExpression(expr.expression, operandCtx);
607
- const newContext = operandCtx !== context
608
- ? { ...ctx, narrowedBindings: context.narrowedBindings }
609
- : ctx;
610
- const text = expr.prefix
611
- ? `${expr.operator}${operandFrag.text}`
612
- : `${operandFrag.text}${expr.operator}`;
613
- return [{ text, precedence: 15 }, newContext];
614
- };
615
- /**
616
- * Emit an assignment expression (=, +=, -=, etc.)
617
- *
618
- * Passes the LHS type as expected type to RHS, enabling proper integer
619
- * literal emission for cases like `this.value = this.value + 1`.
620
- */
621
- export const emitAssignment = (expr, context) => {
622
- // Array element assignment uses native CLR indexer
623
- // HARD GATE: Index must be proven Int32 (validated by proof pass)
624
- if (expr.operator === "=" &&
625
- "kind" in expr.left &&
626
- expr.left.kind === "memberAccess" &&
627
- expr.left.isComputed &&
628
- expr.left.object.inferredType?.kind === "arrayType") {
629
- const leftExpr = expr.left;
630
- const indexExpr = leftExpr.property;
631
- if (!hasInt32Proof(indexExpr)) {
632
- // ICE: Unproven index should have been caught by proof pass (TSN5107)
633
- throw new Error(`Internal Compiler Error: Array index must be proven Int32. ` +
634
- `This should have been caught by the numeric proof pass (TSN5107).`);
635
- }
636
- const [objectFrag, objectContext] = emitExpression(leftExpr.object, context);
637
- const [indexFrag, indexContext] = emitExpression(indexExpr, objectContext);
638
- const [rightFrag, rightContext] = emitExpression(expr.right, indexContext);
639
- // Use native CLR indexer
640
- const text = `${objectFrag.text}[${indexFrag.text}] = ${rightFrag.text}`;
641
- return [{ text, precedence: 2 }, rightContext];
642
- }
643
- // Left side can be an expression or a pattern (for destructuring)
644
- const isPattern = "kind" in expr.left &&
645
- (expr.left.kind === "identifierPattern" ||
646
- expr.left.kind === "arrayPattern" ||
647
- expr.left.kind === "objectPattern");
648
- // Handle destructuring assignment patterns
649
- if (isPattern && expr.operator === "=") {
650
- const pattern = expr.left;
651
- // Emit the RHS first
652
- const [rightFrag, rightContext] = emitExpression(expr.right, context);
653
- // Use lowerAssignmentPattern to generate the destructuring expression
654
- const result = lowerAssignmentPattern(pattern, rightFrag.text, expr.right.inferredType, rightContext);
655
- return [{ text: result.expression, precedence: 2 }, result.context];
656
- }
657
- // Standard assignment (expression on left side)
658
- let leftText;
659
- let leftContext;
660
- let leftType;
661
- if (isPattern) {
662
- // Identifier pattern with compound assignment (+=, etc.)
663
- const pattern = expr.left;
664
- if (pattern.kind === "identifierPattern") {
665
- leftText = emitRemappedLocalName(pattern.name, context);
666
- leftContext = context;
667
- leftType = pattern.type;
668
- }
669
- else {
670
- // Compound assignment to array/object pattern - not valid in JS
671
- leftText = "/* invalid compound destructuring */";
672
- leftContext = context;
673
- }
674
- }
675
- else {
676
- const leftExpr = expr.left;
677
- // Narrowing maps (instanceof / nullable / union) apply to *reads*, not writes.
678
- // For assignment, the LHS is written, so we must not rewrite identifier targets
679
- // to narrowed bindings (e.g., C# pattern vars).
680
- const leftCtx = leftExpr.kind === "identifier" &&
681
- context.narrowedBindings?.has(leftExpr.name)
682
- ? (() => {
683
- const next = new Map(context.narrowedBindings);
684
- next.delete(leftExpr.name);
685
- return { ...context, narrowedBindings: next };
686
- })()
687
- : context;
688
- const [leftFrag, ctx] = emitExpression(leftExpr, leftCtx);
689
- leftText = leftFrag.text;
690
- // Restore narrowing for RHS emission (reads) when we suppressed it for the LHS.
691
- leftContext =
692
- leftCtx !== context
693
- ? { ...ctx, narrowedBindings: context.narrowedBindings }
694
- : ctx;
695
- leftType = leftExpr.inferredType;
696
- }
697
- // Pass LHS type as expected type to RHS for proper integer handling
698
- const [rightFrag, rightContext] = emitExpression(expr.right, leftContext, leftType);
699
- const text = `${leftText} ${expr.operator} ${rightFrag.text}`;
700
- return [{ text, precedence: 2 }, rightContext];
701
- };
702
- const resolveLocalTypesForReference = (type, context) => {
703
- const lookupName = type.name.includes(".")
704
- ? (type.name.split(".").pop() ?? type.name)
705
- : type.name;
706
- if (context.localTypes?.has(lookupName)) {
707
- return context.localTypes;
708
- }
709
- const moduleMap = context.options.moduleMap;
710
- if (!moduleMap)
711
- return undefined;
712
- const matches = [];
713
- for (const m of moduleMap.values()) {
714
- if (!m.localTypes)
715
- continue;
716
- if (m.localTypes.has(lookupName)) {
717
- matches.push({ namespace: m.namespace, localTypes: m.localTypes });
718
- }
719
- }
720
- if (matches.length === 0)
721
- return undefined;
722
- if (matches.length === 1)
723
- return matches[0].localTypes;
724
- const fqn = type.resolvedClrType ?? (type.name.includes(".") ? type.name : undefined);
725
- if (fqn && fqn.includes(".")) {
726
- const ns = fqn.slice(0, fqn.lastIndexOf("."));
727
- const filtered = matches.filter((m) => m.namespace === ns);
728
- if (filtered.length === 1)
729
- return filtered[0].localTypes;
730
- }
731
- return undefined;
732
- };
733
- const tryGetLiteralSet = (type, context) => {
734
- const resolved = resolveTypeAlias(type, context);
735
- if (resolved.kind === "literalType") {
736
- return new Set([resolved.value]);
737
- }
738
- if (resolved.kind === "unionType") {
739
- const out = new Set();
740
- for (const t of resolved.types) {
741
- const r = resolveTypeAlias(t, context);
742
- if (r.kind !== "literalType")
743
- return undefined;
744
- out.add(r.value);
745
- }
746
- return out;
747
- }
748
- return undefined;
749
- };
750
- const tryResolveTernaryGuard = (condition, context) => {
751
- // Check for direct call: isUser(x)
752
- const resolveFromCall = (call) => {
753
- const narrowing = call.narrowing;
754
- if (!narrowing || narrowing.kind !== "typePredicate")
755
- return undefined;
756
- const arg = call.arguments[narrowing.argIndex];
757
- if (!arg ||
758
- ("kind" in arg && arg.kind === "spread") ||
759
- arg.kind !== "identifier") {
760
- return undefined;
761
- }
762
- const originalName = arg.name;
763
- const unionSourceType = arg.inferredType;
764
- if (!unionSourceType)
765
- return undefined;
766
- const resolved = resolveTypeAlias(stripNullish(unionSourceType), context);
767
- if (resolved.kind !== "unionType")
768
- return undefined;
769
- const idx = findUnionMemberIndex(resolved, narrowing.targetType, context);
770
- if (idx === undefined)
771
- return undefined;
772
- return {
773
- originalName,
774
- memberN: idx + 1,
775
- escapedOrig: emitRemappedLocalName(originalName, context),
776
- polarity: "positive",
777
- };
778
- };
779
- // Direct call: isUser(x) -> narrow whenTrue
780
- if (condition.kind === "call") {
781
- return resolveFromCall(condition);
782
- }
783
- // Discriminant literal equality: x.kind === "circle"
784
- const resolveFromDiscriminantEquality = (expr) => {
785
- // Normalize `!(x.prop === lit)` to `x.prop !== lit` (and vice versa) by flipping polarity.
786
- if (expr.kind === "unary" && expr.operator === "!") {
787
- const inner = resolveFromDiscriminantEquality(expr.expression);
788
- if (!inner)
789
- return undefined;
790
- return {
791
- ...inner,
792
- polarity: inner.polarity === "positive" ? "negative" : "positive",
793
- };
794
- }
795
- if (expr.kind !== "binary")
796
- return undefined;
797
- if (expr.operator !== "===" &&
798
- expr.operator !== "!==" &&
799
- expr.operator !== "==" &&
800
- expr.operator !== "!=") {
801
- return undefined;
802
- }
803
- const extract = (left, right) => {
804
- if (left.kind !== "memberAccess")
805
- return undefined;
806
- if (left.isOptional)
807
- return undefined;
808
- if (left.isComputed)
809
- return undefined;
810
- if (left.object.kind !== "identifier")
811
- return undefined;
812
- if (typeof left.property !== "string")
813
- return undefined;
814
- if (right.kind !== "literal")
815
- return undefined;
816
- if (typeof right.value !== "string" &&
817
- typeof right.value !== "number" &&
818
- typeof right.value !== "boolean") {
819
- return undefined;
820
- }
821
- return {
822
- receiver: left.object,
823
- propertyName: left.property,
824
- literal: right.value,
825
- };
826
- };
827
- const direct = extract(expr.left, expr.right);
828
- const swapped = direct ? undefined : extract(expr.right, expr.left);
829
- const match = direct ?? swapped;
830
- if (!match)
831
- return undefined;
832
- const { receiver, propertyName, literal } = match;
833
- const originalName = receiver.name;
834
- if (context.narrowedBindings?.has(originalName))
835
- return undefined;
836
- const unionSourceType = receiver.inferredType;
837
- if (!unionSourceType)
838
- return undefined;
839
- const resolved = resolveTypeAlias(stripNullish(unionSourceType), context);
840
- if (resolved.kind !== "unionType")
841
- return undefined;
842
- const unionArity = resolved.types.length;
843
- if (unionArity < 2 || unionArity > 8)
844
- return undefined;
845
- const matchingMembers = [];
846
- for (let i = 0; i < resolved.types.length; i++) {
847
- const member = resolved.types[i];
848
- if (!member)
849
- continue;
850
- let propType;
851
- if (member.kind === "objectType") {
852
- const prop = member.members.find((m) => m.kind === "propertySignature" && m.name === propertyName);
853
- propType = prop?.type;
854
- }
855
- else if (member.kind === "referenceType") {
856
- const localTypes = resolveLocalTypesForReference(member, context);
857
- if (!localTypes)
858
- continue;
859
- const lookupName = member.name.includes(".")
860
- ? (member.name.split(".").pop() ?? member.name)
861
- : member.name;
862
- propType = getPropertyType({ ...member, name: lookupName }, propertyName, { ...context, localTypes });
863
- }
864
- else {
865
- continue;
866
- }
867
- if (!propType)
868
- continue;
869
- const literals = tryGetLiteralSet(propType, context);
870
- if (!literals)
871
- continue;
872
- if (literals.has(literal)) {
873
- matchingMembers.push(i + 1);
874
- }
875
- }
876
- if (matchingMembers.length !== 1)
877
- return undefined;
878
- const memberN = matchingMembers[0];
879
- if (!memberN)
880
- return undefined;
881
- const isInequality = expr.operator === "!==" || expr.operator === "!=";
882
- return {
883
- originalName,
884
- memberN,
885
- escapedOrig: emitRemappedLocalName(originalName, context),
886
- polarity: isInequality ? "negative" : "positive",
887
- };
888
- };
889
- const discr = resolveFromDiscriminantEquality(condition);
890
- if (discr)
891
- return discr;
892
- // Negated call: !isUser(x) -> narrow whenFalse
893
- if (condition.kind === "unary" &&
894
- condition.operator === "!" &&
895
- condition.expression.kind === "call") {
896
- const guard = resolveFromCall(condition.expression);
897
- if (guard) {
898
- return { ...guard, polarity: "negative" };
899
- }
900
- }
901
- return undefined;
902
- };
903
- /**
904
- * Emit a conditional (ternary) expression
905
- *
906
- * Supports type predicate narrowing:
907
- * - `isUser(x) ? x.name : "anon"` → `x.Is1() ? (x.As1()).name : "anon"`
908
- * - `!isUser(x) ? "anon" : x.name` → `!x.Is1() ? "anon" : (x.As1()).name`
909
- *
910
- * @param expr - The conditional expression
911
- * @param context - Emitter context
912
- * @param expectedType - Optional expected type (for null → default in generic contexts)
913
- */
914
- export const emitConditional = (expr, context, expectedType) => {
915
- // When no contextual expectedType is provided (e.g., `var x = cond ? a : b`),
916
- // use the conditional expression's own inferred type to guide null/undefined → default
917
- // conversions and keep C# type inference consistent with TS.
918
- const branchExpectedType = expectedType ?? expr.inferredType;
919
- // Try to detect type predicate guard in condition
920
- const guard = tryResolveTernaryGuard(expr.condition, context);
921
- if (guard) {
922
- const { originalName, memberN, escapedOrig, polarity } = guard;
923
- // Build condition text
924
- const condText = polarity === "positive"
925
- ? `${escapedOrig}.Is${memberN}()`
926
- : `!${escapedOrig}.Is${memberN}()`;
927
- // Create inline narrowing binding: x -> (x.AsN())
928
- const inlineExpr = `(${escapedOrig}.As${memberN}())`;
929
- const narrowedMap = new Map(context.narrowedBindings ?? []);
930
- narrowedMap.set(originalName, { kind: "expr", exprText: inlineExpr });
931
- const narrowedContext = {
932
- ...context,
933
- narrowedBindings: narrowedMap,
934
- };
935
- // Apply narrowing to the appropriate branch
936
- const [trueFrag, trueContext] = polarity === "positive"
937
- ? emitExpression(expr.whenTrue, narrowedContext, branchExpectedType)
938
- : emitExpression(expr.whenTrue, context, branchExpectedType);
939
- const [falseFrag, falseContext] = polarity === "negative"
940
- ? emitExpression(expr.whenFalse, narrowedContext, branchExpectedType)
941
- : emitExpression(expr.whenFalse, trueContext, branchExpectedType);
942
- const text = `${condText} ? ${trueFrag.text} : ${falseFrag.text}`;
943
- // Return context WITHOUT narrowing (don't leak)
944
- const finalContext = {
945
- ...falseContext,
946
- narrowedBindings: context.narrowedBindings,
947
- };
948
- return [{ text, precedence: 3 }, finalContext];
949
- }
950
- // Standard ternary emission (no narrowing)
951
- const [condText, condContext] = emitBooleanCondition(expr.condition, (e, ctx) => emitExpression(e, ctx), context);
952
- // Pass expectedType (or inferred type) to both branches for null/undefined → default conversion
953
- const [trueFrag, trueContext] = emitExpression(expr.whenTrue, condContext, branchExpectedType);
954
- const [falseFrag, falseContext] = emitExpression(expr.whenFalse, trueContext, branchExpectedType);
955
- const text = `${condText} ? ${trueFrag.text} : ${falseFrag.text}`;
956
- return [{ text, precedence: 3 }, falseContext];
957
- };
9
+ export { emitBinary } from "./operators/binary-emitter.js";
10
+ export { emitLogical } from "./operators/logical-emitter.js";
11
+ export { emitUnary, emitUpdate } from "./operators/unary-emitter.js";
12
+ export { emitAssignment } from "./operators/assignment-emitter.js";
13
+ export { emitConditional } from "./operators/conditional-emitter.js";
958
14
  //# sourceMappingURL=operators.js.map