nadesiko3 3.3.48 → 3.3.49

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 (105) hide show
  1. package/core/.editorconfig +6 -0
  2. package/core/.eslintrc.cjs +33 -0
  3. package/core/.github/dependabot.yml +7 -0
  4. package/core/.github/workflows/nodejs.yml +37 -0
  5. package/core/.github/workflows/super-linter.yml +61 -0
  6. package/core/.github/workflows/textlint.yml +199 -0
  7. package/core/LICENSE +21 -0
  8. package/core/README.md +66 -0
  9. package/core/batch/build_nako_version.nako3 +42 -0
  10. package/core/command/snako.mjs +105 -0
  11. package/core/command/snako.mts +116 -0
  12. package/core/index.mjs +21 -0
  13. package/core/index.mts +21 -0
  14. package/core/package.json +47 -0
  15. package/core/sample/hello.nako3 +7 -0
  16. package/core/sample/hoge.mjs +4 -0
  17. package/core/sample/hoge.mts +6 -0
  18. package/core/src/nako3.mjs +858 -0
  19. package/core/src/nako3.mts +967 -0
  20. package/core/src/nako_colors.mjs +78 -0
  21. package/core/src/nako_colors.mts +86 -0
  22. package/core/src/nako_core_version.mjs +8 -0
  23. package/core/src/nako_core_version.mts +19 -0
  24. package/core/src/nako_csv.mjs +185 -0
  25. package/core/src/nako_csv.mts +188 -0
  26. package/core/src/nako_errors.mjs +173 -0
  27. package/core/src/nako_errors.mts +197 -0
  28. package/core/src/nako_from_dncl.mjs +255 -0
  29. package/core/src/nako_from_dncl.mts +250 -0
  30. package/core/src/nako_gen.mjs +1648 -0
  31. package/core/src/nako_gen.mts +1719 -0
  32. package/core/src/nako_gen_async.mjs +1659 -0
  33. package/core/src/nako_gen_async.mts +1732 -0
  34. package/core/src/nako_global.mjs +107 -0
  35. package/core/src/nako_global.mts +138 -0
  36. package/core/src/nako_indent.mjs +445 -0
  37. package/core/src/nako_indent.mts +492 -0
  38. package/core/src/nako_josi_list.mjs +38 -0
  39. package/core/src/nako_josi_list.mts +45 -0
  40. package/core/src/nako_lex_rules.mjs +253 -0
  41. package/core/src/nako_lex_rules.mts +260 -0
  42. package/core/src/nako_lexer.mjs +609 -0
  43. package/core/src/nako_lexer.mts +612 -0
  44. package/core/src/nako_logger.mjs +199 -0
  45. package/core/src/nako_logger.mts +232 -0
  46. package/core/src/nako_parser3.mjs +2439 -0
  47. package/core/src/nako_parser3.mts +2195 -0
  48. package/core/src/nako_parser_base.mjs +370 -0
  49. package/core/src/nako_parser_base.mts +370 -0
  50. package/core/src/nako_parser_const.mjs +37 -0
  51. package/core/src/nako_parser_const.mts +37 -0
  52. package/core/src/nako_prepare.mjs +304 -0
  53. package/core/src/nako_prepare.mts +315 -0
  54. package/core/src/nako_reserved_words.mjs +38 -0
  55. package/core/src/nako_reserved_words.mts +38 -0
  56. package/core/src/nako_source_mapping.mjs +207 -0
  57. package/core/src/nako_source_mapping.mts +262 -0
  58. package/core/src/nako_test.mjs +37 -0
  59. package/core/src/nako_types.mjs +25 -0
  60. package/core/src/nako_types.mts +151 -0
  61. package/core/src/plugin_csv.mjs +49 -0
  62. package/core/src/plugin_csv.mts +50 -0
  63. package/core/src/plugin_math.mjs +328 -0
  64. package/core/src/plugin_math.mts +326 -0
  65. package/core/src/plugin_promise.mjs +91 -0
  66. package/core/src/plugin_promise.mts +91 -0
  67. package/core/src/plugin_system.mjs +2832 -0
  68. package/core/src/plugin_system.mts +2690 -0
  69. package/core/src/plugin_test.mjs +34 -0
  70. package/core/src/plugin_test.mts +34 -0
  71. package/core/test/array_test.mjs +34 -0
  72. package/core/test/basic_test.mjs +344 -0
  73. package/core/test/calc_test.mjs +140 -0
  74. package/core/test/core_module_test.mjs +23 -0
  75. package/core/test/debug_test.mjs +16 -0
  76. package/core/test/dncl_test.mjs +94 -0
  77. package/core/test/error_message_test.mjs +210 -0
  78. package/core/test/error_test.mjs +16 -0
  79. package/core/test/flow_test.mjs +373 -0
  80. package/core/test/func_call.mjs +160 -0
  81. package/core/test/func_test.mjs +149 -0
  82. package/core/test/indent_test.mjs +364 -0
  83. package/core/test/lex_test.mjs +168 -0
  84. package/core/test/literal_test.mjs +73 -0
  85. package/core/test/nako_lexer_test.mjs +35 -0
  86. package/core/test/nako_logger_test.mjs +76 -0
  87. package/core/test/nako_logger_test.mts +78 -0
  88. package/core/test/plugin_csv_test.mjs +38 -0
  89. package/core/test/plugin_promise_test.mjs +18 -0
  90. package/core/test/plugin_system_test.mjs +630 -0
  91. package/core/test/prepare_test.mjs +96 -0
  92. package/core/test/re_test.mjs +22 -0
  93. package/core/test/side_effects_test.mjs +92 -0
  94. package/core/test/variable_scope_test.mjs +149 -0
  95. package/core/tsconfig.json +101 -0
  96. package/package.json +4 -2
  97. package/release/_hash.txt +12 -12
  98. package/release/_script-tags.txt +14 -14
  99. package/release/editor.js +1 -1
  100. package/release/stats.json +1 -1
  101. package/release/version.js +1 -1
  102. package/release/wnako3.js +1 -1
  103. package/src/nako_version.mjs +2 -2
  104. package/src/nako_version.mts +2 -2
  105. package/test/async/async_basic_test.mjs +3 -3
