@tsonic/frontend 0.0.14 → 0.0.16

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 (507) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/graph/builder.js +2 -2
  3. package/dist/graph/builder.js.map +1 -1
  4. package/dist/graph/extraction/imports.js +1 -1
  5. package/dist/graph/extraction/imports.js.map +1 -1
  6. package/dist/graph/extraction/orchestrator.d.ts.map +1 -1
  7. package/dist/graph/extraction/orchestrator.js +3 -2
  8. package/dist/graph/extraction/orchestrator.js.map +1 -1
  9. package/dist/ir/binding/index.d.ts +155 -0
  10. package/dist/ir/binding/index.d.ts.map +1 -0
  11. package/dist/ir/binding/index.js +1035 -0
  12. package/dist/ir/binding/index.js.map +1 -0
  13. package/dist/ir/binding-resolution.test.js +193 -52
  14. package/dist/ir/binding-resolution.test.js.map +1 -1
  15. package/dist/ir/bindings-disambiguation.test.d.ts +11 -0
  16. package/dist/ir/bindings-disambiguation.test.d.ts.map +1 -0
  17. package/dist/ir/bindings-disambiguation.test.js +416 -0
  18. package/dist/ir/bindings-disambiguation.test.js.map +1 -0
  19. package/dist/ir/builder/exports.d.ts +20 -2
  20. package/dist/ir/builder/exports.d.ts.map +1 -1
  21. package/dist/ir/builder/exports.js +65 -6
  22. package/dist/ir/builder/exports.js.map +1 -1
  23. package/dist/ir/builder/imports.d.ts +9 -5
  24. package/dist/ir/builder/imports.d.ts.map +1 -1
  25. package/dist/ir/builder/imports.js +20 -31
  26. package/dist/ir/builder/imports.js.map +1 -1
  27. package/dist/ir/builder/orchestrator.d.ts +10 -1
  28. package/dist/ir/builder/orchestrator.d.ts.map +1 -1
  29. package/dist/ir/builder/orchestrator.js +32 -15
  30. package/dist/ir/builder/orchestrator.js.map +1 -1
  31. package/dist/ir/builder/statements.d.ts +7 -1
  32. package/dist/ir/builder/statements.d.ts.map +1 -1
  33. package/dist/ir/builder/statements.js +7 -2
  34. package/dist/ir/builder/statements.js.map +1 -1
  35. package/dist/ir/builder/types.d.ts +2 -0
  36. package/dist/ir/builder/types.d.ts.map +1 -1
  37. package/dist/ir/builder/validation.d.ts +4 -1
  38. package/dist/ir/builder/validation.d.ts.map +1 -1
  39. package/dist/ir/builder/validation.js +37 -37
  40. package/dist/ir/builder/validation.js.map +1 -1
  41. package/dist/ir/builder.test.js +55 -112
  42. package/dist/ir/builder.test.js.map +1 -1
  43. package/dist/ir/converters/anonymous-synthesis.d.ts +30 -8
  44. package/dist/ir/converters/anonymous-synthesis.d.ts.map +1 -1
  45. package/dist/ir/converters/anonymous-synthesis.js +46 -55
  46. package/dist/ir/converters/anonymous-synthesis.js.map +1 -1
  47. package/dist/ir/converters/context.d.ts +40 -0
  48. package/dist/ir/converters/context.d.ts.map +1 -0
  49. package/dist/ir/converters/context.js +25 -0
  50. package/dist/ir/converters/context.js.map +1 -0
  51. package/dist/ir/converters/expressions/access.d.ts +6 -1
  52. package/dist/ir/converters/expressions/access.d.ts.map +1 -1
  53. package/dist/ir/converters/expressions/access.js +389 -43
  54. package/dist/ir/converters/expressions/access.js.map +1 -1
  55. package/dist/ir/converters/expressions/calls.d.ts +24 -3
  56. package/dist/ir/converters/expressions/calls.d.ts.map +1 -1
  57. package/dist/ir/converters/expressions/calls.js +674 -397
  58. package/dist/ir/converters/expressions/calls.js.map +1 -1
  59. package/dist/ir/converters/expressions/collections.d.ts +16 -3
  60. package/dist/ir/converters/expressions/collections.d.ts.map +1 -1
  61. package/dist/ir/converters/expressions/collections.js +300 -46
  62. package/dist/ir/converters/expressions/collections.js.map +1 -1
  63. package/dist/ir/converters/expressions/functions.d.ts +10 -3
  64. package/dist/ir/converters/expressions/functions.d.ts.map +1 -1
  65. package/dist/ir/converters/expressions/functions.js +158 -32
  66. package/dist/ir/converters/expressions/functions.js.map +1 -1
  67. package/dist/ir/converters/expressions/helpers.d.ts +22 -23
  68. package/dist/ir/converters/expressions/helpers.d.ts.map +1 -1
  69. package/dist/ir/converters/expressions/helpers.js +242 -239
  70. package/dist/ir/converters/expressions/helpers.js.map +1 -1
  71. package/dist/ir/converters/expressions/index.d.ts +1 -1
  72. package/dist/ir/converters/expressions/index.d.ts.map +1 -1
  73. package/dist/ir/converters/expressions/index.js +1 -1
  74. package/dist/ir/converters/expressions/index.js.map +1 -1
  75. package/dist/ir/converters/expressions/literals.d.ts +12 -12
  76. package/dist/ir/converters/expressions/literals.d.ts.map +1 -1
  77. package/dist/ir/converters/expressions/literals.js +62 -17
  78. package/dist/ir/converters/expressions/literals.js.map +1 -1
  79. package/dist/ir/converters/expressions/numeric-recovery.test.d.ts +5 -2
  80. package/dist/ir/converters/expressions/numeric-recovery.test.d.ts.map +1 -1
  81. package/dist/ir/converters/expressions/numeric-recovery.test.js +62 -49
  82. package/dist/ir/converters/expressions/numeric-recovery.test.js.map +1 -1
  83. package/dist/ir/converters/expressions/operators.d.ts +13 -4
  84. package/dist/ir/converters/expressions/operators.d.ts.map +1 -1
  85. package/dist/ir/converters/expressions/operators.js +183 -33
  86. package/dist/ir/converters/expressions/operators.js.map +1 -1
  87. package/dist/ir/converters/expressions/other.d.ts +11 -3
  88. package/dist/ir/converters/expressions/other.d.ts.map +1 -1
  89. package/dist/ir/converters/expressions/other.js +26 -10
  90. package/dist/ir/converters/expressions/other.js.map +1 -1
  91. package/dist/ir/converters/flow-narrowing.d.ts +27 -0
  92. package/dist/ir/converters/flow-narrowing.d.ts.map +1 -0
  93. package/dist/ir/converters/flow-narrowing.js +73 -0
  94. package/dist/ir/converters/flow-narrowing.js.map +1 -0
  95. package/dist/ir/converters/statements/control/blocks.d.ts +8 -2
  96. package/dist/ir/converters/statements/control/blocks.d.ts.map +1 -1
  97. package/dist/ir/converters/statements/control/blocks.js +7 -2
  98. package/dist/ir/converters/statements/control/blocks.js.map +1 -1
  99. package/dist/ir/converters/statements/control/conditionals.d.ts +14 -4
  100. package/dist/ir/converters/statements/control/conditionals.d.ts.map +1 -1
  101. package/dist/ir/converters/statements/control/conditionals.js +36 -10
  102. package/dist/ir/converters/statements/control/conditionals.js.map +1 -1
  103. package/dist/ir/converters/statements/control/exceptions.d.ts +10 -3
  104. package/dist/ir/converters/statements/control/exceptions.d.ts.map +1 -1
  105. package/dist/ir/converters/statements/control/exceptions.js +13 -7
  106. package/dist/ir/converters/statements/control/exceptions.js.map +1 -1
  107. package/dist/ir/converters/statements/control/loops.d.ts +16 -5
  108. package/dist/ir/converters/statements/control/loops.d.ts.map +1 -1
  109. package/dist/ir/converters/statements/control/loops.js +25 -15
  110. package/dist/ir/converters/statements/control/loops.js.map +1 -1
  111. package/dist/ir/converters/statements/declarations/classes/constructors.d.ts +3 -2
  112. package/dist/ir/converters/statements/declarations/classes/constructors.d.ts.map +1 -1
  113. package/dist/ir/converters/statements/declarations/classes/constructors.js +11 -7
  114. package/dist/ir/converters/statements/declarations/classes/constructors.js.map +1 -1
  115. package/dist/ir/converters/statements/declarations/classes/methods.d.ts +2 -1
  116. package/dist/ir/converters/statements/declarations/classes/methods.d.ts.map +1 -1
  117. package/dist/ir/converters/statements/declarations/classes/methods.js +63 -11
  118. package/dist/ir/converters/statements/declarations/classes/methods.js.map +1 -1
  119. package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts +2 -1
  120. package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts.map +1 -1
  121. package/dist/ir/converters/statements/declarations/classes/orchestrator.js +60 -40
  122. package/dist/ir/converters/statements/declarations/classes/orchestrator.js.map +1 -1
  123. package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts +6 -2
  124. package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts.map +1 -1
  125. package/dist/ir/converters/statements/declarations/classes/override-detection.js +49 -50
  126. package/dist/ir/converters/statements/declarations/classes/override-detection.js.map +1 -1
  127. package/dist/ir/converters/statements/declarations/classes/properties.d.ts +9 -1
  128. package/dist/ir/converters/statements/declarations/classes/properties.d.ts.map +1 -1
  129. package/dist/ir/converters/statements/declarations/classes/properties.js +119 -16
  130. package/dist/ir/converters/statements/declarations/classes/properties.js.map +1 -1
  131. package/dist/ir/converters/statements/declarations/enums.d.ts +2 -1
  132. package/dist/ir/converters/statements/declarations/enums.d.ts.map +1 -1
  133. package/dist/ir/converters/statements/declarations/enums.js +8 -2
  134. package/dist/ir/converters/statements/declarations/enums.js.map +1 -1
  135. package/dist/ir/converters/statements/declarations/functions.d.ts +2 -1
  136. package/dist/ir/converters/statements/declarations/functions.d.ts.map +1 -1
  137. package/dist/ir/converters/statements/declarations/functions.js +11 -6
  138. package/dist/ir/converters/statements/declarations/functions.js.map +1 -1
  139. package/dist/ir/converters/statements/declarations/index.d.ts +3 -1
  140. package/dist/ir/converters/statements/declarations/index.d.ts.map +1 -1
  141. package/dist/ir/converters/statements/declarations/index.js +3 -1
  142. package/dist/ir/converters/statements/declarations/index.js.map +1 -1
  143. package/dist/ir/converters/statements/declarations/interfaces.d.ts +3 -2
  144. package/dist/ir/converters/statements/declarations/interfaces.d.ts.map +1 -1
  145. package/dist/ir/converters/statements/declarations/interfaces.js +26 -20
  146. package/dist/ir/converters/statements/declarations/interfaces.js.map +1 -1
  147. package/dist/ir/converters/statements/declarations/registry.d.ts +72 -0
  148. package/dist/ir/converters/statements/declarations/registry.d.ts.map +1 -1
  149. package/dist/ir/converters/statements/declarations/registry.js +92 -0
  150. package/dist/ir/converters/statements/declarations/registry.js.map +1 -1
  151. package/dist/ir/converters/statements/declarations/type-aliases.d.ts +2 -1
  152. package/dist/ir/converters/statements/declarations/type-aliases.d.ts.map +1 -1
  153. package/dist/ir/converters/statements/declarations/type-aliases.js +6 -4
  154. package/dist/ir/converters/statements/declarations/type-aliases.js.map +1 -1
  155. package/dist/ir/converters/statements/declarations/variables.d.ts +11 -1
  156. package/dist/ir/converters/statements/declarations/variables.d.ts.map +1 -1
  157. package/dist/ir/converters/statements/declarations/variables.js +123 -19
  158. package/dist/ir/converters/statements/declarations/variables.js.map +1 -1
  159. package/dist/ir/converters/statements/declarations.d.ts +4 -1
  160. package/dist/ir/converters/statements/declarations.d.ts.map +1 -1
  161. package/dist/ir/converters/statements/declarations.js +4 -1
  162. package/dist/ir/converters/statements/declarations.js.map +1 -1
  163. package/dist/ir/converters/statements/helpers.d.ts +4 -3
  164. package/dist/ir/converters/statements/helpers.d.ts.map +1 -1
  165. package/dist/ir/converters/statements/helpers.js +55 -31
  166. package/dist/ir/converters/statements/helpers.js.map +1 -1
  167. package/dist/ir/converters/statements/index.d.ts +1 -1
  168. package/dist/ir/converters/statements/index.d.ts.map +1 -1
  169. package/dist/ir/converters/statements/index.js +2 -1
  170. package/dist/ir/converters/statements/index.js.map +1 -1
  171. package/dist/ir/expression-converter.d.ts +10 -3
  172. package/dist/ir/expression-converter.d.ts.map +1 -1
  173. package/dist/ir/expression-converter.js +139 -57
  174. package/dist/ir/expression-converter.js.map +1 -1
  175. package/dist/ir/hierarchical-bindings-e2e.test.js +10 -6
  176. package/dist/ir/hierarchical-bindings-e2e.test.js.map +1 -1
  177. package/dist/ir/index.d.ts +5 -0
  178. package/dist/ir/index.d.ts.map +1 -1
  179. package/dist/ir/index.js +5 -0
  180. package/dist/ir/index.js.map +1 -1
  181. package/dist/ir/no-ts-type-inference.test.d.ts +17 -0
  182. package/dist/ir/no-ts-type-inference.test.d.ts.map +1 -0
  183. package/dist/ir/no-ts-type-inference.test.js +171 -0
  184. package/dist/ir/no-ts-type-inference.test.js.map +1 -0
  185. package/dist/ir/program-context.d.ts +87 -0
  186. package/dist/ir/program-context.d.ts.map +1 -0
  187. package/dist/ir/program-context.js +289 -0
  188. package/dist/ir/program-context.js.map +1 -0
  189. package/dist/ir/statement-converter.d.ts +14 -4
  190. package/dist/ir/statement-converter.d.ts.map +1 -1
  191. package/dist/ir/statement-converter.js +31 -21
  192. package/dist/ir/statement-converter.js.map +1 -1
  193. package/dist/ir/syntax/binding-patterns.d.ts +22 -0
  194. package/dist/ir/syntax/binding-patterns.d.ts.map +1 -0
  195. package/dist/ir/{type-converter/patterns.js → syntax/binding-patterns.js} +34 -8
  196. package/dist/ir/syntax/binding-patterns.js.map +1 -0
  197. package/dist/ir/thisarg-inference.test.d.ts +8 -0
  198. package/dist/ir/thisarg-inference.test.d.ts.map +1 -0
  199. package/dist/ir/thisarg-inference.test.js +94 -0
  200. package/dist/ir/thisarg-inference.test.js.map +1 -0
  201. package/dist/ir/type-system/index.d.ts +21 -0
  202. package/dist/ir/type-system/index.d.ts.map +1 -0
  203. package/dist/ir/type-system/index.js +43 -0
  204. package/dist/ir/type-system/index.js.map +1 -0
  205. package/dist/ir/type-system/internal/handle-types.d.ts +105 -0
  206. package/dist/ir/type-system/internal/handle-types.d.ts.map +1 -0
  207. package/dist/ir/type-system/internal/handle-types.js +13 -0
  208. package/dist/ir/type-system/internal/handle-types.js.map +1 -0
  209. package/dist/ir/type-system/internal/nominal-env.d.ts +66 -0
  210. package/dist/ir/type-system/internal/nominal-env.d.ts.map +1 -0
  211. package/dist/ir/type-system/internal/nominal-env.js +301 -0
  212. package/dist/ir/type-system/internal/nominal-env.js.map +1 -0
  213. package/dist/ir/type-system/internal/type-converter/arrays.d.ts +11 -0
  214. package/dist/ir/type-system/internal/type-converter/arrays.d.ts.map +1 -0
  215. package/dist/ir/{type-converter → type-system/internal/type-converter}/arrays.js +2 -2
  216. package/dist/ir/type-system/internal/type-converter/arrays.js.map +1 -0
  217. package/dist/ir/type-system/internal/type-converter/converter.d.ts +17 -0
  218. package/dist/ir/type-system/internal/type-converter/converter.d.ts.map +1 -0
  219. package/dist/ir/type-system/internal/type-converter/converter.js +16 -0
  220. package/dist/ir/type-system/internal/type-converter/converter.js.map +1 -0
  221. package/dist/ir/type-system/internal/type-converter/functions.d.ts +14 -0
  222. package/dist/ir/type-system/internal/type-converter/functions.d.ts.map +1 -0
  223. package/dist/ir/type-system/internal/type-converter/functions.js +66 -0
  224. package/dist/ir/type-system/internal/type-converter/functions.js.map +1 -0
  225. package/dist/ir/type-system/internal/type-converter/index.d.ts +11 -0
  226. package/dist/ir/type-system/internal/type-converter/index.d.ts.map +1 -0
  227. package/dist/ir/type-system/internal/type-converter/index.js +11 -0
  228. package/dist/ir/type-system/internal/type-converter/index.js.map +1 -0
  229. package/dist/ir/type-system/internal/type-converter/inference.d.ts +37 -0
  230. package/dist/ir/type-system/internal/type-converter/inference.d.ts.map +1 -0
  231. package/dist/ir/type-system/internal/type-converter/inference.js +32 -0
  232. package/dist/ir/type-system/internal/type-converter/inference.js.map +1 -0
  233. package/dist/ir/{type-converter → type-system/internal/type-converter}/literals.d.ts +1 -1
  234. package/dist/ir/type-system/internal/type-converter/literals.d.ts.map +1 -0
  235. package/dist/ir/type-system/internal/type-converter/literals.js.map +1 -0
  236. package/dist/ir/type-system/internal/type-converter/objects.d.ts +20 -0
  237. package/dist/ir/type-system/internal/type-converter/objects.d.ts.map +1 -0
  238. package/dist/ir/{type-converter → type-system/internal/type-converter}/objects.js +56 -6
  239. package/dist/ir/type-system/internal/type-converter/objects.js.map +1 -0
  240. package/dist/ir/{type-converter → type-system/internal/type-converter}/orchestrator.d.ts +3 -2
  241. package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts.map +1 -0
  242. package/dist/ir/{type-converter → type-system/internal/type-converter}/orchestrator.js +63 -21
  243. package/dist/ir/type-system/internal/type-converter/orchestrator.js.map +1 -0
  244. package/dist/ir/{type-converter → type-system/internal/type-converter}/primitives.d.ts +4 -4
  245. package/dist/ir/type-system/internal/type-converter/primitives.d.ts.map +1 -0
  246. package/dist/ir/{type-converter → type-system/internal/type-converter}/primitives.js +2 -2
  247. package/dist/ir/type-system/internal/type-converter/primitives.js.map +1 -0
  248. package/dist/ir/{type-converter → type-system/internal/type-converter}/references.d.ts +3 -2
  249. package/dist/ir/type-system/internal/type-converter/references.d.ts.map +1 -0
  250. package/dist/ir/type-system/internal/type-converter/references.js +545 -0
  251. package/dist/ir/type-system/internal/type-converter/references.js.map +1 -0
  252. package/dist/ir/type-system/internal/type-converter/unions-intersections.d.ts +15 -0
  253. package/dist/ir/type-system/internal/type-converter/unions-intersections.d.ts.map +1 -0
  254. package/dist/ir/type-system/internal/type-converter/unions-intersections.js +22 -0
  255. package/dist/ir/type-system/internal/type-converter/unions-intersections.js.map +1 -0
  256. package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.d.ts +23 -36
  257. package/dist/ir/type-system/internal/type-converter/utility-types.d.ts.map +1 -0
  258. package/dist/ir/type-system/internal/type-converter/utility-types.js +879 -0
  259. package/dist/ir/type-system/internal/type-converter/utility-types.js.map +1 -0
  260. package/dist/ir/type-system/internal/type-converter/utility-types.test.d.ts.map +1 -0
  261. package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.js +398 -120
  262. package/dist/ir/type-system/internal/type-converter/utility-types.test.js.map +1 -0
  263. package/dist/ir/type-system/internal/type-converter.d.ts +9 -0
  264. package/dist/ir/type-system/internal/type-converter.d.ts.map +1 -0
  265. package/dist/ir/type-system/internal/type-converter.js +9 -0
  266. package/dist/ir/type-system/internal/type-converter.js.map +1 -0
  267. package/dist/ir/type-system/internal/type-registry.d.ts +112 -0
  268. package/dist/ir/type-system/internal/type-registry.d.ts.map +1 -0
  269. package/dist/ir/type-system/internal/type-registry.js +535 -0
  270. package/dist/ir/type-system/internal/type-registry.js.map +1 -0
  271. package/dist/ir/type-system/internal/universe/alias-table.d.ts +92 -0
  272. package/dist/ir/type-system/internal/universe/alias-table.d.ts.map +1 -0
  273. package/dist/ir/type-system/internal/universe/alias-table.js +222 -0
  274. package/dist/ir/type-system/internal/universe/alias-table.js.map +1 -0
  275. package/dist/ir/type-system/internal/universe/clr-catalog.d.ts +44 -0
  276. package/dist/ir/type-system/internal/universe/clr-catalog.d.ts.map +1 -0
  277. package/dist/ir/type-system/internal/universe/clr-catalog.js +1192 -0
  278. package/dist/ir/type-system/internal/universe/clr-catalog.js.map +1 -0
  279. package/dist/ir/type-system/internal/universe/index.d.ts +26 -0
  280. package/dist/ir/type-system/internal/universe/index.d.ts.map +1 -0
  281. package/dist/ir/type-system/internal/universe/index.js +30 -0
  282. package/dist/ir/type-system/internal/universe/index.js.map +1 -0
  283. package/dist/ir/type-system/internal/universe/resolution.d.ts +115 -0
  284. package/dist/ir/type-system/internal/universe/resolution.d.ts.map +1 -0
  285. package/dist/ir/type-system/internal/universe/resolution.js +181 -0
  286. package/dist/ir/type-system/internal/universe/resolution.js.map +1 -0
  287. package/dist/ir/type-system/internal/universe/source-catalog.d.ts +64 -0
  288. package/dist/ir/type-system/internal/universe/source-catalog.d.ts.map +1 -0
  289. package/dist/ir/type-system/internal/universe/source-catalog.js +96 -0
  290. package/dist/ir/type-system/internal/universe/source-catalog.js.map +1 -0
  291. package/dist/ir/type-system/internal/universe/types.d.ts +436 -0
  292. package/dist/ir/type-system/internal/universe/types.d.ts.map +1 -0
  293. package/dist/ir/type-system/internal/universe/types.js +69 -0
  294. package/dist/ir/type-system/internal/universe/types.js.map +1 -0
  295. package/dist/ir/type-system/internal/universe/unified-universe.d.ts +70 -0
  296. package/dist/ir/type-system/internal/universe/unified-universe.d.ts.map +1 -0
  297. package/dist/ir/type-system/internal/universe/unified-universe.js +319 -0
  298. package/dist/ir/type-system/internal/universe/unified-universe.js.map +1 -0
  299. package/dist/ir/type-system/type-system.d.ts +617 -0
  300. package/dist/ir/type-system/type-system.d.ts.map +1 -0
  301. package/dist/ir/type-system/type-system.js +2579 -0
  302. package/dist/ir/type-system/type-system.js.map +1 -0
  303. package/dist/ir/type-system/types.d.ts +176 -0
  304. package/dist/ir/type-system/types.d.ts.map +1 -0
  305. package/dist/ir/type-system/types.js +80 -0
  306. package/dist/ir/type-system/types.js.map +1 -0
  307. package/dist/ir/types/expressions.d.ts +35 -7
  308. package/dist/ir/types/expressions.d.ts.map +1 -1
  309. package/dist/ir/types/helpers.d.ts +22 -2
  310. package/dist/ir/types/helpers.d.ts.map +1 -1
  311. package/dist/ir/types/index.d.ts +4 -2
  312. package/dist/ir/types/index.d.ts.map +1 -1
  313. package/dist/ir/types/index.js +1 -0
  314. package/dist/ir/types/index.js.map +1 -1
  315. package/dist/ir/types/ir-substitution.d.ts +144 -0
  316. package/dist/ir/types/ir-substitution.d.ts.map +1 -0
  317. package/dist/ir/types/ir-substitution.js +569 -0
  318. package/dist/ir/types/ir-substitution.js.map +1 -0
  319. package/dist/ir/types/ir-types.d.ts +10 -4
  320. package/dist/ir/types/ir-types.d.ts.map +1 -1
  321. package/dist/ir/types/numeric-helpers.d.ts +2 -1
  322. package/dist/ir/types/numeric-helpers.d.ts.map +1 -1
  323. package/dist/ir/types/numeric-helpers.js +9 -3
  324. package/dist/ir/types/numeric-helpers.js.map +1 -1
  325. package/dist/ir/types/statements.d.ts +22 -1
  326. package/dist/ir/types/statements.d.ts.map +1 -1
  327. package/dist/ir/types.d.ts +1 -1
  328. package/dist/ir/types.d.ts.map +1 -1
  329. package/dist/ir/types.js.map +1 -1
  330. package/dist/ir/validation/anonymous-type-lowering-pass.d.ts.map +1 -1
  331. package/dist/ir/validation/anonymous-type-lowering-pass.js +153 -8
  332. package/dist/ir/validation/anonymous-type-lowering-pass.js.map +1 -1
  333. package/dist/ir/validation/arrow-return-finalization-pass.d.ts +28 -0
  334. package/dist/ir/validation/arrow-return-finalization-pass.d.ts.map +1 -0
  335. package/dist/ir/validation/arrow-return-finalization-pass.js +416 -0
  336. package/dist/ir/validation/arrow-return-finalization-pass.js.map +1 -0
  337. package/dist/ir/validation/attribute-collection-pass.d.ts.map +1 -1
  338. package/dist/ir/validation/attribute-collection-pass.js +40 -6
  339. package/dist/ir/validation/attribute-collection-pass.js.map +1 -1
  340. package/dist/ir/validation/attribute-collection-pass.test.js +43 -36
  341. package/dist/ir/validation/attribute-collection-pass.test.js.map +1 -1
  342. package/dist/ir/validation/char-validation-pass.d.ts +26 -0
  343. package/dist/ir/validation/char-validation-pass.d.ts.map +1 -0
  344. package/dist/ir/validation/char-validation-pass.js +495 -0
  345. package/dist/ir/validation/char-validation-pass.js.map +1 -0
  346. package/dist/ir/validation/index.d.ts +3 -0
  347. package/dist/ir/validation/index.d.ts.map +1 -1
  348. package/dist/ir/validation/index.js +3 -0
  349. package/dist/ir/validation/index.js.map +1 -1
  350. package/dist/ir/validation/numeric-coercion-pass.d.ts +22 -16
  351. package/dist/ir/validation/numeric-coercion-pass.d.ts.map +1 -1
  352. package/dist/ir/validation/numeric-coercion-pass.js +159 -51
  353. package/dist/ir/validation/numeric-coercion-pass.js.map +1 -1
  354. package/dist/ir/validation/numeric-invariants.test.js +72 -108
  355. package/dist/ir/validation/numeric-invariants.test.js.map +1 -1
  356. package/dist/ir/validation/numeric-proof-pass.d.ts.map +1 -1
  357. package/dist/ir/validation/numeric-proof-pass.js +71 -23
  358. package/dist/ir/validation/numeric-proof-pass.js.map +1 -1
  359. package/dist/ir/validation/rest-type-synthesis-pass.d.ts +24 -0
  360. package/dist/ir/validation/rest-type-synthesis-pass.d.ts.map +1 -0
  361. package/dist/ir/validation/rest-type-synthesis-pass.js +417 -0
  362. package/dist/ir/validation/rest-type-synthesis-pass.js.map +1 -0
  363. package/dist/ir/validation/soundness-gate.d.ts +11 -1
  364. package/dist/ir/validation/soundness-gate.d.ts.map +1 -1
  365. package/dist/ir/validation/soundness-gate.js +42 -10
  366. package/dist/ir/validation/soundness-gate.js.map +1 -1
  367. package/dist/ir/validation/soundness-gate.test.js +19 -2
  368. package/dist/ir/validation/soundness-gate.test.js.map +1 -1
  369. package/dist/ir/validation/virtual-marking-pass.d.ts +16 -0
  370. package/dist/ir/validation/virtual-marking-pass.d.ts.map +1 -0
  371. package/dist/ir/validation/virtual-marking-pass.js +77 -0
  372. package/dist/ir/validation/virtual-marking-pass.js.map +1 -0
  373. package/dist/ir/validation/yield-lowering-pass.test.js +2 -2
  374. package/dist/ir/validation/yield-lowering-pass.test.js.map +1 -1
  375. package/dist/program/bindings.d.ts +44 -0
  376. package/dist/program/bindings.d.ts.map +1 -1
  377. package/dist/program/bindings.js +248 -2
  378. package/dist/program/bindings.js.map +1 -1
  379. package/dist/program/bindings.test.js +30 -0
  380. package/dist/program/bindings.test.js.map +1 -1
  381. package/dist/program/creation.d.ts.map +1 -1
  382. package/dist/program/creation.js +158 -4
  383. package/dist/program/creation.js.map +1 -1
  384. package/dist/program/dependency-graph.d.ts.map +1 -1
  385. package/dist/program/dependency-graph.js +33 -26
  386. package/dist/program/dependency-graph.js.map +1 -1
  387. package/dist/program/index.d.ts +1 -1
  388. package/dist/program/index.d.ts.map +1 -1
  389. package/dist/program/types.d.ts +7 -8
  390. package/dist/program/types.d.ts.map +1 -1
  391. package/dist/resolver/clr-bindings-resolver.d.ts +6 -0
  392. package/dist/resolver/clr-bindings-resolver.d.ts.map +1 -1
  393. package/dist/resolver/clr-bindings-resolver.js +185 -39
  394. package/dist/resolver/clr-bindings-resolver.js.map +1 -1
  395. package/dist/resolver/clr-bindings-resolver.test.d.ts +2 -0
  396. package/dist/resolver/clr-bindings-resolver.test.d.ts.map +1 -0
  397. package/dist/resolver/clr-bindings-resolver.test.js +161 -0
  398. package/dist/resolver/clr-bindings-resolver.test.js.map +1 -0
  399. package/dist/resolver/import-resolution.d.ts +16 -1
  400. package/dist/resolver/import-resolution.d.ts.map +1 -1
  401. package/dist/resolver/import-resolution.js +29 -12
  402. package/dist/resolver/import-resolution.js.map +1 -1
  403. package/dist/resolver/namespace.d.ts +2 -1
  404. package/dist/resolver/namespace.d.ts.map +1 -1
  405. package/dist/resolver/namespace.js +5 -2
  406. package/dist/resolver/namespace.js.map +1 -1
  407. package/dist/resolver/namespace.test.js +6 -6
  408. package/dist/resolver/naming-policy.d.ts +20 -0
  409. package/dist/resolver/naming-policy.d.ts.map +1 -0
  410. package/dist/resolver/naming-policy.js +40 -0
  411. package/dist/resolver/naming-policy.js.map +1 -0
  412. package/dist/resolver/naming.d.ts +2 -5
  413. package/dist/resolver/naming.d.ts.map +1 -1
  414. package/dist/resolver/naming.js +3 -20
  415. package/dist/resolver/naming.js.map +1 -1
  416. package/dist/resolver.d.ts +2 -0
  417. package/dist/resolver.d.ts.map +1 -1
  418. package/dist/resolver.js +1 -0
  419. package/dist/resolver.js.map +1 -1
  420. package/dist/resolver.test.js +8 -3
  421. package/dist/resolver.test.js.map +1 -1
  422. package/dist/symbol-table/builder.d.ts +3 -1
  423. package/dist/symbol-table/builder.d.ts.map +1 -1
  424. package/dist/symbol-table/builder.js +9 -8
  425. package/dist/symbol-table/builder.js.map +1 -1
  426. package/dist/symbol-table/types.d.ts +2 -2
  427. package/dist/symbol-table/types.d.ts.map +1 -1
  428. package/dist/types/diagnostic.d.ts +12 -2
  429. package/dist/types/diagnostic.d.ts.map +1 -1
  430. package/dist/types/diagnostic.js +5 -1
  431. package/dist/types/diagnostic.js.map +1 -1
  432. package/dist/validation/core-intrinsics.d.ts +18 -0
  433. package/dist/validation/core-intrinsics.d.ts.map +1 -0
  434. package/dist/validation/core-intrinsics.js +186 -0
  435. package/dist/validation/core-intrinsics.js.map +1 -0
  436. package/dist/validation/extension-methods.d.ts +17 -0
  437. package/dist/validation/extension-methods.d.ts.map +1 -0
  438. package/dist/validation/extension-methods.js +133 -0
  439. package/dist/validation/extension-methods.js.map +1 -0
  440. package/dist/validation/generics.d.ts.map +1 -1
  441. package/dist/validation/generics.js +1 -129
  442. package/dist/validation/generics.js.map +1 -1
  443. package/dist/validation/imports.js +1 -1
  444. package/dist/validation/imports.js.map +1 -1
  445. package/dist/validation/index.d.ts +2 -0
  446. package/dist/validation/index.d.ts.map +1 -1
  447. package/dist/validation/index.js +2 -0
  448. package/dist/validation/index.js.map +1 -1
  449. package/dist/validation/orchestrator.d.ts.map +1 -1
  450. package/dist/validation/orchestrator.js +4 -0
  451. package/dist/validation/orchestrator.js.map +1 -1
  452. package/dist/validation/static-safety.d.ts +1 -0
  453. package/dist/validation/static-safety.d.ts.map +1 -1
  454. package/dist/validation/static-safety.js +366 -96
  455. package/dist/validation/static-safety.js.map +1 -1
  456. package/dist/validator.test.js +123 -1
  457. package/dist/validator.test.js.map +1 -1
  458. package/package.json +2 -2
  459. package/dist/ir/type-converter/arrays.d.ts +0 -10
  460. package/dist/ir/type-converter/arrays.d.ts.map +0 -1
  461. package/dist/ir/type-converter/arrays.js.map +0 -1
  462. package/dist/ir/type-converter/converter.d.ts +0 -6
  463. package/dist/ir/type-converter/converter.d.ts.map +0 -1
  464. package/dist/ir/type-converter/converter.js +0 -6
  465. package/dist/ir/type-converter/converter.js.map +0 -1
  466. package/dist/ir/type-converter/functions.d.ts +0 -10
  467. package/dist/ir/type-converter/functions.d.ts.map +0 -1
  468. package/dist/ir/type-converter/functions.js +0 -15
  469. package/dist/ir/type-converter/functions.js.map +0 -1
  470. package/dist/ir/type-converter/index.d.ts +0 -7
  471. package/dist/ir/type-converter/index.d.ts.map +0 -1
  472. package/dist/ir/type-converter/index.js +0 -7
  473. package/dist/ir/type-converter/index.js.map +0 -1
  474. package/dist/ir/type-converter/inference.d.ts +0 -32
  475. package/dist/ir/type-converter/inference.d.ts.map +0 -1
  476. package/dist/ir/type-converter/inference.js +0 -297
  477. package/dist/ir/type-converter/inference.js.map +0 -1
  478. package/dist/ir/type-converter/literals.d.ts.map +0 -1
  479. package/dist/ir/type-converter/literals.js.map +0 -1
  480. package/dist/ir/type-converter/objects.d.ts +0 -16
  481. package/dist/ir/type-converter/objects.d.ts.map +0 -1
  482. package/dist/ir/type-converter/objects.js.map +0 -1
  483. package/dist/ir/type-converter/orchestrator.d.ts.map +0 -1
  484. package/dist/ir/type-converter/orchestrator.js.map +0 -1
  485. package/dist/ir/type-converter/patterns.d.ts +0 -10
  486. package/dist/ir/type-converter/patterns.d.ts.map +0 -1
  487. package/dist/ir/type-converter/patterns.js.map +0 -1
  488. package/dist/ir/type-converter/primitives.d.ts.map +0 -1
  489. package/dist/ir/type-converter/primitives.js.map +0 -1
  490. package/dist/ir/type-converter/references.d.ts.map +0 -1
  491. package/dist/ir/type-converter/references.js +0 -371
  492. package/dist/ir/type-converter/references.js.map +0 -1
  493. package/dist/ir/type-converter/unions-intersections.d.ts +0 -14
  494. package/dist/ir/type-converter/unions-intersections.d.ts.map +0 -1
  495. package/dist/ir/type-converter/unions-intersections.js +0 -22
  496. package/dist/ir/type-converter/unions-intersections.js.map +0 -1
  497. package/dist/ir/type-converter/utility-types.d.ts.map +0 -1
  498. package/dist/ir/type-converter/utility-types.js +0 -528
  499. package/dist/ir/type-converter/utility-types.js.map +0 -1
  500. package/dist/ir/type-converter/utility-types.test.d.ts.map +0 -1
  501. package/dist/ir/type-converter/utility-types.test.js.map +0 -1
  502. package/dist/ir/type-converter.d.ts +0 -6
  503. package/dist/ir/type-converter.d.ts.map +0 -1
  504. package/dist/ir/type-converter.js +0 -6
  505. package/dist/ir/type-converter.js.map +0 -1
  506. /package/dist/ir/{type-converter → type-system/internal/type-converter}/literals.js +0 -0
  507. /package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.d.ts +0 -0
