@tsonic/frontend 0.0.14 → 0.0.15

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 (513) 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 +1 -1
  8. package/dist/graph/extraction/orchestrator.js.map +1 -1
  9. package/dist/ir/binding/index.d.ts +134 -0
  10. package/dist/ir/binding/index.d.ts.map +1 -0
  11. package/dist/ir/binding/index.js +725 -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/builder/exports.d.ts +20 -2
  16. package/dist/ir/builder/exports.d.ts.map +1 -1
  17. package/dist/ir/builder/exports.js +65 -6
  18. package/dist/ir/builder/exports.js.map +1 -1
  19. package/dist/ir/builder/imports.d.ts +9 -5
  20. package/dist/ir/builder/imports.d.ts.map +1 -1
  21. package/dist/ir/builder/imports.js +20 -31
  22. package/dist/ir/builder/imports.js.map +1 -1
  23. package/dist/ir/builder/orchestrator.d.ts +10 -1
  24. package/dist/ir/builder/orchestrator.d.ts.map +1 -1
  25. package/dist/ir/builder/orchestrator.js +25 -14
  26. package/dist/ir/builder/orchestrator.js.map +1 -1
  27. package/dist/ir/builder/statements.d.ts +7 -1
  28. package/dist/ir/builder/statements.d.ts.map +1 -1
  29. package/dist/ir/builder/statements.js +7 -2
  30. package/dist/ir/builder/statements.js.map +1 -1
  31. package/dist/ir/builder/types.d.ts +3 -0
  32. package/dist/ir/builder/types.d.ts.map +1 -1
  33. package/dist/ir/builder/validation.d.ts +4 -1
  34. package/dist/ir/builder/validation.d.ts.map +1 -1
  35. package/dist/ir/builder/validation.js +37 -37
  36. package/dist/ir/builder/validation.js.map +1 -1
  37. package/dist/ir/builder.test.js +54 -111
  38. package/dist/ir/builder.test.js.map +1 -1
  39. package/dist/ir/clr-type-mappings.d.ts +42 -0
  40. package/dist/ir/clr-type-mappings.d.ts.map +1 -0
  41. package/dist/ir/clr-type-mappings.js +139 -0
  42. package/dist/ir/clr-type-mappings.js.map +1 -0
  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 +24 -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 +239 -15
  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 +431 -391
  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 +140 -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 +179 -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/statements/control/blocks.d.ts +8 -2
  92. package/dist/ir/converters/statements/control/blocks.d.ts.map +1 -1
  93. package/dist/ir/converters/statements/control/blocks.js +7 -2
  94. package/dist/ir/converters/statements/control/blocks.js.map +1 -1
  95. package/dist/ir/converters/statements/control/conditionals.d.ts +14 -4
  96. package/dist/ir/converters/statements/control/conditionals.d.ts.map +1 -1
  97. package/dist/ir/converters/statements/control/conditionals.js +19 -10
  98. package/dist/ir/converters/statements/control/conditionals.js.map +1 -1
  99. package/dist/ir/converters/statements/control/exceptions.d.ts +10 -3
  100. package/dist/ir/converters/statements/control/exceptions.d.ts.map +1 -1
  101. package/dist/ir/converters/statements/control/exceptions.js +13 -7
  102. package/dist/ir/converters/statements/control/exceptions.js.map +1 -1
  103. package/dist/ir/converters/statements/control/loops.d.ts +16 -5
  104. package/dist/ir/converters/statements/control/loops.d.ts.map +1 -1
  105. package/dist/ir/converters/statements/control/loops.js +25 -15
  106. package/dist/ir/converters/statements/control/loops.js.map +1 -1
  107. package/dist/ir/converters/statements/declarations/classes/constructors.d.ts +3 -2
  108. package/dist/ir/converters/statements/declarations/classes/constructors.d.ts.map +1 -1
  109. package/dist/ir/converters/statements/declarations/classes/constructors.js +11 -7
  110. package/dist/ir/converters/statements/declarations/classes/constructors.js.map +1 -1
  111. package/dist/ir/converters/statements/declarations/classes/methods.d.ts +2 -1
  112. package/dist/ir/converters/statements/declarations/classes/methods.d.ts.map +1 -1
  113. package/dist/ir/converters/statements/declarations/classes/methods.js +63 -11
  114. package/dist/ir/converters/statements/declarations/classes/methods.js.map +1 -1
  115. package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts +2 -1
  116. package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts.map +1 -1
  117. package/dist/ir/converters/statements/declarations/classes/orchestrator.js +60 -40
  118. package/dist/ir/converters/statements/declarations/classes/orchestrator.js.map +1 -1
  119. package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts +6 -2
  120. package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts.map +1 -1
  121. package/dist/ir/converters/statements/declarations/classes/override-detection.js +49 -50
  122. package/dist/ir/converters/statements/declarations/classes/override-detection.js.map +1 -1
  123. package/dist/ir/converters/statements/declarations/classes/properties.d.ts +9 -1
  124. package/dist/ir/converters/statements/declarations/classes/properties.d.ts.map +1 -1
  125. package/dist/ir/converters/statements/declarations/classes/properties.js +119 -16
  126. package/dist/ir/converters/statements/declarations/classes/properties.js.map +1 -1
  127. package/dist/ir/converters/statements/declarations/enums.d.ts +2 -1
  128. package/dist/ir/converters/statements/declarations/enums.d.ts.map +1 -1
  129. package/dist/ir/converters/statements/declarations/enums.js +8 -2
  130. package/dist/ir/converters/statements/declarations/enums.js.map +1 -1
  131. package/dist/ir/converters/statements/declarations/functions.d.ts +2 -1
  132. package/dist/ir/converters/statements/declarations/functions.d.ts.map +1 -1
  133. package/dist/ir/converters/statements/declarations/functions.js +11 -6
  134. package/dist/ir/converters/statements/declarations/functions.js.map +1 -1
  135. package/dist/ir/converters/statements/declarations/index.d.ts +3 -1
  136. package/dist/ir/converters/statements/declarations/index.d.ts.map +1 -1
  137. package/dist/ir/converters/statements/declarations/index.js +3 -1
  138. package/dist/ir/converters/statements/declarations/index.js.map +1 -1
  139. package/dist/ir/converters/statements/declarations/interfaces.d.ts +3 -2
  140. package/dist/ir/converters/statements/declarations/interfaces.d.ts.map +1 -1
  141. package/dist/ir/converters/statements/declarations/interfaces.js +26 -20
  142. package/dist/ir/converters/statements/declarations/interfaces.js.map +1 -1
  143. package/dist/ir/converters/statements/declarations/registry.d.ts +72 -0
  144. package/dist/ir/converters/statements/declarations/registry.d.ts.map +1 -1
  145. package/dist/ir/converters/statements/declarations/registry.js +92 -0
  146. package/dist/ir/converters/statements/declarations/registry.js.map +1 -1
  147. package/dist/ir/converters/statements/declarations/type-aliases.d.ts +2 -1
  148. package/dist/ir/converters/statements/declarations/type-aliases.d.ts.map +1 -1
  149. package/dist/ir/converters/statements/declarations/type-aliases.js +6 -4
  150. package/dist/ir/converters/statements/declarations/type-aliases.js.map +1 -1
  151. package/dist/ir/converters/statements/declarations/variables.d.ts +11 -1
  152. package/dist/ir/converters/statements/declarations/variables.d.ts.map +1 -1
  153. package/dist/ir/converters/statements/declarations/variables.js +123 -19
  154. package/dist/ir/converters/statements/declarations/variables.js.map +1 -1
  155. package/dist/ir/converters/statements/declarations.d.ts +4 -1
  156. package/dist/ir/converters/statements/declarations.d.ts.map +1 -1
  157. package/dist/ir/converters/statements/declarations.js +4 -1
  158. package/dist/ir/converters/statements/declarations.js.map +1 -1
  159. package/dist/ir/converters/statements/helpers.d.ts +4 -3
  160. package/dist/ir/converters/statements/helpers.d.ts.map +1 -1
  161. package/dist/ir/converters/statements/helpers.js +55 -31
  162. package/dist/ir/converters/statements/helpers.js.map +1 -1
  163. package/dist/ir/converters/statements/index.d.ts +1 -1
  164. package/dist/ir/converters/statements/index.d.ts.map +1 -1
  165. package/dist/ir/converters/statements/index.js +2 -1
  166. package/dist/ir/converters/statements/index.js.map +1 -1
  167. package/dist/ir/expression-converter.d.ts +10 -3
  168. package/dist/ir/expression-converter.d.ts.map +1 -1
  169. package/dist/ir/expression-converter.js +132 -57
  170. package/dist/ir/expression-converter.js.map +1 -1
  171. package/dist/ir/hierarchical-bindings-e2e.test.js +10 -6
  172. package/dist/ir/hierarchical-bindings-e2e.test.js.map +1 -1
  173. package/dist/ir/index.d.ts +5 -0
  174. package/dist/ir/index.d.ts.map +1 -1
  175. package/dist/ir/index.js +5 -0
  176. package/dist/ir/index.js.map +1 -1
  177. package/dist/ir/no-ts-type-inference.test.d.ts +17 -0
  178. package/dist/ir/no-ts-type-inference.test.d.ts.map +1 -0
  179. package/dist/ir/no-ts-type-inference.test.js +171 -0
  180. package/dist/ir/no-ts-type-inference.test.js.map +1 -0
  181. package/dist/ir/program-context.d.ts +74 -0
  182. package/dist/ir/program-context.d.ts.map +1 -0
  183. package/dist/ir/program-context.js +286 -0
  184. package/dist/ir/program-context.js.map +1 -0
  185. package/dist/ir/statement-converter.d.ts +14 -4
  186. package/dist/ir/statement-converter.d.ts.map +1 -1
  187. package/dist/ir/statement-converter.js +31 -21
  188. package/dist/ir/statement-converter.js.map +1 -1
  189. package/dist/ir/syntax/binding-patterns.d.ts +22 -0
  190. package/dist/ir/syntax/binding-patterns.d.ts.map +1 -0
  191. package/dist/ir/syntax/binding-patterns.js +92 -0
  192. package/dist/ir/syntax/binding-patterns.js.map +1 -0
  193. package/dist/ir/thisarg-inference.test.d.ts +8 -0
  194. package/dist/ir/thisarg-inference.test.d.ts.map +1 -0
  195. package/dist/ir/thisarg-inference.test.js +94 -0
  196. package/dist/ir/thisarg-inference.test.js.map +1 -0
  197. package/dist/ir/type-converter.d.ts +5 -2
  198. package/dist/ir/type-converter.d.ts.map +1 -1
  199. package/dist/ir/type-converter.js +5 -2
  200. package/dist/ir/type-converter.js.map +1 -1
  201. package/dist/ir/type-system/core.d.ts +29 -0
  202. package/dist/ir/type-system/core.d.ts.map +1 -0
  203. package/dist/ir/type-system/core.js +456 -0
  204. package/dist/ir/type-system/core.js.map +1 -0
  205. package/dist/ir/type-system/index.d.ts +21 -0
  206. package/dist/ir/type-system/index.d.ts.map +1 -0
  207. package/dist/ir/type-system/index.js +43 -0
  208. package/dist/ir/type-system/index.js.map +1 -0
  209. package/dist/ir/type-system/internal/handle-types.d.ts +98 -0
  210. package/dist/ir/type-system/internal/handle-types.d.ts.map +1 -0
  211. package/dist/ir/type-system/internal/handle-types.js +13 -0
  212. package/dist/ir/type-system/internal/handle-types.js.map +1 -0
  213. package/dist/ir/type-system/internal/nominal-env.d.ts +66 -0
  214. package/dist/ir/type-system/internal/nominal-env.d.ts.map +1 -0
  215. package/dist/ir/type-system/internal/nominal-env.js +301 -0
  216. package/dist/ir/type-system/internal/nominal-env.js.map +1 -0
  217. package/dist/ir/type-system/internal/type-converter/arrays.d.ts +11 -0
  218. package/dist/ir/type-system/internal/type-converter/arrays.d.ts.map +1 -0
  219. package/dist/ir/{type-converter → type-system/internal/type-converter}/arrays.js +2 -2
  220. package/dist/ir/type-system/internal/type-converter/arrays.js.map +1 -0
  221. package/dist/ir/type-system/internal/type-converter/converter.d.ts +17 -0
  222. package/dist/ir/type-system/internal/type-converter/converter.d.ts.map +1 -0
  223. package/dist/ir/type-system/internal/type-converter/converter.js +16 -0
  224. package/dist/ir/type-system/internal/type-converter/converter.js.map +1 -0
  225. package/dist/ir/type-system/internal/type-converter/functions.d.ts +14 -0
  226. package/dist/ir/type-system/internal/type-converter/functions.d.ts.map +1 -0
  227. package/dist/ir/type-system/internal/type-converter/functions.js +66 -0
  228. package/dist/ir/type-system/internal/type-converter/functions.js.map +1 -0
  229. package/dist/ir/type-system/internal/type-converter/index.d.ts +11 -0
  230. package/dist/ir/type-system/internal/type-converter/index.d.ts.map +1 -0
  231. package/dist/ir/type-system/internal/type-converter/index.js +11 -0
  232. package/dist/ir/type-system/internal/type-converter/index.js.map +1 -0
  233. package/dist/ir/type-system/internal/type-converter/inference.d.ts +37 -0
  234. package/dist/ir/type-system/internal/type-converter/inference.d.ts.map +1 -0
  235. package/dist/ir/type-system/internal/type-converter/inference.js +32 -0
  236. package/dist/ir/type-system/internal/type-converter/inference.js.map +1 -0
  237. package/dist/ir/{type-converter → type-system/internal/type-converter}/literals.d.ts +1 -1
  238. package/dist/ir/type-system/internal/type-converter/literals.d.ts.map +1 -0
  239. package/dist/ir/type-system/internal/type-converter/literals.js.map +1 -0
  240. package/dist/ir/type-system/internal/type-converter/objects.d.ts +20 -0
  241. package/dist/ir/type-system/internal/type-converter/objects.d.ts.map +1 -0
  242. package/dist/ir/{type-converter → type-system/internal/type-converter}/objects.js +56 -6
  243. package/dist/ir/type-system/internal/type-converter/objects.js.map +1 -0
  244. package/dist/ir/{type-converter → type-system/internal/type-converter}/orchestrator.d.ts +3 -2
  245. package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts.map +1 -0
  246. package/dist/ir/{type-converter → type-system/internal/type-converter}/orchestrator.js +63 -21
  247. package/dist/ir/type-system/internal/type-converter/orchestrator.js.map +1 -0
  248. package/dist/ir/type-system/internal/type-converter/patterns.d.ts +12 -0
  249. package/dist/ir/type-system/internal/type-converter/patterns.d.ts.map +1 -0
  250. package/dist/ir/{type-converter → type-system/internal/type-converter}/patterns.js +22 -6
  251. package/dist/ir/type-system/internal/type-converter/patterns.js.map +1 -0
  252. package/dist/ir/{type-converter → type-system/internal/type-converter}/primitives.d.ts +1 -1
  253. package/dist/ir/type-system/internal/type-converter/primitives.d.ts.map +1 -0
  254. package/dist/ir/type-system/internal/type-converter/primitives.js.map +1 -0
  255. package/dist/ir/{type-converter → type-system/internal/type-converter}/references.d.ts +3 -2
  256. package/dist/ir/type-system/internal/type-converter/references.d.ts.map +1 -0
  257. package/dist/ir/type-system/internal/type-converter/references.js +551 -0
  258. package/dist/ir/type-system/internal/type-converter/references.js.map +1 -0
  259. package/dist/ir/type-system/internal/type-converter/unions-intersections.d.ts +15 -0
  260. package/dist/ir/type-system/internal/type-converter/unions-intersections.d.ts.map +1 -0
  261. package/dist/ir/type-system/internal/type-converter/unions-intersections.js +22 -0
  262. package/dist/ir/type-system/internal/type-converter/unions-intersections.js.map +1 -0
  263. package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.d.ts +23 -36
  264. package/dist/ir/type-system/internal/type-converter/utility-types.d.ts.map +1 -0
  265. package/dist/ir/type-system/internal/type-converter/utility-types.js +879 -0
  266. package/dist/ir/type-system/internal/type-converter/utility-types.js.map +1 -0
  267. package/dist/ir/type-system/internal/type-converter/utility-types.test.d.ts.map +1 -0
  268. package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.js +398 -120
  269. package/dist/ir/type-system/internal/type-converter/utility-types.test.js.map +1 -0
  270. package/dist/ir/type-system/internal/type-converter.d.ts +9 -0
  271. package/dist/ir/type-system/internal/type-converter.d.ts.map +1 -0
  272. package/dist/ir/type-system/internal/type-converter.js +9 -0
  273. package/dist/ir/type-system/internal/type-converter.js.map +1 -0
  274. package/dist/ir/type-system/internal/type-registry.d.ts +107 -0
  275. package/dist/ir/type-system/internal/type-registry.d.ts.map +1 -0
  276. package/dist/ir/type-system/internal/type-registry.js +534 -0
  277. package/dist/ir/type-system/internal/type-registry.js.map +1 -0
  278. package/dist/ir/type-system/internal/universe/alias-table.d.ts +92 -0
  279. package/dist/ir/type-system/internal/universe/alias-table.d.ts.map +1 -0
  280. package/dist/ir/type-system/internal/universe/alias-table.js +222 -0
  281. package/dist/ir/type-system/internal/universe/alias-table.js.map +1 -0
  282. package/dist/ir/type-system/internal/universe/clr-catalog.d.ts +44 -0
  283. package/dist/ir/type-system/internal/universe/clr-catalog.d.ts.map +1 -0
  284. package/dist/ir/type-system/internal/universe/clr-catalog.js +1176 -0
  285. package/dist/ir/type-system/internal/universe/clr-catalog.js.map +1 -0
  286. package/dist/ir/type-system/internal/universe/index.d.ts +26 -0
  287. package/dist/ir/type-system/internal/universe/index.d.ts.map +1 -0
  288. package/dist/ir/type-system/internal/universe/index.js +30 -0
  289. package/dist/ir/type-system/internal/universe/index.js.map +1 -0
  290. package/dist/ir/type-system/internal/universe/resolution.d.ts +115 -0
  291. package/dist/ir/type-system/internal/universe/resolution.d.ts.map +1 -0
  292. package/dist/ir/type-system/internal/universe/resolution.js +181 -0
  293. package/dist/ir/type-system/internal/universe/resolution.js.map +1 -0
  294. package/dist/ir/type-system/internal/universe/source-catalog.d.ts +62 -0
  295. package/dist/ir/type-system/internal/universe/source-catalog.d.ts.map +1 -0
  296. package/dist/ir/type-system/internal/universe/source-catalog.js +91 -0
  297. package/dist/ir/type-system/internal/universe/source-catalog.js.map +1 -0
  298. package/dist/ir/type-system/internal/universe/types.d.ts +436 -0
  299. package/dist/ir/type-system/internal/universe/types.d.ts.map +1 -0
  300. package/dist/ir/type-system/internal/universe/types.js +69 -0
  301. package/dist/ir/type-system/internal/universe/types.js.map +1 -0
  302. package/dist/ir/type-system/internal/universe/unified-universe.d.ts +70 -0
  303. package/dist/ir/type-system/internal/universe/unified-universe.d.ts.map +1 -0
  304. package/dist/ir/type-system/internal/universe/unified-universe.js +319 -0
  305. package/dist/ir/type-system/internal/universe/unified-universe.js.map +1 -0
  306. package/dist/ir/type-system/type-system.d.ts +617 -0
  307. package/dist/ir/type-system/type-system.d.ts.map +1 -0
  308. package/dist/ir/type-system/type-system.js +2420 -0
  309. package/dist/ir/type-system/type-system.js.map +1 -0
  310. package/dist/ir/type-system/types.d.ts +176 -0
  311. package/dist/ir/type-system/types.d.ts.map +1 -0
  312. package/dist/ir/type-system/types.js +80 -0
  313. package/dist/ir/type-system/types.js.map +1 -0
  314. package/dist/ir/type-universe/assembly-catalog.d.ts +44 -0
  315. package/dist/ir/type-universe/assembly-catalog.d.ts.map +1 -0
  316. package/dist/ir/type-universe/assembly-catalog.js +532 -0
  317. package/dist/ir/type-universe/assembly-catalog.js.map +1 -0
  318. package/dist/ir/type-universe/assembly-catalog.test.d.ts +7 -0
  319. package/dist/ir/type-universe/assembly-catalog.test.d.ts.map +1 -0
  320. package/dist/ir/type-universe/assembly-catalog.test.js +105 -0
  321. package/dist/ir/type-universe/assembly-catalog.test.js.map +1 -0
  322. package/dist/ir/type-universe/index.d.ts +19 -0
  323. package/dist/ir/type-universe/index.d.ts.map +1 -0
  324. package/dist/ir/type-universe/index.js +21 -0
  325. package/dist/ir/type-universe/index.js.map +1 -0
  326. package/dist/ir/type-universe/types.d.ts +436 -0
  327. package/dist/ir/type-universe/types.d.ts.map +1 -0
  328. package/dist/ir/type-universe/types.js +69 -0
  329. package/dist/ir/type-universe/types.js.map +1 -0
  330. package/dist/ir/type-universe/unified-catalog.d.ts +70 -0
  331. package/dist/ir/type-universe/unified-catalog.d.ts.map +1 -0
  332. package/dist/ir/type-universe/unified-catalog.js +319 -0
  333. package/dist/ir/type-universe/unified-catalog.js.map +1 -0
  334. package/dist/ir/type-universe/unified-catalog.test.d.ts +7 -0
  335. package/dist/ir/type-universe/unified-catalog.test.d.ts.map +1 -0
  336. package/dist/ir/type-universe/unified-catalog.test.js +135 -0
  337. package/dist/ir/type-universe/unified-catalog.test.js.map +1 -0
  338. package/dist/ir/types/expressions.d.ts +33 -7
  339. package/dist/ir/types/expressions.d.ts.map +1 -1
  340. package/dist/ir/types/helpers.d.ts +22 -2
  341. package/dist/ir/types/helpers.d.ts.map +1 -1
  342. package/dist/ir/types/index.d.ts +4 -2
  343. package/dist/ir/types/index.d.ts.map +1 -1
  344. package/dist/ir/types/index.js +1 -0
  345. package/dist/ir/types/index.js.map +1 -1
  346. package/dist/ir/types/ir-substitution.d.ts +144 -0
  347. package/dist/ir/types/ir-substitution.d.ts.map +1 -0
  348. package/dist/ir/types/ir-substitution.js +569 -0
  349. package/dist/ir/types/ir-substitution.js.map +1 -0
  350. package/dist/ir/types/ir-types.d.ts +9 -3
  351. package/dist/ir/types/ir-types.d.ts.map +1 -1
  352. package/dist/ir/types/numeric-helpers.d.ts +2 -1
  353. package/dist/ir/types/numeric-helpers.d.ts.map +1 -1
  354. package/dist/ir/types/numeric-helpers.js +9 -3
  355. package/dist/ir/types/numeric-helpers.js.map +1 -1
  356. package/dist/ir/types/statements.d.ts +13 -1
  357. package/dist/ir/types/statements.d.ts.map +1 -1
  358. package/dist/ir/types.d.ts +1 -1
  359. package/dist/ir/types.d.ts.map +1 -1
  360. package/dist/ir/types.js.map +1 -1
  361. package/dist/ir/validation/anonymous-type-lowering-pass.d.ts.map +1 -1
  362. package/dist/ir/validation/anonymous-type-lowering-pass.js +152 -8
  363. package/dist/ir/validation/anonymous-type-lowering-pass.js.map +1 -1
  364. package/dist/ir/validation/arrow-return-finalization-pass.d.ts +28 -0
  365. package/dist/ir/validation/arrow-return-finalization-pass.d.ts.map +1 -0
  366. package/dist/ir/validation/arrow-return-finalization-pass.js +416 -0
  367. package/dist/ir/validation/arrow-return-finalization-pass.js.map +1 -0
  368. package/dist/ir/validation/attribute-collection-pass.d.ts.map +1 -1
  369. package/dist/ir/validation/attribute-collection-pass.js +40 -6
  370. package/dist/ir/validation/attribute-collection-pass.js.map +1 -1
  371. package/dist/ir/validation/attribute-collection-pass.test.js +43 -36
  372. package/dist/ir/validation/attribute-collection-pass.test.js.map +1 -1
  373. package/dist/ir/validation/index.d.ts +3 -0
  374. package/dist/ir/validation/index.d.ts.map +1 -1
  375. package/dist/ir/validation/index.js +3 -0
  376. package/dist/ir/validation/index.js.map +1 -1
  377. package/dist/ir/validation/numeric-coercion-pass.d.ts +22 -16
  378. package/dist/ir/validation/numeric-coercion-pass.d.ts.map +1 -1
  379. package/dist/ir/validation/numeric-coercion-pass.js +159 -51
  380. package/dist/ir/validation/numeric-coercion-pass.js.map +1 -1
  381. package/dist/ir/validation/numeric-invariants.test.js +72 -108
  382. package/dist/ir/validation/numeric-invariants.test.js.map +1 -1
  383. package/dist/ir/validation/numeric-proof-pass.d.ts.map +1 -1
  384. package/dist/ir/validation/numeric-proof-pass.js +71 -23
  385. package/dist/ir/validation/numeric-proof-pass.js.map +1 -1
  386. package/dist/ir/validation/rest-type-synthesis-pass.d.ts +24 -0
  387. package/dist/ir/validation/rest-type-synthesis-pass.d.ts.map +1 -0
  388. package/dist/ir/validation/rest-type-synthesis-pass.js +417 -0
  389. package/dist/ir/validation/rest-type-synthesis-pass.js.map +1 -0
  390. package/dist/ir/validation/soundness-gate.d.ts +11 -1
  391. package/dist/ir/validation/soundness-gate.d.ts.map +1 -1
  392. package/dist/ir/validation/soundness-gate.js +42 -10
  393. package/dist/ir/validation/soundness-gate.js.map +1 -1
  394. package/dist/ir/validation/soundness-gate.test.js +19 -2
  395. package/dist/ir/validation/soundness-gate.test.js.map +1 -1
  396. package/dist/ir/validation/virtual-marking-pass.d.ts +16 -0
  397. package/dist/ir/validation/virtual-marking-pass.d.ts.map +1 -0
  398. package/dist/ir/validation/virtual-marking-pass.js +77 -0
  399. package/dist/ir/validation/virtual-marking-pass.js.map +1 -0
  400. package/dist/ir/validation/yield-lowering-pass.test.js +2 -2
  401. package/dist/ir/validation/yield-lowering-pass.test.js.map +1 -1
  402. package/dist/program/bindings.d.ts +28 -0
  403. package/dist/program/bindings.d.ts.map +1 -1
  404. package/dist/program/bindings.js +204 -2
  405. package/dist/program/bindings.js.map +1 -1
  406. package/dist/program/bindings.test.js +30 -0
  407. package/dist/program/bindings.test.js.map +1 -1
  408. package/dist/program/creation.d.ts.map +1 -1
  409. package/dist/program/creation.js +251 -4
  410. package/dist/program/creation.js.map +1 -1
  411. package/dist/program/dependency-graph.d.ts.map +1 -1
  412. package/dist/program/dependency-graph.js +25 -25
  413. package/dist/program/dependency-graph.js.map +1 -1
  414. package/dist/program/diagnostics.d.ts.map +1 -1
  415. package/dist/program/diagnostics.js +6 -0
  416. package/dist/program/diagnostics.js.map +1 -1
  417. package/dist/program/index.d.ts +1 -1
  418. package/dist/program/index.d.ts.map +1 -1
  419. package/dist/program/types.d.ts +8 -8
  420. package/dist/program/types.d.ts.map +1 -1
  421. package/dist/resolver/clr-bindings-resolver.d.ts +1 -0
  422. package/dist/resolver/clr-bindings-resolver.d.ts.map +1 -1
  423. package/dist/resolver/clr-bindings-resolver.js +90 -34
  424. package/dist/resolver/clr-bindings-resolver.js.map +1 -1
  425. package/dist/resolver/import-resolution.d.ts +16 -1
  426. package/dist/resolver/import-resolution.d.ts.map +1 -1
  427. package/dist/resolver/import-resolution.js +29 -12
  428. package/dist/resolver/import-resolution.js.map +1 -1
  429. package/dist/resolver/naming.d.ts +1 -1
  430. package/dist/resolver/naming.d.ts.map +1 -1
  431. package/dist/resolver/naming.js +13 -2
  432. package/dist/resolver/naming.js.map +1 -1
  433. package/dist/resolver.test.js +4 -0
  434. package/dist/resolver.test.js.map +1 -1
  435. package/dist/symbol-table/builder.d.ts +3 -1
  436. package/dist/symbol-table/builder.d.ts.map +1 -1
  437. package/dist/symbol-table/builder.js +9 -8
  438. package/dist/symbol-table/builder.js.map +1 -1
  439. package/dist/symbol-table/types.d.ts +2 -2
  440. package/dist/symbol-table/types.d.ts.map +1 -1
  441. package/dist/types/diagnostic.d.ts +12 -2
  442. package/dist/types/diagnostic.d.ts.map +1 -1
  443. package/dist/types/diagnostic.js +5 -1
  444. package/dist/types/diagnostic.js.map +1 -1
  445. package/dist/validation/extension-methods.d.ts +17 -0
  446. package/dist/validation/extension-methods.d.ts.map +1 -0
  447. package/dist/validation/extension-methods.js +133 -0
  448. package/dist/validation/extension-methods.js.map +1 -0
  449. package/dist/validation/generics.d.ts.map +1 -1
  450. package/dist/validation/generics.js +1 -129
  451. package/dist/validation/generics.js.map +1 -1
  452. package/dist/validation/imports.js +1 -1
  453. package/dist/validation/imports.js.map +1 -1
  454. package/dist/validation/index.d.ts +1 -0
  455. package/dist/validation/index.d.ts.map +1 -1
  456. package/dist/validation/index.js +1 -0
  457. package/dist/validation/index.js.map +1 -1
  458. package/dist/validation/orchestrator.d.ts.map +1 -1
  459. package/dist/validation/orchestrator.js +2 -0
  460. package/dist/validation/orchestrator.js.map +1 -1
  461. package/dist/validation/static-safety.d.ts +1 -0
  462. package/dist/validation/static-safety.d.ts.map +1 -1
  463. package/dist/validation/static-safety.js +366 -96
  464. package/dist/validation/static-safety.js.map +1 -1
  465. package/dist/validator.test.js +77 -1
  466. package/dist/validator.test.js.map +1 -1
  467. package/package.json +2 -2
  468. package/dist/ir/type-converter/arrays.d.ts +0 -10
  469. package/dist/ir/type-converter/arrays.d.ts.map +0 -1
  470. package/dist/ir/type-converter/arrays.js.map +0 -1
  471. package/dist/ir/type-converter/converter.d.ts +0 -6
  472. package/dist/ir/type-converter/converter.d.ts.map +0 -1
  473. package/dist/ir/type-converter/converter.js +0 -6
  474. package/dist/ir/type-converter/converter.js.map +0 -1
  475. package/dist/ir/type-converter/functions.d.ts +0 -10
  476. package/dist/ir/type-converter/functions.d.ts.map +0 -1
  477. package/dist/ir/type-converter/functions.js +0 -15
  478. package/dist/ir/type-converter/functions.js.map +0 -1
  479. package/dist/ir/type-converter/index.d.ts +0 -7
  480. package/dist/ir/type-converter/index.d.ts.map +0 -1
  481. package/dist/ir/type-converter/index.js +0 -7
  482. package/dist/ir/type-converter/index.js.map +0 -1
  483. package/dist/ir/type-converter/inference.d.ts +0 -32
  484. package/dist/ir/type-converter/inference.d.ts.map +0 -1
  485. package/dist/ir/type-converter/inference.js +0 -297
  486. package/dist/ir/type-converter/inference.js.map +0 -1
  487. package/dist/ir/type-converter/literals.d.ts.map +0 -1
  488. package/dist/ir/type-converter/literals.js.map +0 -1
  489. package/dist/ir/type-converter/objects.d.ts +0 -16
  490. package/dist/ir/type-converter/objects.d.ts.map +0 -1
  491. package/dist/ir/type-converter/objects.js.map +0 -1
  492. package/dist/ir/type-converter/orchestrator.d.ts.map +0 -1
  493. package/dist/ir/type-converter/orchestrator.js.map +0 -1
  494. package/dist/ir/type-converter/patterns.d.ts +0 -10
  495. package/dist/ir/type-converter/patterns.d.ts.map +0 -1
  496. package/dist/ir/type-converter/patterns.js.map +0 -1
  497. package/dist/ir/type-converter/primitives.d.ts.map +0 -1
  498. package/dist/ir/type-converter/primitives.js.map +0 -1
  499. package/dist/ir/type-converter/references.d.ts.map +0 -1
  500. package/dist/ir/type-converter/references.js +0 -371
  501. package/dist/ir/type-converter/references.js.map +0 -1
  502. package/dist/ir/type-converter/unions-intersections.d.ts +0 -14
  503. package/dist/ir/type-converter/unions-intersections.d.ts.map +0 -1
  504. package/dist/ir/type-converter/unions-intersections.js +0 -22
  505. package/dist/ir/type-converter/unions-intersections.js.map +0 -1
  506. package/dist/ir/type-converter/utility-types.d.ts.map +0 -1
  507. package/dist/ir/type-converter/utility-types.js +0 -528
  508. package/dist/ir/type-converter/utility-types.js.map +0 -1
  509. package/dist/ir/type-converter/utility-types.test.d.ts.map +0 -1
  510. package/dist/ir/type-converter/utility-types.test.js.map +0 -1
  511. /package/dist/ir/{type-converter → type-system/internal/type-converter}/literals.js +0 -0
  512. /package/dist/ir/{type-converter → type-system/internal/type-converter}/primitives.js +0 -0
  513. /package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.d.ts +0 -0
