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
@@ -0,0 +1,105 @@
1
+ /**
2
+ * 構文解析器のエラーメッセージを組み立てるモジュール
3
+ *
4
+ * NakoParser / NakoParserBase から分離した (#2364)。
5
+ * 構文木やトークンを日本語の説明文に変換するだけで、
6
+ * トークンのカーソルにも計算用スタックにも一切触れない。
7
+ * (実体は nako_parser_base.mts の nodeToStr と
8
+ * nako_parser3.mts の makeStackBalanceReport だった)
9
+ */
10
+ import { Ast, AstBlocks, AstOperator, AstConst, AstStrValue } from './nako_ast.mjs'
11
+ import { Token } from './nako_token.mjs'
12
+ import { FuncArgs, FuncListItem } from './nako_types.mjs'
13
+
14
+ /**
15
+ * 構文木やトークンを日本語の説明文にする
16
+ * @param node 説明したいノード
17
+ * @param opts depth: 展開する深さ / typeName: 先頭の型名を上書きする場合に指定
18
+ * @param debugMode true ならノードの JSON も埋め込む
19
+ */
20
+ export function nodeToStr (node: Ast|Token|null, opts: {depth: number, typeName?: string}, debugMode: boolean): string {
21
+ const depth = opts.depth - 1
22
+ const typeName = (name: string) => (opts.typeName !== undefined) ? opts.typeName : name
23
+ const debug = debugMode ? (' debug: ' + JSON.stringify(node, null, 2)) : ''
24
+ if (!node) { return '(NULL)' }
25
+ switch (node.type) {
26
+ case 'not':
27
+ if (depth >= 0) {
28
+ const subNode: Ast = (node as AstBlocks).blocks[0]
29
+ return `${typeName('')}『${nodeToStr(subNode, { depth }, debugMode)}に演算子『not』を適用した式${debug}』`
30
+ } else {
31
+ return `${typeName('演算子')}『not』`
32
+ }
33
+ case 'op': {
34
+ const node2: AstOperator = node as AstOperator
35
+ let operator: string = node2.operator || ''
36
+ const table:{[key: string]: string} = { eq: '=', not: '!', gt: '>', lt: '<', and: 'かつ', or: 'または' }
37
+ if (operator in table) {
38
+ operator = table[operator]
39
+ }
40
+ if (depth >= 0) {
41
+ const left: string = nodeToStr(node2.blocks[0], { depth }, debugMode)
42
+ const right: string = nodeToStr(node2.blocks[1], { depth }, debugMode)
43
+ if (node2.operator === 'eq') {
44
+ return `${typeName('')}『${left}と${right}が等しいかどうかの比較${debug}』`
45
+ }
46
+ return `${typeName('')}『${left}と${right}に演算子『${operator}』を適用した式${debug}』`
47
+ } else {
48
+ return `${typeName('演算子')}『${operator}${debug}』`
49
+ }
50
+ }
51
+ case 'number':
52
+ return `${typeName('数値')}${(node as AstConst).value}`
53
+ case 'bigint':
54
+ return `${typeName('巨大整数')}${(node as AstConst).value}`
55
+ case 'string':
56
+ return `${typeName('文字列')}『${(node as AstConst).value}${debug}』`
57
+ case 'word':
58
+ return `${typeName('単語')}『${(node as AstStrValue).value}${debug}』`
59
+ case 'func':
60
+ return `${typeName('関数')}『${node.name || (node as AstStrValue).value}${debug}』`
61
+ case 'eol':
62
+ return '行の末尾'
63
+ case 'eof':
64
+ return 'ファイルの末尾'
65
+ default: {
66
+ let name: any = (node as any).name
67
+ if (name && typeof name !== 'string') { name = (node as any).value }
68
+ if (typeof name !== 'string') { name = node.type }
69
+ return `${typeName('')}『${name}${debug}』`
70
+ }
71
+ }
72
+ }
73
+
74
+ /**
75
+ * 計算用スタックに余りが出たときのレポートを作る
76
+ * @param stack 余ってしまった計算用スタックの中身
77
+ * @param recentlyCalledFunc 最近呼び出した関数(使い方の候補を示すのに使う #1093)
78
+ */
79
+ export function makeStackBalanceReport (stack: Ast[], recentlyCalledFunc: FuncListItem[]): string {
80
+ const words: string[] = []
81
+ stack.forEach((t) => {
82
+ let w = nodeToStr(t, { depth: 1 }, false)
83
+ if (t.josi) { w += t.josi }
84
+ words.push(w)
85
+ })
86
+ const desc = words.join(',')
87
+ // 最近使った関数の使い方レポートを作る #1093
88
+ let descFunc = ''
89
+ const chA = 'A'.charCodeAt(0)
90
+ for (const f of recentlyCalledFunc) {
91
+ descFunc += ' - '
92
+ let no = 0
93
+ const josiA: FuncArgs | undefined = (f).josi
94
+ if (josiA) {
95
+ for (const arg of josiA) {
96
+ const ch = String.fromCharCode(chA + no)
97
+ descFunc += ch
98
+ if (arg.length === 1) { descFunc += arg[0] } else { descFunc += `(${arg.join('|')})` }
99
+ no++
100
+ }
101
+ }
102
+ descFunc += String(f.name) + '\n'
103
+ }
104
+ return `未解決の単語があります: [${desc}]\n次の命令の可能性があります:\n${descFunc}`
105
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * なでしこの計算式を演算子の優先順位に従って構文木へ変換するモジュール
3
+ *
4
+ * NakoParser から分離した (#2364)。
5
+ * 中置記法のリスト(値と演算子が交互に並んだもの)を、逆ポーランド記法を経由して
6
+ * `op` ノードの木に組み立てる。
7
+ *
8
+ * このモジュールはトークンのカーソルにも計算用スタックにも一切触れないため、
9
+ * 構文解析器の相互再帰から完全に独立している。
10
+ * (実体は nako_parser3.mts の NakoParser.infixToPolish / infixToAST だった)
11
+ */
12
+ import { opPriority } from './nako_parser_const.mjs'
13
+ import { NakoSyntaxError } from './nako_errors.mjs'
14
+ import { NakoLogger } from './nako_logger.mjs'
15
+ import { Ast, AstOperator } from './nako_ast.mjs'
16
+
17
+ /**
18
+ * 中置記法のリストを逆ポーランド記法に変換する
19
+ * @param list 値と演算子が交互に並んだリスト(破壊的に消費される)
20
+ * @param logger エラー報告用
21
+ */
22
+ export function infixToPolish (list: Ast[], logger: NakoLogger): Ast[] {
23
+ // 中間記法から逆ポーランドに変換
24
+ const priority = (t: Ast) => {
25
+ if (opPriority[t.type]) { return opPriority[t.type] }
26
+ return 10
27
+ }
28
+ const stack: Ast[] = []
29
+ const polish: Ast[] = []
30
+ while (list.length > 0) {
31
+ const t = list.shift()
32
+ if (!t) { break }
33
+ while (stack.length > 0) { // 優先順位を見て移動する
34
+ const sTop = stack[stack.length - 1]
35
+ if (priority(t) > priority(sTop)) { break }
36
+ const tpop = stack.pop()
37
+ if (!tpop) {
38
+ logger.error('計算式に間違いがあります。', t)
39
+ break
40
+ }
41
+ polish.push(tpop)
42
+ }
43
+ stack.push(t)
44
+ }
45
+ // 残った要素を積み替える
46
+ while (stack.length > 0) {
47
+ const t = stack.pop()
48
+ if (t) { polish.push(t) }
49
+ }
50
+ return polish
51
+ }
52
+
53
+ /**
54
+ * 中置記法のリストを構文木(op ノードの入れ子)に変換する
55
+ * @param list 値と演算子が交互に並んだリスト
56
+ * @param logger エラー報告用
57
+ */
58
+ export function infixToAST (list: Ast[], logger: NakoLogger): Ast | null {
59
+ if (list.length === 0) { return null }
60
+ // 逆ポーランドを構文木に
61
+ const josi = list[list.length - 1].josi
62
+ const node = list[list.length - 1]
63
+ const polish = infixToPolish(list, logger)
64
+ const stack: Ast[] = []
65
+ for (const t of polish) {
66
+ if (!opPriority[t.type]) { // 演算子ではない
67
+ stack.push(t)
68
+ continue
69
+ }
70
+ const b:Ast|undefined = stack.pop()
71
+ const a:Ast|undefined = stack.pop()
72
+ if (a === undefined || b === undefined) {
73
+ logger.debug('--- 計算式(逆ポーランド) ---\n' + JSON.stringify(polish))
74
+ throw NakoSyntaxError.fromNode('計算式でエラー', node)
75
+ }
76
+ /** @type {AstOperator} */
77
+ const op: AstOperator = {
78
+ type: 'op',
79
+ operator: t.type,
80
+ blocks: [a, b],
81
+ josi,
82
+ startOffset: a.startOffset,
83
+ endOffset: a.endOffset,
84
+ line: a.line,
85
+ column: a.column,
86
+ file: a.file
87
+ }
88
+ stack.push(op)
89
+ }
90
+ const ans = stack.pop()
91
+ if (!ans) { return null }
92
+ return ans
93
+ }
@@ -0,0 +1,260 @@
1
+ // deno-lint-ignore-file no-explicit-any
2
+ /**
3
+ * なでしこ3 のプラグイン管理
4
+ *
5
+ * NakoCompiler からプラグイン登録処理を分離したモジュール (#2360)
6
+ * 循環参照を避けるため、このモジュールは nako3.mts を参照せず、
7
+ * 必要な機能は NakoPluginHost インターフェイス経由で受け取る。
8
+ */
9
+ import { FuncArgs, FuncList, FuncListItem, NakoVars } from './nako_types.mjs'
10
+ import { NakoLogger } from './nako_logger.mjs'
11
+
12
+ const cloneAsJSON = (x: any): any => JSON.parse(JSON.stringify(x))
13
+
14
+ /** プラグインが要求するランタイムの最低バージョン (= minor * 100 + patch) */
15
+ export const PLUGIN_MIN_VERSION_INT = 600
16
+
17
+ /** プラグインのメタ情報 */
18
+ export interface NakoPluginMeta {
19
+ pluginName: string;
20
+ nakoVersionResult?: boolean;
21
+ nakoVersion: string;
22
+ path?: string;
23
+ }
24
+
25
+ /**
26
+ * NakoPluginManager がホスト(NakoCompiler)に要求する最小限の機能
27
+ */
28
+ export interface NakoPluginHost {
29
+ /** プラグインで定義された関数 + ユーザーが定義した関数。reset() で差し替わるため都度取得する */
30
+ getFuncList (): FuncList;
31
+ /** システム領域の変数 (= __varslist[0]) */
32
+ getSysVars (): NakoVars;
33
+ getLogger (): NakoLogger;
34
+ }
35
+
36
+ /**
37
+ * プラグインの登録と、プラグインが定義した関数・変数・定数の管理を行うクラス
38
+ */
39
+ export class NakoPluginManager {
40
+ /** プラグインで定義された関数 (reset() でユーザー定義関数を消すときに使う) */
41
+ readonly pluginFunclist: Record<string, FuncListItem>
42
+ /** 取り込んだファイル一覧 */
43
+ readonly pluginfiles: Record<string, any>
44
+ /** プラグインで定義された定数・変数・関数の名前 */
45
+ readonly commandlist: Set<string>
46
+ /** requireなどで取り込んだモジュールの一覧 (NakoCompiler.__module と同一オブジェクト) */
47
+ readonly modules: Record<string, Record<string, FuncListItem>>
48
+ private host: NakoPluginHost
49
+
50
+ constructor (host: NakoPluginHost) {
51
+ this.host = host
52
+ this.pluginFunclist = {}
53
+ this.pluginfiles = {}
54
+ this.commandlist = new Set()
55
+ this.modules = {}
56
+ }
57
+
58
+ /**
59
+ * プラグイン・オブジェクトを追加
60
+ * @param po プラグイン・オブジェクト
61
+ * @param persistent falseのとき、次以降の実行では使えない
62
+ * @param fpath ファイルパス
63
+ */
64
+ addPlugin (po: {[key: string]: any}, persistent = true, fpath = ''): void {
65
+ // __v0を取得
66
+ const __v0 = this.host.getSysVars()
67
+ // プラグインのメタ情報をチェック (#1034) (#1647)
68
+ let __pluginInfo = __v0.get('__pluginInfo')
69
+ if (!__pluginInfo) {
70
+ __pluginInfo = {}
71
+ __v0.set('__pluginInfo', __pluginInfo)
72
+ }
73
+ // メタ情報を読み取る
74
+ const meta = this.readPluginMeta(po, fpath)
75
+ let pluginName = meta.pluginName
76
+ const metaValue = meta.metaValue
77
+ // プラグイン名の重複を確認
78
+ if (__pluginInfo[pluginName] !== undefined) {
79
+ // プラグイン名が重複した場合はプラグインとして登録しない
80
+ return
81
+ }
82
+ pluginName = NakoPluginManager.removeInvalidFilenameChars(pluginName)
83
+ // プラグイン情報を記録
84
+ __pluginInfo[pluginName] = metaValue
85
+ // バージョンチェック
86
+ pluginName = this.checkPluginVersion(pluginName, meta.intVersion, po, metaValue)
87
+ // 初期化とクリアを変換する
88
+ this.modules[pluginName] = po
89
+ this.pluginfiles[pluginName] = '*'
90
+ // `初期化`と`クリア`をチェック
91
+ if (typeof (po['初期化']) === 'object') {
92
+ const def = po['初期化']
93
+ delete po['初期化']
94
+ const initKey = `!${pluginName}:初期化`
95
+ po[initKey] = def
96
+ }
97
+ // プラグインの値を、なでしこシステム変数(Map)にコピー
98
+ this.registerPluginEntries(po, persistent, __v0)
99
+ }
100
+
101
+ /**
102
+ * プラグインのメタ情報を読み取る
103
+ * @param po プラグイン・オブジェクト
104
+ * @param fpath ファイルパス
105
+ */
106
+ private readPluginMeta (po: {[key: string]: any}, fpath: string): { pluginName: string, intVersion: number, metaValue: NakoPluginMeta } {
107
+ let intVersion = 0
108
+ let pluginName = 'unknown'
109
+ let metaValue: NakoPluginMeta = { pluginName: 'unknown', nakoVersionResult: true, nakoVersion: '0.0.0', path: '' }
110
+ if (po.meta) {
111
+ if (po.meta.value && typeof (po.meta) === 'object') {
112
+ const meta = po.meta
113
+ metaValue = meta.value || { pluginName: 'unknown', nakoVersion: '0.0.0' }
114
+ pluginName = metaValue.pluginName || 'unknown'
115
+ // version check
116
+ const nakoVersion = (metaValue.nakoVersion || '0.0.0') + '.0.0'
117
+ const versions = nakoVersion.split('.').map((v) => parseInt(v))
118
+ intVersion = versions[1] * 100 + versions[2]
119
+ // fpath
120
+ metaValue.path = fpath
121
+ }
122
+ }
123
+ // unknown の場合は、関数名からプラグイン名を自動生成する
124
+ if (pluginName === 'unknown') {
125
+ pluginName = Object.keys(po).join('-')
126
+ }
127
+ return { pluginName, intVersion, metaValue }
128
+ }
129
+
130
+ /**
131
+ * プラグインが要求するランタイムのバージョンを確認する
132
+ * @returns プラグイン名 (古い形式で名前が不明な場合は関数名から生成した名前)
133
+ */
134
+ private checkPluginVersion (pluginName: string, intVersion: number, po: {[key: string]: any}, metaValue: NakoPluginMeta): string {
135
+ if (PLUGIN_MIN_VERSION_INT <= intVersion) { return pluginName }
136
+ const keyStr: string = Object.keys(po).join(',')
137
+ if (pluginName === 'unknown') {
138
+ pluginName = keyStr.substring(0, 30) + '...'
139
+ }
140
+ if (pluginName !== '') {
141
+ const errMsg = `なでしこプラグイン『${pluginName}』は古い形式なので正しく動作しない可能性があります。` +
142
+ `(ランタイムの要求: ${PLUGIN_MIN_VERSION_INT}/プラグイン: ${intVersion})`
143
+ console.warn(errMsg, 'see', 'https://github.com/kujirahand/nadesiko3/issues/1647')
144
+ this.host.getLogger().warn(errMsg)
145
+ metaValue.nakoVersionResult = false
146
+ }
147
+ return pluginName
148
+ }
149
+
150
+ /**
151
+ * プラグインの値を、なでしこシステム変数(Map)にコピーする
152
+ * @param po プラグイン・オブジェクト
153
+ * @param persistent falseのとき、次以降の実行では使えない
154
+ * @param __v0 システム領域の変数
155
+ */
156
+ private registerPluginEntries (po: {[key: string]: any}, persistent: boolean, __v0: NakoVars): void {
157
+ const funclist = this.host.getFuncList()
158
+ for (const key in po) {
159
+ const v = po[key]
160
+ funclist.set(key, v)
161
+ if (persistent) {
162
+ this.pluginFunclist[key] = cloneAsJSON(v)
163
+ }
164
+ if (v.type === 'func') {
165
+ __v0.set(key, v.fn)
166
+ if (v.asyncFn) { // asyncFn を正しく実行するために pure に変更する (core#142)
167
+ v.pure = true
168
+ }
169
+ } else if (v.type === 'const' || v.type === 'var') {
170
+ // メタ情報としての const | var は現在利用していない
171
+ // meta[key] = { readonly: v.type === 'const' }
172
+ __v0.set(key, v.value)
173
+ } else {
174
+ console.error('[プラグイン追加エラー]', v)
175
+ throw new Error('プラグインの追加でエラー。')
176
+ }
177
+ // コマンドを登録するか?
178
+ if (key === '初期化' || key.substring(0, 1) === '!') { // 登録しない関数名
179
+ continue
180
+ }
181
+ this.commandlist.add(key)
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Windowsのパスやファイル名に使えない文字列があると、JSファイル書き出しでエラーになるので置換する
187
+ */
188
+ static removeInvalidFilenameChars (str: string): string {
189
+ return str.replace(/[^A-Za-z0-9\-_\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FAF\u3400-\u4DBF\uF900-\uFAFF]/g, '_')
190
+ }
191
+
192
+ /**
193
+ * プラグイン・オブジェクトを追加(ブラウザ向け)
194
+ * @param objName オブジェクト名 (今後プラグイン名は、meta.value.pluginNameに指定する)
195
+ * @param po 関数リスト
196
+ * @param persistent falseのとき、次以降の実行では使えない
197
+ */
198
+ addPluginObject (objName: string, po: {[key: string]: any}, persistent = true): void {
199
+ // metaプロパティがなければ互換性のため適当に追加
200
+ if (po.meta === undefined) {
201
+ po.meta = { type: 'const', value: { pluginName: objName, nakoVersion: '0.0.0' } }
202
+ }
203
+ this.addPlugin(po, persistent)
204
+ }
205
+
206
+ /**
207
+ * プラグイン・ファイルを追加(Node.js向け)
208
+ * @param fpath ファイルパス
209
+ * @param po 登録するオブジェクト
210
+ * @param persistent falseのとき、次以降の実行では使えない
211
+ */
212
+ addPluginFromFile (fpath: string, po: { [key: string]: any }, persistent = true): void {
213
+ this.addPlugin(po, persistent, fpath)
214
+ }
215
+
216
+ /**
217
+ * 関数を追加する
218
+ * @param key 関数名
219
+ * @param josi 助詞
220
+ * @param fn 関数
221
+ * @param returnNone 値を返す関数の場合はfalseを指定
222
+ * @param asyncFn Promiseを返す関数かを指定
223
+ */
224
+ addFunc (key: string, josi: FuncArgs, fn: any, returnNone = true, asyncFn = false): void {
225
+ const funcObj: FuncListItem = { josi, fn, type: 'func', return_none: returnNone, asyncFn, pure: true }
226
+ this.host.getFuncList().set(key, funcObj)
227
+ this.pluginFunclist[key] = cloneAsJSON(funcObj)
228
+ this.host.getSysVars().set(key, fn)
229
+ }
230
+
231
+ /**
232
+ * プラグイン関数を参照する
233
+ * @param key プラグイン関数の関数名
234
+ * @returns プラグイン・オブジェクト
235
+ */
236
+ getFunc (key: string): FuncListItem|undefined {
237
+ return this.host.getFuncList().get(key)
238
+ }
239
+
240
+ /** プラグインで定義された定数・変数・関数の名前かどうかを返す */
241
+ hasCommand (name: string): boolean {
242
+ return this.commandlist.has(name)
243
+ }
244
+
245
+ /**
246
+ * プラグイン由来の命令だけを含む関数一覧を新規に作る (reset() 用)
247
+ * @param sysVars システム領域の変数 (= __varslist[0])
248
+ */
249
+ createFuncListFromPlugins (sysVars: NakoVars): FuncList {
250
+ const funclist: FuncList = new Map()
251
+ for (const name of sysVars.keys()) {
252
+ const original = this.pluginFunclist[name] // record
253
+ if (!original) {
254
+ continue
255
+ }
256
+ funclist.set(name, cloneAsJSON(original))
257
+ }
258
+ return funclist
259
+ }
260
+ }