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,699 @@
1
+ /**
2
+ * @fileOverview なでしこ3 plugin_system の分割ファイル
3
+ *
4
+ * 配列操作・二次元配列処理の命令を定義する。
5
+ * このファイルは単独のプラグインではなく、plugin_system.mts へマージされる。(#2351)
6
+ */
7
+ export default {
8
+ // @配列操作
9
+ '配列結合': { // @配列Aを文字列Sでつなげて文字列で返す // @はいれつけつごう
10
+ type: 'func',
11
+ josi: [['を'], ['で']],
12
+ pure: true,
13
+ fn: function(a: any, s: string): string {
14
+ // 配列ならOK
15
+ if (a instanceof Array) { return a.join('' + s) }
16
+
17
+ const a2 = String(a).split('\n') // 配列でなければ無理矢理改行で区切ってみる
18
+ return a2.join('' + s)
19
+ }
20
+ },
21
+ '配列只結合': { // @配列Aの要素をただ結合して文字列で返す。(「」で配列結合と同じ) // @はいれつただけつごう
22
+ type: 'func',
23
+ josi: [['を']],
24
+ pure: true,
25
+ fn: function(a: any): string {
26
+ if (a instanceof Array) { return a.join('') }
27
+ const a2 = String(a).split('\n') // 配列でなければ無理矢理改行で区切ってみる
28
+ return a2.join('')
29
+ }
30
+ },
31
+ '配列検索': { // @配列Aから文字列Sを探してインデックス番号(0起点)を返す。見つからなければ-1を返す。 // @はいれつけんさく
32
+ type: 'func',
33
+ josi: [['の', 'から'], ['を']],
34
+ pure: true,
35
+ fn: function(a: any, s: any) {
36
+ if (a instanceof Array) { return a.indexOf(s) }// 配列ならOK
37
+
38
+ return -1
39
+ }
40
+ },
41
+ '配列要素数': { // @配列Aの要素数を返す // @はいれつようそすう
42
+ type: 'func',
43
+ josi: [['の']],
44
+ pure: true,
45
+ fn: function(a: any) {
46
+ if (a instanceof Array) { return a.length }// 配列ならOK
47
+ if (a instanceof Object) { return Object.keys(a).length } // オブジェクト
48
+ if (typeof a === 'string') { return String(a).length } // 文字列
49
+ return 1
50
+ }
51
+ },
52
+ '要素数': { // @Aの要素数を返す。Aには配列/辞書型/文字列を指定する。 // @ようそすう
53
+ type: 'func',
54
+ josi: [['の']],
55
+ pure: true,
56
+ fn: function(a: any, sys: any) {
57
+ return sys.__exec('配列要素数', [a])
58
+ }
59
+ },
60
+ 'LEN': { // @Aの要素数を返す。Aには配列/辞書型/文字列を指定する。 // @LEN
61
+ type: 'func',
62
+ josi: [['の']],
63
+ pure: true,
64
+ fn: function(a: any, sys: any) {
65
+ return sys.__exec('配列要素数', [a])
66
+ }
67
+ },
68
+ '配列挿入': { // @配列AのI番目(0起点)に要素Sを追加して返す(v1非互換) // @はいれつそうにゅう
69
+ type: 'func',
70
+ josi: [['の'], ['に', 'へ'], ['を']],
71
+ pure: true,
72
+ fn: function(a: any, i: any, s: any) {
73
+ if (a instanceof Array) { return a.splice(i, 0, s) } // 配列ならOK
74
+
75
+ throw new Error('『配列挿入』で配列以外の要素への挿入。')
76
+ }
77
+ },
78
+ '配列一括挿入': { // @配列AのI番目(0起点)に配列bを追加して返す(v1非互換) // @はいれついっかつそうにゅう
79
+ type: 'func',
80
+ josi: [['の'], ['に', 'へ'], ['を']],
81
+ pure: true,
82
+ fn: function(a: any, i: number, b: any) {
83
+ if (a instanceof Array && b instanceof Array) { // 配列ならOK
84
+ for (let j = 0; j < b.length; j++) { a.splice(i + j, 0, b[j]) }
85
+
86
+ return a
87
+ }
88
+ throw new Error('『配列一括挿入』で配列以外の要素への挿入。')
89
+ }
90
+ },
91
+ '配列ソート': { // @配列Aをソートして返す(A自体を変更) // @はいれつそーと
92
+ type: 'func',
93
+ josi: [['の', 'を']],
94
+ pure: true,
95
+ fn: function(a: any) {
96
+ if (a instanceof Array) { return a.sort() } // 配列ならOK
97
+
98
+ throw new Error('『配列ソート』で配列以外が指定されました。')
99
+ }
100
+ },
101
+ '配列数値変換': { // @配列Aの各要素を数値に変換して返す(変数A自体を変更) // @はいれつすうちへんかん
102
+ type: 'func',
103
+ josi: [['の', 'を']],
104
+ pure: true,
105
+ fn: function(a: any) {
106
+ // 配列ならOK
107
+ if (a instanceof Array) {
108
+ for (let i = 0; i < a.length; i++) {
109
+ a[i] = parseFloat(a[i])
110
+ }
111
+ return a
112
+ }
113
+ throw new Error('『配列数値変換』で配列以外が指定されました。')
114
+ }
115
+ },
116
+ '配列数値ソート': { // @配列Aをソートして返す(A自体を変更) // @はいれつすうちそーと
117
+ type: 'func',
118
+ josi: [['の', 'を']],
119
+ pure: true,
120
+ fn: function(a: any) {
121
+ // 配列ならOK
122
+ if (a instanceof Array) {
123
+ return a.sort((a, b) => {
124
+ return parseFloat(a) - parseFloat(b)
125
+ })
126
+ }
127
+
128
+ throw new Error('『配列数値ソート』で配列以外が指定されました。')
129
+ }
130
+ },
131
+ '配列カスタムソート': { // @関数Fで配列Aをソートして返す(引数A自体を変更) // @はいれつかすたむそーと
132
+ type: 'func',
133
+ josi: [['で'], ['の', 'を']],
134
+ pure: false,
135
+ fn: function(f: any, a: any, sys: any) {
136
+ let ufunc = f
137
+ if (typeof f === 'string') {
138
+ ufunc = sys.__findFunc(f, '配列カスタムソート')
139
+ }
140
+ if (a instanceof Array) {
141
+ return a.sort(ufunc)
142
+ }
143
+ throw new Error('『配列カスタムソート』で配列以外が指定されました。')
144
+ }
145
+ },
146
+ '配列逆順': { // @配列Aを逆にして返す。Aを書き換える(A自体を変更)。 // @はいれつぎゃくじゅん
147
+ type: 'func',
148
+ josi: [['の', 'を']],
149
+ pure: true,
150
+ fn: function(a: any) {
151
+ if (a instanceof Array) { return a.reverse() } // 配列ならOK
152
+ throw new Error('『配列ソート』で配列以外が指定されました。')
153
+ }
154
+ },
155
+ '配列シャッフル': { // @配列Aをシャッフルして返す。Aを書き換える // @はいれつしゃっふる
156
+ type: 'func',
157
+ josi: [['の', 'を']],
158
+ pure: true,
159
+ fn: function(a: any) {
160
+ if (a instanceof Array) { // 配列ならOK
161
+ for (let i = a.length - 1; i > 0; i--) {
162
+ const r = Math.floor(Math.random() * (i + 1))
163
+ const tmp = a[i]
164
+ a[i] = a[r]
165
+ a[r] = tmp
166
+ }
167
+ return a
168
+ }
169
+ throw new Error('『配列シャッフル』で配列以外が指定されました。')
170
+ }
171
+ },
172
+ '配列削除': { // @配列AのI番目(0起点)の要素を削除して返す。Aの内容を書き換える。辞書型変数ならキーIを削除する。 // @はいれつさくじょ
173
+ type: 'func',
174
+ josi: [['の', 'から'], ['を']],
175
+ pure: true,
176
+ fn: function(a: any, i: any, sys: any) {
177
+ return sys.__exec('配列切取', [a, i, sys])
178
+ }
179
+ },
180
+ '配列切取': { // @配列AのI番目(0起点)の要素を切り取って返す。Aの内容を書き換える。引数Iには範囲オブジェクトを指定できる。その場合戻り値は配列型となる。辞書型変数ならキーIを削除する。 // @はいれつきりとる
181
+ type: 'func',
182
+ josi: [['の', 'から'], ['を']],
183
+ pure: true,
184
+ fn: function(a: any, i: any) {
185
+ // 配列変数のとき
186
+ if (a instanceof Array) {
187
+ if (typeof i === 'number') {
188
+ const b = a.splice(i, 1)
189
+ if (b instanceof Array) { return b[0] } // 切り取った戻り値は必ずArrayになるので。
190
+ }
191
+ if (typeof i === 'object' && typeof i['先頭'] === 'number') {
192
+ const idx = i['先頭']
193
+ const cnt = i['末尾'] - i['先頭'] + 1
194
+ return a.splice(idx, cnt)
195
+ }
196
+ return null
197
+ }
198
+ // 辞書型変数のとき
199
+ if (a instanceof Object && typeof (i) === 'string') { // 辞書型変数も許容
200
+ if (a[i]) {
201
+ const old = a[i]
202
+ delete a[i]
203
+ return old
204
+ }
205
+ return undefined
206
+ }
207
+ throw new Error('『配列切取』で配列以外を指定。')
208
+ }
209
+ },
210
+ '配列取出': { // @配列AのI番目(0起点)からCNT個の要素を取り出して返す。Aの内容を書き換える // @はいれつとりだし
211
+ type: 'func',
212
+ josi: [['の'], ['から'], ['を']],
213
+ pure: true,
214
+ fn: function(a: any, i: any, cnt: any) {
215
+ if (a instanceof Array) { return a.splice(i, cnt) }
216
+ throw new Error('『配列取出』で配列以外を指定。')
217
+ }
218
+ },
219
+ '配列ポップ': { // @配列Aの末尾を取り出して返す。Aの内容を書き換える。 // @はいれつぽっぷ
220
+ type: 'func',
221
+ josi: [['の', 'から']],
222
+ pure: true,
223
+ fn: function(a: any) {
224
+ if (a instanceof Array) { return a.pop() }
225
+ throw new Error('『配列ポップ』で配列以外の処理。')
226
+ }
227
+ },
228
+ '配列プッシュ': { // @配列Aの末尾にNを追加。Aの内容を書き換える。(『配列追加』と同じ) // @はいれつぷっしゅ
229
+ type: 'func',
230
+ josi: [['に', 'へ'], ['を']],
231
+ pure: true,
232
+ fn: function(a: any, b: any, sys: any) {
233
+ return sys.__exec('配列追加', [a, b, sys])
234
+ }
235
+ },
236
+ '配列追加': { // @配列Aの末尾にBを追加して返す。Aの内容を書き換える。 // @はいれつついか
237
+ type: 'func',
238
+ josi: [['に', 'へ'], ['を']],
239
+ pure: true,
240
+ fn: function(a: any, b: any) {
241
+ if (a instanceof Array) { // 配列ならOK
242
+ a.push(b)
243
+ return a
244
+ }
245
+ throw new Error('『配列追加』で配列以外の処理。')
246
+ }
247
+ },
248
+ '配列複製': { // @配列Aを複製して返す。 // @はいれつふくせい
249
+ type: 'func',
250
+ josi: [['を']],
251
+ pure: true,
252
+ fn: function(a: any) {
253
+ return JSON.parse(JSON.stringify(a))
254
+ }
255
+ },
256
+ '配列範囲コピー': { // @配列Aの範囲I(数値化範囲オブジェクト)を複製して返す。 // @はいれつはんいこぴー
257
+ type: 'func',
258
+ josi: [['の', 'から'], ['を']],
259
+ pure: true,
260
+ fn: function(a: any, i: any) {
261
+ if (!Array.isArray(a)) {
262
+ throw new Error('『配列範囲コピー』で配列以外の値が指定されました。')
263
+ }
264
+ if (typeof i === 'number') {
265
+ if (typeof a[i] === 'object') {
266
+ return JSON.parse(JSON.stringify(a[i]))
267
+ }
268
+ return a[i]
269
+ }
270
+ // 範囲オブジェクトのとき
271
+ if (typeof i === 'object' && typeof i['先頭'] === 'number') {
272
+ const start = i['先頭']
273
+ const last = Number(i['末尾']) + 1
274
+ return JSON.parse(JSON.stringify(a.slice(start, last)))
275
+ }
276
+ return undefined
277
+ }
278
+ },
279
+ '参照': { // @値A(配列/文字列/辞書型)の範囲I(キーまたは範囲オブジェクト)を参照して(コピーせず)返す // @さんしょう
280
+ type: 'func',
281
+ josi: [['から', 'の'], ['を']],
282
+ pure: true,
283
+ fn: function(a: any, i: any, _sys: any) {
284
+ // 文字列のとき
285
+ if (typeof a === 'string') {
286
+ if (typeof i === 'number') {
287
+ return a.charAt(i)
288
+ }
289
+ // 範囲オブジェクトのとき
290
+ if (typeof i === 'object' && typeof i['先頭'] === 'number') {
291
+ const start = i['先頭']
292
+ const last = Number(i['末尾']) + 1
293
+ return a.substring(start, last)
294
+ }
295
+ throw new Error(`『参照』で文字列型の範囲指定(${JSON.stringify(i)})が不正です。`)
296
+ }
297
+ // 配列型のとき
298
+ if (Array.isArray(a)) {
299
+ if (typeof i === 'number') {
300
+ return a[i]
301
+ }
302
+ // 範囲オブジェクトのとき
303
+ if (typeof i === 'object' && typeof i['先頭'] === 'number') {
304
+ const start = i['先頭']
305
+ const last = Number(i['末尾']) + 1
306
+ return a.slice(start, last)
307
+ }
308
+ }
309
+ // 辞書型のとき
310
+ if (typeof a === 'object') {
311
+ return a[i]
312
+ }
313
+ throw new Error('『参照』で文字列/配列/辞書型以外の値が指定されました。')
314
+ }
315
+ },
316
+ '配列参照': { // @値A(配列/文字列/辞書型)の範囲I(キーまたは範囲オブジェクト)を参照して(コピーせず)返す(『参照』と同じ) // @はいれつはんいさんしょう
317
+ type: 'func',
318
+ josi: [['の', 'から'], ['を']],
319
+ pure: true,
320
+ fn: function(a: any, i: any, sys: any) {
321
+ return sys.__exec('参照', [a, i, sys])
322
+ }
323
+ },
324
+ '配列足': { // @配列Aに配列Bを足し合わせて返す。 // @はいれつたす
325
+ type: 'func',
326
+ josi: [['に', 'へ', 'と'], ['を']],
327
+ pure: true,
328
+ fn: function(a: any, b: any) {
329
+ if (a instanceof Array) {
330
+ return a.concat(b)
331
+ }
332
+ return JSON.parse(JSON.stringify(a))
333
+ }
334
+ },
335
+ '配列最大値': { // @配列Aの値の最大値を調べて返す。 // @はいれつさいだいち
336
+ type: 'func',
337
+ josi: [['の']],
338
+ pure: true,
339
+ fn: function(a: any) {
340
+ return a.reduce((x: any, y: any) => Math.max(x, y))
341
+ }
342
+ },
343
+ '配列最小値': { // @配列Aの値の最小値を調べて返す。 // @はいれつさいしょうち
344
+ type: 'func',
345
+ josi: [['の']],
346
+ pure: true,
347
+ fn: function(a: any) {
348
+ return a.reduce((x: any, y: any) => Math.min(x, y))
349
+ }
350
+ },
351
+ '配列合計': { // @配列Aの値を全て足して返す。配列の各要素を数値に変換して計算する。数値に変換できない文字列は0になる。 // @はいれつごうけい
352
+ type: 'func',
353
+ josi: [['の']],
354
+ pure: true,
355
+ fn: function(a: any) {
356
+ if (a instanceof Array) {
357
+ let v = 0
358
+ a.forEach((n) => {
359
+ const nn = parseFloat(n)
360
+ if (isNaN(nn)) { return }
361
+ v += nn
362
+ })
363
+ return v
364
+ }
365
+ throw new Error('『配列合計』で配列変数以外の値が指定されました。')
366
+ }
367
+ },
368
+ '配列入替': { // @配列Aの(0から数えて)I番目とJ番目の要素を入れ替えて返す。Aの内容を書き換える。// @はいれついれかえ
369
+ type: 'func',
370
+ josi: [['の'], ['と'], ['を']],
371
+ pure: true,
372
+ fn: function(a: any, i: number, j: number) {
373
+ if (!(a instanceof Array)) {
374
+ throw new Error('『配列入替』の第1引数には配列を指定してください。')
375
+ }
376
+ const tmp = a[i]
377
+ a[i] = a[j]
378
+ a[j] = tmp
379
+ return a
380
+ }
381
+ },
382
+ '配列連番作成': { // @AからBまでの連番配列を生成して返す。 // @はいれつれんばんさくせい
383
+ type: 'func',
384
+ josi: [['から'], ['までの', 'まで', 'の']],
385
+ pure: true,
386
+ fn: function(a: number, b: number) {
387
+ const result: number[] = []
388
+ for (let i = a; i <= b; i++) {
389
+ result.push(i)
390
+ }
391
+ return result
392
+ }
393
+ },
394
+ '配列要素作成': { // @値AをB個持つ配列を生成して返す。引数Bに配列を指定すると二次元以上の配列を生成する。// @はいれつようそさくせい
395
+ type: 'func',
396
+ josi: [['を'], ['だけ', 'で']],
397
+ pure: true,
398
+ fn: function(a: any, b: number | number[]) {
399
+ // value が配列やオブジェクトでも深くコピーするヘルパー
400
+ const cloneValue = (v: any): any => {
401
+ if (Array.isArray(v)) {
402
+ return (v).map(item => cloneValue(item)) as any
403
+ }
404
+ if (v instanceof Date) {
405
+ return new Date(v.getTime())
406
+ }
407
+ if (typeof v === 'object' && v !== null) {
408
+ return JSON.parse(JSON.stringify(v))
409
+ }
410
+ return v
411
+ }
412
+ // 再帰的に配列を生成する関数
413
+ const full = function(value: any, shape: number | number[]): any {
414
+ // 1次元:shape が数値
415
+ if (!Array.isArray(shape)) {
416
+ return Array.from({ length: shape }, () => cloneValue(value))
417
+ }
418
+ // 1次元:shape が数値
419
+ if (Array.isArray(shape) && shape.length === 1) {
420
+ return Array.from({ length: shape[0] }, () => cloneValue(value))
421
+ }
422
+ // 多次元:shape が配列
423
+ const [first, ...rest] = shape
424
+ return Array.from(
425
+ { length: first },
426
+ () => full(cloneValue(value), rest)
427
+ )
428
+ }
429
+ return full(a, b)
430
+ }
431
+ },
432
+ '配列関数適用': { // @引数を1つ持つ関数Fを、配列Aの全要素に適用した、新しい配列を返す。 // @はいれつかんすうてきよう
433
+ type: 'func',
434
+ josi: [['を'], ['へ', 'に']],
435
+ pure: true,
436
+ fn: function(f: any, a: any, sys: any) {
437
+ let ufunc: any = f
438
+ if (typeof f === 'string') { ufunc = sys.__findFunc(f, '配列関数適用') }
439
+ const result: any = []
440
+ for (const e of a) {
441
+ result.push(ufunc(e))
442
+ }
443
+ return result
444
+ }
445
+ },
446
+ '配列マップ': { // @引数を1つ持つ関数Fを、配列Aの全要素に適用した、新しい配列を返す。(『配列関数適用』と同じ) // @はいれつまっぷ
447
+ type: 'func',
448
+ josi: [['を'], ['へ', 'に']],
449
+ pure: true,
450
+ fn: function(f: any, a: any, sys: any) {
451
+ return sys.__exec('配列関数適用', [f, a, sys])
452
+ }
453
+ },
454
+ '配列フィルタ': { // @引数を1つ持ち真偽を返す関数Fを利用して、配列Aの要素をフィルタして、新しい配列として返す。 // @はいれつふぃるた
455
+ type: 'func',
456
+ josi: [['で', 'の'], ['を', 'について']],
457
+ pure: true,
458
+ fn: function(f: any, a: any, sys: any) {
459
+ let ufunc: any = f
460
+ if (typeof f === 'string') { ufunc = sys.__findFunc(f, '配列フィルタ') }
461
+ const result: any = []
462
+ for (const e of a) {
463
+ if (ufunc(e)) { result.push(e) }
464
+ }
465
+ return result
466
+ }
467
+ },
468
+
469
+ // @二次元配列処理
470
+ '表ソート': { // @二次元配列AでB列目(0起点)(あるいはキー名)をキーに文字列順にソートする。Aの内容を書き換える。 // @ひょうそーと
471
+ type: 'func',
472
+ josi: [['の'], ['を']],
473
+ pure: true,
474
+ fn: function(a: any, no: any) {
475
+ if (!(a instanceof Array)) {
476
+ throw new Error('『表ソート』には配列を指定する必要があります。')
477
+ }
478
+ a.sort((n, m) => {
479
+ const ns = n[no]
480
+ const ms = m[no]
481
+
482
+ if (ns === ms) {
483
+ return 0
484
+ } else if (ns < ms) {
485
+ return -1
486
+ } else {
487
+ return 1
488
+ }
489
+ })
490
+ return a
491
+ }
492
+ },
493
+ '表数値ソート': { // @二次元配列AでB列目(0起点)(あるいはキー名)をキーに数値順にソートする。Aの内容を書き換える。 // @ひょうすうちそーと
494
+ type: 'func',
495
+ josi: [['の'], ['を']],
496
+ pure: true,
497
+ fn: function(a: any, no: number) {
498
+ if (!(a instanceof Array)) {
499
+ throw new Error('『表数値ソート』には配列を指定する必要があります。')
500
+ }
501
+ a.sort((n, m) => {
502
+ const ns = n[no]
503
+ const ms = m[no]
504
+ return ns - ms
505
+ })
506
+ return a
507
+ }
508
+ },
509
+ '表ピックアップ': { // @配列Aの列番号B(0起点)(あるいはキー名)で検索文字列Sを含む行を返す // @ひょうぴっくあっぷ
510
+ type: 'func',
511
+ josi: [['の'], ['から'], ['を', 'で']],
512
+ pure: true,
513
+ fn: function(a: any, no: number, s: any) {
514
+ if (!(a instanceof Array)) { throw new Error('『表ピックアップ』には配列を指定する必要があります。') }
515
+ return a.filter((row) => String(row[no]).indexOf(s) >= 0)
516
+ }
517
+ },
518
+ '表完全一致ピックアップ': { // @配列Aの列番号B(0起点)(あるいはキー名)で検索文字列Sと一致する行を返す // @ひょうかんぜんいっちぴっくあっぷ
519
+ type: 'func',
520
+ josi: [['の'], ['から'], ['を', 'で']],
521
+ pure: true,
522
+ fn: function(a: any, no: number, s: any) {
523
+ if (!(a instanceof Array)) { throw new Error('『表完全ピックアップ』には配列を指定する必要があります。') }
524
+ return a.filter((row) => row[no] === s)
525
+ }
526
+ },
527
+ '表検索': { // @二次元配列AでCOL列目(0起点)からキーSを含む行をROW行目から検索して何行目にあるか返す。見つからなければ-1を返す。 // @ひょうけんさく
528
+ type: 'func',
529
+ josi: [['の'], ['で', 'に'], ['から'], ['を']],
530
+ pure: true,
531
+ fn: function(a: any, col: number, row: number, s: any) {
532
+ if (!(a instanceof Array)) { throw new Error('『表検索』には配列を指定する必要があります。') }
533
+ for (let i = row; i < a.length; i++) {
534
+ if (a[i][col] === s) { return i }
535
+ }
536
+ return -1
537
+ }
538
+ },
539
+ '表列数': { // @二次元配列Aの列数を調べて返す。 // @ひょうれつすう
540
+ type: 'func',
541
+ josi: [['の']],
542
+ pure: true,
543
+ fn: function(a: any) {
544
+ if (!(a instanceof Array)) { throw new Error('『表列数』には配列を指定する必要があります。') }
545
+ let cols = 1
546
+ for (let i = 0; i < a.length; i++) {
547
+ if (a[i].length > cols) { cols = a[i].length }
548
+ }
549
+ return cols
550
+ }
551
+ },
552
+ '表行数': { // @二次元配列Aの行数を調べて返す。 // @ひょうぎょうすう
553
+ type: 'func',
554
+ josi: [['の']],
555
+ pure: true,
556
+ fn: function(a: any) {
557
+ if (!(a instanceof Array)) { throw new Error('『表行数』には配列を指定する必要があります。') }
558
+ return a.length
559
+ }
560
+ },
561
+ '表行列交換': { // @二次元配列Aの行と列を交換して返す。 // @ひょうぎょうれつこうかん
562
+ type: 'func',
563
+ josi: [['の', 'を']],
564
+ pure: true,
565
+ fn: function(a: any, sys: any) {
566
+ if (!(a instanceof Array)) { throw new Error('『表行列交換』には配列を指定する必要があります。') }
567
+ const cols = sys.__exec('表列数', [a])
568
+ const rows = a.length
569
+ const res = []
570
+ for (let r = 0; r < cols; r++) {
571
+ const row: any[] = []
572
+ res.push(row)
573
+ for (let c = 0; c < rows; c++) {
574
+ row[c] = (a[c][r] !== undefined) ? a[c][r] : ''
575
+ }
576
+ }
577
+ return res
578
+ }
579
+ },
580
+ '表右回転': { // @二次元配列Aを90度回転して返す。 // @ひょうみぎかいてん
581
+ type: 'func',
582
+ josi: [['の', 'を']],
583
+ pure: true,
584
+ fn: function(a: any, sys: any) {
585
+ if (!(a instanceof Array)) { throw new Error('『表右回転』には配列を指定する必要があります。') }
586
+ const cols = sys.__exec('表列数', [a])
587
+ const rows = a.length
588
+ const res = []
589
+ for (let r = 0; r < cols; r++) {
590
+ const row: any[] = []
591
+ res.push(row)
592
+ for (let c = 0; c < rows; c++) {
593
+ row[c] = a[rows - c - 1][r]
594
+ }
595
+ }
596
+ return res
597
+ }
598
+ },
599
+ '表重複削除': { // @二次元配列AのI列目にある重複項目を削除して返す。 // @ひょうじゅうふくさくじょ
600
+ type: 'func',
601
+ josi: [['の'], ['を', 'で']],
602
+ pure: true,
603
+ fn: function(a: any, i: any) {
604
+ if (!(a instanceof Array)) { throw new Error('『表重複削除』には配列を指定する必要があります。') }
605
+ const res: any[] = []
606
+ const keys:{[key: string]: boolean} = {}
607
+ for (let n = 0; n < a.length; n++) {
608
+ const k = a[n][i]
609
+ if (undefined === keys[k]) {
610
+ keys[k] = true
611
+ res.push(a[n])
612
+ }
613
+ }
614
+ return res
615
+ }
616
+ },
617
+ '表列取得': { // @二次元配列AのI列目を返す。 // @ひょうれつしゅとく
618
+ type: 'func',
619
+ josi: [['の'], ['を']],
620
+ pure: true,
621
+ fn: function(a: any, i: number) {
622
+ if (!(a instanceof Array)) { throw new Error('『表列取得』には配列を指定する必要があります。') }
623
+ const res = a.map(row => row[i])
624
+ return res
625
+ }
626
+ },
627
+ '表列挿入': { // @二次元配列Aの(0から数えて)I列目に配列Sを挿入して返す // @ひょうれつそうにゅう
628
+ type: 'func',
629
+ josi: [['の'], ['に', 'へ'], ['を']],
630
+ pure: true,
631
+ fn: function(a: any, i: any, s: any) {
632
+ if (!(a instanceof Array)) { throw new Error('『表列挿入』には配列を指定する必要があります。') }
633
+ const res: any[] = []
634
+ a.forEach((row, idx) => {
635
+ let nr: any[] = []
636
+ if (i > 0) { nr = nr.concat(row.slice(0, i)) }
637
+ nr.push(s[idx])
638
+ nr = nr.concat(row.slice(i))
639
+ res.push(nr)
640
+ })
641
+ return res
642
+ }
643
+ },
644
+ '表列削除': { // @二次元配列Aの(0から数えて)I列目削除して返す // @ひょうれつそうにゅう
645
+ type: 'func',
646
+ josi: [['の'], ['を']],
647
+ pure: true,
648
+ fn: function(a: any, i: any) {
649
+ if (!(a instanceof Array)) { throw new Error('『表列削除』には配列を指定する必要があります。') }
650
+ const res: any[] = []
651
+ a.forEach((row) => {
652
+ const nr = row.slice(0)
653
+ nr.splice(i, 1)
654
+ res.push(nr)
655
+ })
656
+ return res
657
+ }
658
+ },
659
+ '表列合計': { // @二次元配列Aの(0から数えて)I列目を合計して返す。 // @ひょうれつごうけい
660
+ type: 'func',
661
+ josi: [['の'], ['を', 'で']],
662
+ pure: true,
663
+ fn: function(a: any, i: any) {
664
+ if (!(a instanceof Array)) { throw new Error('『表列合計』には配列を指定する必要があります。') }
665
+ let sum = 0
666
+ a.forEach((row) => { sum += row[i] })
667
+ return sum
668
+ }
669
+ },
670
+ '表曖昧検索': { // @二次元配列AのROW行目からCOL列目(0起点)で正規表現Sにマッチする行を検索して何行目にあるか返す。見つからなければ-1を返す。(v1非互換) // @ひょうあいまいけんさく
671
+ type: 'func',
672
+ josi: [['の'], ['から'], ['で'], ['を']],
673
+ pure: true,
674
+ fn: function(a: any, row: any, col: any, s: any) {
675
+ if (!(a instanceof Array)) { throw new Error('『表曖昧検索』には配列を指定する必要があります。') }
676
+ const re = new RegExp(s)
677
+ for (let i = row; i < a.length; i++) {
678
+ const line = a[i]
679
+ if (re.test(line[col])) { return i }
680
+ }
681
+ return -1
682
+ }
683
+ },
684
+ '表正規表現ピックアップ': { // @二次元配列AでI列目(0起点)から正規表現パターンSにマッチする行をピックアップして返す。 // @ひょうせいきひょうげんぴっくあっぷ
685
+ type: 'func',
686
+ josi: [['の', 'で'], ['から'], ['を']],
687
+ pure: true,
688
+ fn: function(a: any, col: any, s: any) {
689
+ if (!(a instanceof Array)) { throw new Error('『表正規表現ピックアップ』には配列を指定する必要があります。') }
690
+ const re = new RegExp(s)
691
+ const res = []
692
+ for (let i = 0; i < a.length; i++) {
693
+ const row = a[i]
694
+ if (re.test(row[col])) { res.push(row.slice(0)) }
695
+ }
696
+ return res
697
+ }
698
+ },
699
+ }