@@ -0,0 +1,2420 @@
1
+ /**
2
+ * TypeAuthority — Alice's 100% Specification
3
+ *
4
+ * The single, authoritative type facility for Tsonic. This is the ONLY place
5
+ * where type information is computed or queried. All converters, validation,
6
+ * and utilities use this interface exclusively.
7
+ *
8
+ * INVARIANTS (enforced by scripts/verify-invariants.sh):
9
+ * - INV-0: No TS computed type APIs outside Binding
10
+ * - INV-1: No convertType/getHandleRegistry outside TypeAuthority
11
+ * - INV-2: Deterministic type sources only
12
+ * - INV-3: Poison-on-missing-types (return unknownType + emit diagnostic)
13
+ */
14
+ import * as ts from "typescript";
15
+ import { substituteIrType as irSubstitute, } from "../types/ir-substitution.js";
16
+ import { inferNumericKindFromRaw } from "../types/numeric-helpers.js";
17
+ import { getBinaryResultKind, TSONIC_TO_NUMERIC_KIND } from "../types/numeric-kind.js";
18
+ // ═══════════════════════════════════════════════════════════════════════════
19
+ // BUILTIN NOMINAL MAPPING
20
+ // ═══════════════════════════════════════════════════════════════════════════
21
+ /**
22
+ * Mapping from primitive type names to their nominal type names.
23
+ *
24
+ * Used by typeOfMember to look up members on primitives.
25
+ * e.g., `"hello".length` → String.length
26
+ */
27
+ export const BUILTIN_NOMINALS = {
28
+ string: "String",
29
+ number: "Number",
30
+ boolean: "Boolean",
31
+ bigint: "BigInt",
32
+ symbol: "Symbol",
33
+ };
34
+ // ═══════════════════════════════════════════════════════════════════════════
35
+ // POISON VALUES
36
+ // ═══════════════════════════════════════════════════════════════════════════
37
+ /** Poison type for undeterminable types */
38
+ export const unknownType = { kind: "unknownType" };
39
+ /** Poison type for impossible types */
40
+ export const neverType = { kind: "neverType" };
41
+ /** Void type for functions with no return */
42
+ export const voidType = { kind: "voidType" };
43
+ /**
44
+ * Create a poisoned ResolvedCall with correct arity.
45
+ *
46
+ * CRITICAL (Alice's spec): Empty arrays are ILLEGAL.
47
+ * Poisoned results must have correct arity so callers cannot
48
+ * detect failure via `length === 0` and fall back to legacy.
49
+ *
50
+ * @param arity Number of parameters/arguments (from CallQuery.argumentCount)
51
+ * @param diagnostics Diagnostics explaining why resolution failed
52
+ */
53
+ export const poisonedCall = (arity, diagnostics) => ({
54
+ parameterTypes: Array(arity).fill(unknownType),
55
+ parameterModes: Array(arity).fill("value"),
56
+ returnType: unknownType,
57
+ diagnostics,
58
+ });
59
+ /**
60
+ * Create a TypeSystem instance with internal caches.
61
+ *
62
+ * This is the single factory for TypeSystem. All type queries go through
63
+ * the returned TypeSystem instance.
64
+ */
65
+ export const createTypeSystem = (config) => {
66
+ const { handleRegistry, typeRegistry, nominalEnv, convertTypeNode, unifiedCatalog, aliasTable, resolveIdentifier, resolveCallSignature, resolveConstructorSignature, } = config;
67
+ // ─────────────────────────────────────────────────────────────────────────
68
+ // INTERNAL CACHES — Step 4 Implementation
69
+ // ─────────────────────────────────────────────────────────────────────────
70
+ /**
71
+ * Cache for declaration types.
72
+ * Key: DeclId.id (number)
73
+ * Value: IrType
74
+ */
75
+ const declTypeCache = new Map();
76
+ /**
77
+ * Cache for member declared types (fully substituted).
78
+ * Key: "fqName:memberName" or "fqName:memberName:typeArgs" for generics
79
+ * Value: IrType
80
+ */
81
+ const memberDeclaredTypeCache = new Map();
82
+ /**
83
+ * Cache for raw signature info (pre-substitution).
84
+ * Key: SignatureId.id (number)
85
+ * Value: RawSignatureInfo
86
+ */
87
+ const signatureRawCache = new Map();
88
+ /**
89
+ * Cache for nominal member lookups.
90
+ * Key: "fqName:typeArgs:memberName"
91
+ * Value: NominalLookupResult
92
+ */
93
+ const nominalMemberLookupCache = new Map();
94
+ /**
95
+ * Accumulated diagnostics from type queries.
96
+ */
97
+ const diagnostics = [];
98
+ // ─────────────────────────────────────────────────────────────────────────
99
+ // DIAGNOSTIC HELPERS
100
+ // ─────────────────────────────────────────────────────────────────────────
101
+ const emitDiagnostic = (code, message, site) => {
102
+ const location = site?.file !== undefined &&
103
+ site?.line !== undefined &&
104
+ site?.column !== undefined
105
+ ? {
106
+ file: site.file,
107
+ line: site.line,
108
+ column: site.column,
109
+ length: 1, // Default length
110
+ }
111
+ : undefined;
112
+ diagnostics.push({
113
+ code,
114
+ severity: "error",
115
+ message,
116
+ location,
117
+ });
118
+ };
119
+ // ─────────────────────────────────────────────────────────────────────────
120
+ // CACHE KEY HELPERS
121
+ // ─────────────────────────────────────────────────────────────────────────
122
+ /**
123
+ * Create a cache key for member type lookup.
124
+ */
125
+ const makeMemberCacheKey = (fqName, memberName, typeArgs) => {
126
+ if (typeArgs && typeArgs.length > 0) {
127
+ return `${fqName}:${memberName}:${JSON.stringify(typeArgs)}`;
128
+ }
129
+ return `${fqName}:${memberName}`;
130
+ };
131
+ /**
132
+ * Create a cache key for nominal lookup.
133
+ */
134
+ const makeNominalLookupKey = (fqName, typeArgs, memberName) => {
135
+ return `${fqName}:${JSON.stringify(typeArgs)}:${memberName}`;
136
+ };
137
+ // Helper to check if type is null/undefined primitive
138
+ const isNullishPrimitive = (t) => {
139
+ return (t.kind === "primitiveType" &&
140
+ (t.name === "null" || t.name === "undefined"));
141
+ };
142
+ // Use makeNominalLookupKey to suppress unused warning
143
+ void makeNominalLookupKey;
144
+ // ─────────────────────────────────────────────────────────────────────────
145
+ // RAW SIGNATURE EXTRACTION
146
+ // ─────────────────────────────────────────────────────────────────────────
147
+ /**
148
+ * Get or compute raw signature info from SignatureId.
149
+ * Caches the result for subsequent calls.
150
+ */
151
+ const getRawSignature = (sigId) => {
152
+ const cached = signatureRawCache.get(sigId.id);
153
+ if (cached)
154
+ return cached;
155
+ const sigInfo = handleRegistry.getSignature(sigId);
156
+ if (!sigInfo)
157
+ return undefined;
158
+ // Convert parameter types from TypeNodes to IrTypes
159
+ const parameterTypes = sigInfo.parameters.map((p) => (p.typeNode ? convertTypeNode(p.typeNode) : undefined));
160
+ // Extract parameter modes
161
+ const parameterModes = sigInfo.parameters.map((p) => p.mode ?? "value");
162
+ // Extract parameter names
163
+ const parameterNames = sigInfo.parameters.map((p) => p.name);
164
+ // Extract type parameters
165
+ const typeParameters = (sigInfo.typeParameters ?? []).map((tp) => ({
166
+ name: tp.name,
167
+ constraint: tp.constraintNode
168
+ ? convertTypeNode(tp.constraintNode)
169
+ : undefined,
170
+ defaultType: tp.defaultNode ? convertTypeNode(tp.defaultNode) : undefined,
171
+ }));
172
+ const isConstructor = sigInfo.declaringMemberName === "constructor";
173
+ // Convert return type
174
+ const returnType = (() => {
175
+ if (sigInfo.returnTypeNode)
176
+ return convertTypeNode(sigInfo.returnTypeNode);
177
+ // Class constructor declarations do not have return type annotations in TS syntax.
178
+ // Deterministically synthesize the constructed instance type using the declaring
179
+ // identity captured in Binding and the (class) type parameters captured for the
180
+ // constructor signature.
181
+ if (isConstructor && sigInfo.declaringTypeTsName) {
182
+ const typeArguments = typeParameters.map((tp) => ({ kind: "typeParameterType", name: tp.name }));
183
+ return {
184
+ kind: "referenceType",
185
+ name: sigInfo.declaringTypeTsName,
186
+ ...(typeArguments.length > 0 ? { typeArguments } : {}),
187
+ };
188
+ }
189
+ return voidType;
190
+ })();
191
+ // Extract type predicate (already extracted in Binding at registration time)
192
+ let typePredicate;
193
+ if (sigInfo.typePredicate) {
194
+ const pred = sigInfo.typePredicate;
195
+ const targetType = convertTypeNode(pred.targetTypeNode);
196
+ if (pred.kind === "param") {
197
+ typePredicate = {
198
+ kind: "param",
199
+ parameterIndex: pred.parameterIndex,
200
+ targetType,
201
+ };
202
+ }
203
+ else {
204
+ typePredicate = {
205
+ kind: "this",
206
+ targetType,
207
+ };
208
+ }
209
+ }
210
+ const rawSig = {
211
+ parameterTypes,
212
+ returnType,
213
+ parameterModes,
214
+ typeParameters,
215
+ parameterNames,
216
+ typePredicate,
217
+ declaringTypeTsName: sigInfo.declaringTypeTsName,
218
+ declaringMemberName: sigInfo.declaringMemberName,
219
+ };
220
+ signatureRawCache.set(sigId.id, rawSig);
221
+ return rawSig;
222
+ };
223
+ // ─────────────────────────────────────────────────────────────────────────
224
+ // STEP 5: TYPESYSTEM ALGORITHM IMPLEMENTATIONS
225
+ // ─────────────────────────────────────────────────────────────────────────
226
+ /**
227
+ * Resolve a surface name to a canonical TypeId.
228
+ *
229
+ * Order:
230
+ * 1) AliasTable (primitives/globals/System.* canonicalization)
231
+ * 2) UnifiedTypeCatalog by tsName
232
+ * 3) UnifiedTypeCatalog by clrName
233
+ */
234
+ const resolveTypeIdByName = (name) => {
235
+ return (aliasTable.get(name) ??
236
+ unifiedCatalog.resolveTsName(name) ??
237
+ unifiedCatalog.resolveClrName(name));
238
+ };
239
+ /**
240
+ * Normalize a receiver type to nominal form for member lookup.
241
+ *
242
+ * Phase 6: Returns TypeId + typeArgs for TypeId-based NominalEnv.
243
+ *
244
+ * ALICE'S RULE R3: Primitive-to-nominal bridging is part of TypeSystem.
245
+ */
246
+ const normalizeToNominal = (type) => {
247
+ if (type.kind === "referenceType") {
248
+ const typeId = (type.resolvedClrType
249
+ ? resolveTypeIdByName(type.resolvedClrType)
250
+ : undefined) ?? resolveTypeIdByName(type.name);
251
+ if (!typeId)
252
+ return undefined;
253
+ return { typeId, typeArgs: type.typeArguments ?? [] };
254
+ }
255
+ if (type.kind === "primitiveType") {
256
+ const typeId = resolveTypeIdByName(type.name);
257
+ if (!typeId)
258
+ return undefined;
259
+ return { typeId, typeArgs: [] };
260
+ }
261
+ if (type.kind === "arrayType") {
262
+ const arrayTypeId = resolveTypeIdByName("Array");
263
+ if (!arrayTypeId)
264
+ return undefined;
265
+ return { typeId: arrayTypeId, typeArgs: [type.elementType] };
266
+ }
267
+ return undefined;
268
+ };
269
+ /**
270
+ * Convert a nominal CLR delegate type to an IrFunctionType by reading its Invoke signature.
271
+ *
272
+ * This is used for deterministic lambda typing when the expected type is a delegate
273
+ * (e.g., custom delegates from CLR metadata).
274
+ */
275
+ const delegateToFunctionType = (type) => {
276
+ // Expression<TDelegate> wrapper: treat as its underlying delegate type for
277
+ // deterministic lambda contextual typing.
278
+ //
279
+ // This models C#'s implicit lambda conversion to Expression<Func<...>>:
280
+ // the TypeScript surface uses Expression<TDelegate>, but lambdas should be
281
+ // typed against the delegate shape.
282
+ if (type.kind === "referenceType" &&
283
+ type.name === "Expression_1" &&
284
+ (type.typeArguments?.length ?? 0) === 1) {
285
+ const inner = type.typeArguments?.[0];
286
+ if (!inner)
287
+ return undefined;
288
+ if (inner.kind === "functionType")
289
+ return inner;
290
+ return delegateToFunctionType(inner);
291
+ }
292
+ const normalized = normalizeToNominal(type);
293
+ if (!normalized)
294
+ return undefined;
295
+ const entry = unifiedCatalog.getByTypeId(normalized.typeId);
296
+ if (!entry || entry.kind !== "delegate")
297
+ return undefined;
298
+ const invokeMember = unifiedCatalog.getMember(normalized.typeId, "Invoke") ??
299
+ unifiedCatalog.getMember(normalized.typeId, "invoke");
300
+ const invokeSig = invokeMember?.signatures?.[0];
301
+ if (!invokeSig)
302
+ return undefined;
303
+ const typeParams = unifiedCatalog.getTypeParameters(normalized.typeId);
304
+ const subst = new Map();
305
+ for (let i = 0; i < Math.min(typeParams.length, normalized.typeArgs.length); i++) {
306
+ const tp = typeParams[i];
307
+ const arg = normalized.typeArgs[i];
308
+ if (tp && arg)
309
+ subst.set(tp.name, arg);
310
+ }
311
+ const substitute = (t) => subst.size > 0 ? irSubstitute(t, subst) : t;
312
+ const parameters = invokeSig.parameters.map((p) => {
313
+ const paramType = substitute(p.type);
314
+ return {
315
+ kind: "parameter",
316
+ pattern: {
317
+ kind: "identifierPattern",
318
+ name: p.name,
319
+ ...(paramType ? { type: paramType } : {}),
320
+ },
321
+ type: paramType,
322
+ initializer: undefined,
323
+ isOptional: p.isOptional,
324
+ isRest: p.isRest,
325
+ passing: p.mode,
326
+ };
327
+ });
328
+ return {
329
+ kind: "functionType",
330
+ parameters,
331
+ returnType: substitute(invokeSig.returnType),
332
+ };
333
+ };
334
+ /**
335
+ * Look up a member on a structural (object) type.
336
+ */
337
+ const lookupStructuralMember = (type, memberName, site) => {
338
+ if (type.kind === "objectType") {
339
+ const member = type.members.find((m) => m.name === memberName);
340
+ if (member) {
341
+ if (member.kind === "propertySignature") {
342
+ return member.type;
343
+ }
344
+ // Method signature - return function type using the same parameters
345
+ if (member.kind === "methodSignature") {
346
+ const funcType = {
347
+ kind: "functionType",
348
+ parameters: member.parameters,
349
+ returnType: member.returnType ?? voidType,
350
+ };
351
+ return funcType;
352
+ }
353
+ }
354
+ }
355
+ if (type.kind === "referenceType" &&
356
+ type.structuralMembers &&
357
+ type.structuralMembers.length > 0) {
358
+ const member = type.structuralMembers.find((m) => m.name === memberName);
359
+ if (member) {
360
+ if (member.kind === "propertySignature") {
361
+ return member.type;
362
+ }
363
+ if (member.kind === "methodSignature") {
364
+ const funcType = {
365
+ kind: "functionType",
366
+ parameters: member.parameters,
367
+ returnType: member.returnType ?? voidType,
368
+ };
369
+ return funcType;
370
+ }
371
+ }
372
+ }
373
+ emitDiagnostic("TSN5203", `Member '${memberName}' not found on structural type`, site);
374
+ return unknownType;
375
+ };
376
+ /**
377
+ * Compute receiver substitution for a method call.
378
+ *
379
+ * Given a receiver type (e.g., Array<string>) and a declaring type's TS name,
380
+ * computes the substitution map for class type parameters.
381
+ *
382
+ * Phase 6: Uses TypeId-based NominalEnv.getInstantiation().
383
+ */
384
+ const computeReceiverSubstitution = (receiverType, declaringTypeTsName, _declaringMemberName) => {
385
+ const normalized = normalizeToNominal(receiverType);
386
+ if (!normalized)
387
+ return undefined;
388
+ const declaringTypeId = resolveTypeIdByName(declaringTypeTsName);
389
+ if (!declaringTypeId)
390
+ return undefined;
391
+ return nominalEnv.getInstantiation(normalized.typeId, normalized.typeArgs, declaringTypeId);
392
+ };
393
+ // ─────────────────────────────────────────────────────────────────────────
394
+ // typeOfDecl — Get declared type of a declaration
395
+ // ─────────────────────────────────────────────────────────────────────────
396
+ /**
397
+ * Derive IrType from NumericKind (deterministic, no TypeScript).
398
+ * Mirrors the logic in literals.ts deriveTypeFromNumericIntent.
399
+ */
400
+ const deriveTypeFromNumericKind = (kind) => {
401
+ if (kind === "Int32")
402
+ return { kind: "referenceType", name: "int" };
403
+ if (kind === "Int64")
404
+ return { kind: "referenceType", name: "long" };
405
+ if (kind === "Double")
406
+ return { kind: "primitiveType", name: "number" };
407
+ if (kind === "Single")
408
+ return { kind: "referenceType", name: "float" };
409
+ if (kind === "Byte")
410
+ return { kind: "referenceType", name: "byte" };
411
+ if (kind === "Int16")
412
+ return { kind: "referenceType", name: "short" };
413
+ if (kind === "UInt32")
414
+ return { kind: "referenceType", name: "uint" };
415
+ if (kind === "UInt64")
416
+ return { kind: "referenceType", name: "ulong" };
417
+ if (kind === "UInt16")
418
+ return { kind: "referenceType", name: "ushort" };
419
+ if (kind === "SByte")
420
+ return { kind: "referenceType", name: "sbyte" };
421
+ // Default to double for unknown
422
+ return { kind: "primitiveType", name: "number" };
423
+ };
424
+ const unwrapParens = (expr) => {
425
+ let current = expr;
426
+ while (ts.isParenthesizedExpression(current)) {
427
+ current = current.expression;
428
+ }
429
+ return current;
430
+ };
431
+ const isLambdaExpression = (expr) => {
432
+ const unwrapped = unwrapParens(expr);
433
+ return ts.isArrowFunction(unwrapped) || ts.isFunctionExpression(unwrapped);
434
+ };
435
+ const getNumericKindFromIrType = (type) => {
436
+ if (type.kind === "primitiveType" && type.name === "number")
437
+ return "Double";
438
+ if (type.kind === "primitiveType") {
439
+ return TSONIC_TO_NUMERIC_KIND.get(type.name);
440
+ }
441
+ if (type.kind === "referenceType") {
442
+ return TSONIC_TO_NUMERIC_KIND.get(type.name);
443
+ }
444
+ return undefined;
445
+ };
446
+ /**
447
+ * Deterministically infer an expression's type using only:
448
+ * - local lambda parameter environment
449
+ * - declaration types (typeOfDecl)
450
+ * - numeric literal lexeme rules
451
+ *
452
+ * This is intentionally small: it's used only to type lambda bodies for
453
+ * initializer-driven generic inference (e.g., `Enumerable.select(..., x => x * 2)`).
454
+ */
455
+ const inferExpressionType = (expr, env) => {
456
+ const unwrapped = unwrapParens(expr);
457
+ if (ts.isCallExpression(unwrapped)) {
458
+ return tryInferReturnTypeFromCallExpression(unwrapped, env);
459
+ }
460
+ if (ts.isNewExpression(unwrapped)) {
461
+ const sigId = resolveConstructorSignature(unwrapped);
462
+ if (!sigId)
463
+ return undefined;
464
+ const explicitTypeArgs = unwrapped.typeArguments && unwrapped.typeArguments.length > 0
465
+ ? unwrapped.typeArguments.map((ta) => convertTypeNode(ta))
466
+ : undefined;
467
+ const argumentCount = unwrapped.arguments?.length ?? 0;
468
+ const argTypesWorking = Array(argumentCount).fill(undefined);
469
+ const args = unwrapped.arguments ?? [];
470
+ for (let i = 0; i < args.length; i++) {
471
+ const arg = args[i];
472
+ if (!arg)
473
+ continue;
474
+ if (ts.isSpreadElement(arg))
475
+ continue;
476
+ if (isLambdaExpression(arg))
477
+ continue;
478
+ const t = inferExpressionType(arg, env);
479
+ if (t && t.kind !== "unknownType") {
480
+ argTypesWorking[i] = t;
481
+ }
482
+ }
483
+ const resolved = resolveCall({
484
+ sigId,
485
+ argumentCount,
486
+ explicitTypeArgs,
487
+ argTypes: argTypesWorking,
488
+ });
489
+ return resolved.returnType.kind === "unknownType"
490
+ ? undefined
491
+ : resolved.returnType;
492
+ }
493
+ if (ts.isPropertyAccessExpression(unwrapped)) {
494
+ const receiverType = inferExpressionType(unwrapped.expression, env);
495
+ if (!receiverType || receiverType.kind === "unknownType")
496
+ return undefined;
497
+ const memberType = typeOfMember(receiverType, {
498
+ kind: "byName",
499
+ name: unwrapped.name.text,
500
+ });
501
+ return memberType.kind === "unknownType" ? undefined : memberType;
502
+ }
503
+ if (ts.isElementAccessExpression(unwrapped)) {
504
+ const objectType = inferExpressionType(unwrapped.expression, env);
505
+ if (!objectType || objectType.kind === "unknownType")
506
+ return undefined;
507
+ if (objectType.kind === "arrayType") {
508
+ return objectType.elementType;
509
+ }
510
+ if (objectType.kind === "dictionaryType") {
511
+ return objectType.valueType;
512
+ }
513
+ if (objectType.kind === "primitiveType" && objectType.name === "string") {
514
+ return { kind: "primitiveType", name: "string" };
515
+ }
516
+ return undefined;
517
+ }
518
+ if (ts.isIdentifier(unwrapped)) {
519
+ const fromEnv = env.get(unwrapped.text);
520
+ if (fromEnv)
521
+ return fromEnv;
522
+ const declId = resolveIdentifier(unwrapped);
523
+ if (!declId)
524
+ return undefined;
525
+ const t = typeOfDecl(declId);
526
+ return t.kind === "unknownType" ? undefined : t;
527
+ }
528
+ if (ts.isNumericLiteral(unwrapped)) {
529
+ const numericKind = inferNumericKindFromRaw(unwrapped.getText());
530
+ return deriveTypeFromNumericKind(numericKind);
531
+ }
532
+ if (ts.isStringLiteral(unwrapped)) {
533
+ return { kind: "primitiveType", name: "string" };
534
+ }
535
+ if (unwrapped.kind === ts.SyntaxKind.TrueKeyword ||
536
+ unwrapped.kind === ts.SyntaxKind.FalseKeyword) {
537
+ return { kind: "primitiveType", name: "boolean" };
538
+ }
539
+ if (ts.isPrefixUnaryExpression(unwrapped)) {
540
+ if (unwrapped.operator === ts.SyntaxKind.ExclamationToken) {
541
+ return { kind: "primitiveType", name: "boolean" };
542
+ }
543
+ return inferExpressionType(unwrapped.operand, env);
544
+ }
545
+ if (ts.isBinaryExpression(unwrapped)) {
546
+ const op = unwrapped.operatorToken.kind;
547
+ // Comparisons / equality always return boolean.
548
+ if (op === ts.SyntaxKind.EqualsEqualsToken ||
549
+ op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
550
+ op === ts.SyntaxKind.ExclamationEqualsToken ||
551
+ op === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
552
+ op === ts.SyntaxKind.LessThanToken ||
553
+ op === ts.SyntaxKind.LessThanEqualsToken ||
554
+ op === ts.SyntaxKind.GreaterThanToken ||
555
+ op === ts.SyntaxKind.GreaterThanEqualsToken) {
556
+ return { kind: "primitiveType", name: "boolean" };
557
+ }
558
+ if (op === ts.SyntaxKind.AmpersandAmpersandToken ||
559
+ op === ts.SyntaxKind.BarBarToken) {
560
+ return { kind: "primitiveType", name: "boolean" };
561
+ }
562
+ if (op === ts.SyntaxKind.PlusToken ||
563
+ op === ts.SyntaxKind.MinusToken ||
564
+ op === ts.SyntaxKind.AsteriskToken ||
565
+ op === ts.SyntaxKind.SlashToken ||
566
+ op === ts.SyntaxKind.PercentToken) {
567
+ const leftType = inferExpressionType(unwrapped.left, env);
568
+ const rightType = inferExpressionType(unwrapped.right, env);
569
+ if (!leftType || !rightType)
570
+ return undefined;
571
+ // String concatenation
572
+ if (op === ts.SyntaxKind.PlusToken &&
573
+ ((leftType.kind === "primitiveType" && leftType.name === "string") ||
574
+ (rightType.kind === "primitiveType" && rightType.name === "string"))) {
575
+ return { kind: "primitiveType", name: "string" };
576
+ }
577
+ const leftKind = getNumericKindFromIrType(leftType);
578
+ const rightKind = getNumericKindFromIrType(rightType);
579
+ if (!leftKind || !rightKind)
580
+ return undefined;
581
+ return deriveTypeFromNumericKind(getBinaryResultKind(leftKind, rightKind));
582
+ }
583
+ }
584
+ return undefined;
585
+ };
586
+ const inferLambdaType = (expr, expectedType) => {
587
+ const unwrapped = unwrapParens(expr);
588
+ if (!ts.isArrowFunction(unwrapped) && !ts.isFunctionExpression(unwrapped)) {
589
+ return undefined;
590
+ }
591
+ const expectedFnType = expectedType?.kind === "functionType"
592
+ ? expectedType
593
+ : expectedType
594
+ ? delegateToFunctionType(expectedType)
595
+ : undefined;
596
+ const parameters = unwrapped.parameters.map((p, index) => {
597
+ const name = ts.isIdentifier(p.name) ? p.name.text : `arg${index}`;
598
+ const paramType = p.type
599
+ ? convertTypeNode(p.type)
600
+ : expectedFnType?.parameters[index]?.type;
601
+ return {
602
+ kind: "parameter",
603
+ pattern: {
604
+ kind: "identifierPattern",
605
+ name,
606
+ },
607
+ type: paramType,
608
+ initializer: undefined,
609
+ isOptional: !!p.questionToken,
610
+ isRest: !!p.dotDotDotToken,
611
+ passing: "value",
612
+ };
613
+ });
614
+ const env = new Map();
615
+ for (const p of parameters) {
616
+ if (p.pattern.kind === "identifierPattern" &&
617
+ p.pattern.name &&
618
+ p.type) {
619
+ env.set(p.pattern.name, p.type);
620
+ }
621
+ }
622
+ const explicitReturnType = "type" in unwrapped && unwrapped.type ? convertTypeNode(unwrapped.type) : undefined;
623
+ const expectedReturnType = expectedFnType?.returnType;
624
+ const inferredReturnType = explicitReturnType ??
625
+ (expectedReturnType && !containsTypeParameter(expectedReturnType)
626
+ ? expectedReturnType
627
+ : undefined) ??
628
+ (() => {
629
+ if (ts.isBlock(unwrapped.body)) {
630
+ const returns = [];
631
+ const visit = (n) => {
632
+ if (ts.isFunctionLike(n) && n !== unwrapped)
633
+ return;
634
+ if (ts.isReturnStatement(n) && n.expression) {
635
+ returns.push(n.expression);
636
+ }
637
+ n.forEachChild(visit);
638
+ };
639
+ unwrapped.body.forEachChild(visit);
640
+ if (returns.length === 0)
641
+ return { kind: "voidType" };
642
+ const first = inferExpressionType(returns[0], env);
643
+ if (!first)
644
+ return undefined;
645
+ for (let i = 1; i < returns.length; i++) {
646
+ const t = inferExpressionType(returns[i], env);
647
+ if (!t || !typesEqual(t, first))
648
+ return undefined;
649
+ }
650
+ return first;
651
+ }
652
+ return inferExpressionType(unwrapped.body, env);
653
+ })();
654
+ if (!inferredReturnType)
655
+ return undefined;
656
+ return {
657
+ kind: "functionType",
658
+ parameters,
659
+ returnType: inferredReturnType,
660
+ };
661
+ };
662
+ /**
663
+ * Try to infer type from a variable declaration's literal initializer.
664
+ *
665
+ * DETERMINISM: Uses the raw lexeme form of the literal, not TS computed types.
666
+ * Only handles simple literal initializers:
667
+ * - Numeric literals → inferred via inferNumericKindFromRaw
668
+ * - String literals → primitiveType("string")
669
+ * - Boolean literals → primitiveType("boolean")
670
+ *
671
+ * Returns undefined if the initializer is not a simple literal.
672
+ */
673
+ const tryInferTypeFromLiteralInitializer = (declNode) => {
674
+ // TypeScript's VariableDeclaration has an `initializer` property
675
+ const decl = declNode;
676
+ // Must have an initializer
677
+ if (!decl.initializer)
678
+ return undefined;
679
+ const init = decl.initializer;
680
+ if (init.kind === ts.SyntaxKind.NumericLiteral && init.getText) {
681
+ const raw = init.getText();
682
+ const numericKind = inferNumericKindFromRaw(raw);
683
+ return deriveTypeFromNumericKind(numericKind);
684
+ }
685
+ if (init.kind === ts.SyntaxKind.StringLiteral) {
686
+ return { kind: "primitiveType", name: "string" };
687
+ }
688
+ if (init.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral ||
689
+ init.kind === ts.SyntaxKind.TemplateExpression) {
690
+ return { kind: "primitiveType", name: "string" };
691
+ }
692
+ if (init.kind === ts.SyntaxKind.TrueKeyword ||
693
+ init.kind === ts.SyntaxKind.FalseKeyword) {
694
+ return { kind: "primitiveType", name: "boolean" };
695
+ }
696
+ // Not a simple literal - cannot infer
697
+ return undefined;
698
+ };
699
+ /**
700
+ * Try to infer type from a variable declaration's initializer using only
701
+ * deterministic sources (declarations + explicit syntax).
702
+ *
703
+ * Handles:
704
+ * - simple literals (delegates to tryInferTypeFromLiteralInitializer)
705
+ * - call expressions where the callee has an explicit declared return type
706
+ * - new expressions with explicit type arguments (or best-effort nominal type)
707
+ * - identifier initializers (propagate deterministically)
708
+ */
709
+ const tryInferReturnTypeFromCallExpression = (call, env) => {
710
+ const sigId = resolveCallSignature(call);
711
+ if (!sigId)
712
+ return undefined;
713
+ const explicitTypeArgs = call.typeArguments && call.typeArguments.length > 0
714
+ ? call.typeArguments.map((ta) => convertTypeNode(ta))
715
+ : undefined;
716
+ const receiverType = (() => {
717
+ if (!ts.isPropertyAccessExpression(call.expression))
718
+ return undefined;
719
+ const receiverExpr = call.expression.expression;
720
+ if (!ts.isIdentifier(receiverExpr))
721
+ return undefined;
722
+ const receiverDeclId = resolveIdentifier(receiverExpr);
723
+ if (!receiverDeclId)
724
+ return undefined;
725
+ const receiver = typeOfDecl(receiverDeclId);
726
+ return receiver.kind === "unknownType" ? undefined : receiver;
727
+ })();
728
+ const argumentCount = call.arguments.length;
729
+ // Two-pass: resolve once to get expected parameter types, then infer non-lambda args,
730
+ // then infer lambda arg types (from expected types + body), then final resolve.
731
+ const initialResolved = resolveCall({
732
+ sigId,
733
+ argumentCount,
734
+ receiverType,
735
+ explicitTypeArgs,
736
+ });
737
+ const initialParameterTypes = initialResolved.parameterTypes;
738
+ const argTypesWorking = Array(argumentCount).fill(undefined);
739
+ for (let index = 0; index < call.arguments.length; index++) {
740
+ const arg = call.arguments[index];
741
+ if (!arg)
742
+ continue;
743
+ if (ts.isSpreadElement(arg))
744
+ continue;
745
+ if (isLambdaExpression(arg))
746
+ continue;
747
+ if (ts.isNumericLiteral(arg)) {
748
+ const numericKind = inferNumericKindFromRaw(arg.getText());
749
+ argTypesWorking[index] = deriveTypeFromNumericKind(numericKind);
750
+ continue;
751
+ }
752
+ if (ts.isStringLiteral(arg)) {
753
+ argTypesWorking[index] = { kind: "primitiveType", name: "string" };
754
+ continue;
755
+ }
756
+ if (arg.kind === ts.SyntaxKind.TrueKeyword ||
757
+ arg.kind === ts.SyntaxKind.FalseKeyword) {
758
+ argTypesWorking[index] = {
759
+ kind: "primitiveType",
760
+ name: "boolean",
761
+ };
762
+ continue;
763
+ }
764
+ if (ts.isIdentifier(arg)) {
765
+ const argDeclId = resolveIdentifier(arg);
766
+ if (!argDeclId)
767
+ continue;
768
+ const t = typeOfDecl(argDeclId);
769
+ if (t.kind !== "unknownType") {
770
+ argTypesWorking[index] = t;
771
+ }
772
+ continue;
773
+ }
774
+ if (ts.isCallExpression(arg)) {
775
+ const t = tryInferReturnTypeFromCallExpression(arg, env);
776
+ if (t) {
777
+ argTypesWorking[index] = t;
778
+ }
779
+ continue;
780
+ }
781
+ if (ts.isNewExpression(arg)) {
782
+ const nestedSigId = resolveConstructorSignature(arg);
783
+ if (!nestedSigId)
784
+ continue;
785
+ const nestedExplicitTypeArgs = arg.typeArguments && arg.typeArguments.length > 0
786
+ ? arg.typeArguments.map((ta) => convertTypeNode(ta))
787
+ : undefined;
788
+ const nestedResolved = resolveCall({
789
+ sigId: nestedSigId,
790
+ argumentCount: arg.arguments?.length ?? 0,
791
+ explicitTypeArgs: nestedExplicitTypeArgs,
792
+ });
793
+ if (nestedResolved.returnType.kind !== "unknownType") {
794
+ argTypesWorking[index] = nestedResolved.returnType;
795
+ }
796
+ continue;
797
+ }
798
+ // Fallback: infer from a small deterministic expression set (identifiers, literals,
799
+ // arithmetic, nested member/index access, calls, etc).
800
+ const t = inferExpressionType(arg, env);
801
+ if (t && t.kind !== "unknownType") {
802
+ argTypesWorking[index] = t;
803
+ continue;
804
+ }
805
+ }
806
+ const lambdaContextResolved = resolveCall({
807
+ sigId,
808
+ argumentCount,
809
+ receiverType,
810
+ explicitTypeArgs,
811
+ argTypes: argTypesWorking,
812
+ });
813
+ const parameterTypesForLambdaContext = lambdaContextResolved.parameterTypes ?? initialParameterTypes;
814
+ for (let index = 0; index < call.arguments.length; index++) {
815
+ const arg = call.arguments[index];
816
+ if (!arg)
817
+ continue;
818
+ if (ts.isSpreadElement(arg))
819
+ continue;
820
+ if (!isLambdaExpression(arg))
821
+ continue;
822
+ const expectedType = parameterTypesForLambdaContext[index];
823
+ const lambdaType = inferLambdaType(arg, expectedType);
824
+ if (lambdaType) {
825
+ argTypesWorking[index] = lambdaType;
826
+ }
827
+ }
828
+ const finalResolved = resolveCall({
829
+ sigId,
830
+ argumentCount,
831
+ receiverType,
832
+ explicitTypeArgs,
833
+ argTypes: argTypesWorking,
834
+ });
835
+ return finalResolved.returnType.kind === "unknownType"
836
+ ? undefined
837
+ : finalResolved.returnType;
838
+ };
839
+ const tryInferTypeFromInitializer = (declNode) => {
840
+ const literalType = tryInferTypeFromLiteralInitializer(declNode);
841
+ if (literalType)
842
+ return literalType;
843
+ if (!declNode || typeof declNode !== "object")
844
+ return undefined;
845
+ const node = declNode;
846
+ if (!ts.isVariableDeclaration(node))
847
+ return undefined;
848
+ const init = node.initializer;
849
+ if (!init)
850
+ return undefined;
851
+ // Explicit type assertions are deterministic sources for variable typing.
852
+ // This supports patterns like:
853
+ // const xs = numbers as unknown as LinqSeq<int>;
854
+ // where the user intentionally supplies the type at the assertion site.
855
+ if (ts.isAsExpression(init) || ts.isTypeAssertionExpression(init)) {
856
+ return convertTypeNode(init.type);
857
+ }
858
+ if (ts.isCallExpression(init)) {
859
+ return tryInferReturnTypeFromCallExpression(init, new Map());
860
+ }
861
+ if (ts.isArrayLiteralExpression(init)) {
862
+ // Deterministic array literal typing for variable declarations:
863
+ // infer `T[]` only when all element types are deterministically known and equal.
864
+ const elementTypes = [];
865
+ const emptyEnv = new Map();
866
+ for (const el of init.elements) {
867
+ if (ts.isOmittedExpression(el)) {
868
+ return undefined;
869
+ }
870
+ if (ts.isSpreadElement(el)) {
871
+ return undefined;
872
+ }
873
+ const t = inferExpressionType(el, emptyEnv);
874
+ if (!t || t.kind === "unknownType") {
875
+ return undefined;
876
+ }
877
+ elementTypes.push(t);
878
+ }
879
+ if (elementTypes.length === 0)
880
+ return undefined;
881
+ const first = elementTypes[0];
882
+ if (first && elementTypes.every((t) => typesEqual(t, first))) {
883
+ return { kind: "arrayType", elementType: first };
884
+ }
885
+ return undefined;
886
+ }
887
+ // Phase 15: NewExpression branch - use constructor signature with argTypes
888
+ if (ts.isNewExpression(init)) {
889
+ const sigId = resolveConstructorSignature(init);
890
+ if (!sigId)
891
+ return undefined;
892
+ const explicitTypeArgs = init.typeArguments && init.typeArguments.length > 0
893
+ ? init.typeArguments.map((ta) => convertTypeNode(ta))
894
+ : undefined;
895
+ // Derive argTypes conservatively from syntax (same pattern as CallExpression)
896
+ const args = init.arguments ?? [];
897
+ const argTypes = args.map((arg) => {
898
+ if (ts.isSpreadElement(arg))
899
+ return undefined;
900
+ if (ts.isNumericLiteral(arg)) {
901
+ const numericKind = inferNumericKindFromRaw(arg.getText());
902
+ return deriveTypeFromNumericKind(numericKind);
903
+ }
904
+ if (ts.isStringLiteral(arg)) {
905
+ return { kind: "primitiveType", name: "string" };
906
+ }
907
+ if (arg.kind === ts.SyntaxKind.TrueKeyword ||
908
+ arg.kind === ts.SyntaxKind.FalseKeyword) {
909
+ return { kind: "primitiveType", name: "boolean" };
910
+ }
911
+ if (ts.isIdentifier(arg)) {
912
+ const argDeclId = resolveIdentifier(arg);
913
+ if (!argDeclId)
914
+ return undefined;
915
+ const t = typeOfDecl(argDeclId);
916
+ return t.kind === "unknownType" ? undefined : t;
917
+ }
918
+ // Recursive handling for nested new expressions
919
+ if (ts.isNewExpression(arg)) {
920
+ const nestedSigId = resolveConstructorSignature(arg);
921
+ if (!nestedSigId)
922
+ return undefined;
923
+ const nestedExplicitTypeArgs = arg.typeArguments && arg.typeArguments.length > 0
924
+ ? arg.typeArguments.map((ta) => convertTypeNode(ta))
925
+ : undefined;
926
+ const nestedResolved = resolveCall({
927
+ sigId: nestedSigId,
928
+ argumentCount: arg.arguments?.length ?? 0,
929
+ explicitTypeArgs: nestedExplicitTypeArgs,
930
+ });
931
+ return nestedResolved.returnType.kind === "unknownType"
932
+ ? undefined
933
+ : nestedResolved.returnType;
934
+ }
935
+ return undefined;
936
+ });
937
+ // Resolve constructor call with argTypes for inference
938
+ const resolved = resolveCall({
939
+ sigId,
940
+ argumentCount: args.length,
941
+ explicitTypeArgs,
942
+ argTypes,
943
+ });
944
+ return resolved.returnType.kind === "unknownType"
945
+ ? undefined
946
+ : resolved.returnType;
947
+ }
948
+ if (ts.isIdentifier(init)) {
949
+ const sourceDeclId = resolveIdentifier(init);
950
+ if (!sourceDeclId)
951
+ return undefined;
952
+ const sourceType = typeOfDecl(sourceDeclId);
953
+ return sourceType.kind === "unknownType" ? undefined : sourceType;
954
+ }
955
+ // Property access: const output = response.outputStream
956
+ // DETERMINISTIC: Infer via TypeSystem member lookup on a typed receiver identifier.
957
+ if (ts.isPropertyAccessExpression(init)) {
958
+ const receiver = init.expression;
959
+ if (ts.isIdentifier(receiver)) {
960
+ const receiverDeclId = resolveIdentifier(receiver);
961
+ if (!receiverDeclId)
962
+ return undefined;
963
+ const receiverType = typeOfDecl(receiverDeclId);
964
+ if (receiverType.kind === "unknownType")
965
+ return undefined;
966
+ const memberType = typeOfMember(receiverType, {
967
+ kind: "byName",
968
+ name: init.name.text,
969
+ });
970
+ return memberType.kind === "unknownType" ? undefined : memberType;
971
+ }
972
+ }
973
+ return undefined;
974
+ };
975
+ const typeOfDecl = (declId) => {
976
+ // Check cache first
977
+ const cached = declTypeCache.get(declId.id);
978
+ if (cached)
979
+ return cached;
980
+ const declInfo = handleRegistry.getDecl(declId);
981
+ if (!declInfo) {
982
+ emitDiagnostic("TSN5203", "Cannot resolve declaration");
983
+ const result = unknownType;
984
+ declTypeCache.set(declId.id, result);
985
+ return result;
986
+ }
987
+ let result;
988
+ if (declInfo.typeNode) {
989
+ // Explicit type annotation - convert to IR
990
+ result = convertTypeNode(declInfo.typeNode);
991
+ }
992
+ else if (declInfo.kind === "class" || declInfo.kind === "interface") {
993
+ // Class/interface - return reference type
994
+ result = {
995
+ kind: "referenceType",
996
+ name: declInfo.fqName ?? "unknown",
997
+ };
998
+ }
999
+ else if (declInfo.kind === "function") {
1000
+ // Function without type annotation - need to build function type from signature
1001
+ // For now, return unknownType as we need the signature ID
1002
+ emitDiagnostic("TSN5201", `Function '${declInfo.fqName ?? "unknown"}' requires explicit return type`);
1003
+ result = unknownType;
1004
+ }
1005
+ else if (declInfo.kind === "variable" && declInfo.declNode) {
1006
+ // Variable without type annotation - infer from deterministic initializer
1007
+ const inferred = tryInferTypeFromInitializer(declInfo.declNode);
1008
+ if (inferred) {
1009
+ result = inferred;
1010
+ }
1011
+ else {
1012
+ // Not a simple literal - require explicit type annotation
1013
+ emitDiagnostic("TSN5201", `Declaration requires explicit type annotation`);
1014
+ result = unknownType;
1015
+ }
1016
+ }
1017
+ else {
1018
+ // Parameter or other declaration without type annotation
1019
+ emitDiagnostic("TSN5201", `Declaration requires explicit type annotation`);
1020
+ result = unknownType;
1021
+ }
1022
+ declTypeCache.set(declId.id, result);
1023
+ return result;
1024
+ };
1025
+ // ─────────────────────────────────────────────────────────────────────────
1026
+ // typeOfMember — Get declared type of a member (with inheritance substitution)
1027
+ // ─────────────────────────────────────────────────────────────────────────
1028
+ const typeOfMember = (receiver, member, site) => {
1029
+ const memberName = member.kind === "byName" ? member.name : "unknown"; // MemberId.name not defined yet
1030
+ // Common nullish unions (T | undefined | null) should behave like T for member lookup.
1031
+ // This preserves deterministic typing for patterns like:
1032
+ // const url = request.url; if (!url) return; url.absolutePath
1033
+ const effectiveReceiver = receiver.kind === "unionType"
1034
+ ? (() => {
1035
+ const nonNullish = receiver.types.filter((t) => t && !isNullishPrimitive(t));
1036
+ return nonNullish.length === 1 && nonNullish[0] ? nonNullish[0] : receiver;
1037
+ })()
1038
+ : receiver;
1039
+ // 1. Normalize receiver to nominal form
1040
+ const normalized = normalizeToNominal(effectiveReceiver);
1041
+ if (!normalized) {
1042
+ // Handle structural types (objectType)
1043
+ if (effectiveReceiver.kind === "objectType" ||
1044
+ (effectiveReceiver.kind === "referenceType" && effectiveReceiver.structuralMembers)) {
1045
+ return lookupStructuralMember(effectiveReceiver, memberName, site);
1046
+ }
1047
+ emitDiagnostic("TSN5203", `Cannot resolve member '${memberName}' on type`, site);
1048
+ return unknownType;
1049
+ }
1050
+ // 2. Check cache (use clrName as key for compatibility)
1051
+ const cacheKey = makeMemberCacheKey(normalized.typeId.stableId, memberName, normalized.typeArgs);
1052
+ const cached = memberDeclaredTypeCache.get(cacheKey);
1053
+ if (cached)
1054
+ return cached;
1055
+ // 3. Use NominalEnv to find declaring type + substitution (Phase 6: TypeId-based)
1056
+ const lookupResult = nominalEnv.findMemberDeclaringType(normalized.typeId, normalized.typeArgs, memberName);
1057
+ // 4a. If NominalEnv found the member, get its declared type from Universe
1058
+ if (lookupResult) {
1059
+ const memberEntry = unifiedCatalog.getMember(lookupResult.declaringTypeId, memberName);
1060
+ // Property/field member: return its declared type.
1061
+ const memberType = memberEntry?.type;
1062
+ if (memberType) {
1063
+ const result = irSubstitute(memberType, lookupResult.substitution);
1064
+ memberDeclaredTypeCache.set(cacheKey, result);
1065
+ return result;
1066
+ }
1067
+ // Method member: materialize a callable function type from the first signature.
1068
+ // Call resolution (resolveCall) uses SignatureId for overload selection; this
1069
+ // type is used only to keep member access expressions deterministic.
1070
+ const firstSig = memberEntry?.signatures?.[0];
1071
+ if (firstSig) {
1072
+ const funcType = {
1073
+ kind: "functionType",
1074
+ parameters: firstSig.parameters.map((p) => ({
1075
+ kind: "parameter",
1076
+ pattern: {
1077
+ kind: "identifierPattern",
1078
+ name: p.name,
1079
+ },
1080
+ type: p.type,
1081
+ initializer: undefined,
1082
+ isOptional: p.isOptional,
1083
+ isRest: p.isRest,
1084
+ passing: p.mode,
1085
+ })),
1086
+ returnType: firstSig.returnType,
1087
+ };
1088
+ const result = irSubstitute(funcType, lookupResult.substitution);
1089
+ memberDeclaredTypeCache.set(cacheKey, result);
1090
+ return result;
1091
+ }
1092
+ }
1093
+ // 5. Member not found anywhere
1094
+ emitDiagnostic("TSN5203", `Member '${memberName}' not found`, site);
1095
+ return unknownType;
1096
+ };
1097
+ // ─────────────────────────────────────────────────────────────────────────
1098
+ // resolveCall — THE HEART OF DETERMINISM
1099
+ // Resolve a call site: returns fully instantiated param/return types + modes
1100
+ // ─────────────────────────────────────────────────────────────────────────
1101
+ /**
1102
+ * Deterministically infer method type parameters from argument types.
1103
+ *
1104
+ * This is intentionally conservative: it only infers when it can unify
1105
+ * parameter and argument shapes without ambiguity.
1106
+ */
1107
+ const inferMethodTypeArgsFromArguments = (methodTypeParams, parameterTypes, argTypes) => {
1108
+ if (methodTypeParams.length === 0)
1109
+ return new Map();
1110
+ const methodTypeParamNames = new Set(methodTypeParams.map((p) => p.name));
1111
+ const substitution = new Map();
1112
+ const tryUnify = (parameterType, argumentType) => {
1113
+ // Method type parameter position: infer directly
1114
+ if (parameterType.kind === "typeParameterType") {
1115
+ if (!methodTypeParamNames.has(parameterType.name)) {
1116
+ // Not a method type parameter (could be outer generic) — ignore
1117
+ return true;
1118
+ }
1119
+ const existing = substitution.get(parameterType.name);
1120
+ if (existing) {
1121
+ // A self-mapping like `B -> B` can be produced when a lambda argument was typed
1122
+ // contextually from the unresolved expected signature. This provides no real
1123
+ // inference signal and must not block later concrete inference.
1124
+ if (existing.kind === "typeParameterType" &&
1125
+ existing.name === parameterType.name) {
1126
+ substitution.set(parameterType.name, argumentType);
1127
+ return true;
1128
+ }
1129
+ return typesEqual(existing, argumentType);
1130
+ }
1131
+ substitution.set(parameterType.name, argumentType);
1132
+ return true;
1133
+ }
1134
+ // Poison/any provides no deterministic information
1135
+ if (argumentType.kind === "unknownType" || argumentType.kind === "anyType") {
1136
+ return true;
1137
+ }
1138
+ // Expression<TDelegate> wrapper: infer through the underlying delegate shape.
1139
+ // This is required for Queryable APIs that use Expression<Func<...>>.
1140
+ if (parameterType.kind === "referenceType" &&
1141
+ parameterType.name === "Expression_1" &&
1142
+ (parameterType.typeArguments?.length ?? 0) === 1) {
1143
+ const inner = parameterType.typeArguments?.[0];
1144
+ return inner ? tryUnify(inner, argumentType) : true;
1145
+ }
1146
+ // Array<T> ↔ T[] unification
1147
+ if (parameterType.kind === "referenceType" &&
1148
+ parameterType.name === "Array" &&
1149
+ (parameterType.typeArguments?.length ?? 0) === 1 &&
1150
+ argumentType.kind === "arrayType") {
1151
+ const elementParam = parameterType.typeArguments?.[0];
1152
+ return elementParam ? tryUnify(elementParam, argumentType.elementType) : true;
1153
+ }
1154
+ // Union parameter type: allow deterministic inference through common nullish unions.
1155
+ // Example: constructor(value: T | null) with argument of type T.
1156
+ if (parameterType.kind === "unionType") {
1157
+ const nonNullish = parameterType.types.filter((t) => t && !isNullishPrimitive(t));
1158
+ const nullish = parameterType.types.filter((t) => t && isNullishPrimitive(t));
1159
+ const candidates = isNullishPrimitive(argumentType) ? nullish : nonNullish;
1160
+ if (candidates.length === 1) {
1161
+ const only = candidates[0];
1162
+ return only ? tryUnify(only, argumentType) : true;
1163
+ }
1164
+ // Conservative: ambiguous unions provide no deterministic signal.
1165
+ return true;
1166
+ }
1167
+ if (parameterType.kind === "arrayType" &&
1168
+ argumentType.kind === "referenceType" &&
1169
+ argumentType.name === "Array" &&
1170
+ (argumentType.typeArguments?.length ?? 0) === 1) {
1171
+ const elementArg = argumentType.typeArguments?.[0];
1172
+ return elementArg ? tryUnify(parameterType.elementType, elementArg) : true;
1173
+ }
1174
+ // Same-kind structural unification
1175
+ if (parameterType.kind !== argumentType.kind) {
1176
+ // Type mismatch provides no deterministic inference signal.
1177
+ return true;
1178
+ }
1179
+ switch (parameterType.kind) {
1180
+ case "primitiveType":
1181
+ return true;
1182
+ case "literalType":
1183
+ return true;
1184
+ case "referenceType": {
1185
+ const argRef = argumentType;
1186
+ const sameNominal = (() => {
1187
+ if (parameterType.typeId && argRef.typeId) {
1188
+ return parameterType.typeId.stableId === argRef.typeId.stableId;
1189
+ }
1190
+ return parameterType.name === argRef.name;
1191
+ })();
1192
+ // Direct generic unification when the nominals match
1193
+ if (sameNominal) {
1194
+ const paramArgs = parameterType.typeArguments ?? [];
1195
+ const argArgs = argRef.typeArguments ?? [];
1196
+ if (paramArgs.length !== argArgs.length)
1197
+ return true;
1198
+ for (let i = 0; i < paramArgs.length; i++) {
1199
+ const pa = paramArgs[i];
1200
+ const aa = argArgs[i];
1201
+ if (!pa || !aa)
1202
+ continue;
1203
+ if (!tryUnify(pa, aa))
1204
+ return false;
1205
+ }
1206
+ return true;
1207
+ }
1208
+ // Inheritance/interface unification: allow argumentType to flow through
1209
+ // its inheritance chain to the parameter type (e.g., List<T> → IEnumerable<T>).
1210
+ const paramNominal = normalizeToNominal(parameterType);
1211
+ const argNominal = normalizeToNominal(argRef);
1212
+ if (paramNominal && argNominal) {
1213
+ const inst = nominalEnv.getInstantiation(argNominal.typeId, argNominal.typeArgs, paramNominal.typeId);
1214
+ if (inst) {
1215
+ const targetTypeParams = unifiedCatalog.getTypeParameters(paramNominal.typeId);
1216
+ const instantiatedArgs = targetTypeParams.map((tp) => inst.get(tp.name));
1217
+ const paramArgs = parameterType.typeArguments ?? [];
1218
+ if (instantiatedArgs.every((t) => t !== undefined) &&
1219
+ paramArgs.length === instantiatedArgs.length) {
1220
+ for (let i = 0; i < paramArgs.length; i++) {
1221
+ const pa = paramArgs[i];
1222
+ const aa = instantiatedArgs[i];
1223
+ if (!pa || !aa)
1224
+ continue;
1225
+ if (!tryUnify(pa, aa))
1226
+ return false;
1227
+ }
1228
+ }
1229
+ }
1230
+ }
1231
+ return true;
1232
+ }
1233
+ case "arrayType":
1234
+ return tryUnify(parameterType.elementType, argumentType.elementType);
1235
+ case "tupleType": {
1236
+ const argTuple = argumentType;
1237
+ if (parameterType.elementTypes.length !== argTuple.elementTypes.length) {
1238
+ return true;
1239
+ }
1240
+ for (let i = 0; i < parameterType.elementTypes.length; i++) {
1241
+ const pe = parameterType.elementTypes[i];
1242
+ const ae = argTuple.elementTypes[i];
1243
+ if (!pe || !ae)
1244
+ continue;
1245
+ if (!tryUnify(pe, ae))
1246
+ return false;
1247
+ }
1248
+ return true;
1249
+ }
1250
+ case "functionType": {
1251
+ const argFn = argumentType;
1252
+ if (parameterType.parameters.length !== argFn.parameters.length) {
1253
+ return true;
1254
+ }
1255
+ for (let i = 0; i < parameterType.parameters.length; i++) {
1256
+ const pp = parameterType.parameters[i];
1257
+ const ap = argFn.parameters[i];
1258
+ const pt = pp?.type;
1259
+ const at = ap?.type;
1260
+ if (pt && at) {
1261
+ if (!tryUnify(pt, at))
1262
+ return false;
1263
+ }
1264
+ }
1265
+ return tryUnify(parameterType.returnType, argFn.returnType);
1266
+ }
1267
+ case "intersectionType":
1268
+ case "objectType":
1269
+ case "dictionaryType":
1270
+ // Conservative: only infer through these when shapes already match exactly.
1271
+ return true;
1272
+ case "voidType":
1273
+ case "neverType":
1274
+ return true;
1275
+ default:
1276
+ return true;
1277
+ }
1278
+ };
1279
+ const pairs = Math.min(parameterTypes.length, argTypes.length);
1280
+ for (let i = 0; i < pairs; i++) {
1281
+ const paramType = parameterTypes[i];
1282
+ const argType = argTypes[i];
1283
+ if (!paramType || !argType)
1284
+ continue;
1285
+ if (!tryUnify(paramType, argType))
1286
+ return undefined;
1287
+ }
1288
+ return substitution;
1289
+ };
1290
+ const containsMethodTypeParameter = (type, unresolved) => {
1291
+ if (type.kind === "typeParameterType")
1292
+ return unresolved.has(type.name);
1293
+ if (type.kind === "referenceType") {
1294
+ return (type.typeArguments ?? []).some((t) => t ? containsMethodTypeParameter(t, unresolved) : false);
1295
+ }
1296
+ if (type.kind === "arrayType") {
1297
+ return containsMethodTypeParameter(type.elementType, unresolved);
1298
+ }
1299
+ if (type.kind === "tupleType") {
1300
+ return type.elementTypes.some((t) => t ? containsMethodTypeParameter(t, unresolved) : false);
1301
+ }
1302
+ if (type.kind === "functionType") {
1303
+ const paramsContain = type.parameters.some((p) => p.type ? containsMethodTypeParameter(p.type, unresolved) : false);
1304
+ return paramsContain || containsMethodTypeParameter(type.returnType, unresolved);
1305
+ }
1306
+ if (type.kind === "unionType" || type.kind === "intersectionType") {
1307
+ return type.types.some((t) => t ? containsMethodTypeParameter(t, unresolved) : false);
1308
+ }
1309
+ if (type.kind === "objectType") {
1310
+ return type.members.some((m) => {
1311
+ if (m.kind === "propertySignature") {
1312
+ return containsMethodTypeParameter(m.type, unresolved);
1313
+ }
1314
+ if (m.kind === "methodSignature") {
1315
+ const paramsContain = m.parameters.some((p) => p.type ? containsMethodTypeParameter(p.type, unresolved) : false);
1316
+ return (paramsContain ||
1317
+ (m.returnType
1318
+ ? containsMethodTypeParameter(m.returnType, unresolved)
1319
+ : false));
1320
+ }
1321
+ return false;
1322
+ });
1323
+ }
1324
+ return false;
1325
+ };
1326
+ const normalizeCatalogTsName = (name) => {
1327
+ if (name.endsWith("$instance"))
1328
+ return name.slice(0, -"$instance".length);
1329
+ if (name.startsWith("__") && name.endsWith("$views")) {
1330
+ return name.slice("__".length, -"$views".length);
1331
+ }
1332
+ return name;
1333
+ };
1334
+ const isArityCompatible = (signature, argumentCount) => {
1335
+ const params = signature.parameters;
1336
+ if (params.length === 0)
1337
+ return argumentCount === 0;
1338
+ // Rest parameter can absorb any extra args.
1339
+ const restIndex = params.findIndex((p) => p.isRest);
1340
+ if (restIndex >= 0) {
1341
+ // Only support `...rest` in the last position.
1342
+ if (restIndex !== params.length - 1)
1343
+ return false;
1344
+ // Must supply all non-rest parameters.
1345
+ if (argumentCount < restIndex)
1346
+ return false;
1347
+ return true;
1348
+ }
1349
+ // Too many args for non-rest signature.
1350
+ if (argumentCount > params.length)
1351
+ return false;
1352
+ // Missing args must correspond to optional parameters.
1353
+ for (let i = argumentCount; i < params.length; i++) {
1354
+ const p = params[i];
1355
+ if (!p || !p.isOptional)
1356
+ return false;
1357
+ }
1358
+ return true;
1359
+ };
1360
+ const scoreSignatureMatch = (parameterTypes, argTypes, argumentCount) => {
1361
+ let score = 0;
1362
+ const pairs = Math.min(argumentCount, parameterTypes.length, argTypes.length);
1363
+ for (let i = 0; i < pairs; i++) {
1364
+ const pt = parameterTypes[i];
1365
+ const at = argTypes[i];
1366
+ if (!pt || !at)
1367
+ continue;
1368
+ if (typesEqual(pt, at)) {
1369
+ score += 3;
1370
+ continue;
1371
+ }
1372
+ const pNom = normalizeToNominal(pt);
1373
+ const aNom = normalizeToNominal(at);
1374
+ if (!pNom || !aNom)
1375
+ continue;
1376
+ if (pNom.typeId.stableId === aNom.typeId.stableId) {
1377
+ score += 2;
1378
+ continue;
1379
+ }
1380
+ const inst = nominalEnv.getInstantiation(aNom.typeId, aNom.typeArgs, pNom.typeId);
1381
+ if (inst)
1382
+ score += 1;
1383
+ }
1384
+ return score;
1385
+ };
1386
+ const tryResolveCallFromUnifiedCatalog = (declaringTypeTsName, declaringMemberName, query) => {
1387
+ const { argumentCount, receiverType, explicitTypeArgs, argTypes, } = query;
1388
+ if (!argTypes)
1389
+ return undefined;
1390
+ if (argTypes.length < argumentCount)
1391
+ return undefined;
1392
+ for (let i = 0; i < argumentCount; i++) {
1393
+ if (!argTypes[i])
1394
+ return undefined;
1395
+ }
1396
+ const catalogTypeName = normalizeCatalogTsName(declaringTypeTsName);
1397
+ const declaringTypeId = resolveTypeIdByName(catalogTypeName);
1398
+ if (!declaringTypeId)
1399
+ return undefined;
1400
+ const entry = unifiedCatalog.getByTypeId(declaringTypeId);
1401
+ if (!entry || entry.origin !== "assembly")
1402
+ return undefined;
1403
+ const member = unifiedCatalog.getMember(declaringTypeId, declaringMemberName) ??
1404
+ unifiedCatalog.getMember(declaringTypeId, declaringMemberName.charAt(0).toUpperCase() + declaringMemberName.slice(1));
1405
+ const candidates = member?.signatures;
1406
+ if (!candidates || candidates.length === 0)
1407
+ return undefined;
1408
+ const resolveCandidate = (signature) => {
1409
+ if (!isArityCompatible(signature, argumentCount))
1410
+ return undefined;
1411
+ let workingParams = signature.parameters.map((p) => p.type);
1412
+ let workingReturn = signature.returnType;
1413
+ // Receiver substitution (class type params) for instance calls.
1414
+ if (receiverType) {
1415
+ const receiverSubst = computeReceiverSubstitution(receiverType, catalogTypeName, declaringMemberName);
1416
+ if (receiverSubst && receiverSubst.size > 0) {
1417
+ workingParams = workingParams.map((p) => irSubstitute(p, receiverSubst));
1418
+ workingReturn = irSubstitute(workingReturn, receiverSubst);
1419
+ }
1420
+ }
1421
+ // Method type parameter substitution.
1422
+ const methodTypeParams = signature.typeParameters.map((tp) => ({
1423
+ name: tp.name,
1424
+ constraint: tp.constraint,
1425
+ defaultType: tp.defaultType,
1426
+ }));
1427
+ if (methodTypeParams.length > 0) {
1428
+ const callSubst = new Map();
1429
+ if (explicitTypeArgs) {
1430
+ for (let i = 0; i < Math.min(explicitTypeArgs.length, methodTypeParams.length); i++) {
1431
+ const param = methodTypeParams[i];
1432
+ const arg = explicitTypeArgs[i];
1433
+ if (param && arg) {
1434
+ callSubst.set(param.name, arg);
1435
+ }
1436
+ }
1437
+ }
1438
+ const paramsForInference = callSubst.size > 0
1439
+ ? workingParams.map((p) => irSubstitute(p, callSubst))
1440
+ : workingParams;
1441
+ const inferred = inferMethodTypeArgsFromArguments(methodTypeParams, paramsForInference, argTypes);
1442
+ if (!inferred)
1443
+ return undefined;
1444
+ for (const [name, inferredType] of inferred) {
1445
+ const existing = callSubst.get(name);
1446
+ if (existing) {
1447
+ if (!typesEqual(existing, inferredType))
1448
+ return undefined;
1449
+ continue;
1450
+ }
1451
+ callSubst.set(name, inferredType);
1452
+ }
1453
+ for (const tp of methodTypeParams) {
1454
+ if (!callSubst.has(tp.name) && tp.defaultType) {
1455
+ callSubst.set(tp.name, tp.defaultType);
1456
+ }
1457
+ }
1458
+ if (callSubst.size > 0) {
1459
+ workingParams = workingParams.map((p) => irSubstitute(p, callSubst));
1460
+ workingReturn = irSubstitute(workingReturn, callSubst);
1461
+ }
1462
+ const unresolved = new Set(methodTypeParams
1463
+ .map((tp) => tp.name)
1464
+ .filter((name) => !callSubst.has(name)));
1465
+ if (unresolved.size > 0 &&
1466
+ containsMethodTypeParameter(workingReturn, unresolved)) {
1467
+ return undefined;
1468
+ }
1469
+ }
1470
+ return {
1471
+ parameterTypes: workingParams,
1472
+ parameterModes: signature.parameters.map((p) => p.mode),
1473
+ returnType: workingReturn,
1474
+ typePredicate: undefined,
1475
+ diagnostics: [],
1476
+ };
1477
+ };
1478
+ let best;
1479
+ for (const sig of candidates) {
1480
+ const resolved = resolveCandidate(sig);
1481
+ if (!resolved)
1482
+ continue;
1483
+ if (resolved.returnType.kind === "unknownType")
1484
+ continue;
1485
+ const candidate = {
1486
+ resolved,
1487
+ score: scoreSignatureMatch(resolved.parameterTypes, argTypes, argumentCount),
1488
+ typeParamCount: sig.typeParameters.length,
1489
+ parameterCount: sig.parameters.length,
1490
+ stableId: sig.stableId,
1491
+ };
1492
+ if (!best) {
1493
+ best = candidate;
1494
+ continue;
1495
+ }
1496
+ const better = candidate.score > best.score ||
1497
+ (candidate.score === best.score &&
1498
+ candidate.typeParamCount < best.typeParamCount) ||
1499
+ (candidate.score === best.score &&
1500
+ candidate.typeParamCount === best.typeParamCount &&
1501
+ candidate.parameterCount < best.parameterCount) ||
1502
+ (candidate.score === best.score &&
1503
+ candidate.typeParamCount === best.typeParamCount &&
1504
+ candidate.parameterCount === best.parameterCount &&
1505
+ candidate.stableId < best.stableId);
1506
+ if (better)
1507
+ best = candidate;
1508
+ }
1509
+ return best?.resolved;
1510
+ };
1511
+ const resolveCall = (query) => {
1512
+ const { sigId, argumentCount, receiverType, explicitTypeArgs, argTypes, site, } = query;
1513
+ // 1. Load raw signature (cached)
1514
+ const rawSig = getRawSignature(sigId);
1515
+ if (!rawSig) {
1516
+ // BINDING CONTRACT VIOLATION (Alice's spec): If Binding returned a
1517
+ // SignatureId, HandleRegistry.getSignature(sigId) MUST succeed.
1518
+ // This indicates a bug in Binding, not a normal runtime condition.
1519
+ //
1520
+ // However, we cannot throw during normal compilation as it would
1521
+ // crash the compiler. Instead, emit diagnostic and return poisoned
1522
+ // result with correct arity.
1523
+ emitDiagnostic("TSN5203", `Cannot resolve signature (Binding contract violation: ID ${sigId.id} not in HandleRegistry)`, site);
1524
+ return poisonedCall(argumentCount, diagnostics.slice());
1525
+ }
1526
+ // 2. Start with raw types
1527
+ let workingParams = [...rawSig.parameterTypes];
1528
+ let workingReturn = rawSig.returnType;
1529
+ let workingPredicate = rawSig.typePredicate;
1530
+ // 3. Compute receiver substitution (class type params)
1531
+ if (receiverType &&
1532
+ rawSig.declaringTypeTsName &&
1533
+ rawSig.declaringMemberName) {
1534
+ const receiverSubst = computeReceiverSubstitution(receiverType, rawSig.declaringTypeTsName, rawSig.declaringMemberName);
1535
+ if (receiverSubst && receiverSubst.size > 0) {
1536
+ workingParams = workingParams.map((p) => p ? irSubstitute(p, receiverSubst) : undefined);
1537
+ workingReturn = irSubstitute(workingReturn, receiverSubst);
1538
+ if (workingPredicate) {
1539
+ workingPredicate =
1540
+ workingPredicate.kind === "param"
1541
+ ? {
1542
+ ...workingPredicate,
1543
+ targetType: irSubstitute(workingPredicate.targetType, receiverSubst),
1544
+ }
1545
+ : {
1546
+ ...workingPredicate,
1547
+ targetType: irSubstitute(workingPredicate.targetType, receiverSubst),
1548
+ };
1549
+ }
1550
+ }
1551
+ }
1552
+ // 4. Compute call substitution (method type params)
1553
+ const methodTypeParams = rawSig.typeParameters;
1554
+ if (methodTypeParams.length > 0) {
1555
+ const callSubst = new Map();
1556
+ // Source 1: Explicit type args from call syntax
1557
+ if (explicitTypeArgs) {
1558
+ for (let i = 0; i < Math.min(explicitTypeArgs.length, methodTypeParams.length); i++) {
1559
+ const param = methodTypeParams[i];
1560
+ const arg = explicitTypeArgs[i];
1561
+ if (param && arg) {
1562
+ callSubst.set(param.name, arg);
1563
+ }
1564
+ }
1565
+ }
1566
+ // Source 2: Deterministic argument-driven unification
1567
+ if (argTypes && argTypes.length > 0) {
1568
+ const paramsForInference = callSubst.size > 0
1569
+ ? workingParams.map((p) => (p ? irSubstitute(p, callSubst) : undefined))
1570
+ : workingParams;
1571
+ const inferred = inferMethodTypeArgsFromArguments(methodTypeParams, paramsForInference, argTypes);
1572
+ if (!inferred) {
1573
+ emitDiagnostic("TSN5202", "Type arguments cannot be inferred deterministically from arguments", site);
1574
+ return poisonedCall(argumentCount, diagnostics.slice());
1575
+ }
1576
+ for (const [name, inferredType] of inferred) {
1577
+ const existing = callSubst.get(name);
1578
+ if (existing) {
1579
+ if (!typesEqual(existing, inferredType)) {
1580
+ emitDiagnostic("TSN5202", `Conflicting type argument inference for '${name}'`, site);
1581
+ return poisonedCall(argumentCount, diagnostics.slice());
1582
+ }
1583
+ continue;
1584
+ }
1585
+ callSubst.set(name, inferredType);
1586
+ }
1587
+ }
1588
+ // Source 3: Default type parameters
1589
+ for (const tp of methodTypeParams) {
1590
+ if (!callSubst.has(tp.name) && tp.defaultType) {
1591
+ callSubst.set(tp.name, tp.defaultType);
1592
+ }
1593
+ }
1594
+ // Apply call substitution
1595
+ if (callSubst.size > 0) {
1596
+ workingParams = workingParams.map((p) => p ? irSubstitute(p, callSubst) : undefined);
1597
+ workingReturn = irSubstitute(workingReturn, callSubst);
1598
+ if (workingPredicate) {
1599
+ workingPredicate =
1600
+ workingPredicate.kind === "param"
1601
+ ? {
1602
+ ...workingPredicate,
1603
+ targetType: irSubstitute(workingPredicate.targetType, callSubst),
1604
+ }
1605
+ : {
1606
+ ...workingPredicate,
1607
+ targetType: irSubstitute(workingPredicate.targetType, callSubst),
1608
+ };
1609
+ }
1610
+ }
1611
+ // Check for unresolved method type parameters (after explicit/arg/default inference)
1612
+ const unresolved = new Set(methodTypeParams
1613
+ .map((tp) => tp.name)
1614
+ .filter((name) => !callSubst.has(name)));
1615
+ if (unresolved.size > 0 && containsMethodTypeParameter(workingReturn, unresolved)) {
1616
+ const fallback = argTypes && rawSig.declaringTypeTsName && rawSig.declaringMemberName
1617
+ ? tryResolveCallFromUnifiedCatalog(rawSig.declaringTypeTsName, rawSig.declaringMemberName, query)
1618
+ : undefined;
1619
+ if (fallback) {
1620
+ return fallback;
1621
+ }
1622
+ emitDiagnostic("TSN5202", "Return type contains unresolved type parameters - explicit type arguments required", site);
1623
+ workingReturn = unknownType;
1624
+ }
1625
+ }
1626
+ return {
1627
+ parameterTypes: workingParams,
1628
+ parameterModes: rawSig.parameterModes,
1629
+ returnType: workingReturn,
1630
+ typePredicate: workingPredicate,
1631
+ diagnostics: [],
1632
+ };
1633
+ };
1634
+ // ─────────────────────────────────────────────────────────────────────────
1635
+ // expandUtility — Utility type expansion (Step 8)
1636
+ //
1637
+ // Implements all 13 utility types with deterministic constraints:
1638
+ // - Partial/Required/Readonly: T must be object-like
1639
+ // - Pick/Omit: K must be string literal union (finite keys)
1640
+ // - ReturnType/Parameters: F must be function type
1641
+ // - NonNullable: Works on any type
1642
+ // - Exclude/Extract: Works on any types
1643
+ // - Awaited: Recursive on Promise<T>
1644
+ // - Record: K must be finite literal union (string/number infinite → dictionary)
1645
+ // ─────────────────────────────────────────────────────────────────────────
1646
+ const expandUtility = (name, args, site) => {
1647
+ const firstArg = args[0];
1648
+ if (!firstArg) {
1649
+ emitDiagnostic("TSN7414", `Utility type '${name}' requires a type argument`, site);
1650
+ return unknownType;
1651
+ }
1652
+ // Check if first arg contains type parameters (cannot expand)
1653
+ if (containsTypeParameter(firstArg)) {
1654
+ // Return unknownType - cannot expand utility types with type parameters
1655
+ return unknownType;
1656
+ }
1657
+ switch (name) {
1658
+ case "NonNullable":
1659
+ return expandNonNullableUtility(firstArg);
1660
+ case "Partial":
1661
+ return expandMappedUtility(firstArg, "optional", site);
1662
+ case "Required":
1663
+ return expandMappedUtility(firstArg, "required", site);
1664
+ case "Readonly":
1665
+ return expandMappedUtility(firstArg, "readonly", site);
1666
+ case "Pick": {
1667
+ const keysArg = args[1];
1668
+ if (!keysArg) {
1669
+ emitDiagnostic("TSN7414", `Pick requires two type arguments`, site);
1670
+ return unknownType;
1671
+ }
1672
+ return expandPickOmitUtility(firstArg, keysArg, true, site);
1673
+ }
1674
+ case "Omit": {
1675
+ const keysArg = args[1];
1676
+ if (!keysArg) {
1677
+ emitDiagnostic("TSN7414", `Omit requires two type arguments`, site);
1678
+ return unknownType;
1679
+ }
1680
+ return expandPickOmitUtility(firstArg, keysArg, false, site);
1681
+ }
1682
+ case "ReturnType":
1683
+ return expandReturnTypeUtility(firstArg, site);
1684
+ case "Parameters":
1685
+ return expandParametersUtility(firstArg, site);
1686
+ case "Exclude": {
1687
+ const excludeArg = args[1];
1688
+ if (!excludeArg) {
1689
+ emitDiagnostic("TSN7414", `Exclude requires two type arguments`, site);
1690
+ return unknownType;
1691
+ }
1692
+ return expandExcludeExtractUtility(firstArg, excludeArg, false);
1693
+ }
1694
+ case "Extract": {
1695
+ const extractArg = args[1];
1696
+ if (!extractArg) {
1697
+ emitDiagnostic("TSN7414", `Extract requires two type arguments`, site);
1698
+ return unknownType;
1699
+ }
1700
+ return expandExcludeExtractUtility(firstArg, extractArg, true);
1701
+ }
1702
+ case "Awaited":
1703
+ return expandAwaitedUtility(firstArg);
1704
+ case "Record": {
1705
+ const valueArg = args[1];
1706
+ if (!valueArg) {
1707
+ emitDiagnostic("TSN7414", `Record requires two type arguments`, site);
1708
+ return unknownType;
1709
+ }
1710
+ return expandRecordUtility(firstArg, valueArg, site);
1711
+ }
1712
+ default:
1713
+ emitDiagnostic("TSN7414", `Utility type '${name}' is not supported`, site);
1714
+ return unknownType;
1715
+ }
1716
+ };
1717
+ // ─────────────────────────────────────────────────────────────────────────
1718
+ // Utility Type Helper Functions
1719
+ // ─────────────────────────────────────────────────────────────────────────
1720
+ /**
1721
+ * Expand NonNullable<T>: Filter out null and undefined from union
1722
+ */
1723
+ const expandNonNullableUtility = (type) => {
1724
+ // Direct null/undefined
1725
+ if (isNullishPrimitive(type)) {
1726
+ return neverType;
1727
+ }
1728
+ // Not a union - return as-is
1729
+ if (type.kind !== "unionType") {
1730
+ return type;
1731
+ }
1732
+ // Filter out null and undefined from union
1733
+ const filtered = type.types.filter((t) => !isNullishPrimitive(t));
1734
+ if (filtered.length === 0) {
1735
+ return neverType;
1736
+ }
1737
+ if (filtered.length === 1 && filtered[0]) {
1738
+ return filtered[0];
1739
+ }
1740
+ return { kind: "unionType", types: filtered };
1741
+ };
1742
+ /**
1743
+ * Expand Partial/Required/Readonly<T>: Mapped type transformation
1744
+ */
1745
+ const expandMappedUtility = (type, mode, site) => {
1746
+ // Must be object-like
1747
+ if (type.kind !== "objectType") {
1748
+ // For reference types, we need structural members
1749
+ if (type.kind === "referenceType") {
1750
+ // Try to get structural members from type
1751
+ const members = getStructuralMembersForType(type);
1752
+ if (members.length === 0) {
1753
+ emitDiagnostic("TSN7414", `${mode === "optional" ? "Partial" : mode === "required" ? "Required" : "Readonly"} requires a concrete object type`, site);
1754
+ return unknownType;
1755
+ }
1756
+ // Transform the members
1757
+ return {
1758
+ kind: "objectType",
1759
+ members: transformMembers(members, mode),
1760
+ };
1761
+ }
1762
+ emitDiagnostic("TSN7414", `${mode === "optional" ? "Partial" : mode === "required" ? "Required" : "Readonly"} requires an object type`, site);
1763
+ return unknownType;
1764
+ }
1765
+ return {
1766
+ kind: "objectType",
1767
+ members: transformMembers(type.members, mode),
1768
+ };
1769
+ };
1770
+ /**
1771
+ * Transform members for Partial/Required/Readonly
1772
+ */
1773
+ const transformMembers = (members, mode) => {
1774
+ return members.map((m) => {
1775
+ if (m.kind === "propertySignature") {
1776
+ return {
1777
+ ...m,
1778
+ isOptional: mode === "optional"
1779
+ ? true
1780
+ : mode === "required"
1781
+ ? false
1782
+ : m.isOptional,
1783
+ isReadonly: mode === "readonly" ? true : m.isReadonly,
1784
+ };
1785
+ }
1786
+ return m;
1787
+ });
1788
+ };
1789
+ /**
1790
+ * Get structural members for a reference type
1791
+ */
1792
+ const getStructuralMembersForType = (type) => {
1793
+ if (type.structuralMembers) {
1794
+ return type.structuralMembers;
1795
+ }
1796
+ // Try to look up in registry
1797
+ const fqName = typeRegistry.getFQName(type.name);
1798
+ const entry = fqName
1799
+ ? typeRegistry.resolveNominal(fqName)
1800
+ : typeRegistry.resolveBySimpleName(type.name);
1801
+ if (!entry)
1802
+ return [];
1803
+ // Convert registry members to IR members
1804
+ const members = [];
1805
+ entry.members.forEach((info, name) => {
1806
+ if (info.kind === "property" && info.type) {
1807
+ members.push({
1808
+ kind: "propertySignature",
1809
+ name,
1810
+ type: info.type,
1811
+ isOptional: info.isOptional,
1812
+ isReadonly: info.isReadonly,
1813
+ });
1814
+ }
1815
+ });
1816
+ return members;
1817
+ };
1818
+ /**
1819
+ * Expand Pick/Omit<T, K>: Filter members by keys
1820
+ */
1821
+ const expandPickOmitUtility = (type, keysType, isPick, site) => {
1822
+ // Extract literal keys from keysType
1823
+ const keys = extractLiteralKeys(keysType);
1824
+ if (keys === null) {
1825
+ emitDiagnostic("TSN7414", `${isPick ? "Pick" : "Omit"} requires literal string keys`, site);
1826
+ return unknownType;
1827
+ }
1828
+ // Get members from type
1829
+ let members;
1830
+ if (type.kind === "objectType") {
1831
+ members = type.members;
1832
+ }
1833
+ else if (type.kind === "referenceType") {
1834
+ members = getStructuralMembersForType(type);
1835
+ }
1836
+ else {
1837
+ emitDiagnostic("TSN7414", `${isPick ? "Pick" : "Omit"} requires an object type`, site);
1838
+ return unknownType;
1839
+ }
1840
+ // Filter members
1841
+ const filtered = members.filter((m) => {
1842
+ const include = isPick ? keys.has(m.name) : !keys.has(m.name);
1843
+ return include;
1844
+ });
1845
+ return { kind: "objectType", members: filtered };
1846
+ };
1847
+ /**
1848
+ * Extract literal keys from a type (string literals or union of string literals)
1849
+ */
1850
+ const extractLiteralKeys = (type) => {
1851
+ if (type.kind === "literalType" && typeof type.value === "string") {
1852
+ return new Set([type.value]);
1853
+ }
1854
+ if (type.kind === "unionType") {
1855
+ const keys = new Set();
1856
+ for (const t of type.types) {
1857
+ if (t.kind === "literalType" && typeof t.value === "string") {
1858
+ keys.add(t.value);
1859
+ }
1860
+ else if (t.kind === "literalType" && typeof t.value === "number") {
1861
+ keys.add(String(t.value));
1862
+ }
1863
+ else {
1864
+ return null; // Non-literal in union
1865
+ }
1866
+ }
1867
+ return keys;
1868
+ }
1869
+ return null;
1870
+ };
1871
+ /**
1872
+ * Expand ReturnType<F>: Extract return type from function type
1873
+ */
1874
+ const expandReturnTypeUtility = (type, site) => {
1875
+ if (type.kind === "functionType") {
1876
+ return type.returnType ?? voidType;
1877
+ }
1878
+ emitDiagnostic("TSN7414", `ReturnType requires a function type argument`, site);
1879
+ return unknownType;
1880
+ };
1881
+ /**
1882
+ * Expand Parameters<F>: Extract parameters as tuple from function type
1883
+ */
1884
+ const expandParametersUtility = (type, site) => {
1885
+ if (type.kind === "functionType") {
1886
+ const elementTypes = type.parameters.map((p) => p.type ?? { kind: "anyType" });
1887
+ return { kind: "tupleType", elementTypes };
1888
+ }
1889
+ emitDiagnostic("TSN7414", `Parameters requires a function type argument`, site);
1890
+ return unknownType;
1891
+ };
1892
+ /**
1893
+ * Expand Exclude<T, U> or Extract<T, U>
1894
+ */
1895
+ const expandExcludeExtractUtility = (tType, uType, isExtract) => {
1896
+ // If T is not a union, check if it matches U
1897
+ if (tType.kind !== "unionType") {
1898
+ const matches = typesEqual(tType, uType) ||
1899
+ (uType.kind === "unionType" &&
1900
+ uType.types.some((u) => typesEqual(tType, u)));
1901
+ if (isExtract) {
1902
+ return matches ? tType : neverType;
1903
+ }
1904
+ else {
1905
+ return matches ? neverType : tType;
1906
+ }
1907
+ }
1908
+ // T is a union - filter its constituents
1909
+ const uTypes = uType.kind === "unionType" ? uType.types : [uType];
1910
+ const filtered = tType.types.filter((t) => {
1911
+ const matches = uTypes.some((u) => typesEqual(t, u));
1912
+ return isExtract ? matches : !matches;
1913
+ });
1914
+ if (filtered.length === 0) {
1915
+ return neverType;
1916
+ }
1917
+ if (filtered.length === 1 && filtered[0]) {
1918
+ return filtered[0];
1919
+ }
1920
+ return { kind: "unionType", types: filtered };
1921
+ };
1922
+ /**
1923
+ * Expand Awaited<T>: Unwrap Promise types recursively
1924
+ */
1925
+ const expandAwaitedUtility = (type) => {
1926
+ // Check for Promise<T>
1927
+ if (type.kind === "referenceType" &&
1928
+ (type.name === "Promise" || type.name === "PromiseLike")) {
1929
+ const innerType = type.typeArguments?.[0];
1930
+ if (innerType) {
1931
+ // Recursively unwrap
1932
+ return expandAwaitedUtility(innerType);
1933
+ }
1934
+ }
1935
+ // Not a Promise - return as-is
1936
+ return type;
1937
+ };
1938
+ /**
1939
+ * Expand Record<K, V>: Create object type from literal keys
1940
+ */
1941
+ const expandRecordUtility = (keyType, valueType, site) => {
1942
+ // Check if K is a finite set of literal keys
1943
+ const keys = extractLiteralKeys(keyType);
1944
+ if (keys === null) {
1945
+ // Non-finite key type - cannot expand to object, use dictionary instead
1946
+ // Return unknownType to signal that caller should use dictionaryType
1947
+ emitDiagnostic("TSN7414", `Record with non-literal keys cannot be expanded to object type`, site);
1948
+ return unknownType;
1949
+ }
1950
+ // Build object type with a property for each key
1951
+ const members = Array.from(keys).map((key) => ({
1952
+ kind: "propertySignature",
1953
+ name: key,
1954
+ type: valueType,
1955
+ isOptional: false,
1956
+ isReadonly: false,
1957
+ }));
1958
+ return { kind: "objectType", members };
1959
+ };
1960
+ // ─────────────────────────────────────────────────────────────────────────
1961
+ // substitute — Delegate to ir-substitution
1962
+ // ─────────────────────────────────────────────────────────────────────────
1963
+ const substitute = (type, subst) => {
1964
+ // Convert TypeSubstitutionMap to IrSubstitutionMap if needed
1965
+ // (they're the same type, just different naming)
1966
+ return irSubstitute(type, subst);
1967
+ };
1968
+ // ─────────────────────────────────────────────────────────────────────────
1969
+ // instantiate — Instantiate a generic type with type arguments
1970
+ // ─────────────────────────────────────────────────────────────────────────
1971
+ const instantiate = (typeName, typeArgs, site) => {
1972
+ // Look up the type in registry
1973
+ const fqName = typeRegistry.getFQName(typeName);
1974
+ const entry = fqName
1975
+ ? typeRegistry.resolveNominal(fqName)
1976
+ : typeRegistry.resolveBySimpleName(typeName);
1977
+ if (!entry) {
1978
+ emitDiagnostic("TSN5203", `Cannot resolve type '${typeName}'`, site);
1979
+ return unknownType;
1980
+ }
1981
+ // Build substitution map from type parameters to arguments
1982
+ const subst = new Map();
1983
+ const typeParams = entry.typeParameters;
1984
+ for (let i = 0; i < Math.min(typeParams.length, typeArgs.length); i++) {
1985
+ const param = typeParams[i];
1986
+ const arg = typeArgs[i];
1987
+ if (param && arg) {
1988
+ subst.set(param.name, arg);
1989
+ }
1990
+ }
1991
+ // Return instantiated reference type
1992
+ const result = {
1993
+ kind: "referenceType",
1994
+ name: entry.name,
1995
+ typeArguments: typeArgs.length > 0 ? [...typeArgs] : undefined,
1996
+ };
1997
+ return result;
1998
+ };
1999
+ // ─────────────────────────────────────────────────────────────────────────
2000
+ // isAssignableTo — Conservative subtype check
2001
+ // ─────────────────────────────────────────────────────────────────────────
2002
+ const isAssignableTo = (source, target) => {
2003
+ // Same type - always assignable
2004
+ if (typesEqual(source, target))
2005
+ return true;
2006
+ // any is assignable to anything, anything is assignable to any
2007
+ if (source.kind === "anyType" || target.kind === "anyType")
2008
+ return true;
2009
+ // never is assignable to anything
2010
+ if (source.kind === "neverType")
2011
+ return true;
2012
+ // undefined/null assignability (represented as primitiveType with name "null"/"undefined")
2013
+ if (isNullishPrimitive(source)) {
2014
+ // Assignable to union containing undefined/null
2015
+ if (target.kind === "unionType") {
2016
+ return target.types.some((t) => t.kind === "primitiveType" && t.name === source.name);
2017
+ }
2018
+ return false;
2019
+ }
2020
+ // Primitives - same primitive type
2021
+ if (source.kind === "primitiveType" && target.kind === "primitiveType") {
2022
+ return source.name === target.name;
2023
+ }
2024
+ // Union source - all members must be assignable
2025
+ if (source.kind === "unionType") {
2026
+ return source.types.every((t) => isAssignableTo(t, target));
2027
+ }
2028
+ // Union target - source must be assignable to at least one member
2029
+ if (target.kind === "unionType") {
2030
+ return target.types.some((t) => isAssignableTo(source, t));
2031
+ }
2032
+ // Array types
2033
+ if (source.kind === "arrayType" && target.kind === "arrayType") {
2034
+ return isAssignableTo(source.elementType, target.elementType);
2035
+ }
2036
+ // Reference types - check nominal compatibility via TypeId
2037
+ if (source.kind === "referenceType" && target.kind === "referenceType") {
2038
+ const sourceNominal = normalizeToNominal(source);
2039
+ const targetNominal = normalizeToNominal(target);
2040
+ if (!sourceNominal || !targetNominal)
2041
+ return false;
2042
+ if (sourceNominal.typeId.stableId === targetNominal.typeId.stableId) {
2043
+ const sourceArgs = sourceNominal.typeArgs;
2044
+ const targetArgs = targetNominal.typeArgs;
2045
+ if (sourceArgs.length !== targetArgs.length)
2046
+ return false;
2047
+ return sourceArgs.every((sa, i) => {
2048
+ const ta = targetArgs[i];
2049
+ return ta ? typesEqual(sa, ta) : false;
2050
+ });
2051
+ }
2052
+ const chain = nominalEnv.getInheritanceChain(sourceNominal.typeId);
2053
+ return chain.some((t) => t.stableId === targetNominal.typeId.stableId);
2054
+ }
2055
+ // Conservative - return false if unsure
2056
+ return false;
2057
+ };
2058
+ // ─────────────────────────────────────────────────────────────────────────
2059
+ // typesEqual — Structural equality check
2060
+ // ─────────────────────────────────────────────────────────────────────────
2061
+ const typesEqual = (a, b) => {
2062
+ if (a.kind !== b.kind)
2063
+ return false;
2064
+ switch (a.kind) {
2065
+ case "primitiveType":
2066
+ return b.kind === "primitiveType" && a.name === b.name;
2067
+ case "referenceType": {
2068
+ if (b.kind !== "referenceType")
2069
+ return false;
2070
+ if (a.name !== b.name)
2071
+ return false;
2072
+ const aArgs = a.typeArguments ?? [];
2073
+ const bArgs = b.typeArguments ?? [];
2074
+ if (aArgs.length !== bArgs.length)
2075
+ return false;
2076
+ return aArgs.every((arg, i) => {
2077
+ const bArg = bArgs[i];
2078
+ return bArg ? typesEqual(arg, bArg) : false;
2079
+ });
2080
+ }
2081
+ case "arrayType":
2082
+ return (b.kind === "arrayType" &&
2083
+ typesEqual(a.elementType, b.elementType));
2084
+ case "tupleType": {
2085
+ if (b.kind !== "tupleType")
2086
+ return false;
2087
+ const bTyped = b;
2088
+ if (a.elementTypes.length !== bTyped.elementTypes.length)
2089
+ return false;
2090
+ return a.elementTypes.every((el, i) => {
2091
+ const bEl = bTyped.elementTypes[i];
2092
+ return bEl ? typesEqual(el, bEl) : false;
2093
+ });
2094
+ }
2095
+ case "unionType":
2096
+ case "intersectionType": {
2097
+ if (b.kind !== a.kind)
2098
+ return false;
2099
+ const bTyped = b;
2100
+ if (a.types.length !== bTyped.types.length)
2101
+ return false;
2102
+ // Order-independent comparison for unions/intersections
2103
+ return a.types.every((at) => bTyped.types.some((bt) => typesEqual(at, bt)));
2104
+ }
2105
+ case "functionType": {
2106
+ if (b.kind !== "functionType")
2107
+ return false;
2108
+ const bTyped = b;
2109
+ if (a.parameters.length !== bTyped.parameters.length)
2110
+ return false;
2111
+ const paramsEqual = a.parameters.every((ap, i) => {
2112
+ const bp = bTyped.parameters[i];
2113
+ if (!bp)
2114
+ return false;
2115
+ if (ap.type && bp.type)
2116
+ return typesEqual(ap.type, bp.type);
2117
+ return !ap.type && !bp.type;
2118
+ });
2119
+ if (!paramsEqual)
2120
+ return false;
2121
+ if (a.returnType && bTyped.returnType) {
2122
+ return typesEqual(a.returnType, bTyped.returnType);
2123
+ }
2124
+ return !a.returnType && !bTyped.returnType;
2125
+ }
2126
+ case "typeParameterType":
2127
+ return (b.kind === "typeParameterType" && a.name === b.name);
2128
+ case "literalType":
2129
+ return b.kind === "literalType" && a.value === b.value;
2130
+ case "voidType":
2131
+ case "neverType":
2132
+ case "unknownType":
2133
+ case "anyType":
2134
+ return a.kind === b.kind;
2135
+ default:
2136
+ // For other types, fall back to JSON comparison
2137
+ return JSON.stringify(a) === JSON.stringify(b);
2138
+ }
2139
+ };
2140
+ // ─────────────────────────────────────────────────────────────────────────
2141
+ // containsTypeParameter — Check if type contains unresolved type params
2142
+ // ─────────────────────────────────────────────────────────────────────────
2143
+ const containsTypeParameter = (type) => {
2144
+ if (type.kind === "typeParameterType")
2145
+ return true;
2146
+ if (type.kind === "referenceType") {
2147
+ return (type.typeArguments ?? []).some(containsTypeParameter);
2148
+ }
2149
+ if (type.kind === "arrayType") {
2150
+ return containsTypeParameter(type.elementType);
2151
+ }
2152
+ if (type.kind === "functionType") {
2153
+ const paramsContain = type.parameters.some((p) => p.type && containsTypeParameter(p.type));
2154
+ const returnContains = type.returnType && containsTypeParameter(type.returnType);
2155
+ return paramsContain || !!returnContains;
2156
+ }
2157
+ if (type.kind === "unionType" || type.kind === "intersectionType") {
2158
+ return type.types.some(containsTypeParameter);
2159
+ }
2160
+ if (type.kind === "tupleType") {
2161
+ return type.elementTypes.some(containsTypeParameter);
2162
+ }
2163
+ if (type.kind === "objectType") {
2164
+ return type.members.some((m) => {
2165
+ if (m.kind === "propertySignature") {
2166
+ return containsTypeParameter(m.type);
2167
+ }
2168
+ if (m.kind === "methodSignature") {
2169
+ const paramsContain = m.parameters.some((p) => p.type && containsTypeParameter(p.type));
2170
+ const returnContains = m.returnType && containsTypeParameter(m.returnType);
2171
+ return paramsContain || !!returnContains;
2172
+ }
2173
+ return false;
2174
+ });
2175
+ }
2176
+ return false;
2177
+ };
2178
+ const getDiagnostics = () => {
2179
+ return diagnostics.slice();
2180
+ };
2181
+ const clearDiagnostics = () => {
2182
+ diagnostics.length = 0;
2183
+ };
2184
+ // ─────────────────────────────────────────────────────────────────────────
2185
+ // hasTypeParameters — Check if declaration has type parameters
2186
+ // ─────────────────────────────────────────────────────────────────────────
2187
+ const hasTypeParameters = (declId) => {
2188
+ const declInfo = handleRegistry.getDecl(declId);
2189
+ if (!declInfo?.declNode)
2190
+ return false;
2191
+ // Check the declaration node for type parameters
2192
+ // We need to import ts to check for type parameter declarations
2193
+ // Access the declNode as any to check for typeParameters property
2194
+ const declNode = declInfo.declNode;
2195
+ return !!(declNode.typeParameters && declNode.typeParameters.length > 0);
2196
+ };
2197
+ // ─────────────────────────────────────────────────────────────────────────
2198
+ // typeOfMemberId — Get type of member by handle
2199
+ // ─────────────────────────────────────────────────────────────────────────
2200
+ const typeOfMemberId = (memberId) => {
2201
+ const memberInfo = handleRegistry.getMember(memberId);
2202
+ if (!memberInfo) {
2203
+ return unknownType;
2204
+ }
2205
+ // If the member has a type node, convert it
2206
+ if (memberInfo.typeNode) {
2207
+ return convertTypeNode(memberInfo.typeNode);
2208
+ }
2209
+ // Otherwise, attempt to recover type deterministically from the member declaration.
2210
+ // This is required for namespace imports (`import * as X`) where members are
2211
+ // function declarations / const declarations (no typeNode captured by Binding).
2212
+ const decl = memberInfo.declNode;
2213
+ if (decl) {
2214
+ if (ts.isFunctionDeclaration(decl)) {
2215
+ // Determinism: require explicit parameter + return annotations.
2216
+ if (!decl.type)
2217
+ return unknownType;
2218
+ if (decl.parameters.some((p) => p.type === undefined))
2219
+ return unknownType;
2220
+ const parameters = decl.parameters.map((p) => ({
2221
+ kind: "parameter",
2222
+ pattern: {
2223
+ kind: "identifierPattern",
2224
+ name: ts.isIdentifier(p.name) ? p.name.text : "param",
2225
+ },
2226
+ type: p.type ? convertTypeNode(p.type) : undefined,
2227
+ initializer: undefined,
2228
+ isOptional: !!p.questionToken || !!p.initializer,
2229
+ isRest: !!p.dotDotDotToken,
2230
+ passing: "value",
2231
+ }));
2232
+ const returnType = convertTypeNode(decl.type);
2233
+ const fnType = {
2234
+ kind: "functionType",
2235
+ parameters,
2236
+ returnType,
2237
+ };
2238
+ return fnType;
2239
+ }
2240
+ if (ts.isVariableDeclaration(decl)) {
2241
+ if (decl.type)
2242
+ return convertTypeNode(decl.type);
2243
+ const inferred = tryInferTypeFromInitializer(decl);
2244
+ return inferred ?? unknownType;
2245
+ }
2246
+ }
2247
+ return unknownType;
2248
+ };
2249
+ // ─────────────────────────────────────────────────────────────────────────
2250
+ // getFQNameOfDecl — Get fully-qualified name of declaration
2251
+ // ─────────────────────────────────────────────────────────────────────────
2252
+ const getFQNameOfDecl = (declId) => {
2253
+ const declInfo = handleRegistry.getDecl(declId);
2254
+ return declInfo?.fqName;
2255
+ };
2256
+ // ─────────────────────────────────────────────────────────────────────────
2257
+ // isTypeDecl — Check if declaration is a type
2258
+ // ─────────────────────────────────────────────────────────────────────────
2259
+ const isTypeDecl = (declId) => {
2260
+ const declInfo = handleRegistry.getDecl(declId);
2261
+ if (!declInfo)
2262
+ return false;
2263
+ const typeKinds = [
2264
+ "interface",
2265
+ "class",
2266
+ "typeAlias",
2267
+ "enum",
2268
+ ];
2269
+ return typeKinds.includes(declInfo.kind);
2270
+ };
2271
+ // ─────────────────────────────────────────────────────────────────────────
2272
+ // isInterfaceDecl — Check if declaration is an interface
2273
+ // ─────────────────────────────────────────────────────────────────────────
2274
+ const isInterfaceDecl = (declId) => {
2275
+ const declInfo = handleRegistry.getDecl(declId);
2276
+ return declInfo?.kind === "interface";
2277
+ };
2278
+ // ─────────────────────────────────────────────────────────────────────────
2279
+ // isTypeAliasToObjectLiteral — Check if type alias points to object literal
2280
+ // ─────────────────────────────────────────────────────────────────────────
2281
+ const isTypeAliasToObjectLiteral = (declId) => {
2282
+ const declInfo = handleRegistry.getDecl(declId);
2283
+ if (!declInfo || declInfo.kind !== "typeAlias")
2284
+ return false;
2285
+ // Check if the typeNode is a type literal node
2286
+ // We need to access the declNode to get the type alias declaration
2287
+ const declNode = declInfo.declNode;
2288
+ if (!declNode?.type)
2289
+ return false;
2290
+ return declNode.type.kind === ts.SyntaxKind.TypeLiteral;
2291
+ };
2292
+ // Suppress unused variable warning for nominalMemberLookupCache
2293
+ // Will be used for more advanced caching in future
2294
+ void nominalMemberLookupCache;
2295
+ // ─────────────────────────────────────────────────────────────────────────
2296
+ // signatureHasConditionalReturn — Check for conditional return type
2297
+ // ─────────────────────────────────────────────────────────────────────────
2298
+ const signatureHasConditionalReturn = (sigId) => {
2299
+ const sigInfo = handleRegistry.getSignature(sigId);
2300
+ if (!sigInfo)
2301
+ return false;
2302
+ const returnTypeNode = sigInfo.returnTypeNode;
2303
+ if (!returnTypeNode)
2304
+ return false;
2305
+ return returnTypeNode.kind === ts.SyntaxKind.ConditionalType;
2306
+ };
2307
+ // ─────────────────────────────────────────────────────────────────────────
2308
+ // signatureHasVariadicTypeParams — Check for variadic type parameters
2309
+ // ─────────────────────────────────────────────────────────────────────────
2310
+ const signatureHasVariadicTypeParams = (sigId) => {
2311
+ const sigInfo = handleRegistry.getSignature(sigId);
2312
+ if (!sigInfo)
2313
+ return false;
2314
+ if (!sigInfo.typeParameters)
2315
+ return false;
2316
+ for (const typeParam of sigInfo.typeParameters) {
2317
+ const constraintNode = typeParam.constraintNode;
2318
+ if (!constraintNode)
2319
+ continue;
2320
+ // Check if constraint is an array type (variadic pattern: T extends unknown[])
2321
+ if (constraintNode.kind === ts.SyntaxKind.ArrayType) {
2322
+ const elementType = constraintNode.elementType;
2323
+ if (!elementType)
2324
+ continue;
2325
+ // Check for unknown[] or any[] constraint
2326
+ if (elementType.kind === ts.SyntaxKind.UnknownKeyword ||
2327
+ elementType.kind === ts.SyntaxKind.AnyKeyword) {
2328
+ return true;
2329
+ }
2330
+ // Also check for type reference to "unknown" or "any"
2331
+ const typeName = elementType.typeName?.text;
2332
+ if (typeName === "unknown" || typeName === "any") {
2333
+ return true;
2334
+ }
2335
+ }
2336
+ }
2337
+ return false;
2338
+ };
2339
+ // ─────────────────────────────────────────────────────────────────────────
2340
+ // declHasTypeAnnotation — Check if declaration has explicit type
2341
+ // ─────────────────────────────────────────────────────────────────────────
2342
+ const declHasTypeAnnotation = (declId) => {
2343
+ const declInfo = handleRegistry.getDecl(declId);
2344
+ return declInfo?.typeNode !== undefined;
2345
+ };
2346
+ // ─────────────────────────────────────────────────────────────────────────
2347
+ // checkTsClassMemberOverride — Check if member can be overridden
2348
+ // ─────────────────────────────────────────────────────────────────────────
2349
+ /**
2350
+ * Check if a class member overrides a base class member.
2351
+ *
2352
+ * ALICE'S SPEC: Uses captured ClassMemberNames (pure data) from Binding.
2353
+ * No TS AST inspection, no SyntaxKind numbers. TS-version safe.
2354
+ */
2355
+ const checkTsClassMemberOverride = (declId, memberName, memberKind) => {
2356
+ const declInfo = handleRegistry.getDecl(declId);
2357
+ const members = declInfo?.classMemberNames;
2358
+ // No class member info available
2359
+ if (!members) {
2360
+ return { isOverride: false, isShadow: false };
2361
+ }
2362
+ // Check if base class has this member
2363
+ const has = memberKind === "method"
2364
+ ? members.methods.has(memberName)
2365
+ : members.properties.has(memberName);
2366
+ // In TypeScript, all methods can be overridden (no `final` keyword)
2367
+ return has
2368
+ ? { isOverride: true, isShadow: false }
2369
+ : { isOverride: false, isShadow: false };
2370
+ };
2371
+ // ─────────────────────────────────────────────────────────────────────────
2372
+ // typeFromSyntax — Convert captured type syntax to IrType
2373
+ // ─────────────────────────────────────────────────────────────────────────
2374
+ /**
2375
+ * Convert a captured type syntax to IrType.
2376
+ *
2377
+ * This method takes a TypeSyntaxId handle (opaque to caller) and looks up
2378
+ * the captured TypeNode in the HandleRegistry, then converts it.
2379
+ *
2380
+ * ALICE'S SPEC (Phase 2): TypeSystem receives opaque handles, not ts.TypeNode.
2381
+ */
2382
+ const typeFromSyntax = (typeSyntaxId) => {
2383
+ const syntaxInfo = handleRegistry.getTypeSyntax(typeSyntaxId);
2384
+ if (!syntaxInfo) {
2385
+ // Invalid handle - return unknownType
2386
+ return { kind: "unknownType" };
2387
+ }
2388
+ // Phase 5: convertTypeNode accepts unknown, cast is inside type-system/internal
2389
+ return convertTypeNode(syntaxInfo.typeNode);
2390
+ };
2391
+ // ─────────────────────────────────────────────────────────────────────────
2392
+ // RETURN TYPESYSTEM INSTANCE
2393
+ // ─────────────────────────────────────────────────────────────────────────
2394
+ return {
2395
+ typeFromSyntax,
2396
+ typeOfDecl,
2397
+ typeOfMember,
2398
+ typeOfMemberId,
2399
+ getFQNameOfDecl,
2400
+ isTypeDecl,
2401
+ isInterfaceDecl,
2402
+ isTypeAliasToObjectLiteral,
2403
+ signatureHasConditionalReturn,
2404
+ signatureHasVariadicTypeParams,
2405
+ declHasTypeAnnotation,
2406
+ checkTsClassMemberOverride,
2407
+ resolveCall,
2408
+ delegateToFunctionType,
2409
+ expandUtility,
2410
+ substitute,
2411
+ instantiate,
2412
+ isAssignableTo,
2413
+ typesEqual,
2414
+ containsTypeParameter,
2415
+ hasTypeParameters,
2416
+ getDiagnostics,
2417
+ clearDiagnostics,
2418
+ };
2419
+ };
2420
+ //# sourceMappingURL=type-system.js.map