@tsonic/frontend 0.0.14 → 0.0.16

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