@aster-cloud/aster-lang-ts 1.2.3 → 1.2.5

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 (64) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/dist/src/config/semantic.d.ts +19 -0
  3. package/dist/src/config/semantic.d.ts.map +1 -1
  4. package/dist/src/config/semantic.js +32 -0
  5. package/dist/src/config/semantic.js.map +1 -1
  6. package/dist/src/core/interpreter.js +43 -7
  7. package/dist/src/core/interpreter.js.map +1 -1
  8. package/dist/src/core/resolve-typed-references.d.ts.map +1 -1
  9. package/dist/src/core/resolve-typed-references.js +18 -1
  10. package/dist/src/core/resolve-typed-references.js.map +1 -1
  11. package/dist/src/lsp/member-completion.d.ts.map +1 -1
  12. package/dist/src/lsp/member-completion.js +22 -5
  13. package/dist/src/lsp/member-completion.js.map +1 -1
  14. package/dist/src/parser/decl-parser.d.ts.map +1 -1
  15. package/dist/src/parser/decl-parser.js +2 -1
  16. package/dist/src/parser/decl-parser.js.map +1 -1
  17. package/dist/src/typecheck/browser.d.ts.map +1 -1
  18. package/dist/src/typecheck/browser.js +5 -4
  19. package/dist/src/typecheck/browser.js.map +1 -1
  20. package/dist/src/typecheck/context.d.ts +1 -1
  21. package/dist/src/typecheck/context.d.ts.map +1 -1
  22. package/dist/src/typecheck/context.js +9 -3
  23. package/dist/src/typecheck/context.js.map +1 -1
  24. package/dist/src/typecheck/expression.d.ts.map +1 -1
  25. package/dist/src/typecheck/expression.js +64 -20
  26. package/dist/src/typecheck/expression.js.map +1 -1
  27. package/dist/src/typecheck/module.d.ts.map +1 -1
  28. package/dist/src/typecheck/module.js +5 -4
  29. package/dist/src/typecheck/module.js.map +1 -1
  30. package/dist/src/typecheck/pure.d.ts +17 -0
  31. package/dist/src/typecheck/pure.d.ts.map +1 -1
  32. package/dist/src/typecheck/pure.js +96 -0
  33. package/dist/src/typecheck/pure.js.map +1 -1
  34. package/dist/src/typecheck/statement.d.ts.map +1 -1
  35. package/dist/src/typecheck/statement.js +3 -1
  36. package/dist/src/typecheck/statement.js.map +1 -1
  37. package/dist/src/typecheck/symbol_table.d.ts +3 -0
  38. package/dist/src/typecheck/symbol_table.d.ts.map +1 -1
  39. package/dist/src/typecheck/symbol_table.js +1 -0
  40. package/dist/src/typecheck/symbol_table.js.map +1 -1
  41. package/dist/src/typecheck/utils.d.ts +1 -1
  42. package/dist/src/typecheck/utils.d.ts.map +1 -1
  43. package/dist/src/typecheck/utils.js +1 -1
  44. package/dist/src/typecheck/utils.js.map +1 -1
  45. package/dist/src/typecheck/workflow.d.ts.map +1 -1
  46. package/dist/src/typecheck/workflow.js +13 -2
  47. package/dist/src/typecheck/workflow.js.map +1 -1
  48. package/dist/test/unit/core/caseless-pattern-name.test.d.ts +2 -0
  49. package/dist/test/unit/core/caseless-pattern-name.test.d.ts.map +1 -0
  50. package/dist/test/unit/core/caseless-pattern-name.test.js +114 -0
  51. package/dist/test/unit/core/caseless-pattern-name.test.js.map +1 -0
  52. package/dist/test/unit/formatter-corpus-roundtrip.test.js +2 -0
  53. package/dist/test/unit/formatter-corpus-roundtrip.test.js.map +1 -1
  54. package/dist/test/unit/lsp/member-completion.test.js +67 -6
  55. package/dist/test/unit/lsp/member-completion.test.js.map +1 -1
  56. package/dist/test/unit/rule-call-checks.test.d.ts +2 -0
  57. package/dist/test/unit/rule-call-checks.test.d.ts.map +1 -0
  58. package/dist/test/unit/rule-call-checks.test.js +275 -0
  59. package/dist/test/unit/rule-call-checks.test.js.map +1 -0
  60. package/dist/test/unit/typecheck-followups.test.d.ts +2 -0
  61. package/dist/test/unit/typecheck-followups.test.d.ts.map +1 -0
  62. package/dist/test/unit/typecheck-followups.test.js +165 -0
  63. package/dist/test/unit/typecheck-followups.test.js.map +1 -0
  64. package/package.json +1 -1
