nadesiko3 3.7.21 → 3.7.23
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/README.md +20 -1
- package/batch/command.txt +370 -334
- package/batch/generate_command_list.mjs +102 -0
- package/batch/jsplugin2text.nako3 +1 -1
- package/batch/pickup_command.nako3 +12 -0
- package/batch/search_command.mjs +34 -0
- package/batch/search_command.nako3 +430 -0
- package/core/command/snako.mts +5 -1
- package/core/deno/snako.ts +5 -1
- package/core/package-lock.json +382 -21
- package/core/package.json +7 -4
- package/core/sample/algorithms/README.md +43 -0
- package/core/sample/algorithms/graph/dijkstra.nako3 +47 -0
- package/core/sample/algorithms/graph/kruskal.nako3 +69 -0
- package/core/sample/algorithms/math/euclidean_gcd.nako3 +15 -0
- package/core/sample/algorithms/math/sieve_of_eratosthenes.nako3 +26 -0
- package/core/sample/algorithms/search/binary_search.nako3 +17 -0
- package/core/sample/algorithms/search/breadth_first_search.nako3 +33 -0
- package/core/sample/algorithms/search/depth_first_search.nako3 +25 -0
- package/core/sample/algorithms/sort/heap_sort.nako3 +37 -0
- package/core/sample/algorithms/sort/insertion_sort.nako3 +18 -0
- package/core/sample/algorithms/sort/merge_sort.nako3 +40 -0
- package/core/sample/algorithms/sort/quick_sort.nako3 +36 -0
- package/core/sample/algorithms/string/knuth_morris_pratt.nako3 +50 -0
- package/core/sample/algorithms/string/run_length_encoding.nako3 +25 -0
- package/core/src/nako3.mts +178 -614
- package/core/src/nako_basic_plugins.mts +39 -0
- package/core/src/nako_core_version.mts +2 -2
- package/core/src/nako_csv.mts +0 -1
- package/core/src/nako_event.mts +49 -0
- package/core/src/nako_gen.mts +320 -209
- package/core/src/nako_global.mts +18 -0
- package/core/src/nako_indent_inline.mts +2 -2
- package/core/src/nako_lex_rules.mts +1 -1
- package/core/src/nako_parser3.mts +111 -166
- package/core/src/nako_parser_async.mts +165 -0
- package/core/src/nako_parser_base.mts +4 -55
- package/core/src/nako_parser_message.mts +105 -0
- package/core/src/nako_parser_operator.mts +93 -0
- package/core/src/nako_plugin_manager.mts +260 -0
- package/core/src/nako_require.mts +292 -0
- package/core/src/nako_runner.mts +208 -0
- package/core/src/nako_tokenizer.mts +221 -0
- package/core/src/plugin_csv.mts +1 -1
- package/core/src/plugin_system.mts +34 -3259
- package/core/src/plugin_system_array.mts +699 -0
- package/core/src/plugin_system_datetime.mts +368 -0
- package/core/src/plugin_system_debug.mts +403 -0
- package/core/src/plugin_system_dict.mts +85 -0
- package/core/src/plugin_system_json.mts +73 -0
- package/core/src/plugin_system_math.mts +383 -0
- package/core/src/plugin_system_regexp.mts +120 -0
- package/core/src/plugin_system_stdio.mts +86 -0
- package/core/src/plugin_system_string.mts +666 -0
- package/core/src/plugin_system_timer.mts +152 -0
- package/core/src/plugin_system_types.mts +151 -0
- package/core/src/plugin_system_url.mts +193 -0
- package/core/src/plugin_toml.mts +3 -3
- package/core/test/algorithm_samples_test.mjs +58 -0
- package/core/test/algorithms/graph/dijkstra_test.nako3 +21 -0
- package/core/test/algorithms/graph/kruskal_test.nako3 +21 -0
- package/core/test/algorithms/helper.mjs +13 -0
- package/core/test/algorithms/math/euclidean_gcd_test.nako3 +13 -0
- package/core/test/algorithms/math/sieve_of_eratosthenes_test.nako3 +10 -0
- package/core/test/algorithms/search/binary_search_test.nako3 +15 -0
- package/core/test/algorithms/search/breadth_first_search_test.nako3 +13 -0
- package/core/test/algorithms/search/depth_first_search_test.nako3 +13 -0
- package/core/test/algorithms/sort/heap_sort_test.nako3 +13 -0
- package/core/test/algorithms/sort/insertion_sort_test.nako3 +13 -0
- package/core/test/algorithms/sort/merge_sort_test.nako3 +18 -0
- package/core/test/algorithms/sort/quick_sort_test.nako3 +34 -0
- package/core/test/algorithms/string/knuth_morris_pratt_test.nako3 +16 -0
- package/core/test/algorithms/string/run_length_encoding_test.nako3 +13 -0
- package/core/test/array_test.mjs +3 -0
- package/core/test/fixtures/README.md +39 -0
- package/core/test/fixtures/make_parser_ast_golden.mjs +31 -0
- package/core/test/fixtures/parser_ast_golden.json +8027 -0
- package/core/test/fixtures/parser_corpus.mjs +120 -0
- package/core/test/func_call.mjs +18 -0
- package/core/test/func_test.mjs +28 -0
- package/core/test/indent_test.mjs +6 -0
- package/core/test/nako_basic_plugins_test.mjs +44 -0
- package/core/test/nako_event_test.mjs +127 -0
- package/core/test/nako_gen_perf_test.mjs +178 -0
- package/core/test/nako_parser_async_test.mjs +385 -0
- package/core/test/nako_parser_test.mjs +160 -0
- package/core/test/nako_plugin_manager_test.mjs +185 -0
- package/core/test/nako_require_test.mjs +153 -0
- package/core/test/nako_runner_test.mjs +174 -0
- package/core/test/nako_tokenizer_test.mjs +115 -0
- package/core/test/plugin_system_debug_test.mjs +138 -0
- package/core/test/plugin_system_split_test.mjs +179 -0
- package/core/test/plugin_system_test.mjs +6 -0
- package/core/tsconfig.json +0 -1
- package/demo/browsers.html +1 -1
- package/doc/SETUP.md +1 -1
- package/doc/ai-code-generation.md +136 -0
- package/doc/browsers.md +1 -1
- package/doc/command_list.json +16842 -0
- package/doc/search_command.md +222 -0
- package/doc/syntax-nako3.md +344 -0
- package/package.json +29 -26
- package/release/_hash.txt +40 -40
- package/release/_script-tags.txt +16 -16
- package/release/command.json +1 -1
- package/release/command.json.js +1 -1
- package/release/command_cnako3.json +1 -1
- package/release/command_list.json +1 -1
- package/release/edit_main.js +6 -6
- package/release/edit_main.js.map +3 -3
- package/release/editor.js +6 -6
- package/release/plugin_caniuse.js +1 -1
- package/release/plugin_caniuse.js.map +2 -2
- package/release/plugin_keigo.js.map +3 -3
- package/release/plugin_markup.js +46 -46
- package/release/plugin_markup.js.map +3 -3
- package/release/plugin_weykturtle3d.js +1 -1
- package/release/plugin_weykturtle3d.js.map +3 -3
- package/release/version.js +2 -2
- package/release/version_main.js +2 -2
- package/release/version_main.js.map +1 -1
- package/release/wnako3.js +219 -230
- package/release/wnako3.js.map +4 -4
- package/release/wnako3webworker.js +193 -204
- package/release/wnako3webworker.js.map +4 -4
- package/src/browsers.mjs +1 -1
- package/src/browsers.txt +0 -1
- package/src/cnako3mod.mjs +7 -2
- package/src/cnako3mod.mts +7 -2
- package/src/nako_version.mjs +2 -2
- package/src/nako_version.mts +2 -2
- package/src/plugin_browser_ajax.mjs +4 -4
- package/src/plugin_browser_ajax.mts +4 -4
- package/src/plugin_browser_audio.mjs +10 -10
- package/src/plugin_browser_audio.mts +10 -10
- package/src/plugin_browser_camera.mjs +4 -4
- package/src/plugin_browser_camera.mts +4 -4
- package/src/plugin_browser_canvas.mjs +2 -2
- package/src/plugin_browser_canvas.mts +2 -2
- package/src/plugin_browser_crypto.mjs +3 -3
- package/src/plugin_browser_crypto.mts +3 -3
- package/src/plugin_browser_dom_event.mjs +1 -1
- package/src/plugin_browser_dom_event.mts +1 -1
- package/src/plugin_browser_geolocation.mjs +1 -1
- package/src/plugin_browser_geolocation.mts +1 -1
- package/src/plugin_browser_hotkey.mjs +1 -1
- package/src/plugin_browser_hotkey.mts +1 -1
- package/src/plugin_browser_html.mjs +1 -1
- package/src/plugin_browser_html.mts +1 -1
- package/src/plugin_browser_location.mjs +1 -1
- package/src/plugin_browser_location.mts +1 -1
- package/src/plugin_browser_speech.mjs +1 -1
- package/src/plugin_browser_speech.mts +1 -1
- package/src/plugin_browser_storage.mjs +2 -2
- package/src/plugin_browser_storage.mts +2 -2
- package/src/plugin_httpserver.mjs +3 -3
- package/src/plugin_httpserver.mts +3 -3
- package/src/plugin_keigo.mjs +2 -2
- package/src/plugin_keigo.mts +2 -2
- package/src/plugin_node.mjs +48 -48
- package/src/plugin_node.mts +53 -53
- package/src/plugin_weykturtle3d.mjs +56 -56
- package/src/plugin_weykturtle3d.mts +56 -56
- package/src/wnako3.mjs +1 -1
- package/src/wnako3.mts +1 -1
- package/src/wnako3_editor.mjs +5 -5
- package/src/wnako3_editor.mts +5 -5
- package/src/wnako3mod.mjs +2 -2
- package/src/wnako3mod.mts +2 -2
- package/test/nako3edit/index_nako3_test.mjs +282 -0
- package/test/nako3server/index_nako3_test.mjs +239 -0
- package/test/node/ai_code_generation_guide_test.mjs +29 -0
- package/test/node/node_version_support_test.mjs +45 -0
- package/test/node/search_command_test.mjs +174 -0
- package/tools/nako3edit/AGENTS.md +23 -0
- package/tools/nako3edit/index.nako3 +404 -0
- package/tools/nako3server/AGENTS.md +23 -0
- package/tools/nako3server/index.nako3 +156 -23
- package/core/src/nako3.mjs +0 -1021
- package/core/src/nako_ast.mjs +0 -4
- package/core/src/nako_colors.mjs +0 -77
- package/core/src/nako_core_version.mjs +0 -8
- package/core/src/nako_csv.mjs +0 -193
- package/core/src/nako_errors.mjs +0 -166
- package/core/src/nako_from_dncl.mjs +0 -285
- package/core/src/nako_from_dncl2.mjs +0 -347
- package/core/src/nako_gen.mjs +0 -2500
- package/core/src/nako_global.mjs +0 -138
- package/core/src/nako_indent.mjs +0 -442
- package/core/src/nako_indent_chars.mjs +0 -29
- package/core/src/nako_indent_inline.mjs +0 -361
- package/core/src/nako_josi_list.mjs +0 -47
- package/core/src/nako_lex_rules.mjs +0 -319
- package/core/src/nako_lexer.mjs +0 -794
- package/core/src/nako_logger.mjs +0 -221
- package/core/src/nako_parser3.mjs +0 -3250
- package/core/src/nako_parser_base.mjs +0 -403
- package/core/src/nako_parser_const.mjs +0 -37
- package/core/src/nako_prepare.mjs +0 -329
- package/core/src/nako_reserved_words.mjs +0 -42
- package/core/src/nako_source_mapping.mjs +0 -207
- package/core/src/nako_test.mjs +0 -37
- package/core/src/nako_token.mjs +0 -1
- package/core/src/nako_tools.mjs +0 -53
- package/core/src/nako_types.mjs +0 -14
- package/core/src/plugin_api.mjs +0 -4
- package/core/src/plugin_csv.mjs +0 -97
- package/core/src/plugin_math.mjs +0 -352
- package/core/src/plugin_promise.mjs +0 -102
- package/core/src/plugin_system.mjs +0 -3810
- package/core/src/plugin_test.mjs +0 -52
- package/core/src/plugin_toml.mjs +0 -39
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
/**
|
|
3
|
+
* 構文解析器(NakoParser)の回帰テスト用コーパス (#2364)
|
|
4
|
+
*
|
|
5
|
+
* `core/test/nako_parser_test.mjs`(検証)と
|
|
6
|
+
* `core/test/fixtures/make_parser_ast_golden.mjs`(ゴールデン生成)の
|
|
7
|
+
* 双方から参照する。テスト本体とは分離しておかないと、
|
|
8
|
+
* 生成スクリプトを実行したときにテストまで走ってしまう。
|
|
9
|
+
*
|
|
10
|
+
* このディレクトリは `core/test/*.mjs` のテストグロブに含まれないので、
|
|
11
|
+
* テスト実行時にこのファイル自体が走ることはない。
|
|
12
|
+
*/
|
|
13
|
+
import { NakoCompiler } from '../../src/nako3.mjs'
|
|
14
|
+
|
|
15
|
+
/** ゴールデン比較で使うファイル名(AST の file フィールドに入るので固定する) */
|
|
16
|
+
export const CORPUS_FILENAME = 'main.nako3'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 構文解析のコーパス。
|
|
20
|
+
* `core/src/nako_parser3.mts` の構文規則クラスタを一通り踏むように選んである。
|
|
21
|
+
*/
|
|
22
|
+
export const PARSER_CORPUS = {
|
|
23
|
+
// --- 文の骨格 (parse / ySentenceList / ySentence / yBlock / yEOL) ---
|
|
24
|
+
'文-空行とコメント': '# コメント\n\nA=1\n',
|
|
25
|
+
'文-複数文': 'A=1\nB=2\nA+Bを表示\n',
|
|
26
|
+
'文-連文': '1に2を足して3を掛けて表示\n',
|
|
27
|
+
'文-抜ける': '3回\n抜ける\nここまで\n',
|
|
28
|
+
'文-続ける': '3回\n続ける\nここまで\n',
|
|
29
|
+
'文-ここから': '3回ここから\nA=1\nここまで\n',
|
|
30
|
+
'文-ハテナ表示': '??1+2\n',
|
|
31
|
+
|
|
32
|
+
// --- モード設定・実行モード指定 (ySpeedMode / yPerformanceMonitor / yDNCLMode ほか) ---
|
|
33
|
+
'モード-DNCL': '!DNCLモード\nA=1\n',
|
|
34
|
+
'モード-速度優先': '「全て」で実行速度優先\nA=1\nここまで\n',
|
|
35
|
+
'モード-モニタ': '「全て」でパフォーマンスモニタ適用\nA=1\nここまで\n',
|
|
36
|
+
'モード-厳チェック': '!厳チェック\nA=1\n',
|
|
37
|
+
'モード-公開既定値': '!モジュール公開既定値=「非公開」\nA=1\n',
|
|
38
|
+
|
|
39
|
+
// --- 関数定義 (yDefFunc / yDefFuncCommon / yMumeiFunc / yDefTest) ---
|
|
40
|
+
'定義-関数': '●(AとBを)足すとは\nA+Bで戻る\nここまで\n',
|
|
41
|
+
'定義-関数公開': '●{公開}(Aを)倍とは\nA*2で戻る\nここまで\n',
|
|
42
|
+
'定義-カッコ引数': '●足す(AとBを)とは\nA+Bで戻る\nここまで\n',
|
|
43
|
+
'定義-ここから': '●Fとは、ここから\nA=1\nここまで\n',
|
|
44
|
+
'定義-無名関数': 'F=関数(Aを)\nAを表示\nここまで\n',
|
|
45
|
+
'定義-テスト': '●テスト:足すとは\nA=1\nここまで\n',
|
|
46
|
+
|
|
47
|
+
// --- 制御構文 (yIF / yFor / yWhile / ySwitch / yTryExcept ほか) ---
|
|
48
|
+
'制御-もし': 'もしA=1ならば\nB=1\n違えば\nB=2\nここまで\n',
|
|
49
|
+
'制御-もし単文': 'もしA=1ならばB=1\n',
|
|
50
|
+
'制御-回': '3回\nA=1\nここまで\n',
|
|
51
|
+
'制御-間': 'A<3の間\nA=A+1\nここまで\n',
|
|
52
|
+
'制御-後判定': '後判定\nA=A+1\nここまでA>3になるまで\n',
|
|
53
|
+
'制御-繰返': 'Nを1から10まで繰り返す\nNを表示\nここまで\n',
|
|
54
|
+
'制御-増繰返': 'Nを1から10まで2ずつ増やして繰り返す\nNを表示\nここまで\n',
|
|
55
|
+
'制御-減繰返': 'Nを10から1まで1ずつ減らして繰り返す\nNを表示\nここまで\n',
|
|
56
|
+
'制御-反復': '[1,2,3]を反復\n対象を表示\nここまで\n',
|
|
57
|
+
'制御-条件分岐': 'Aで条件分岐\n1ならば\nB=1\nここまで\n違えば\nB=2\nここまで\nここまで\n',
|
|
58
|
+
'制御-戻る': '●Fとは\n1で戻る\nここまで\n',
|
|
59
|
+
'制御-エラー監視': 'エラー監視\nA=1\nエラーならば\nB=2\nここまで\n',
|
|
60
|
+
|
|
61
|
+
// --- 代入・変数定義 (yLet / yDainyu / ySadameru / yIncDec) ---
|
|
62
|
+
'代入-単純': 'A=1\n',
|
|
63
|
+
'代入-代入文': 'Aに1を代入\n',
|
|
64
|
+
'代入-定める': 'Aを1に定める\n',
|
|
65
|
+
'代入-変数宣言': '変数 A=1\n',
|
|
66
|
+
'代入-定数宣言': '定数 A=1\n',
|
|
67
|
+
'代入-とは変数': 'Aとは変数=1\n',
|
|
68
|
+
'代入-複数変数': '変数 [A,B]=[1,2]\n',
|
|
69
|
+
'代入-複数代入': 'A,B=[1,2]\n',
|
|
70
|
+
'代入-増やす': 'Aを1だけ増やす\n',
|
|
71
|
+
'代入-減らす': 'Aを1だけ減らす\n',
|
|
72
|
+
'代入-プロパティ': 'A={}\nA$「b」=1\n',
|
|
73
|
+
|
|
74
|
+
// --- 配列要素への代入 (yLetArrayAt / yLetArrayBracket) ---
|
|
75
|
+
'配列-角括弧': 'A=[0]\nA[0]=1\n',
|
|
76
|
+
'配列-アット': 'A=[0]\nA@0=1\n',
|
|
77
|
+
'配列-二次元': 'A=[[0]]\nA[0][1]=1\n',
|
|
78
|
+
'配列-カンマ': 'A=[[0]]\nA[0,1]=1\n',
|
|
79
|
+
|
|
80
|
+
// --- 関数呼び出し (yCall / yCallFunc / yGetArgParen) ---
|
|
81
|
+
'呼出-単純': '「あ」を表示\n',
|
|
82
|
+
'呼出-C風': '足す(1,2)を表示\n',
|
|
83
|
+
'呼出-一語関数': 'A=1\nAを表示\n',
|
|
84
|
+
|
|
85
|
+
// --- 式・値 (yCalc / yValue / yValueKakko / yValueWord) ---
|
|
86
|
+
'式-カッコ': '(1+2)*3を表示\n',
|
|
87
|
+
'式-演算子': '1+2*3-4/5を表示\n',
|
|
88
|
+
'式-比較': 'もし1<2かつ3>2ならばA=1\n',
|
|
89
|
+
'式-範囲': 'A=1…10\n',
|
|
90
|
+
'式-単項マイナス': 'A=1\nB=-A\n',
|
|
91
|
+
'式-NOT': 'A=1\nB=!A\n',
|
|
92
|
+
|
|
93
|
+
// --- JSON/配列リテラル (yJSONArray / yJSONObject / yRefArrayValue) ---
|
|
94
|
+
'リテラル-配列': 'A=[1,2,3]\n',
|
|
95
|
+
'リテラル-辞書': 'A={"a":1,"b":2}\n',
|
|
96
|
+
'リテラル-辞書省略': 'A={a:1}\n',
|
|
97
|
+
'リテラル-空配列': 'A=[]\n',
|
|
98
|
+
'リテラル-空辞書': 'A={}\n',
|
|
99
|
+
'リテラル-入れ子': 'A=[[1,2],[3,4]]\n',
|
|
100
|
+
'リテラル-添字直接': 'A=[[1,2],[3,4]][0][1]\n',
|
|
101
|
+
'リテラル-アット直接': 'A=[1,2,3]@0\n',
|
|
102
|
+
'リテラル-プロパティ直接': 'A={a:1}$「a」\n',
|
|
103
|
+
|
|
104
|
+
// --- 非同期関数の判定 (_checkAsyncFn) ---
|
|
105
|
+
'非同期-async関数': '●Fとは\n1秒待つ\nここまで\nF\n'
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* AST を JSON 化可能なプレーンオブジェクトに変換する。
|
|
110
|
+
* `meta.fn` にはプラグイン関数の実体が入るため、JSON.stringify が黙って捨てて
|
|
111
|
+
* しまわないよう replacer で目印に置き換える。
|
|
112
|
+
*/
|
|
113
|
+
export function toPlainAst (ast) {
|
|
114
|
+
return JSON.parse(JSON.stringify(ast, (key, value) => (typeof value === 'function' ? '[fn]' : value)))
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** なでしこのコードを構文解析してプレーンな AST を返す */
|
|
118
|
+
export function parseToPlainAst (code) {
|
|
119
|
+
return toPlainAst(new NakoCompiler().parse(code, CORPUS_FILENAME))
|
|
120
|
+
}
|
package/core/test/func_call.mjs
CHANGED
|
@@ -221,6 +221,24 @@ TIDのタイマー停止
|
|
|
221
221
|
test2`
|
|
222
222
|
await cmp(code, '1\n2')
|
|
223
223
|
})
|
|
224
|
+
it('並行した非同期関数の終了後にローカル変数領域を残さない #1758', async () => {
|
|
225
|
+
const nako = new NakoCompiler()
|
|
226
|
+
const code = `
|
|
227
|
+
●test1():
|
|
228
|
+
xとは変数= 1
|
|
229
|
+
0.05秒待つ
|
|
230
|
+
●test2():
|
|
231
|
+
xとは変数= 2
|
|
232
|
+
0.05秒待つ
|
|
233
|
+
|
|
234
|
+
0.01秒後には:
|
|
235
|
+
test1
|
|
236
|
+
0.03秒後には:
|
|
237
|
+
test2`
|
|
238
|
+
const g = await nako.runAsync(code, 'main.nako3')
|
|
239
|
+
await forceWait(200)
|
|
240
|
+
assert.strictEqual(g.__vars, g.__varslist[2])
|
|
241
|
+
})
|
|
224
242
|
it('後方で宣言した関数がasyncFnだったときその関数が正しく実行できない(2) #1758', async () => {
|
|
225
243
|
const code = `
|
|
226
244
|
0.1秒後には:
|
package/core/test/func_test.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { describe, it } from 'node:test'
|
|
3
3
|
import assert from 'assert'
|
|
4
4
|
import { NakoCompiler } from '../src/nako3.mjs'
|
|
5
|
+
import { NakoSyntaxError } from '../src/nako_errors.mjs'
|
|
5
6
|
|
|
6
7
|
describe('func_test', async () => {
|
|
7
8
|
// nako.logger.addListener('trace', ({ browserConsole }) => { console.log(...browserConsole) })
|
|
@@ -10,6 +11,19 @@ describe('func_test', async () => {
|
|
|
10
11
|
nako.getLogger().debug('code=' + code)
|
|
11
12
|
assert.strictEqual((await nako.runAsync(code, 'main.nako3')).log, res)
|
|
12
13
|
}
|
|
14
|
+
/** 文法エラー(NakoSyntaxError)になることを確認する */
|
|
15
|
+
const cmpError = async (/** @type {string} */ code) => {
|
|
16
|
+
const nako = new NakoCompiler()
|
|
17
|
+
nako.getLogger().debug('code=' + code)
|
|
18
|
+
await assert.rejects(
|
|
19
|
+
async () => { await nako.runAsync(code, 'main.nako3') },
|
|
20
|
+
(err) => {
|
|
21
|
+
assert(err instanceof NakoSyntaxError, `NakoSyntaxErrorではありません: ${err}`)
|
|
22
|
+
assert(err.message.includes('式の中で『戻す(戻る)』文は使えません'), `想定外のエラーです: ${err.message}`)
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
}
|
|
13
27
|
// --- test ---
|
|
14
28
|
|
|
15
29
|
it('簡単な関数定義', async () => {
|
|
@@ -146,4 +160,18 @@ describe('func_test', async () => {
|
|
|
146
160
|
await cmp('●(AとBを)加算処理とは\n引数[0]と引数[1]を足すこと。。。3と5を加算処理して表示。', '8')
|
|
147
161
|
await cmp('●(AとBをCで)加算処理とは\nそれ=引数[0]+引数[1]+引数[2]。。。3と5を2で加算処理して表示。', '10')
|
|
148
162
|
})
|
|
163
|
+
it('代入文の値の中に『戻す』は書けない #2064', async () => {
|
|
164
|
+
// 『(式)して戻す』を代入文の値に書くと不正なJavaScriptが生成されていた
|
|
165
|
+
await cmpError('●テストとは\n定数の結果は「あ」を真偽判定して戻す。\nここまで\nテストを表示。')
|
|
166
|
+
await cmpError('●テストとは\n変数の結果は「あ」を真偽判定して戻す。\nここまで\nテストを表示。')
|
|
167
|
+
await cmpError('●テストとは\n結果は「あ」を真偽判定して戻す。\nここまで\nテストを表示。')
|
|
168
|
+
// 『戻る』の書き方でも同じエラーになる
|
|
169
|
+
await cmpError('●テストとは\n定数の結果は1に2を足して戻る。\nここまで\nテストを表示。')
|
|
170
|
+
})
|
|
171
|
+
it('『戻す』の正しい書き方は動く #2064', async () => {
|
|
172
|
+
await cmp('●テストとは\n「あ」を真偽判定して戻す。\nここまで\nテストを表示。', '真')
|
|
173
|
+
await cmp('●テストとは\n定数の結果は「あ」を真偽判定。\n結果で戻す。\nここまで\nテストを表示。', '真')
|
|
174
|
+
// 『戻す』以外の連文は今まで通り動く
|
|
175
|
+
await cmp('1に2を足して3を掛けて表示。', '9')
|
|
176
|
+
})
|
|
149
177
|
})
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
import { describe, it } from 'node:test'
|
|
3
|
+
import assert from 'assert'
|
|
4
|
+
|
|
5
|
+
import { NakoCompiler } from '../src/nako3.mjs'
|
|
6
|
+
import { basicPlugins, registerBasicPlugins } from '../src/nako_basic_plugins.mjs'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 基本プラグインの一覧を NakoCompiler から分離したモジュールのテスト (#2360)
|
|
10
|
+
*/
|
|
11
|
+
describe('nako_basic_plugins_test', () => {
|
|
12
|
+
it('基本プラグインの一覧を取得できる', () => {
|
|
13
|
+
assert.strictEqual(basicPlugins.length, 6)
|
|
14
|
+
const names = basicPlugins.map((po) => po.meta.value.pluginName)
|
|
15
|
+
assert.deepStrictEqual(names, [
|
|
16
|
+
'plugin_system', 'plugin_math', 'plugin_promise', 'plugin_test', 'plugin_csv', 'plugin_toml'
|
|
17
|
+
])
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('registerBasicPluginsは一覧の順にaddPluginを呼ぶ', () => {
|
|
21
|
+
const called = []
|
|
22
|
+
registerBasicPlugins({ addPlugin: (po) => { called.push(po) } })
|
|
23
|
+
assert.deepStrictEqual(called, basicPlugins)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('useBasicPluginがtrueなら基本プラグインの命令を使える', () => {
|
|
27
|
+
const nako = new NakoCompiler({ useBasicPlugin: true })
|
|
28
|
+
assert.ok(nako.getFunc('表示') !== undefined, 'PluginSystemの命令')
|
|
29
|
+
assert.ok(nako.getFunc('SIN') !== undefined, 'PluginMathの命令')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('useBasicPluginがfalseなら基本プラグインは登録されない', () => {
|
|
33
|
+
const nako = new NakoCompiler({ useBasicPlugin: false })
|
|
34
|
+
assert.strictEqual(nako.getFunc('表示'), undefined)
|
|
35
|
+
assert.deepStrictEqual(Object.keys(nako.getPluginfiles()), [])
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('addBasicPluginsを後から呼んでも登録できる', () => {
|
|
39
|
+
const nako = new NakoCompiler({ useBasicPlugin: false })
|
|
40
|
+
nako.addBasicPlugins()
|
|
41
|
+
assert.ok(nako.getFunc('表示') !== undefined)
|
|
42
|
+
assert.strictEqual(Object.keys(nako.getPluginfiles()).length, basicPlugins.length)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
import { describe, it } from 'node:test'
|
|
3
|
+
import assert from 'assert'
|
|
4
|
+
|
|
5
|
+
import { NakoCompiler } from '../src/nako3.mjs'
|
|
6
|
+
import { NakoEventEmitter } from '../src/nako_event.mjs'
|
|
7
|
+
import { NakoRunner } from '../src/nako_runner.mjs'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* イベント機構を NakoCompiler から分離したモジュールのテスト (#2360)
|
|
11
|
+
*/
|
|
12
|
+
describe('nako_event_test', () => {
|
|
13
|
+
it('onで登録したコールバックがfireで呼ばれる', () => {
|
|
14
|
+
const emitter = new NakoEventEmitter()
|
|
15
|
+
const log = []
|
|
16
|
+
emitter.on('beforeParse', (v) => { log.push(`a:${v}`) })
|
|
17
|
+
emitter.on('beforeParse', (v) => { log.push(`b:${v}`) })
|
|
18
|
+
emitter.fire('beforeParse', 1)
|
|
19
|
+
assert.deepStrictEqual(log, ['a:1', 'b:1'])
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('登録していないイベントを発火しても何も起きない', () => {
|
|
23
|
+
const emitter = new NakoEventEmitter()
|
|
24
|
+
let called = 0
|
|
25
|
+
emitter.on('beforeParse', () => { called++ })
|
|
26
|
+
emitter.fire('finish', null)
|
|
27
|
+
assert.strictEqual(called, 0)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('別のイベント名のコールバックは呼ばれない', () => {
|
|
31
|
+
const emitter = new NakoEventEmitter()
|
|
32
|
+
const log = []
|
|
33
|
+
emitter.on('beforeParse', () => { log.push('parse') })
|
|
34
|
+
emitter.on('finish', () => { log.push('finish') })
|
|
35
|
+
emitter.fire('finish', null)
|
|
36
|
+
assert.deepStrictEqual(log, ['finish'])
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('getEventListで登録済みのイベントを取得できる', () => {
|
|
40
|
+
const emitter = new NakoEventEmitter()
|
|
41
|
+
emitter.on('beforeRun', () => {})
|
|
42
|
+
assert.strictEqual(emitter.getEventList().length, 1)
|
|
43
|
+
assert.strictEqual(emitter.getEventList()[0].eventName, 'beforeRun')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('clearで登録済みのイベントを削除できる', () => {
|
|
47
|
+
const emitter = new NakoEventEmitter()
|
|
48
|
+
let called = 0
|
|
49
|
+
emitter.on('finish', () => { called++ })
|
|
50
|
+
emitter.clear()
|
|
51
|
+
emitter.fire('finish', null)
|
|
52
|
+
assert.strictEqual(called, 0)
|
|
53
|
+
assert.strictEqual(emitter.getEventList().length, 0)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('NakoCompilerのaddListenerでイベントが発火する順番', async () => {
|
|
57
|
+
const nako = new NakoCompiler()
|
|
58
|
+
const log = []
|
|
59
|
+
nako.addListener('beforeParse', () => { log.push('beforeParse') })
|
|
60
|
+
nako.addListener('beforeGenerate', () => { log.push('beforeGenerate') })
|
|
61
|
+
nako.addListener('afterGenerate', () => { log.push('afterGenerate') })
|
|
62
|
+
nako.addListener('beforeRun', () => { log.push('beforeRun') })
|
|
63
|
+
nako.addListener('finish', () => { log.push('finish') })
|
|
64
|
+
await nako.runAsync('「テスト」を表示', 'main.nako3')
|
|
65
|
+
assert.deepStrictEqual(log, ['beforeParse', 'beforeGenerate', 'afterGenerate', 'beforeRun', 'finish'])
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('非同期プログラムの完了後にfinishが発火する (#2384)', async () => {
|
|
69
|
+
const nako = new NakoCompiler()
|
|
70
|
+
let logAtFinish = null
|
|
71
|
+
nako.addListener('finish', (g) => { logAtFinish = g.log })
|
|
72
|
+
const g = await nako.runAsync('0.02秒待つ\n「完了」を表示', 'main.nako3')
|
|
73
|
+
assert.strictEqual(logAtFinish, '完了')
|
|
74
|
+
assert.strictEqual(g.log, '完了')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('runSyncでは非同期プログラムでも同期的にfinishが発火する (#2384)', async () => {
|
|
78
|
+
const nako = new NakoCompiler()
|
|
79
|
+
const logsAtFinish = []
|
|
80
|
+
nako.addListener('finish', (g) => { logsAtFinish.push(g.log) })
|
|
81
|
+
const g = nako.runSync('0.02秒待つ\n「完了」を表示', 'main.nako3')
|
|
82
|
+
assert.deepStrictEqual(logsAtFinish, [''])
|
|
83
|
+
assert.strictEqual(g.log, '')
|
|
84
|
+
await new Promise((resolve) => setTimeout(resolve, 40))
|
|
85
|
+
assert.strictEqual(g.log, '完了')
|
|
86
|
+
assert.deepStrictEqual(logsAtFinish, [''])
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('thenableがrejectした後にもfinishが発火する (#2384)', async () => {
|
|
90
|
+
const events = []
|
|
91
|
+
const runner = new NakoRunner({
|
|
92
|
+
fireEvent: (name, g) => { events.push([name, g.completed]) },
|
|
93
|
+
getLogger: () => ({ error: () => {} })
|
|
94
|
+
})
|
|
95
|
+
const g = { lastJSCode: '', numFailures: 0, completed: false }
|
|
96
|
+
const result = runner.evalJS(`
|
|
97
|
+
return {
|
|
98
|
+
then: (_resolve, reject) => setTimeout(() => {
|
|
99
|
+
this.completed = true
|
|
100
|
+
reject(new Error('非同期失敗'))
|
|
101
|
+
}, 1)
|
|
102
|
+
}
|
|
103
|
+
`, g, true)
|
|
104
|
+
assert.deepStrictEqual(events, [['beforeRun', false]])
|
|
105
|
+
await assert.rejects(Promise.resolve(result), /非同期失敗/)
|
|
106
|
+
assert.deepStrictEqual(events, [['beforeRun', false], ['finish', true]])
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('beforeParseにはソースコードが渡される', async () => {
|
|
110
|
+
const nako = new NakoCompiler()
|
|
111
|
+
let received = null
|
|
112
|
+
nako.addListener('beforeParse', (code) => { received = code })
|
|
113
|
+
await nako.runAsync('1と2を足して表示', 'main.nako3')
|
|
114
|
+
assert.strictEqual(received, '1と2を足して表示')
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('beforeRunとfinishには実行環境が渡される', async () => {
|
|
118
|
+
const nako = new NakoCompiler()
|
|
119
|
+
const received = []
|
|
120
|
+
nako.addListener('beforeRun', (g) => { received.push(g) })
|
|
121
|
+
nako.addListener('finish', (g) => { received.push(g) })
|
|
122
|
+
const g = await nako.runAsync('「テスト」を表示', 'main.nako3')
|
|
123
|
+
assert.strictEqual(received.length, 2)
|
|
124
|
+
assert.strictEqual(received[0], g)
|
|
125
|
+
assert.strictEqual(received[1], g)
|
|
126
|
+
})
|
|
127
|
+
})
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
/**
|
|
3
|
+
* nako_gen.mts のパフォーマンスモニタ / 関数呼び出しコード生成のテスト (#2333)
|
|
4
|
+
*
|
|
5
|
+
* `「〜」にパフォーマンスモニタ適用` で生成されるコードと、
|
|
6
|
+
* 実行時に作られる `__self.__performance_monitor` の内容を検証する。
|
|
7
|
+
* nako_gen.mts のリファクタリングで生成コードが壊れていないことを保証するのが目的。
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it } from 'node:test'
|
|
10
|
+
import assert from 'assert'
|
|
11
|
+
import { NakoCompiler } from '../src/nako3.mjs'
|
|
12
|
+
|
|
13
|
+
describe('nako_gen_perf_test', async () => {
|
|
14
|
+
/**
|
|
15
|
+
* なでしこコードを実行して、ログと計測結果を返す
|
|
16
|
+
* @param {string} code
|
|
17
|
+
*/
|
|
18
|
+
const run = async (code) => {
|
|
19
|
+
const nako = new NakoCompiler()
|
|
20
|
+
const g = await nako.runAsync(code, 'main.nako3')
|
|
21
|
+
// 非同期命令は runAsync の完了後も動いているので待つ (func_call.mjs と同様)
|
|
22
|
+
if (code.indexOf('秒待') >= 0) { await forceWait(200) }
|
|
23
|
+
return { log: g.log, pm: g.__performance_monitor }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 強制的にミリ秒待機
|
|
27
|
+
function forceWait (/** @type {number} */ ms) {
|
|
28
|
+
return /** @type {Promise<void>} */(new Promise((resolve) => {
|
|
29
|
+
setTimeout(() => { resolve() }, ms)
|
|
30
|
+
}))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('計測なしのとき', async () => {
|
|
34
|
+
it('__performance_monitor は作られない', async () => {
|
|
35
|
+
const { log, pm } = await run('「あ」と表示')
|
|
36
|
+
assert.strictEqual(log, 'あ')
|
|
37
|
+
assert.strictEqual(pm, undefined)
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('システム関数本体の計測', async () => {
|
|
42
|
+
it('キーは『命令名_body』、typeは『sysbody』', async () => {
|
|
43
|
+
const { log, pm } = await run(
|
|
44
|
+
'「システム関数本体」にパフォーマンスモニタ適用ここから\n' +
|
|
45
|
+
' 「あ」と表示\n' +
|
|
46
|
+
' 1に2を足して表示\n' +
|
|
47
|
+
'ここまで\n')
|
|
48
|
+
assert.strictEqual(log, 'あ\n3')
|
|
49
|
+
assert.strictEqual(pm['表示_body'].type, 'sysbody')
|
|
50
|
+
assert.strictEqual(pm['表示_body'].called, 2)
|
|
51
|
+
assert.strictEqual(pm['足_body'].type, 'sysbody')
|
|
52
|
+
assert.strictEqual(pm['足_body'].called, 1)
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
describe('システム関数の計測', async () => {
|
|
57
|
+
it('キーは『命令名_sys』、typeは『system』', async () => {
|
|
58
|
+
const { log, pm } = await run(
|
|
59
|
+
'「システム関数」にパフォーマンスモニタ適用ここから\n' +
|
|
60
|
+
' 「あ」と表示\n' +
|
|
61
|
+
' S=1に2を足す\n' +
|
|
62
|
+
' Sを表示\n' +
|
|
63
|
+
'ここまで\n')
|
|
64
|
+
assert.strictEqual(log, 'あ\n3')
|
|
65
|
+
assert.strictEqual(pm['表示_sys'].type, 'system')
|
|
66
|
+
assert.strictEqual(pm['表示_sys'].called, 2)
|
|
67
|
+
assert.strictEqual(pm['足_sys'].type, 'system')
|
|
68
|
+
assert.strictEqual(pm['足_sys'].called, 1)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('計測結果には called/totel_usec/min_usec/max_usec が入る', async () => {
|
|
72
|
+
const { pm } = await run(
|
|
73
|
+
'「システム関数」にパフォーマンスモニタ適用ここから\n' +
|
|
74
|
+
' 「あ」と表示\n' +
|
|
75
|
+
'ここまで\n')
|
|
76
|
+
const r = pm['表示_sys']
|
|
77
|
+
assert.deepStrictEqual(Object.keys(r).sort(), ['called', 'max_usec', 'min_usec', 'totel_usec', 'type'].sort())
|
|
78
|
+
assert.ok(r.min_usec <= r.max_usec)
|
|
79
|
+
assert.ok(r.totel_usec >= r.max_usec)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('ブロックの外は計測されない', async () => {
|
|
83
|
+
const { log, pm } = await run(
|
|
84
|
+
'「システム関数」にパフォーマンスモニタ適用ここから\n' +
|
|
85
|
+
' 「あ」と表示\n' +
|
|
86
|
+
'ここまで\n' +
|
|
87
|
+
'1に2を足して表示\n')
|
|
88
|
+
assert.strictEqual(log, 'あ\n3')
|
|
89
|
+
assert.strictEqual(pm['表示_sys'].called, 1)
|
|
90
|
+
assert.strictEqual(pm['足_sys'], undefined)
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
describe('ユーザ関数の計測', async () => {
|
|
95
|
+
it('キーは関数名、typeは『user』 (#2333)', async () => {
|
|
96
|
+
const { log, pm } = await run(
|
|
97
|
+
'「ユーザ関数」にパフォーマンスモニタ適用ここから\n' +
|
|
98
|
+
' ●(AとBを)テスト足すとは\n' +
|
|
99
|
+
' AにBを足して戻す\n' +
|
|
100
|
+
' ここまで\n' +
|
|
101
|
+
' 1と2をテスト足して表示\n' +
|
|
102
|
+
' 3と4をテスト足して表示\n' +
|
|
103
|
+
'ここまで\n')
|
|
104
|
+
assert.strictEqual(log, '3\n7')
|
|
105
|
+
assert.strictEqual(pm.main__テスト足.type, 'user')
|
|
106
|
+
assert.strictEqual(pm.main__テスト足.called, 2)
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
describe('非同期命令の計測 (#2333)', async () => {
|
|
111
|
+
it('システム関数本体: 構文エラーにならず、実行も完了する', async () => {
|
|
112
|
+
const { log, pm } = await run(
|
|
113
|
+
'「システム関数本体」にパフォーマンスモニタ適用ここから\n' +
|
|
114
|
+
' 0.01秒待つ\n' +
|
|
115
|
+
' 「おわり」と表示\n' +
|
|
116
|
+
'ここまで\n')
|
|
117
|
+
assert.strictEqual(log, 'おわり')
|
|
118
|
+
assert.strictEqual(pm.秒待_body.type, 'sysbody')
|
|
119
|
+
assert.strictEqual(pm.秒待_body.called, 1)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('システム関数: 構文エラーにならず、実行も完了する', async () => {
|
|
123
|
+
const { log, pm } = await run(
|
|
124
|
+
'「システム関数」にパフォーマンスモニタ適用ここから\n' +
|
|
125
|
+
' 0.01秒待つ\n' +
|
|
126
|
+
' 「おわり」と表示\n' +
|
|
127
|
+
'ここまで\n')
|
|
128
|
+
assert.strictEqual(log, 'おわり')
|
|
129
|
+
assert.strictEqual(pm.秒待_sys.type, 'system')
|
|
130
|
+
assert.strictEqual(pm.秒待_sys.called, 1)
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
describe('全てのオプションを同時に適用 (#2333)', async () => {
|
|
135
|
+
it('ユーザ関数・システム関数本体・システム関数を同時に計測できる', async () => {
|
|
136
|
+
const { log, pm } = await run(
|
|
137
|
+
'「全て」にパフォーマンスモニタ適用ここから\n' +
|
|
138
|
+
' ●(Aを)テスト表示とは\n' +
|
|
139
|
+
' Aを表示\n' +
|
|
140
|
+
' ここまで\n' +
|
|
141
|
+
' 「あ」をテスト表示\n' +
|
|
142
|
+
' 1に2を足して表示\n' +
|
|
143
|
+
'ここまで\n')
|
|
144
|
+
assert.strictEqual(log, 'あ\n3')
|
|
145
|
+
assert.strictEqual(pm.main__テスト表示.type, 'user')
|
|
146
|
+
assert.strictEqual(pm.足_body.type, 'sysbody')
|
|
147
|
+
assert.strictEqual(pm.足_sys.type, 'system')
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
describe('関数呼び出しコード生成の回帰チェック', async () => {
|
|
152
|
+
it('戻り値のある命令と『それ』', async () => {
|
|
153
|
+
const { log } = await run('1に2を足す\nそれを表示')
|
|
154
|
+
assert.strictEqual(log, '3')
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('ユーザ関数の呼び出しと戻り値', async () => {
|
|
158
|
+
const { log } = await run(
|
|
159
|
+
'●(AとBを)テスト足すとは\n' +
|
|
160
|
+
' AにBを足して戻す\n' +
|
|
161
|
+
'ここまで\n' +
|
|
162
|
+
'1と2をテスト足して表示\n')
|
|
163
|
+
assert.strictEqual(log, '3')
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
it('無名関数の呼び出し', async () => {
|
|
167
|
+
const { log } = await run(
|
|
168
|
+
'F=関数(a,b)それはa+b;ここまで\n' +
|
|
169
|
+
'F(3,4)を表示\n')
|
|
170
|
+
assert.strictEqual(log, '7')
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
it('非同期命令の呼び出し', async () => {
|
|
174
|
+
const { log } = await run('0.01秒待つ\n「おわり」と表示')
|
|
175
|
+
assert.strictEqual(log, 'おわり')
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
})
|