nadesiko3 3.7.21 → 3.7.22

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 (155) hide show
  1. package/batch/command.txt +370 -334
  2. package/batch/jsplugin2text.nako3 +1 -1
  3. package/batch/pickup_command.nako3 +12 -0
  4. package/core/command/snako.mts +5 -1
  5. package/core/deno/snako.ts +5 -1
  6. package/core/package-lock.json +382 -21
  7. package/core/package.json +4 -4
  8. package/core/src/nako3.mts +178 -614
  9. package/core/src/nako_basic_plugins.mts +39 -0
  10. package/core/src/nako_core_version.mts +2 -2
  11. package/core/src/nako_csv.mts +0 -1
  12. package/core/src/nako_event.mts +49 -0
  13. package/core/src/nako_gen.mts +291 -202
  14. package/core/src/nako_indent_inline.mts +2 -2
  15. package/core/src/nako_lex_rules.mts +1 -1
  16. package/core/src/nako_parser3.mts +106 -165
  17. package/core/src/nako_parser_async.mts +97 -0
  18. package/core/src/nako_parser_base.mts +4 -55
  19. package/core/src/nako_parser_message.mts +105 -0
  20. package/core/src/nako_parser_operator.mts +93 -0
  21. package/core/src/nako_plugin_manager.mts +260 -0
  22. package/core/src/nako_require.mts +292 -0
  23. package/core/src/nako_runner.mts +191 -0
  24. package/core/src/nako_tokenizer.mts +221 -0
  25. package/core/src/plugin_csv.mts +1 -1
  26. package/core/src/plugin_system.mts +34 -3259
  27. package/core/src/plugin_system_array.mts +699 -0
  28. package/core/src/plugin_system_datetime.mts +368 -0
  29. package/core/src/plugin_system_debug.mts +403 -0
  30. package/core/src/plugin_system_dict.mts +85 -0
  31. package/core/src/plugin_system_json.mts +73 -0
  32. package/core/src/plugin_system_math.mts +383 -0
  33. package/core/src/plugin_system_regexp.mts +120 -0
  34. package/core/src/plugin_system_stdio.mts +86 -0
  35. package/core/src/plugin_system_string.mts +666 -0
  36. package/core/src/plugin_system_timer.mts +152 -0
  37. package/core/src/plugin_system_types.mts +151 -0
  38. package/core/src/plugin_system_url.mts +193 -0
  39. package/core/src/plugin_toml.mts +3 -3
  40. package/core/test/fixtures/README.md +39 -0
  41. package/core/test/fixtures/make_parser_ast_golden.mjs +31 -0
  42. package/core/test/fixtures/parser_ast_golden.json +8027 -0
  43. package/core/test/fixtures/parser_corpus.mjs +120 -0
  44. package/core/test/indent_test.mjs +6 -0
  45. package/core/test/nako_basic_plugins_test.mjs +44 -0
  46. package/core/test/nako_event_test.mjs +85 -0
  47. package/core/test/nako_gen_perf_test.mjs +178 -0
  48. package/core/test/nako_parser_async_test.mjs +112 -0
  49. package/core/test/nako_parser_test.mjs +160 -0
  50. package/core/test/nako_plugin_manager_test.mjs +185 -0
  51. package/core/test/nako_require_test.mjs +153 -0
  52. package/core/test/nako_runner_test.mjs +114 -0
  53. package/core/test/nako_tokenizer_test.mjs +115 -0
  54. package/core/test/plugin_system_debug_test.mjs +141 -0
  55. package/core/test/plugin_system_split_test.mjs +179 -0
  56. package/core/test/plugin_system_test.mjs +6 -0
  57. package/core/tsconfig.json +0 -1
  58. package/package.json +17 -21
  59. package/release/_hash.txt +36 -36
  60. package/release/_script-tags.txt +16 -16
  61. package/release/command.json +1 -1
  62. package/release/command.json.js +1 -1
  63. package/release/command_cnako3.json +1 -1
  64. package/release/command_list.json +1 -1
  65. package/release/edit_main.js +6 -6
  66. package/release/edit_main.js.map +3 -3
  67. package/release/editor.js +6 -6
  68. package/release/plugin_keigo.js.map +3 -3
  69. package/release/plugin_markup.js +46 -46
  70. package/release/plugin_markup.js.map +3 -3
  71. package/release/plugin_weykturtle3d.js +1 -1
  72. package/release/plugin_weykturtle3d.js.map +3 -3
  73. package/release/version.js +2 -2
  74. package/release/version_main.js +2 -2
  75. package/release/version_main.js.map +1 -1
  76. package/release/wnako3.js +186 -213
  77. package/release/wnako3.js.map +4 -4
  78. package/release/wnako3webworker.js +172 -199
  79. package/release/wnako3webworker.js.map +4 -4
  80. package/src/cnako3mod.mjs +7 -2
  81. package/src/cnako3mod.mts +7 -2
  82. package/src/nako_version.mjs +2 -2
  83. package/src/nako_version.mts +2 -2
  84. package/src/plugin_browser_ajax.mjs +4 -4
  85. package/src/plugin_browser_ajax.mts +4 -4
  86. package/src/plugin_browser_audio.mjs +10 -10
  87. package/src/plugin_browser_audio.mts +10 -10
  88. package/src/plugin_browser_camera.mjs +4 -4
  89. package/src/plugin_browser_camera.mts +4 -4
  90. package/src/plugin_browser_canvas.mjs +2 -2
  91. package/src/plugin_browser_canvas.mts +2 -2
  92. package/src/plugin_browser_crypto.mjs +3 -3
  93. package/src/plugin_browser_crypto.mts +3 -3
  94. package/src/plugin_browser_dom_event.mjs +1 -1
  95. package/src/plugin_browser_dom_event.mts +1 -1
  96. package/src/plugin_browser_geolocation.mjs +1 -1
  97. package/src/plugin_browser_geolocation.mts +1 -1
  98. package/src/plugin_browser_hotkey.mjs +1 -1
  99. package/src/plugin_browser_hotkey.mts +1 -1
  100. package/src/plugin_browser_html.mjs +1 -1
  101. package/src/plugin_browser_html.mts +1 -1
  102. package/src/plugin_browser_location.mjs +1 -1
  103. package/src/plugin_browser_location.mts +1 -1
  104. package/src/plugin_browser_speech.mjs +1 -1
  105. package/src/plugin_browser_speech.mts +1 -1
  106. package/src/plugin_browser_storage.mjs +2 -2
  107. package/src/plugin_browser_storage.mts +2 -2
  108. package/src/plugin_httpserver.mjs +3 -3
  109. package/src/plugin_httpserver.mts +3 -3
  110. package/src/plugin_keigo.mjs +2 -2
  111. package/src/plugin_keigo.mts +2 -2
  112. package/src/plugin_node.mjs +48 -48
  113. package/src/plugin_node.mts +53 -53
  114. package/src/plugin_weykturtle3d.mjs +56 -56
  115. package/src/plugin_weykturtle3d.mts +56 -56
  116. package/src/wnako3.mjs +1 -1
  117. package/src/wnako3.mts +1 -1
  118. package/src/wnako3_editor.mjs +5 -5
  119. package/src/wnako3_editor.mts +5 -5
  120. package/src/wnako3mod.mjs +2 -2
  121. package/src/wnako3mod.mts +2 -2
  122. package/core/src/nako3.mjs +0 -1021
  123. package/core/src/nako_ast.mjs +0 -4
  124. package/core/src/nako_colors.mjs +0 -77
  125. package/core/src/nako_core_version.mjs +0 -8
  126. package/core/src/nako_csv.mjs +0 -193
  127. package/core/src/nako_errors.mjs +0 -166
  128. package/core/src/nako_from_dncl.mjs +0 -285
  129. package/core/src/nako_from_dncl2.mjs +0 -347
  130. package/core/src/nako_gen.mjs +0 -2500
  131. package/core/src/nako_global.mjs +0 -138
  132. package/core/src/nako_indent.mjs +0 -442
  133. package/core/src/nako_indent_chars.mjs +0 -29
  134. package/core/src/nako_indent_inline.mjs +0 -361
  135. package/core/src/nako_josi_list.mjs +0 -47
  136. package/core/src/nako_lex_rules.mjs +0 -319
  137. package/core/src/nako_lexer.mjs +0 -794
  138. package/core/src/nako_logger.mjs +0 -221
  139. package/core/src/nako_parser3.mjs +0 -3250
  140. package/core/src/nako_parser_base.mjs +0 -403
  141. package/core/src/nako_parser_const.mjs +0 -37
  142. package/core/src/nako_prepare.mjs +0 -329
  143. package/core/src/nako_reserved_words.mjs +0 -42
  144. package/core/src/nako_source_mapping.mjs +0 -207
  145. package/core/src/nako_test.mjs +0 -37
  146. package/core/src/nako_token.mjs +0 -1
  147. package/core/src/nako_tools.mjs +0 -53
  148. package/core/src/nako_types.mjs +0 -14
  149. package/core/src/plugin_api.mjs +0 -4
  150. package/core/src/plugin_csv.mjs +0 -97
  151. package/core/src/plugin_math.mjs +0 -352
  152. package/core/src/plugin_promise.mjs +0 -102
  153. package/core/src/plugin_system.mjs +0 -3810
  154. package/core/src/plugin_test.mjs +0 -52
  155. package/core/src/plugin_toml.mjs +0 -39