@@ -0,0 +1,373 @@
1
+ import assert from 'assert'
2
+ import { NakoCompiler } from '../src/nako3.mjs'
3
+
4
+ describe('flow_test', async () => {
5
+ // nako.logger.addListener('trace', ({ browserConsole }) => { console.log(...browserConsole) })
6
+ const cmp = async (/** @type {string} */ code, /** @type {string} */ res) => {
7
+ const nako = new NakoCompiler()
8
+ nako.logger.debug('code=' + code)
9
+ assert.strictEqual((await nako.runAsync(code)).log, res)
10
+ }
11
+ it('もし', async () => {
12
+ await cmp('もし3>1ならば「あ」と表示。', 'あ')
13
+ await cmp('もし3<1ならば「あ」と表示。違えば「い」と表示。', 'い')
14
+ })
15
+ it('もし - AがBならば', async () => {
16
+ await cmp('もし3が3ならば\n「OK」と表示。\n違えば\n「NG」と表示。\nここまで\n', 'OK')
17
+ })
18
+ it('もし - ネスト', async () => {
19
+ await cmp('A=5\n' +
20
+ 'もしAが3以上ならば\n' +
21
+ '  もしA=5ならば\n' +
22
+ '    「OK」と表示。\n' +
23
+ '  違えば\n' +
24
+ '    「NG」と表示。\n' +
25
+ '  ここまで。\n' +
26
+ '違えば\n' +
27
+ '  「NG」と表示。\n' +
28
+ 'ここまで。\n', 'OK')
29
+ await cmp('A=1\n' +
30
+ 'もしAが3以上ならば\n' +
31
+ '  もしA=5ならば\n' +
32
+ '    「NG」と表示。\n' +
33
+ '  違えば\n' +
34
+ '    「NG」と表示。\n' +
35
+ '  ここまで。\n' +
36
+ '違えば\n' +
37
+ '  「OK」と表示。\n' +
38
+ 'ここまで。\n', 'OK')
39
+ })
40
+ it('もし - ネスト - 違えばの一致', async () => {
41
+ await cmp('A=2\n' +
42
+ 'もしAが3以上ならば\n' +
43
+ '  もしA=5ならば\n' +
44
+ '    「NG」と表示。\n' +
45
+ '  ここまで\n' +
46
+ '違えば\n' +
47
+ '  「OK」と表示。\n' +
48
+ 'ここまで。\n' +
49
+ '', 'OK')
50
+ })
51
+ it('違えばもし', async () => {
52
+ // 「違えば」の次がeolではないときfalse_blockが単文扱いになり「ここまで」が不要。
53
+ await cmp('もし0ならば\n' +
54
+ ' 「NG」を表示\n' +
55
+ '違えばもし0ならば\n' +
56
+ ' 「NG」を表示\n' +
57
+ '違えばもし1ならば\n' +
58
+ ' 「OK」を表示\n' +
59
+ '違えば\n' +
60
+ ' 「NG」を表示\n' +
61
+ 'ここまで\n', 'OK')
62
+
63
+ await cmp('もし0ならば\n' +
64
+ ' 「NG」を表示\n' +
65
+ '違えば、もし0ならば\n' +
66
+ ' 「NG」を表示\n' +
67
+ '違えば、もし1ならば\n' +
68
+ ' 「OK」を表示\n' +
69
+ '違えば\n' +
70
+ ' 「NG」を表示\n' +
71
+ 'ここまで\n', 'OK')
72
+ })
73
+ it('回', async () => {
74
+ await cmp('3回「あ」と表示。', 'あ\nあ\nあ')
75
+ await cmp('A=3;(A)回、Aを表示。', '3\n3\n3')
76
+ })
77
+ it('回、ここから', async () => {
78
+ await cmp('A=3;(A)回、ここから\nAを表示。\nここまで\n', '3\n3\n3')
79
+ await cmp('A=3;(A)回ここから\nAを表示。\nここまで\n', '3\n3\n3')
80
+ })
81
+ it('回、繰り返す(#924)', async () => {
82
+ await cmp('A=3;(A)回、繰り返す\nAを表示。\nここまで\n', '3\n3\n3')
83
+ await cmp('A=3;(A)回ここから、繰り返す\nAを表示。\nここまで\n', '3\n3\n3')
84
+ })
85
+ it('回繰り返す(#924)', async () => {
86
+ await cmp('A=3;(A)回繰り返す\nAを表示。\nここまで\n', '3\n3\n3')
87
+ await cmp('A=3;(A)回繰り返す、ここから\nAを表示。\nここまで\n', '3\n3\n3')
88
+ })
89
+ it('回 - 「それ」の自動挿入', async () => {
90
+ await cmp('1と2を足す\n回\n1を表示\nここまで', '1\n1\n1')
91
+ })
92
+ it('の間', async () => {
93
+ await cmp('N=3;\n(N>0)の間\nNを表示\nN=N-1\nここまで', '3\n2\n1')
94
+ })
95
+ it('の間、ここから', async () => {
96
+ await cmp('N=3;\n(N>0)の間、ここから\nNを表示\nN=N-1\nここまで', '3\n2\n1')
97
+ await cmp('N=3;\n(N>0)の間ここから\nNを表示\nN=N-1\nここまで', '3\n2\n1')
98
+ })
99
+ it('の間、繰り返す #927', async () => {
100
+ await cmp('N=3;\n(N>0)の間、繰り返す\nNを表示\nN=N-1\nここまで', '3\n2\n1')
101
+ await cmp('N=3;\n(N>0)の間繰り返す\nNを表示\nN=N-1\nここまで', '3\n2\n1')
102
+ })
103
+ it('一致する間', async () => {
104
+ await cmp('●(AとBが)超一致するとは\n' +
105
+ ' それはAとBが等しい\n' +
106
+ 'ここまで\n' +
107
+ 'a=1\n' +
108
+ 'i=0\n' +
109
+ 'aと1が超一致する間\n' +
110
+ ' iを表示\n' +
111
+ ' i=i+1\n' +
112
+ ' もしiが3以上ならば\n' +
113
+ ' a=0\n' +
114
+ ' ここまで\n' +
115
+ 'ここまで',
116
+ // ---
117
+ '0\n1\n2')
118
+ })
119
+ it('等しい間', async () => {
120
+ await cmp('a=1\n' +
121
+ 'i=0\n' +
122
+ 'aと1が等しい間\n' +
123
+ ' iを表示\n' +
124
+ ' i=i+1\n' +
125
+ ' もしiが3以上ならば\n' +
126
+ ' a=0\n' +
127
+ ' ここまで\n' +
128
+ 'ここまで',
129
+ // ---
130
+ '0\n1\n2')
131
+ })
132
+ it('未満の間', async () => {
133
+ await cmp('i=0\n' +
134
+ 'iが3未満の間\n' +
135
+ ' iを表示\n' +
136
+ ' i=i+1\n' +
137
+ 'ここまで',
138
+ // ---
139
+ '0\n1\n2')
140
+ })
141
+ it('超えの間', async () => {
142
+ await cmp('i=0' +
143
+ 'iが-3超えの間\n' +
144
+ ' iを表示\n' +
145
+ ' i=i-1\n' +
146
+ 'ここまで',
147
+ // ---
148
+ '0\n-1\n-2')
149
+ })
150
+ it('範囲内の間', async () => {
151
+ await cmp('i=0' +
152
+ 'iが-3から3の範囲内の間\n' +
153
+ ' iを表示\n' +
154
+ ' i=i+1\n' +
155
+ 'ここまで',
156
+ // ---
157
+ '0\n1\n2\n3')
158
+ })
159
+ it('繰り返す', async () => {
160
+ await cmp('Nを1から3まで繰り返す\nNを表示\nここまで', '1\n2\n3')
161
+ await cmp('Nを1から3まで繰り返す\n  Nを表示\nここまで', '1\n2\n3')
162
+ })
163
+ it('繰り返す2', async () => {
164
+ await cmp('1から3まで繰り返す\nそれを表示\nここまで', '1\n2\n3')
165
+ })
166
+ it('連続計算', async () => {
167
+ await cmp('3に5を足してNに代入;Nを表示', '8')
168
+ await cmp('3に5を足して2を掛けて表示', '16')
169
+ })
170
+ it('もし-日本語による比較', async () => {
171
+ await cmp('もし3が3と等しいならば「OK」と表示。', 'OK')
172
+ await cmp('もし(3+2)が5と等しいならば「OK」と表示。', 'OK')
173
+ await cmp('もし(3+2)が1以上ならば「OK」と表示。', 'OK')
174
+ await cmp('もし3が5未満ならば「OK」と表示。', 'OK')
175
+ await cmp('もし(3+10)が(5+10)以下ならば「OK」と表示。', 'OK')
176
+ })
177
+ it('もし--一行文。違えば', async () => {
178
+ await cmp('もし(3+10)が5以下ならば「ng」と表示。違えば「ok」と表示。', 'ok')
179
+ })
180
+ it('もし-しなければ', async () => {
181
+ await cmp('もし{ "a": 30 }に「b」がハッシュキー存在しなければ\n「ok」と表示\nここまで', 'ok')
182
+ await cmp('もし1と2が等しくなければ\n「ok」と表示\nここまで', 'ok')
183
+ })
184
+ it('回-break', async () => {
185
+ await cmp('3回\n\'a\'と表示。もし(回数=2)ならば、抜ける;\n;ここまで;', 'a\na')
186
+ await cmp('3回\n\'a\'と表示。もし、回数が2ならば、抜ける;\n;ここまで;', 'a\na')
187
+ })
188
+ it('反復 - 配列', async () => {
189
+ await cmp('[1,2,3]を反復\n対象を表示\nここまで\n', '1\n2\n3')
190
+ })
191
+ it('反復 - オブジェクト', async () => {
192
+ await cmp('{\'a\':1,\'b\':2,\'c\':3}を反復\n対象を表示\nここまで\n', '1\n2\n3')
193
+ await cmp('{\'a\':1,\'b\':2,\'c\':3}を反復\n対象キーを表示\nここまで\n', 'a\nb\nc')
194
+ })
195
+ it('反復 - 変数付き', async () => {
196
+ await cmp('A=[1,2,3];NでAを反復\nNを表示\nここまで\n', '1\n2\n3')
197
+ await cmp('Nで[1,2,3]を反復\nNを表示\nここまで\n', '1\n2\n3')
198
+ })
199
+ it('反復2 - 変数付き', async () => {
200
+ await cmp('A=[[3,30],[1,10],[2,20]];NでAを反復\nN[1]を表示\nここまで\n', '30\n10\n20')
201
+ })
202
+ it('反復 - prototypeを無視', async () => {
203
+ await cmp('f=『function F(){}; F.prototype.foo = 20; const f = new F(); f.p1 = 10; f』をJS実行。fを反復して表示', '10')
204
+ })
205
+ it('ここから反復', async () => {
206
+ await cmp('それは[1,2,3];ここから反復\n表示\nここまで\n', '1\n2\n3')
207
+ })
208
+ it('ここから繰り返し', async () => {
209
+ await cmp('ここから1から3まで繰り返し\n表示\nここまで\n', '1\n2\n3')
210
+ })
211
+ it('ここから3回', async () => {
212
+ await cmp('ここから3回\n表示\nここまで\n', '1\n2\n3')
213
+ })
214
+ it('不等号', async () => {
215
+ await cmp('もし、5≧5ならば、「あ」と表示。', 'あ')
216
+ await cmp('もし、5≧3ならば、「あ」と表示。', 'あ')
217
+ await cmp('もし、5≦5ならば、「あ」と表示。', 'あ')
218
+ await cmp('もし、3≦5ならば、「あ」と表示。', 'あ')
219
+ await cmp('もし、5=5ならば、「あ」と表示。', 'あ')
220
+ await cmp('もし、3≠5ならば、「あ」と表示。', 'あ')
221
+ })
222
+ it('繰り返しのネスト', async () => {
223
+ await cmp('C=0;Iを0から3まで繰り返す\nJを0から3まで繰り返す\nC=C+1;ここまで;ここまで;Cを表示', '16')
224
+ })
225
+ it('繰り返し:AからBまででA>Bの時', async () => {
226
+ await cmp('Iを3から0まで繰り返す;Iを表示;ここまで', '3\n2\n1\n0')
227
+ await cmp('Iを11から9まで繰り返す;Iを表示;ここまで', '11\n10\n9')
228
+ })
229
+ it('繰り返し:AからBまででA>Bの時', async () => {
230
+ await cmp('Iを3から0まで繰り返す;Iを表示;ここまで', '3\n2\n1\n0')
231
+ await cmp('Iを11から9まで繰り返す;Iを表示;ここまで', '11\n10\n9')
232
+ })
233
+ it('もし、と戻るの組み合わせ', async () => {
234
+ await cmp('●テスト処理\n' +
235
+ '  「あ」と表示\n' +
236
+ '  もし、3=3ならば、戻る。\n' +
237
+ '  「ここには来ない」と表示\n' +
238
+ 'ここまで\n' +
239
+ 'テスト処理。', 'あ')
240
+ await cmp('●(Sを)テスト処理\n' +
241
+ '  Sを大文字変換して表示。\n' +
242
+ '  もし、そうならば、戻る。\n' +
243
+ '  「ここには来ない」と表示\n' +
244
+ 'ここまで\n' +
245
+ '「a」をテスト処理。', 'A')
246
+ })
247
+ it('もしと抜けるの組み合わせ', async () => {
248
+ await cmp('Iを1から3まで繰り返す\n' +
249
+ '  「あ」と表示\n' +
250
+ '  もし、I=2ならば、抜ける。\n' +
251
+ '  「い」と表示\n' +
252
+ 'ここまで\n', 'あ\nい\nあ')
253
+ await cmp('Iを1から3まで繰り返す\n' +
254
+ '  2回、「あ」と表示。\n' +
255
+ '  もし、I=2ならば、抜ける。\n' +
256
+ '  「い」と表示\n' +
257
+ 'ここまで\n', 'あ\nあ\nい\nあ\nあ')
258
+ await cmp('Iを1から3まで繰り返す\n' +
259
+ '  「あ」と表示\n' +
260
+ '  もし、I=2ならば、「う」と表示して、抜ける。\n' +
261
+ '  「い」と表示\n' +
262
+ 'ここまで\n', 'あ\nい\nあ\nう')
263
+ })
264
+ it('もし文のエラー(#378)', async () => {
265
+ await cmp('●AAAとは\n' +
266
+ '  列を1から3まで繰り返す。\n' +
267
+ '   列を表示。' +
268
+ '    もし、列=2ならば、「*」と表示。\n' +
269
+ '  ここまで。\n' +
270
+ 'ここまで\n' +
271
+ 'AAA', '1\n2\n*\n3')
272
+ })
273
+ it('条件分岐(#694)', async () => {
274
+ await cmp('2で条件分岐\n' +
275
+ ' 1ならば\n「a」と表示\nここまで\n' +
276
+ ' 2ならば\n「b」と表示\nここまで\n' +
277
+ ' 3ならば\n「c」と表示\nここまで\n' +
278
+ ' 違えば\n「d」と表示\nここまで\n' +
279
+ 'ここまで\n',
280
+ 'b')
281
+ await cmp('3で条件分岐\n' +
282
+ ' 1ならば\n「a」と表示\nここまで\n' +
283
+ ' 2ならば\n「b」と表示\nここまで\n' +
284
+ ' 3ならば\n「c」と表示\nここまで\n' +
285
+ ' 違えば\n「d」と表示\nここまで\n' +
286
+ 'ここまで\n',
287
+ 'c')
288
+ await cmp('5で条件分岐\n' +
289
+ ' 1ならば\n「a」と表示\nここまで\n' +
290
+ ' 2ならば\n「b」と表示\nここまで\n' +
291
+ ' 3ならば\n「c」と表示\nここまで\n' +
292
+ ' 違えば\n「d」と表示\nここまで\n' +
293
+ 'ここまで\n',
294
+ 'd')
295
+ })
296
+ it('条件分岐で違えばを省略', async () => {
297
+ await cmp('2で条件分岐\n' +
298
+ ' 1ならば\n「a」と表示\nここまで\n' +
299
+ ' 2ならば\n「b」と表示\nここまで\n' +
300
+ ' 3ならば\n「c」と表示\nここまで\n' +
301
+ 'ここまで\n',
302
+ 'b')
303
+ await cmp('5で条件分岐\n' +
304
+ ' 1ならば\n「a」と表示\nここまで\n' +
305
+ ' 2ならば\n「b」と表示\nここまで\n' +
306
+ ' 3ならば\n「c」と表示\nここまで\n' +
307
+ 'ここまで\n',
308
+ '')
309
+ })
310
+ it('条件分岐で違えばの後にカンマがあってもエラーにならない #942', async () => {
311
+ await cmp('A=0;2で条件分岐\n' +
312
+ ' 1ならば、A=A+1\nここまで\n' +
313
+ ' 2ならば、A=A+2\nここまで\n' +
314
+ ' 3ならば、A=A+3\nここまで\n' +
315
+ ' 違えば、A=A+10\nここまで\n' +
316
+ 'ここまで\nAを表示',
317
+ '2')
318
+ })
319
+ it('N回をN|回に分ける', async () => {
320
+ await cmp('S="";N=3;N回、S=S&"a";Sを表示。', 'aaa')
321
+ await cmp('S="";N=3;N回\nS=S&"a";💧;Sを表示。', 'aaa')
322
+ })
323
+ it('「、」と「,」の違いが分かりづらい #877', async () => {
324
+ await cmp('もし,0ならば,\n' +
325
+ ' 「NG」を表示\n' +
326
+ '違えば,もし,0ならば\n' +
327
+ ' 「NG」を表示\n' +
328
+ '違えば,もし,1ならば\n' +
329
+ ' 「OK」を表示\n' +
330
+ '違えば,\n' +
331
+ ' 「NG」を表示\n' +
332
+ 'ここまで\n', 'OK')
333
+ await cmp('S="";[1,2,3]を,反復,\n' +
334
+ ' S=S&対象\n' +
335
+ 'ここまで。Sを表示。\n', '123')
336
+ await cmp('S="";[1,2,3]を,反復,ここから,\n' +
337
+ ' S=S&対象\n' +
338
+ 'ここまで。Sを表示。\n', '123')
339
+ })
340
+ it('「。。。」=「ここまで」#925', async () => {
341
+ await cmp('S="";3回;S=S&"a";;;Sを表示。', 'aaa')
342
+ await cmp('A=0;3回\nA=A+1;;;Aを表示。', '3')
343
+ await cmp(
344
+ 'A=0;3回\n' +
345
+ ' A=A+1;\n' +
346
+ ' A=A+1;\n' +
347
+ '。。。;Aを表示。', '6')
348
+ await cmp(
349
+ 'S=「」。3回\n' +
350
+ ' S=S&「a」\n' +
351
+ ' S=S&「b」。。。\n' +
352
+ 'Sを表示。\n', 'ababab')
353
+ })
354
+ it('「或いは」「あるいは」を追加#987', async () => {
355
+ await cmp('A=3;もし、A=3或いはA=5あるいはA=7ならば「OK」と表示。違えば「NG」と表示。', 'OK')
356
+ await cmp('A=3;もし、A=5あるいはA=3ならば「OK」と表示。違えば「NG」と表示。', 'OK')
357
+ await cmp('A=空;B=3;もし(A=空)あるいは(B=空)ならば、"OK"と表示;違えば「NG」と表示。', 'OK')
358
+ })
359
+ it('「増繰り返す」「減繰り返す」を追加#1140', async () => {
360
+ await cmp('Nを0から4まで2ずつ増やし繰り返す\nNを表示\nここまで\n', '0\n2\n4')
361
+ await cmp('A=2;Nを0から4までAずつ増やし繰り返す\nNを表示\nここまで\n', '0\n2\n4')
362
+ await cmp('Nを4から0まで2ずつ減らし繰り返す\nNを表示\nここまで\n', '4\n2\n0')
363
+ })
364
+ it('「増やして繰り返す」「減らして繰り返す」を追加#1140', async () => {
365
+ // トークンをスタックからポップして処理するので確認
366
+ await cmp('Nを0から4まで2ずつ増やして繰り返す\nNを表示\nここまで\n', '0\n2\n4')
367
+ await cmp('A=2;Nを0から4までAずつ増やして繰り返す\nNを表示\nここまで\n', '0\n2\n4')
368
+ await cmp('Nを4から0まで2ずつ減らして繰り返す\nNを表示\nここまで\n', '4\n2\n0')
369
+ })
370
+ it('ならばの直前に空白があるとエラー(#1141)', async () => {
371
+ await cmp('A=30。もし、A>5 ならば、「OK」と表示。', 'OK')
372
+ })
373
+ })
@@ -0,0 +1,160 @@
1
+ /* eslint-disable no-undef */
2
+ import assert from 'assert'
3
+ import { NakoCompiler } from '../src/nako3.mjs'
4
+ import { NakoSyntaxError } from '../src/nako_errors.mjs'
5
+
6
+ describe('関数呼び出しテスト', async () => {
7
+ const cmp = async (/** @type {string} */ code, /** @type {string} */ res) => {
8
+ const nako = new NakoCompiler()
9
+ nako.logger.debug('code=' + code)
10
+ assert.strictEqual((await nako.runAsync(code)).log, res)
11
+ }
12
+ const cmd = (/** @type {string} */ code) => {
13
+ const nako = new NakoCompiler()
14
+ nako.logger.debug('code=' + code)
15
+ nako.run(code)
16
+ }
17
+ // --- test ---
18
+ it('関数式の呼び出し - 足す(2,3)を表示。', async () => {
19
+ await cmp('足す(2,3)を表示。', '5')
20
+ })
21
+ it('四則演算を連文で', async () => {
22
+ await cmp('1に2を足して3を掛けて3で割って2を引いて表示', '1')
23
+ })
24
+ it('「そう」のテスト', async () => {
25
+ await cmp('3が1以上。もしそうならば「真」と表示。', '真')
26
+ })
27
+ it('後方で定義した関数を前方で使う1', async () => {
28
+ await cmp('HOGE(3,4)を表示;●(A,B)HOGEとは;それはA+B;ここまで;', '7')
29
+ await cmp('「姫」と「殿」が出会って表示;●(AとBが)出会うとは;それはA&B;ここまで;', '姫殿')
30
+ })
31
+ it('後方で定義した関数を前方で使う2', async () => {
32
+ await cmp('Nとは変数=30;HOGE(3,4)を表示;●(A,B)HOGEとは;それはA+B+N;ここまで;', '37')
33
+ })
34
+ it('代入と表示', async () => {
35
+ await cmp('A=今日;もし(今日=A)ならば「1」と表示', '1')
36
+ })
37
+ it('代入1', async () => {
38
+ await cmp('A=今日の曜日番号取得;B=(今日)の曜日番号取得;もしA=Bならば「等しい」を表示。', '等しい')
39
+ })
40
+ it('代入2', async () => {
41
+ await cmp('Aは、今日の曜日番号取得;Bは、(今日)の曜日番号取得;もしA=Bならば「等しい」を表示。', '等しい')
42
+ })
43
+ it('代入3', async () => {
44
+ await cmp('A=(今日の曜日番号取得)+1;B=((今日)の曜日番号取得)+1;もしA=Bならば「等しい」を表示。', '等しい')
45
+ })
46
+ it('配列への代入', async () => {
47
+ await cmp('値段は空配列。値段[0]に3000を代入。値段[0]を表示。', '3000')
48
+ })
49
+ it('**には**構文 - 基本', async () => {
50
+ await cmp('実行には;「あ」と表示;ここまで', 'あ')
51
+ })
52
+ it('**には**構文 - 配列カスタムソート', async () => {
53
+ await cmp('A=[5,1,3];Aを配列カスタムソートするには(a,b);それはb-a;ここまで;Aを「:」で配列結合して表示', '5:3:1')
54
+ })
55
+ it('階乗計算 - 再帰', async () => {
56
+ await cmp('●(VをAのBで)階乗計算とは;' +
57
+ 'もし、Bが0以下ならば、Vを戻す。;(V*A)をAの(B-1)で階乗計算して戻す。' +
58
+ 'ここまで。;1を2の3で階乗計算して表示。', '8')
59
+ })
60
+ it('連続文後の代入', async () => {
61
+ await cmp('「2017/09/01T00:00:99」の「T」を「 」に置換して「 」まで切り取り、対象日に代入。対象日を表示。', '2017/09/01')
62
+ })
63
+ it('連続文後の=代入', async () => {
64
+ await cmp('対象日=「2017/09/01T00:00:99」の「T」を「 」に置換して「 」まで切り取る。対象日を表示。', '2017/09/01')
65
+ })
66
+ it('関数の引数に関数呼び出しがある場合', async () => {
67
+ await cmp('A=「ab」;「abcd」の1から(Aの文字数)だけ文字削除。それを表示。', 'cd')
68
+ })
69
+ it('配列カスタムソートの基本的な使い方例', async () => {
70
+ await cmp('●MYSORT(a,b)とは\n' +
71
+ '(INT(a) - INT(b))で戻る。\n' +
72
+ 'ここまで。\n' +
73
+ 'ARY=[8,3,4];' +
74
+ '「MYSORT」でARYを配列カスタムソートしてJSONエンコードして表示', '[3,4,8]')
75
+ })
76
+ it('引数の順番を入れ替えて呼び出す(#342)その1', async () => {
77
+ await cmp('『abc』の『a』を「*」に置換。表示', '*bc')
78
+ await cmp('『a』を「*」に『abc』の置換。表示', '*bc')
79
+ await cmp('「*」へ『a』から『abc』の置換。表示', '*bc')
80
+ await cmp('「abcdefg」の1から3だけ文字削除して表示。', 'defg')
81
+ await cmp('「abcdefg」の1から3を文字削除して表示。', 'defg')
82
+ await cmp('1から3を「abcdefg」の文字削除して表示。', 'defg')
83
+ await cmp('3を「abcdefg」の1から文字削除して表示。', 'defg')
84
+ await cmp('3だけ「abcdefg」の1から文字削除して表示。', 'defg')
85
+ })
86
+ it('引数の順番を入れ替えて呼び出す(#342)その2', async () => {
87
+ await cmp('[8,3,4]の配列カスタムソートには(a,b)\nそれは(a - b)\nここまで。それをJSONエンコードして表示', '[3,4,8]')
88
+ await cmp('[8,3,4]を配列カスタムソートには(a,b)\nそれは(a - b)\nここまで。それをJSONエンコードして表示', '[3,4,8]')
89
+ await cmp('[8,3,4]の配列カスタムソートには(a,b)\nそれは(INT(a) - INT(b))\nここまで。それをJSONエンコードして表示', '[3,4,8]')
90
+ })
91
+ it('引数の順番を入れ替えて呼び出す(#342)その3', async () => {
92
+ await cmp('ARY=[8,3,4];' +
93
+ 'ARYの配列カスタムソートには(a,b)\n' +
94
+ 'aと255のXORをAに代入。bと255のXORをBに代入。' +
95
+ 'それは(INT(a) - INT(b))\n' +
96
+ 'ここまで。\n' +
97
+ 'ARYをJSONエンコードして表示', '[3,4,8]')
98
+ })
99
+ it('可変長引数 #729', async () => { // 経緯 #501 → #729
100
+ await cmp('連続加算(1,2,3)を表示。', '6')
101
+ await cmp('1と2と3を連続加算して表示。', '6')
102
+ await cmp('1に2と3を連続加算して表示。', '6')
103
+ })
104
+ // ---
105
+ it('関数呼び出し演算子に変更(1) #891', async () => {
106
+ await cmp('表示←3', '3')
107
+ await cmp('表示←3を', '3')
108
+ await cmp('表示←INT←3.14', '3')
109
+ await cmp('足す←2に3を;それを表示;', '5')
110
+ await cmp('割る←10を2で;それを表示;', '5')
111
+ await cmp('割る<--2で10を;それを表示', '5')
112
+ })
113
+ it('関数呼び出し演算子に変更(2) #891', async () => {
114
+ await cmp('A=(割る<--10を2で)+2;Aを表示;', '7')
115
+ await cmp('(割る←10を2で)を表示;', '5')
116
+ await cmp('割る<--2で(割る←100を10で)を;それを表示', '5')
117
+ await cmp('(割る←100を10で)を2で割って表示', '5')
118
+ })
119
+ it('関数呼び出し演算子に変更(ユーザー関数) #891', async () => {
120
+ await cmp('●(Aを)AAA;それはA*2;ここまで;AAA←30;それを表示', '60')
121
+ await cmp('●(AをBで)AAA;それはA/B;ここまで;AAA←30を3で;それを表示', '10')
122
+ })
123
+ it('エラー/関数の呼び出し演算子 #891/引数がない関数', async () => {
124
+ const funcName = 'AAA'
125
+ assert.throws(
126
+ () => cmd(`●${funcName};それは5;ここまで;${funcName}←`),
127
+ NakoSyntaxError, `引数がない関数『${funcName}』を関数呼び出し演算子で呼び出すことはできません。`
128
+ )
129
+ })
130
+ it('エラー/関数の呼び出し演算子 #891/引数が異なる', async () => {
131
+ const funcName = 'テスト'
132
+ assert.throws(
133
+ () => cmd(`●${funcName}(aとbを);それはa*b;ここまで;${funcName}<--8と`),
134
+ NakoSyntaxError, `関数『${funcName}』呼び出しで引数の数(1)が定義(2)と違います。`
135
+ )
136
+ })
137
+ it('ローカル変数が解決できない1 #1210', async () => {
138
+ await cmp('S=「あいうえお」;A=「かきくけこ」;AをFテスト;●(Sを)Fテストとは;Sを表示;ここまで', 'かきくけこ')
139
+ })
140
+ it('ローカル変数が解決できない2 #1210', async () => {
141
+ await cmp('S=「あいうえお」;Fテスト;●Fテストとは;Sとは変数=30;Sを表示;ここまで', '30')
142
+ await cmp('S=「あいうえお」;Fテスト;Sを表示;●Fテストとは;Sとは変数=30;ここまで', 'あいうえお')
143
+ await cmp('A=10;B=20;Aを三倍処理して表示;●(Bを)三倍処理とは;Aとは変数=3;A*Bを戻す;ここまで', '30')
144
+ })
145
+ it('ローカル変数の配列が解決できない2 #1213', async () => {
146
+ await cmp(`
147
+ 変数 A=空配列。
148
+ B=[10,20,30]
149
+ BでAAテスト
150
+ ●(Aで)AAテスト
151
+ もし(A[0]=10)かつ(A[1]=20)ならば「OK」を表示。
152
+ 違えば,「NG」を表示。# (えっ!)
153
+ ここまで。
154
+ `, 'OK')
155
+ })
156
+ it('ひらがなだけの関数名がエラーになる #1214', async () => {
157
+ await cmp('あ。;●あとは;「A」と表示;ここまで', 'A')
158
+ await cmp('おくら。;●おくらとは;「O」と表示;ここまで', 'O')
159
+ })
160
+ })