@aster-cloud/aster-lang-ts 1.0.27 → 1.0.29

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 (207) hide show
  1. package/dist/scripts/generate_error_codes.js +49 -6
  2. package/dist/scripts/generate_error_codes.js.map +1 -1
  3. package/dist/src/ai/providers/openai.d.ts +10 -0
  4. package/dist/src/ai/providers/openai.d.ts.map +1 -1
  5. package/dist/src/ai/providers/openai.js +4 -0
  6. package/dist/src/ai/providers/openai.js.map +1 -1
  7. package/dist/src/config/lexicons/regex-guard.d.ts.map +1 -1
  8. package/dist/src/config/lexicons/regex-guard.js +128 -0
  9. package/dist/src/config/lexicons/regex-guard.js.map +1 -1
  10. package/dist/src/core/interpreter.d.ts.map +1 -1
  11. package/dist/src/core/interpreter.js +221 -27
  12. package/dist/src/core/interpreter.js.map +1 -1
  13. package/dist/src/cst/cst_builder.js +0 -14
  14. package/dist/src/cst/cst_builder.js.map +1 -1
  15. package/dist/src/cst/cst_printer.d.ts.map +1 -1
  16. package/dist/src/cst/cst_printer.js +20 -3
  17. package/dist/src/cst/cst_printer.js.map +1 -1
  18. package/dist/src/diagnostics/error_codes.d.ts +3 -3
  19. package/dist/src/diagnostics/error_codes.d.ts.map +1 -1
  20. package/dist/src/diagnostics/error_codes.js +509 -78
  21. package/dist/src/diagnostics/error_codes.js.map +1 -1
  22. package/dist/src/formatter.d.ts +7 -0
  23. package/dist/src/formatter.d.ts.map +1 -1
  24. package/dist/src/formatter.js +175 -5
  25. package/dist/src/formatter.js.map +1 -1
  26. package/dist/src/frontend/canonicalizer.d.ts.map +1 -1
  27. package/dist/src/frontend/canonicalizer.js +47 -6
  28. package/dist/src/frontend/canonicalizer.js.map +1 -1
  29. package/dist/src/frontend/lexer.d.ts +2 -1
  30. package/dist/src/frontend/lexer.d.ts.map +1 -1
  31. package/dist/src/frontend/lexer.js +10 -3
  32. package/dist/src/frontend/lexer.js.map +1 -1
  33. package/dist/src/frontend/transformers.d.ts.map +1 -1
  34. package/dist/src/frontend/transformers.js +50 -3
  35. package/dist/src/frontend/transformers.js.map +1 -1
  36. package/dist/src/lower_to_core.js +101 -4
  37. package/dist/src/lower_to_core.js.map +1 -1
  38. package/dist/src/lsp/canonicalize-options.d.ts +26 -0
  39. package/dist/src/lsp/canonicalize-options.d.ts.map +1 -0
  40. package/dist/src/lsp/canonicalize-options.js +14 -0
  41. package/dist/src/lsp/canonicalize-options.js.map +1 -0
  42. package/dist/src/lsp/completion.d.ts.map +1 -1
  43. package/dist/src/lsp/completion.js +22 -4
  44. package/dist/src/lsp/completion.js.map +1 -1
  45. package/dist/src/lsp/server.js +29 -1
  46. package/dist/src/lsp/server.js.map +1 -1
  47. package/dist/src/lsp/tenant-init.d.ts +55 -0
  48. package/dist/src/lsp/tenant-init.d.ts.map +1 -0
  49. package/dist/src/lsp/tenant-init.js +88 -0
  50. package/dist/src/lsp/tenant-init.js.map +1 -0
  51. package/dist/src/mapping/candidate-generator.d.ts +84 -0
  52. package/dist/src/mapping/candidate-generator.d.ts.map +1 -0
  53. package/dist/src/mapping/candidate-generator.js +114 -0
  54. package/dist/src/mapping/candidate-generator.js.map +1 -0
  55. package/dist/src/mapping/entity-proposer.d.ts +85 -0
  56. package/dist/src/mapping/entity-proposer.d.ts.map +1 -0
  57. package/dist/src/mapping/entity-proposer.js +162 -0
  58. package/dist/src/mapping/entity-proposer.js.map +1 -0
  59. package/dist/src/mapping/mapping-ir.d.ts +85 -0
  60. package/dist/src/mapping/mapping-ir.d.ts.map +1 -0
  61. package/dist/src/mapping/mapping-ir.js +195 -0
  62. package/dist/src/mapping/mapping-ir.js.map +1 -0
  63. package/dist/src/mapping/proof-ir.d.ts +125 -0
  64. package/dist/src/mapping/proof-ir.d.ts.map +1 -0
  65. package/dist/src/mapping/proof-ir.js +48 -0
  66. package/dist/src/mapping/proof-ir.js.map +1 -0
  67. package/dist/src/mapping/quantity-ir.d.ts +93 -0
  68. package/dist/src/mapping/quantity-ir.d.ts.map +1 -0
  69. package/dist/src/mapping/quantity-ir.js +151 -0
  70. package/dist/src/mapping/quantity-ir.js.map +1 -0
  71. package/dist/src/mapping/source-ir.d.ts +82 -0
  72. package/dist/src/mapping/source-ir.d.ts.map +1 -0
  73. package/dist/src/mapping/source-ir.js +231 -0
  74. package/dist/src/mapping/source-ir.js.map +1 -0
  75. package/dist/src/nodeid/change-impact.d.ts +77 -0
  76. package/dist/src/nodeid/change-impact.d.ts.map +1 -0
  77. package/dist/src/nodeid/change-impact.js +132 -0
  78. package/dist/src/nodeid/change-impact.js.map +1 -0
  79. package/dist/src/nodeid/node-id-map.d.ts +69 -0
  80. package/dist/src/nodeid/node-id-map.d.ts.map +1 -0
  81. package/dist/src/nodeid/node-id-map.js +193 -0
  82. package/dist/src/nodeid/node-id-map.js.map +1 -0
  83. package/dist/src/parser/decl-parser.d.ts.map +1 -1
  84. package/dist/src/parser/decl-parser.js +10 -4
  85. package/dist/src/parser/decl-parser.js.map +1 -1
  86. package/dist/src/parser/expr-stmt-parser.d.ts.map +1 -1
  87. package/dist/src/parser/expr-stmt-parser.js +36 -24
  88. package/dist/src/parser/expr-stmt-parser.js.map +1 -1
  89. package/dist/src/parser/span-utils.d.ts +25 -0
  90. package/dist/src/parser/span-utils.d.ts.map +1 -1
  91. package/dist/src/parser/span-utils.js +43 -0
  92. package/dist/src/parser/span-utils.js.map +1 -1
  93. package/dist/src/parser/type-parser.d.ts.map +1 -1
  94. package/dist/src/parser/type-parser.js +21 -0
  95. package/dist/src/parser/type-parser.js.map +1 -1
  96. package/dist/src/typecheck/expression.d.ts.map +1 -1
  97. package/dist/src/typecheck/expression.js +26 -0
  98. package/dist/src/typecheck/expression.js.map +1 -1
  99. package/dist/test/fuzz/fuzz.test.js +62 -2
  100. package/dist/test/fuzz/fuzz.test.js.map +1 -1
  101. package/dist/test/unit/call-arity.test.d.ts +2 -0
  102. package/dist/test/unit/call-arity.test.d.ts.map +1 -0
  103. package/dist/test/unit/call-arity.test.js +71 -0
  104. package/dist/test/unit/call-arity.test.js.map +1 -0
  105. package/dist/test/unit/canonicalizer/canonicalizer.test.js +42 -4
  106. package/dist/test/unit/canonicalizer/canonicalizer.test.js.map +1 -1
  107. package/dist/test/unit/canonicalizer/line-preservation.test.d.ts +2 -0
  108. package/dist/test/unit/canonicalizer/line-preservation.test.d.ts.map +1 -0
  109. package/dist/test/unit/canonicalizer/line-preservation.test.js +71 -0
  110. package/dist/test/unit/canonicalizer/line-preservation.test.js.map +1 -0
  111. package/dist/test/unit/canonicalizer/marker-restore-linear.test.d.ts +2 -0
  112. package/dist/test/unit/canonicalizer/marker-restore-linear.test.d.ts.map +1 -0
  113. package/dist/test/unit/canonicalizer/marker-restore-linear.test.js +98 -0
  114. package/dist/test/unit/canonicalizer/marker-restore-linear.test.js.map +1 -0
  115. package/dist/test/unit/canonicalizer/possessive-anchor.test.d.ts +2 -0
  116. package/dist/test/unit/canonicalizer/possessive-anchor.test.d.ts.map +1 -0
  117. package/dist/test/unit/canonicalizer/possessive-anchor.test.js +101 -0
  118. package/dist/test/unit/canonicalizer/possessive-anchor.test.js.map +1 -0
  119. package/dist/test/unit/formatter-redos.test.d.ts +2 -0
  120. package/dist/test/unit/formatter-redos.test.d.ts.map +1 -0
  121. package/dist/test/unit/formatter-redos.test.js +196 -0
  122. package/dist/test/unit/formatter-redos.test.js.map +1 -0
  123. package/dist/test/unit/interpreter/interpreter.test.js +7 -2
  124. package/dist/test/unit/interpreter/interpreter.test.js.map +1 -1
  125. package/dist/test/unit/lexer/bom.test.d.ts +2 -0
  126. package/dist/test/unit/lexer/bom.test.d.ts.map +1 -0
  127. package/dist/test/unit/lexer/bom.test.js +49 -0
  128. package/dist/test/unit/lexer/bom.test.js.map +1 -0
  129. package/dist/test/unit/list-get-bounds.test.d.ts +2 -0
  130. package/dist/test/unit/list-get-bounds.test.d.ts.map +1 -0
  131. package/dist/test/unit/list-get-bounds.test.js +66 -0
  132. package/dist/test/unit/list-get-bounds.test.js.map +1 -0
  133. package/dist/test/unit/long-bigint-exact.test.d.ts +2 -0
  134. package/dist/test/unit/long-bigint-exact.test.d.ts.map +1 -0
  135. package/dist/test/unit/long-bigint-exact.test.js +79 -0
  136. package/dist/test/unit/long-bigint-exact.test.js.map +1 -0
  137. package/dist/test/unit/lsp/completion-lexicon.test.d.ts +2 -0
  138. package/dist/test/unit/lsp/completion-lexicon.test.d.ts.map +1 -0
  139. package/dist/test/unit/lsp/completion-lexicon.test.js +83 -0
  140. package/dist/test/unit/lsp/completion-lexicon.test.js.map +1 -0
  141. package/dist/test/unit/lsp/tenant-vocabulary.test.d.ts +2 -0
  142. package/dist/test/unit/lsp/tenant-vocabulary.test.d.ts.map +1 -0
  143. package/dist/test/unit/lsp/tenant-vocabulary.test.js +187 -0
  144. package/dist/test/unit/lsp/tenant-vocabulary.test.js.map +1 -0
  145. package/dist/test/unit/map-builtins.test.js +163 -3
  146. package/dist/test/unit/map-builtins.test.js.map +1 -1
  147. package/dist/test/unit/map-structural-equality.test.d.ts +2 -0
  148. package/dist/test/unit/map-structural-equality.test.d.ts.map +1 -0
  149. package/dist/test/unit/map-structural-equality.test.js +64 -0
  150. package/dist/test/unit/map-structural-equality.test.js.map +1 -0
  151. package/dist/test/unit/map-type-guard.test.js +8 -5
  152. package/dist/test/unit/map-type-guard.test.js.map +1 -1
  153. package/dist/test/unit/mapping/candidate-generator.test.d.ts +2 -0
  154. package/dist/test/unit/mapping/candidate-generator.test.d.ts.map +1 -0
  155. package/dist/test/unit/mapping/candidate-generator.test.js +177 -0
  156. package/dist/test/unit/mapping/candidate-generator.test.js.map +1 -0
  157. package/dist/test/unit/mapping/entity-proposer.test.d.ts +2 -0
  158. package/dist/test/unit/mapping/entity-proposer.test.d.ts.map +1 -0
  159. package/dist/test/unit/mapping/entity-proposer.test.js +168 -0
  160. package/dist/test/unit/mapping/entity-proposer.test.js.map +1 -0
  161. package/dist/test/unit/mapping/mapping-ir.test.d.ts +2 -0
  162. package/dist/test/unit/mapping/mapping-ir.test.d.ts.map +1 -0
  163. package/dist/test/unit/mapping/mapping-ir.test.js +144 -0
  164. package/dist/test/unit/mapping/mapping-ir.test.js.map +1 -0
  165. package/dist/test/unit/mapping/proof-ir.test.d.ts +2 -0
  166. package/dist/test/unit/mapping/proof-ir.test.d.ts.map +1 -0
  167. package/dist/test/unit/mapping/proof-ir.test.js +119 -0
  168. package/dist/test/unit/mapping/proof-ir.test.js.map +1 -0
  169. package/dist/test/unit/mapping/quantity-ir.test.d.ts +2 -0
  170. package/dist/test/unit/mapping/quantity-ir.test.d.ts.map +1 -0
  171. package/dist/test/unit/mapping/quantity-ir.test.js +144 -0
  172. package/dist/test/unit/mapping/quantity-ir.test.js.map +1 -0
  173. package/dist/test/unit/mapping/quantity-redos-property.test.d.ts +2 -0
  174. package/dist/test/unit/mapping/quantity-redos-property.test.d.ts.map +1 -0
  175. package/dist/test/unit/mapping/quantity-redos-property.test.js +182 -0
  176. package/dist/test/unit/mapping/quantity-redos-property.test.js.map +1 -0
  177. package/dist/test/unit/mapping/redos-budget.test.d.ts +2 -0
  178. package/dist/test/unit/mapping/redos-budget.test.d.ts.map +1 -0
  179. package/dist/test/unit/mapping/redos-budget.test.js +168 -0
  180. package/dist/test/unit/mapping/redos-budget.test.js.map +1 -0
  181. package/dist/test/unit/mapping/source-ir.test.d.ts +2 -0
  182. package/dist/test/unit/mapping/source-ir.test.d.ts.map +1 -0
  183. package/dist/test/unit/mapping/source-ir.test.js +113 -0
  184. package/dist/test/unit/mapping/source-ir.test.js.map +1 -0
  185. package/dist/test/unit/nodeid/change-impact.test.d.ts +2 -0
  186. package/dist/test/unit/nodeid/change-impact.test.d.ts.map +1 -0
  187. package/dist/test/unit/nodeid/change-impact.test.js +152 -0
  188. package/dist/test/unit/nodeid/change-impact.test.js.map +1 -0
  189. package/dist/test/unit/nodeid/rename-declaration.test.d.ts +2 -0
  190. package/dist/test/unit/nodeid/rename-declaration.test.d.ts.map +1 -0
  191. package/dist/test/unit/nodeid/rename-declaration.test.js +75 -0
  192. package/dist/test/unit/nodeid/rename-declaration.test.js.map +1 -0
  193. package/dist/test/unit/parse-type-recursion.test.d.ts +2 -0
  194. package/dist/test/unit/parse-type-recursion.test.d.ts.map +1 -0
  195. package/dist/test/unit/parse-type-recursion.test.js +58 -0
  196. package/dist/test/unit/parse-type-recursion.test.js.map +1 -0
  197. package/dist/test/unit/regex-guard.test.js +64 -0
  198. package/dist/test/unit/regex-guard.test.js.map +1 -1
  199. package/dist/test/unit/strict-int-coercion.test.d.ts +2 -0
  200. package/dist/test/unit/strict-int-coercion.test.d.ts.map +1 -0
  201. package/dist/test/unit/strict-int-coercion.test.js +96 -0
  202. package/dist/test/unit/strict-int-coercion.test.js.map +1 -0
  203. package/dist/test/unit/ufcs-receiver.test.d.ts +2 -0
  204. package/dist/test/unit/ufcs-receiver.test.d.ts.map +1 -0
  205. package/dist/test/unit/ufcs-receiver.test.js +75 -0
  206. package/dist/test/unit/ufcs-receiver.test.js.map +1 -0
  207. package/package.json +1 -1
