@aster-cloud/aster-lang-ts 1.0.30 → 1.0.32
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.
- package/dist/scripts/aster.js +11 -26
- package/dist/scripts/aster.js.map +1 -1
- package/dist/scripts/corpus-loader.d.ts +17 -0
- package/dist/scripts/corpus-loader.d.ts.map +1 -0
- package/dist/scripts/corpus-loader.js +60 -0
- package/dist/scripts/corpus-loader.js.map +1 -0
- package/dist/scripts/emit-classfiles-core.js +5 -13
- package/dist/scripts/emit-classfiles-core.js.map +1 -1
- package/dist/scripts/emit-classfiles.js +7 -12
- package/dist/scripts/emit-classfiles.js.map +1 -1
- package/dist/scripts/generate_error_codes.js +2 -0
- package/dist/scripts/generate_error_codes.js.map +1 -1
- package/dist/scripts/golden.js +4 -1
- package/dist/scripts/golden.js.map +1 -1
- package/dist/scripts/test-lossless-golden.js +2 -1
- package/dist/scripts/test-lossless-golden.js.map +1 -1
- package/dist/scripts/validate_error_codes.js +1 -0
- package/dist/scripts/validate_error_codes.js.map +1 -1
- package/dist/scripts/verify-lexicon-sync.js +5 -1
- package/dist/scripts/verify-lexicon-sync.js.map +1 -1
- package/dist/src/ast/ast.d.ts +1 -1
- package/dist/src/ast/ast.d.ts.map +1 -1
- package/dist/src/ast/ast.js +2 -1
- package/dist/src/ast/ast.js.map +1 -1
- package/dist/src/browser.d.ts +7 -0
- package/dist/src/browser.d.ts.map +1 -1
- package/dist/src/browser.js +4 -0
- package/dist/src/browser.js.map +1 -1
- package/dist/src/cli/utils/gradle-env.d.ts +9 -0
- package/dist/src/cli/utils/gradle-env.d.ts.map +1 -0
- package/dist/src/cli/utils/gradle-env.js +18 -0
- package/dist/src/cli/utils/gradle-env.js.map +1 -0
- package/dist/src/cli/utils/out-dir.d.ts +18 -0
- package/dist/src/cli/utils/out-dir.d.ts.map +1 -0
- package/dist/src/cli/utils/out-dir.js +49 -0
- package/dist/src/cli/utils/out-dir.js.map +1 -0
- package/dist/src/cnl-printer.d.ts +10 -0
- package/dist/src/cnl-printer.d.ts.map +1 -0
- package/dist/src/cnl-printer.js +360 -0
- package/dist/src/cnl-printer.js.map +1 -0
- package/dist/src/config/lexicons/de-DE.d.ts.map +1 -1
- package/dist/src/config/lexicons/de-DE.js +8 -2
- package/dist/src/config/lexicons/de-DE.js.map +1 -1
- package/dist/src/config/lexicons/en-US.d.ts.map +1 -1
- package/dist/src/config/lexicons/en-US.js +8 -4
- package/dist/src/config/lexicons/en-US.js.map +1 -1
- package/dist/src/config/lexicons/hi-IN.d.ts.map +1 -1
- package/dist/src/config/lexicons/hi-IN.js +8 -2
- package/dist/src/config/lexicons/hi-IN.js.map +1 -1
- package/dist/src/config/lexicons/template.d.ts.map +1 -1
- package/dist/src/config/lexicons/template.js +12 -0
- package/dist/src/config/lexicons/template.js.map +1 -1
- package/dist/src/config/lexicons/zh-CN.d.ts.map +1 -1
- package/dist/src/config/lexicons/zh-CN.js +9 -3
- package/dist/src/config/lexicons/zh-CN.js.map +1 -1
- package/dist/src/config/semantic.d.ts +6 -0
- package/dist/src/config/semantic.d.ts.map +1 -1
- package/dist/src/config/semantic.js +8 -0
- package/dist/src/config/semantic.js.map +1 -1
- package/dist/src/config/token-kind.d.ts +12 -0
- package/dist/src/config/token-kind.d.ts.map +1 -1
- package/dist/src/config/token-kind.js +18 -0
- package/dist/src/config/token-kind.js.map +1 -1
- package/dist/src/core/core_ir.d.ts +1 -1
- package/dist/src/core/core_ir.d.ts.map +1 -1
- package/dist/src/core/core_ir.js +3 -1
- package/dist/src/core/core_ir.js.map +1 -1
- package/dist/src/core/interpreter.d.ts.map +1 -1
- package/dist/src/core/interpreter.js +222 -18
- package/dist/src/core/interpreter.js.map +1 -1
- package/dist/src/cst/cst_printer.d.ts.map +1 -1
- package/dist/src/cst/cst_printer.js +66 -32
- package/dist/src/cst/cst_printer.js.map +1 -1
- package/dist/src/diagnostics/diagnostics.d.ts +1 -0
- package/dist/src/diagnostics/diagnostics.d.ts.map +1 -1
- package/dist/src/diagnostics/diagnostics.js +1 -0
- package/dist/src/diagnostics/diagnostics.js.map +1 -1
- package/dist/src/diagnostics/error_codes.d.ts +10 -2
- package/dist/src/diagnostics/error_codes.d.ts.map +1 -1
- package/dist/src/diagnostics/error_codes.js +64 -0
- package/dist/src/diagnostics/error_codes.js.map +1 -1
- package/dist/src/effects/effect_inference.js +1 -1
- package/dist/src/effects/effect_inference.js.map +1 -1
- package/dist/src/formatter.d.ts +3 -0
- package/dist/src/formatter.d.ts.map +1 -1
- package/dist/src/formatter.js +8 -261
- package/dist/src/formatter.js.map +1 -1
- package/dist/src/frontend/transformers.d.ts.map +1 -1
- package/dist/src/frontend/transformers.js +10 -2
- package/dist/src/frontend/transformers.js.map +1 -1
- package/dist/src/governance/controls-registry.data.d.ts +40 -0
- package/dist/src/governance/controls-registry.data.d.ts.map +1 -0
- package/dist/src/governance/controls-registry.data.js +35 -0
- package/dist/src/governance/controls-registry.data.js.map +1 -0
- package/dist/src/governance/controls.d.ts +23 -0
- package/dist/src/governance/controls.d.ts.map +1 -0
- package/dist/src/governance/controls.js +77 -0
- package/dist/src/governance/controls.js.map +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/lower_to_core.js +1 -1
- package/dist/src/lower_to_core.js.map +1 -1
- package/dist/src/lsp/completion.d.ts +22 -1
- package/dist/src/lsp/completion.d.ts.map +1 -1
- package/dist/src/lsp/completion.js +42 -1
- package/dist/src/lsp/completion.js.map +1 -1
- package/dist/src/lsp/debounce-map.d.ts +16 -0
- package/dist/src/lsp/debounce-map.d.ts.map +1 -0
- package/dist/src/lsp/debounce-map.js +32 -0
- package/dist/src/lsp/debounce-map.js.map +1 -0
- package/dist/src/lsp/server.js +6 -8
- package/dist/src/lsp/server.js.map +1 -1
- package/dist/src/lsp/utils.d.ts.map +1 -1
- package/dist/src/lsp/utils.js +2 -0
- package/dist/src/lsp/utils.js.map +1 -1
- package/dist/src/lsp/workspace/file-watcher.d.ts +1 -0
- package/dist/src/lsp/workspace/file-watcher.d.ts.map +1 -1
- package/dist/src/lsp/workspace/file-watcher.js +24 -14
- package/dist/src/lsp/workspace/file-watcher.js.map +1 -1
- package/dist/src/manifest.d.ts +2 -0
- package/dist/src/manifest.d.ts.map +1 -1
- package/dist/src/manifest.js.map +1 -1
- package/dist/src/package/manifest-parser.d.ts +10 -0
- package/dist/src/package/manifest-parser.d.ts.map +1 -1
- package/dist/src/package/manifest-parser.js +27 -28
- package/dist/src/package/manifest-parser.js.map +1 -1
- package/dist/src/package/manifest-schema.d.ts +15 -0
- package/dist/src/package/manifest-schema.d.ts.map +1 -0
- package/dist/src/package/manifest-schema.js +116 -0
- package/dist/src/package/manifest-schema.js.map +1 -0
- package/dist/src/parser/context.d.ts +2 -0
- package/dist/src/parser/context.d.ts.map +1 -1
- package/dist/src/parser/context.js +1 -0
- package/dist/src/parser/context.js.map +1 -1
- package/dist/src/parser/decl-parser.d.ts.map +1 -1
- package/dist/src/parser/decl-parser.js +26 -10
- package/dist/src/parser/decl-parser.js.map +1 -1
- package/dist/src/parser/expr-stmt-parser.d.ts +4 -1
- package/dist/src/parser/expr-stmt-parser.d.ts.map +1 -1
- package/dist/src/parser/expr-stmt-parser.js +199 -6
- package/dist/src/parser/expr-stmt-parser.js.map +1 -1
- package/dist/src/parser/import-parser.d.ts +12 -0
- package/dist/src/parser/import-parser.d.ts.map +1 -1
- package/dist/src/parser/import-parser.js +28 -0
- package/dist/src/parser/import-parser.js.map +1 -1
- package/dist/src/parser.js +1 -1
- package/dist/src/parser.js.map +1 -1
- package/dist/src/typecheck/browser.d.ts +3 -0
- package/dist/src/typecheck/browser.d.ts.map +1 -1
- package/dist/src/typecheck/browser.js +10 -1
- package/dist/src/typecheck/browser.js.map +1 -1
- package/dist/src/typecheck/context.d.ts +3 -0
- package/dist/src/typecheck/context.d.ts.map +1 -1
- package/dist/src/typecheck/context.js.map +1 -1
- package/dist/src/typecheck/expression.d.ts +6 -0
- package/dist/src/typecheck/expression.d.ts.map +1 -1
- package/dist/src/typecheck/expression.js +54 -2
- package/dist/src/typecheck/expression.js.map +1 -1
- package/dist/src/typecheck/generics.d.ts.map +1 -1
- package/dist/src/typecheck/generics.js +3 -0
- package/dist/src/typecheck/generics.js.map +1 -1
- package/dist/src/typecheck/governance.d.ts +43 -0
- package/dist/src/typecheck/governance.d.ts.map +1 -0
- package/dist/src/typecheck/governance.js +162 -0
- package/dist/src/typecheck/governance.js.map +1 -0
- package/dist/src/typecheck/module.d.ts.map +1 -1
- package/dist/src/typecheck/module.js +10 -1
- package/dist/src/typecheck/module.js.map +1 -1
- package/dist/src/typecheck/statement.d.ts.map +1 -1
- package/dist/src/typecheck/statement.js +2 -2
- package/dist/src/typecheck/statement.js.map +1 -1
- package/dist/src/typecheck/type_system.d.ts.map +1 -1
- package/dist/src/typecheck/type_system.js +4 -0
- package/dist/src/typecheck/type_system.js.map +1 -1
- package/dist/src/typecheck/verdict_signatures.d.ts +19 -0
- package/dist/src/typecheck/verdict_signatures.d.ts.map +1 -0
- package/dist/src/typecheck/verdict_signatures.js +23 -0
- package/dist/src/typecheck/verdict_signatures.js.map +1 -0
- package/dist/src/types/base.d.ts +2 -0
- package/dist/src/types/base.d.ts.map +1 -1
- package/dist/test/helpers/sibling-source.d.ts +10 -0
- package/dist/test/helpers/sibling-source.d.ts.map +1 -0
- package/dist/test/helpers/sibling-source.js +20 -0
- package/dist/test/helpers/sibling-source.js.map +1 -0
- package/dist/test/unit/allocation-budget.test.d.ts +2 -0
- package/dist/test/unit/allocation-budget.test.d.ts.map +1 -0
- package/dist/test/unit/allocation-budget.test.js +160 -0
- package/dist/test/unit/allocation-budget.test.js.map +1 -0
- package/dist/test/unit/apply-call.test.js +5 -0
- package/dist/test/unit/apply-call.test.js.map +1 -1
- package/dist/test/unit/canonicalizer/possessive-anchor.test.js +10 -0
- package/dist/test/unit/canonicalizer/possessive-anchor.test.js.map +1 -1
- package/dist/test/unit/cli/gradle-env-guard.test.d.ts +2 -0
- package/dist/test/unit/cli/gradle-env-guard.test.d.ts.map +1 -0
- package/dist/test/unit/cli/gradle-env-guard.test.js +53 -0
- package/dist/test/unit/cli/gradle-env-guard.test.js.map +1 -0
- package/dist/test/unit/cli/gradle-env.test.d.ts +2 -0
- package/dist/test/unit/cli/gradle-env.test.d.ts.map +1 -0
- package/dist/test/unit/cli/gradle-env.test.js +31 -0
- package/dist/test/unit/cli/gradle-env.test.js.map +1 -0
- package/dist/test/unit/cli/out-dir.test.d.ts +2 -0
- package/dist/test/unit/cli/out-dir.test.d.ts.map +1 -0
- package/dist/test/unit/cli/out-dir.test.js +96 -0
- package/dist/test/unit/cli/out-dir.test.js.map +1 -0
- package/dist/test/unit/eval-regression-poker-straight-high.test.d.ts +2 -0
- package/dist/test/unit/eval-regression-poker-straight-high.test.d.ts.map +1 -0
- package/dist/test/unit/eval-regression-poker-straight-high.test.js +61 -0
- package/dist/test/unit/eval-regression-poker-straight-high.test.js.map +1 -0
- package/dist/test/unit/formatter-corpus-roundtrip.test.d.ts +2 -0
- package/dist/test/unit/formatter-corpus-roundtrip.test.d.ts.map +1 -0
- package/dist/test/unit/formatter-corpus-roundtrip.test.js +190 -0
- package/dist/test/unit/formatter-corpus-roundtrip.test.js.map +1 -0
- package/dist/test/unit/formatter-roundtrip.test.d.ts +2 -0
- package/dist/test/unit/formatter-roundtrip.test.d.ts.map +1 -0
- package/dist/test/unit/formatter-roundtrip.test.js +125 -0
- package/dist/test/unit/formatter-roundtrip.test.js.map +1 -0
- package/dist/test/unit/governance/controls-registry-parity.test.d.ts +2 -0
- package/dist/test/unit/governance/controls-registry-parity.test.d.ts.map +1 -0
- package/dist/test/unit/governance/controls-registry-parity.test.js +28 -0
- package/dist/test/unit/governance/controls-registry-parity.test.js.map +1 -0
- package/dist/test/unit/governance/controls-registry-profiles.test.d.ts +2 -0
- package/dist/test/unit/governance/controls-registry-profiles.test.d.ts.map +1 -0
- package/dist/test/unit/governance/controls-registry-profiles.test.js +106 -0
- package/dist/test/unit/governance/controls-registry-profiles.test.js.map +1 -0
- package/dist/test/unit/governance/governance-check.test.d.ts +2 -0
- package/dist/test/unit/governance/governance-check.test.d.ts.map +1 -0
- package/dist/test/unit/governance/governance-check.test.js +169 -0
- package/dist/test/unit/governance/governance-check.test.js.map +1 -0
- package/dist/test/unit/governance/profile-check.test.d.ts +2 -0
- package/dist/test/unit/governance/profile-check.test.d.ts.map +1 -0
- package/dist/test/unit/governance/profile-check.test.js +139 -0
- package/dist/test/unit/governance/profile-check.test.js.map +1 -0
- package/dist/test/unit/governance/verdict-typecheck.test.d.ts +2 -0
- package/dist/test/unit/governance/verdict-typecheck.test.d.ts.map +1 -0
- package/dist/test/unit/governance/verdict-typecheck.test.js +80 -0
- package/dist/test/unit/governance/verdict-typecheck.test.js.map +1 -0
- package/dist/test/unit/interpreter/verdict-builtins.test.d.ts +2 -0
- package/dist/test/unit/interpreter/verdict-builtins.test.d.ts.map +1 -0
- package/dist/test/unit/interpreter/verdict-builtins.test.js +72 -0
- package/dist/test/unit/interpreter/verdict-builtins.test.js.map +1 -0
- package/dist/test/unit/list-numeric-fail-loud.test.d.ts +2 -0
- package/dist/test/unit/list-numeric-fail-loud.test.d.ts.map +1 -0
- package/dist/test/unit/list-numeric-fail-loud.test.js +83 -0
- package/dist/test/unit/list-numeric-fail-loud.test.js.map +1 -0
- package/dist/test/unit/lossless-mirror.test.d.ts +2 -0
- package/dist/test/unit/lossless-mirror.test.d.ts.map +1 -0
- package/dist/test/unit/lossless-mirror.test.js +41 -0
- package/dist/test/unit/lossless-mirror.test.js.map +1 -0
- package/dist/test/unit/lossless-reflow.test.d.ts +2 -0
- package/dist/test/unit/lossless-reflow.test.d.ts.map +1 -0
- package/dist/test/unit/lossless-reflow.test.js +84 -0
- package/dist/test/unit/lossless-reflow.test.js.map +1 -0
- package/dist/test/unit/lowering/lowering.test.js +35 -35
- package/dist/test/unit/lowering/lowering.test.js.map +1 -1
- package/dist/test/unit/lsp/control-completion.test.d.ts +2 -0
- package/dist/test/unit/lsp/control-completion.test.d.ts.map +1 -0
- package/dist/test/unit/lsp/control-completion.test.js +46 -0
- package/dist/test/unit/lsp/control-completion.test.js.map +1 -0
- package/dist/test/unit/lsp/debounce-map.test.d.ts +2 -0
- package/dist/test/unit/lsp/debounce-map.test.d.ts.map +1 -0
- package/dist/test/unit/lsp/debounce-map.test.js +47 -0
- package/dist/test/unit/lsp/debounce-map.test.js.map +1 -0
- package/dist/test/unit/lsp/file-watcher-restart.test.d.ts +2 -0
- package/dist/test/unit/lsp/file-watcher-restart.test.d.ts.map +1 -0
- package/dist/test/unit/lsp/file-watcher-restart.test.js +40 -0
- package/dist/test/unit/lsp/file-watcher-restart.test.js.map +1 -0
- package/dist/test/unit/manifest-parser.test.js +8 -0
- package/dist/test/unit/manifest-parser.test.js.map +1 -1
- package/dist/test/unit/manifest-schema.test.d.ts +7 -5
- package/dist/test/unit/manifest-schema.test.d.ts.map +1 -1
- package/dist/test/unit/manifest-schema.test.js +48 -10
- package/dist/test/unit/manifest-schema.test.js.map +1 -1
- package/dist/test/unit/mapping/redos-budget.test.js +60 -23
- package/dist/test/unit/mapping/redos-budget.test.js.map +1 -1
- package/dist/test/unit/parser/governance-sugar.test.d.ts +2 -0
- package/dist/test/unit/parser/governance-sugar.test.d.ts.map +1 -0
- package/dist/test/unit/parser/governance-sugar.test.js +258 -0
- package/dist/test/unit/parser/governance-sugar.test.js.map +1 -0
- package/dist/test/unit/parser/module-header.test.d.ts +2 -0
- package/dist/test/unit/parser/module-header.test.d.ts.map +1 -0
- package/dist/test/unit/parser/module-header.test.js +25 -0
- package/dist/test/unit/parser/module-header.test.js.map +1 -0
- package/dist/test/unit/parser/positional-annotation-args.test.d.ts +2 -0
- package/dist/test/unit/parser/positional-annotation-args.test.d.ts.map +1 -0
- package/dist/test/unit/parser/positional-annotation-args.test.js +26 -0
- package/dist/test/unit/parser/positional-annotation-args.test.js.map +1 -0
- package/dist/test/unit/parser/prefix-operator-call.test.d.ts +2 -0
- package/dist/test/unit/parser/prefix-operator-call.test.d.ts.map +1 -0
- package/dist/test/unit/parser/prefix-operator-call.test.js +185 -0
- package/dist/test/unit/parser/prefix-operator-call.test.js.map +1 -0
- package/dist/test/unit/scripts/corpus-loader.test.d.ts +2 -0
- package/dist/test/unit/scripts/corpus-loader.test.d.ts.map +1 -0
- package/dist/test/unit/scripts/corpus-loader.test.js +85 -0
- package/dist/test/unit/scripts/corpus-loader.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
// List.sum/min/max/sort/sortBy/minBy/maxBy 对非数值元素必须**响亮失败**,
|
|
6
|
+
// 与 truffle `Builtins.toDouble`(`Double.parseDouble` 抛 NumberFormatException)对齐。
|
|
7
|
+
//
|
|
8
|
+
// ★修复前(issue #193):这七个 builtin 直接 `Number(x)`,`Number("2o")` 得 NaN 后
|
|
9
|
+
// sum 静默产出 NaN、max/min 因 `NaN > x` 恒假静默返回首元素、sort 顺序未定义——
|
|
10
|
+
// 规则跑通了、结果是错的,且与 Java 侧一个响亮失败一个静默错答案。
|
|
11
|
+
function run(expr, ret = 'Int', rules = '') {
|
|
12
|
+
const c = compile(`Module probe.\n${rules}Rule r given a as Int, produce ${ret}:\n Return ${expr}.\n`);
|
|
13
|
+
if (!c.core)
|
|
14
|
+
return { ok: false, value: undefined, error: 'compile failed' };
|
|
15
|
+
const ev = evaluate(c.core, 'r', { a: 1 });
|
|
16
|
+
return { ok: ev.success, value: ev.value, error: String(ev.error ?? '') };
|
|
17
|
+
}
|
|
18
|
+
const ID_RULE = 'Rule id given x, produce:\n Return x.\n';
|
|
19
|
+
describe('List 数值 builtin 对非数值元素响亮失败(与 truffle toDouble 对齐)', () => {
|
|
20
|
+
const cases = [
|
|
21
|
+
['List.sum', 'List.sum(["10", "2o"])', 'Int'],
|
|
22
|
+
['List.min', 'List.min(["x", "y"])', 'Text'],
|
|
23
|
+
['List.max', 'List.max(["x", "y"])', 'Text'],
|
|
24
|
+
['List.sort', 'List.get(List.sort(["1", "b"]), 0)', 'Text'],
|
|
25
|
+
['List.sum 空串', 'List.sum([""])', 'Int'],
|
|
26
|
+
['List.sum 字符串 NaN', 'List.sum(["NaN"])', 'Int'],
|
|
27
|
+
['List.sum 字符串 Infinity', 'List.sum(["Infinity"])', 'Int'],
|
|
28
|
+
['List.sum 十六进制', 'List.sum(["0x10"])', 'Int'],
|
|
29
|
+
['List.sum 布尔', 'List.sum([true])', 'Int'],
|
|
30
|
+
];
|
|
31
|
+
for (const [name, expr, ret] of cases) {
|
|
32
|
+
it(`${name} 非数值元素必须报错,而不是静默给答案`, () => {
|
|
33
|
+
const r = run(expr, ret);
|
|
34
|
+
assert.equal(r.ok, false, `★${name} 静默返回了 ${JSON.stringify(r.value)}——静默错答案比报错危险`);
|
|
35
|
+
assert.match(r.error, /expected Number/i);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const keyed = [
|
|
39
|
+
['List.sortBy', 'List.get(List.sortBy(["1", "b"], id), 0)', 'Text'],
|
|
40
|
+
['List.minBy', 'List.minBy(["x", "y"], id)', 'Text'],
|
|
41
|
+
['List.maxBy', 'List.maxBy(["x", "y"], id)', 'Text'],
|
|
42
|
+
];
|
|
43
|
+
for (const [name, expr, ret] of keyed) {
|
|
44
|
+
it(`${name} 键函数返回非数值必须报错`, () => {
|
|
45
|
+
const r = run(expr, ret, ID_RULE);
|
|
46
|
+
assert.equal(r.ok, false, `★${name} 静默返回了 ${JSON.stringify(r.value)}`);
|
|
47
|
+
assert.match(r.error, /expected Number/i);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// 反向保险:合法数值(含可解析的字符串、前后空白)不得被误伤
|
|
51
|
+
it('数值列表照常工作', () => {
|
|
52
|
+
assert.equal(run('List.sum([3, 8, 1, 9])').value, 21);
|
|
53
|
+
assert.equal(run('List.max([3, 8, 1, 9])').value, 9);
|
|
54
|
+
assert.equal(run('List.min([3, 8, 1, 9])').value, 1);
|
|
55
|
+
assert.equal(run('List.get(List.sort([3, 8, 1]), 0)').value, 1);
|
|
56
|
+
assert.equal(run('List.maxBy([3, 8, 1], id)', 'Int', ID_RULE).value, 8);
|
|
57
|
+
});
|
|
58
|
+
it('可解析的数值字符串(含前后空白、小数、科学计数)照常换算', () => {
|
|
59
|
+
assert.equal(run('List.sum(["10", " 2 ", "1.5", "1e1"])', 'Decimal').value, 23.5);
|
|
60
|
+
assert.equal(run('List.max(["10", "9"])', 'Text').value, '10');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
// ★issue #204:List.combinations 的 k 曾是裸 Number(),Number.isInteger 只拦得住 NaN:
|
|
64
|
+
// ""→0、true→1、"0x2"→2 静默被接受,而 truffle 侧 toInt(Integer.parseInt)一律抛错。
|
|
65
|
+
describe('List.combinations 的 k 非法时响亮失败(与 truffle toInt 对齐)', () => {
|
|
66
|
+
for (const k of ['""', 'true', '"0x2"', '"2o"', '"2.0"']) {
|
|
67
|
+
it(`k=${k} 必须报错,而不是静默给答案`, () => {
|
|
68
|
+
const r = run(`List.length(List.combinations([1, 2, 3], ${k}))`);
|
|
69
|
+
assert.equal(r.ok, false, `★静默返回了 ${JSON.stringify(r.value)}`);
|
|
70
|
+
assert.match(r.error, /List\.combinations: expected Int/);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
it('k 为负数仍报错', () => {
|
|
74
|
+
const r = run('List.length(List.combinations([1, 2, 3], 0 minus 1))');
|
|
75
|
+
assert.equal(r.ok, false);
|
|
76
|
+
assert.match(r.error, /非负整数/);
|
|
77
|
+
});
|
|
78
|
+
it('合法 k(数字、整数字符串)照常工作', () => {
|
|
79
|
+
assert.equal(run('List.length(List.combinations([1, 2, 3], 2))').value, 3);
|
|
80
|
+
assert.equal(run('List.length(List.combinations([1, 2, 3], "2"))').value, 3);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
//# sourceMappingURL=list-numeric-fail-loud.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-numeric-fail-loud.test.js","sourceRoot":"","sources":["../../../test/unit/list-numeric-fail-loud.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lossless-mirror.test.d.ts","sourceRoot":"","sources":["../../../test/unit/lossless-mirror.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lossless golden 的真源是本仓 test/lossless/golden/;兄弟仓 aster-lang-test 的
|
|
3
|
+
* corpus/tier3-fixtures/lossless/ 是它的镜像(落位规则同 aster-lang-test scripts/classify-existing.mjs 的 tier3:
|
|
4
|
+
* 原样复制 .aster,并配同名 meta)。golden 改动后须同步镜像,否则本测试失败。
|
|
5
|
+
* CI 的 test job 会 checkout aster-lang-test,因此 CI 中缺失即失败;仅本地未并列 checkout 时跳过。
|
|
6
|
+
*/
|
|
7
|
+
import { test } from 'node:test';
|
|
8
|
+
import assert from 'node:assert/strict';
|
|
9
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { dirname, join } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
// 编译后从 dist/test/unit 运行:上溯 3 级到仓库根
|
|
13
|
+
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
|
|
14
|
+
const goldenDir = join(repoRoot, 'test', 'lossless', 'golden');
|
|
15
|
+
const MIRROR = ['corpus', 'tier3-fixtures', 'lossless'];
|
|
16
|
+
function mirrorDir() {
|
|
17
|
+
return [join(repoRoot, '..', 'aster-lang-test', ...MIRROR), join(repoRoot, 'aster-lang-test', ...MIRROR)]
|
|
18
|
+
.find((c) => existsSync(c));
|
|
19
|
+
}
|
|
20
|
+
const asterFiles = (dir) => readdirSync(dir).filter((n) => n.endsWith('.aster')).sort();
|
|
21
|
+
// 与 classify-existing.mjs 写 tier3 meta 的方式逐字节相同
|
|
22
|
+
function expectedMeta(name) {
|
|
23
|
+
const meta = { tier: 3, bucket: 'lossless', engines: ['ts'], lexicon: 'en-US', source: `aster-lang-ts/test/lossless/golden/${name}` };
|
|
24
|
+
return JSON.stringify(meta, null, 2) + '\n';
|
|
25
|
+
}
|
|
26
|
+
test('lossless golden 与 aster-lang-test 镜像逐字节一致', (t) => {
|
|
27
|
+
const mirror = mirrorDir();
|
|
28
|
+
if (mirror === undefined) {
|
|
29
|
+
assert.ok(!process.env.CI, 'CI 中须 checkout aster-lang-test(见 .github/workflows/ci.yml test job)');
|
|
30
|
+
return t.skip('aster-lang-test 未并列 checkout');
|
|
31
|
+
}
|
|
32
|
+
const names = asterFiles(goldenDir);
|
|
33
|
+
assert.deepEqual(asterFiles(mirror), names, '镜像的 .aster 文件集合须与 golden 相同');
|
|
34
|
+
for (const name of names) {
|
|
35
|
+
assert.ok(readFileSync(join(mirror, name)).equals(readFileSync(join(goldenDir, name))), `${name} 与 golden 不一致`);
|
|
36
|
+
const metaPath = join(mirror, name.replace(/\.aster$/, '.meta.json'));
|
|
37
|
+
assert.ok(existsSync(metaPath), `${name} 缺同名 meta`);
|
|
38
|
+
assert.equal(readFileSync(metaPath, 'utf8'), expectedMeta(name), `${name} 的 meta 不符合落位规则`);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=lossless-mirror.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lossless-mirror.test.js","sourceRoot":"","sources":["../../../test/unit/lossless-mirror.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lossless-reflow.test.d.ts","sourceRoot":"","sources":["../../../test/unit/lossless-reflow.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lossless 模式的 reflow:只整理记号之间的空白,不得改动字符串字面量、注释正文与语句结构。
|
|
3
|
+
* LSP 默认格式化即 lossless + reflow,任何改动都会直接改写用户源码。
|
|
4
|
+
*/
|
|
5
|
+
import { describe, test } from 'node:test';
|
|
6
|
+
import assert from 'node:assert/strict';
|
|
7
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
10
|
+
import { buildCstLossless } from '../../src/cst/cst_builder.js';
|
|
11
|
+
import { printCNLFromCst, printRangeFromCst } from '../../src/cst/cst_printer.js';
|
|
12
|
+
import { canonicalize } from '../../src/frontend/canonicalizer.js';
|
|
13
|
+
import { lex } from '../../src/frontend/lexer.js';
|
|
14
|
+
import { parse } from '../../src/parser.js';
|
|
15
|
+
import { lowerModule } from '../../src/lower_to_core.js';
|
|
16
|
+
// 编译后从 dist/test/unit 运行:上溯 3 级到仓库根
|
|
17
|
+
const goldenDir = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'test', 'lossless', 'golden');
|
|
18
|
+
const reflow = (src) => printCNLFromCst(buildCstLossless(src), { reflow: true });
|
|
19
|
+
function coreJson(src) {
|
|
20
|
+
const result = parse(lex(canonicalize(src)));
|
|
21
|
+
const errors = result.diagnostics.filter((d) => d.severity === 'error');
|
|
22
|
+
if (errors.length > 0)
|
|
23
|
+
throw new Error(errors.map((d) => d.message).join('; '));
|
|
24
|
+
return JSON.stringify(lowerModule(result.ast), (k, v) => (k === 'origin' ? undefined : v));
|
|
25
|
+
}
|
|
26
|
+
describe('lossless reflow 只动记号之间的空白', () => {
|
|
27
|
+
test('标点前同行空白、行尾空白、`. :` 与多余结尾换行被整理', () => {
|
|
28
|
+
const src = 'Module m . \n\nRule r given a as Int , produce Int . : \n Return a .\n\n\n';
|
|
29
|
+
assert.equal(reflow(src), 'Module m.\n\nRule r given a as Int, produce Int:\n Return a.\n');
|
|
30
|
+
});
|
|
31
|
+
test('字符串字面量原样保留', () => {
|
|
32
|
+
const src = 'Module m.\n\nRule r, produce Text:\n Return "Hi , there . : ! ?" .\n';
|
|
33
|
+
assert.equal(reflow(src), 'Module m.\n\nRule r, produce Text:\n Return "Hi , there . : ! ?".\n');
|
|
34
|
+
});
|
|
35
|
+
test('注释正文原样保留(只去行尾空白)', () => {
|
|
36
|
+
const src = '// 注释 , 带空格 . \nModule m. // 行尾 : 注释\n';
|
|
37
|
+
assert.equal(reflow(src), '// 注释 , 带空格 .\nModule m. // 行尾 : 注释\n');
|
|
38
|
+
});
|
|
39
|
+
test('独占一行的句点(workflow 结束)不被拉到上一行', () => {
|
|
40
|
+
const src = ['Module m.', '', 'Rule run, produce. It performs io:', ' workflow:', ' step only:',
|
|
41
|
+
' Return ok of 1.', '', ' .', ''].join('\n');
|
|
42
|
+
assert.equal(reflow(src), src);
|
|
43
|
+
});
|
|
44
|
+
test('文件中间只含空白的行被清空', () => {
|
|
45
|
+
const src = 'Module m.\n \nRule r, produce Int:\n Let x be 1.\n \t \n Return x.\n';
|
|
46
|
+
assert.equal(reflow(src), 'Module m.\n\nRule r, produce Int:\n Let x be 1.\n\n Return x.\n');
|
|
47
|
+
});
|
|
48
|
+
test('文件末尾的空白行与行尾空白去掉,至多留一个换行', () => {
|
|
49
|
+
const body = 'Module m.\n\nRule r, produce Int:\n Return 1.';
|
|
50
|
+
assert.equal(reflow(`${body}\n \n \n`), `${body}\n`);
|
|
51
|
+
assert.equal(reflow(`${body}\n\n `), `${body}\n`);
|
|
52
|
+
assert.equal(reflow(`${body} `), body);
|
|
53
|
+
});
|
|
54
|
+
test('CRLF 文件去掉换行前的空白并保持 CRLF', () => {
|
|
55
|
+
const src = 'Module m. \r\n \r\nRule r, produce Int: \r\n // 注释 , 不动 \r\n Return 1. \r\n \r\n\r\n';
|
|
56
|
+
const want = 'Module m.\r\n\r\nRule r, produce Int:\r\n // 注释 , 不动\r\n Return 1.\r\n';
|
|
57
|
+
assert.equal(reflow(src), want);
|
|
58
|
+
});
|
|
59
|
+
test('reflow 幂等', () => {
|
|
60
|
+
const src = 'Module m . \r\n \r\nRule r given a as Int , produce Int . : \r\n Return a . \r\n \r\n ';
|
|
61
|
+
assert.equal(reflow(reflow(src)), reflow(src));
|
|
62
|
+
});
|
|
63
|
+
test('区间格式化同样不改字符串', () => {
|
|
64
|
+
const src = 'Module m.\n\nRule r, produce Text:\n Return "a , b" .\n';
|
|
65
|
+
const cst = buildCstLossless(src);
|
|
66
|
+
const start = src.indexOf('Return');
|
|
67
|
+
assert.equal(printRangeFromCst(cst, start, src.length, { reflow: true }), 'Return "a , b".\n');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
describe('lossless golden', () => {
|
|
71
|
+
const inputs = readdirSync(goldenDir).filter((f) => f.endsWith('.in.aster')).sort();
|
|
72
|
+
for (const file of inputs) {
|
|
73
|
+
test(file, () => {
|
|
74
|
+
const src = readFileSync(join(goldenDir, file), 'utf8');
|
|
75
|
+
const expected = readFileSync(join(goldenDir, file.replace(/\.in\.aster$/, '.out.aster')), 'utf8');
|
|
76
|
+
assert.equal(printCNLFromCst(buildCstLossless(src)), src, '无 reflow 时须逐字节还原');
|
|
77
|
+
// 与 scripts/test-lossless-golden 同一比较口径:只忽略期望文件末尾的单个换行,其余空白逐字比较
|
|
78
|
+
const norm = (t) => t.replace(/\n$/, '');
|
|
79
|
+
assert.equal(norm(reflow(src)), norm(expected));
|
|
80
|
+
assert.equal(coreJson(expected), coreJson(src), 'reflow 前后 Core IR 须相同');
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=lossless-reflow.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lossless-reflow.test.js","sourceRoot":"","sources":["../../../test/unit/lossless-reflow.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -123,7 +123,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
123
123
|
retType: Node.TypeName('Fn1'),
|
|
124
124
|
statements: [Node.Return(lambdaExpr)],
|
|
125
125
|
});
|
|
126
|
-
const moduleAst = Node.Module('test.lowering.lambda_capture', [funcDecl]);
|
|
126
|
+
const moduleAst = Node.Module('test.lowering.lambda_capture', null, [funcDecl]);
|
|
127
127
|
const core = lowerAst(moduleAst);
|
|
128
128
|
const func = core.decls.find(d => d.kind === 'Func');
|
|
129
129
|
const lambda = func.body.statements[0].expr;
|
|
@@ -137,7 +137,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
137
137
|
retType: Node.TypeName('Text'),
|
|
138
138
|
statements: [Node.Return(awaitExpr)],
|
|
139
139
|
});
|
|
140
|
-
const moduleAst = Node.Module('test.lowering.await_expr', [funcDecl]);
|
|
140
|
+
const moduleAst = Node.Module('test.lowering.await_expr', null, [funcDecl]);
|
|
141
141
|
const core = lowerAst(moduleAst);
|
|
142
142
|
const func = core.decls[0];
|
|
143
143
|
const retExpr = func.body.statements[0].expr;
|
|
@@ -151,7 +151,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
151
151
|
retType: Node.TypeName('Int'),
|
|
152
152
|
statements: [Node.Block([Node.Let('inner', Node.Int(2))]), inner],
|
|
153
153
|
});
|
|
154
|
-
const moduleAst = Node.Module('test.lowering.scope_block', [funcDecl]);
|
|
154
|
+
const moduleAst = Node.Module('test.lowering.scope_block', null, [funcDecl]);
|
|
155
155
|
const core = lowerAst(moduleAst);
|
|
156
156
|
const func = core.decls[0];
|
|
157
157
|
assert.equal(func.body.statements[0].kind, 'Scope');
|
|
@@ -171,7 +171,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
171
171
|
retType: Node.TypeName('List'),
|
|
172
172
|
statements: [Node.Return(resultCall), Node.Return(listCall)],
|
|
173
173
|
});
|
|
174
|
-
const moduleAst = Node.Module('test.lowering.map_calls', [funcDecl]);
|
|
174
|
+
const moduleAst = Node.Module('test.lowering.map_calls', null, [funcDecl]);
|
|
175
175
|
const core = lowerAst(moduleAst);
|
|
176
176
|
const body = core.decls[0].body.statements;
|
|
177
177
|
const resultExpr = body[0].expr;
|
|
@@ -184,7 +184,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
184
184
|
it('effectCaps 显式声明应完整传递', () => {
|
|
185
185
|
const caps = [CapabilityKind.SECRETS];
|
|
186
186
|
const funcDecl = Node.Func('readSecret', [], [], Node.TypeName('Text'), [], caps, true, Node.Block([Node.Return(Node.String('ok'))]));
|
|
187
|
-
const moduleAst = Node.Module('test.lowering.effectcaps.explicit', [funcDecl]);
|
|
187
|
+
const moduleAst = Node.Module('test.lowering.effectcaps.explicit', null, [funcDecl]);
|
|
188
188
|
const core = lowerAst(moduleAst);
|
|
189
189
|
const func = core.decls[0];
|
|
190
190
|
assert.deepEqual(func.effectCaps, caps);
|
|
@@ -194,7 +194,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
194
194
|
it('effectCaps 推断结果应保持并标记为隐式', () => {
|
|
195
195
|
const caps = [CapabilityKind.FILES, CapabilityKind.TIME];
|
|
196
196
|
const funcDecl = Node.Func('touchFile', [], [], Node.TypeName('Bool'), [], caps, false, Node.Block([Node.Return(Node.Bool(true))]));
|
|
197
|
-
const moduleAst = Node.Module('test.lowering.effectcaps.implicit', [funcDecl]);
|
|
197
|
+
const moduleAst = Node.Module('test.lowering.effectcaps.implicit', null, [funcDecl]);
|
|
198
198
|
const core = lowerAst(moduleAst);
|
|
199
199
|
const func = core.decls[0];
|
|
200
200
|
assert.deepEqual(func.effectCaps, caps);
|
|
@@ -203,7 +203,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
203
203
|
});
|
|
204
204
|
it('未知 effect 应抛出诊断错误', () => {
|
|
205
205
|
const funcDecl = Node.Func('useUnknownEffect', [], [], Node.TypeName('Int'), ['teleport'], [], false, Node.Block([Node.Return(Node.Int(1))]));
|
|
206
|
-
const moduleAst = Node.Module('test.lowering.effectcaps.unknown', [funcDecl]);
|
|
206
|
+
const moduleAst = Node.Module('test.lowering.effectcaps.unknown', null, [funcDecl]);
|
|
207
207
|
assert.throws(() => lowerAst(moduleAst), /Unknown effect/);
|
|
208
208
|
});
|
|
209
209
|
it('Set 语句应降级为 Core.Set 并保留表达式', () => {
|
|
@@ -217,7 +217,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
217
217
|
Node.Return(Node.Name('counter')),
|
|
218
218
|
],
|
|
219
219
|
});
|
|
220
|
-
const moduleAst = Node.Module('test.lowering.set.basic', [funcDecl]);
|
|
220
|
+
const moduleAst = Node.Module('test.lowering.set.basic', null, [funcDecl]);
|
|
221
221
|
const core = lowerAst(moduleAst);
|
|
222
222
|
const func = core.decls[0];
|
|
223
223
|
const body = func.body.statements;
|
|
@@ -237,7 +237,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
237
237
|
Node.Return(Node.Name('a')),
|
|
238
238
|
],
|
|
239
239
|
});
|
|
240
|
-
const moduleAst = Node.Module('test.lowering.set.sequence', [funcDecl]);
|
|
240
|
+
const moduleAst = Node.Module('test.lowering.set.sequence', null, [funcDecl]);
|
|
241
241
|
const core = lowerAst(moduleAst);
|
|
242
242
|
const func = core.decls[0];
|
|
243
243
|
const body = func.body.statements;
|
|
@@ -256,7 +256,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
256
256
|
retType: Node.TypeName('Int'),
|
|
257
257
|
statements: [matchStmt],
|
|
258
258
|
});
|
|
259
|
-
const moduleAst = Node.Module('test.lowering.match.null', [funcDecl]);
|
|
259
|
+
const moduleAst = Node.Module('test.lowering.match.null', null, [funcDecl]);
|
|
260
260
|
const core = lowerAst(moduleAst);
|
|
261
261
|
const matchCore = (core.decls[0].body.statements[0]);
|
|
262
262
|
assert.equal(matchCore.cases[0]?.pattern.kind, 'PatNull');
|
|
@@ -271,7 +271,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
271
271
|
retType: Node.TypeName('Int'),
|
|
272
272
|
statements: [matchStmt],
|
|
273
273
|
});
|
|
274
|
-
const moduleAst = Node.Module('test.lowering.match.ctor', [funcDecl]);
|
|
274
|
+
const moduleAst = Node.Module('test.lowering.match.ctor', null, [funcDecl]);
|
|
275
275
|
const core = lowerAst(moduleAst);
|
|
276
276
|
const matchCore = (core.decls[0].body.statements[0]);
|
|
277
277
|
const pat = matchCore.cases[0].pattern;
|
|
@@ -288,7 +288,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
288
288
|
retType: Node.TypeName('Text'),
|
|
289
289
|
statements: [matchStmt],
|
|
290
290
|
});
|
|
291
|
-
const moduleAst = Node.Module('test.lowering.match.int', [funcDecl]);
|
|
291
|
+
const moduleAst = Node.Module('test.lowering.match.int', null, [funcDecl]);
|
|
292
292
|
const core = lowerAst(moduleAst);
|
|
293
293
|
const matchCore = (core.decls[0].body.statements[0]);
|
|
294
294
|
const pat = matchCore.cases[0].pattern;
|
|
@@ -301,7 +301,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
301
301
|
retType: Node.TypeName('Result'),
|
|
302
302
|
statements: [Node.Return(Node.Ok(Node.Int(1)))],
|
|
303
303
|
});
|
|
304
|
-
const moduleAst = Node.Module('test.lowering.expr.ok', [funcDecl]);
|
|
304
|
+
const moduleAst = Node.Module('test.lowering.expr.ok', null, [funcDecl]);
|
|
305
305
|
const core = lowerAst(moduleAst);
|
|
306
306
|
const retStmt = core.decls[0].body.statements[0];
|
|
307
307
|
const expr = retStmt.expr;
|
|
@@ -314,7 +314,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
314
314
|
retType: Node.TypeName('Result'),
|
|
315
315
|
statements: [Node.Return(Node.Err(Node.String('fail')))],
|
|
316
316
|
});
|
|
317
|
-
const moduleAst = Node.Module('test.lowering.expr.err', [funcDecl]);
|
|
317
|
+
const moduleAst = Node.Module('test.lowering.expr.err', null, [funcDecl]);
|
|
318
318
|
const core = lowerAst(moduleAst);
|
|
319
319
|
const retStmt = core.decls[0].body.statements[0];
|
|
320
320
|
const expr = retStmt.expr;
|
|
@@ -327,7 +327,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
327
327
|
retType: Node.Maybe(Node.TypeName('Int')),
|
|
328
328
|
statements: [Node.Return(Node.Some(Node.Int(7))), Node.Return(Node.None())],
|
|
329
329
|
});
|
|
330
|
-
const moduleAst = Node.Module('test.lowering.expr.option', [funcDecl]);
|
|
330
|
+
const moduleAst = Node.Module('test.lowering.expr.option', null, [funcDecl]);
|
|
331
331
|
const core = lowerAst(moduleAst);
|
|
332
332
|
const firstReturn = core.decls[0].body.statements[0];
|
|
333
333
|
const secondReturn = core.decls[0].body.statements[1];
|
|
@@ -344,7 +344,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
344
344
|
retType: Node.TypeName('Int'),
|
|
345
345
|
statements: [startStmt, Node.Return(Node.Int(0))],
|
|
346
346
|
});
|
|
347
|
-
const moduleAst = Node.Module('test.lowering.start', [funcDecl]);
|
|
347
|
+
const moduleAst = Node.Module('test.lowering.start', null, [funcDecl]);
|
|
348
348
|
const core = lowerAst(moduleAst);
|
|
349
349
|
const stmt = core.decls[0].body.statements[0];
|
|
350
350
|
assert.equal(stmt.kind, 'Start');
|
|
@@ -358,7 +358,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
358
358
|
retType: Node.TypeName('Int'),
|
|
359
359
|
statements: [waitStmt, Node.Return(Node.Int(1))],
|
|
360
360
|
});
|
|
361
|
-
const moduleAst = Node.Module('test.lowering.wait', [funcDecl]);
|
|
361
|
+
const moduleAst = Node.Module('test.lowering.wait', null, [funcDecl]);
|
|
362
362
|
const core = lowerAst(moduleAst);
|
|
363
363
|
const stmt = core.decls[0].body.statements[0];
|
|
364
364
|
assert.equal(stmt.kind, 'Wait');
|
|
@@ -371,7 +371,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
371
371
|
retType: Node.TypeName('Null'),
|
|
372
372
|
statements: [callStmt, Node.Return(Node.Null())],
|
|
373
373
|
});
|
|
374
|
-
const moduleAst = Node.Module('test.lowering.callStmt', [funcDecl]);
|
|
374
|
+
const moduleAst = Node.Module('test.lowering.callStmt', null, [funcDecl]);
|
|
375
375
|
const core = lowerAst(moduleAst);
|
|
376
376
|
const stmt = core.decls[0].body.statements[0];
|
|
377
377
|
assert.equal(stmt.kind, 'Let');
|
|
@@ -387,7 +387,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
387
387
|
retType: Node.TypeName('Int'),
|
|
388
388
|
statements: [ifStmt, Node.Return(Node.Int(0))],
|
|
389
389
|
});
|
|
390
|
-
const moduleAst = Node.Module('test.lowering.if.then', [funcDecl]);
|
|
390
|
+
const moduleAst = Node.Module('test.lowering.if.then', null, [funcDecl]);
|
|
391
391
|
const core = lowerAst(moduleAst);
|
|
392
392
|
const stmt = core.decls[0].body.statements[0];
|
|
393
393
|
assert.equal(stmt.kind, 'If');
|
|
@@ -401,7 +401,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
401
401
|
retType: Node.TypeName('Int'),
|
|
402
402
|
statements: [ifStmt, Node.Return(Node.Int(0))],
|
|
403
403
|
});
|
|
404
|
-
const moduleAst = Node.Module('test.lowering.if.else', [funcDecl]);
|
|
404
|
+
const moduleAst = Node.Module('test.lowering.if.else', null, [funcDecl]);
|
|
405
405
|
const core = lowerAst(moduleAst);
|
|
406
406
|
const stmt = core.decls[0].body.statements[0];
|
|
407
407
|
assert.equal(stmt.elseBlock.statements[0]?.kind, 'Return');
|
|
@@ -416,7 +416,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
416
416
|
retType: Node.TypeName('Int'),
|
|
417
417
|
statements: [scopeBlock],
|
|
418
418
|
});
|
|
419
|
-
const moduleAst = Node.Module('test.lowering.scope.single', [funcDecl]);
|
|
419
|
+
const moduleAst = Node.Module('test.lowering.scope.single', null, [funcDecl]);
|
|
420
420
|
const core = lowerAst(moduleAst);
|
|
421
421
|
const stmt = core.decls[0].body.statements[0];
|
|
422
422
|
assert.equal(stmt.kind, 'Scope');
|
|
@@ -434,7 +434,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
434
434
|
retType: Node.TypeName('Int'),
|
|
435
435
|
statements: [outer],
|
|
436
436
|
});
|
|
437
|
-
const moduleAst = Node.Module('test.lowering.scope.nested', [funcDecl]);
|
|
437
|
+
const moduleAst = Node.Module('test.lowering.scope.nested', null, [funcDecl]);
|
|
438
438
|
const core = lowerAst(moduleAst);
|
|
439
439
|
const scope = core.decls[0].body.statements[0];
|
|
440
440
|
assert.equal(scope.kind, 'Scope');
|
|
@@ -450,7 +450,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
450
450
|
retType: Node.TypeName('Bool'),
|
|
451
451
|
statements: [Node.Return(Node.Bool(true))],
|
|
452
452
|
});
|
|
453
|
-
const moduleAst = Node.Module('test.lowering.type.pii', [funcDecl]);
|
|
453
|
+
const moduleAst = Node.Module('test.lowering.type.pii', null, [funcDecl]);
|
|
454
454
|
const core = lowerAst(moduleAst);
|
|
455
455
|
const paramType = (core.decls[0].params[0]).type;
|
|
456
456
|
assert.equal(paramType.kind, 'PiiType');
|
|
@@ -464,7 +464,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
464
464
|
Node.String('ok'),
|
|
465
465
|
])),
|
|
466
466
|
]));
|
|
467
|
-
const moduleAst = Node.Module('test.lowering.func.pii', [funcDecl]);
|
|
467
|
+
const moduleAst = Node.Module('test.lowering.func.pii', null, [funcDecl]);
|
|
468
468
|
const core = lowerAst(moduleAst);
|
|
469
469
|
const func = core.decls[0];
|
|
470
470
|
assert.equal(func.piiLevel, 'L2');
|
|
@@ -472,7 +472,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
472
472
|
});
|
|
473
473
|
it('类型参数引用应降级为 Core.TypeVar', () => {
|
|
474
474
|
const funcDecl = Node.Func('identity', ['T'], [makeParam('value', Node.TypeName('T'))], Node.TypeName('T'), [], [], false, Node.Block([Node.Return(Node.Name('value'))]));
|
|
475
|
-
const moduleAst = Node.Module('test.lowering.type.var', [funcDecl]);
|
|
475
|
+
const moduleAst = Node.Module('test.lowering.type.var', null, [funcDecl]);
|
|
476
476
|
const core = lowerAst(moduleAst);
|
|
477
477
|
const func = core.decls[0];
|
|
478
478
|
assert.equal(func.params[0].type.kind, 'TypeVar');
|
|
@@ -480,7 +480,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
480
480
|
});
|
|
481
481
|
it('TypeApp 应降级并保留参数列表', () => {
|
|
482
482
|
const funcDecl = Node.Func('getFuture', [], [], Node.TypeApp('Future', [Node.TypeName('Text'), Node.TypeName('Int')]), [], [], false, Node.Block([Node.Return(Node.Name('pending'))]));
|
|
483
|
-
const moduleAst = Node.Module('test.lowering.type.app', [funcDecl]);
|
|
483
|
+
const moduleAst = Node.Module('test.lowering.type.app', null, [funcDecl]);
|
|
484
484
|
const core = lowerAst(moduleAst);
|
|
485
485
|
const ret = core.decls[0].ret;
|
|
486
486
|
assert.equal(ret.kind, 'TypeApp');
|
|
@@ -496,7 +496,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
496
496
|
retType: Node.Maybe(Node.TypeName('Text')),
|
|
497
497
|
statements: [Node.Return(Node.None())],
|
|
498
498
|
});
|
|
499
|
-
const moduleAst = Node.Module('test.lowering.type.option', [funcDecl]);
|
|
499
|
+
const moduleAst = Node.Module('test.lowering.type.option', null, [funcDecl]);
|
|
500
500
|
const core = lowerAst(moduleAst);
|
|
501
501
|
const paramType = (core.decls[0].params[0]).type;
|
|
502
502
|
const ret = core.decls[0].ret;
|
|
@@ -511,7 +511,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
511
511
|
retType: Node.Result(Node.TypeName('Text'), Node.TypeName('Error')),
|
|
512
512
|
statements: [Node.Return(Node.Ok(Node.String('ok')))],
|
|
513
513
|
});
|
|
514
|
-
const moduleAst = Node.Module('test.lowering.type.result', [funcDecl]);
|
|
514
|
+
const moduleAst = Node.Module('test.lowering.type.result', null, [funcDecl]);
|
|
515
515
|
const core = lowerAst(moduleAst);
|
|
516
516
|
const ret = core.decls[0].ret;
|
|
517
517
|
assert.equal(ret.kind, 'Result');
|
|
@@ -519,7 +519,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
519
519
|
assert.equal(ret.err.kind, 'TypeName');
|
|
520
520
|
});
|
|
521
521
|
it('Import 声明应直接映射为 Core.Import', () => {
|
|
522
|
-
const moduleAst = Node.Module('test.lowering.import', [
|
|
522
|
+
const moduleAst = Node.Module('test.lowering.import', null, [
|
|
523
523
|
Node.Import('Http.Client', 'HttpClient'),
|
|
524
524
|
]);
|
|
525
525
|
const core = lowerAst(moduleAst);
|
|
@@ -530,7 +530,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
530
530
|
assert.equal(Object.prototype.hasOwnProperty.call(decl, 'version'), false);
|
|
531
531
|
});
|
|
532
532
|
it('Import version 应映射为 Core.Import version', () => {
|
|
533
|
-
const moduleAst = Node.Module('test.lowering.import.version', [
|
|
533
|
+
const moduleAst = Node.Module('test.lowering.import.version', null, [
|
|
534
534
|
Node.Import('risk.Scoring', 'Score', 2),
|
|
535
535
|
]);
|
|
536
536
|
const core = lowerAst(moduleAst);
|
|
@@ -552,7 +552,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
552
552
|
span: freshSpan(),
|
|
553
553
|
};
|
|
554
554
|
const dataDecl = Node.Data('User', [field]);
|
|
555
|
-
const moduleAst = Node.Module('test.lowering.data.constraints', [dataDecl]);
|
|
555
|
+
const moduleAst = Node.Module('test.lowering.data.constraints', null, [dataDecl]);
|
|
556
556
|
const core = lowerAst(moduleAst);
|
|
557
557
|
const data = core.decls[0];
|
|
558
558
|
assert.ok(data.fields[0].constraints, '应该存在 constraints');
|
|
@@ -582,7 +582,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
582
582
|
span: freshSpan(),
|
|
583
583
|
};
|
|
584
584
|
const dataDecl = Node.Data('Profile', [fieldWithConstraints, fieldWithoutConstraints]);
|
|
585
|
-
const moduleAst = Node.Module('test.lowering.data.multi_constraints', [dataDecl]);
|
|
585
|
+
const moduleAst = Node.Module('test.lowering.data.multi_constraints', null, [dataDecl]);
|
|
586
586
|
const core = lowerAst(moduleAst);
|
|
587
587
|
const data = core.decls[0];
|
|
588
588
|
assert.equal(data.fields[0].constraints.length, 2);
|
|
@@ -598,7 +598,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
598
598
|
retType: Node.TypeName('User'),
|
|
599
599
|
statements: [Node.Return(construct)],
|
|
600
600
|
});
|
|
601
|
-
const moduleAst = Node.Module('test.lowering.construct', [funcDecl]);
|
|
601
|
+
const moduleAst = Node.Module('test.lowering.construct', null, [funcDecl]);
|
|
602
602
|
const core = lowerAst(moduleAst);
|
|
603
603
|
const expr = core.decls[0].body.statements[0]
|
|
604
604
|
.expr;
|
|
@@ -613,7 +613,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
613
613
|
retType: Node.TypeName('Long'),
|
|
614
614
|
statements: [Node.Return(Node.Long('1234567890123456789'))],
|
|
615
615
|
});
|
|
616
|
-
const moduleAst = Node.Module('test.lowering.long', [funcDecl]);
|
|
616
|
+
const moduleAst = Node.Module('test.lowering.long', null, [funcDecl]);
|
|
617
617
|
const core = lowerAst(moduleAst);
|
|
618
618
|
const retStmt = core.decls[0].body.statements[0];
|
|
619
619
|
const expr = retStmt.expr;
|
|
@@ -626,7 +626,7 @@ Rule makeIdentity, produce Fn1:
|
|
|
626
626
|
retType: Node.TypeName('Double'),
|
|
627
627
|
statements: [Node.Return(Node.Double(3.14))],
|
|
628
628
|
});
|
|
629
|
-
const moduleAst = Node.Module('test.lowering.double', [funcDecl]);
|
|
629
|
+
const moduleAst = Node.Module('test.lowering.double', null, [funcDecl]);
|
|
630
630
|
const core = lowerAst(moduleAst);
|
|
631
631
|
const retStmt = core.decls[0].body.statements[0];
|
|
632
632
|
const expr = retStmt.expr;
|