nadesiko3 3.7.20 → 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.
- package/batch/command.txt +483 -445
- package/batch/jsplugin2text.nako3 +1 -1
- package/batch/pickup_command.nako3 +12 -0
- package/core/command/snako.mts +5 -1
- package/core/deno/snako.ts +5 -1
- package/core/package-lock.json +382 -21
- package/core/package.json +4 -4
- package/core/src/README.md +98 -0
- package/core/src/nako3.mts +178 -614
- package/core/src/nako_basic_plugins.mts +39 -0
- package/core/src/nako_core_version.mts +2 -2
- package/core/src/nako_csv.mts +0 -1
- package/core/src/nako_event.mts +49 -0
- package/core/src/nako_gen.mts +291 -202
- package/core/src/nako_indent_inline.mts +2 -2
- package/core/src/nako_lex_rules.mts +1 -1
- package/core/src/nako_parser3.mts +106 -165
- package/core/src/nako_parser_async.mts +97 -0
- package/core/src/nako_parser_base.mts +4 -55
- package/core/src/nako_parser_message.mts +105 -0
- package/core/src/nako_parser_operator.mts +93 -0
- package/core/src/nako_plugin_manager.mts +260 -0
- package/core/src/nako_require.mts +292 -0
- package/core/src/nako_runner.mts +191 -0
- package/core/src/nako_tokenizer.mts +221 -0
- package/core/src/plugin_csv.mts +1 -1
- package/core/src/plugin_system.mts +34 -3259
- package/core/src/plugin_system_array.mts +699 -0
- package/core/src/plugin_system_datetime.mts +368 -0
- package/core/src/plugin_system_debug.mts +403 -0
- package/core/src/plugin_system_dict.mts +85 -0
- package/core/src/plugin_system_json.mts +73 -0
- package/core/src/plugin_system_math.mts +383 -0
- package/core/src/plugin_system_regexp.mts +120 -0
- package/core/src/plugin_system_stdio.mts +86 -0
- package/core/src/plugin_system_string.mts +666 -0
- package/core/src/plugin_system_timer.mts +152 -0
- package/core/src/plugin_system_types.mts +151 -0
- package/core/src/plugin_system_url.mts +193 -0
- package/core/src/plugin_toml.mts +3 -3
- package/core/test/fixtures/README.md +39 -0
- package/core/test/fixtures/make_parser_ast_golden.mjs +31 -0
- package/core/test/fixtures/parser_ast_golden.json +8027 -0
- package/core/test/fixtures/parser_corpus.mjs +120 -0
- package/core/test/indent_test.mjs +6 -0
- package/core/test/nako_basic_plugins_test.mjs +44 -0
- package/core/test/nako_event_test.mjs +85 -0
- package/core/test/nako_gen_perf_test.mjs +178 -0
- package/core/test/nako_parser_async_test.mjs +112 -0
- package/core/test/nako_parser_test.mjs +160 -0
- package/core/test/nako_plugin_manager_test.mjs +185 -0
- package/core/test/nako_require_test.mjs +153 -0
- package/core/test/nako_runner_test.mjs +114 -0
- package/core/test/nako_tokenizer_test.mjs +115 -0
- package/core/test/plugin_system_debug_test.mjs +141 -0
- package/core/test/plugin_system_split_test.mjs +179 -0
- package/core/test/plugin_system_test.mjs +6 -0
- package/core/tsconfig.json +0 -1
- package/package.json +24 -34
- package/release/_hash.txt +40 -40
- package/release/_script-tags.txt +16 -16
- package/release/command.json +1 -1
- package/release/command.json.js +1 -1
- package/release/command_cnako3.json +1 -1
- package/release/command_list.json +1 -1
- package/release/edit_main.js +6 -6
- package/release/edit_main.js.map +3 -3
- package/release/editor.js +6 -6
- package/release/plugin_datetime.js +1 -1
- package/release/plugin_datetime.js.map +3 -3
- package/release/plugin_keigo.js.map +3 -3
- package/release/plugin_markup.js +47 -47
- package/release/plugin_markup.js.map +3 -3
- package/release/plugin_weykturtle3d.js +1 -1
- package/release/plugin_weykturtle3d.js.map +3 -3
- package/release/version.js +2 -2
- package/release/version_main.js +2 -2
- package/release/version_main.js.map +2 -2
- package/release/wnako3.js +187 -214
- package/release/wnako3.js.map +4 -4
- package/release/wnako3webworker.js +172 -199
- package/release/wnako3webworker.js.map +4 -4
- package/src/cnako3mod.mjs +8 -4
- package/src/cnako3mod.mts +8 -4
- package/src/nako_version.mjs +2 -2
- package/src/nako_version.mts +2 -2
- package/src/plugin_browser_ajax.mjs +4 -4
- package/src/plugin_browser_ajax.mts +4 -4
- package/src/plugin_browser_audio.mjs +10 -10
- package/src/plugin_browser_audio.mts +10 -10
- package/src/plugin_browser_camera.mjs +4 -4
- package/src/plugin_browser_camera.mts +4 -4
- package/src/plugin_browser_canvas.mjs +2 -2
- package/src/plugin_browser_canvas.mts +2 -2
- package/src/plugin_browser_crypto.mjs +3 -3
- package/src/plugin_browser_crypto.mts +3 -3
- package/src/plugin_browser_dom_event.mjs +1 -1
- package/src/plugin_browser_dom_event.mts +1 -1
- package/src/plugin_browser_geolocation.mjs +1 -1
- package/src/plugin_browser_geolocation.mts +1 -1
- package/src/plugin_browser_hotkey.mjs +1 -1
- package/src/plugin_browser_hotkey.mts +1 -1
- package/src/plugin_browser_html.mjs +1 -1
- package/src/plugin_browser_html.mts +1 -1
- package/src/plugin_browser_location.mjs +1 -1
- package/src/plugin_browser_location.mts +1 -1
- package/src/plugin_browser_speech.mjs +1 -1
- package/src/plugin_browser_speech.mts +1 -1
- package/src/plugin_browser_storage.mjs +2 -2
- package/src/plugin_browser_storage.mts +2 -2
- package/src/plugin_httpserver.mjs +186 -15
- package/src/plugin_httpserver.mts +178 -12
- package/src/plugin_keigo.mjs +2 -2
- package/src/plugin_keigo.mts +2 -2
- package/src/plugin_node.mjs +48 -49
- package/src/plugin_node.mts +53 -54
- package/src/plugin_weykturtle3d.mjs +56 -56
- package/src/plugin_weykturtle3d.mts +56 -56
- package/src/wnako3.mjs +1 -1
- package/src/wnako3.mts +1 -1
- package/src/wnako3_editor.mjs +5 -5
- package/src/wnako3_editor.mts +5 -5
- package/src/wnako3mod.mjs +5 -2
- package/src/wnako3mod.mts +5 -2
- package/test/common/wnako3mod_test.mjs +48 -0
- package/test/node/package_json_test.mjs +17 -0
- package/test/node/plugin_httpserver_test.mjs +239 -0
- package/tools/nako3server/index.nako3 +4 -2
- package/core/src/nako3.mjs +0 -1021
- package/core/src/nako_ast.mjs +0 -4
- package/core/src/nako_colors.mjs +0 -77
- package/core/src/nako_core_version.mjs +0 -8
- package/core/src/nako_csv.mjs +0 -193
- package/core/src/nako_errors.mjs +0 -166
- package/core/src/nako_from_dncl.mjs +0 -285
- package/core/src/nako_from_dncl2.mjs +0 -347
- package/core/src/nako_gen.mjs +0 -2500
- package/core/src/nako_global.mjs +0 -138
- package/core/src/nako_indent.mjs +0 -442
- package/core/src/nako_indent_chars.mjs +0 -29
- package/core/src/nako_indent_inline.mjs +0 -361
- package/core/src/nako_josi_list.mjs +0 -47
- package/core/src/nako_lex_rules.mjs +0 -319
- package/core/src/nako_lexer.mjs +0 -794
- package/core/src/nako_logger.mjs +0 -221
- package/core/src/nako_parser3.mjs +0 -3250
- package/core/src/nako_parser_base.mjs +0 -403
- package/core/src/nako_parser_const.mjs +0 -37
- package/core/src/nako_prepare.mjs +0 -329
- package/core/src/nako_reserved_words.mjs +0 -42
- package/core/src/nako_source_mapping.mjs +0 -207
- package/core/src/nako_test.mjs +0 -37
- package/core/src/nako_token.mjs +0 -1
- package/core/src/nako_tools.mjs +0 -53
- package/core/src/nako_types.mjs +0 -14
- package/core/src/plugin_api.mjs +0 -4
- package/core/src/plugin_csv.mjs +0 -97
- package/core/src/plugin_math.mjs +0 -352
- package/core/src/plugin_promise.mjs +0 -102
- package/core/src/plugin_system.mjs +0 -3810
- package/core/src/plugin_test.mjs +0 -52
- package/core/src/plugin_toml.mjs +0 -39
|
@@ -0,0 +1,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
|
+
}
|