@@ -0,0 +1,96 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { compile } from '../../src/browser.js';
4
+ import { evaluate } from '../../src/core/interpreter.js';
5
+ /**
6
+ * 严格整型换算(issue aster-lang-ts#144)。
7
+ *
8
+ * ★真实缺陷:`Date.*` / `List.range` / `List.get` / `List.slice` / `Text.substring`
9
+ * 用裸 `Number()` 强转。`Number("x")` 得 `NaN` 后**所有防线同时失效**——
10
+ * `NaN < MIN || NaN > MAX` 两侧都是 false 于是放行;`size > MAX_RANGE_SIZE` 同理,
11
+ * 然后循环零次静默返回 `[]`。非法输入不报错,反而产出「看起来正常」的决策值。
12
+ *
13
+ * 实测(修复前):
14
+ *
15
+ * Date.daysBetween("x","b") → success:true, value:NaN
16
+ * Date.addDays("x",5) greater than 0 → success:true, value:false
17
+ * List.length(List.range("a",5)) → success:true, value:0
18
+ *
19
+ * 而 truffle 同输入抛 `NumberFormatException`——**同一条规则两引擎一个静默出错答案、
20
+ * 一个响亮失败**。对合规引擎,静默的那个远更危险:错误答案会一路流进裁决结果。
21
+ */
22
+ function run(body) {
23
+ const c = compile(`Module probe.\n${body}\n`);
24
+ assert.ok(c.core, `compile: ${JSON.stringify(c.parseErrors ?? [])}`);
25
+ const ev = evaluate(c.core, 'main', { seed: 0 });
26
+ return { success: ev.success, value: ev.value, error: String(ev.error ?? '') };
27
+ }
28
+ function expectLoudFailure(body, mustMention) {
29
+ const r = run(body);
30
+ assert.equal(r.success, false, `必须响亮失败,实际 success=true value=${JSON.stringify(r.value)}`);
31
+ assert.match(r.error, /expected Int/, `错误信息须指明期望 Int;实际:${r.error}`);
32
+ assert.ok(r.error.includes(mustMention), `错误信息须点名出问题的 builtin(${mustMention}),否则用户无从定位;实际:${r.error}`);
33
+ }
34
+ describe('非法整型入参必须响亮失败(不得静默产 NaN)', () => {
35
+ it('★Date.daysBetween 非数字字符串(此前 success:true, value:NaN)', () => {
36
+ expectLoudFailure('Rule main produce Int:\n Return Date.daysBetween("x", "b").', 'Date.daysBetween');
37
+ });
38
+ it('★Date.addDays 非数字字符串(此前静默产出 false 决策)', () => {
39
+ // 这条最能说明危害:NaN 参与比较后产出一个**看似正常的布尔裁决**。
40
+ expectLoudFailure('Rule main produce Bool:\n Return Date.addDays("x", 5) greater than 0.', 'Date.addDays');
41
+ });
42
+ it('★List.range 非数字字符串(此前静默返回空列表)', () => {
43
+ expectLoudFailure('Rule main produce Int:\n Return List.length(List.range("a", 5)).', 'List.range');
44
+ });
45
+ it('List.get / List.slice / Text.substring 同样收口', () => {
46
+ expectLoudFailure('Rule main produce Int:\n Return List.get([1, 2, 3], "x").', 'List.get');
47
+ expectLoudFailure('Rule main produce Int:\n Return List.length(List.slice([1, 2, 3], "x", 2)).', 'List.slice');
48
+ expectLoudFailure('Rule main produce Text:\n Return Text.substring("hello", "x").', 'Text.substring');
49
+ });
50
+ it('★小数字符串被拒(对齐 Integer.parseInt,不接受 "5.0")', () => {
51
+ expectLoudFailure('Rule main produce Int:\n Return List.length(List.range("5.0", 9)).', 'List.range');
52
+ });
53
+ it('★十六进制字符串被拒(裸 Number("0x10") 会读成 16,Java 侧拒绝)', () => {
54
+ // 与 decimalScale 里已记录的同一类分叉:JS 的宽松数字解析会与 Java 分叉。
55
+ expectLoudFailure('Rule main produce Int:\n Return List.length(List.range("0x10", 99)).', 'List.range');
56
+ });
57
+ it('★空串与纯空白被拒(Number("") 是 0,会静默变成合法索引)', () => {
58
+ expectLoudFailure('Rule main produce Int:\n Return List.get([1, 2, 3], "").', 'List.get');
59
+ expectLoudFailure('Rule main produce Int:\n Return List.get([1, 2, 3], " ").', 'List.get');
60
+ });
61
+ });
62
+ describe('合法输入行为不变(反向护栏)', () => {
63
+ // ★没有这一组,把 toInt 写成「一律抛错」也能让上面全部变绿。
64
+ it('List.range 正常', () => {
65
+ const r = run('Rule main produce Int:\n Return List.length(List.range(1, 5)).');
66
+ assert.equal(r.success, true, r.error);
67
+ assert.equal(r.value, 4);
68
+ });
69
+ it('Date.addDays 正常', () => {
70
+ const r = run('Rule main produce Int:\n Return Date.addDays(Date.fromISO("2026-01-01"), 5).');
71
+ assert.equal(r.success, true, r.error);
72
+ assert.equal(r.value, 20459);
73
+ });
74
+ it('List.get 正常', () => {
75
+ const r = run('Rule main produce Int:\n Return List.get([10, 20, 30], 1).');
76
+ assert.equal(r.success, true, r.error);
77
+ assert.equal(r.value, 20);
78
+ });
79
+ it('★数字字符串仍被接受(对齐 Integer.parseInt 收 "5")', () => {
80
+ const r = run('Rule main produce Int:\n Return List.length(List.range("1", 5)).');
81
+ assert.equal(r.success, true, r.error);
82
+ assert.equal(r.value, 4);
83
+ });
84
+ it('★负数与前后空白仍被接受(parseInt 亦然)', () => {
85
+ const r = run('Rule main produce Int:\n Return List.length(List.range("-2", 2)).');
86
+ assert.equal(r.success, true, r.error);
87
+ assert.equal(r.value, 4);
88
+ });
89
+ it('★Double 入参按截断取整(对齐 Java Number.intValue())', () => {
90
+ // 不是拒绝——truffle 的 toInt 对 Number 走 intValue() 截断,必须一致。
91
+ const r = run('Rule main produce Int:\n Return List.get([10, 20, 30], 1.9).');
92
+ assert.equal(r.success, true, r.error);
93
+ assert.equal(r.value, 20, '1.9 应截断为 1');
94
+ });
95
+ });
96
+ //# sourceMappingURL=strict-int-coercion.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strict-int-coercion.test.js","sourceRoot":"","sources":["../../../test/unit/strict-int-coercion.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ufcs-receiver.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ufcs-receiver.test.d.ts","sourceRoot":"","sources":["../../../test/unit/ufcs-receiver.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { canonicalize } from '../../src/frontend/canonicalizer.js';
4
+ import { lex } from '../../src/frontend/lexer.js';
5
+ import { parse } from '../../src/parser.js';
6
+ import { lowerModule } from '../../src/lower_to_core.js';
7
+ /**
8
+ * UFCS(接收者转参数):`value.sum(1, 2)` → `sum(value, 1, 2)`。
9
+ *
10
+ * <p>这是 Java 引擎有意设计的调用约定(`AstBuilder.applyCallSuffix`,由
11
+ * `AstBuilderTest.testMethodCallTransformsReceiver` 钉住),TS 侧此前缺失,
12
+ * 导致同一段源码在两个引擎上**实际传参个数不同**——不是表示差异,是行为差异:
13
+ *
14
+ * <pre>
15
+ * io.verify(user, pass)
16
+ * Java → Call(Name "verify", [io, user, pass]) 3 参
17
+ * TS → Call(Name "io.verify", [user, pass]) 2 参 ← 分叉
18
+ * </pre>
19
+ *
20
+ * <p>★触发条件是 lexer 的 IDENT / TYPE_IDENT 之分,**不是**「首字母是否大写」:
21
+ * ASCII 小写或下划线开头 → IDENT → 走 UFCS;其余(大写、CJK…)→ TYPE_IDENT → 不拆分。
22
+ */
23
+ function callOf(expr) {
24
+ const src = `Module p.\n\nRule r, produce:\n Return ${expr}.\n`;
25
+ const ast = parse(lex(canonicalize(src))).ast;
26
+ const ir = JSON.parse(JSON.stringify(lowerModule(ast)));
27
+ const call = ir.decls[0].body.statements[0].expr;
28
+ return { target: call.target?.name, args: call.args };
29
+ }
30
+ describe('UFCS 接收者转参数(与 Java 引擎对齐)', () => {
31
+ it('★小写接收者:`value.sum(1, 2)` → `sum(value, 1, 2)`', () => {
32
+ const { target, args } = callOf('value.sum(1, 2)');
33
+ assert.strictEqual(target, 'sum', '调用目标应是方法名 `sum`(接收者已转为首个实参)。');
34
+ assert.strictEqual(args.length, 3, `实参应为 3 个(接收者 + 2 个原参),实际 ${args.length}`
35
+ + '\n★若为 2,说明未做 UFCS,与 Java 引擎的实际传参个数不一致。');
36
+ assert.strictEqual(args[0].name, 'value', '首个实参应是接收者 `value`。');
37
+ });
38
+ it('多段限定名:接收者只取**首段**(`a.b.c(1)` → 方法 `b.c`,接收者 `a`)', () => {
39
+ // 与 Java `combineName(null, pendingMembers)` 一致:除首段外全部并入方法名。
40
+ const { target, args } = callOf('a.b.c(1)');
41
+ assert.strictEqual(target, 'b.c', '方法名应是除首段外的全部段。');
42
+ assert.strictEqual(args[0].name, 'a', '接收者应只取首段。');
43
+ assert.strictEqual(args.length, 2);
44
+ });
45
+ it('★大写接收者不拆分:`Text.concat(a, b)` 保持限定名', () => {
46
+ // 反向守卫。没有这条,「UFCS」可以退化成「所有带点的名字都拆」——
47
+ // 那会把 Text.concat / Http.get / Map.get 这些**类型/模块限定名**一并拆坏,
48
+ // 而上面那条正向用例照样绿。
49
+ const { target, args } = callOf('Text.concat(1, 2)');
50
+ assert.strictEqual(target, 'Text.concat', '大写开头是类型/模块限定名,必须整体作为调用目标,不得拆分。');
51
+ assert.strictEqual(args.length, 2, '实参应仍为 2 个(没有多塞接收者)。');
52
+ });
53
+ it('★`Map.get` 同样不拆分(Map 有独立 lexer token,易被漏掉)', () => {
54
+ const { target, args } = callOf('Map.get(1, 2)');
55
+ assert.strictEqual(target, 'Map.get');
56
+ assert.strictEqual(args.length, 2);
57
+ });
58
+ it('无点的普通调用不受影响', () => {
59
+ const { target, args } = callOf('sum(1, 2)');
60
+ assert.strictEqual(target, 'sum');
61
+ assert.strictEqual(args.length, 2, '无接收者可转,实参个数不应变化。');
62
+ });
63
+ it('★拆出的接收者与方法名都必须带 origin(否则在 OriginMap 里不可达)', () => {
64
+ // 与 `Let "_"` 内层 Call 缺 origin 是同一类问题:节点没有位置信息时,
65
+ // ADR 0032 的 trace 锚点与 ADR 0037 的双向导航都定位不到它——不报错,
66
+ // 只是这段代码从导航里静默消失。
67
+ const src = 'Module p.\n\nRule r, produce:\n Return value.sum(1).\n';
68
+ const ast = parse(lex(canonicalize(src))).ast;
69
+ const call = JSON.parse(JSON.stringify(lowerModule(ast)))
70
+ .decls[0].body.statements[0].expr;
71
+ assert.ok(call.target?.origin, '方法名节点缺少 origin。');
72
+ assert.ok(call.args[0]?.origin, '接收者节点缺少 origin。');
73
+ });
74
+ });
75
+ //# sourceMappingURL=ufcs-receiver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ufcs-receiver.test.js","sourceRoot":"","sources":["../../../test/unit/ufcs-receiver.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aster-cloud/aster-lang-ts",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
4
4
  "description": "Aster CNL (Controlled Natural Language) TypeScript Compiler - Lexer, Parser, AST, Core IR, Type Checker",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",