@@ -1,421 +1,384 @@
1
1
  /**
2
2
  * Call and new expression converters
3
+ *
4
+ * ALICE'S SPEC: All call resolution goes through TypeSystem.resolveCall().
5
+ * NO FALLBACKS ALLOWED. If TypeSystem can't resolve, return unknownType.
3
6
  */
4
7
  import * as ts from "typescript";
5
- import { getInferredType, getSourceSpan, extractTypeArguments, checkIfRequiresSpecialization, } from "./helpers.js";
8
+ import { getSourceSpan, extractTypeArguments, checkIfRequiresSpecialization, } from "./helpers.js";
6
9
  import { convertExpression } from "../../expression-converter.js";
7
- import { convertType, convertTsTypeToIr } from "../../type-converter.js";
8
10
  /**
9
- * Extract argument passing modes from resolved signature
10
- * Returns array aligned with arguments, indicating ref/out/in/value for each
11
+ * Extract argument passing modes from resolved signature.
12
+ * Returns array aligned with arguments, indicating ref/out/in/value for each.
13
+ *
14
+ * ALICE'S SPEC: Uses TypeSystem to get parameter modes.
15
+ * Parameter modes were normalized in Binding at registration time.
11
16
  */
12
- const extractArgumentPassing = (node, checker) => {
13
- try {
14
- const signature = checker.getResolvedSignature(node);
15
- if (!signature || !signature.declaration) {
16
- return undefined;
17
- }
18
- const decl = signature.declaration;
19
- let parameters = [];
20
- // Extract parameters from declaration
21
- if (ts.isFunctionDeclaration(decl) ||
22
- ts.isMethodDeclaration(decl) ||
23
- ts.isConstructorDeclaration(decl) ||
24
- ts.isArrowFunction(decl) ||
25
- ts.isFunctionExpression(decl)) {
26
- parameters = decl.parameters;
27
- }
28
- if (parameters.length === 0) {
29
- return undefined;
30
- }
31
- // Build passing mode for each parameter
32
- const passingModes = [];
33
- for (const param of parameters) {
34
- let passing = "value";
35
- // Check if parameter type is ref<T>, out<T>, or in<T>
36
- if (param.type &&
37
- ts.isTypeReferenceNode(param.type) &&
38
- ts.isIdentifier(param.type.typeName)) {
39
- const typeName = param.type.typeName.text;
40
- if ((typeName === "ref" || typeName === "out" || typeName === "in") &&
41
- param.type.typeArguments &&
42
- param.type.typeArguments.length > 0) {
43
- passing = typeName === "in" ? "in" : typeName;
44
- }
45
- }
46
- passingModes.push(passing);
47
- }
48
- return passingModes;
49
- }
50
- catch {
17
+ const extractArgumentPassing = (node, ctx) => {
18
+ // Get the TypeSystem
19
+ const typeSystem = ctx.typeSystem;
20
+ // Handle both CallExpression and NewExpression
21
+ const sigId = ts.isCallExpression(node)
22
+ ? ctx.binding.resolveCallSignature(node)
23
+ : ctx.binding.resolveConstructorSignature(node);
24
+ if (!sigId)
51
25
  return undefined;
52
- }
26
+ // Use TypeSystem.resolveCall() to get parameter modes
27
+ const resolved = typeSystem.resolveCall({
28
+ sigId,
29
+ argumentCount: ts.isCallExpression(node)
30
+ ? node.arguments.length
31
+ : (node.arguments?.length ?? 0),
32
+ });
33
+ // Return parameter modes from TypeSystem (already normalized in Binding)
34
+ return resolved.parameterModes;
53
35
  };
54
36
  /**
55
- * Safely convert a ts.Type to IrType
37
+ * Get the declared return type from a call or new expression's signature.
38
+ *
39
+ * This function extracts the return type from the **signature declaration's TypeNode**,
40
+ * NOT from TypeScript's inferred type. This is critical for preserving CLR type aliases.
41
+ *
42
+ * For generic methods, type parameters are substituted using the receiver's type arguments.
43
+ * For example: `dict.get(key)` where `dict: Dictionary<int, Todo>` returns `Todo | undefined`,
44
+ * not `TValue | undefined`.
45
+ *
46
+ * Returns undefined if:
47
+ * - No signature found
48
+ * - No declaration on signature
49
+ * - No return type annotation on declaration
56
50
  */
57
- const convertTsTypeToIrSafe = (tsType, node, checker) => {
58
- try {
59
- const typeNode = checker.typeToTypeNode(tsType, node, ts.NodeBuilderFlags.None);
60
- return typeNode
61
- ? convertType(typeNode, checker)
62
- : convertTsTypeToIr(tsType, checker);
51
+ // DELETED: getReturnTypeFromFunctionType - Was part of fallback path
52
+ // DELETED: getCalleesDeclaredType - Was part of fallback path
53
+ // Alice's spec: TypeSystem.resolveCall() is the single source of truth.
54
+ /**
55
+ * Walk a property access chain and build a qualified name.
56
+ * For `Foo.Bar.Baz`, returns "Foo.Bar.Baz" by walking the AST identifiers.
57
+ * This avoids getText() which bakes source formatting into type identity.
58
+ */
59
+ const buildQualifiedName = (expr) => {
60
+ if (ts.isIdentifier(expr)) {
61
+ return expr.text;
63
62
  }
64
- catch {
65
- return undefined;
63
+ if (ts.isPropertyAccessExpression(expr)) {
64
+ const parts = [];
65
+ let current = expr;
66
+ while (ts.isPropertyAccessExpression(current)) {
67
+ parts.unshift(current.name.text);
68
+ current = current.expression;
69
+ }
70
+ if (ts.isIdentifier(current)) {
71
+ parts.unshift(current.text);
72
+ return parts.join(".");
73
+ }
66
74
  }
75
+ return undefined;
67
76
  };
77
+ // DELETED: getDeclaredReturnTypeFallback - Alice's spec: no fallbacks allowed
78
+ // TypeSystem.resolveCall() is the single source of truth.
79
+ // DELETED: normalizeReceiverToNominal - No longer needed without NominalEnv fallback
80
+ // DELETED: getDeclaredReturnTypeNominalEnvFallback - Alice's spec: no fallbacks allowed
81
+ // TypeSystem.resolveCall() is the single source of truth.
68
82
  /**
69
- * Extract type predicate narrowing metadata from a call expression.
70
- * Returns narrowing info if the callee is a type predicate function (x is T).
83
+ * Get the declared return type from a call or new expression's signature.
84
+ *
85
+ * ALICE'S SPEC: Uses TypeSystem.resolveCall() EXCLUSIVELY.
86
+ * NO FALLBACKS. If TypeSystem can't resolve, return unknownType.
87
+ * This ensures any missing TypeSystem functionality surfaces as test failures.
71
88
  */
72
- const extractNarrowing = (node, checker) => {
73
- try {
74
- const sig = checker.getResolvedSignature(node);
75
- if (!sig)
76
- return undefined;
77
- const pred = checker.getTypePredicateOfSignature(sig);
78
- // We only handle "param is T" predicates (not "this is T")
79
- if (pred &&
80
- pred.kind === ts.TypePredicateKind.Identifier &&
81
- pred.parameterIndex !== undefined &&
82
- pred.type) {
83
- const targetType = convertTsTypeToIrSafe(pred.type, node, checker);
84
- if (targetType) {
89
+ export const getDeclaredReturnType = (node, ctx, receiverIrType) => {
90
+ const DEBUG = process.env.DEBUG_RETURN_TYPE === "1";
91
+ const methodName = ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)
92
+ ? node.expression.name.text
93
+ : undefined;
94
+ if (DEBUG && methodName) {
95
+ console.log("[getDeclaredReturnType]", methodName, "receiver:", receiverIrType);
96
+ }
97
+ // Handle new expressions specially - they construct the type from the expression
98
+ if (ts.isNewExpression(node)) {
99
+ // For new expressions with explicit type arguments
100
+ if (node.typeArguments && node.typeArguments.length > 0) {
101
+ const typeName = buildQualifiedName(node.expression);
102
+ if (typeName) {
103
+ // PHASE 4 (Alice's spec): Use captureTypeSyntax + typeFromSyntax
104
+ const typeSystem = ctx.typeSystem;
85
105
  return {
86
- kind: "typePredicate",
87
- argIndex: pred.parameterIndex,
88
- targetType,
106
+ kind: "referenceType",
107
+ name: typeName,
108
+ typeArguments: node.typeArguments.map((ta) => typeSystem.typeFromSyntax(ctx.binding.captureTypeSyntax(ta))),
89
109
  };
90
110
  }
91
111
  }
112
+ // For constructors without type arguments, use the class name
113
+ const typeName = buildQualifiedName(node.expression);
114
+ if (typeName) {
115
+ return { kind: "referenceType", name: typeName };
116
+ }
117
+ return undefined;
118
+ }
119
+ // For call expressions, use TypeSystem.resolveCall() EXCLUSIVELY
120
+ const typeSystem = ctx.typeSystem;
121
+ const sigId = ctx.binding.resolveCallSignature(node);
122
+ if (!sigId) {
123
+ if (DEBUG && methodName)
124
+ console.log("[getDeclaredReturnType]", methodName, "No signature resolved");
92
125
  return undefined;
93
126
  }
94
- catch {
127
+ // Get argument count for totality
128
+ const argumentCount = node.arguments.length;
129
+ // Extract explicit type arguments from call site if any
130
+ // PHASE 4 (Alice's spec): Use captureTypeSyntax + typeFromSyntax
131
+ const explicitTypeArgs = node.typeArguments
132
+ ? node.typeArguments.map((ta) => typeSystem.typeFromSyntax(ctx.binding.captureTypeSyntax(ta)))
133
+ : undefined;
134
+ // Use TypeSystem.resolveCall() - guaranteed to return a result
135
+ // NO FALLBACK: If TypeSystem returns unknownType, that's the answer
136
+ const resolved = typeSystem.resolveCall({
137
+ sigId,
138
+ argumentCount,
139
+ receiverType: receiverIrType,
140
+ explicitTypeArgs,
141
+ });
142
+ if (DEBUG && methodName) {
143
+ console.log("[getDeclaredReturnType]", methodName, "TypeSystem returned:", resolved.returnType);
144
+ }
145
+ // Return TypeSystem's answer directly - no fallbacks
146
+ return resolved.returnType;
147
+ };
148
+ const extractArgumentPassingFromParameterModifiers = (modifiers, argCount) => {
149
+ if (modifiers.length === 0)
95
150
  return undefined;
151
+ const passing = Array(argCount).fill("value");
152
+ for (const mod of modifiers) {
153
+ if (mod.index >= 0 && mod.index < argCount) {
154
+ passing[mod.index] = mod.modifier;
155
+ }
96
156
  }
157
+ return passing;
97
158
  };
98
159
  /**
99
- * Build a substitution map from type parameter names to their instantiated TypeNodes.
160
+ * Extract argument passing modes from CLR bindings for the *selected overload*.
100
161
  *
101
- * For a call like `dict.add(key, value)` where `dict: Dictionary<int, Todo>`,
102
- * this returns a map: { "TKey" -> int TypeNode, "TValue" -> Todo TypeNode }
162
+ * CRITICAL: Methods can be overloaded, and overloads can differ in ref/out/in modifiers.
163
+ * We must not attach a single overload's modifiers to the member access itself.
103
164
  *
104
- * The key insight is that the RECEIVER's type (Dictionary<int, Todo>) preserves
105
- * the type arguments as TypeNodes, which in turn preserve CLR type aliases.
106
- * TypeScript's type instantiation mechanism loses aliasSymbol, but TypeNodes don't.
165
+ * This resolver selects the best-matching binding overload using the call's argument
166
+ * types, then applies that overload's parameterModifiers.
107
167
  */
108
- const buildTypeParameterSubstitutionMap = (node, checker) => {
109
- // For method calls, get the receiver's type arguments
110
- // e.g., for dict.add(...), get Dictionary<int, Todo>'s type arguments
111
- if (ts.isCallExpression(node) &&
112
- ts.isPropertyAccessExpression(node.expression)) {
113
- const receiver = node.expression.expression;
114
- const receiverType = checker.getTypeAtLocation(receiver);
115
- // Get the class/interface/type alias declaration that defines the type parameters
116
- // For type aliases like Dictionary_2<TKey, TValue>, use aliasSymbol
117
- // For classes/interfaces, use getSymbol()
118
- const symbol = receiverType.aliasSymbol ?? receiverType.getSymbol();
119
- if (!symbol)
120
- return undefined;
121
- const declarations = symbol.getDeclarations();
122
- if (!declarations || declarations.length === 0)
123
- return undefined;
124
- // Find the class/interface/type alias declaration with type parameters
125
- let typeParamDecls;
126
- for (const decl of declarations) {
127
- if (ts.isClassDeclaration(decl) && decl.typeParameters) {
128
- typeParamDecls = decl.typeParameters;
129
- break;
168
+ const extractArgumentPassingFromBinding = (callee, argCount, ctx, parameterTypes, argTypes) => {
169
+ if (callee.kind !== "memberAccess" || !callee.memberBinding)
170
+ return undefined;
171
+ // Fast path: already-resolved modifiers (extension methods or non-overloaded members).
172
+ const directMods = callee.memberBinding.parameterModifiers;
173
+ if (directMods && directMods.length > 0) {
174
+ return extractArgumentPassingFromParameterModifiers(directMods, argCount);
175
+ }
176
+ // No member binding no CLR parameter modifiers.
177
+ const binding = callee.memberBinding;
178
+ const overloadsAll = ctx.bindings.getClrMemberOverloads(binding.assembly, binding.type, binding.member);
179
+ if (!overloadsAll || overloadsAll.length === 0)
180
+ return undefined;
181
+ const calledName = typeof callee.property === "string" ? callee.property : undefined;
182
+ const overloads = calledName
183
+ ? overloadsAll.filter((m) => m.alias === calledName || m.name === calledName)
184
+ : overloadsAll;
185
+ if (overloads.length === 0)
186
+ return undefined;
187
+ const matchTypes = parameterTypes ?? argTypes;
188
+ const hasMatchTypes = matchTypes && matchTypes.some((t) => t !== undefined);
189
+ const splitSignatureTypeList = (str) => {
190
+ const result = [];
191
+ let depth = 0;
192
+ let current = "";
193
+ for (const char of str) {
194
+ if (char === "[") {
195
+ depth++;
196
+ current += char;
130
197
  }
131
- if (ts.isInterfaceDeclaration(decl) && decl.typeParameters) {
132
- typeParamDecls = decl.typeParameters;
133
- break;
198
+ else if (char === "]") {
199
+ depth--;
200
+ current += char;
134
201
  }
135
- if (ts.isTypeAliasDeclaration(decl) && decl.typeParameters) {
136
- typeParamDecls = decl.typeParameters;
137
- break;
202
+ else if (char === "," && depth === 0) {
203
+ result.push(current.trim());
204
+ current = "";
138
205
  }
139
- }
140
- if (!typeParamDecls || typeParamDecls.length === 0)
141
- return undefined;
142
- // Get the type arguments from the receiver's type
143
- // IMPORTANT: We must trace back to the ORIGINAL source code AST to preserve
144
- // CLR type aliases like `int`. TypeScript's typeToTypeNode() does NOT preserve
145
- // type aliases - it synthesizes primitive keywords like NumberKeyword instead.
146
- //
147
- // Look for the variable declaration that has type arguments in:
148
- // 1. Explicit type annotation: const dict: Dictionary<int, Todo> = ...
149
- // 2. NewExpression initializer: const dict = new Dictionary<int, Todo>()
150
- // 3. Other declaration forms (property, parameter)
151
- const receiverSymbol = checker.getSymbolAtLocation(receiver);
152
- if (receiverSymbol) {
153
- const receiverDecls = receiverSymbol.getDeclarations();
154
- if (receiverDecls) {
155
- for (const decl of receiverDecls) {
156
- // Helper to build substitution map from type argument nodes
157
- const buildMapFromTypeArgs = (typeArgNodes) => {
158
- if (typeParamDecls &&
159
- typeArgNodes.length === typeParamDecls.length) {
160
- const substitutionMap = new Map();
161
- for (let i = 0; i < typeParamDecls.length; i++) {
162
- const paramDecl = typeParamDecls[i];
163
- const argNode = typeArgNodes[i];
164
- if (paramDecl && argNode) {
165
- substitutionMap.set(paramDecl.name.text, argNode);
166
- }
167
- }
168
- return substitutionMap;
169
- }
170
- return undefined;
171
- };
172
- // Check explicit type annotation first
173
- if (ts.isVariableDeclaration(decl) && decl.type) {
174
- if (ts.isTypeReferenceNode(decl.type) && decl.type.typeArguments) {
175
- const result = buildMapFromTypeArgs(decl.type.typeArguments);
176
- if (result)
177
- return result;
178
- }
179
- }
180
- // Check initializer: new Dictionary<int, Todo>()
181
- // This handles: const todos = new Dictionary<int, Todo>();
182
- if (ts.isVariableDeclaration(decl) && decl.initializer) {
183
- // Handle direct NewExpression
184
- if (ts.isNewExpression(decl.initializer) &&
185
- decl.initializer.typeArguments) {
186
- const result = buildMapFromTypeArgs(decl.initializer.typeArguments);
187
- if (result)
188
- return result;
189
- }
190
- // Handle AsExpression (type assertion): new List<int>() as List<int>
191
- // The type arguments are in the AsExpression's type, not the NewExpression
192
- if (ts.isAsExpression(decl.initializer)) {
193
- const asType = decl.initializer.type;
194
- if (ts.isTypeReferenceNode(asType) && asType.typeArguments) {
195
- const result = buildMapFromTypeArgs(asType.typeArguments);
196
- if (result)
197
- return result;
198
- }
199
- }
200
- }
201
- // Also check property declarations with type annotation
202
- if (ts.isPropertyDeclaration(decl) &&
203
- decl.type &&
204
- ts.isTypeReferenceNode(decl.type) &&
205
- decl.type.typeArguments) {
206
- const result = buildMapFromTypeArgs(decl.type.typeArguments);
207
- if (result)
208
- return result;
209
- }
210
- // Check property declaration initializer
211
- if (ts.isPropertyDeclaration(decl) && decl.initializer) {
212
- if (ts.isNewExpression(decl.initializer) &&
213
- decl.initializer.typeArguments) {
214
- const result = buildMapFromTypeArgs(decl.initializer.typeArguments);
215
- if (result)
216
- return result;
217
- }
218
- }
219
- // Check parameter declarations
220
- if (ts.isParameter(decl) &&
221
- decl.type &&
222
- ts.isTypeReferenceNode(decl.type) &&
223
- decl.type.typeArguments) {
224
- const result = buildMapFromTypeArgs(decl.type.typeArguments);
225
- if (result)
226
- return result;
227
- }
228
- }
206
+ else {
207
+ current += char;
229
208
  }
230
209
  }
231
- }
232
- return undefined;
233
- };
234
- /**
235
- * Substitute type parameters in a TypeNode using the substitution map.
236
- * For a type like `TKey`, returns the substituted TypeNode (e.g., `int`).
237
- * For complex types like `List<TKey>`, recursively substitutes.
238
- *
239
- * Returns the substituted TypeNode, or undefined if no substitution needed.
240
- */
241
- const substituteTypeNode = (typeNode, substitutionMap, checker) => {
242
- // Handle type reference nodes (most common case)
243
- if (ts.isTypeReferenceNode(typeNode)) {
244
- const typeName = ts.isIdentifier(typeNode.typeName)
245
- ? typeNode.typeName.text
246
- : typeNode.typeName.getText();
247
- // Direct substitution: if this is a type parameter, substitute it
248
- const substitution = substitutionMap.get(typeName);
249
- if (substitution) {
250
- return substitution;
210
+ if (current.trim())
211
+ result.push(current.trim());
212
+ return result;
213
+ };
214
+ const parseParameterTypes = (sig) => {
215
+ if (!sig)
216
+ return [];
217
+ const paramsMatch = sig.match(/\|\(([^)]*)\):/);
218
+ const paramsStr = paramsMatch?.[1]?.trim();
219
+ if (!paramsStr)
220
+ return [];
221
+ return splitSignatureTypeList(paramsStr).map((s) => s.trim());
222
+ };
223
+ const extractSimpleClrName = (typeName) => {
224
+ let t = typeName.trim();
225
+ if (t.endsWith("&"))
226
+ t = t.slice(0, -1);
227
+ if (t.endsWith("[]"))
228
+ t = t.slice(0, -2);
229
+ const bracket = t.indexOf("[");
230
+ if (bracket >= 0)
231
+ t = t.slice(0, bracket);
232
+ const lastDot = t.lastIndexOf(".");
233
+ if (lastDot >= 0)
234
+ t = t.slice(lastDot + 1);
235
+ return t;
236
+ };
237
+ const primitiveToClrSimpleName = (name) => {
238
+ switch (name) {
239
+ case "string":
240
+ return "String";
241
+ case "boolean":
242
+ case "bool":
243
+ return "Boolean";
244
+ case "char":
245
+ return "Char";
246
+ case "byte":
247
+ return "Byte";
248
+ case "sbyte":
249
+ return "SByte";
250
+ case "short":
251
+ return "Int16";
252
+ case "ushort":
253
+ return "UInt16";
254
+ case "int":
255
+ return "Int32";
256
+ case "uint":
257
+ return "UInt32";
258
+ case "long":
259
+ return "Int64";
260
+ case "ulong":
261
+ return "UInt64";
262
+ case "float":
263
+ return "Single";
264
+ case "double":
265
+ return "Double";
266
+ case "decimal":
267
+ return "Decimal";
268
+ default:
269
+ return undefined;
251
270
  }
252
- // Recursive substitution: if this is a generic type, substitute its type arguments
253
- if (typeNode.typeArguments && typeNode.typeArguments.length > 0) {
254
- let anySubstituted = false;
255
- const newTypeArgs = [];
256
- for (const arg of typeNode.typeArguments) {
257
- const substituted = substituteTypeNode(arg, substitutionMap, checker);
258
- if (substituted) {
259
- newTypeArgs.push(substituted);
260
- anySubstituted = true;
261
- }
262
- else {
263
- newTypeArgs.push(arg);
264
- }
271
+ };
272
+ const collectMatchNames = (t) => {
273
+ switch (t.kind) {
274
+ case "primitiveType": {
275
+ const mapped = primitiveToClrSimpleName(t.name);
276
+ return mapped ? [mapped] : [];
265
277
  }
266
- if (anySubstituted) {
267
- // Create a new type reference with substituted type arguments
268
- // We use the factory to create a new node
269
- return ts.factory.createTypeReferenceNode(typeNode.typeName, newTypeArgs);
278
+ case "referenceType": {
279
+ const lastDot = t.name.lastIndexOf(".");
280
+ const simple = lastDot >= 0 ? t.name.slice(lastDot + 1) : t.name;
281
+ return [simple.replace(/\$instance$/, "").replace(/^\_\_/, "").replace(/\$views$/, "")];
270
282
  }
283
+ case "unionType":
284
+ return Array.from(new Set(t.types.flatMap((x) => collectMatchNames(x))));
285
+ case "intersectionType":
286
+ return Array.from(new Set(t.types.flatMap((x) => collectMatchNames(x))));
287
+ default:
288
+ return [];
271
289
  }
272
- }
273
- // Handle array types: T[] -> int[]
274
- if (ts.isArrayTypeNode(typeNode)) {
275
- const substituted = substituteTypeNode(typeNode.elementType, substitutionMap, checker);
276
- if (substituted) {
277
- return ts.factory.createArrayTypeNode(substituted);
278
- }
279
- }
280
- // Handle union types: T | null -> int | null
281
- if (ts.isUnionTypeNode(typeNode)) {
282
- let anySubstituted = false;
283
- const newTypes = [];
284
- for (const member of typeNode.types) {
285
- const substituted = substituteTypeNode(member, substitutionMap, checker);
286
- if (substituted) {
287
- newTypes.push(substituted);
288
- anySubstituted = true;
290
+ };
291
+ const modifiersKey = (m) => {
292
+ const mods = m.parameterModifiers ?? [];
293
+ if (mods.length === 0)
294
+ return "";
295
+ return [...mods]
296
+ .slice()
297
+ .sort((a, b) => a.index - b.index)
298
+ .map((mod) => `${mod.index}:${mod.modifier}`)
299
+ .join(",");
300
+ };
301
+ const scoreCandidate = (m) => {
302
+ if (!hasMatchTypes)
303
+ return 0;
304
+ const paramTypes = parseParameterTypes(m.signature);
305
+ let score = 0;
306
+ for (let i = 0; i < argCount; i++) {
307
+ const expected = matchTypes?.[i];
308
+ if (!expected)
309
+ continue;
310
+ const expectedNames = collectMatchNames(expected);
311
+ if (expectedNames.length === 0)
312
+ continue;
313
+ const paramType = paramTypes[i];
314
+ if (!paramType)
315
+ continue;
316
+ const paramName = extractSimpleClrName(paramType);
317
+ if (expectedNames.includes(paramName)) {
318
+ score += 10;
289
319
  }
290
320
  else {
291
- newTypes.push(member);
321
+ score -= 3;
292
322
  }
293
323
  }
294
- if (anySubstituted) {
295
- return ts.factory.createUnionTypeNode(newTypes);
296
- }
297
- }
298
- return undefined;
299
- };
300
- /**
301
- * Extract parameter types from resolved signature.
302
- * Used for threading expectedType to array literal arguments etc.
303
- *
304
- * Uses the resolved signature to get INSTANTIATED parameter types.
305
- * For example, for `dict.add(key, value)` where `dict: Dictionary<int, Todo>`,
306
- * this returns the instantiated types [int, Todo], not the formal types [TKey, TValue].
307
- *
308
- * CLR type aliases (like `int`) are preserved by:
309
- * 1. For non-type-parameter declarations: use the declaration's type node directly
310
- * 2. For type parameters: use TypeNode substitution to preserve CLR aliases
311
- *
312
- * The key insight is that TypeScript's type instantiation mechanism loses
313
- * aliasSymbol, but the original TypeNodes in variable declarations preserve
314
- * the type aliases. We trace back to those TypeNodes and substitute.
315
- */
316
- const extractParameterTypes = (node, checker) => {
317
- try {
318
- const signature = checker.getResolvedSignature(node);
319
- if (!signature) {
320
- return undefined;
321
- }
322
- const sigParams = signature.getParameters();
323
- if (sigParams.length === 0) {
324
- return undefined;
324
+ return score;
325
+ };
326
+ // Discard candidates that can't accept the provided arguments (best-effort, arity only).
327
+ const candidates = overloads.filter((m) => {
328
+ if (typeof m.parameterCount !== "number")
329
+ return true;
330
+ return m.parameterCount >= argCount;
331
+ });
332
+ if (candidates.length === 0)
333
+ return undefined;
334
+ let bestScore = Number.NEGATIVE_INFINITY;
335
+ let best = [];
336
+ for (const c of candidates) {
337
+ const score = scoreCandidate(c);
338
+ if (score > bestScore) {
339
+ bestScore = score;
340
+ best = [c];
325
341
  }
326
- // Build type parameter substitution map from receiver's type arguments
327
- // This preserves CLR type aliases through generic instantiation
328
- const substitutionMap = buildTypeParameterSubstitutionMap(node, checker);
329
- // Build parameter type array using instantiated types from signature
330
- const paramTypes = [];
331
- for (const sigParam of sigParams) {
332
- const decl = sigParam.valueDeclaration;
333
- // Get the declaration's type node if available
334
- if (decl && ts.isParameter(decl) && decl.type) {
335
- // Check if the declaration type is a type parameter
336
- const declType = checker.getTypeAtLocation(decl.type);
337
- const isTypeParameter = Boolean(declType.flags & ts.TypeFlags.TypeParameter);
338
- if (isTypeParameter) {
339
- if (substitutionMap) {
340
- // Type parameter case: use substitution map to preserve CLR aliases
341
- const substituted = substituteTypeNode(decl.type, substitutionMap, checker);
342
- if (substituted) {
343
- const irType = convertType(substituted, checker);
344
- if (irType) {
345
- paramTypes.push(irType);
346
- continue;
347
- }
348
- }
349
- }
350
- // Type parameter without substitution (e.g., generic function call with inferred types)
351
- // The type parameter is INFERRED from the argument, so don't validate against
352
- // TypeScript's instantiated type (which loses CLR type aliases like `int`).
353
- // Push undefined to skip validation for this parameter.
354
- paramTypes.push(undefined);
355
- continue;
356
- }
357
- else {
358
- // Non-type-parameter: use declaration type node directly
359
- // This preserves imported CLR type aliases like `int`
360
- const irType = convertType(decl.type, checker);
361
- if (irType) {
362
- paramTypes.push(irType);
363
- continue;
364
- }
365
- }
366
- }
367
- // Fallback: Use instantiated type from getTypeOfSymbolAtLocation
368
- // This handles cases where we couldn't get the declaration type
369
- const paramType = checker.getTypeOfSymbolAtLocation(sigParam, decl ?? node);
370
- const irType = convertTsTypeToIr(paramType, checker);
371
- paramTypes.push(irType);
342
+ else if (score === bestScore) {
343
+ best.push(c);
372
344
  }
373
- return paramTypes;
374
345
  }
375
- catch {
346
+ if (best.length === 0)
376
347
  return undefined;
377
- }
378
- };
379
- /**
380
- * Extract argument passing modes from member binding's parameter modifiers.
381
- * Converts parameterModifiers to the argumentPassing array format.
382
- * Returns undefined if no modifiers are present.
383
- */
384
- const extractArgumentPassingFromBinding = (callee, argCount) => {
385
- // Check if callee is a member access with parameter modifiers
386
- if (callee.kind !== "memberAccess" ||
387
- !callee.memberBinding?.parameterModifiers) {
348
+ // If ambiguous, only accept when all best candidates agree on modifiers.
349
+ const first = best[0];
350
+ if (!first)
388
351
  return undefined;
389
- }
390
- const modifiers = callee.memberBinding.parameterModifiers;
391
- if (modifiers.length === 0) {
352
+ const key = modifiersKey(first);
353
+ if (best.some((m) => modifiersKey(m) !== key)) {
392
354
  return undefined;
393
355
  }
394
- // Build the argumentPassing array
395
- // Initialize all as "value", then override based on modifiers
396
- const passing = Array(argCount).fill("value");
397
- for (const mod of modifiers) {
398
- if (mod.index >= 0 && mod.index < argCount) {
399
- passing[mod.index] = mod.modifier;
400
- }
401
- }
402
- return passing;
356
+ const chosenMods = first.parameterModifiers;
357
+ if (!chosenMods || chosenMods.length === 0)
358
+ return undefined;
359
+ return extractArgumentPassingFromParameterModifiers(chosenMods, argCount);
403
360
  };
404
361
  /**
405
362
  * Convert call expression
406
363
  */
407
- export const convertCallExpression = (node, checker) => {
408
- // Check for tryCast<T>(x) - special intrinsic for safe casting
409
- // tryCast<T>(x) compiles to C#: x as T (safe cast, returns null on failure)
364
+ export const convertCallExpression = (node, ctx) => {
365
+ // Check for trycast<T>(x) - special intrinsic for safe casting
366
+ // trycast<T>(x) compiles to C#: x as T (safe cast, returns null on failure)
410
367
  if (ts.isIdentifier(node.expression) &&
411
- node.expression.text === "tryCast" &&
368
+ node.expression.text === "trycast" &&
412
369
  node.typeArguments &&
413
370
  node.typeArguments.length === 1 &&
414
371
  node.arguments.length === 1) {
415
372
  // We've verified length === 1 above, so these are guaranteed to exist
416
373
  const targetTypeNode = node.typeArguments[0];
417
- const targetType = convertType(targetTypeNode, checker);
418
- const argExpr = convertExpression(node.arguments[0], checker);
374
+ const argNode = node.arguments[0];
375
+ if (!targetTypeNode || !argNode) {
376
+ throw new Error("ICE: trycast requires exactly 1 type argument and 1 argument");
377
+ }
378
+ // PHASE 4 (Alice's spec): Use captureTypeSyntax + typeFromSyntax
379
+ const typeSystem = ctx.typeSystem;
380
+ const targetType = typeSystem.typeFromSyntax(ctx.binding.captureTypeSyntax(targetTypeNode));
381
+ const argExpr = convertExpression(argNode, ctx, undefined);
419
382
  // Build union type T | null for inferredType
420
383
  const nullType = { kind: "primitiveType", name: "null" };
421
384
  const unionType = {
@@ -423,39 +386,238 @@ export const convertCallExpression = (node, checker) => {
423
386
  types: [targetType, nullType],
424
387
  };
425
388
  return {
426
- kind: "tryCast",
389
+ kind: "trycast",
427
390
  expression: argExpr,
428
391
  targetType,
429
392
  inferredType: unionType,
430
393
  sourceSpan: getSourceSpan(node),
431
394
  };
432
395
  }
396
+ // Check for stackalloc<T>(size) - language intrinsic for stack allocation.
397
+ // stackalloc<T>(size) compiles to C#: stackalloc T[size]
398
+ if (ts.isIdentifier(node.expression) &&
399
+ node.expression.text === "stackalloc" &&
400
+ node.typeArguments &&
401
+ node.typeArguments.length === 1 &&
402
+ node.arguments.length === 1) {
403
+ const elementTypeNode = node.typeArguments[0];
404
+ const sizeNode = node.arguments[0];
405
+ if (!elementTypeNode || !sizeNode) {
406
+ throw new Error("ICE: stackalloc requires exactly 1 type argument and 1 argument");
407
+ }
408
+ const typeSystem = ctx.typeSystem;
409
+ const elementType = typeSystem.typeFromSyntax(ctx.binding.captureTypeSyntax(elementTypeNode));
410
+ const sizeExpr = convertExpression(sizeNode, ctx, {
411
+ kind: "primitiveType",
412
+ name: "int",
413
+ });
414
+ return {
415
+ kind: "stackalloc",
416
+ elementType,
417
+ size: sizeExpr,
418
+ inferredType: {
419
+ kind: "referenceType",
420
+ name: "Span",
421
+ typeArguments: [elementType],
422
+ },
423
+ sourceSpan: getSourceSpan(node),
424
+ };
425
+ }
433
426
  // Extract type arguments from the call signature
434
- const typeArguments = extractTypeArguments(node, checker);
435
- const requiresSpecialization = checkIfRequiresSpecialization(node, checker);
436
- const narrowing = extractNarrowing(node, checker);
437
- const parameterTypes = extractParameterTypes(node, checker);
438
- // Convert callee first so we can access its memberBinding
439
- const callee = convertExpression(node.expression, checker);
440
- // Try to get argument passing from binding's parameter modifiers first (tsbindgen format),
441
- // then fall back to TypeScript declaration analysis (ref<T>/out<T>/in<T> wrapper types)
442
- const argumentPassing = extractArgumentPassingFromBinding(callee, node.arguments.length) ??
443
- extractArgumentPassing(node, checker);
444
- return {
445
- kind: "call",
446
- callee,
447
- arguments: node.arguments.map((arg) => {
427
+ const typeArguments = extractTypeArguments(node, ctx);
428
+ const requiresSpecialization = checkIfRequiresSpecialization(node, ctx);
429
+ // Convert callee first so we can access memberBinding and receiver type
430
+ const callee = convertExpression(node.expression, ctx, undefined);
431
+ // Extract receiver type for member method calls (e.g., dict.get() → dict's type)
432
+ const receiverIrType = callee.kind === "memberAccess" ? callee.object.inferredType : undefined;
433
+ // Resolve call (two-pass):
434
+ // 1) Resolve parameter types (for expectedType threading)
435
+ // 2) Convert arguments, then re-resolve with argTypes to infer generics deterministically
436
+ const typeSystem = ctx.typeSystem;
437
+ const sigId = ctx.binding.resolveCallSignature(node);
438
+ const argumentCount = node.arguments.length;
439
+ const explicitTypeArgs = node.typeArguments
440
+ ? node.typeArguments.map((ta) => typeSystem.typeFromSyntax(ctx.binding.captureTypeSyntax(ta)))
441
+ : undefined;
442
+ // If we can't resolve a signature handle (common for calls through function-typed
443
+ // variables), fall back to the callee's inferred function type.
444
+ const calleeFunctionType = (() => {
445
+ const t = callee.inferredType;
446
+ if (!t)
447
+ return undefined;
448
+ if (t.kind === "functionType")
449
+ return t;
450
+ return typeSystem.delegateToFunctionType(t) ?? undefined;
451
+ })();
452
+ if (!sigId && calleeFunctionType) {
453
+ const params = calleeFunctionType.parameters;
454
+ const paramTypesForArgs = [];
455
+ const hasRest = params.some((p) => p.isRest);
456
+ for (let i = 0; i < node.arguments.length; i++) {
457
+ const p = params[i] ?? (hasRest ? params[params.length - 1] : undefined);
458
+ paramTypesForArgs[i] = p?.type;
459
+ }
460
+ const args = [];
461
+ for (let i = 0; i < node.arguments.length; i++) {
462
+ const arg = node.arguments[i];
463
+ if (!arg)
464
+ continue;
465
+ const expectedType = paramTypesForArgs[i];
448
466
  if (ts.isSpreadElement(arg)) {
449
- return {
467
+ const spreadExpr = convertExpression(arg.expression, ctx, undefined);
468
+ args.push({
450
469
  kind: "spread",
451
- expression: convertExpression(arg.expression, checker),
470
+ expression: spreadExpr,
471
+ inferredType: spreadExpr.inferredType,
452
472
  sourceSpan: getSourceSpan(arg),
453
- };
473
+ });
474
+ continue;
454
475
  }
455
- return convertExpression(arg, checker);
456
- }),
476
+ args.push(convertExpression(arg, ctx, expectedType));
477
+ }
478
+ return {
479
+ kind: "call",
480
+ callee,
481
+ arguments: args,
482
+ isOptional: node.questionDotToken !== undefined,
483
+ inferredType: calleeFunctionType.returnType,
484
+ sourceSpan: getSourceSpan(node),
485
+ typeArguments,
486
+ requiresSpecialization,
487
+ argumentPassing: extractArgumentPassing(node, ctx),
488
+ parameterTypes: paramTypesForArgs,
489
+ };
490
+ }
491
+ const initialResolved = sigId
492
+ ? typeSystem.resolveCall({
493
+ sigId,
494
+ argumentCount,
495
+ receiverType: receiverIrType,
496
+ explicitTypeArgs,
497
+ })
498
+ : undefined;
499
+ const initialParameterTypes = initialResolved?.parameterTypes;
500
+ const isLambdaArg = (expr) => {
501
+ if (ts.isArrowFunction(expr) || ts.isFunctionExpression(expr))
502
+ return true;
503
+ if (ts.isParenthesizedExpression(expr))
504
+ return isLambdaArg(expr.expression);
505
+ return false;
506
+ };
507
+ const isExplicitlyTypedLambdaArg = (expr) => {
508
+ if (ts.isParenthesizedExpression(expr)) {
509
+ return isExplicitlyTypedLambdaArg(expr.expression);
510
+ }
511
+ if (!ts.isArrowFunction(expr) && !ts.isFunctionExpression(expr)) {
512
+ return false;
513
+ }
514
+ if (expr.type)
515
+ return true;
516
+ if (expr.typeParameters && expr.typeParameters.length > 0)
517
+ return true;
518
+ return expr.parameters.some((p) => p.type !== undefined);
519
+ };
520
+ const shouldDeferLambdaForInference = (expr) => isLambdaArg(expr) && !isExplicitlyTypedLambdaArg(expr);
521
+ // Pass 1: convert non-lambda arguments and infer type args from them.
522
+ const argsWorking = new Array(node.arguments.length);
523
+ const argTypesForInference = Array(node.arguments.length).fill(undefined);
524
+ for (let index = 0; index < node.arguments.length; index++) {
525
+ const arg = node.arguments[index];
526
+ if (!arg)
527
+ continue;
528
+ const expectedType = initialParameterTypes?.[index];
529
+ if (ts.isSpreadElement(arg)) {
530
+ const spreadExpr = convertExpression(arg.expression, ctx, undefined);
531
+ argsWorking[index] = {
532
+ kind: "spread",
533
+ expression: spreadExpr,
534
+ inferredType: spreadExpr.inferredType,
535
+ sourceSpan: getSourceSpan(arg),
536
+ };
537
+ continue;
538
+ }
539
+ if (shouldDeferLambdaForInference(arg)) {
540
+ // Defer *untyped* lambda conversion until after we infer generic type args
541
+ // from other arguments. Explicitly typed lambdas are safe to convert early
542
+ // and often provide the only deterministic inference signal.
543
+ continue;
544
+ }
545
+ const converted = convertExpression(arg, ctx, expectedType);
546
+ argsWorking[index] = converted;
547
+ argTypesForInference[index] = converted.inferredType;
548
+ }
549
+ const lambdaContextResolved = sigId
550
+ ? typeSystem.resolveCall({
551
+ sigId,
552
+ argumentCount,
553
+ receiverType: receiverIrType,
554
+ explicitTypeArgs,
555
+ argTypes: argTypesForInference,
556
+ })
557
+ : initialResolved;
558
+ const parameterTypesForLambdaContext = lambdaContextResolved?.parameterTypes ?? initialParameterTypes;
559
+ // Pass 2: convert lambda arguments with inferred parameter types in scope.
560
+ for (let index = 0; index < node.arguments.length; index++) {
561
+ if (argsWorking[index])
562
+ continue;
563
+ const arg = node.arguments[index];
564
+ if (!arg)
565
+ continue;
566
+ if (ts.isSpreadElement(arg))
567
+ continue;
568
+ if (!isLambdaArg(arg))
569
+ continue;
570
+ const expectedType = parameterTypesForLambdaContext?.[index];
571
+ const lambdaExpectedType = expectedType?.kind === "functionType"
572
+ ? expectedType
573
+ : expectedType
574
+ ? typeSystem.delegateToFunctionType(expectedType) ?? expectedType
575
+ : undefined;
576
+ argsWorking[index] = convertExpression(arg, ctx, lambdaExpectedType);
577
+ }
578
+ const convertedArgs = argsWorking.map((a) => {
579
+ if (!a) {
580
+ throw new Error("ICE: call argument conversion produced a hole");
581
+ }
582
+ return a;
583
+ });
584
+ const argTypes = convertedArgs.map((a) => a.kind === "spread" ? undefined : a.inferredType);
585
+ const finalResolved = sigId
586
+ ? typeSystem.resolveCall({
587
+ sigId,
588
+ argumentCount,
589
+ receiverType: receiverIrType,
590
+ explicitTypeArgs,
591
+ argTypes,
592
+ })
593
+ : lambdaContextResolved;
594
+ const parameterTypes = finalResolved?.parameterTypes ?? initialParameterTypes;
595
+ const inferredType = finalResolved?.returnType ?? { kind: "unknownType" };
596
+ const argumentPassingFromBinding = extractArgumentPassingFromBinding(callee, node.arguments.length, ctx, parameterTypes, argTypes);
597
+ const argumentPassing = argumentPassingFromBinding ??
598
+ (finalResolved
599
+ ? finalResolved.parameterModes.slice(0, node.arguments.length)
600
+ : extractArgumentPassing(node, ctx));
601
+ const narrowing = (() => {
602
+ const pred = finalResolved?.typePredicate;
603
+ if (!pred)
604
+ return undefined;
605
+ if (pred.kind !== "param")
606
+ return undefined;
607
+ return {
608
+ kind: "typePredicate",
609
+ argIndex: pred.parameterIndex,
610
+ targetType: pred.targetType,
611
+ };
612
+ })();
613
+ return {
614
+ kind: "call",
615
+ callee,
616
+ // Pass parameter types as expectedType for deterministic contextual typing
617
+ // This ensures `spreadArray([1,2,3], [4,5,6])` with `number[]` params produces `double[]`
618
+ arguments: convertedArgs,
457
619
  isOptional: node.questionDotToken !== undefined,
458
- inferredType: getInferredType(node, checker),
620
+ inferredType,
459
621
  sourceSpan: getSourceSpan(node),
460
622
  typeArguments,
461
623
  requiresSpecialization,
@@ -464,29 +626,144 @@ export const convertCallExpression = (node, checker) => {
464
626
  narrowing,
465
627
  };
466
628
  };
629
+ // DELETED: getConstructedType - Phase 15 uses resolveCall.returnType instead
467
630
  /**
468
631
  * Convert new expression
632
+ *
633
+ * Phase 15 (Alice's spec): Two-pass resolution for deterministic constructor typing.
634
+ * 1) Resolve once (without argTypes) to get parameter types for expected-type threading.
635
+ * 2) Convert non-lambda arguments first, collecting argTypes for inference.
636
+ * 3) Re-resolve with argTypes to infer constructor type parameters.
637
+ * 4) Convert lambda arguments using instantiated parameter types.
638
+ * 5) Final resolve with full argTypes.
639
+ * 6) inferredType MUST be finalResolved.returnType.
469
640
  */
470
- export const convertNewExpression = (node, checker) => {
471
- // Extract type arguments from the constructor signature
472
- const typeArguments = extractTypeArguments(node, checker);
473
- const requiresSpecialization = checkIfRequiresSpecialization(node, checker);
641
+ export const convertNewExpression = (node, ctx) => {
642
+ // Extract explicit type arguments (for IR output, not inference)
643
+ const typeArguments = extractTypeArguments(node, ctx);
644
+ const requiresSpecialization = checkIfRequiresSpecialization(node, ctx);
645
+ // Convert callee (the constructor expression)
646
+ const callee = convertExpression(node.expression, ctx, undefined);
647
+ // Two-pass resolution (matching convertCallExpression pattern)
648
+ const typeSystem = ctx.typeSystem;
649
+ const sigId = ctx.binding.resolveConstructorSignature(node);
650
+ const argumentCount = node.arguments?.length ?? 0;
651
+ // Extract explicit type arguments from call site
652
+ const explicitTypeArgs = node.typeArguments
653
+ ? node.typeArguments.map((ta) => typeSystem.typeFromSyntax(ctx.binding.captureTypeSyntax(ta)))
654
+ : undefined;
655
+ // Initial resolution (without argTypes) for parameter type threading
656
+ const initialResolved = sigId
657
+ ? typeSystem.resolveCall({
658
+ sigId,
659
+ argumentCount,
660
+ explicitTypeArgs,
661
+ })
662
+ : undefined;
663
+ const initialParameterTypes = initialResolved?.parameterTypes;
664
+ const isLambdaArg = (expr) => {
665
+ if (ts.isArrowFunction(expr) || ts.isFunctionExpression(expr))
666
+ return true;
667
+ if (ts.isParenthesizedExpression(expr))
668
+ return isLambdaArg(expr.expression);
669
+ return false;
670
+ };
671
+ // Pass 1: convert non-lambda arguments and collect argTypes for inference
672
+ const argsWorking = new Array(argumentCount);
673
+ const argTypesForInference = Array(argumentCount).fill(undefined);
674
+ const args = node.arguments ?? [];
675
+ for (let index = 0; index < args.length; index++) {
676
+ const arg = args[index];
677
+ if (!arg)
678
+ continue;
679
+ const expectedType = initialParameterTypes?.[index];
680
+ if (ts.isSpreadElement(arg)) {
681
+ const spreadExpr = convertExpression(arg.expression, ctx, undefined);
682
+ argsWorking[index] = {
683
+ kind: "spread",
684
+ expression: spreadExpr,
685
+ inferredType: spreadExpr.inferredType,
686
+ sourceSpan: getSourceSpan(arg),
687
+ };
688
+ continue;
689
+ }
690
+ if (isLambdaArg(arg)) {
691
+ // Defer lambda conversion until after generic type arg inference
692
+ continue;
693
+ }
694
+ const converted = convertExpression(arg, ctx, expectedType);
695
+ argsWorking[index] = converted;
696
+ argTypesForInference[index] = converted.inferredType;
697
+ }
698
+ // Re-resolve with argTypes to infer constructor type parameters
699
+ const lambdaContextResolved = sigId
700
+ ? typeSystem.resolveCall({
701
+ sigId,
702
+ argumentCount,
703
+ explicitTypeArgs,
704
+ argTypes: argTypesForInference,
705
+ })
706
+ : initialResolved;
707
+ const parameterTypesForLambdaContext = lambdaContextResolved?.parameterTypes ?? initialParameterTypes;
708
+ // Pass 2: convert lambda arguments with inferred parameter types
709
+ for (let index = 0; index < args.length; index++) {
710
+ if (argsWorking[index])
711
+ continue;
712
+ const arg = args[index];
713
+ if (!arg)
714
+ continue;
715
+ if (ts.isSpreadElement(arg))
716
+ continue;
717
+ if (!isLambdaArg(arg))
718
+ continue;
719
+ const expectedType = parameterTypesForLambdaContext?.[index];
720
+ const lambdaExpectedType = expectedType?.kind === "functionType"
721
+ ? expectedType
722
+ : expectedType
723
+ ? typeSystem.delegateToFunctionType(expectedType) ?? expectedType
724
+ : undefined;
725
+ argsWorking[index] = convertExpression(arg, ctx, lambdaExpectedType);
726
+ }
727
+ // Fill any remaining undefined slots (shouldn't happen, but be safe)
728
+ const convertedArgs = argsWorking.map((a, index) => {
729
+ if (a)
730
+ return a;
731
+ const arg = args[index];
732
+ if (!arg) {
733
+ throw new Error("ICE: new expression argument conversion produced a hole");
734
+ }
735
+ return convertExpression(arg, ctx, undefined);
736
+ });
737
+ // Collect final argTypes
738
+ const argTypes = convertedArgs.map((a) => a.kind === "spread" ? undefined : a.inferredType);
739
+ // Final resolution with full argTypes
740
+ const finalResolved = sigId
741
+ ? typeSystem.resolveCall({
742
+ sigId,
743
+ argumentCount,
744
+ explicitTypeArgs,
745
+ argTypes,
746
+ })
747
+ : lambdaContextResolved;
748
+ // Phase 15: inferredType MUST be finalResolved.returnType
749
+ // If sigId is missing, use unknownType (do not fabricate a nominal type)
750
+ const inferredType = finalResolved?.returnType ?? { kind: "unknownType" };
751
+ const parameterTypes = finalResolved?.parameterTypes ?? initialParameterTypes;
752
+ // Phase 18: IrNewExpression.typeArguments must include inferred type arguments.
753
+ // The emitter relies on this field to emit generic constructor calls (e.g., new Box<int>(...)).
754
+ const inferredTypeArguments = inferredType.kind === "referenceType" ? inferredType.typeArguments : undefined;
755
+ const typeArgumentsForIr = typeArguments ??
756
+ (inferredTypeArguments && inferredTypeArguments.length > 0
757
+ ? inferredTypeArguments
758
+ : undefined);
474
759
  return {
475
760
  kind: "new",
476
- callee: convertExpression(node.expression, checker),
477
- arguments: node.arguments?.map((arg) => {
478
- if (ts.isSpreadElement(arg)) {
479
- return {
480
- kind: "spread",
481
- expression: convertExpression(arg.expression, checker),
482
- sourceSpan: getSourceSpan(arg),
483
- };
484
- }
485
- return convertExpression(arg, checker);
486
- }) ?? [],
487
- inferredType: getInferredType(node, checker),
761
+ callee,
762
+ arguments: convertedArgs,
763
+ inferredType,
488
764
  sourceSpan: getSourceSpan(node),
489
- typeArguments,
765
+ parameterTypes,
766
+ typeArguments: typeArgumentsForIr,
490
767
  requiresSpecialization,
491
768
  };
492
769
  };