@@ -1,2500 +0,0 @@
1
- /**
2
- * パーサーが生成した中間オブジェクトを実際のJavaScriptのコードに変換する。
3
- * なお速度優先で忠実にJavaScriptのコードを生成する。
4
- */
5
- import { NakoSyntaxError } from './nako_errors.mjs';
6
- // なでしこで定義した関数の開始コードと終了コード
7
- const topOfFunction = '(function(){\n';
8
- const endOfFunction = '})';
9
- const topOfFunctionAsync = '(async function(){\n';
10
- /** コード生成オプション */
11
- export class NakoGenOptions {
12
- constructor(isTest = false, importFiles = [], codeStandalone = '', convEnv = '') {
13
- this.isTest = isTest;
14
- this.codeStandalone = codeStandalone;
15
- this.codeEnv = convEnv;
16
- this.importFiles = ['plugin_system.mjs', 'plugin_math.mjs', 'plugin_csv.mjs', 'plugin_promise.mjs', 'plugin_test.mjs'];
17
- for (const fname of importFiles) {
18
- this.importFiles.push(fname);
19
- }
20
- }
21
- }
22
- /**
23
- * 構文木からJSのコードを生成するクラス
24
- */
25
- export class NakoGen {
26
- /** constructor
27
- * @param com コンパイラのインスタンス
28
- */
29
- constructor(com) {
30
- /**
31
- * 出力するJavaScriptコードのヘッダー部分で定義する必要のある関数。fnはjsのコード。
32
- * プラグイン関数は含まれない。
33
- */
34
- this.nakoFuncList = new Map(com.getNakoFuncList());
35
- /**
36
- * なでしこで定義したテストの一覧
37
- */
38
- this.nakoTestFuncs = new Map();
39
- /**
40
- * プログラム内で参照された関数のリスト。プラグインの命令を含む。
41
- * JavaScript単体で実行するとき、このリストにある関数の定義をJavaScriptコードの先頭に付け足す。
42
- */
43
- this.usedFuncSet = new Set();
44
- /**
45
- * ループ時の一時変数が被らないようにIDで管理
46
- */
47
- this.loopId = 1;
48
- /**
49
- * 非同関数を何回使ったか
50
- */
51
- this.numAsyncFn = 0;
52
- /**
53
- * 関数定義の際、関数の中でasyncFn=trueの関数を呼び出したかどうかを調べる @see convDefFuncCommon
54
- */
55
- this.usedAsyncFn = false;
56
- /** 変換中の処理が、ループの中かどうかを判定する */
57
- this.flagLoop = false;
58
- this.__self = com;
59
- /** コードジェネレータの種類 */
60
- this.genMode = 'sync';
61
- /** 行番号とファイル名が分かるときは `l123:main.nako3`、行番号だけ分かるときは `l123`、そうでなければ任意の文字列。 */
62
- this.lastLineNo = null;
63
- /** スタック */
64
- this.varslistSet = this.setVarslistSet(com.__varslist);
65
- /** スタックトップ */
66
- this.varsSet = { isFunction: false, names: new Set(), readonly: new Set() };
67
- this.varslistSet[2] = this.varsSet;
68
- this.functionContextStack = [];
69
- // 現在定義中の関数名
70
- this.defFuncName = '';
71
- // 1以上のとき高速化する。
72
- // 実行速度優先ブロック内で1増える。
73
- this.speedMode = {
74
- lineNumbers: 0, // 行番号を出力しない
75
- implicitTypeCasting: 0, // 数値加算でparseFloatを出力しない
76
- invalidSore: 0, // 「それ」を用いない
77
- forcePure: 0 // 全てのシステム命令をpureとして扱う。命令からローカル変数への参照が出来なくなる。
78
- };
79
- // 1以上のとき測定をinjectする。
80
- // パフォーマンスモニタのブロック内で1増える。
81
- this.performanceMonitor = {
82
- userFunction: 0, // 呼び出されたユーザ関数
83
- systemFunction: 0, // システム関数(呼び出しコードを含む)
84
- systemFunctionBody: 0, // システム関数(呼び出しコードを除く)
85
- mumeiId: 0
86
- };
87
- /**
88
- * 未定義の変数の警告を行う
89
- */
90
- this.constPools = [];
91
- this.constPoolsTemplate = [];
92
- // undefinedの警告制御 (「厳しくチェック」でオンになる)
93
- this.warnUndefinedVar = false;
94
- this.warnUndefinedReturnUserFunc = false;
95
- this.warnUndefinedCallingUserFunc = false;
96
- this.warnUndefinedCallingSystemFunc = false;
97
- this.warnUndefinedCalledUserFuncArgs = false;
98
- this.debugOption = com.debugOption;
99
- }
100
- static isValidIdentifier(name) {
101
- // TODO: いらなそうな部分は削る
102
- // https://stackoverflow.com/a/9337047
103
- // eslint-disable-next-line no-misleading-character-class
104
- return /^(?!(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$)[$A-Z_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc][$A-Z_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc0-9\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19d9\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f]*$/.test(name);
105
- }
106
- /**
107
- * com.__varslistを元に、this.varslistSetを設定
108
- */
109
- setVarslistSet(varslist) {
110
- const vlist = [];
111
- // 変数名の一覧をVarsSetに格納 (0: システム変数, 1: グローバル変数, 2: ローカル変数) 0と1のみ移す
112
- for (let i = 0; i <= 1; i++) {
113
- const scope = varslist[i];
114
- const names = new Set(scope.keys());
115
- names.delete('meta'); // remove 'meta' from names
116
- vlist[i] = { isFunction: false, names, readonly: new Set() };
117
- }
118
- return vlist;
119
- }
120
- /**
121
- * 改行を埋め込む
122
- */
123
- convLineno(node, forceUpdate = false, incLine = 0) {
124
- // スピードモードでは行番号を埋め込まない
125
- if (this.speedMode.lineNumbers > 0) {
126
- return '';
127
- }
128
- const lineNo = node.line + incLine;
129
- let lineNoStr;
130
- if (typeof node.line !== 'number') {
131
- lineNoStr = 'unknown';
132
- }
133
- else if (typeof node.file !== 'string') {
134
- lineNoStr = `l${lineNo}`;
135
- }
136
- else {
137
- lineNoStr = `l${lineNo}:${node.file}`;
138
- }
139
- // 強制的に行番号をアップデートするか
140
- if (!forceUpdate) {
141
- if (lineNoStr === this.lastLineNo) {
142
- return '';
143
- }
144
- this.lastLineNo = lineNoStr;
145
- }
146
- // 実行行のデータ
147
- const lineDataJSON = JSON.stringify(lineNoStr);
148
- // デバッグ実行か
149
- let debugCode = '';
150
- if (this.debugOption.useDebug) {
151
- // messageAction
152
- if (this.debugOption.messageAction) {
153
- debugCode += `window.postMessage({action:'${this.debugOption.messageAction}',` +
154
- `line: ${lineDataJSON}});`;
155
- }
156
- // waitTime
157
- if (lineNo >= 1) {
158
- if (this.debugOption.waitTime > 0) {
159
- debugCode += `await __v0.get('秒待')(${this.debugOption.waitTime},__self);`;
160
- }
161
- // breakpoints
162
- this.numAsyncFn += 1;
163
- this.usedAsyncFn = true;
164
- debugCode += `await __v0.get('__DEBUG_BP_WAIT')(${lineNo}, __self);`;
165
- }
166
- // end
167
- debugCode += 'if (__v0.get(\'__forceClose\')) { return -1 };';
168
- }
169
- // 例: __v0.set('__line', 'l1:main.nako3')
170
- // return `__v0.set('__line', ${lineDataJSON});` + debugCode
171
- return `__line(${lineDataJSON});` + debugCode;
172
- }
173
- /**
174
- * ローカル変数の取得用JavaScriptコードを生成する。
175
- * @param {string} name
176
- */
177
- varname_get(name) {
178
- if (this.varslistSet.length === 3) {
179
- // グローバル
180
- return `__self.__varslist[${2}].get(${JSON.stringify(name)})`;
181
- }
182
- else {
183
- // ローカル
184
- return `__self.__vars.get(${JSON.stringify(name)})`;
185
- }
186
- }
187
- /**
188
- * ローカル変数の設定用JavaScriptコードを生成する。
189
- * @param {string} name
190
- * @param {string} jsvalue
191
- */
192
- varname_set(name, jsvalue) {
193
- if (this.varslistSet.length === 3) {
194
- return `__self.__varslist[2].set(${JSON.stringify(name)}, (${jsvalue}))`;
195
- }
196
- else {
197
- return `__self.__vars.set(${JSON.stringify(name)}, (${jsvalue}))`;
198
- }
199
- }
200
- /**
201
- * ローカル変数の設定用JavaScriptコードを生成する。
202
- * @param {string} name
203
- * @param {string} jsvalue
204
- */
205
- varname_set_sys(name, jsvalue) {
206
- return `__self.__setSysVar(${JSON.stringify(name)}, (${jsvalue}))`;
207
- }
208
- /**
209
- * @param {string} name
210
- * @returns {string}
211
- */
212
- static getFuncName(name) {
213
- if (name.indexOf('__') >= 0) { // スコープがある場合
214
- const a = name.split('__');
215
- const scope = a[0];
216
- const name3 = NakoGen.getFuncName(a[1]);
217
- return `${scope}__${name3}`;
218
- }
219
- let name2 = name.replace(/[ぁ-ん]+$/, '');
220
- if (name2 === '') {
221
- name2 = name;
222
- }
223
- return name2;
224
- }
225
- /** @param {Ast} node */
226
- static convPrint(node) {
227
- return `__print(${node});`;
228
- }
229
- /** @param {AstStrValue} node */
230
- convRequire(node) {
231
- const moduleName = node.value;
232
- return this.convLineno(node, false) +
233
- `__module['${moduleName}'] = require('${moduleName}');\n`;
234
- }
235
- /**
236
- * プログラムの実行に必要な関数定義を書き出す(グローバル領域)
237
- * convGenの結果を利用するため、convGenの後に呼び出すこと。
238
- * @param com
239
- * @param opt
240
- */
241
- getDefFuncCode(com, opt) {
242
- let code = '';
243
- // よく使う変数のショートカット
244
- // jsInit の部分に設定するコード
245
- code += `const nakoVersion = { version: ${JSON.stringify(com.version)} }\n`;
246
- code += 'const __self = self;\n';
247
- code += '__self.__self = __self;\n';
248
- code += 'const __varslist = __self.__varslist;\n';
249
- code += 'const __module = __self.__module;\n';
250
- code += 'const __v0 = __self.__v0 = __self.__varslist[0];\n';
251
- code += 'const __v1 = __self.__v1 = __self.__varslist[1];\n';
252
- code += 'const __vars = __self.__vars = __self.__varslist[2];\n';
253
- code += 'const __nako_make_closure = (local, parent) => ({\n' +
254
- ' has: (key) => local.has(key) || (parent !== null && parent.has(key)),\n' +
255
- ' get: (key) => local.has(key) ? local.get(key) : (parent !== null ? parent.get(key) : undefined),\n' +
256
- ' set: (key, value) => { if (local.has(key) || parent === null || !parent.has(key)) { local.set(key, value); } else { parent.set(key, value); } return value; }\n' +
257
- '});\n';
258
- code += `const __modList = __self.__modList = ${JSON.stringify(com.getModList())}\n`;
259
- code += 'const __line = (lineno) => { __self.__v0.set(\'__line\', lineno); }\n';
260
- code += '__v0.set(\'__line\', \'l0:__getDefFuncCode\');\n';
261
- code += '__v0.set(\'__forceClose\', false);\n';
262
- code += `__v0.set('__useDebug', ${String(this.debugOption.useDebug)});\n`;
263
- // 定数を埋め込む
264
- code += '__self.constPools = ' + JSON.stringify(this.constPools) + ';\n';
265
- code += '__self.constPoolsTemplate = ' + JSON.stringify(this.constPoolsTemplate) + ';\n';
266
- //
267
- code += '__self.__propAccessor = [];\n';
268
- // なでしこの関数定義を行う
269
- let nakoFuncCode = '';
270
- this.nakoFuncList.forEach((value, key) => {
271
- const f = trim(cleanGeneratedCode(String(value.fn), 1));
272
- const isAsync = value.asyncFn ? 'true' : 'false';
273
- nakoFuncCode += '' +
274
- `//[DEF_FUNC name='${key}' asyncFn=${isAsync}]\n` +
275
- `__self.__varslist[1].set("${key}", ${f});\n` +
276
- `//[/DEF_FUNC name='${key}']\n`;
277
- });
278
- if (nakoFuncCode !== '') {
279
- code += '__v0.set(\'__line\', \'関数の定義\');\n' + nakoFuncCode;
280
- }
281
- // テストの定義を行う
282
- if (opt.isTest) {
283
- let testCode = 'const __tests = [];\n';
284
- this.nakoTestFuncs.forEach((value) => {
285
- const f = value.fn;
286
- testCode += `${String(f)};\n`;
287
- });
288
- if (testCode !== '') {
289
- code += '__v0.set(\'__line\', \'テストの定義\');\n';
290
- code += testCode + '\n';
291
- }
292
- }
293
- return code;
294
- }
295
- /**
296
- * プラグイン・オブジェクトを追加
297
- * @param po プラグイン・オブジェクト
298
- */
299
- addPlugin(po) {
300
- return this.__self.addPlugin(po);
301
- }
302
- /**
303
- * プラグイン・オブジェクトを追加(ブラウザ向け)
304
- * @param name オブジェクト名
305
- * @param po 関数リスト
306
- */
307
- addPluginObject(name, po) {
308
- this.__self.addPluginObject(name, po);
309
- }
310
- /**
311
- * プラグイン・ファイルを追加(Node.js向け)
312
- * @param objName オブジェクト名
313
- * @param path ファイルパス
314
- * @param po 登録するオブジェクト
315
- */
316
- addPluginFile(objName, path, po) {
317
- this.__self.addPluginFile(objName, path, po);
318
- }
319
- /**
320
- * 関数を追加する
321
- * @param key 関数名
322
- * @param josi 助詞
323
- * @param fn 関数
324
- */
325
- addFunc(key, josi, fn) {
326
- this.__self.addFunc(key, josi, fn);
327
- }
328
- /**
329
- * プラグイン関数を参照する
330
- * @param key プラグイン関数の関数名
331
- * @returns プラグイン・オブジェクト
332
- */
333
- getFunc(key) {
334
- return this.__self.getFunc(key);
335
- }
336
- /**
337
- * 関数を先に登録してしまう
338
- */
339
- registerFunction(ast) {
340
- if (ast.type !== 'block') {
341
- throw NakoSyntaxError.fromNode('構文解析に失敗しています。構文は必ずblockが先頭になります', ast);
342
- }
343
- /** 関数一覧 */
344
- const funcList = [];
345
- // なでしこ関数を定義して this.nako_func[name] に定義する
346
- const registFunc = (t) => {
347
- // (t.type == 'def_func') はチェック済み
348
- if (!t.name) {
349
- throw new Error('[System Error] 関数の定義で関数名が指定されていません');
350
- }
351
- const name = t.name;
352
- this.usedFuncSet.add(name);
353
- this.__self.__varslist[1].set(name, () => { }); // 事前に適当な値を設定
354
- this.varslistSet[1].names.add(name); // global
355
- const meta = t.meta;
356
- if (!meta) {
357
- throw new Error('[System Error] 関数の定義で関数名のメタ情報が指定されていません');
358
- }
359
- this.nakoFuncList.set(name, {
360
- josi: meta.josi,
361
- fn: () => { },
362
- type: 'func',
363
- asyncFn: !!t.asyncFn,
364
- isExport: t.isExport
365
- });
366
- funcList.push({ name, node: t });
367
- };
368
- const registFuncs = (ast) => {
369
- // blocksプロパティを持っているか?
370
- if (ast.blocks) {
371
- // 各ブロックをくまなく巡回チェック
372
- for (const t of ast.blocks) {
373
- if (t.type === 'def_func') { // 関数定義
374
- registFunc(t);
375
- }
376
- else {
377
- registFuncs(t);
378
- }
379
- }
380
- }
381
- };
382
- // 関数の登録
383
- registFuncs(ast);
384
- // __self.__varslistの変更を反映
385
- const initialNames = new Set();
386
- if (this.speedMode.invalidSore === 0) {
387
- initialNames.add('それ');
388
- }
389
- this.varsSet = { isFunction: false, names: initialNames, readonly: new Set() };
390
- this.varslistSet = this.setVarslistSet(this.__self.__varslist);
391
- this.varslistSet[2] = this.varsSet;
392
- }
393
- /**
394
- * @param node
395
- * @param opt
396
- */
397
- convGen(node, opt) {
398
- const result = this.convLineno(node, false) + this._convGen(node, true);
399
- if (opt.isTest) {
400
- return '';
401
- }
402
- else {
403
- return result;
404
- }
405
- }
406
- /**
407
- * @param {Ast} node
408
- * @param {boolean} isExpression
409
- */
410
- _convGen(node, isExpression) {
411
- if (!node) {
412
- return '';
413
- }
414
- let code = '';
415
- if (node instanceof Array) {
416
- for (let i = 0; i < node.length; i++) {
417
- const n = node[i];
418
- code += this._convGen(n, isExpression);
419
- }
420
- return code;
421
- }
422
- if (node === null) {
423
- return 'null';
424
- }
425
- if (node === undefined) {
426
- return 'undefined';
427
- }
428
- if (typeof (node) !== 'object') {
429
- return '' + String(node);
430
- }
431
- // switch
432
- switch (node.type) {
433
- case 'nop':
434
- break;
435
- case 'block':
436
- code += this.convBlock(node);
437
- break;
438
- case 'comment':
439
- case 'eol':
440
- code += this.convComment(node);
441
- break;
442
- case 'run_mode':
443
- code += this.convRunMode(node);
444
- break;
445
- case 'break':
446
- code += this.convCheckLoop(node, 'break');
447
- break;
448
- case 'continue':
449
- code += this.convCheckLoop(node, 'continue');
450
- break;
451
- case 'end':
452
- code += '__v0.get(\'終\')(__self);';
453
- break;
454
- case 'number':
455
- code += node.value;
456
- break;
457
- case 'bigint':
458
- code += node.value;
459
- break;
460
- case 'string':
461
- code += this.convString(node);
462
- break;
463
- case 'def_local_var':
464
- code += this.convDefLocalVar(node);
465
- break;
466
- case 'def_local_varlist':
467
- code += this.convDefLocalVarlist(node);
468
- break;
469
- case 'let':
470
- code += this.convLet(node);
471
- break;
472
- case 'let_prop':
473
- code += this.convLetProp(node);
474
- break;
475
- case 'ref_prop':
476
- code += this.convRefProp(node);
477
- break;
478
- case 'inc':
479
- code += this.convInc(node);
480
- break;
481
- case 'word':
482
- case 'variable':
483
- code += this.convGetVar(node);
484
- break;
485
- case 'op':
486
- case 'calc':
487
- code += this.convOp(node);
488
- break;
489
- case 'renbun':
490
- code += this.convRenbun(node);
491
- break;
492
- case 'not':
493
- code += '((' + this._convGen(node.blocks[0], true) + ')?false:true)';
494
- break;
495
- case 'func':
496
- case 'func_pointer':
497
- case 'calc_func':
498
- code += this.convCallFunc(node, isExpression);
499
- break;
500
- case 'call_value':
501
- code += this.convCallValue(node, isExpression);
502
- break;
503
- case 'if':
504
- code += this.convIf(node);
505
- break;
506
- case 'for':
507
- code += this.convFor(node);
508
- break;
509
- case 'foreach': // 反復
510
- code += this.convForeach(node);
511
- break;
512
- case 'repeat_times': // 回
513
- code += this.convRepeatTimes(node);
514
- break;
515
- case 'speed_mode':
516
- code += this.convSpeedMode(node, isExpression);
517
- break;
518
- case 'performance_monitor':
519
- code += this.convPerformanceMonitor(node, isExpression);
520
- break;
521
- case 'while':
522
- code += this.convWhile(node);
523
- break;
524
- case 'atohantei':
525
- code += this.convAtohantei(node);
526
- break;
527
- case 'switch':
528
- code += this.convSwitch(node);
529
- break;
530
- case 'let_array':
531
- code += this.convLetArray(node);
532
- break;
533
- case 'ref_array':
534
- code += this.convRefArray(node);
535
- break;
536
- case 'ref_array_value':
537
- code += this.convRefArrayValue(node);
538
- break;
539
- case 'json_array':
540
- code += this.convJsonArray(node);
541
- break;
542
- case 'json_obj':
543
- code += this.convJsonObj(node);
544
- break;
545
- case 'bool':
546
- code += (node.value) ? 'true' : 'false';
547
- break;
548
- case 'null':
549
- code += 'null';
550
- break;
551
- case 'def_test':
552
- code += this.convDefTest(node);
553
- break;
554
- case 'def_func':
555
- code += this.convDefFunc(node);
556
- break;
557
- case 'func_obj':
558
- code += this.convFuncObj(node);
559
- break;
560
- case 'return':
561
- code += this.convReturn(node);
562
- break;
563
- case 'try_except':
564
- code += this.convTryExcept(node);
565
- break;
566
- case 'require':
567
- code += this.convRequire(node);
568
- break;
569
- default:
570
- throw new Error('System Error: unknown_type=' + node.type);
571
- }
572
- return code;
573
- }
574
- /** 変数を検索 */
575
- findVar(name, jsvalue = null) {
576
- // __vars ? (ローカル変数)
577
- if (this.varslistSet.length > 3 && this.varsSet.names.has(name)) {
578
- return {
579
- i: this.varslistSet.length - 1,
580
- name,
581
- isTop: true,
582
- js: this.varname_get(name),
583
- js_set: this.varname_set(name, String(jsvalue))
584
- };
585
- }
586
- // 外側の無名関数のローカル変数をクロージャとして参照する #2268
587
- const currentFunc = this.functionContextStack[this.functionContextStack.length - 1];
588
- if (this.varslistSet.length > 4 && currentFunc?.isAnonymous) {
589
- const currentIndex = this.varslistSet.length - 1;
590
- for (let i = currentIndex - 1; i >= 3; i--) {
591
- if (this.varslistSet[i].names.has(name)) {
592
- for (const context of this.functionContextStack) {
593
- if (context.isAnonymous && context.varsIndex > i) {
594
- context.usesClosure = true;
595
- }
596
- }
597
- const nameJson = JSON.stringify(name);
598
- return {
599
- i,
600
- name,
601
- isTop: false,
602
- js: `__nako_closure.get(${nameJson})`,
603
- js_set: `__nako_closure.set(${nameJson}, ${jsvalue ?? 'undefined'})`
604
- };
605
- }
606
- }
607
- }
608
- // __varslist ?
609
- for (let i = 2; i >= 0; i--) {
610
- if (this.varslistSet[i].names.has(name)) {
611
- // ユーザーの定義したグローバル変数 (__varslist[2]) は、変数展開されている(そのままの名前で定義されている)可能性がある。
612
- // それ以外の変数は、必ず__varslistに入っている。
613
- return {
614
- i,
615
- name,
616
- isTop: false,
617
- js: `__self.__varslist[${i}].get(${JSON.stringify(name)})`,
618
- js_set: `__self.__varslist[${i}].set(${JSON.stringify(name)}, ${jsvalue ?? 'undefined'})`
619
- };
620
- }
621
- }
622
- return null;
623
- }
624
- /**
625
- * 定義済みの変数の参照
626
- * @param {string} name
627
- * @param {Ast} position
628
- */
629
- genVar(name, position) {
630
- const res = this.findVar(name);
631
- const lno = position.line;
632
- if (res === null) {
633
- // 定義されていない名前の参照は変数の定義とみなす。
634
- // 多くの場合はundefined値を持つ変数であり分かりづらいバグを引き起こすが、
635
- // 「ナデシコする」などの命令の中で定義された変数の参照の場合があるため警告に留める。
636
- // ただし、自動的に定義される変数『引数』『それ』などは例外 #952
637
- if (name === '引数' || name === 'それ' || name === '対象' || name === '対象キー') {
638
- // デフォルト定義されている変数名
639
- }
640
- else {
641
- if (this.warnUndefinedVar) {
642
- // main__は省略して表示するように。 #1223
643
- const dispName = name.replace(/^main__(.+)$/, '$1');
644
- this.__self.getLogger().warn(`変数『${dispName}』は定義されていません。`, position);
645
- }
646
- }
647
- this.varsSet.names.add(name);
648
- return this.varname_get(name);
649
- }
650
- const i = res.i;
651
- // システム関数・変数の場合
652
- if (i === 0) {
653
- const pv = this.__self.getNakoFunc(name);
654
- if (!pv) {
655
- return `${res.js}/*[link_error]l${lno}:${position.file ?? 'unknown'}*/`;
656
- }
657
- if (pv.type === 'const' || pv.type === 'var') {
658
- return res.js;
659
- }
660
- if (pv.type === 'func') {
661
- if (!pv.josi || pv.josi.length === 0) {
662
- return `(${res.js}())`;
663
- }
664
- throw NakoSyntaxError.fromNode(`『${name}』が複文で使われました。単文で記述してください。(v1非互換)`, position);
665
- }
666
- throw NakoSyntaxError.fromNode(`『${name}』は関数であり参照できません。`, position);
667
- }
668
- return res.js;
669
- }
670
- convGetVar(node) {
671
- // 変数名を得る
672
- const name = node.value;
673
- // 変数を取得するコードを生成
674
- return this.genVar(name, node);
675
- }
676
- convBlock(node) {
677
- let code = '';
678
- for (const block of node.blocks) {
679
- code += this._convGen(block, false);
680
- }
681
- return code;
682
- }
683
- convComment(node) {
684
- let commentSrc = String(node.comment);
685
- // コメントの改行や空行を無効化
686
- commentSrc = commentSrc.replace(/\n/g, '¶');
687
- commentSrc = commentSrc.replace(/\*\//g, '*/');
688
- commentSrc = commentSrc.replace(/(^\s+|\s+$)/g, '');
689
- // コメントの行番号を得る
690
- const lineNo = this.convLineno(node, false);
691
- if (commentSrc === '' && lineNo === '') {
692
- return ';';
693
- }
694
- if (commentSrc === '') {
695
- return ';' + lineNo + '\n';
696
- }
697
- return ';' + lineNo + '//' + commentSrc + '\n';
698
- }
699
- convRunMode(node) {
700
- const mode = node.value;
701
- let isStrict = false;
702
- if (mode === '厳しくチェック') {
703
- // 厳しくチェックモードの場合、変数の未定義チェックを行う
704
- isStrict = true;
705
- }
706
- this.warnUndefinedVar = isStrict;
707
- this.warnUndefinedReturnUserFunc = isStrict;
708
- this.warnUndefinedCallingUserFunc = isStrict;
709
- this.warnUndefinedCallingSystemFunc = isStrict;
710
- this.warnUndefinedCalledUserFuncArgs = isStrict;
711
- return `/* 実行モード: ${mode} */`;
712
- }
713
- convReturn(node) {
714
- // 関数の中であれば利用可能
715
- if (this.varsSet.names.has('!関数')) {
716
- throw NakoSyntaxError.fromNode('『戻る』がありますが、関数定義内のみで使用可能です。', node);
717
- }
718
- const astValue = node.blocks[0];
719
- const lno = this.convLineno(node, false);
720
- // 戻り値のコードを得る
721
- let value = '';
722
- if (astValue.type !== 'nop') {
723
- value = this._convGen(astValue, true);
724
- }
725
- else if (this.speedMode.invalidSore === 0) {
726
- value = this.varname_get('それ');
727
- }
728
- // 戻り値のない関数の場合
729
- if (value === '') {
730
- return lno + 'return;';
731
- }
732
- // 戻り値がundefindかをチェックするかどうか
733
- if (!this.warnUndefinedReturnUserFunc) {
734
- return lno + `return ${value};`;
735
- }
736
- else {
737
- const funcName = (this.defFuncName) ? this.defFuncName : '無名関数';
738
- const poolIndex = this.addConstPool(`ユーザ関数『${funcName}』からundefinedが返されています`, [], node.file, node.line);
739
- return lno + `return (__self.chk(${value}, ${poolIndex}));`;
740
- }
741
- }
742
- getConstPoolsTemplateId(msg) {
743
- let id = this.constPoolsTemplate.indexOf(msg);
744
- if (id < 0) {
745
- id = this.constPoolsTemplate.length;
746
- this.constPoolsTemplate[id] = msg;
747
- }
748
- return id;
749
- }
750
- addConstPool(msg, args, file, line) {
751
- // file
752
- file = String(file);
753
- const fileNo = this.getConstPoolsTemplateId(file);
754
- // msg
755
- const msgNo = this.getConstPoolsTemplateId(msg);
756
- // args
757
- const args2 = [];
758
- for (const arg of args) {
759
- const argStr = '' + String(arg);
760
- const argNo = this.getConstPoolsTemplateId(argStr);
761
- args2.push(argNo);
762
- }
763
- const poolIndex = this.constPools.length;
764
- this.constPools.push([msgNo, args2, fileNo, line]);
765
- return poolIndex;
766
- }
767
- convCheckLoop(node, cmd) {
768
- // ループの中であれば利用可能
769
- if (!this.flagLoop) {
770
- const cmdj = (cmd === 'continue') ? '続ける' : '抜ける';
771
- throw NakoSyntaxError.fromNode(`『${cmdj}』文がありますが、それは繰り返しの中で利用してください。`, node);
772
- }
773
- return this.convLineno(node) + cmd + ';';
774
- }
775
- convDefFuncCommon(node, name) {
776
- // 定義中の関数名を記録
777
- this.defFuncName = name;
778
- // 変数をJS変数に展開するかどうか (TODO)
779
- const isExtractJS = false;
780
- // パフォーマンスモニタ:ユーザ関数のinjectの定義
781
- let performanceMonitorInjectAtStart = '';
782
- let performanceMonitorInjectAtEnd = '';
783
- if (this.performanceMonitor.userFunction !== 0) {
784
- let key = name;
785
- if (!key) {
786
- if (typeof this.performanceMonitor.mumeiId === 'undefined') {
787
- this.performanceMonitor.mumeiId = 0;
788
- }
789
- this.performanceMonitor.mumeiId++;
790
- key = `anous_${this.performanceMonitor.mumeiId}`;
791
- }
792
- performanceMonitorInjectAtStart = 'const performanceMonitorEnd = (function (key, type) {\n' +
793
- 'const uf_start = performance.now() * 1000;\n' +
794
- 'return function () {\n' +
795
- 'const el_time = performance.now() * 1000 - uf_start;\n' +
796
- 'if (!__self.__performance_monitor) {\n' +
797
- '__self.__performance_monitor={};\n' +
798
- '__self.__performance_monitor[key] = { called:1, totel_usec: el_time, min_usec: el_time, max_usec: el_time, type: type };\n' +
799
- '} else if (!__self.__performance_monitor[key]) {\n' +
800
- '__self.__performance_monitor[key] = { called:1, totel_usec: el_time, min_usec: el_time, max_usec: el_time, type: type };\n' +
801
- '} else {\n' +
802
- '__self.__performance_monitor[key].called++;\n' +
803
- '__self.__performance_monitor[key].totel_usec+=el_time;\n' +
804
- 'if(__self.__performance_monitor[key].min_usec>el_time){__self.__performance_monitor[key].min_usec=el_time;}\n' +
805
- 'if(__self.__performance_monitor[key].max_usec<el_time){__self.__performance_monitor[key].max_usec=el_time;}\n' +
806
- `}};})('${key}', 'user');` +
807
- 'try {\n';
808
- performanceMonitorInjectAtEnd = '} finally { performanceMonitorEnd(); }\n';
809
- }
810
- let variableDeclarations = '';
811
- const indent = ' ';
812
- let pushStack = '';
813
- let popStack = '';
814
- const initialNames = new Set();
815
- if (this.speedMode.invalidSore === 0) {
816
- initialNames.add('それ');
817
- }
818
- this.varsSet = { isFunction: true, names: initialNames, readonly: new Set() };
819
- // ローカル変数をPUSHする
820
- this.varslistSet.push(this.varsSet);
821
- const funcContext = {
822
- isAnonymous: name === '',
823
- varsIndex: this.varslistSet.length - 1,
824
- usesClosure: false
825
- };
826
- this.functionContextStack.push(funcContext);
827
- // JSの引数と引数をバインド
828
- if (isExtractJS) {
829
- variableDeclarations += indent + 'var 引数 = arguments;\n';
830
- }
831
- else {
832
- variableDeclarations += indent + '__self.__vars.set(\'引数\', arguments);\n';
833
- }
834
- // ローカル変数を生成 (再帰関数呼び出しで引数の値が壊れる問題があるので修正 #1663 / タイミングによって壊れるので修理 #1758)
835
- // 暫定変数__localVarsに現在のローカル変数の値をPUSHし、変数を抜ける時にPOPする)
836
- // 関数として宣言しているが、JS関数となでしこ関数では変数管理の方法が異なるため、完全なローカル変数としては使えない
837
- // 必ず、pushStack/popStack する必要がある
838
- pushStack += '\n// PUSH STACK\n';
839
- pushStack += 'const __localvars = __self.__vars;\n';
840
- pushStack += '__self.__vars = new Map();\n';
841
- pushStack += 'try {\n';
842
- popStack += '} finally {\n';
843
- popStack += indent + '// POP STACK\n';
844
- popStack += indent + 'self.__vars = __localvars;\n';
845
- popStack += '}\n';
846
- // 宣言済みの名前を保存
847
- const varsDeclared = Array.from(this.varsSet.names.values());
848
- let code = '';
849
- // 引数をローカル変数に設定
850
- const meta = node.meta;
851
- if (!meta) {
852
- throw new Error('[System Error] 関数の定義でメタ情報が指定されていません');
853
- }
854
- if (!meta.varnames) {
855
- meta.varnames = [];
856
- }
857
- for (let i = 0; i < meta.varnames.length; i++) {
858
- const word = meta.varnames[i];
859
- if (word === '引数') {
860
- continue;
861
- }
862
- if (!this.warnUndefinedCalledUserFuncArgs) {
863
- code += indent + this.varname_set(word, `arguments[${i}]`) + ';\n';
864
- }
865
- else {
866
- // check undefined
867
- let errMsg = `匿名関数の引数『${word}』にundefinedが渡されました`;
868
- if (name) {
869
- errMsg = `ユーザ関数『${name}』の引数『${word}』にundefinedが渡されました`;
870
- }
871
- const warnJS = `__self.logger.warn('${errMsg}', {line: ${node.line}, file: ${JSON.stringify(node.file)}});`;
872
- const checkFunc = `((a) => { if (a === undefined) { ${warnJS} }; return a; })`;
873
- const callCheckFunc = `${checkFunc}(arguments[${i}])`;
874
- code += indent + this.varname_set(word, callCheckFunc) + ';\n';
875
- }
876
- this.varsSet.names.add(word);
877
- }
878
- // 関数定義は、グローバル領域で。
879
- if (name) {
880
- this.usedFuncSet.add(name);
881
- this.varslistSet[1].names.add(name);
882
- if (this.nakoFuncList.get(name) === undefined) {
883
- if (!node.meta) {
884
- throw new Error('[System Error] 関数の定義でメタ情報が指定されていません');
885
- }
886
- // 既に generate で作成済みのはず(念のため)
887
- this.nakoFuncList.set(name, {
888
- josi: node.meta.josi,
889
- fn: () => { },
890
- type: 'func',
891
- asyncFn: false,
892
- isExport: null
893
- });
894
- this.__self.getLogger().warn(`generateで未定義の状態の関数『${name}』が動的に登録されています。`);
895
- }
896
- }
897
- // ブロックを解析
898
- const oldUsedAsyncFn = this.usedAsyncFn;
899
- this.usedAsyncFn = false;
900
- if (this.debugOption.useDebug) {
901
- this.usedAsyncFn = true;
902
- }
903
- const block = this._convGen(node.blocks[0], false);
904
- code += block.split('\n').map((line) => ' ' + line).join('\n') + '\n';
905
- // 関数の最後に、変数「それ」をreturnするようにする
906
- if (this.speedMode.invalidSore === 0) {
907
- code += ` return (${this.varname_get('それ')});\n`;
908
- }
909
- // パフォーマンスモニタ:ユーザ関数のinject
910
- code += performanceMonitorInjectAtEnd;
911
- // 名前のある関数で非同期関数であれば、関数にasyncを付与する
912
- if (name && this.usedAsyncFn) {
913
- const f = this.nakoFuncList.get(name);
914
- if (f) {
915
- f.asyncFn = true;
916
- }
917
- }
918
- // 関数の末尾に、ローカル変数をPOP
919
- // 関数内で定義されたローカル変数の宣言
920
- if (isExtractJS) {
921
- for (const name of Array.from(this.varsSet.names.values())) {
922
- if (!varsDeclared.includes(name)) {
923
- if (NakoGen.isValidIdentifier(name)) {
924
- variableDeclarations += ` var ${name};\n`;
925
- }
926
- }
927
- }
928
- if (this.speedMode.invalidSore === 0) {
929
- if (NakoGen.isValidIdentifier('それ')) {
930
- variableDeclarations += ' var それ = \'\';\n';
931
- }
932
- else {
933
- variableDeclarations += ` ${this.varname_get('それ')} = '';`;
934
- }
935
- }
936
- }
937
- // usedAsyncFnの値に応じて関数定義の方法を変更
938
- const tof = (this.usedAsyncFn) ? topOfFunctionAsync : topOfFunction;
939
- // 関数コード全体を構築
940
- const lineInfo = ' ' + this.convLineno(node, true, 1) + '\n';
941
- code = tof + performanceMonitorInjectAtStart + pushStack + variableDeclarations + lineInfo + code + popStack;
942
- code += endOfFunction;
943
- if (funcContext.isAnonymous && funcContext.usesClosure) {
944
- const parentClosure = `(typeof __nako_closure === 'undefined' ? null : __nako_closure)`;
945
- code = `(function(__nako_closure) {\n return ${code}\n})(__nako_make_closure(__self.__vars, ${parentClosure}))`;
946
- }
947
- // 名前があれば、関数を登録する
948
- if (name) {
949
- const nameFuncValue = this.nakoFuncList.get(name);
950
- if (nameFuncValue) {
951
- nameFuncValue.fn = code;
952
- nameFuncValue.asyncFn = this.usedAsyncFn;
953
- meta.asyncFn = this.usedAsyncFn;
954
- }
955
- }
956
- this.usedAsyncFn = oldUsedAsyncFn; // 以前の値を戻す
957
- this.varslistSet.pop();
958
- this.functionContextStack.pop();
959
- this.varsSet = this.varslistSet[this.varslistSet.length - 1];
960
- if (name) {
961
- this.__self.__varslist[1].set(name, code);
962
- }
963
- this.defFuncName = ''; // 関数名をクリア
964
- return code;
965
- }
966
- convDefTest(node) {
967
- const name = node.name;
968
- let code = `__tests.push({ name: '${name}', f: () => {\n`;
969
- // ブロックを解析
970
- const block = this._convGen(node.blocks[0], false);
971
- code += ` ${block}\n` +
972
- '}});';
973
- if (!node.meta) {
974
- throw new Error('[System Error] テストのメタ情報が指定されていません');
975
- }
976
- this.nakoTestFuncs.set(name, {
977
- josi: node.meta.josi,
978
- fn: code,
979
- type: 'test_func'
980
- });
981
- // ★この時点ではテストコードを生成しない★
982
- // プログラム冒頭でコード生成時にテストの定義を行う
983
- return '';
984
- }
985
- convDefFunc(node) {
986
- // ※ [関数定義のメモ]
987
- // ※ 関数の定義はプログラムの冒頭に移される。
988
- // ※ そのため、生成されたコードはここでは返さない
989
- // ※ registerFunction を参照
990
- if (!node.name) {
991
- return '';
992
- }
993
- const name = NakoGen.getFuncName(node.name);
994
- this.convDefFuncCommon(node, name);
995
- return '';
996
- }
997
- convFuncObj(node) {
998
- return '/*convFuncObj*/' + this.convDefFuncCommon(node, '');
999
- }
1000
- convJsonObj(node) {
1001
- const resultArray = [];
1002
- const list = node.blocks;
1003
- for (let i = 0; i < list.length / 2; i++) {
1004
- const idx = i * 2;
1005
- const key = list[idx + 0];
1006
- const val = list[idx + 1];
1007
- const keyStr = this._convGen(key, true);
1008
- const valStr = this._convGen(val, true);
1009
- resultArray.push(`${keyStr}: ${valStr}`);
1010
- }
1011
- return '{' + resultArray.join(', ') + '}';
1012
- }
1013
- convJsonArray(node) {
1014
- const list = node.blocks;
1015
- const codelist = list.map((e) => {
1016
- return this._convGen(e, true);
1017
- });
1018
- return '[' + codelist.join(',') + ']';
1019
- }
1020
- convRefArray(node) {
1021
- let code = '';
1022
- code = this._convGen(node.name, true);
1023
- const list = node.index;
1024
- if (!list) {
1025
- return code;
1026
- }
1027
- for (let i = 0; i < list.length; i++) {
1028
- const idx = this._convGen(list[i], true);
1029
- code += '[' + idx + ']';
1030
- }
1031
- return code;
1032
- }
1033
- convRefArrayValue(node) {
1034
- let code = '';
1035
- const op = node.name ? String(node.name) : '???';
1036
- const val = node.index ? node.index.shift() : undefined;
1037
- if (!val) {
1038
- return '/*[WARNING] convRefArrayOperator::InvalidValue */';
1039
- }
1040
- code = this._convGen(val, true);
1041
- const list = node.index;
1042
- if (!list) {
1043
- return code;
1044
- }
1045
- if (op === '@' || op === '[') {
1046
- for (let i = 0; i < list.length; i++) {
1047
- const idx = this._convGen(list[i], true);
1048
- code += '[' + idx + ']';
1049
- }
1050
- return code;
1051
- }
1052
- if (op === '$') {
1053
- return this.convRefProp_genCode(code, list);
1054
- }
1055
- // operator not found
1056
- const op2 = op.replace('*/', '*/');
1057
- return `/* [WARNING] convRefArrayOperator::UnknownOperator [${op2}] */` + code;
1058
- }
1059
- convLetArray(node) {
1060
- const id = this.loopId++;
1061
- const valueNode = node.blocks[0];
1062
- const indexNodes = node.blocks.slice(1);
1063
- const name = this.genVar(node.name, node);
1064
- let codeInit = '';
1065
- let code = name;
1066
- let codeArray = '';
1067
- // codeInit?
1068
- if (node.checkInit) { // DNCLのための初期化処理 ... DNCLでは配列の初期化なしでいきなり配列を使う試験問題があるため
1069
- const arrayDefCode = '[0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0]';
1070
- // [name]の内容は[__self.__varslist[2].get("a__A")]のようなものになっているはず
1071
- if (node.name) {
1072
- const word = node.name;
1073
- const tmpVar = `$nako_tmp_a${id}`;
1074
- const initArrayCode = this.varname_set(word, arrayDefCode);
1075
- codeInit += `\n/*配列初期化*/if (!(${name} instanceof Array)) { ${initArrayCode} };\n`;
1076
- codeInit += `${tmpVar} = ${name};\n`;
1077
- for (let i = 0; i < indexNodes.length - 1; i++) {
1078
- const idx = this._convGen(indexNodes[i], true);
1079
- codeArray += `[${idx}]`;
1080
- codeInit += `\n/*配列初期化${i}*/if (!(${tmpVar}${codeArray} instanceof Array)) { ${tmpVar}${codeArray} = ${arrayDefCode}; };`;
1081
- }
1082
- codeInit += '\n';
1083
- }
1084
- }
1085
- // array
1086
- for (let i = 0; i < indexNodes.length; i++) {
1087
- const idx = this._convGen(indexNodes[i], true);
1088
- code += '[' + idx + ']';
1089
- }
1090
- // value
1091
- let value = null;
1092
- if (this.speedMode.invalidSore === 0) {
1093
- value = this.varname_get('それ');
1094
- }
1095
- if (valueNode.type !== 'nop') {
1096
- value = this._convGen(valueNode, true);
1097
- }
1098
- if (value === null) {
1099
- throw NakoSyntaxError.fromNode('代入する先の変数名がありません。', node);
1100
- }
1101
- code += ' = ' + value + ';\n';
1102
- // generate code
1103
- const src = this.convLineno(node, false) + codeInit + code;
1104
- return src;
1105
- }
1106
- convGenLoop(node) {
1107
- const tmpflag = this.flagLoop;
1108
- this.flagLoop = true;
1109
- try {
1110
- return this._convGen(node, false);
1111
- }
1112
- finally {
1113
- this.flagLoop = tmpflag;
1114
- }
1115
- }
1116
- convFor(node) {
1117
- const astFrom = node.blocks[0];
1118
- const astTo = node.blocks[1];
1119
- const astInc = node.blocks[2];
1120
- const astBlock = node.blocks[3];
1121
- // forのIDを取得
1122
- const idLoop = this.loopId++;
1123
- const varI = `$nako_i${idLoop}`;
1124
- // ループ変数について
1125
- let loopVarSetter = '';
1126
- if (node.word !== '') { // ループ変数を使う時
1127
- const varName = node.word;
1128
- this.varsSet.names.add(varName);
1129
- loopVarSetter = this.varname_set(varName, varI);
1130
- }
1131
- // ループ条件を変数に入れる用
1132
- const varFrom = `$nako_from${idLoop}`;
1133
- const varTo = `$nako_to${idLoop}`;
1134
- const varTemp = `$nako_temp${idLoop}`;
1135
- let sorePrefex = '';
1136
- if (this.speedMode.invalidSore === 0) {
1137
- sorePrefex = this.varname_set('それ', varI);
1138
- }
1139
- // ループ条件を確認
1140
- let kara = '0';
1141
- let made = '0';
1142
- let temp = '0';
1143
- if (astTo && astTo.type === 'func' && astTo.name === '範囲') {
1144
- temp = this._convGen(astTo, true);
1145
- kara = `${varTemp}['先頭'] || 0`;
1146
- made = `${varTemp}['末尾'] || 0`;
1147
- }
1148
- else {
1149
- kara = this._convGen(astFrom, true);
1150
- made = this._convGen(astTo, true);
1151
- }
1152
- const flagDown = node.flagDown;
1153
- const flagUp = node.flagUp;
1154
- let inc = '1';
1155
- if (astInc.type !== 'nop') {
1156
- inc = this._convGen(astInc, true);
1157
- }
1158
- // ループ内のブロック内容を得る
1159
- const block = this.convGenLoop(astBlock);
1160
- const code = this.convLineno(node, false) + '\n' +
1161
- `/*[convFor id=${idLoop}]*/\n` +
1162
- `const ${varTemp} = ${temp};\n` +
1163
- `const ${varFrom} = ${kara};\n` +
1164
- `const ${varTo} = ${made};\n` +
1165
- `if (${varFrom} < ${varTo}) { // up\n` +
1166
- ` if (${String(flagUp)}) {` +
1167
- ` for (let ${varI} = ${varFrom}; ${varI} <= ${varTo}; ${varI}+= ${inc}) {\n` +
1168
- ` ${sorePrefex};${loopVarSetter}\n` +
1169
- ' // for block begin\n' +
1170
- ` ${block}\n` +
1171
- ' // for block end\n' +
1172
- ' };\n' +
1173
- ' };\n' +
1174
- `} else if (${varFrom} > ${varTo}) { // down\n` +
1175
- ` if (${String(flagDown)}) {` +
1176
- ` for (let ${varI} = ${varFrom}; ${varI} >= ${varTo}; ${varI}-= ${inc}) {\n` +
1177
- ` ${sorePrefex};${loopVarSetter}\n` +
1178
- ' // for block begin\n' +
1179
- ` ${block}\n` +
1180
- ' // for block end\n' +
1181
- ' }\n' +
1182
- ' };\n' +
1183
- '} else { // from == to\n' +
1184
- ` for (let ${varI} = ${varFrom}; ${varI} <= ${varTo}; ${varI}+= 1) {\n` +
1185
- ` ${sorePrefex};${loopVarSetter}\n` +
1186
- ' // for block begin\n' +
1187
- ` ${block}\n` +
1188
- ' // for block end\n' +
1189
- ' };\n' +
1190
- '};\n' +
1191
- `//[/convFor id=${idLoop}]\n`;
1192
- return code;
1193
- }
1194
- convForeach(node) {
1195
- const exprAst = node.blocks[0];
1196
- const blockAst = node.blocks[1];
1197
- // foreachのIDを取得
1198
- const id = this.loopId++;
1199
- const loopKeyVar = `$nako_i${id}`;
1200
- const loopValueVar = `$nako_foreach_value${id}`;
1201
- const loopDataVar = `$nako_foreach_data${id}`;
1202
- const taisyouTemp = `$nako_taisyou_temp${id}`;
1203
- const taisyouKeyTemp = `$nako_taisyou_key_temp${id}`;
1204
- const soreTemp = `$nako_foreach_sore_temp${id}`;
1205
- // 「対象」「対象キー」を取得 --- blockより早く変数を定義する必要がある
1206
- let taisyoPrefex = this.varname_set_sys('対象', loopValueVar);
1207
- if (node.word !== '') { // 対象変数がある場合、対象は設定されない
1208
- const valueVar = node.word;
1209
- this.varsSet.names.add(valueVar);
1210
- taisyoPrefex = this.varname_set(valueVar, loopValueVar);
1211
- }
1212
- const keyVar = '対象キー';
1213
- const keySetter = this.varname_set_sys(keyVar, loopKeyVar);
1214
- // 「それ」(対象のエイリアス)の設定
1215
- let sorePrefex = '';
1216
- let soreRecover = '';
1217
- let soreBackup = '';
1218
- if (this.speedMode.invalidSore === 0) {
1219
- sorePrefex = this.varname_set('それ', loopValueVar);
1220
- soreRecover = this.varname_set('それ', soreTemp);
1221
- soreBackup = `let ${soreTemp} = ` + this.varname_get('それ') + ';';
1222
- }
1223
- // 反復するデータを取得
1224
- let targetData = '';
1225
- if (exprAst.type === 'nop') {
1226
- if (this.speedMode.invalidSore === 0) {
1227
- targetData = this.varname_get('それ');
1228
- }
1229
- else {
1230
- throw NakoSyntaxError.fromNode('『反復』の対象がありません。', node);
1231
- }
1232
- }
1233
- else {
1234
- targetData = this._convGen(exprAst, true);
1235
- }
1236
- // 反復するブロックを取得
1237
- const block = trim(cleanGeneratedCode(this.convGenLoop(blockAst), 1));
1238
- // コードを生成
1239
- const code = this.convLineno(node, false) + '\n' +
1240
- `// [convForeach id=${id}]\n` +
1241
- `const ${taisyouTemp} = __self.__getSysVar('対象'); ${soreBackup}; ` +
1242
- `const ${taisyouKeyTemp} = __self.__getSysVar('対象キー');\n` +
1243
- `let ${loopDataVar} = ${targetData};\n` +
1244
- '// foreach Map?\n' +
1245
- `if (${loopDataVar} instanceof Map) { // Objectに強制変換\n` +
1246
- ` let tmp = {}; for (let tmpKey of ${loopDataVar}.keys()) { tmp[tmpKey] = ${loopDataVar}.get(tmpKey); }; \n` +
1247
- ` ${loopDataVar} = tmp;\n` +
1248
- '}\n' +
1249
- `for (let ${loopKeyVar} in ${loopDataVar}) {\n` +
1250
- ` if (!${loopDataVar}.hasOwnProperty(${loopKeyVar})) { continue }\n` +
1251
- ' // 対象キーの設定\n' +
1252
- ` ${keySetter}\n` +
1253
- ' // 対象の設定\n' +
1254
- ` let ${loopValueVar} = $nako_foreach_data${id}[${loopKeyVar}]\n` +
1255
- ` ${sorePrefex};\n` +
1256
- ` ${taisyoPrefex};\n` +
1257
- ' // [convForeach::block]\n' +
1258
- ` ${block}\n` +
1259
- ' // [/convForeach::block]\n' +
1260
- '}\n' +
1261
- `__self.__setSysVar('対象', ${taisyouTemp});${soreRecover};` +
1262
- `__self.__setSysVar('対象キー', ${taisyouKeyTemp});` +
1263
- `// [/convForeach id=${id}]\n`;
1264
- return code;
1265
- }
1266
- convRepeatTimes(node) {
1267
- // ループのIDを取得
1268
- const id = this.loopId++;
1269
- const varI = `$nako_i${id}`;
1270
- const varCount = `$nako_times_data${id}`;
1271
- const varKaisuTemp = `$nako_kaisu_temp${id}`;
1272
- const codeCount = this._convGen(node.blocks[0], true);
1273
- // ブロックを得る
1274
- const block = trim(cleanGeneratedCode(this.convGenLoop(node.blocks[1]), 1));
1275
- // それ
1276
- let sorePrefex = '';
1277
- let soreRecover = '';
1278
- if (this.speedMode.invalidSore === 0) {
1279
- sorePrefex = this.varname_set('それ', varI);
1280
- soreRecover = this.varname_set('それ', varKaisuTemp);
1281
- }
1282
- // 回数
1283
- sorePrefex += `;__self.__setSysVar('回数', ${varI});`;
1284
- soreRecover += `;__self.__setSysVar('回数', ${varKaisuTemp});`;
1285
- const code = this.convLineno(node, false) + '\n' +
1286
- `// [convRepeatTimes id=${id}] // 『n回』構文\n` +
1287
- `let ${varKaisuTemp} = __self.__getSysVar('回数')\n` +
1288
- `let ${varCount} = ${codeCount};\n` +
1289
- `for (let ${varI} = 1; ${varI} <= ${varCount}; ${varI}++) {\n` +
1290
- ` ${sorePrefex}\n` +
1291
- ` ${block}\n` +
1292
- '}\n' +
1293
- `${soreRecover}\n` +
1294
- `// [/convRepeatTimes id=${id}]\n`;
1295
- return code;
1296
- }
1297
- /**
1298
- * @param {Ast} node
1299
- * @param {boolean} isExpression
1300
- */
1301
- convSpeedMode(node, isExpression) {
1302
- if (!node.options) {
1303
- return '';
1304
- }
1305
- const prev = { ...this.speedMode };
1306
- if (node.options['行番号無し']) {
1307
- this.speedMode.lineNumbers++;
1308
- }
1309
- if (node.options['暗黙の型変換無し']) {
1310
- this.speedMode.implicitTypeCasting++;
1311
- }
1312
- if (node.options['強制ピュア']) {
1313
- this.speedMode.forcePure++;
1314
- }
1315
- if (node.options['それ無効']) {
1316
- this.speedMode.invalidSore++;
1317
- }
1318
- try {
1319
- return this._convGen(node.blocks[0], isExpression);
1320
- }
1321
- finally {
1322
- this.speedMode = prev;
1323
- }
1324
- }
1325
- /**
1326
- * @param {Ast} node
1327
- * @param {boolean} isExpression
1328
- */
1329
- convPerformanceMonitor(node, isExpression) {
1330
- const prev = { ...this.performanceMonitor };
1331
- if (!node.options) {
1332
- return '';
1333
- }
1334
- if (node.options['ユーザ関数']) {
1335
- this.performanceMonitor.userFunction++;
1336
- }
1337
- if (node.options['システム関数本体']) {
1338
- this.performanceMonitor.systemFunctionBody++;
1339
- }
1340
- if (node.options['システム関数']) {
1341
- this.performanceMonitor.systemFunction++;
1342
- }
1343
- try {
1344
- return this._convGen(node.blocks[0], isExpression);
1345
- }
1346
- finally {
1347
- this.performanceMonitor = prev;
1348
- }
1349
- }
1350
- convWhile(node) {
1351
- const exprAst = node.blocks[0];
1352
- const blockAst = node.blocks[1];
1353
- const cond = this._convGen(exprAst, true);
1354
- const block = trim(cleanGeneratedCode(this.convGenLoop(blockAst), 1));
1355
- const code = '// [convWhile]\n' +
1356
- this.convLineno(node, false) + '\n' +
1357
- `while (${cond})` + '{\n' +
1358
- ` ${block}` + '\n' +
1359
- '}\n' +
1360
- '// [convWhile]\n';
1361
- return code;
1362
- }
1363
- convAtohantei(node) {
1364
- const id = this.loopId++;
1365
- const varId = `$nako_i${id}`;
1366
- const cond = this._convGen(node.blocks[0], true);
1367
- const block = this.convGenLoop(node.blocks[1]);
1368
- const code = 'while (true) {\n' +
1369
- ` ${block}\n` +
1370
- ` let ${varId} = ${cond};\n` +
1371
- ` if (${varId}) { continue } else { break }\n` +
1372
- '}\n\n';
1373
- return this.convLineno(node, false) + code;
1374
- }
1375
- convSwitch(node) {
1376
- const expr = this._convGen(node.blocks[0], true);
1377
- const defaultStr = this._convGen(node.blocks[1], false);
1378
- let body = '';
1379
- for (let i = 0; i < node.case_count; i++) {
1380
- const caseIndex = i * 2 + 2;
1381
- const condStr = this._convGen(node.blocks[caseIndex + 0], true);
1382
- const blockStr = this.convGenLoop(node.blocks[caseIndex + 1]);
1383
- body += ` case ${condStr}:\n`;
1384
- body += ` ${blockStr}\n` +
1385
- ' break\n';
1386
- }
1387
- const code = '// [switch]\n' +
1388
- `switch (${expr})` + '{\n' +
1389
- `${body}` + '\n' +
1390
- ' default:\n' +
1391
- ` ${defaultStr}\n` +
1392
- '}\n' +
1393
- '// [/switch]\n';
1394
- return this.convLineno(node, false) + code;
1395
- }
1396
- convIf(node) {
1397
- const exprAst = node.blocks[0];
1398
- const trueAst = node.blocks[1];
1399
- const falseAst = node.blocks[2];
1400
- // 条件
1401
- const expr = this._convGen(exprAst, true);
1402
- // TRUEブロック
1403
- const trueBlock = trim(cleanGeneratedCode(this._convGen(trueAst, false), 1));
1404
- // FALSEブロック
1405
- const falseBlock = trim(cleanGeneratedCode(this._convGen(falseAst, false), 1));
1406
- let code = '// [convIf]\n' +
1407
- this.convLineno(node, false) + '\n' +
1408
- `if (${expr}) {\n` +
1409
- ` ${trueBlock}\n` +
1410
- '}';
1411
- if (trim(falseBlock) !== '') {
1412
- code +=
1413
- ' else {\n' +
1414
- ` ${falseBlock}\n` +
1415
- '}\n';
1416
- }
1417
- code += '\n// [/convIf]\n';
1418
- return code;
1419
- }
1420
- convFuncGetArgsCalcType(_funcName, _func, node) {
1421
- const args = [];
1422
- const opts = {};
1423
- const nodeArgs = (node.blocks) ? node.blocks : [];
1424
- for (let i = 0; i < nodeArgs.length; i++) {
1425
- const arg = nodeArgs[i];
1426
- if (i === 0 && arg === null && this.speedMode.invalidSore === 0) {
1427
- args.push(this.varname_get('それ'));
1428
- opts.sore = true;
1429
- }
1430
- else {
1431
- let argCode = this._convGen(arg, true);
1432
- if (argCode === '') {
1433
- argCode = 'undefined';
1434
- }
1435
- if (typeof argCode !== 'string') {
1436
- argCode = 'undefined';
1437
- }
1438
- args.push(`/*arg${i}*/${argCode}`);
1439
- }
1440
- }
1441
- return [args, opts];
1442
- }
1443
- getPluginList() {
1444
- const r = [];
1445
- for (const name in this.__self.__module) {
1446
- r.push(name);
1447
- }
1448
- return r;
1449
- }
1450
- /**
1451
- * 関数の呼び出し
1452
- * @param {Ast} node
1453
- * @param {boolean} isExpression
1454
- * @returns string コード
1455
- */
1456
- convCallFunc(node, isExpression) {
1457
- const funcName = NakoGen.getFuncName(node.name);
1458
- const res = this.findVar(funcName);
1459
- if (res === null) {
1460
- throw NakoSyntaxError.fromNode(`関数『${funcName}』が見当たりません。有効プラグイン=[` + this.getPluginList().join(', ') + ']', node);
1461
- }
1462
- // どの関数を呼び出すのか関数を特定する
1463
- let func;
1464
- if (res.i === 0) { // plugin function
1465
- func = this.__self.getFunc(funcName);
1466
- if (!func) {
1467
- throw new Error(`[System Error] 関数「${funcName}」NakoCompiler.nakoFuncList の不整合があります。`);
1468
- }
1469
- if (func.type !== 'func') {
1470
- throw NakoSyntaxError.fromNode(`『${funcName}』は関数ではありません。`, node);
1471
- }
1472
- }
1473
- else {
1474
- func = this.nakoFuncList.get(funcName);
1475
- // 無名関数の可能性
1476
- if (func === undefined) {
1477
- func = { return_none: false, asyncFn: !!node.asyncFn };
1478
- }
1479
- }
1480
- // 関数の参照渡しか?
1481
- if (node.type === 'func_pointer') {
1482
- return res.js;
1483
- }
1484
- // 関数の参照渡しでない場合
1485
- // 関数定義より助詞を一つずつ調べる
1486
- const argsInfo = this.convFuncGetArgsCalcType(funcName, func, node);
1487
- const args = argsInfo[0];
1488
- const argsOpts = argsInfo[1];
1489
- // function
1490
- this.usedFuncSet.add(funcName);
1491
- if (funcName === '名前空間設定') {
1492
- return `\n// --- 名前空間(${args[0]}) ---\n__self.__varslist[0].get('名前空間設定')(${args[0]}, __self);__self.__modName=${args[0]};\n`;
1493
- }
1494
- else if (funcName === 'プラグイン名設定') {
1495
- return `\n__self.__varslist[0].get('プラグイン名設定')(${args[0]}, __self);\n`;
1496
- }
1497
- // 関数呼び出しで、引数の末尾にthisを追加する-システム情報を参照するため
1498
- args.push('__self');
1499
- let funcDef = 'function';
1500
- let funcBegin = '';
1501
- let funcEnd = '';
1502
- // setter?
1503
- if (node.setter) {
1504
- funcBegin += ';__self.isSetter = true;\n';
1505
- funcEnd += ';__self.isSetter = false;\n';
1506
- }
1507
- // 関数内 (__varslist.length > 3) からプラグイン関数 (res.i === 0) を呼び出すとき、 そのプラグイン関数がpureでなければ
1508
- // 呼び出しの直前に全てのローカル変数をthis.__localsに入れる。
1509
- if (res.i === 0 && this.varslistSet.length > 3 && func.pure !== true && this.speedMode.forcePure === 0) { // undefinedはfalseとみなす
1510
- // 展開されたローカル変数の列挙
1511
- const localVars = [];
1512
- for (const name of Array.from(this.varsSet.names.values())) {
1513
- if (NakoGen.isValidIdentifier(name)) {
1514
- localVars.push({ str: JSON.stringify(name), js: this.varname_get(name) });
1515
- }
1516
- }
1517
- // --- 実行前 ---
1518
- // 全ての展開されていないローカル変数を __self.__locals にコピーする
1519
- funcBegin += '__self.__locals = __vars;\n';
1520
- // 全ての展開されたローカル変数を __self.__locals に保存する
1521
- if (localVars.length > 0) {
1522
- funcBegin += '/* 全ての展開されたローカル変数を __self.__locals に保存 */\n';
1523
- for (const v of localVars) {
1524
- funcBegin += `__self.__locals.set(${v.str}, ${v.js});\n`;
1525
- }
1526
- }
1527
- // --- 実行後 ---
1528
- // 全ての展開されたローカル変数を __self.__locals から受け取る
1529
- // 「それ」は関数の実行結果を受け取るために使うためスキップ。
1530
- if (localVars.length > 0) {
1531
- funcEnd += '/* 全ての展開されたローカル変数を __self.__locals から受け取る */\n';
1532
- for (const v of localVars) {
1533
- if (v.js !== 'それ') {
1534
- funcEnd += `__self.__varslist[2].set(${v.str}, __self.__locals[${v.str}]);\n`;
1535
- }
1536
- }
1537
- }
1538
- }
1539
- // 変数「それ」が補完されていることをヒントとして出力
1540
- if (argsOpts.sore) {
1541
- funcBegin += '/*[sore]*/';
1542
- }
1543
- const indent = (text, n) => {
1544
- let result = '';
1545
- for (const line of text.split('\n')) {
1546
- if (line !== '') {
1547
- result += ' '.repeat(n) + line + '\n';
1548
- }
1549
- }
1550
- return result;
1551
- };
1552
- // 引数チェックの例外 #1260
1553
- const noCheckFuncs = { 'TYPEOF': true, '変数型確認': true };
1554
- // 関数呼び出しコードの構築
1555
- let argsCode;
1556
- if ((!this.warnUndefinedCallingUserFunc && res.i !== 0) || (!this.warnUndefinedCallingSystemFunc && res.i === 0)) {
1557
- argsCode = args.join(',');
1558
- }
1559
- else {
1560
- const argsA = [];
1561
- args.forEach((arg) => {
1562
- if (arg === '__self' || noCheckFuncs[funcName] === true) { // #1260
1563
- argsA.push(`${arg}`);
1564
- }
1565
- else {
1566
- // 引数のundefinedチェックのコードを入れる
1567
- const msg = (res.i === 0) ? '命令『$0』の引数にundefinedを渡しています。' : 'ユーザ命令『$0』の引数にundefinedを渡しています。';
1568
- const poolIndex = this.addConstPool(msg, [funcName], node.file, node.line);
1569
- // argが空になる対策 #1315
1570
- const argStr = (arg === '') ? '""' : arg;
1571
- argsA.push(`(__self.chk(${argStr}, ${poolIndex}))`);
1572
- }
1573
- });
1574
- argsCode = argsA.join(', ');
1575
- }
1576
- let funcCall = `${res.js}(${argsCode})`;
1577
- if (func.asyncFn) {
1578
- funcDef = `async ${funcDef}`;
1579
- funcCall = `await ${funcCall}`;
1580
- this.numAsyncFn++;
1581
- this.usedAsyncFn = true;
1582
- // 非同期関数の呼び出し前に __self.__vars を待避しておく必要がある (#1758)
1583
- const varI = `$nako_i${this.loopId}`;
1584
- this.loopId++;
1585
- funcBegin += `const __local_async${varI} = __self.__vars;\n`;
1586
- funcEnd += `__self.__vars = __local_async${varI};\n`;
1587
- }
1588
- if (res.i === 0 && this.performanceMonitor.systemFunctionBody !== 0) {
1589
- let key = funcName;
1590
- if (!key) {
1591
- if (typeof this.performanceMonitor.mumeiId === 'undefined') {
1592
- this.performanceMonitor.mumeiId = 0;
1593
- }
1594
- this.performanceMonitor.mumeiId++;
1595
- key = `anous_${this.performanceMonitor.mumeiId}`;
1596
- }
1597
- funcCall = `(${funcDef} (key, type) {\n` +
1598
- 'const sbf_start = performance.now() * 1000;\n' +
1599
- 'try {\n' +
1600
- 'return ' + funcCall + ';\n' +
1601
- '} finally {\n' +
1602
- 'const sbl_time = performance.now() * 1000 - sbf_start;\n' +
1603
- 'if (!__self.__performance_monitor) {\n' +
1604
- '__self.__performance_monitor={};\n' +
1605
- '__self.__performance_monitor[key] = { called:1, totel_usec: sbl_time, min_usec: sbl_time, max_usec: sbl_time, type: type };\n' +
1606
- '} else if (!__self.__performance_monitor[key]) {\n' +
1607
- '__self.__performance_monitor[key] = { called:1, totel_usec: sbl_time, min_usec: sbl_time, max_usec: sbl_time, type: type };\n' +
1608
- '} else {\n' +
1609
- '__self.__performance_monitor[key].called++;\n' +
1610
- '__self.__performance_monitor[key].totel_usec+=sbl_time;\n' +
1611
- 'if(__self.__performance_monitor[key].min_usec>sbl_time){__self.__performance_monitor[key].min_usec=sbl_time;}\n' +
1612
- 'if(__self.__performance_monitor[key].max_usec<sbl_time){__self.__performance_monitor[key].max_usec=sbl_time;}\n' +
1613
- `}}})('${funcName}_body', 'sysbody')\n`;
1614
- }
1615
- let code = '';
1616
- if (func.return_none) {
1617
- // ------------------------------------
1618
- // 戻り値のない関数の場合
1619
- // ------------------------------------
1620
- if (funcEnd === '') {
1621
- code = `/*VOID関数呼出*/${funcBegin}${funcCall}\n`;
1622
- }
1623
- else {
1624
- code = `/*VOID関数呼出(前後処理付)*/${funcBegin}try {\n${indent(funcCall, 1)};\n} finally {\n${indent(funcEnd, 1)}}\n`;
1625
- }
1626
- // 行番号を追加
1627
- code = this.convLineno(node, false) + code;
1628
- }
1629
- else {
1630
- // ------------------------------------
1631
- // 戻り値のある関数の場合
1632
- // ------------------------------------
1633
- let sorePrefex = '';
1634
- let sorePostfix = '';
1635
- if (this.speedMode.invalidSore === 0) {
1636
- // 関数の戻り値を記録
1637
- sorePrefex = '__self.__setSore(';
1638
- sorePostfix = ')';
1639
- }
1640
- if (funcBegin === '' && funcEnd === '') {
1641
- code = `${sorePrefex}${funcCall}${sorePostfix}`;
1642
- }
1643
- else {
1644
- if (funcEnd === '') {
1645
- const funcBody = `${sorePrefex}${funcCall}${sorePostfix}`;
1646
- const funcObj = `${funcDef}(){ return ${funcBody} }`;
1647
- const funcCallThis = `(${funcObj}).call(this)`;
1648
- code = `/* funcCallThis1 */${funcCallThis}`;
1649
- }
1650
- else { // つまり、pure=falseの場合
1651
- const varI = `$nako_i${this.loopId}`;
1652
- this.loopId++;
1653
- code = `/* funcCallThis2 */(${funcDef}(){\n` +
1654
- indent(funcBegin, 1) + '\n' +
1655
- indent('try {', 1) + '\n' +
1656
- indent(`let ${varI} = ${funcCall};`, 2) + '\n' +
1657
- indent(`return ${varI};`, 2) + '\n' +
1658
- indent('} finally {', 2) + '\n' +
1659
- indent(funcEnd, 1) + '\n' +
1660
- indent('}', 1) + '\n' +
1661
- '}).call(this)';
1662
- if (func.asyncFn) {
1663
- code = `await (${code})`;
1664
- }
1665
- code = `${sorePrefex}${code}${sorePostfix}`;
1666
- }
1667
- }
1668
- // ...して
1669
- if (node.josi === 'して' || (node.josi === '' && !isExpression)) {
1670
- code = this.convLineno(node, false) + code;
1671
- code += ';\n';
1672
- }
1673
- }
1674
- if (res.i === 0 && this.performanceMonitor.systemFunction !== 0) {
1675
- code = '(function (key, type) {\n' +
1676
- 'const sf_start = performance.now() * 1000;\n' +
1677
- 'try {\n' +
1678
- 'return ' + code + ';\n' +
1679
- '} finally {\n' +
1680
- 'const sl_time = performance.now() * 1000 - sf_start;\n' +
1681
- 'if (!__self.__performance_monitor) {\n' +
1682
- '__self.__performance_monitor={};\n' +
1683
- '__self.__performance_monitor[key] = { called:1, totel_usec: sl_time, min_usec: sl_time, max_usec: sl_time, type: type };\n' +
1684
- '} else if (!__self.__performance_monitor[key]) {\n' +
1685
- '__self.__performance_monitor[key] = { called:1, totel_usec: sl_time, min_usec: sl_time, max_usec: sl_time, type: type };\n' +
1686
- '} else {\n' +
1687
- '__self.__performance_monitor[key].called++;\n' +
1688
- '__self.__performance_monitor[key].totel_usec+=sl_time;\n' +
1689
- 'if(__self.__performance_monitor[key].min_usec>sl_time){__self.__performance_monitor[key].min_usec=sl_time;}\n' +
1690
- 'if(__self.__performance_monitor[key].max_usec<sl_time){__self.__performance_monitor[key].max_usec=sl_time;}\n' +
1691
- `}}})('${funcName}_sys', 'system')\n`;
1692
- }
1693
- return code;
1694
- }
1695
- convCallValue(node, isExpression) {
1696
- const callee = this._convGen(node.blocks[0], true);
1697
- const args = node.blocks.slice(1).map((arg) => this._convGen(arg, true));
1698
- args.push('__self');
1699
- const funcCall = `${callee}(${args.join(',')})`;
1700
- if (isExpression) {
1701
- return funcCall;
1702
- }
1703
- const sorePrefex = (this.speedMode.invalidSore === 0) ? '__self.__setSore(' : '';
1704
- const sorePostfix = (this.speedMode.invalidSore === 0) ? ')' : '';
1705
- return this.convLineno(node, false) + `${sorePrefex}${funcCall}${sorePostfix};\n`;
1706
- }
1707
- convRenbun(node) {
1708
- const right = this._convGen(node.blocks[1], true);
1709
- const left = this._convGen(node.blocks[0], false);
1710
- this.numAsyncFn++;
1711
- this.usedAsyncFn = true;
1712
- return `/*[連文]*/await (async function(){ ${left}; return ${right} }).call(this)/*[/連文]*/`;
1713
- }
1714
- convOp(node) {
1715
- // トークン名からJS演算子への変換 - 単純な変換が可能なものをここで定義
1716
- const OP_TBL = {
1717
- '&': '+""+',
1718
- eq: '==',
1719
- noteq: '!=',
1720
- '===': '===',
1721
- '!==': '!==',
1722
- gt: '>',
1723
- lt: '<',
1724
- gteq: '>=',
1725
- lteq: '<=',
1726
- and: '&&',
1727
- or: '||',
1728
- shift_l: '<<',
1729
- shift_r: '>>',
1730
- shift_r0: '>>>',
1731
- '÷': '/'
1732
- };
1733
- let op = node.operator || ''; // 演算子
1734
- let right = this._convGen(node.blocks[1], true);
1735
- let left = this._convGen(node.blocks[0], true);
1736
- if (op === '+' && this.speedMode.implicitTypeCasting === 0) {
1737
- if (node.blocks[0] && (node.blocks[0]).type !== 'number' && (node.blocks[0]).type !== 'bigint') {
1738
- left = `self.__parseFloatOrBigint(${left})`;
1739
- }
1740
- if (node.blocks[1] && (node.blocks[1]).type !== 'number' && (node.blocks[1]).type !== 'bigint') {
1741
- right = `self.__parseFloatOrBigint(${right})`;
1742
- }
1743
- }
1744
- // 階乗
1745
- if (op === '^' || op === '**') {
1746
- return `((${left}) ** (${right}))`;
1747
- }
1748
- // 整数の割り算 #1152
1749
- if (op === '÷÷') {
1750
- return `(Math.floor(${left} / ${right}))`;
1751
- }
1752
- // 一般的なオペレータに変換
1753
- if (OP_TBL[op]) {
1754
- op = OP_TBL[op];
1755
- }
1756
- //
1757
- return `(${left} ${op} ${right})`;
1758
- }
1759
- convInc(node) {
1760
- // idを得る
1761
- const id = this.loopId++;
1762
- const valueVar = `$nako_v${id}`;
1763
- // もし値が省略されていたら、変数「それ」に代入する
1764
- let incValue = '1';
1765
- if (this.speedMode.invalidSore === 0) {
1766
- incValue = this.varname_get('それ');
1767
- }
1768
- const astValue = node.blocks[0];
1769
- if (astValue.type !== 'nop') {
1770
- incValue = this._convGen(astValue, true);
1771
- }
1772
- // 配列への代入か(core#86)
1773
- let code = '';
1774
- let varGetter = '';
1775
- let varSetter = '';
1776
- let varInitter = '';
1777
- const nodeName = node.name;
1778
- if (nodeName.type === 'ref_array') {
1779
- varGetter = this.convRefArray(nodeName);
1780
- varSetter = `${varGetter} = ${valueVar}`;
1781
- varInitter = `${varGetter} = 0`;
1782
- }
1783
- else if (nodeName.type === 'ref_prop') {
1784
- // プロパティアクセス(A$a)の場合 (#1793)
1785
- const baseName = this._convGen(nodeName.name, true);
1786
- const propList = nodeName.index;
1787
- // __getProp/__setPropを持つオブジェクトにも対応するgetter/setter生成
1788
- const buildPropGetter = (targetExpr, propKey) => `(()=>{const __nako_obj=${targetExpr};` +
1789
- `return (__nako_obj!=null&&typeof __nako_obj.__getProp==='function')` +
1790
- `?__nako_obj.__getProp(${propKey}, __self)` +
1791
- `:__nako_obj[${propKey}]})()`;
1792
- const buildPropSetter = (targetExpr, propKey, valueExpr) => `(()=>{const __nako_obj=${targetExpr};` +
1793
- `return (__nako_obj!=null&&typeof __nako_obj.__setProp==='function')` +
1794
- `?__nako_obj.__setProp(${propKey}, ${valueExpr}, __self)` +
1795
- `:(__nako_obj[${propKey}]=${valueExpr})})()`;
1796
- const propKeys = propList.map((prop) => JSON.stringify(prop.value));
1797
- // getter: 全プロパティを順にたどる
1798
- let currentExpr = baseName;
1799
- for (const propKey of propKeys) {
1800
- currentExpr = buildPropGetter(currentExpr, propKey);
1801
- }
1802
- varGetter = currentExpr;
1803
- // setter/initter: 最後のプロパティだけsetterで、残りはgetterでたどる
1804
- let parentExpr = baseName;
1805
- for (const propKey of propKeys.slice(0, -1)) {
1806
- parentExpr = buildPropGetter(parentExpr, propKey);
1807
- }
1808
- const lastPropKey = propKeys[propKeys.length - 1];
1809
- varSetter = buildPropSetter(parentExpr, lastPropKey, valueVar);
1810
- varInitter = buildPropSetter(parentExpr, lastPropKey, '0');
1811
- }
1812
- else {
1813
- // 変数名
1814
- const name = nodeName.value;
1815
- let res = this.findVar(name, valueVar);
1816
- if (res === null) {
1817
- this.varsSet.names.add(name);
1818
- res = this.findVar(name, valueVar);
1819
- if (!res) {
1820
- throw new Error('『増』または『減』で変数が見当たりません。');
1821
- }
1822
- }
1823
- varGetter = res.js;
1824
- varSetter = res.js_set;
1825
- res = this.findVar(name, '0');
1826
- if (res !== null) {
1827
- varInitter = res.js_set;
1828
- }
1829
- }
1830
- // 自動初期化するか
1831
- code += '\n/*[convInc]*/\n';
1832
- code += this.convLineno(node, false) + '\n';
1833
- code += `let ${valueVar} = ${varGetter}\n`;
1834
- code += `if (typeof ${valueVar} === 'undefined') { ${varInitter}; }\n`;
1835
- code += `${valueVar} = Number(${varGetter}) + Number(${incValue});\n`;
1836
- code += `${varSetter}\n`;
1837
- code += '/*[/convInc]*/\n';
1838
- return code;
1839
- }
1840
- convLet(node) {
1841
- const astValue = node.blocks[0];
1842
- // もし値が省略されていたら、変数「それ」に代入する
1843
- let value = null;
1844
- if (this.speedMode.invalidSore === 0) {
1845
- value = this.varname_get('それ');
1846
- }
1847
- // 値のプログラムを生成
1848
- if (astValue) {
1849
- // 関数の戻り値がない場合はエラーを出す
1850
- if (astValue.type === 'func' && astValue.name !== undefined) {
1851
- const astFunc = astValue;
1852
- const func = this.__self.getFunc(astFunc.name);
1853
- if (func && func.return_none) {
1854
- throw NakoSyntaxError.fromNode(`関数『${astValue.name}』は戻り値がないので結果を代入できません。`, node);
1855
- }
1856
- }
1857
- value = this._convGen(astValue, true);
1858
- }
1859
- // 戻り値の検証
1860
- if (value === null) {
1861
- throw NakoSyntaxError.fromNode('代入する先の変数名がありません。', node);
1862
- }
1863
- // 変数名
1864
- const name = node.name;
1865
- const res = this.findVar(name, value);
1866
- let code = '/*[convLet]*/';
1867
- if (res === null) {
1868
- this.varsSet.names.add(name);
1869
- code = `${this.varname_set(name, value)};`;
1870
- }
1871
- else {
1872
- // 定数ならエラーを出す
1873
- if (this.varslistSet[res.i].readonly.has(name)) {
1874
- throw NakoSyntaxError.fromNode(`定数『${name}』は既に定義済みなので、値を代入することはできません。`, node);
1875
- }
1876
- code = `${res.js_set};`;
1877
- }
1878
- return ';' + this.convLineno(node, false) + code + '\n';
1879
- }
1880
- // プロパティへの代入式 (#1793)
1881
- convLetProp(node) {
1882
- if (!node.index || node.index.length === 0) {
1883
- throw NakoSyntaxError.fromNode('代入する先のプロパティ名がありません。', node);
1884
- }
1885
- if (!node.blocks || node.blocks.length === 0) {
1886
- throw NakoSyntaxError.fromNode('代入する値がありません。', node);
1887
- }
1888
- const propList = node.index;
1889
- const propTopAst = propList.pop();
1890
- if (propTopAst === undefined) {
1891
- throw NakoSyntaxError.fromNode('代入する先のプロパティ名がありません。', node);
1892
- }
1893
- const propTop = (typeof propTopAst.value === 'string') ? propTopAst.value : '';
1894
- const astValue = node.blocks[0];
1895
- let value = null;
1896
- // 値のプログラムを生成
1897
- if (astValue) {
1898
- value = this._convGen(astValue, true);
1899
- }
1900
- else {
1901
- throw NakoSyntaxError.fromNode('代入する値がありません。', node);
1902
- }
1903
- // 変数名
1904
- const name = node.name;
1905
- const res = this.findVar(name, value);
1906
- let code = '/*[convLetProp]*/\n';
1907
- // 変数が存在しないとき
1908
- if (res === null) {
1909
- throw NakoSyntaxError.fromNode(`変数『${name}』が見当たりません。`, node);
1910
- }
1911
- // 変数のプロパティ
1912
- let nameJs = res.js;
1913
- // 配列アクセス
1914
- if (node.blocks.length >= 2) {
1915
- for (let i = 1; i < node.blocks.length; i++) {
1916
- const indexNode = node.blocks[i];
1917
- const indexJs = this._convGen(indexNode, true);
1918
- nameJs += `[${indexJs}]`;
1919
- }
1920
- }
1921
- if (propList.length > 0) {
1922
- for (const prop of propList) {
1923
- if (typeof prop.value === 'string') {
1924
- nameJs += `['${prop.value}']`;
1925
- }
1926
- else {
1927
- throw NakoSyntaxError.fromNode(`変数『${nameJs}』以下のプロパティにアクセスできません。`, node);
1928
- }
1929
- }
1930
- }
1931
- // プロパティへの代入式を作る
1932
- code += `if (typeof ${nameJs}.__setProp === 'function') { ${nameJs}.__setProp('${propTop}', ${value}, __self); } else { `;
1933
- code += `__self.__checkPropAccessor('set', ${nameJs});`;
1934
- code += `if (typeof ${nameJs}.__setProp === 'function') { ${nameJs}.__setProp('${propTop}', ${value}, __self); } else { `;
1935
- code += `${nameJs}['${propTop}'] = ${value} }};`;
1936
- return ';' + this.convLineno(node, false) + code + '\n';
1937
- }
1938
- // プロパティへの参照 (#1793)
1939
- convRefProp(node) {
1940
- const name = this._convGen(node.name, true);
1941
- const list = node.index;
1942
- if (!list || list.length <= 0) {
1943
- throw NakoSyntaxError.fromNode('プロパティがありません。', node);
1944
- }
1945
- return this.convRefProp_genCode(name, list);
1946
- }
1947
- // プロパティへの参照のコード生成部分 (#1793)
1948
- convRefProp_genCode(name, propList) {
1949
- let code;
1950
- if (propList.length <= 1) {
1951
- const propKey = propList[0].value;
1952
- const codeCall = `${name}.__getProp('${propKey}', __self)`;
1953
- const codeProp = `${name}['${propKey}']`;
1954
- const codeCheckAccessor = `__self.__checkPropAccessor('get', ${name});\n` +
1955
- `if (typeof ${name}.__getProp === 'function') { return ${codeCall} }\n` +
1956
- `return ${codeProp}\n`;
1957
- const codeIf = `if (${name}.__getProp) { return ${codeCall} } else { ${codeCheckAccessor} }`;
1958
- code = `( (()=>{ ${codeIf} })() )`;
1959
- }
1960
- else {
1961
- const arrs = [];
1962
- const keys = [];
1963
- for (let i = 0; i < propList.length; i++) {
1964
- const propKey = propList[i].value;
1965
- keys.push(`['${propKey}']`);
1966
- arrs.push(`'${propKey}'`);
1967
- }
1968
- const keyStr = keys.join('');
1969
- const arrStr = '[' + arrs.join(',') + ']';
1970
- const codeCall = `${name}.__getProp(${arrStr}, __self)`;
1971
- const codeProp = `${name}${keyStr}`;
1972
- const codeCheckAccessor = `__self.__checkPropAccessor('get', ${name});\n` +
1973
- `if (${name}.__getProp) { return ${codeCall} }\n` +
1974
- `return ${codeProp}\n`;
1975
- const codeIf = `if (${name}.__getProp) { return ${codeCall} } else { ${codeCheckAccessor} }`;
1976
- code = `( (()=>{ ${codeIf} })() )`;
1977
- }
1978
- return code;
1979
- }
1980
- convDefLocalVar(node) {
1981
- const astValue = node.blocks[0];
1982
- let value = '0';
1983
- if (astValue.type !== 'nop') {
1984
- value = this._convGen(astValue, true);
1985
- }
1986
- const name = node.name; // 変数名
1987
- const vtype = node.vartype; // 変数 or 定数
1988
- // 二重定義?
1989
- if (this.varsSet.names.has(name)) {
1990
- throw NakoSyntaxError.fromNode(`${vtype}『${name}』の二重定義はできません。`, node);
1991
- }
1992
- //
1993
- this.varsSet.names.add(name);
1994
- if (vtype === '定数') {
1995
- this.varsSet.readonly.add(name);
1996
- }
1997
- const code = `/*${vtype}*/${this.varname_set(name, value)};\n`;
1998
- return this.convLineno(node, false) + code;
1999
- }
2000
- // #563 複数変数への代入
2001
- convDefLocalVarlist(node) {
2002
- let code = '';
2003
- const vtype = node.vartype; // 変数 or 定数
2004
- // 初期値を取得
2005
- let value = '0';
2006
- if (node.blocks.length > 0) {
2007
- const astValue = node.blocks[0];
2008
- if (astValue.type !== 'nop') {
2009
- value = this._convGen(astValue, true);
2010
- }
2011
- }
2012
- // 代入する変数名を取得
2013
- const id = this.loopId++;
2014
- const varI = `$nako_i${id}`;
2015
- code += `let ${varI} = ${value}\n`;
2016
- code += `if (!(${varI} instanceof Array)) { ${varI}=[${varI}] }\n`;
2017
- const names = (node.names) ? node.names : [];
2018
- for (let i = 0; i < names.length; i++) {
2019
- const nameObj = names[i];
2020
- const name = nameObj.value;
2021
- // 二重定義?
2022
- if (this.varsSet.names.has(name)) {
2023
- // 複数変数文では、二重定義も許容する #1027
2024
- // throw NakoSyntaxError.fromNode(`${vtype}『${name}』の二重定義はできません。`, node)
2025
- }
2026
- this.varsSet.names.add(name);
2027
- if (vtype === '定数') {
2028
- this.varsSet.readonly.add(name);
2029
- }
2030
- code += this.varname_set(name, `${varI}[${i}]`) + ';\n';
2031
- }
2032
- return this.convLineno(node, false) +
2033
- '/*[convDefLocalVarlist]*/\n' +
2034
- code +
2035
- '/*[/convDefLocalVarlist]*/\n';
2036
- }
2037
- convString(node) {
2038
- let value = String(node.value);
2039
- value = value.replace(/\\/g, '\\\\');
2040
- value = value.replace(/"/g, '\\"');
2041
- value = value.replace(/\r/g, '\\r');
2042
- value = value.replace(/\n/g, '\\n');
2043
- return '"' + value + '"';
2044
- }
2045
- convTryExcept(node) {
2046
- const block = this._convGen(node.blocks[0], false);
2047
- const errBlock = this._convGen(node.blocks[1], false);
2048
- return this.convLineno(node, false) +
2049
- `try {\n${block}\n} catch (e) {\n` +
2050
- ' __self.__setSysVar("エラーメッセージ", e.message);\n' +
2051
- ';\n' +
2052
- `${errBlock}}\n`;
2053
- }
2054
- getUsedFuncSet() {
2055
- return this.usedFuncSet;
2056
- }
2057
- getPluginInitCode() {
2058
- // プラグインの初期化関数を実行する
2059
- let code = '';
2060
- let pluginCode = '';
2061
- for (const name in this.__self.__module) {
2062
- const initkey = `!${name}:初期化`;
2063
- if (this.varslistSet[0].names.has(initkey)) {
2064
- const initkeyDone = `!${name}:初期化済`;
2065
- this.usedFuncSet.add(initkey);
2066
- pluginCode += `if (!__v0.has('${initkeyDone}')) { __v0.get('${initkey}')(__self); __v0.set('${initkeyDone}', true) }\n`;
2067
- }
2068
- }
2069
- if (pluginCode !== '') {
2070
- code += '__v0.set(\'__line\', \'l0:プラグインの初期化\');\n' + pluginCode;
2071
- }
2072
- return code;
2073
- }
2074
- }
2075
- /** template of standalone js code */
2076
- const STANDALONE_CODE = `
2077
- // === generated by nadesiko3 v__version__(core:__coreVersion__) ===
2078
- // -----------------------------------------------------------------
2079
- // <nadesiko3standalone>
2080
- // -----------------------------------------------------------------
2081
- // --- import
2082
- import path from 'path'
2083
- import { NakoRuntimeError } from './nako3runtime/nako_errors.mjs'
2084
- __codeImportFiles__
2085
- // --- init global self
2086
- const self = {
2087
- newVariables: () => {
2088
- const map = new Map()
2089
- return map
2090
- }
2091
- }
2092
- self.coreVersion = '__coreVersion__'
2093
- self.version = '__version__'
2094
- self.logger = {
2095
- error: (message) => { console.error(message) },
2096
- warn: (message) => { console.warn(message) },
2097
- send: (level, message) => { console.log(message) },
2098
- runtimeError: (message, lineInfo) => { console.error(message, lineInfo) }
2099
- };
2100
- self.__varslist = [self.newVariables(), self.newVariables(), self.newVariables()]
2101
- self.__v0 = self.__varslist[0]
2102
- self.initFuncList = []
2103
- self.clearFuncList = []
2104
- self.__propAccessor = []
2105
- // --- jsInit ---
2106
- __jsInit__
2107
- // --- Copy module functions ---
2108
- for (const mod of __importNames__) {
2109
- for (const funcName in mod) {
2110
- // プラグインの初期化とクリア関数を登録
2111
- if (funcName === '初期化') {
2112
- __self.initFuncList.push(mod[funcName].fn)
2113
- continue
2114
- }
2115
- if (funcName === '!クリア') {
2116
- __self.clearFuncList.push(mod[funcName].fn)
2117
- continue
2118
- }
2119
- // 関数や定数を登録
2120
- const f = mod[funcName]
2121
- if (f.type === 'func') { // 関数
2122
- __self.__varslist[0].set(funcName, f.fn)
2123
- } else { // 定数
2124
- __self.__varslist[0].set(funcName, f.value)
2125
- }
2126
- }
2127
- }
2128
- __self.__vars = __self.__varslist[2];
2129
- __self.__module = {};
2130
- __self.__locals = __self.newVariables();
2131
- __self.__genMode = 'sync';
2132
- // プラグインの初期化コードを実行
2133
- __self.initFuncList.map(f => f(self))
2134
- // standalone
2135
- __self.__v0.set('__standalone', true)
2136
- // -----------------------------------------------------------------
2137
- try {
2138
- try {
2139
- // -----------------------------------------------------------------
2140
- // <prepareMainCode>
2141
- __codeStandalone__
2142
- // </prepareMainCode>
2143
- // -----------------------------------------------------------------
2144
- // <mainCode>
2145
- // -----------------------------------------------------------------
2146
- __codeJS__
2147
- // -----------------------------------------------------------------
2148
- // </mainCode>
2149
- // -----------------------------------------------------------------
2150
- } catch (err) {
2151
- __self.logger.error(err);
2152
- throw err;
2153
- }
2154
- } finally {
2155
- // standaloneCodeでは、即時プラグインのクリアコードを実行
2156
- __self.clearFuncList.map(f => f(__self))
2157
- }
2158
- // -----------------------------------------------------------------
2159
- // </nadesiko3standalone>
2160
- // -----------------------------------------------------------------
2161
- `;
2162
- /**
2163
- * @param com
2164
- * @param ast
2165
- * @param opt
2166
- */
2167
- export function generateJS(com, ast, opt) {
2168
- // NakoGenのインスタンスを作成
2169
- const gen = new NakoGen(com);
2170
- // ※ [関数定義に関するコード生成のヒント]
2171
- // ※ 関数の名前だけを(1)で登録して、(2)で実際に関数のコードを生成する。
2172
- // ※ ただし(2)では生成するだけなので、(3)でプログラム冒頭に関数定義のコードを記述する。
2173
- // この順番を変えることはできない (グローバル変数が認識できなくなったり、関数定義のタイミングがずれる)
2174
- // (1) ユーザー定義関数をシステムに登録する
2175
- gen.registerFunction(ast);
2176
- // (2) JSコードを生成する
2177
- let js = trim(cleanGeneratedCode(gen.convGen(ast, opt), 1));
2178
- // (3) JSコードを実行するための事前ヘッダ部分の生成
2179
- const jsInit = gen.getDefFuncCode(com, opt);
2180
- // ランダムな関数名を生成
2181
- const funcID = String((new Date()).getTime()) + '_' + Math.floor(0xFFFFFFFF * Math.random()).toString();
2182
- // テストの実行
2183
- if (js && opt.isTest) {
2184
- js += '\n__self._runTests(__tests);\n';
2185
- }
2186
- // async method
2187
- if (gen.numAsyncFn > 0 || gen.debugOption.useDebug) {
2188
- const asyncMain = '__eval_nako3async_' + funcID + '__';
2189
- js = `
2190
- // ------------------------------------------------------------------
2191
- // <nadesiko3::gen::async id="${funcID}" times="${gen.numAsyncFn}">
2192
- // ------------------------------------------------------------------
2193
- async function ${asyncMain}(__self) {
2194
- // --- code_begin ---
2195
- ${js}
2196
- // --- code_end ---
2197
- // __処理末尾__ // ← テストなどで必要なので消さない
2198
- } // end of ${asyncMain}
2199
- // ------------------------------------------------------------------
2200
- // call ${asyncMain}
2201
- (async () => {
2202
- if (__self.__v0.get('__standalone')) {
2203
- await ${asyncMain}(self);
2204
- } else {
2205
- ${asyncMain}.call(self, self)
2206
- .then(() => { /* __async_ok__ */ })
2207
- .catch(err => {
2208
- if (err.message === '__終わる__') { return }
2209
- __self.numFailures++
2210
- // send errors to logger
2211
- let rterr = __self.logger.runtimeError(err, __self.__v0.get('__line'))
2212
- __self.logger.error(rterr)
2213
- })
2214
- }
2215
- })();
2216
- // ------------------------------------------------------------------
2217
- // </nadesiko3::gen::async id="${funcID}">
2218
- // ------------------------------------------------------------------
2219
- `;
2220
- }
2221
- else {
2222
- const syncMain = '__eval_nako3sync_' + funcID + '__';
2223
- js = `
2224
- // ------------------------------------------------------------------
2225
- // <nadesiko3::gen::syncMode>
2226
- // ------------------------------------------------------------------
2227
- function ${syncMain}(__self) {
2228
- try {
2229
- ${js}
2230
- // __処理末尾__ // ← テストなどで必要なので消さない
2231
- } catch (err) {
2232
- if (err.message === '__終わる__') { return }
2233
- __self.numFailures++
2234
- throw __self.logger.runtimeError(err, __self.__v0.get('__line'))
2235
- }
2236
- } // end of ${syncMain}
2237
- ${syncMain}(__self)
2238
- // ------------------------------------------------------------------
2239
- // </nadesiko3::gen::syncMode>
2240
- // ------------------------------------------------------------------
2241
- `;
2242
- }
2243
- // --- 生成したコードの簡単な整形 ---
2244
- js = cleanGeneratedCode(js);
2245
- // デバッグメッセージ
2246
- let codeImportFiles = '';
2247
- const importNames = [];
2248
- for (const f of opt.importFiles) {
2249
- if (f === 'nako_errors.mjs') {
2250
- continue;
2251
- }
2252
- const ff = 'nako3runtime_' + f.replace(/\.(js|mjs)$/, '').replace(/[^a-zA-Z0-9_]/g, '_');
2253
- importNames.push(ff);
2254
- codeImportFiles += `import ${ff} from './nako3runtime/${f}'\n`;
2255
- }
2256
- // ---
2257
- const initCode = gen.getPluginInitCode();
2258
- const runtimeEnvCode = `
2259
- // <runtimeEnvCode>
2260
- const self = this
2261
- ${opt.codeEnv}
2262
- ${jsInit}
2263
- ${initCode}
2264
- ${js}
2265
- // </runtimeEnvCode>
2266
- `;
2267
- com.getLogger().trace('--- generate::jsInit ---\n' + jsInit);
2268
- com.getLogger().trace('--- generate::js ---\n' + js);
2269
- return {
2270
- // なでしこの実行環境ありの場合(thisが有効)
2271
- runtimeEnv: runtimeEnvCode,
2272
- // JavaScript単体で動かす場合
2273
- standalone: replaceTemplateCode(STANDALONE_CODE, {
2274
- codeImportFiles,
2275
- 'coreVersion': com.coreVersion,
2276
- 'version': com.version,
2277
- 'importNames': ('[' + importNames.join(', ') + ']'),
2278
- 'codeStandalone': opt.codeStandalone,
2279
- 'codeJS': js,
2280
- jsInit
2281
- }),
2282
- // コード生成に使ったNakoGenのインスタンス
2283
- gen
2284
- };
2285
- }
2286
- // template
2287
- function replaceTemplateCode(template, values) {
2288
- for (const key in values) {
2289
- const pat = `__${key}__`;
2290
- const val = values[key];
2291
- template = template.split(pat).join(val);
2292
- }
2293
- return template;
2294
- }
2295
- // clean generated code
2296
- function cleanGeneratedCode(code, indent = 0) {
2297
- // 1. 無意味な改行やセミコロンを削除
2298
- // 2. 行頭の空白やセミコロンを削除
2299
- // 3. indent分インデントを追加
2300
- // ただし、文字列リテラル内の改行やセミコロンは削除しない (#2153)
2301
- // 文字列リテラル外の連続セミコロンと連続改行を削除
2302
- code = removeDuplicateChars(code);
2303
- // indent分インデントを追加
2304
- let spc = '';
2305
- for (let i = 0; i < indent; i++) {
2306
- spc += ' ';
2307
- }
2308
- // 行頭の";"を削除
2309
- const result = [];
2310
- const lines = code.split('\n');
2311
- for (let i = 0; i < lines.length; i++) {
2312
- let line = lines[i];
2313
- line = line.replace(/^(\s*);/, '$1');
2314
- if (trim(line) === '') {
2315
- continue;
2316
- }
2317
- result.push(spc + line);
2318
- }
2319
- // 結果のコードを返す
2320
- code = result.join('\n');
2321
- return code;
2322
- }
2323
- /**
2324
- * 文字列リテラル外の連続セミコロンと連続改行を1つに置換する
2325
- * 文字列リテラル内のセミコロンと改行は保護する (#2153)
2326
- * JavaScriptの文字列リテラル、正規表現、テンプレートリテラル、コメントを考慮
2327
- */
2328
- function removeDuplicateChars(code) {
2329
- const result = [];
2330
- let i = 0;
2331
- let inString = false;
2332
- let inRegex = false;
2333
- let inTemplate = false;
2334
- let inLineComment = false;
2335
- let inBlockComment = false;
2336
- let stringDelimiter = '';
2337
- let prevChar = '';
2338
- let lastSemiPos = -2; // 最後のセミコロンの位置
2339
- let lastNewlinePos = -2; // 最後の改行の位置
2340
- /**
2341
- * 直前のバックスラッシュの数をカウント
2342
- * 偶数個なら次の文字はエスケープされていない
2343
- */
2344
- const countBackslashes = (pos) => {
2345
- let count = 0;
2346
- let p = pos - 1;
2347
- while (p >= 0 && code.charAt(p) === '\\') {
2348
- count++;
2349
- p--;
2350
- }
2351
- return count;
2352
- };
2353
- while (i < code.length) {
2354
- const ch = code.charAt(i);
2355
- const nextCh = i + 1 < code.length ? code.charAt(i + 1) : '';
2356
- // 行コメントの処理
2357
- if (inLineComment) {
2358
- result.push(ch);
2359
- if (ch === '\n') {
2360
- inLineComment = false;
2361
- }
2362
- prevChar = ch;
2363
- i++;
2364
- continue;
2365
- }
2366
- // ブロックコメントの処理
2367
- if (inBlockComment) {
2368
- result.push(ch);
2369
- if (ch === '*' && nextCh === '/') {
2370
- result.push(nextCh);
2371
- inBlockComment = false;
2372
- i += 2;
2373
- prevChar = '/';
2374
- continue;
2375
- }
2376
- prevChar = ch;
2377
- i++;
2378
- continue;
2379
- }
2380
- // テンプレートリテラルの処理
2381
- if (inTemplate) {
2382
- result.push(ch);
2383
- if (ch === '`') {
2384
- const backslashCount = countBackslashes(i);
2385
- if (backslashCount % 2 === 0) {
2386
- // 偶数個のバックスラッシュ = エスケープされていない
2387
- inTemplate = false;
2388
- }
2389
- }
2390
- prevChar = ch;
2391
- i++;
2392
- continue;
2393
- }
2394
- // 正規表現の処理
2395
- if (inRegex) {
2396
- result.push(ch);
2397
- if (ch === '/') {
2398
- const backslashCount = countBackslashes(i);
2399
- if (backslashCount % 2 === 0) {
2400
- inRegex = false;
2401
- }
2402
- }
2403
- prevChar = ch;
2404
- i++;
2405
- continue;
2406
- }
2407
- // 文字列リテラルの処理
2408
- if (inString) {
2409
- result.push(ch);
2410
- if (ch === stringDelimiter) {
2411
- const backslashCount = countBackslashes(i);
2412
- if (backslashCount % 2 === 0) {
2413
- // 偶数個のバックスラッシュ = エスケープされていない
2414
- inString = false;
2415
- stringDelimiter = '';
2416
- }
2417
- }
2418
- prevChar = ch;
2419
- i++;
2420
- continue;
2421
- }
2422
- // コメント開始チェック
2423
- if (ch === '/' && nextCh === '/') {
2424
- result.push(ch);
2425
- result.push(nextCh);
2426
- inLineComment = true;
2427
- i += 2;
2428
- prevChar = '/';
2429
- continue;
2430
- }
2431
- if (ch === '/' && nextCh === '*') {
2432
- result.push(ch);
2433
- result.push(nextCh);
2434
- inBlockComment = true;
2435
- i += 2;
2436
- prevChar = '*';
2437
- continue;
2438
- }
2439
- // 文字列・正規表現・テンプレートリテラルの開始チェック
2440
- if (ch === '"' || ch === '\'') {
2441
- inString = true;
2442
- stringDelimiter = ch;
2443
- result.push(ch);
2444
- prevChar = ch;
2445
- i++;
2446
- continue;
2447
- }
2448
- if (ch === '`') {
2449
- inTemplate = true;
2450
- result.push(ch);
2451
- prevChar = ch;
2452
- i++;
2453
- continue;
2454
- }
2455
- // 正規表現リテラルの開始チェック(簡易版)
2456
- // / の前が演算子や ( や , や = などの場合は正規表現の可能性が高い
2457
- if (ch === '/' && /[=([,;:!&|?+\-*%^~{]|\breturn\b|\bnew\b/.test(prevChar)) {
2458
- inRegex = true;
2459
- result.push(ch);
2460
- prevChar = ch;
2461
- i++;
2462
- continue;
2463
- }
2464
- // 文字列外の連続セミコロンをスキップ
2465
- if (ch === ';' && lastSemiPos === i - 1) {
2466
- // 連続するセミコロンの2番目以降はスキップ
2467
- lastSemiPos = i;
2468
- i++;
2469
- prevChar = ch;
2470
- continue;
2471
- }
2472
- if (ch === ';') {
2473
- lastSemiPos = i;
2474
- }
2475
- // 文字列外の連続改行をスキップ
2476
- if (ch === '\n' && lastNewlinePos === i - 1) {
2477
- // 連続する改行の2番目以降はスキップ
2478
- lastNewlinePos = i;
2479
- i++;
2480
- prevChar = ch;
2481
- continue;
2482
- }
2483
- if (ch === '\n') {
2484
- lastNewlinePos = i;
2485
- }
2486
- result.push(ch);
2487
- prevChar = ch;
2488
- i++;
2489
- }
2490
- return result.join('');
2491
- }
2492
- /**
2493
- * 前後の空白を削除する
2494
- * @param str 対象文字列
2495
- * @returns トリムした文字列
2496
- */
2497
- function trim(str) {
2498
- str = String(str);
2499
- return str.replace(/^\s+|\s+$/g, '');
2500
- }