@@ -0,0 +1,275 @@
1
+ /**
2
+ * 用户规则调用的静态检查与运行期调用目标(#266 #268)。
3
+ *
4
+ * #266:调用本模块规则或函数值局部名时,按**显式写了类型**的形参比较实参类型,不符报 E001
5
+ * (与 Java BaseTypeChecker.checkCall 同码)。未写类型的形参(解析器按名字推断出类型,
6
+ * `typeInferred`)不参与比较——推断类型只是按名字猜的。Java 目前仍按推断类型比较并拒绝这类调用,
7
+ * TS 放行(向 TS 对齐见 aster-lang-core#229)。原则:能正常运行的程序不新增 E001,拿不准时放行。
8
+ * #268:调用目标解析与 Java/truffle 一致——局部名遮蔽同名规则。局部名类型已知且不是函数类型时
9
+ * 报 E001(期望函数);TS 解释器同样按局部名分派,不再悄悄改调同名规则。
10
+ */
11
+ import { describe, it } from 'node:test';
12
+ import { existsSync, readFileSync } from 'node:fs';
13
+ import { join, resolve } from 'node:path';
14
+ import assert from 'node:assert/strict';
15
+ import { compileAndTypecheck, evaluate, EN_US } from '../../src/browser.js';
16
+ import { CALL_TARGET_BUILTIN_ALIASES, NAMED_BUILTIN_OPS } from '../../src/config/semantic.js';
17
+ const INC = 'Rule inc given x as Int, produce Int:\n Return x plus 1.\n\n';
18
+ const GREET = 'Rule greet given name as Text, produce Text:\n Return name.\n\n';
19
+ const TWICE = 'Rule twice given f as (Int) -> Int, n as Int, produce Int:\n Return f(f(n)).\n\n';
20
+ function check(body) {
21
+ const r = compileAndTypecheck(`Module demo.\n\n${body}`, { lexicon: EN_US });
22
+ const errors = [...(r.parseErrors ?? []), ...(r.resolutionDiagnostics ?? []), ...(r.typeErrors ?? [])]
23
+ .filter((d) => d.severity === 'error');
24
+ return { errors, core: r.core };
25
+ }
26
+ function mismatches(errors) {
27
+ return errors.filter((d) => d.code === 'E001').map((d) => d.data);
28
+ }
29
+ describe('#266 用户规则调用的实参类型', () => {
30
+ it('★inc("a"):形参 Int、实参 Text,报 E001', () => {
31
+ const { errors } = check(INC + 'Rule main given n as Int, produce Int:\n Return inc("a").\n');
32
+ assert.deepEqual(mismatches(errors), [{ expected: 'Int', actual: 'Text' }]);
33
+ });
34
+ it('经函数值局部名调用同样比较:Let g be inc. Return g("a").', () => {
35
+ const { errors } = check(INC + 'Rule main given n as Int, produce Int:\n Let g be inc.\n Return g("a").\n');
36
+ assert.deepEqual(mismatches(errors), [{ expected: 'Int', actual: 'Text' }]);
37
+ });
38
+ it('函数值实参与函数类型形参不符:twice(greet, n) 报 E001', () => {
39
+ const { errors } = check(GREET + TWICE + 'Rule main given n as Int, produce Int:\n Return twice(greet, n).\n');
40
+ assert.deepEqual(mismatches(errors), [{ expected: '(Int) -> Int', actual: '(Text) -> Text' }]);
41
+ });
42
+ it('类型相符不报错:inc(n)、twice(inc, n)', () => {
43
+ const { errors } = check(INC + TWICE + 'Rule main given n as Int, produce Int:\n Return twice(inc, inc(n)).\n');
44
+ assert.deepEqual(errors, []);
45
+ });
46
+ it('★未写类型的形参不比较:greet given name 推断为 Text,传 Int 不报错', () => {
47
+ const { errors } = check('Rule label given amount, produce Text:\n Return "x".\n\n' +
48
+ 'Rule main given n as Int, produce Text:\n Return label("a").\n');
49
+ assert.deepEqual(errors, []);
50
+ });
51
+ it('未写类型的形参经函数值传递也不比较:twice(bump, n) 不因推断类型报错', () => {
52
+ const { errors } = check('Rule bump given amount, produce Int:\n Return 1.\n\n' + TWICE +
53
+ 'Rule main given n as Int, produce Int:\n Return twice(bump, n).\n');
54
+ assert.deepEqual(mismatches(errors), []);
55
+ });
56
+ it('lambda 函数值:显式类型形参比较,未写类型的形参不比较', () => {
57
+ const typed = check('Rule main given n as Int, produce Int:\n Let f be function with x as Int, produce Int:\n Return x.\n Return f("a").\n');
58
+ assert.deepEqual(mismatches(typed.errors), [{ expected: 'Int', actual: 'Text' }]);
59
+ const untyped = check('Rule main given flag as Bool, produce Int:\n Let f be function with x, produce:\n Return 1.\n Return f(flag).\n');
60
+ assert.deepEqual(mismatches(untyped.errors), []);
61
+ });
62
+ it('Int 实参传给 Float 形参按数值拓宽放行', () => {
63
+ const { errors } = check('Rule half given x as Float, produce Float:\n Return x.\n\n' +
64
+ 'Rule main given n as Int, produce Float:\n Return half(n).\n');
65
+ assert.deepEqual(mismatches(errors), []);
66
+ });
67
+ it('函数类型形参位按逆变比较:期望 (Int) -> Int 时可传 (Float) -> Int', () => {
68
+ const { errors } = check('Rule widen given x as Float, produce Int:\n Return 1.\n\n' + TWICE +
69
+ 'Rule main given n as Int, produce Int:\n Return twice(widen, n).\n');
70
+ assert.deepEqual(mismatches(errors), []);
71
+ });
72
+ it('实参只类型化一次:实参内部的诊断不重复', () => {
73
+ const { errors } = check(INC + 'Rule main given n as Int, produce Int:\n Return inc(Verdict.nope()).\n');
74
+ assert.deepEqual(errors.map((d) => d.code), ['E101'], JSON.stringify(errors));
75
+ });
76
+ it('个数不符报 E032,前缀位置照常比较类型(与 Java 一致,按 min 个数比较)', () => {
77
+ const { errors } = check(INC + 'Rule main given n as Int, produce Int:\n Return inc("a", n).\n');
78
+ assert.deepEqual(errors.map((d) => d.code).sort(), ['E001', 'E032']);
79
+ });
80
+ });
81
+ describe('#268 非函数局部名与规则同名', () => {
82
+ const SCORE = 'Rule score given a as Int, produce Int:\n Return a.\n\n';
83
+ it('★Rule main given score as Int … Return score(1, 2).:报 E001(期望函数),不按同名规则校验', () => {
84
+ const { errors } = check(SCORE + 'Rule main given score as Int, produce Int:\n Return score(1, 2).\n');
85
+ assert.deepEqual(errors.map((d) => d.code), ['E001']);
86
+ assert.deepEqual(errors[0].data, { expected: 'a function', actual: "'score' of type Int" });
87
+ });
88
+ it('没有同名规则时调用非函数局部名同样报 E001', () => {
89
+ const { errors } = check('Rule main given n as Int, produce Int:\n Return n(1).\n');
90
+ assert.deepEqual(errors.map((d) => d.data), [{ expected: 'a function', actual: "'n' of type Int" }]);
91
+ });
92
+ it('★解释器按局部名分派:局部值不可调用时报错,不再静默调用同名规则', () => {
93
+ const { core } = check(SCORE + 'Rule main given score as Int, produce Int:\n Return score(1, 2).\n');
94
+ assert.ok(core, '应产出 Core IR');
95
+ const r = evaluate(core, 'main', { score: 7 });
96
+ assert.equal(r.success, false, `不应求值成功:${JSON.stringify(r)}`);
97
+ assert.match(r.error ?? '', /score/);
98
+ });
99
+ it('函数类型局部名遮蔽同名规则的既有行为不变', () => {
100
+ const { errors, core } = check(INC + 'Rule main given inc as (Int) -> Int, n as Int, produce Int:\n Return inc(n).\n\n' +
101
+ 'Rule dec given x as Int, produce Int:\n Return x minus 1.\n\n' +
102
+ 'Rule run given n as Int, produce Int:\n Return main(dec, n).\n');
103
+ assert.deepEqual(errors, []);
104
+ const r = evaluate(core, 'run', { n: 5 });
105
+ assert.equal(r.success, true, r.error);
106
+ assert.equal(r.value, 4);
107
+ });
108
+ });
109
+ /** 运行 main 并断言成功:放行的用例须是真能跑通的程序 */
110
+ function runsOk(core, input) {
111
+ assert.ok(core, '应产出 Core IR');
112
+ const r = evaluate(core, 'main', input);
113
+ assert.equal(r.success, true, r.error);
114
+ return r.value;
115
+ }
116
+ describe('#266 审查跟进:能正常运行的调用不新增 E001', () => {
117
+ it('M1 实参为推断失败的返回类型(produce:):inc(mk(n)) 放行', () => {
118
+ const { errors, core } = check(INC + 'Rule mk given x as Int, produce:\n Return x.\n\nRule main given n as Int, produce Int:\n Return inc(mk(n)).\n');
119
+ assert.deepEqual(mismatches(errors), []);
120
+ assert.equal(runsOk(core, { n: 1 }), 2);
121
+ });
122
+ it('M1 函数值的返回类型为推断占位:twice(inc2, n)(inc2 写 produce:)放行', () => {
123
+ const { errors, core } = check('Rule inc2 given x as Int, produce:\n Return x plus 1.\n\n' + TWICE + 'Rule main given n as Int, produce Int:\n Return twice(inc2, n).\n');
124
+ assert.deepEqual(mismatches(errors), []);
125
+ assert.equal(runsOk(core, { n: 1 }), 3);
126
+ });
127
+ it('M1 未写类型且 produce: 推断不出返回类型的规则作函数值:twice(bump, n) 放行', () => {
128
+ // `amount plus 1` 推断不出返回类型,签名 ret 为 TypeVar 'Unknown' 占位,函数值类型为 (Unknown) -> Unknown
129
+ const { errors, core } = check('Rule bump given amount, produce:\n Return amount plus 1.\n\n' + TWICE + 'Rule main given n as Int, produce Int:\n Return twice(bump, n).\n');
130
+ assert.deepEqual(mismatches(errors), []);
131
+ assert.equal(runsOk(core, { n: 1 }), 3);
132
+ });
133
+ it('M1 泛型规则 id of T 作函数值传给 (Int) -> Int 放行', () => {
134
+ const { errors, core } = check('Rule id of T given x as T, produce T:\n Return x.\n\n' + TWICE + 'Rule main given n as Int, produce Int:\n Return twice(id, n).\n');
135
+ assert.deepEqual(mismatches(errors), []);
136
+ assert.equal(runsOk(core, { n: 4 }), 4);
137
+ });
138
+ it('M2 T → T?、None → T?、T? ↔ Option of T、Some(n) → Option of Int 都放行', () => {
139
+ const OPT = 'Rule pick given x as Text?, produce Text:\n Return "k".\n\nRule pickO given x as Option of Text, produce Text:\n Return "o".\n\nRule pickI given x as Option of Int, produce Text:\n Return "i".\n\n';
140
+ for (const call of ['pick(t)', 'pick(None)', 'pickO(m)', 'pick(o)', 'pickI(Some(n))']) {
141
+ const { errors, core } = check(OPT + `Rule main given t as Text, m as Text?, o as Option of Text, n as Int, produce Text:\n Return ${call}.\n`);
142
+ assert.deepEqual(mismatches(errors), [], call);
143
+ runsOk(core, { t: 'a', m: 'b', o: 'c', n: 1 });
144
+ }
145
+ });
146
+ it('M2 内层类型不符仍报:Text? 形参传 Int', () => {
147
+ const { errors } = check('Rule pick given x as Text?, produce Text:\n Return "k".\n\nRule main given n as Int, produce Text:\n Return pick(n).\n');
148
+ assert.deepEqual(mismatches(errors), [{ expected: 'Text?', actual: 'Int' }]);
149
+ });
150
+ it('M3 实参类型只来自名字推断(given amount)时放行:inc(amount)', () => {
151
+ const { errors, core } = check(INC + 'Rule main given amount, produce Int:\n Return inc(amount).\n');
152
+ assert.deepEqual(mismatches(errors), []);
153
+ assert.equal(runsOk(core, { amount: 1 }), 2);
154
+ });
155
+ it('M3 调用未写类型的形参(given f … f(n))不报「期望函数」', () => {
156
+ const { errors, core } = check(INC + 'Rule ap given f, n as Int, produce Int:\n Return f(n).\n\nRule main given n as Int, produce Int:\n Return ap(inc, n).\n');
157
+ assert.deepEqual(errors, []);
158
+ assert.equal(runsOk(core, { n: 1 }), 2);
159
+ });
160
+ it('数值拓宽统一放行:Int → Long / Float、Long → Float,含字面量与容器元素', () => {
161
+ const DECLS = 'Rule toL given x as Long, produce Int:\n Return 1.\n\nRule toF given x as Float, produce Int:\n Return 1.\n\n' +
162
+ 'Rule toLF given xs as List of Float, produce Int:\n Return 1.\n\nRule toOF given x as Option of Float, produce Int:\n Return 1.\n\n';
163
+ for (const call of ['toL(n)', 'toL(5)', 'toF(5)', 'toF(l)', 'toLF(xs)', 'toLF([1, 2])', 'toOF(Some(n))']) {
164
+ const { errors } = check(DECLS + `Rule main given n as Int, l as Long, xs as List of Int, produce Int:\n Return ${call}.\n`);
165
+ assert.deepEqual(mismatches(errors), [], call);
166
+ }
167
+ });
168
+ it('数值拓宽:Int / Long 实参传给 Decimal 形参放行,Double 传 Decimal 报错(ADR 0025)', () => {
169
+ const DECLS = 'Rule toD given x as Decimal, produce Int:\n Return 1.\n\n';
170
+ for (const call of ['toD(n)', 'toD(l)', 'toD(5)']) {
171
+ const { errors } = check(DECLS + `Rule main given n as Int, l as Long, produce Int:\n Return ${call}.\n`);
172
+ assert.deepEqual(mismatches(errors), [], call);
173
+ }
174
+ const { errors } = check(DECLS + 'Rule main given x as Float, produce Int:\n Return toD(x).\n');
175
+ assert.equal(mismatches(errors).length, 1);
176
+ });
177
+ it('收窄仍报:Float 实参传给 Int 形参', () => {
178
+ const { errors } = check(INC + 'Rule main given x as Float, produce Int:\n Return inc(x).\n');
179
+ assert.deepEqual(mismatches(errors), [{ expected: 'Int', actual: 'Double' }]);
180
+ });
181
+ });
182
+ describe('core#231 审查跟进:TS 不比 Java 严', () => {
183
+ const codes = (errors) => errors.map((d) => d.code);
184
+ it('F2 字段构造(E012)复用实参兼容规则:T? ← T、T? ← None、Long ← Int、List of Float ← List of Int 放行', () => {
185
+ const DATA = 'Define Box has t as Text?, l as Long, fs as List of Float.\n\n';
186
+ for (const [t, l, fs] of [['s', 'n', 'xs'], ['None', '5', '[1, 2]']]) {
187
+ const { errors, core } = check(DATA + `Rule main given s as Text, n as Int, xs as List of Int, produce Int:\n Let b be Box with t set to ${t}, l set to ${l}, fs set to ${fs}.\n Return 1.\n`);
188
+ assert.deepEqual(codes(errors), [], `${t} ${l} ${fs}`);
189
+ runsOk(core, { s: 'a', n: 1, xs: [1] });
190
+ }
191
+ });
192
+ it('F2 字段构造:推断不出返回类型的实参(produce:)放行,不再报 expects Float, got Unknown', () => {
193
+ const { errors } = check('Define Q has cost as Float.\n\nRule est given x as Int, produce:\n Return x plus 1.\n\n' +
194
+ 'Rule main given n as Int, produce Int:\n Let q be Q with cost set to est(n).\n Return 1.\n');
195
+ assert.deepEqual(codes(errors), []);
196
+ });
197
+ it('F2 字段构造的收窄仍报 E012:Int 字段 ← Float', () => {
198
+ const { errors } = check('Define Box has i as Int.\n\nRule main given x as Float, produce Int:\n Let b be Box with i set to x.\n Return 1.\n');
199
+ assert.deepEqual(codes(errors), ['E012']);
200
+ });
201
+ it('F2 Set(E002)复用实参兼容规则:Float 变量 ← Int、Text? 变量 ← Text 放行', () => {
202
+ const { errors, core } = check('Rule main given n as Int, f as Float, m as Text?, t as Text, produce Int:\n Let x be f.\n Set x to n.\n Let y be m.\n Set y to t.\n Return 1.\n');
203
+ assert.deepEqual(codes(errors), []);
204
+ runsOk(core, { n: 1, f: 1.5, m: 'a', t: 'b' });
205
+ });
206
+ it('F2 Set 的收窄仍报 E002:Int 变量 ← Float', () => {
207
+ const { errors } = check('Rule main given n as Int, f as Float, produce Int:\n Let x be n.\n Set x to f.\n Return 1.\n');
208
+ assert.deepEqual(codes(errors), ['E002']);
209
+ });
210
+ it('按名字推断的标记随 Let 传播:given amount 后 Let y be amount. inc(y) 放行', () => {
211
+ const { errors, core } = check(INC + 'Rule main given amount, produce Int:\n Let y be amount.\n Return inc(y).\n');
212
+ assert.deepEqual(codes(errors), []);
213
+ assert.equal(runsOk(core, { amount: 1 }), 2);
214
+ });
215
+ it('F1 局部名与单段 builtin 同名、调用的正是 builtin:不报「期望函数」,解释器先调 builtin(与 truffle 一致)', () => {
216
+ const cases = [
217
+ ['Rule main given add as Int, produce Int:\n Return add(1, 2).\n', { add: 7 }, 3],
218
+ ['Rule main given n as Int, produce Int:\n Let sub be 3.\n Return sub(5, n).\n', { n: 2 }, 3],
219
+ ['Rule main given gt as Int, produce Bool:\n Return gt(2, 1).\n', { gt: 0 }, true],
220
+ ];
221
+ for (const [body, input, expected] of cases) {
222
+ const { errors, core } = check(body);
223
+ assert.deepEqual(codes(errors), [], body);
224
+ assert.equal(runsOk(core, input), expected, body);
225
+ }
226
+ });
227
+ it('F1 builtin 名一律不做调用目标检查(与 core CallTargetBuiltins 一致);有同名规则时运行期按局部值分派,与 truffle 一致失败', () => {
228
+ const { errors, core } = check('Rule add given a as Int, b as Int, produce Int:\n Return a.\n\nRule main given add as Int, produce Int:\n Return add(1, 2).\n');
229
+ assert.deepEqual(codes(errors), []);
230
+ const r = evaluate(core, 'main', { add: 7 });
231
+ assert.equal(r.success, false);
232
+ assert.match(r.error ?? '', /'add' is not a function/);
233
+ });
234
+ it('R1 局部函数值优先于同名 builtin:函数类型形参 gt、闭包 add、单参闭包 add 都调用局部值', () => {
235
+ const cases = [
236
+ [
237
+ 'Rule lessThan given a as Int, b as Int, produce Bool:\n Return a less than b.\n\n' +
238
+ 'Rule ap given gt as (Int, Int) -> Bool, produce Bool:\n Return gt(1, 2).\n\n' +
239
+ 'Rule main given n as Int, produce Bool:\n Return ap(lessThan).\n',
240
+ { n: 0 },
241
+ true,
242
+ ],
243
+ ['Rule main given n as Int, produce Int:\n Let add be function with a as Int, b as Int, produce Int:\n Return a times b.\n Return add(2, 3).\n', { n: 0 }, 6],
244
+ ['Rule main given n as Int, produce Int:\n Let add be function with a as Int, produce Int:\n Return a.\n Return add(n).\n', { n: 1 }, 1],
245
+ ];
246
+ for (const [body, input, expected] of cases) {
247
+ const { errors, core } = check(body);
248
+ assert.deepEqual(codes(errors), [], body);
249
+ assert.equal(runsOk(core, input), expected, body);
250
+ }
251
+ });
252
+ it('R1 与 builtin 同名的局部函数值按局部函数类型检查:add 闭包为 (Int) -> Int 时 add(1, 2) 报 E032', () => {
253
+ const { errors } = check('Rule main given n as Int, produce Int:\n Let add be function with a as Int, produce Int:\n Return a.\n Return add(1, 2).\n');
254
+ assert.deepEqual(codes(errors), ['E032']);
255
+ });
256
+ it('F1 交叉核对:单段 builtin 名单与别名表与 aster-lang-core CallTargetBuiltins.NAMES / ALIASES 一致(找不到 core 即失败)', () => {
257
+ // CI 的 test job 把 core 检出到工作区内 ./aster-lang-core;本地可用 ASTER_CORE_DIR 指定,或放在兄弟目录 ../aster-lang-core
258
+ const RELATIVE = 'src/main/java/aster/core/typecheck/CallTargetBuiltins.java';
259
+ const roots = [process.env['ASTER_CORE_DIR'], resolve(process.cwd(), 'aster-lang-core'), resolve(process.cwd(), '..', 'aster-lang-core')];
260
+ const file = roots.filter((r) => !!r).map((r) => join(r, RELATIVE)).find((f) => existsSync(f));
261
+ assert.ok(file, `找不到 aster-lang-core 的 ${RELATIVE}(CI 检出 ./aster-lang-core;本地用 ASTER_CORE_DIR 指定)`);
262
+ const source = readFileSync(file, 'utf8');
263
+ const block = /Set\.of\(([^)]*)\)/.exec(source);
264
+ assert.ok(block, 'CallTargetBuiltins.NAMES 的 Set.of(...) 未找到');
265
+ const names = [...block[1].matchAll(/"([^"]+)"/g)].map((m) => m[1]);
266
+ assert.deepEqual([...new Set(names)].sort(), Object.keys(NAMED_BUILTIN_OPS).sort());
267
+ // core#234:单词别名表(ALIASES = Map.of("plus", "add", …))同样逐项一致
268
+ const aliasBlock = /ALIASES\s*=\s*Map\.of\(([^)]*)\)/.exec(source);
269
+ assert.ok(aliasBlock, 'CallTargetBuiltins.ALIASES 的 Map.of(...) 未找到');
270
+ const flat = [...aliasBlock[1].matchAll(/"([^"]+)"/g)].map((m) => m[1]);
271
+ const aliases = Object.fromEntries(flat.flatMap((v, i) => (i % 2 === 0 ? [[v, flat[i + 1]]] : [])));
272
+ assert.deepEqual(aliases, { ...CALL_TARGET_BUILTIN_ALIASES });
273
+ });
274
+ });
275
+ //# sourceMappingURL=rule-call-checks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-call-checks.test.js","sourceRoot":"","sources":["../../../test/unit/rule-call-checks.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=typecheck-followups.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typecheck-followups.test.d.ts","sourceRoot":"","sources":["../../../test/unit/typecheck-followups.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * 类型检查跟进(aster-lang-core#232 #234、aster-lang-ts#276 #277,两引擎同步)。
3
+ *
4
+ * 原则(用户裁决):能正确运行的代码不报错;按名字推断出的类型视为未知;数值拓宽在所有赋值类位置
5
+ * (实参、字段、Set、Return)放行,收窄照常报错;TS 不比 Java 严。
6
+ * - core#232:未写类型的 data 字段不按推断类型检查构造值(E012);按名字推断类型的局部名放进字段、
7
+ * Set、Return 时不作约束;Return 位置与实参一样按可赋值规则比较(拓宽、T → T?、None → T?)。
8
+ * - core#234:truffle 把 equals / is / over / under / divide 等单词别名(不区分大小写)归一为 builtin,
9
+ * 与这些名字同名的非函数局部名被调用时不报「调用非函数局部名」;未声明时 TS 解释器同样按 builtin 分派。
10
+ * - ts#276:`Decimal` 是内置标量,不再被当作隐式类型参数;Int / Long → Decimal 放行,
11
+ * Float / Double ↔ Decimal(ADR 0025)、Decimal → Int、Text → Decimal 报错。
12
+ * - ts#277:`T?` 的值可能是裸值 / null(宿主传入,或 T → T? 直接传入):裸的非 null 值匹配 `When Some(v)`,
13
+ * null 匹配 `When None`(与 truffle 同步修复)。
14
+ */
15
+ import { describe, it } from 'node:test';
16
+ import assert from 'node:assert/strict';
17
+ import { compileAndTypecheck, evaluate, EN_US } from '../../src/browser.js';
18
+ function check(body) {
19
+ const r = compileAndTypecheck(`Module demo.\n\n${body}`, { lexicon: EN_US });
20
+ const errors = [...(r.parseErrors ?? []), ...(r.resolutionDiagnostics ?? []), ...(r.typeErrors ?? [])]
21
+ .filter((d) => d.severity === 'error' || d.severity === undefined);
22
+ return { codes: errors.map((d) => d.code), messages: errors.map((d) => `${d.code} ${d.message}`), core: r.core };
23
+ }
24
+ function run(core, input) {
25
+ assert.ok(core, '应产出 Core IR');
26
+ const r = evaluate(core, 'main', input);
27
+ assert.equal(r.success, true, r.error);
28
+ return r.value;
29
+ }
30
+ describe('core#232 按名字推断的类型视为未知', () => {
31
+ it('★未写类型的 data 字段不按推断类型检查构造值(collateralRequired 推断为 Text,传 Int)', () => {
32
+ const { codes } = check('Define Decision has approved, collateralRequired, bmi.\n\n' +
33
+ 'Rule main given n as Int, produce Decision:\n' +
34
+ ' Return Decision with approved set to true, collateralRequired set to 1, bmi set to 22.\n');
35
+ assert.deepEqual(codes, []);
36
+ });
37
+ it('按名字推断类型的局部名放进写了类型的字段不报 E012', () => {
38
+ const { codes } = check('Define P has total as Int.\n\nRule main given amount, produce P:\n Return P with total set to amount.\n');
39
+ assert.deepEqual(codes, []);
40
+ });
41
+ it('★Return amount(推断为 Float)在 produce Int 规则中不报 E003,经 Let 传递同样', () => {
42
+ assert.deepEqual(check('Rule main given amount, produce Int:\n Return amount.\n').codes, []);
43
+ assert.deepEqual(check('Rule main given amount, produce Int:\n Let y be amount.\n Return y.\n').codes, []);
44
+ });
45
+ it('Set 为按名字推断类型的值不报 E002,之后 Return 也不报 E003', () => {
46
+ const { codes } = check('Rule main given amount, produce Int:\n Let y be 1.\n Set y to amount.\n Return y.\n');
47
+ assert.deepEqual(codes, []);
48
+ });
49
+ it('If 条件为按名字推断类型的局部名不报错', () => {
50
+ const { codes } = check('Rule main given approved_status, produce Int:\n If approved_status:\n Return 1.\n Return 0.\n');
51
+ assert.deepEqual(codes, []);
52
+ });
53
+ it('★Return 位置数值拓宽与可空放行:Int → Float / Long / Decimal、Long → Float、T → T?、None → T?', () => {
54
+ const cases = [
55
+ 'Rule main given n as Int, produce Float:\n Return 1.\n',
56
+ 'Rule main given n as Int, produce Long:\n Return n.\n',
57
+ 'Rule main given n as Int, produce Decimal:\n Return n.\n',
58
+ 'Rule main given n as Long, produce Float:\n Return n.\n',
59
+ 'Rule main given n as Int, produce Int?:\n Return n.\n',
60
+ 'Rule main given n as Int, produce Int?:\n Return None.\n',
61
+ 'Rule main given n as Int, produce Long:\n Let g be function with x as Int, produce Long:\n Return x.\n Return g(n).\n',
62
+ ];
63
+ for (const body of cases)
64
+ assert.deepEqual(check(body).codes, [], body);
65
+ });
66
+ it('收窄仍报错:Return Float → Int、Text → Int、T? → T、Double → Decimal、Decimal → Float;字段 Text → Int;Set Float → Int', () => {
67
+ const cases = [
68
+ ['Rule main given n as Float, produce Int:\n Return n.\n', 'E003'],
69
+ ['Rule main given t as Text, produce Int:\n Return t.\n', 'E003'],
70
+ ['Rule main given n as Int?, produce Int:\n Return n.\n', 'E003'],
71
+ ['Rule main given d as Double, produce Decimal:\n Return d.\n', 'E003'],
72
+ ['Rule main given d as Decimal, produce Float:\n Return d.\n', 'E003'],
73
+ ['Rule main given n as Float, produce Int:\n Let g be function with x as Float, produce Int:\n Return x.\n Return g(n).\n', 'E003'],
74
+ ['Define P has total as Int.\n\nRule main given t as Text, produce P:\n Return P with total set to t.\n', 'E012'],
75
+ ['Rule main given f as Float, produce Int:\n Let y be 1.\n Set y to f.\n Return 0.\n', 'E002'],
76
+ ];
77
+ for (const [body, code] of cases)
78
+ assert.ok(check(body).codes.includes(code), `${body} 应报 ${code}`);
79
+ });
80
+ });
81
+ describe('core#234 truffle 归一化的 builtin 别名', () => {
82
+ it('★与别名同名的非函数局部名被调用不报 E001:over / divide / under / equals / is', () => {
83
+ const cases = [
84
+ 'Rule main given over as Int, produce Bool:\n Return over(3, 2).\n',
85
+ 'Rule main given divide as Int, produce Int:\n Return divide(10, 2).\n',
86
+ 'Rule main given under as Int, produce Bool:\n Return under(1, 2).\n',
87
+ 'Rule main given equals as Int, produce Bool:\n Return equals(2, 2).\n',
88
+ 'Rule main given is as Int, produce Bool:\n Return is(2, 2).\n',
89
+ ];
90
+ for (const body of cases)
91
+ assert.deepEqual(check(body).codes, [], body);
92
+ });
93
+ it('解释器按 builtin 分派别名(与 truffle Builtins.canonicalName 一致)', () => {
94
+ assert.equal(run(check('Rule main given over as Int, produce Bool:\n Return over(3, 2).\n').core, { over: 0 }), true);
95
+ assert.equal(run(check('Rule main given n as Int, produce Int:\n Return divide(10, 2).\n').core, { n: 0 }), 5);
96
+ assert.equal(run(check('Rule main given n as Int, produce Bool:\n Return equals(n, 2).\n').core, { n: 2 }), true);
97
+ });
98
+ it('不是别名的非函数局部名仍报 E001', () => {
99
+ const { codes } = check('Rule score given a as Int, produce Int:\n Return a.\n\nRule main given n as Int, produce Int:\n Let score be 3.\n Return score(n).\n');
100
+ assert.deepEqual(codes, ['E001']);
101
+ });
102
+ });
103
+ describe('ts#276 Decimal 是内置标量', () => {
104
+ const MONEY = 'Rule money given x as Decimal, produce Decimal:\n Return x.\n\n';
105
+ const INC = 'Rule inc given x as Int, produce Int:\n Return x plus 1.\n\n';
106
+ it('Decimal 形参不再降级为类型参数', () => {
107
+ const { core } = check(MONEY);
108
+ const func = core.decls.find((d) => d.kind === 'Func');
109
+ assert.deepEqual(func.typeParams, []);
110
+ assert.equal(func.params[0].type.kind, 'TypeName');
111
+ });
112
+ it('★Int / Long / Decimal → Decimal 放行', () => {
113
+ for (const t of ['Int', 'Long', 'Decimal']) {
114
+ assert.deepEqual(check(MONEY + `Rule main given d as ${t}, produce Decimal:\n Return money(d).\n`).codes, [], t);
115
+ }
116
+ });
117
+ it('★Text / Float / Double → Decimal、Decimal → Int / Double 报 E001(ADR 0025)', () => {
118
+ for (const t of ['Text', 'Float', 'Double']) {
119
+ assert.deepEqual(check(MONEY + `Rule main given d as ${t}, produce Decimal:\n Return money(d).\n`).codes, ['E001'], t);
120
+ }
121
+ assert.deepEqual(check(MONEY + 'Rule main given n as Int, produce Decimal:\n Return money(1.5).\n').codes, ['E001']);
122
+ assert.deepEqual(check(INC + 'Rule main given d as Decimal, produce Int:\n Return inc(d).\n').codes, ['E001']);
123
+ assert.deepEqual(check('Rule h given x as Double, produce Double:\n Return x.\n\nRule main given d as Decimal, produce Double:\n Return h(d).\n').codes, ['E001']);
124
+ });
125
+ it('produce Decimal 返回 Decimal 运算结果不报 E003(此前 TypeVar 与 TypeName 比较误报 expected Decimal, got Decimal)', () => {
126
+ const { codes } = check('Rule main given d as Decimal, produce Decimal:\n Return Decimal.round(d plus 1, 2, "HALF_UP").\n');
127
+ assert.deepEqual(codes, []);
128
+ });
129
+ });
130
+ describe('ts#277 T? 的裸值与 Some / None 模式', () => {
131
+ const MATCH = 'Rule f given x as Int?, produce Int:\n Match x:\n When None, Return 0.\n When Some(v), Return v.\n\n';
132
+ it('★裸值实参 f(n) 走 Some 分支,Some(n) 与 None 不变', () => {
133
+ assert.equal(run(check(MATCH + 'Rule main given n as Int, produce Int:\n Return f(n).\n').core, { n: 3 }), 3);
134
+ assert.equal(run(check(MATCH + 'Rule main given n as Int, produce Int:\n Return f(Some(n)).\n').core, { n: 3 }), 3);
135
+ assert.equal(run(check(MATCH + 'Rule main given n as Int, produce Int:\n Return f(None).\n').core, { n: 3 }), 0);
136
+ });
137
+ it('★宿主传入的裸值 3 与 null', () => {
138
+ const body = 'Rule main given x as Int?, produce Int:\n Match x:\n When Some(v), Return v.\n When None, Return 0.\n';
139
+ const { codes, core } = check(body);
140
+ assert.deepEqual(codes, []);
141
+ assert.equal(run(core, { x: 3 }), 3);
142
+ assert.equal(run(core, { x: null }), 0);
143
+ });
144
+ it('Ok 值不匹配 Some(v)', () => {
145
+ const body = 'Rule main given n as Int, produce Int:\n Let y be Ok(n).\n Match y:\n When Some(v), Return 1.\n When other, Return 2.\n';
146
+ assert.equal(run(check(body).core, { n: 5 }), 2);
147
+ });
148
+ });
149
+ describe('ts#279 workflow step / compensate 体的作用域(与 truffle#163 一致)', () => {
150
+ it('不同 step 与 compensate 中的同名 Let 不报 E104;Set 写回外层', () => {
151
+ const body = 'Rule runSteps given n as Int, produce Int. It performs io:\n Let x be n.\n workflow:\n' +
152
+ ' step first:\n Let x be n plus 1.\n Let y be x times 2.\n Return ok of y.\n' +
153
+ ' compensate:\n Let x be n minus 1.\n Return ok of x.\n\n' +
154
+ ' step second:\n Let y be n plus 10.\n Return ok of y.\n\n' +
155
+ ' step third:\n Set x to n plus 100.\n Return ok of x.\n .\n Return x.\n';
156
+ assert.deepEqual(check(body).codes, []);
157
+ });
158
+ it('跨 step 读取另一 step 的 Let 报未定义', () => {
159
+ const body = 'Rule runSteps given n as Int, produce Int. It performs io:\n workflow:\n' +
160
+ ' step first:\n Let y be n plus 1.\n Return ok of y.\n\n' +
161
+ ' step second:\n Return ok of y.\n .\n Return n.\n';
162
+ assert.ok(check(body).codes.length > 0);
163
+ });
164
+ });
165
+ //# sourceMappingURL=typecheck-followups.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typecheck-followups.test.js","sourceRoot":"","sources":["../../../test/unit/typecheck-followups.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.2.3",
3
+ "version": "1.2.5",
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",