@aster-cloud/aster-lang-ts 0.0.28 → 0.0.30
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/peg/headers-parser.js +459 -233
- package/dist/scripts/aster.js +0 -0
- package/dist/scripts/emit-core.js +0 -0
- package/dist/scripts/generate-lexicons.d.ts +13 -0
- package/dist/scripts/generate-lexicons.d.ts.map +1 -0
- package/dist/scripts/generate-lexicons.js +152 -0
- package/dist/scripts/generate-lexicons.js.map +1 -0
- package/dist/scripts/generate-vocabularies.d.ts +13 -0
- package/dist/scripts/generate-vocabularies.d.ts.map +1 -0
- package/dist/scripts/generate-vocabularies.js +205 -0
- package/dist/scripts/generate-vocabularies.js.map +1 -0
- package/dist/scripts/golden.js +4 -4
- package/dist/scripts/golden.js.map +1 -1
- package/dist/scripts/perf-assert.js +2 -2
- package/dist/scripts/perf-assert.js.map +1 -1
- package/dist/scripts/perf-lsp.js +2 -2
- package/dist/scripts/perf-lsp.js.map +1 -1
- package/dist/scripts/scaffold.js +4 -4
- package/dist/scripts/verify-lexicon-sync.d.ts +14 -0
- package/dist/scripts/verify-lexicon-sync.d.ts.map +1 -0
- package/dist/scripts/verify-lexicon-sync.js +248 -0
- package/dist/scripts/verify-lexicon-sync.js.map +1 -0
- package/dist/src/browser.d.ts +2 -0
- package/dist/src/browser.d.ts.map +1 -1
- package/dist/src/browser.js +14 -3
- package/dist/src/browser.js.map +1 -1
- package/dist/src/cli/policy-converter.js +0 -0
- package/dist/src/config/lexicons/de-DE.d.ts +0 -9
- package/dist/src/config/lexicons/de-DE.d.ts.map +1 -1
- package/dist/src/config/lexicons/de-DE.js +27 -53
- package/dist/src/config/lexicons/de-DE.js.map +1 -1
- package/dist/src/config/lexicons/en-US.d.ts +0 -12
- package/dist/src/config/lexicons/en-US.d.ts.map +1 -1
- package/dist/src/config/lexicons/en-US.js +27 -50
- package/dist/src/config/lexicons/en-US.js.map +1 -1
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.de-DE.d.ts +3 -0
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.de-DE.d.ts.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.de-DE.js +310 -0
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.de-DE.js.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.en-US.d.ts +3 -0
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.en-US.d.ts.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.en-US.js +291 -0
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.en-US.js.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.zh-CN.d.ts +1 -11
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.zh-CN.d.ts.map +1 -1
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.zh-CN.js +47 -33
- package/dist/src/config/lexicons/identifiers/domains/finance.loan.zh-CN.js.map +1 -1
- package/dist/src/config/lexicons/identifiers/domains/index.d.ts +7 -0
- package/dist/src/config/lexicons/identifiers/domains/index.d.ts.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/index.js +8 -0
- package/dist/src/config/lexicons/identifiers/domains/index.js.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.de-DE.d.ts +3 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.de-DE.d.ts.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.de-DE.js +275 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.de-DE.js.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.en-US.d.ts +3 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.en-US.d.ts.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.en-US.js +261 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.en-US.js.map +1 -0
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.zh-CN.d.ts +1 -23
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.zh-CN.d.ts.map +1 -1
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.zh-CN.js +81 -155
- package/dist/src/config/lexicons/identifiers/domains/insurance.auto.zh-CN.js.map +1 -1
- package/dist/src/config/lexicons/identifiers/examples/canonicalizer-integration.js +8 -8
- package/dist/src/config/lexicons/identifiers/examples/canonicalizer-integration.js.map +1 -1
- package/dist/src/config/lexicons/identifiers/index.d.ts +1 -2
- package/dist/src/config/lexicons/identifiers/index.d.ts.map +1 -1
- package/dist/src/config/lexicons/identifiers/index.js +2 -3
- package/dist/src/config/lexicons/identifiers/index.js.map +1 -1
- package/dist/src/config/lexicons/identifiers/registry.d.ts +2 -2
- package/dist/src/config/lexicons/identifiers/registry.d.ts.map +1 -1
- package/dist/src/config/lexicons/identifiers/registry.js +16 -3
- package/dist/src/config/lexicons/identifiers/registry.js.map +1 -1
- package/dist/src/config/lexicons/template.d.ts.map +1 -1
- package/dist/src/config/lexicons/template.js +18 -8
- package/dist/src/config/lexicons/template.js.map +1 -1
- package/dist/src/config/lexicons/types.d.ts +1 -1
- package/dist/src/config/lexicons/types.d.ts.map +1 -1
- package/dist/src/config/lexicons/zh-CN.d.ts +0 -18
- package/dist/src/config/lexicons/zh-CN.d.ts.map +1 -1
- package/dist/src/config/lexicons/zh-CN.js +26 -61
- package/dist/src/config/lexicons/zh-CN.js.map +1 -1
- package/dist/src/config/semantic.d.ts +9 -4
- package/dist/src/config/semantic.d.ts.map +1 -1
- package/dist/src/config/semantic.js +16 -5
- package/dist/src/config/semantic.js.map +1 -1
- package/dist/src/config/token-kind.d.ts +17 -5
- package/dist/src/config/token-kind.d.ts.map +1 -1
- package/dist/src/config/token-kind.js +23 -7
- package/dist/src/config/token-kind.js.map +1 -1
- package/dist/src/frontend/canonicalizer.d.ts +20 -2
- package/dist/src/frontend/canonicalizer.d.ts.map +1 -1
- package/dist/src/frontend/canonicalizer.js +58 -2
- package/dist/src/frontend/canonicalizer.js.map +1 -1
- package/dist/src/frontend/index.d.ts +1 -0
- package/dist/src/frontend/index.d.ts.map +1 -1
- package/dist/src/frontend/index.js.map +1 -1
- package/dist/src/frontend/keyword-translator.d.ts.map +1 -1
- package/dist/src/frontend/keyword-translator.js +51 -15
- package/dist/src/frontend/keyword-translator.js.map +1 -1
- package/dist/src/lsp/codeaction.js +9 -9
- package/dist/src/lsp/codeaction.js.map +1 -1
- package/dist/src/lsp/completion.js +2 -2
- package/dist/src/lsp/completion.js.map +1 -1
- package/dist/src/lsp/module_cache.js +2 -2
- package/dist/src/lsp/module_cache.js.map +1 -1
- package/dist/src/lsp/server.js +0 -0
- package/dist/src/lsp/symbols.js +2 -2
- package/dist/src/lsp/symbols.js.map +1 -1
- package/dist/src/parser/decl-parser.d.ts +2 -2
- package/dist/src/parser/decl-parser.js +12 -12
- package/dist/src/parser/decl-parser.js.map +1 -1
- package/dist/src/parser/expr-stmt-parser.js +2 -2
- package/dist/src/parser/expr-stmt-parser.js.map +1 -1
- package/dist/src/parser.d.ts +1 -1
- package/dist/src/parser.js +1 -1
- package/dist/test/compiler/depends-on.test.js +2 -2
- package/dist/test/compiler/depends-on.test.js.map +1 -1
- package/dist/test/compiler/workflow-emitter-helpers.js +2 -2
- package/dist/test/compiler/workflow-emitter-helpers.js.map +1 -1
- package/dist/test/generators.js +18 -18
- package/dist/test/generators.js.map +1 -1
- package/dist/test/integration/lsp/lsp-completion.test.js +13 -13
- package/dist/test/integration/lsp/lsp-completion.test.js.map +1 -1
- package/dist/test/integration/lsp/lsp-diagnostics.test.js +7 -7
- package/dist/test/integration/lsp/lsp-diagnostics.test.js.map +1 -1
- package/dist/test/integration/lsp/lsp-file-watcher.test.js +8 -8
- package/dist/test/integration/lsp/lsp-file-watcher.test.js.map +1 -1
- package/dist/test/integration/lsp/lsp-modules.test.js +6 -6
- package/dist/test/integration/lsp/lsp-multi-rename.test.js +1 -1
- package/dist/test/integration/lsp/lsp-multi-rename.test.js.map +1 -1
- package/dist/test/integration/lsp/lsp-navigation.test.js +21 -21
- package/dist/test/integration/lsp/lsp-navigation.test.js.map +1 -1
- package/dist/test/integration/pipeline/pipeline.test.js +38 -38
- package/dist/test/integration/pipeline/pipeline.test.js.map +1 -1
- package/dist/test/property/lsp-props.test.js +2 -2
- package/dist/test/property/lsp-props.test.js.map +1 -1
- package/dist/test/property/property.test.js +25 -25
- package/dist/test/property/property.test.js.map +1 -1
- package/dist/test/type-checker/cross-module-packages.test.js +2 -1
- package/dist/test/type-checker/cross-module-packages.test.js.map +1 -1
- package/dist/test/unit/async/async-discipline.test.js +81 -81
- package/dist/test/unit/async/async-schedule.test.js +23 -23
- package/dist/test/unit/canonicalizer/canonicalizer.test.js +19 -13
- package/dist/test/unit/canonicalizer/canonicalizer.test.js.map +1 -1
- package/dist/test/unit/config/lexicons/zh-CN.test.js +44 -71
- package/dist/test/unit/config/lexicons/zh-CN.test.js.map +1 -1
- package/dist/test/unit/generator.test.js +3 -3
- package/dist/test/unit/generator.test.js.map +1 -1
- package/dist/test/unit/keyword-translator.test.js +55 -56
- package/dist/test/unit/keyword-translator.test.js.map +1 -1
- package/dist/test/unit/lexer/lexer.test.js +5 -5
- package/dist/test/unit/lexer/lexer.test.js.map +1 -1
- package/dist/test/unit/lowering/lowering.test.js +13 -13
- package/dist/test/unit/lsp/codeaction.test.js +9 -9
- package/dist/test/unit/lsp/codeaction.test.js.map +1 -1
- package/dist/test/unit/lsp/symbols.test.js +2 -2
- package/dist/test/unit/lsp/symbols.test.js.map +1 -1
- package/dist/test/unit/module-cache-packages.test.js +4 -4
- package/dist/test/unit/module-cache-packages.test.js.map +1 -1
- package/dist/test/unit/parser/parser.test.js +137 -137
- package/dist/test/unit/parser/parser.test.js.map +1 -1
- package/dist/test/unit/provenance-integration.test.js +16 -16
- package/dist/test/unit/provenance.test.js +5 -5
- package/dist/test/unit/provenance.test.js.map +1 -1
- package/dist/test/unit/typecheck/async-discipline-extended.test.js +4 -4
- package/dist/test/unit/typecheck/effects-and-capabilities.test.js +18 -18
- package/dist/test/unit/typecheck/type-inference.test.js +23 -23
- package/dist/test/unit/typecheck/typecheck-advanced.test.js +10 -10
- package/dist/test/unit/validator.test.js +14 -14
- package/dist/test/unit/validator.test.js.map +1 -1
- package/package.json +57 -39
|
@@ -24,18 +24,18 @@ function findFunc(module, name) {
|
|
|
24
24
|
describe('语法分析器', () => {
|
|
25
25
|
test('应该解析模块名称', () => {
|
|
26
26
|
const module = parseSource(`
|
|
27
|
-
|
|
27
|
+
Module test.parser.module_name.
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Rule ping, produce Text:
|
|
30
30
|
Return "pong".
|
|
31
31
|
`);
|
|
32
32
|
assert.equal(module.name, 'test.parser.module_name');
|
|
33
33
|
});
|
|
34
34
|
test('应该解析数据类型字段', () => {
|
|
35
35
|
const module = parseSource(`
|
|
36
|
-
|
|
36
|
+
Module test.parser.data_decl.
|
|
37
37
|
|
|
38
|
-
Define User
|
|
38
|
+
Define User has id: Text, name: Text, age: Int.
|
|
39
39
|
`);
|
|
40
40
|
const data = findDecl(module, 'Data');
|
|
41
41
|
assert.equal(data.fields.length, 3);
|
|
@@ -45,7 +45,7 @@ Define User with id: Text, name: Text, age: Int.
|
|
|
45
45
|
});
|
|
46
46
|
test('应该解析枚举变体列表', () => {
|
|
47
47
|
const module = parseSource(`
|
|
48
|
-
|
|
48
|
+
Module test.parser.enum_decl.
|
|
49
49
|
|
|
50
50
|
Define Status as one of Pending, Success, Failure.
|
|
51
51
|
`);
|
|
@@ -54,9 +54,9 @@ Define Status as one of Pending, Success, Failure.
|
|
|
54
54
|
});
|
|
55
55
|
test('应该解析函数的参数与返回类型', () => {
|
|
56
56
|
const module = parseSource(`
|
|
57
|
-
|
|
57
|
+
Module test.parser.func_signature.
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Rule format given name: Text and times: Int, produce Text:
|
|
60
60
|
Return Text.concat(name, Text.toString(times)).
|
|
61
61
|
`);
|
|
62
62
|
const func = findDecl(module, 'Func');
|
|
@@ -67,9 +67,9 @@ To format with name: Text and times: Int, produce Text:
|
|
|
67
67
|
});
|
|
68
68
|
test('应该解析函数体中的 Return 语句', () => {
|
|
69
69
|
const module = parseSource(`
|
|
70
|
-
|
|
70
|
+
Module test.parser.return_stmt.
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
Rule identity given value: Text, produce Text:
|
|
73
73
|
Return value.
|
|
74
74
|
`);
|
|
75
75
|
const func = findDecl(module, 'Func');
|
|
@@ -79,9 +79,9 @@ To identity with value: Text, produce Text:
|
|
|
79
79
|
});
|
|
80
80
|
test('应该解析 Let 语句并构建调用表达式', () => {
|
|
81
81
|
const module = parseSource(`
|
|
82
|
-
|
|
82
|
+
Module test.parser.let_stmt.
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
Rule greet given name: Text, produce Text:
|
|
85
85
|
Let trimmed be Text.trim(name).
|
|
86
86
|
Return Text.concat("Hi, ", trimmed).
|
|
87
87
|
`);
|
|
@@ -93,9 +93,9 @@ To greet with name: Text, produce Text:
|
|
|
93
93
|
});
|
|
94
94
|
test('应该解析 If 语句并生成 then/else 分支', () => {
|
|
95
95
|
const module = parseSource(`
|
|
96
|
-
|
|
96
|
+
Module test.parser.if_stmt.
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
Rule classify given score: Int, produce Text:
|
|
99
99
|
If score at least 800:
|
|
100
100
|
Return "Top".
|
|
101
101
|
Otherwise:
|
|
@@ -110,11 +110,11 @@ To classify with score: Int, produce Text:
|
|
|
110
110
|
});
|
|
111
111
|
test('应该解析 Match 表达式及其分支', () => {
|
|
112
112
|
const module = parseSource(`
|
|
113
|
-
|
|
113
|
+
Module test.parser.match_stmt.
|
|
114
114
|
|
|
115
|
-
Define User
|
|
115
|
+
Define User has id: Text, name: Text.
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
Rule welcome given user: User?, produce Text:
|
|
118
118
|
Match user:
|
|
119
119
|
When null, Return "Guest".
|
|
120
120
|
When User(id, name), Return Text.concat("Hi ", name).
|
|
@@ -128,14 +128,14 @@ To welcome with user: User?, produce Text:
|
|
|
128
128
|
});
|
|
129
129
|
test('应该解析 Start/Wait 异步语句', () => {
|
|
130
130
|
const module = parseSource(`
|
|
131
|
-
|
|
131
|
+
Module test.parser.async_stmt.
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
Rule runTasks, produce Text. It performs io:
|
|
134
134
|
Start task as async fetch().
|
|
135
135
|
Wait for task.
|
|
136
136
|
Return "done".
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
Rule fetch, produce Text:
|
|
139
139
|
Return "ok".
|
|
140
140
|
`);
|
|
141
141
|
const func = findDecl(module, 'Func');
|
|
@@ -145,19 +145,19 @@ To fetch, produce Text:
|
|
|
145
145
|
});
|
|
146
146
|
test('应该在语法错误时抛出诊断', () => {
|
|
147
147
|
assert.throws(() => parseSource(`
|
|
148
|
-
|
|
148
|
+
Module test.parser.error.
|
|
149
149
|
|
|
150
|
-
Define Broken
|
|
150
|
+
Define Broken has x: Int
|
|
151
151
|
`), /expected '.'/i);
|
|
152
152
|
});
|
|
153
153
|
describe('边界场景', () => {
|
|
154
154
|
it('应该解析 import 别名并保持调用目标一致', () => {
|
|
155
155
|
const module = parseSource(`
|
|
156
|
-
|
|
156
|
+
Module test.parser.import_alias.
|
|
157
157
|
|
|
158
158
|
Use Http as H.
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
Rule call, produce Text:
|
|
161
161
|
Return H.get().
|
|
162
162
|
`);
|
|
163
163
|
const importDecl = findDecl(module, 'Import');
|
|
@@ -182,11 +182,11 @@ To call, produce Text:
|
|
|
182
182
|
});
|
|
183
183
|
it('应该解析空效果列表与多基础效果组合', () => {
|
|
184
184
|
const module = parseSource(`
|
|
185
|
-
|
|
185
|
+
Module test.parser.effects_basic.
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
Rule audit, produce Int. It performs [].
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
Rule compute given value: Int, produce Int. It performs io and cpu.
|
|
190
190
|
`);
|
|
191
191
|
const audit = findFunc(module, 'audit');
|
|
192
192
|
assert.deepEqual(audit.effects, []);
|
|
@@ -207,9 +207,9 @@ To compute with value: Int, produce Int. It performs io and cpu.
|
|
|
207
207
|
});
|
|
208
208
|
it('应该解析显式 capability 列表并保留效果体', () => {
|
|
209
209
|
const module = parseSource(`
|
|
210
|
-
|
|
210
|
+
Module test.parser.effects_explicit.
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
Rule fetch, produce Text. It performs io with Http and Sql:
|
|
213
213
|
Return "ok".
|
|
214
214
|
`);
|
|
215
215
|
const func = findFunc(module, 'fetch');
|
|
@@ -220,13 +220,13 @@ To fetch, produce Text. It performs io with Http and Sql:
|
|
|
220
220
|
});
|
|
221
221
|
it('应该解析 CNL 约束并保留参数信息', () => {
|
|
222
222
|
const module = parseSource(`
|
|
223
|
-
|
|
223
|
+
Module test.parser.constraints.
|
|
224
224
|
|
|
225
|
-
Define User
|
|
225
|
+
Define User has
|
|
226
226
|
id: Text required,
|
|
227
227
|
age: Int between 0 and 120 matching "^[0-9]+$".
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
Rule validate given input: Text required, produce Bool:
|
|
230
230
|
Return true.
|
|
231
231
|
`);
|
|
232
232
|
const data = findDecl(module, 'Data');
|
|
@@ -265,13 +265,13 @@ To validate with input: Text required, produce Bool:
|
|
|
265
265
|
});
|
|
266
266
|
it('应该解析无类型声明的字段和参数约束', () => {
|
|
267
267
|
const module = parseSource(`
|
|
268
|
-
|
|
268
|
+
Module test.parser.inline_constraints.
|
|
269
269
|
|
|
270
|
-
Define LoanApplication
|
|
270
|
+
Define LoanApplication has applicantId required, amount, termMonths between 0 and 600, purpose required.
|
|
271
271
|
|
|
272
|
-
Define ApplicantProfile
|
|
272
|
+
Define ApplicantProfile has age between 0 and 120, creditScore between 300 and 850, annualIncome.
|
|
273
273
|
|
|
274
|
-
|
|
274
|
+
Rule determineInterestRateBps given creditScore between 300 and 850, produce:
|
|
275
275
|
Return 350.
|
|
276
276
|
`);
|
|
277
277
|
const loanDecl = module.decls.find((decl) => decl.kind === 'Data' && decl.name === 'LoanApplication');
|
|
@@ -320,9 +320,9 @@ To determineInterestRateBps with creditScore between 300 and 850, produce:
|
|
|
320
320
|
});
|
|
321
321
|
it('应该在缺失参数分隔符时报告诊断', () => {
|
|
322
322
|
assert.throws(() => parseSource(`
|
|
323
|
-
|
|
323
|
+
Module test.parser.error.missing_separator.
|
|
324
324
|
|
|
325
|
-
|
|
325
|
+
Rule broken given first: Int second: Int, produce Int:
|
|
326
326
|
Return first.
|
|
327
327
|
`), error => {
|
|
328
328
|
assert.match(String(error), /Expected 'produce' and return type/i);
|
|
@@ -331,9 +331,9 @@ To broken with first: Int second: Int, produce Int:
|
|
|
331
331
|
});
|
|
332
332
|
it('应该在括号不匹配时报告诊断', () => {
|
|
333
333
|
assert.throws(() => parseSource(`
|
|
334
|
-
|
|
334
|
+
Module test.parser.error.parentheses.
|
|
335
335
|
|
|
336
|
-
|
|
336
|
+
Rule fail given value: Text, produce Text:
|
|
337
337
|
Return (value.
|
|
338
338
|
`), error => {
|
|
339
339
|
assert.ok(String(error).includes("Expected ')' after expression"), '诊断信息应该指出括号缺失');
|
|
@@ -344,9 +344,9 @@ To fail with value: Text, produce Text:
|
|
|
344
344
|
describe('函数类型参数解析', () => {
|
|
345
345
|
test('应该解析单一显式类型参数并绑定到参数类型', () => {
|
|
346
346
|
const module = parseSource(`
|
|
347
|
-
|
|
347
|
+
Module test.parser.func_type_params.single.
|
|
348
348
|
|
|
349
|
-
|
|
349
|
+
Rule wrap of T given value: T, produce List of T:
|
|
350
350
|
Return List.build(value).
|
|
351
351
|
`);
|
|
352
352
|
const func = findFunc(module, 'wrap');
|
|
@@ -366,9 +366,9 @@ To wrap of T with value: T, produce List of T:
|
|
|
366
366
|
});
|
|
367
367
|
test('应该解析多个显式类型参数并保持顺序', () => {
|
|
368
368
|
const module = parseSource(`
|
|
369
|
-
|
|
369
|
+
Module test.parser.func_type_params.multi.
|
|
370
370
|
|
|
371
|
-
|
|
371
|
+
Rule pair of Left and Right given left: Left and right: Right, produce Result of Left or Right:
|
|
372
372
|
Return Result.ok(left).
|
|
373
373
|
`);
|
|
374
374
|
const func = findFunc(module, 'pair');
|
|
@@ -394,9 +394,9 @@ To pair of Left and Right with left: Left and right: Right, produce Result of Le
|
|
|
394
394
|
});
|
|
395
395
|
test('应该支持逗号与 and 混合的类型参数列表', () => {
|
|
396
396
|
const module = parseSource(`
|
|
397
|
-
|
|
397
|
+
Module test.parser.func_type_params.mixed.
|
|
398
398
|
|
|
399
|
-
|
|
399
|
+
Rule compose of Input, Middle and Output given first: Input, second: Middle, produce Output:
|
|
400
400
|
Return second.
|
|
401
401
|
`);
|
|
402
402
|
const func = findFunc(module, 'compose');
|
|
@@ -411,9 +411,9 @@ To compose of Input, Middle and Output with first: Input, second: Middle, produc
|
|
|
411
411
|
});
|
|
412
412
|
test('应该允许类型参数参与复杂返回类型', () => {
|
|
413
413
|
const module = parseSource(`
|
|
414
|
-
|
|
414
|
+
Module test.parser.func_type_params.complex.
|
|
415
415
|
|
|
416
|
-
|
|
416
|
+
Rule pipeline of Source and Target given items: List of Source, produce Result of Map Source to Target or Text:
|
|
417
417
|
Return Result.err("empty").
|
|
418
418
|
`);
|
|
419
419
|
const func = findFunc(module, 'pipeline');
|
|
@@ -444,11 +444,11 @@ To pipeline of Source and Target with items: List of Source, produce Result of M
|
|
|
444
444
|
});
|
|
445
445
|
});
|
|
446
446
|
describe('多行参数列表与缩进', () => {
|
|
447
|
-
test('应该解析
|
|
447
|
+
test('应该解析 given 子句的多行参数', () => {
|
|
448
448
|
const module = parseSource(`
|
|
449
|
-
|
|
449
|
+
Module test.parser.params.multiline_with.
|
|
450
450
|
|
|
451
|
-
|
|
451
|
+
Rule summarize given
|
|
452
452
|
first: Text,
|
|
453
453
|
second: Text,
|
|
454
454
|
third: Text, produce Text:
|
|
@@ -460,9 +460,9 @@ To summarize with
|
|
|
460
460
|
});
|
|
461
461
|
test('应该在多行参数后继续解析效果声明', () => {
|
|
462
462
|
const module = parseSource(`
|
|
463
|
-
|
|
463
|
+
Module test.parser.params.multiline_effect.
|
|
464
464
|
|
|
465
|
-
|
|
465
|
+
Rule compute given
|
|
466
466
|
value: Int,
|
|
467
467
|
factor: Int, produce Int. It performs cpu:
|
|
468
468
|
Return value times factor.
|
|
@@ -474,9 +474,9 @@ To compute with
|
|
|
474
474
|
});
|
|
475
475
|
test('应该在多行参数中保留约束', () => {
|
|
476
476
|
const module = parseSource(`
|
|
477
|
-
|
|
477
|
+
Module test.parser.params.multiline_constraints.
|
|
478
478
|
|
|
479
|
-
|
|
479
|
+
Rule filter given
|
|
480
480
|
query: Text required,
|
|
481
481
|
limit: Int, produce List of Text:
|
|
482
482
|
Return List.empty().
|
|
@@ -495,9 +495,9 @@ To filter with
|
|
|
495
495
|
describe('Let 内联 lambda 解析', () => {
|
|
496
496
|
test('应该将内联函数解析为 Lambda 节点', () => {
|
|
497
497
|
const module = parseSource(`
|
|
498
|
-
|
|
498
|
+
Module test.parser.let.lambda.basic.
|
|
499
499
|
|
|
500
|
-
|
|
500
|
+
Rule operate given value: Int, produce Int:
|
|
501
501
|
Let increment be function with input: Int, produce Int:
|
|
502
502
|
Return input plus 1.
|
|
503
503
|
Return increment(value).
|
|
@@ -516,9 +516,9 @@ To operate with value: Int, produce Int:
|
|
|
516
516
|
});
|
|
517
517
|
test('应该支持带可选 a function 的写法', () => {
|
|
518
518
|
const module = parseSource(`
|
|
519
|
-
|
|
519
|
+
Module test.parser.let.lambda.article.
|
|
520
520
|
|
|
521
|
-
|
|
521
|
+
Rule demo, produce Int:
|
|
522
522
|
Let noop be a function with value: Int, produce Int:
|
|
523
523
|
Return value.
|
|
524
524
|
Return noop(0).
|
|
@@ -534,9 +534,9 @@ To demo, produce Int:
|
|
|
534
534
|
});
|
|
535
535
|
test('应该保留 lambda 内部的语句块', () => {
|
|
536
536
|
const module = parseSource(`
|
|
537
|
-
|
|
537
|
+
Module test.parser.let.lambda.body.
|
|
538
538
|
|
|
539
|
-
|
|
539
|
+
Rule compose, produce Int:
|
|
540
540
|
Let combine be function with left: Int and right: Int, produce Int:
|
|
541
541
|
Let sum be left plus right.
|
|
542
542
|
Return sum.
|
|
@@ -559,9 +559,9 @@ To compose, produce Int:
|
|
|
559
559
|
describe('Set 语句解析', () => {
|
|
560
560
|
test('应该解析基本的赋值语句', () => {
|
|
561
561
|
const module = parseSource(`
|
|
562
|
-
|
|
562
|
+
Module test.parser.set.basic.
|
|
563
563
|
|
|
564
|
-
|
|
564
|
+
Rule update given value: Int, produce Int:
|
|
565
565
|
Let total be 0.
|
|
566
566
|
Set total to total plus value.
|
|
567
567
|
Return total.
|
|
@@ -578,9 +578,9 @@ To update with value: Int, produce Int:
|
|
|
578
578
|
});
|
|
579
579
|
test('应该在嵌套块中解析 Set 语句', () => {
|
|
580
580
|
const module = parseSource(`
|
|
581
|
-
|
|
581
|
+
Module test.parser.set.nested.
|
|
582
582
|
|
|
583
|
-
|
|
583
|
+
Rule configure, produce Text:
|
|
584
584
|
Within scope:
|
|
585
585
|
Let state be "initial".
|
|
586
586
|
Set state to "ready".
|
|
@@ -603,9 +603,9 @@ To configure, produce Text:
|
|
|
603
603
|
});
|
|
604
604
|
test('应该在缺少 to 时抛出诊断', () => {
|
|
605
605
|
assert.throws(() => parseSource(`
|
|
606
|
-
|
|
606
|
+
Module test.parser.set.error_missing_to.
|
|
607
607
|
|
|
608
|
-
|
|
608
|
+
Rule broken, produce Int:
|
|
609
609
|
Set total value.
|
|
610
610
|
Return 0.
|
|
611
611
|
`), error => {
|
|
@@ -615,9 +615,9 @@ To broken, produce Int:
|
|
|
615
615
|
});
|
|
616
616
|
test('应该在缺少结尾句点时抛出诊断', () => {
|
|
617
617
|
assert.throws(() => parseSource(`
|
|
618
|
-
|
|
618
|
+
Module test.parser.set.error_missing_period.
|
|
619
619
|
|
|
620
|
-
|
|
620
|
+
Rule broken, produce Int:
|
|
621
621
|
Set total to 1
|
|
622
622
|
Return total.
|
|
623
623
|
`), error => {
|
|
@@ -629,9 +629,9 @@ To broken, produce Int:
|
|
|
629
629
|
describe('Return 效果采集', () => {
|
|
630
630
|
test('应该收集 Return 语句后的效果说明', () => {
|
|
631
631
|
const module = parseSource(`
|
|
632
|
-
|
|
632
|
+
Module test.parser.return.effects.inline.
|
|
633
633
|
|
|
634
|
-
|
|
634
|
+
Rule fetch, produce Text:
|
|
635
635
|
Return "ok". It performs io.
|
|
636
636
|
`);
|
|
637
637
|
const func = findFunc(module, 'fetch');
|
|
@@ -648,9 +648,9 @@ To fetch, produce Text:
|
|
|
648
648
|
});
|
|
649
649
|
test('应该合并函数体收集的效果', () => {
|
|
650
650
|
const module = parseSource(`
|
|
651
|
-
|
|
651
|
+
Module test.parser.return.effects.merge.
|
|
652
652
|
|
|
653
|
-
|
|
653
|
+
Rule compute, produce Int. It performs cpu:
|
|
654
654
|
Return 1. It performs io.
|
|
655
655
|
`);
|
|
656
656
|
const func = findFunc(module, 'compute');
|
|
@@ -670,9 +670,9 @@ To compute, produce Int. It performs cpu:
|
|
|
670
670
|
describe('If not 条件', () => {
|
|
671
671
|
test('应该将 If not 条件转换为 not 调用', () => {
|
|
672
672
|
const module = parseSource(`
|
|
673
|
-
|
|
673
|
+
Module test.parser.if.not.basic.
|
|
674
674
|
|
|
675
|
-
|
|
675
|
+
Rule guard given flag: Bool, produce Text:
|
|
676
676
|
If not flag:
|
|
677
677
|
Return "blocked".
|
|
678
678
|
Otherwise:
|
|
@@ -696,9 +696,9 @@ To guard with flag: Bool, produce Text:
|
|
|
696
696
|
});
|
|
697
697
|
test('应该在复合条件中保持原始表达式', () => {
|
|
698
698
|
const module = parseSource(`
|
|
699
|
-
|
|
699
|
+
Module test.parser.if.not.complex.
|
|
700
700
|
|
|
701
|
-
|
|
701
|
+
Rule score given value: Int, produce Text:
|
|
702
702
|
If not (value at least 600):
|
|
703
703
|
Return "retry".
|
|
704
704
|
Otherwise:
|
|
@@ -725,9 +725,9 @@ To score with value: Int, produce Text:
|
|
|
725
725
|
describe('List/Map/Result 复杂类型', () => {
|
|
726
726
|
test('应该解析问号表示的 Maybe 类型', () => {
|
|
727
727
|
const module = parseSource(`
|
|
728
|
-
|
|
728
|
+
Module test.parser.types.maybe.
|
|
729
729
|
|
|
730
|
-
|
|
730
|
+
Rule handle given token: Text?, produce Bool:
|
|
731
731
|
Return true.
|
|
732
732
|
`);
|
|
733
733
|
const func = findFunc(module, 'handle');
|
|
@@ -744,9 +744,9 @@ To handle with token: Text?, produce Bool:
|
|
|
744
744
|
});
|
|
745
745
|
test('应该解析 Option of 与 Maybe 组合', () => {
|
|
746
746
|
const module = parseSource(`
|
|
747
|
-
|
|
747
|
+
Module test.parser.types.option.
|
|
748
748
|
|
|
749
|
-
|
|
749
|
+
Rule parse given payload: Option of Text?, produce Bool:
|
|
750
750
|
Return true.
|
|
751
751
|
`);
|
|
752
752
|
const func = findFunc(module, 'parse');
|
|
@@ -767,9 +767,9 @@ To parse with payload: Option of Text?, produce Bool:
|
|
|
767
767
|
});
|
|
768
768
|
test('应该解析 Result of 基本组合', () => {
|
|
769
769
|
const module = parseSource(`
|
|
770
|
-
|
|
770
|
+
Module test.parser.types.result.
|
|
771
771
|
|
|
772
|
-
|
|
772
|
+
Rule convert given input: Result of Int or Text, produce Int:
|
|
773
773
|
Return 0.
|
|
774
774
|
`);
|
|
775
775
|
const func = findFunc(module, 'convert');
|
|
@@ -788,9 +788,9 @@ To convert with input: Result of Int or Text, produce Int:
|
|
|
788
788
|
});
|
|
789
789
|
test('应该解析 List of Map 嵌套类型', () => {
|
|
790
790
|
const module = parseSource(`
|
|
791
|
-
|
|
791
|
+
Module test.parser.types.list_map.
|
|
792
792
|
|
|
793
|
-
|
|
793
|
+
Rule collect given rows: List of Map Text to Int, produce Int:
|
|
794
794
|
Return 0.
|
|
795
795
|
`);
|
|
796
796
|
const func = findFunc(module, 'collect');
|
|
@@ -813,9 +813,9 @@ To collect with rows: List of Map Text to Int, produce Int:
|
|
|
813
813
|
});
|
|
814
814
|
test('应该解析自定义类型应用', () => {
|
|
815
815
|
const module = parseSource(`
|
|
816
|
-
|
|
816
|
+
Module test.parser.types.type_app_single.
|
|
817
817
|
|
|
818
|
-
|
|
818
|
+
Rule adapt given response: Text, produce Promise of Text:
|
|
819
819
|
Return Promise.success(response).
|
|
820
820
|
`);
|
|
821
821
|
const func = findFunc(module, 'adapt');
|
|
@@ -830,9 +830,9 @@ To adapt with response: Text, produce Promise of Text:
|
|
|
830
830
|
});
|
|
831
831
|
test('应该解析多层 List 嵌套', () => {
|
|
832
832
|
const module = parseSource(`
|
|
833
|
-
|
|
833
|
+
Module test.parser.types.list_nested.
|
|
834
834
|
|
|
835
|
-
|
|
835
|
+
Rule flatten given input: List of List of Int, produce List of Int:
|
|
836
836
|
Return input.
|
|
837
837
|
`);
|
|
838
838
|
const func = findFunc(module, 'flatten');
|
|
@@ -853,9 +853,9 @@ To flatten with input: List of List of Int, produce List of Int:
|
|
|
853
853
|
});
|
|
854
854
|
test('应该解析带 @pii 注解的类型', () => {
|
|
855
855
|
const module = parseSource(`
|
|
856
|
-
|
|
856
|
+
Module test.parser.types.pii.
|
|
857
857
|
|
|
858
|
-
|
|
858
|
+
Rule secure given field: @pii(L2, email) Text, produce Text:
|
|
859
859
|
Return field.
|
|
860
860
|
`);
|
|
861
861
|
const func = findFunc(module, 'secure');
|
|
@@ -874,9 +874,9 @@ To secure with field: @pii(L2, email) Text, produce Text:
|
|
|
874
874
|
});
|
|
875
875
|
test('应该解析 Map 到 Result 的组合', () => {
|
|
876
876
|
const module = parseSource(`
|
|
877
|
-
|
|
877
|
+
Module test.parser.types.map_result.
|
|
878
878
|
|
|
879
|
-
|
|
879
|
+
Rule inspect given entry: Map Text to Result of Int or Text, produce Bool:
|
|
880
880
|
Return true.
|
|
881
881
|
`);
|
|
882
882
|
const func = findFunc(module, 'inspect');
|
|
@@ -899,9 +899,9 @@ To inspect with entry: Map Text to Result of Int or Text, produce Bool:
|
|
|
899
899
|
});
|
|
900
900
|
test('应该解析 Result of 中嵌套 Option', () => {
|
|
901
901
|
const module = parseSource(`
|
|
902
|
-
|
|
902
|
+
Module test.parser.types.result_option.
|
|
903
903
|
|
|
904
|
-
|
|
904
|
+
Rule decide given payload: Result of Option of Text or List of Text, produce Bool:
|
|
905
905
|
Return true.
|
|
906
906
|
`);
|
|
907
907
|
const func = findFunc(module, 'decide');
|
|
@@ -928,9 +928,9 @@ To decide with payload: Result of Option of Text or List of Text, produce Bool:
|
|
|
928
928
|
});
|
|
929
929
|
test('应该解析多个参数的类型应用', () => {
|
|
930
930
|
const module = parseSource(`
|
|
931
|
-
|
|
931
|
+
Module test.parser.types.type_app_multi.
|
|
932
932
|
|
|
933
|
-
|
|
933
|
+
Rule choose given picker: Text, produce Either of Text and Int:
|
|
934
934
|
Return Either.left(picker).
|
|
935
935
|
`);
|
|
936
936
|
const func = findFunc(module, 'choose');
|
|
@@ -949,12 +949,12 @@ To choose with picker: Text, produce Either of Text and Int:
|
|
|
949
949
|
describe('类型变量作用域', () => {
|
|
950
950
|
test('显式类型参数不会泄漏到后续函数', () => {
|
|
951
951
|
const module = parseSource(`
|
|
952
|
-
|
|
952
|
+
Module test.parser.type_scope.explicit.
|
|
953
953
|
|
|
954
|
-
|
|
954
|
+
Rule first of T given value: T, produce T:
|
|
955
955
|
Return value.
|
|
956
956
|
|
|
957
|
-
|
|
957
|
+
Rule second given value: T, produce T:
|
|
958
958
|
Return value.
|
|
959
959
|
`);
|
|
960
960
|
const firstFunc = findFunc(module, 'first');
|
|
@@ -971,11 +971,11 @@ To second with value: T, produce T:
|
|
|
971
971
|
});
|
|
972
972
|
test('推断不会误将数据类型视为类型变量', () => {
|
|
973
973
|
const module = parseSource(`
|
|
974
|
-
|
|
974
|
+
Module test.parser.type_scope.declared.
|
|
975
975
|
|
|
976
|
-
Define User
|
|
976
|
+
Define User has id: Text.
|
|
977
977
|
|
|
978
|
-
|
|
978
|
+
Rule fetch given id: User, produce User:
|
|
979
979
|
Return User.new(id).
|
|
980
980
|
`);
|
|
981
981
|
const func = findFunc(module, 'fetch');
|
|
@@ -990,12 +990,12 @@ To fetch with id: User, produce User:
|
|
|
990
990
|
});
|
|
991
991
|
test('推断的类型变量在不同函数间独立', () => {
|
|
992
992
|
const module = parseSource(`
|
|
993
|
-
|
|
993
|
+
Module test.parser.type_scope.independent.
|
|
994
994
|
|
|
995
|
-
|
|
995
|
+
Rule box given value: Alpha, produce Alpha:
|
|
996
996
|
Return value.
|
|
997
997
|
|
|
998
|
-
|
|
998
|
+
Rule unwrap given value: Beta, produce Beta:
|
|
999
999
|
Return value.
|
|
1000
1000
|
`);
|
|
1001
1001
|
const box = findFunc(module, 'box');
|
|
@@ -1007,9 +1007,9 @@ To unwrap with value: Beta, produce Beta:
|
|
|
1007
1007
|
describe('效果和能力解析', () => {
|
|
1008
1008
|
test('应该解析带显式能力列表的效果声明', () => {
|
|
1009
1009
|
const module = parseSource(`
|
|
1010
|
-
|
|
1010
|
+
Module test.parser.effects.explicit_caps.
|
|
1011
1011
|
|
|
1012
|
-
|
|
1012
|
+
Rule fetch, produce Text. It performs io [Http, Sql].
|
|
1013
1013
|
`);
|
|
1014
1014
|
const func = findFunc(module, 'fetch');
|
|
1015
1015
|
assert.deepEqual(func.effects, ['io']);
|
|
@@ -1018,9 +1018,9 @@ To fetch, produce Text. It performs io [Http, Sql].
|
|
|
1018
1018
|
});
|
|
1019
1019
|
test('应该解析混合效果与显式能力', () => {
|
|
1020
1020
|
const module = parseSource(`
|
|
1021
|
-
|
|
1021
|
+
Module test.parser.effects.mixed.
|
|
1022
1022
|
|
|
1023
|
-
|
|
1023
|
+
Rule sync, produce Int. It performs io and cpu and Http.
|
|
1024
1024
|
`);
|
|
1025
1025
|
const func = findFunc(module, 'sync');
|
|
1026
1026
|
assert.deepEqual(func.effects, ['io', 'cpu']);
|
|
@@ -1029,9 +1029,9 @@ To sync, produce Int. It performs io and cpu and Http.
|
|
|
1029
1029
|
});
|
|
1030
1030
|
test('应该在出现未知能力时抛出诊断', () => {
|
|
1031
1031
|
assert.throws(() => parseSource(`
|
|
1032
|
-
|
|
1032
|
+
Module test.parser.effects.unknown_cap.
|
|
1033
1033
|
|
|
1034
|
-
|
|
1034
|
+
Rule risky, produce Text. It performs io with Blockchain.
|
|
1035
1035
|
`), error => {
|
|
1036
1036
|
assert.match(String(error), /Unknown capability 'Blockchain'/);
|
|
1037
1037
|
return true;
|
|
@@ -1039,9 +1039,9 @@ To risky, produce Text. It performs io with Blockchain.
|
|
|
1039
1039
|
});
|
|
1040
1040
|
test('应该在仅声明 cpu 时推导能力', () => {
|
|
1041
1041
|
const module = parseSource(`
|
|
1042
|
-
|
|
1042
|
+
Module test.parser.effects.cpu_only.
|
|
1043
1043
|
|
|
1044
|
-
|
|
1044
|
+
Rule crunch, produce Int. It performs cpu.
|
|
1045
1045
|
`);
|
|
1046
1046
|
const func = findFunc(module, 'crunch');
|
|
1047
1047
|
assert.deepEqual(func.effects, ['cpu']);
|
|
@@ -1052,9 +1052,9 @@ To crunch, produce Int. It performs cpu.
|
|
|
1052
1052
|
describe('其他高优场景', () => {
|
|
1053
1053
|
test('应该解析 Within scope 块语句', () => {
|
|
1054
1054
|
const module = parseSource(`
|
|
1055
|
-
|
|
1055
|
+
Module test.parser.misc.within_scope.
|
|
1056
1056
|
|
|
1057
|
-
|
|
1057
|
+
Rule wrap, produce Text:
|
|
1058
1058
|
Within scope:
|
|
1059
1059
|
Let temp be "a".
|
|
1060
1060
|
Return temp.
|
|
@@ -1071,9 +1071,9 @@ To wrap, produce Text:
|
|
|
1071
1071
|
});
|
|
1072
1072
|
test('应该解析 Wait for 多个名称列表', () => {
|
|
1073
1073
|
const module = parseSource(`
|
|
1074
|
-
|
|
1074
|
+
Module test.parser.misc.wait_many.
|
|
1075
1075
|
|
|
1076
|
-
|
|
1076
|
+
Rule waitAll, produce Text:
|
|
1077
1077
|
Let taskOne be start().
|
|
1078
1078
|
Let taskTwo be start().
|
|
1079
1079
|
Let taskThree be start().
|
|
@@ -1090,9 +1090,9 @@ To waitAll, produce Text:
|
|
|
1090
1090
|
});
|
|
1091
1091
|
test('应该解析 await 调用语句', () => {
|
|
1092
1092
|
const module = parseSource(`
|
|
1093
|
-
|
|
1093
|
+
Module test.parser.misc.await_stmt.
|
|
1094
1094
|
|
|
1095
|
-
|
|
1095
|
+
Rule sync, produce Text:
|
|
1096
1096
|
Let result be await(fetch()).
|
|
1097
1097
|
Return result.
|
|
1098
1098
|
`);
|
|
@@ -1111,9 +1111,9 @@ To sync, produce Text:
|
|
|
1111
1111
|
});
|
|
1112
1112
|
test('应该保留裸调用语句', () => {
|
|
1113
1113
|
const module = parseSource(`
|
|
1114
|
-
|
|
1114
|
+
Module test.parser.misc.expression_stmt.
|
|
1115
1115
|
|
|
1116
|
-
|
|
1116
|
+
Rule log, produce Text:
|
|
1117
1117
|
Text.log("started").
|
|
1118
1118
|
Return "ok".
|
|
1119
1119
|
`);
|
|
@@ -1127,9 +1127,9 @@ To log, produce Text:
|
|
|
1127
1127
|
});
|
|
1128
1128
|
test('应该解析 Match 分支中的名称模式', () => {
|
|
1129
1129
|
const module = parseSource(`
|
|
1130
|
-
|
|
1130
|
+
Module test.parser.misc.match_name.
|
|
1131
1131
|
|
|
1132
|
-
|
|
1132
|
+
Rule unwrap given option: Option of Text, produce Text:
|
|
1133
1133
|
Match option:
|
|
1134
1134
|
When value, Return value.
|
|
1135
1135
|
When null, Return "none".
|
|
@@ -1150,9 +1150,9 @@ To unwrap with option: Option of Text, produce Text:
|
|
|
1150
1150
|
});
|
|
1151
1151
|
test('应该解析 Start 语句的绑定与调用目标', () => {
|
|
1152
1152
|
const module = parseSource(`
|
|
1153
|
-
|
|
1153
|
+
Module test.parser.misc.start_detail.
|
|
1154
1154
|
|
|
1155
|
-
|
|
1155
|
+
Rule spawn, produce Text:
|
|
1156
1156
|
Start worker as async Http.fetch().
|
|
1157
1157
|
Return "done".
|
|
1158
1158
|
`);
|
|
@@ -1173,9 +1173,9 @@ To spawn, produce Text:
|
|
|
1173
1173
|
describe('parseWithLexicon 多语言支持', () => {
|
|
1174
1174
|
test('应该使用 en-US lexicon 直接解析(无翻译)', () => {
|
|
1175
1175
|
const source = `
|
|
1176
|
-
|
|
1176
|
+
Module test.parser.lexicon.en.
|
|
1177
1177
|
|
|
1178
|
-
|
|
1178
|
+
Rule greet given name: Text, produce Text:
|
|
1179
1179
|
Return Text.concat("Hello, ", name).
|
|
1180
1180
|
`;
|
|
1181
1181
|
const canonical = canonicalize(source, EN_US);
|
|
@@ -1188,9 +1188,9 @@ To greet with name: Text, produce Text:
|
|
|
1188
1188
|
});
|
|
1189
1189
|
test('应该使用 zh-CN lexicon 自动翻译并解析', () => {
|
|
1190
1190
|
const zhSource = `
|
|
1191
|
-
|
|
1191
|
+
模块 测试。
|
|
1192
1192
|
|
|
1193
|
-
|
|
1193
|
+
规则 identity 包含 value:整数,产出:
|
|
1194
1194
|
返回 value。
|
|
1195
1195
|
`;
|
|
1196
1196
|
const canonical = canonicalize(zhSource, ZH_CN);
|
|
@@ -1205,9 +1205,9 @@ To greet with name: Text, produce Text:
|
|
|
1205
1205
|
});
|
|
1206
1206
|
test('应该解析中文 CNL 的类型定义', () => {
|
|
1207
1207
|
const zhSource = `
|
|
1208
|
-
|
|
1208
|
+
模块 测试。
|
|
1209
1209
|
|
|
1210
|
-
|
|
1210
|
+
定义 User 包含 age:整数。
|
|
1211
1211
|
`;
|
|
1212
1212
|
const canonical = canonicalize(zhSource, ZH_CN);
|
|
1213
1213
|
const tokens = lex(canonical, ZH_CN);
|
|
@@ -1223,9 +1223,9 @@ To greet with name: Text, produce Text:
|
|
|
1223
1223
|
});
|
|
1224
1224
|
test('应该解析中文 CNL 的 If 语句', () => {
|
|
1225
1225
|
const zhSource = `
|
|
1226
|
-
|
|
1226
|
+
模块 测试。
|
|
1227
1227
|
|
|
1228
|
-
|
|
1228
|
+
规则 check 包含 x:整数,产出:
|
|
1229
1229
|
如果 x 大于 0:
|
|
1230
1230
|
返回 1。
|
|
1231
1231
|
否则:
|
|
@@ -1245,9 +1245,9 @@ To greet with name: Text, produce Text:
|
|
|
1245
1245
|
});
|
|
1246
1246
|
test('应该解析中文 CNL 的 Match 语句(若...为)', () => {
|
|
1247
1247
|
const zhSource = `
|
|
1248
|
-
|
|
1248
|
+
模块 测试。
|
|
1249
1249
|
|
|
1250
|
-
|
|
1250
|
+
规则 describe 包含 status:整数,产出:
|
|
1251
1251
|
若 status:
|
|
1252
1252
|
为 1,返回 「成功」。
|
|
1253
1253
|
为 0,返回 「失败」。
|
|
@@ -1266,9 +1266,9 @@ To greet with name: Text, produce Text:
|
|
|
1266
1266
|
});
|
|
1267
1267
|
test('应该解析中文 CNL 的 Let...为 语句', () => {
|
|
1268
1268
|
const zhSource = `
|
|
1269
|
-
|
|
1269
|
+
模块 测试。
|
|
1270
1270
|
|
|
1271
|
-
|
|
1271
|
+
规则 calc 包含 x:整数,产出:
|
|
1272
1272
|
令 result 为 x 加 1。
|
|
1273
1273
|
返回 result。
|
|
1274
1274
|
`;
|