nadesiko3 3.7.2 → 3.7.4

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 (159) hide show
  1. package/batch/command.txt +472 -469
  2. package/batch/pickup_command.nako3 +1 -1
  3. package/core/.eslintrc.cjs +10 -3
  4. package/core/package-lock.json +1184 -645
  5. package/core/package.json +4 -5
  6. package/core/src/nako3.mjs +8 -6
  7. package/core/src/nako3.mts +19 -16
  8. package/core/src/nako_ast.mts +2 -3
  9. package/core/src/nako_core_version.mjs +2 -2
  10. package/core/src/nako_core_version.mts +2 -2
  11. package/core/src/nako_csv.mjs +1 -0
  12. package/core/src/nako_csv.mts +3 -2
  13. package/core/src/nako_from_dncl.mjs +1 -1
  14. package/core/src/nako_from_dncl.mts +1 -1
  15. package/core/src/nako_from_dncl2.mjs +1 -1
  16. package/core/src/nako_from_dncl2.mts +2 -2
  17. package/core/src/nako_gen.mjs +37 -35
  18. package/core/src/nako_gen.mts +70 -67
  19. package/core/src/nako_global.mjs +3 -2
  20. package/core/src/nako_global.mts +3 -2
  21. package/core/src/nako_lexer.mjs +3 -3
  22. package/core/src/nako_lexer.mts +3 -3
  23. package/core/src/nako_logger.mjs +1 -1
  24. package/core/src/nako_logger.mts +2 -2
  25. package/core/src/nako_parser3.mjs +67 -59
  26. package/core/src/nako_parser3.mts +96 -90
  27. package/core/src/nako_parser_base.mts +3 -3
  28. package/core/src/nako_prepare.mjs +1 -1
  29. package/core/src/nako_prepare.mts +1 -1
  30. package/core/src/nako_source_mapping.mts +0 -1
  31. package/core/src/nako_token.mts +8 -8
  32. package/core/src/nako_types.mts +1 -1
  33. package/core/src/plugin_api.mts +1 -1
  34. package/core/src/plugin_csv.mjs +1 -0
  35. package/core/src/plugin_csv.mts +2 -1
  36. package/core/src/plugin_math.mjs +2 -2
  37. package/core/src/plugin_math.mts +3 -3
  38. package/core/src/plugin_promise.mjs +1 -1
  39. package/core/src/plugin_promise.mts +1 -1
  40. package/core/src/plugin_system.mjs +117 -40
  41. package/core/src/plugin_system.mts +132 -58
  42. package/core/src/plugin_test.mjs +3 -1
  43. package/core/src/plugin_test.mts +3 -1
  44. package/core/test/basic_test.mjs +16 -0
  45. package/core/test/calc_test.mjs +7 -0
  46. package/core/test/plugin_system_test.mjs +33 -0
  47. package/doc/files.md +4 -4
  48. package/doc/plugins.md +1 -1
  49. package/package.json +9 -9
  50. package/release/_hash.txt +36 -121
  51. package/release/_script-tags.txt +16 -33
  52. package/release/command.json +1 -1
  53. package/release/command.json.js +1 -1
  54. package/release/command_cnako3.json +1 -1
  55. package/release/command_list.json +1 -1
  56. package/release/edit_main.js +3 -3
  57. package/release/edit_main.js.map +2 -2
  58. package/release/editor.js +3 -3
  59. package/release/plugin_markup.js +53 -53
  60. package/release/plugin_markup.js.map +3 -3
  61. package/release/plugin_weykturtle3d.js +1 -1
  62. package/release/plugin_weykturtle3d.js.map +4 -4
  63. package/release/version.js +3 -3
  64. package/release/version_main.js +3 -3
  65. package/release/version_main.js.map +2 -2
  66. package/release/wnako3.js +66 -66
  67. package/release/wnako3.js.map +3 -3
  68. package/release/wnako3webworker.js +58 -58
  69. package/release/wnako3webworker.js.map +3 -3
  70. package/src/browsers.txt +30 -20
  71. package/src/cnako3mod.mjs +19 -18
  72. package/src/cnako3mod.mts +17 -16
  73. package/src/deno_wrapper.mjs +6 -6
  74. package/src/deno_wrapper.mts +11 -11
  75. package/src/nako_version.mjs +2 -2
  76. package/src/nako_version.mts +2 -2
  77. package/src/plugin_browser.mjs +2 -2
  78. package/src/plugin_browser.mts +5 -5
  79. package/src/plugin_browser_ajax.mjs +2 -2
  80. package/src/plugin_browser_ajax.mts +2 -2
  81. package/src/plugin_browser_api.mts +0 -1
  82. package/src/plugin_browser_crypto.mjs +8 -8
  83. package/src/plugin_browser_crypto.mts +13 -13
  84. package/src/plugin_browser_dom_basic.mjs +3 -3
  85. package/src/plugin_browser_dom_basic.mts +5 -7
  86. package/src/plugin_browser_dom_event.mjs +1 -1
  87. package/src/plugin_browser_dom_event.mts +2 -1
  88. package/src/plugin_browser_dom_parts.mjs +33 -18
  89. package/src/plugin_browser_dom_parts.mts +60 -59
  90. package/src/plugin_browser_speech.mjs +1 -1
  91. package/src/plugin_browser_speech.mts +1 -1
  92. package/src/plugin_node.mjs +5 -3
  93. package/src/plugin_node.mts +6 -4
  94. package/src/plugin_weykturtle3d.mjs +38 -15
  95. package/src/plugin_weykturtle3d.mts +279 -240
  96. package/src/plugin_weykturtle3d_three.mjs +3 -0
  97. package/src/plugin_weykturtle3d_three.mts +214 -0
  98. package/src/plugin_weykturtle3d_threeutil.mjs +28 -0
  99. package/src/plugin_weykturtle3d_threeutil.mts +31 -0
  100. package/src/wnako3.mjs +1 -0
  101. package/src/wnako3.mts +1 -0
  102. package/src/wnako3mod.mjs +5 -2
  103. package/src/wnako3mod.mts +6 -3
  104. package/batch/command_nakopad.txt +0 -1177
  105. package/core/__report.txt +0 -617
  106. package/core/command/plugin_snako.mjs +0 -112
  107. package/core/command/snako.mjs +0 -108
  108. package/release/core_src_nako_josi_list_mjs.js +0 -3
  109. package/release/core_src_nako_josi_list_mjs.js.LICENSE.txt +0 -3
  110. package/release/core_src_nako_josi_list_mjs.js.map +0 -1
  111. package/release/core_src_nako_reserved_words_mjs.js +0 -3
  112. package/release/core_src_nako_reserved_words_mjs.js.LICENSE.txt +0 -3
  113. package/release/core_src_nako_reserved_words_mjs.js.map +0 -1
  114. package/release/editor/edit_main.js +0 -48
  115. package/release/editor/edit_main.js.map +0 -7
  116. package/release/editor/version_main.js +0 -44
  117. package/release/editor/version_main.js.map +0 -7
  118. package/release/editor.js.LICENSE.txt +0 -91
  119. package/release/editor.js.map +0 -1
  120. package/release/nako_gen_async.js +0 -2
  121. package/release/nako_gen_async.js.LICENSE.txt +0 -21
  122. package/release/nako_gen_async.js.map +0 -1
  123. package/release/plugin_caniuse.js.LICENSE.txt +0 -15
  124. package/release/plugin_datetime.js.LICENSE.txt +0 -21
  125. package/release/plugin_kansuji.js.LICENSE.txt +0 -3
  126. package/release/plugin_markup.js.LICENSE.txt +0 -15
  127. package/release/plugin_toml.js +0 -295
  128. package/release/plugin_toml.js.map +0 -7
  129. package/release/plugin_turtle.js.LICENSE.txt +0 -9
  130. package/release/plugin_webworker.js.LICENSE.txt +0 -3
  131. package/release/plugin_weykturtle3d.js.LICENSE.txt +0 -3
  132. package/release/src/plugin_caniuse.js +0 -2
  133. package/release/src/plugin_caniuse.js.map +0 -7
  134. package/release/src/plugin_datetime.js +0 -2
  135. package/release/src/plugin_datetime.js.map +0 -7
  136. package/release/src/plugin_kansuji.js +0 -2
  137. package/release/src/plugin_kansuji.js.map +0 -7
  138. package/release/src/plugin_keigo.js +0 -2
  139. package/release/src/plugin_keigo.js.map +0 -7
  140. package/release/src/plugin_markup.js +0 -64
  141. package/release/src/plugin_markup.js.map +0 -7
  142. package/release/src/plugin_three.js +0 -2
  143. package/release/src/plugin_three.js.map +0 -7
  144. package/release/src/plugin_turtle.js +0 -2
  145. package/release/src/plugin_turtle.js.map +0 -7
  146. package/release/src/plugin_webworker.js +0 -4
  147. package/release/src/plugin_webworker.js.map +0 -7
  148. package/release/src/plugin_weykturtle3d.js +0 -2
  149. package/release/src/plugin_weykturtle3d.js.map +0 -7
  150. package/release/src/wnako3.js +0 -482
  151. package/release/src/wnako3.js.map +0 -7
  152. package/release/src/wnako3webworker.js +0 -428
  153. package/release/src/wnako3webworker.js.map +0 -7
  154. package/release/stats.json +0 -1
  155. package/release/version.js.LICENSE.txt +0 -65
  156. package/release/version.js.map +0 -1
  157. package/release/wnako3.js.LICENSE.txt +0 -341
  158. package/release/wnako3webworker.js.LICENSE.txt +0 -209
  159. package/src/plugin_three.mts +0 -240
@@ -53,7 +53,7 @@ export default {
53
53
  // 名前空間を参照して関数・変数名を解決する
54
54
  const modList = system.__modList ? system.__modList : [system.__modName]
55
55
  for (const modName of modList) {
56
- const gname = modName + '__' + nameStr
56
+ const gname = `${modName}__${nameStr}`
57
57
  for (let i = 2; i >= 0; i--) {
58
58
  const scope = system.__varslist[i]
59
59
  const scopeValue = scope.get(gname)
@@ -83,7 +83,7 @@ export default {
83
83
  sys.__interval = []
84
84
  // 日付処理などに使う
85
85
  const z2 = sys.__zero2 = (s: string|number): string => {
86
- s = '00' + s
86
+ s = '00' + String(s)
87
87
  return s.substring(s.length - 2)
88
88
  }
89
89
  sys.__zero = (s: string, keta: number): string => {
@@ -93,13 +93,13 @@ export default {
93
93
  return s.substring(s.length - keta)
94
94
  }
95
95
  sys.__formatDate = (t: Date): string => {
96
- return t.getFullYear() + '/' + z2(t.getMonth() + 1) + '/' + z2(t.getDate())
96
+ return String(t.getFullYear()) + '/' + z2(t.getMonth() + 1) + '/' + z2(t.getDate())
97
97
  }
98
98
  sys.__formatTime = (t: Date): string => {
99
99
  return z2(t.getHours()) + ':' + z2(t.getSeconds()) + ':' + z2(t.getMinutes())
100
100
  }
101
101
  sys.__formatDateTime = (t: Date, fmt: string): string => {
102
- const dateStr = t.getFullYear() + '/' + z2(t.getMonth() + 1) + '/' + z2(t.getDate())
102
+ const dateStr = String(t.getFullYear()) + '/' + z2(t.getMonth() + 1) + '/' + z2(t.getDate())
103
103
  const timeStr = z2(t.getHours()) + ':' + z2(t.getMinutes()) + ':' + z2(t.getSeconds())
104
104
  if (fmt.match(/^\d+\/\d+\/\d+\s+\d+:\d+:\d+$/)) {
105
105
  return dateStr + ' ' + timeStr
@@ -159,6 +159,7 @@ export default {
159
159
  sys.__evalSafe = (src: string) => {
160
160
  // evalのスコープを変えるためのテクニック
161
161
  // https://esbuild.github.io/content-types/#direct-eval
162
+ // eslint-disable-next-line no-eval
162
163
  const _eval = eval
163
164
  try {
164
165
  return _eval(src)
@@ -171,6 +172,7 @@ export default {
171
172
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
172
173
  sys.__evalJS = (src: string, sys?: NakoSystem) => {
173
174
  try {
175
+ // eslint-disable-next-line no-eval
174
176
  return eval(src)
175
177
  } catch (e) {
176
178
  console.warn('[eval]', e)
@@ -178,7 +180,7 @@ export default {
178
180
  }
179
181
  }
180
182
  // Propアクセス支援
181
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
183
+ // eslint-disable-next-line @typescript-eslint/ban-types
182
184
  sys.__registPropAccessor = (f: Function, getProp: (prop: string|string[], sys: NakoSystem) => any, setProp: (prop: string|string[], value: object, sys: NakoSystem) => any) => {
183
185
  system.__propAccessor.push(
184
186
  {
@@ -306,10 +308,10 @@ export default {
306
308
  pure: true,
307
309
  fn: function (s: string, sys: any) {
308
310
  // 継続表示の一時プールを出力
309
- s = sys.__printPool + s
311
+ s = String(sys.__printPool) + s
310
312
  sys.__printPool = ''
311
313
  //
312
- sys.__setSysVar('表示ログ', sys.__getSysVar('表示ログ') + s + '\n')
314
+ sys.__setSysVar('表示ログ', String(sys.__getSysVar('表示ログ')) + s + '\n')
313
315
  sys.logger.send('stdout', s + '')
314
316
  },
315
317
  return_none: true
@@ -377,13 +379,45 @@ export default {
377
379
  },
378
380
 
379
381
  // @四則演算
380
- '足': { // @AとBを足す // @たす
382
+ '足': { // @AとBを足す(算術演算を行う) // @たす
381
383
  type: 'func',
382
384
  josi: [['に', 'と'], ['を']],
383
385
  isVariableJosi: false,
384
386
  pure: true,
385
387
  fn: function (a: any, b: any) {
386
- return a + b
388
+ if (typeof (a) === 'bigint' || typeof (b) === 'bigint') {
389
+ return BigInt(a) + BigInt(b)
390
+ }
391
+ return parseFloat(a) + parseFloat(b)
392
+ }
393
+ },
394
+ '合計': { // @引数(可変)に指定した値を全て合計して返す // @ごうけい
395
+ type: 'func',
396
+ josi: [['と', 'を', 'の']],
397
+ isVariableJosi: true,
398
+ pure: true,
399
+ fn: function (...a: any) {
400
+ const sys = a.pop() // remove NakoSystem
401
+ if (a.length >= 1 && a[0] instanceof Array) {
402
+ return sys.__exec('配列合計', [a[0], sys])
403
+ }
404
+ let isBigInt = false
405
+ let sum = 0
406
+ for (const v of a) {
407
+ if (typeof (v) === 'bigint') {
408
+ isBigInt = true
409
+ break
410
+ }
411
+ sum += parseFloat(v)
412
+ }
413
+ if (isBigInt) {
414
+ let bigsum = 0n
415
+ for (const v of a) {
416
+ bigsum += BigInt(v)
417
+ }
418
+ return bigsum
419
+ }
420
+ return sum
387
421
  }
388
422
  },
389
423
  '引': { // @AからBを引く // @ひく
@@ -581,6 +615,7 @@ export default {
581
615
  fn: function (b: any, ...a: any) {
582
616
  a.pop() // 必ず末尾に sys があるので、末尾のシステム変数を除外
583
617
  a.push(b)
618
+ // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
584
619
  return a.reduce((p: any, c: any) => p + c)
585
620
  }
586
621
  },
@@ -616,7 +651,7 @@ export default {
616
651
  }
617
652
  },
618
653
  '最小値': { // @2個以上の数値のうち最小値を返す。// @さいしょうち
619
- type: 'func',
654
+ type: 'func',
620
655
  josi: [['の'], ['と']],
621
656
  isVariableJosi: true,
622
657
  pure: true,
@@ -780,7 +815,7 @@ export default {
780
815
  fn: function (code: string, sys: any) {
781
816
  sys.__setSysVar('表示ログ', '')
782
817
  sys.__self.runEx(code, sys.__modName, { resetEnv: false, resetLog: true })
783
- const outLog = sys.__getSysVar('表示ログ') + ''
818
+ const outLog = String(sys.__getSysVar('表示ログ'))
784
819
  if (outLog) {
785
820
  sys.logger.trace(outLog)
786
821
  }
@@ -792,7 +827,7 @@ export default {
792
827
  josi: [['を', 'で']],
793
828
  fn: function (code: string, sys: any) {
794
829
  sys.__self.runEx(code, sys.__modName, { resetEnv: false, resetAll: false })
795
- const out = sys.__getSysVar('表示ログ') + ''
830
+ const out = String(sys.__getSysVar('表示ログ'))
796
831
  if (out) {
797
832
  sys.logger.trace(out)
798
833
  }
@@ -986,7 +1021,7 @@ export default {
986
1021
  pure: true,
987
1022
  fn: function (r: any, g: any, b: any): string {
988
1023
  const z2 = (v: any): string => {
989
- const v2: string = '00' + (parseInt('' + v).toString(16))
1024
+ const v2: string = '00' + (parseInt(String(v)).toString(16))
990
1025
  return v2.substring(v2.length - 2, v2.length)
991
1026
  }
992
1027
  return '#' + z2(r) + z2(g) + z2(b)
@@ -1015,7 +1050,7 @@ export default {
1015
1050
  josi: [['の']],
1016
1051
  pure: true,
1017
1052
  fn: function (v: any): boolean {
1018
- return (!v) ? true : false
1053
+ return (!v)
1019
1054
  }
1020
1055
  },
1021
1056
 
@@ -1148,7 +1183,7 @@ export default {
1148
1183
  fn: function (s: string, i: number, a: string): string {
1149
1184
  if (i <= 0) { i = 1 }
1150
1185
  const strArray = Array.from(s)
1151
- strArray.splice(i-1, 0, a)
1186
+ strArray.splice(i - 1, 0, a)
1152
1187
  return strArray.join('')
1153
1188
  }
1154
1189
  },
@@ -1204,7 +1239,17 @@ export default {
1204
1239
  fn: function (...a: any) {
1205
1240
  a.pop() // NakoSystemを取り除く
1206
1241
  return a.join('')
1207
- },
1242
+ }
1243
+ },
1244
+ '文字列連結': { // @引数(可変)に指定した文字列を連結して文字列を返す // @もじれつれんけつ
1245
+ type: 'func',
1246
+ josi: [['と', 'を']],
1247
+ pure: true,
1248
+ isVariableJosi: true,
1249
+ fn: function (...a: any) {
1250
+ a.pop() // NakoSystemを取り除く
1251
+ return a.join('')
1252
+ }
1208
1253
  },
1209
1254
  '文字列分解': { // @文字列Vを一文字ずつに分解して返す // @もじれつぶんかい
1210
1255
  type: 'func',
@@ -1247,7 +1292,7 @@ export default {
1247
1292
  type: 'func',
1248
1293
  josi: [['で', 'の'], ['から'], ['を', '']],
1249
1294
  pure: true,
1250
- fn: function (s: any, a: any, cnt: number) {
1295
+ fn: function (s: any, a: number, cnt: number) {
1251
1296
  cnt = cnt || 1
1252
1297
  // return (String(s).substring(a - 1, a + cnt - 1))
1253
1298
  // サロゲートペアを考慮
@@ -1290,7 +1335,9 @@ export default {
1290
1335
  // return (s.substring(s.length - cnt, s.length))
1291
1336
  // サロゲートペアを考慮
1292
1337
  const strArray = Array.from(s)
1293
- return strArray.slice(strArray.length - cnt, strArray.length).join('')
1338
+ let index = strArray.length - cnt
1339
+ if (index < 0) { index = 0 }
1340
+ return strArray.slice(index, strArray.length).join('')
1294
1341
  }
1295
1342
  },
1296
1343
  '区切': { // @文字列Sを区切り文字Aで区切って配列で返す // @くぎる
@@ -1450,7 +1497,7 @@ export default {
1450
1497
  pure: true,
1451
1498
  fn: function (s: string): string {
1452
1499
  const kanaToHira = (str: string) => {
1453
- return String(str).replace(/[\u30a1-\u30f6]/g, function (m) {
1500
+ return String(str).replace(/[\u30a1-\u30f6]/g, function (m: string) {
1454
1501
  const chr = m.charCodeAt(0) - 0x60
1455
1502
  return String.fromCharCode(chr)
1456
1503
  })
@@ -1464,7 +1511,7 @@ export default {
1464
1511
  pure: true,
1465
1512
  fn: function (s: string): string {
1466
1513
  const hiraToKana = (str: string) => {
1467
- return String(str).replace(/[\u3041-\u3096]/g, function (m) {
1514
+ return String(str).replace(/[\u3041-\u3096]/g, function (m: string) {
1468
1515
  const chr = m.charCodeAt(0) + 0x60
1469
1516
  return String.fromCharCode(chr)
1470
1517
  })
@@ -1477,7 +1524,7 @@ export default {
1477
1524
  josi: [['の', 'を']],
1478
1525
  pure: true,
1479
1526
  fn: function (s: string): string {
1480
- return String(s).replace(/[A-Za-z0-9]/g, function (v: any) {
1527
+ return String(s).replace(/[A-Za-z0-9]/g, function (v: string) {
1481
1528
  return String.fromCharCode(v.charCodeAt(0) + 0xFEE0)
1482
1529
  })
1483
1530
  }
@@ -1487,7 +1534,7 @@ export default {
1487
1534
  josi: [['の', 'を']],
1488
1535
  pure: true,
1489
1536
  fn: function (s: string): string {
1490
- return String(s).replace(/[A-Za-z0-9]/g, function (v: any) {
1537
+ return String(s).replace(/[A-Za-z0-9]/g, function (v: string) {
1491
1538
  return String.fromCharCode(v.charCodeAt(0) - 0xFEE0)
1492
1539
  })
1493
1540
  }
@@ -1497,7 +1544,8 @@ export default {
1497
1544
  josi: [['の', 'を']],
1498
1545
  pure: true,
1499
1546
  fn: function (s: string): string {
1500
- return String(s).replace(/[\x20-\x7F]/g, function (v: any) {
1547
+ return String(s).replace(/[\x20-\x7E]/g, function (v: string) {
1548
+ if (v === ' ') { return ' ' } // 半角スペース(0x20)を全角スペース(U+3000)に
1501
1549
  return String.fromCharCode(v.charCodeAt(0) + 0xFEE0)
1502
1550
  })
1503
1551
  }
@@ -1507,7 +1555,8 @@ export default {
1507
1555
  josi: [['の', 'を']],
1508
1556
  pure: true,
1509
1557
  fn: function (s: string): string {
1510
- return String(s).replace(/[\uFF00-\uFF5F]/g, function (v: any) {
1558
+ return String(s).replace(/[\u3000\uFF00-\uFF5F]/g, function (v: string) {
1559
+ if (v === ' ') { return ' ' } // 全角スペース(U+3000)を半角スペース(U+0020)
1511
1560
  return String.fromCharCode(v.charCodeAt(0) - 0xFEE0)
1512
1561
  })
1513
1562
  }
@@ -1652,7 +1701,7 @@ export default {
1652
1701
  type: 'func',
1653
1702
  josi: [['を', 'が'], ['で', 'に']],
1654
1703
  pure: true,
1655
- fn: function (a: any, b: any, sys: any): string {
1704
+ fn: function (a: string, b: string, sys: any): string {
1656
1705
  let re
1657
1706
  const f = ('' + b).match(/^\/(.+)\/([a-zA-Z]*)$/)
1658
1707
  // パターンがない場合
@@ -1849,7 +1898,7 @@ export default {
1849
1898
  type: 'func',
1850
1899
  josi: [['の'], ['に', 'へ'], ['を']],
1851
1900
  pure: true,
1852
- fn: function (a: any, i: any, b: any) {
1901
+ fn: function (a: any, i: number, b: any) {
1853
1902
  if (a instanceof Array && b instanceof Array) { // 配列ならOK
1854
1903
  for (let j = 0; j < b.length; j++) { a.splice(i + j, 0, b[j]) }
1855
1904
 
@@ -2025,7 +2074,7 @@ export default {
2025
2074
  },
2026
2075
  '配列範囲コピー': { // @配列Aの範囲I(数値化範囲オブジェクト)を複製して返す。 // @はいれつはんいこぴー
2027
2076
  type: 'func',
2028
- josi: [['の','から'],['を']],
2077
+ josi: [['の', 'から'], ['を']],
2029
2078
  pure: true,
2030
2079
  fn: function (a: any, i: any) {
2031
2080
  if (!Array.isArray(a)) {
@@ -2040,7 +2089,7 @@ export default {
2040
2089
  // 範囲オブジェクトのとき
2041
2090
  if (typeof i === 'object' && typeof i['先頭'] === 'number') {
2042
2091
  const start = i['先頭']
2043
- const last = i['末尾'] + 1
2092
+ const last = Number(i['末尾']) + 1
2044
2093
  return JSON.parse(JSON.stringify(a.slice(start, last)))
2045
2094
  }
2046
2095
  return undefined
@@ -2060,7 +2109,7 @@ export default {
2060
2109
  // 範囲オブジェクトのとき
2061
2110
  if (typeof i === 'object' && typeof i['先頭'] === 'number') {
2062
2111
  const start = i['先頭']
2063
- const last = i['末尾'] + 1
2112
+ const last = Number(i['末尾']) + 1
2064
2113
  return a.substring(start, last)
2065
2114
  }
2066
2115
  throw new Error(`『参照』で文字列型の範囲指定(${JSON.stringify(i)})が不正です。`)
@@ -2073,7 +2122,7 @@ export default {
2073
2122
  // 範囲オブジェクトのとき
2074
2123
  if (typeof i === 'object' && typeof i['先頭'] === 'number') {
2075
2124
  const start = i['先頭']
2076
- const last = i['末尾'] + 1
2125
+ const last = Number(i['末尾']) + 1
2077
2126
  return a.slice(start, last)
2078
2127
  }
2079
2128
  }
@@ -2162,16 +2211,42 @@ export default {
2162
2211
  return result
2163
2212
  }
2164
2213
  },
2165
- '配列要素作成': { // @値AをB個持つ配列を生成して返す。 // @はいれつようそさくせい
2214
+ '配列要素作成': { // @値AをB個持つ配列を生成して返す。引数Bに配列を指定すると二次元以上の配列を生成する。// @はいれつようそさくせい
2166
2215
  type: 'func',
2167
- josi: [['を'], ['だけ']],
2216
+ josi: [['を'], ['だけ', 'で']],
2168
2217
  pure: true,
2169
- fn: function (a: number, b: number) {
2170
- const result: number[] = []
2171
- for (let i = 0; i < b; i++) {
2172
- result.push(a)
2218
+ fn: function (a: any, b: number | number[]) {
2219
+ // value が配列やオブジェクトでも深くコピーするヘルパー
2220
+ const cloneValue = (v: any): any => {
2221
+ if (Array.isArray(v)) {
2222
+ return (v).map(item => cloneValue(item)) as any
2223
+ }
2224
+ if (v instanceof Date) {
2225
+ return new Date(v.getTime())
2226
+ }
2227
+ if (typeof v === 'object' && v !== null) {
2228
+ return JSON.parse(JSON.stringify(v))
2229
+ }
2230
+ return v
2173
2231
  }
2174
- return result
2232
+ // 再帰的に配列を生成する関数
2233
+ const full = function (value: any, shape: number | number[]): any {
2234
+ // 1次元:shape が数値
2235
+ if (!Array.isArray(shape)) {
2236
+ return Array.from({ length: shape }, () => cloneValue(value))
2237
+ }
2238
+ // 1次元:shape が数値
2239
+ if (Array.isArray(shape) && shape.length === 1) {
2240
+ return Array.from({ length: shape[0] }, () => cloneValue(value))
2241
+ }
2242
+ // 多次元:shape が配列
2243
+ const [first, ...rest] = shape
2244
+ return Array.from(
2245
+ { length: first },
2246
+ () => full(cloneValue(value), rest)
2247
+ )
2248
+ }
2249
+ return full(a, b)
2175
2250
  }
2176
2251
  },
2177
2252
  '配列関数適用': { // @引数を1つ持つ関数Fを、配列Aの全要素に適用した、新しい配列を返す。 // @はいれつかんすうてきよう
@@ -2664,9 +2739,9 @@ export default {
2664
2739
  josi: [],
2665
2740
  pure: true,
2666
2741
  fn: function () {
2667
- const z2 = (n: any) => {
2668
- n = '00' + n
2669
- return n.substring(n.length - 2, n.length)
2742
+ const z2 = (n: number): string => {
2743
+ const ns = '00' + String(n)
2744
+ return ns.substring(ns.length - 2, ns.length)
2670
2745
  }
2671
2746
  const t = new Date()
2672
2747
  return z2(t.getHours()) + ':' + z2(t.getMinutes()) + ':' + z2(t.getSeconds())
@@ -2819,10 +2894,10 @@ export default {
2819
2894
  fmt = fmt.replace(/(YYYY|ccc|WWW|MMM|YY|MM|DD|HH|mm|ss|[MDHmsW])/g, (m: string) => {
2820
2895
  switch (m) {
2821
2896
  case 'YYYY': return t.getFullYear()
2822
- case 'YY': return ('' + t.getFullYear()).substring(2)
2823
- case 'MM': return sys.__zero2(t.getMonth() + 1)
2897
+ case 'YY': return (String(t.getFullYear())).substring(2)
2898
+ case 'MM': return sys.__zero2(String(t.getMonth() as number + 1))
2824
2899
  case 'DD': return sys.__zero2(t.getDate())
2825
- case 'M': return (t.getMonth() + 1)
2900
+ case 'M': return (t.getMonth() as number + 1)
2826
2901
  case 'D': return (t.getDate())
2827
2902
  case 'HH': return sys.__zero2(t.getHours())
2828
2903
  case 'mm': return sys.__zero2(t.getMinutes())
@@ -2844,17 +2919,17 @@ export default {
2844
2919
  type: 'func',
2845
2920
  josi: [['を']],
2846
2921
  pure: true,
2847
- fn: function (s: string, sys: any) {
2922
+ fn: function (s: string, sys: NakoSystem) {
2848
2923
  const d = sys.__str2date(s)
2849
2924
  const t = d.getTime()
2850
2925
  for (const era of sys.__getSysVar('元号データ')) {
2851
- const gengo = era['元号']
2926
+ const gengo = String(era['元号'])
2852
2927
  const d2 = sys.__str2date(era['改元日'])
2853
2928
  const t2 = d2.getTime()
2854
2929
  if (t2 <= t) {
2855
2930
  let y: any = (d.getFullYear() - d2.getFullYear()) + 1
2856
2931
  if (y === 1) { y = '元' }
2857
- return gengo + y + '年' + sys.__zero2(d.getMonth() + 1) + '月' + sys.__zero2(d.getDate()) + '日'
2932
+ return gengo + String(y) + '年' + sys.__zero2(d.getMonth() + 1) + '月' + sys.__zero2(d.getDate()) + '日'
2858
2933
  }
2859
2934
  }
2860
2935
  throw new Error('『和暦変換』は明示以前の日付には対応していません。')
@@ -2877,8 +2952,8 @@ export default {
2877
2952
  fn: function (a: any, b: any, sys: any) {
2878
2953
  const t1 = sys.__str2date(a)
2879
2954
  const t2 = sys.__str2date(b)
2880
- return ((t2.getFullYear() * 12 + t2.getMonth()) -
2881
- (t1.getFullYear() * 12 + t1.getMonth()))
2955
+ return (t2.getFullYear() * 12 + Number(t2.getMonth())) -
2956
+ (t1.getFullYear() * 12 + Number(t1.getMonth()))
2882
2957
  }
2883
2958
  },
2884
2959
  '日数差': { // @日付AとBの差を日数で求めて返す。A<Bなら正の数、そうでないなら負の数を返す。 // @にっすうさ
@@ -2945,7 +3020,7 @@ export default {
2945
3020
  type: 'func',
2946
3021
  josi: [['に'], ['を']],
2947
3022
  pure: true,
2948
- fn: function (s: any, a: any, sys: any) {
3023
+ fn: function (s: string, a: string, sys: any) {
2949
3024
  const op = a.charAt(0)
2950
3025
  if (op === '-' || op === '+') {
2951
3026
  a = a.substring(1)
@@ -2956,7 +3031,7 @@ export default {
2956
3031
  parseInt(aa[1]) * 60 +
2957
3032
  parseInt(aa[2])
2958
3033
  if (op === '-') { sec *= -1 }
2959
- const rd = new Date(d.getTime() + (sec * 1000))
3034
+ const rd = new Date(Number(d.getTime()) + (sec * 1000))
2960
3035
  return sys.__formatDateTime(rd, s)
2961
3036
  }
2962
3037
  },
@@ -2964,7 +3039,7 @@ export default {
2964
3039
  type: 'func',
2965
3040
  josi: [['に'], ['を']],
2966
3041
  pure: true,
2967
- fn: function (s: any, a: any, sys: any) {
3042
+ fn: function (s: string, a: string, sys: any) {
2968
3043
  let op = 1
2969
3044
  const opc = a.charAt(0)
2970
3045
  if (opc === '-' || opc === '+') {
@@ -2976,9 +3051,9 @@ export default {
2976
3051
  const addY = parseInt(aa[0]) * op
2977
3052
  const addM = parseInt(aa[1]) * op
2978
3053
  const addD = parseInt(aa[2]) * op
2979
- d.setFullYear(d.getFullYear() + addY)
2980
- d.setMonth(d.getMonth() + addM)
2981
- d.setDate(d.getDate() + addD)
3054
+ d.setFullYear(Number(d.getFullYear()) + addY)
3055
+ d.setMonth(Number(d.getMonth()) + addM)
3056
+ d.setDate(Number(d.getDate()) + addD)
2982
3057
  return sys.__formatDateTime(d, s)
2983
3058
  }
2984
3059
  },
@@ -2986,7 +3061,7 @@ export default {
2986
3061
  type: 'func',
2987
3062
  josi: [['に'], ['を']],
2988
3063
  pure: true,
2989
- fn: function (s: any, a: any, sys: any) {
3064
+ fn: function (s: string, a: string, sys: any) {
2990
3065
  const r = ('' + a).match(/([+|-]?)(\d+)(年|ヶ月|日|週間|時間|分|秒)$/)
2991
3066
  if (!r) { throw new Error('『日付加算』は『(+|-)1(年|ヶ月|日|時間|分|秒)』の書式で指定します。') }
2992
3067
  switch (r[3]) {
@@ -3022,12 +3097,12 @@ export default {
3022
3097
  pure: true,
3023
3098
  fn: function (s: any, sys: NakoSystem) {
3024
3099
  // 行番号の情報を得る
3025
- const lineInfo: string = sys.__getSysVar('__line', 0) + '::'
3100
+ const lineInfo: string = String(sys.__getSysVar('__line', 0)) + '::'
3026
3101
  const a = lineInfo.split(':', 2)
3027
3102
  const no = parseInt(String(a[0]).replace('l', '')) + 1
3028
3103
  const fname = a[1]
3029
3104
  // オブジェクトならJSON文字列に変換
3030
- if (typeof s == 'object') {
3105
+ if (typeof s === 'object') {
3031
3106
  s = JSON.stringify(s)
3032
3107
  }
3033
3108
  s = `${fname}(${no}): ${s}`
@@ -3062,7 +3137,6 @@ export default {
3062
3137
  for (const f of fa) {
3063
3138
  param = f(param, sys)
3064
3139
  }
3065
- return
3066
3140
  }
3067
3141
  return
3068
3142
  }
@@ -28,7 +28,7 @@ export default {
28
28
  pure: true,
29
29
  fn: function (a, b) {
30
30
  if (a !== b) {
31
- throw new Error(`不一致 [実際]${a} [期待]${b}`);
31
+ throw new Error(`不一致 [実際]${JSON.stringify(a)} [期待]${JSON.stringify(b)}`);
32
32
  }
33
33
  return true;
34
34
  }
@@ -38,6 +38,7 @@ export default {
38
38
  josi: [['と'], ['で']],
39
39
  pure: false,
40
40
  fn: function (a, b, sys) {
41
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
41
42
  sys.__exec('ASSERT等', [a, b, sys]);
42
43
  }
43
44
  },
@@ -46,6 +47,7 @@ export default {
46
47
  josi: [['と'], ['が']],
47
48
  pure: false,
48
49
  fn: function (a, b, sys) {
50
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
49
51
  sys.__exec('ASSERT等', [a, b, sys]);
50
52
  }
51
53
  }
@@ -31,7 +31,7 @@ export default {
31
31
  pure: true,
32
32
  fn: function (a: any, b: any): boolean {
33
33
  if (a !== b) {
34
- throw new Error(`不一致 [実際]${a} [期待]${b}`)
34
+ throw new Error(`不一致 [実際]${JSON.stringify(a)} [期待]${JSON.stringify(b)}`)
35
35
  }
36
36
  return true
37
37
  }
@@ -41,6 +41,7 @@ export default {
41
41
  josi: [['と'], ['で']],
42
42
  pure: false,
43
43
  fn: function (a: any, b: any, sys: NakoSystem) {
44
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
44
45
  sys.__exec('ASSERT等', [a, b, sys])
45
46
  }
46
47
  },
@@ -49,6 +50,7 @@ export default {
49
50
  josi: [['と'], ['が']],
50
51
  pure: false,
51
52
  fn: function (a: any, b: any, sys: NakoSystem) {
53
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
52
54
  sys.__exec('ASSERT等', [a, b, sys])
53
55
  }
54
56
  }
@@ -328,10 +328,22 @@ describe('basic', async () => {
328
328
  await cmp('変数[A,B]=[1];Aを表示;Bを表示;', '1\nundefined')
329
329
  await cmp('変数[A,B,C,D]=[1,2,3,4];Dを表示;', '4')
330
330
  })
331
+ it('定数複数代入', async () => {
332
+ await cmp('定数[A,B] = [1,2]; 「{A}:{B}」を表示', '1:2')
333
+ await cmp('定数[A,B,C] = [1,2,3]; 「{A}:{B}:{C}」を表示', '1:2:3')
334
+ await cmp('定数[A,B,C,D] = [1,2,3,4,5]; 「{A}:{B}:{C}:{D}」を表示', '1:2:3:4')
335
+ await cmp('定数[A,B,C,D,E] = [1,2,3,4,5]; 「{A}:{B}:{C}:{D}:{E}」を表示', '1:2:3:4:5')
336
+ })
331
337
  it('複数代入文の問題 #1027', async () => {
332
338
  await cmp('塊=[[0,0],[1,1]];塊を反復\nx,y=対象;💧;塊をJSONエンコードして表示。', '[[0,0],[1,1]]')
333
339
  await cmp('x=1;y=2;x,y=[y,x];xを表示', '2')
334
340
  })
341
+ it('変数の複数代入', async () => {
342
+ await cmp('A,B = [1,2]; 「{A}:{B}」を表示', '1:2')
343
+ await cmp('A,B,C = [1,2,3]; 「{A}:{B}:{C}」を表示', '1:2:3')
344
+ await cmp('A,B,C,D = [1,2,3,4,5]; 「{A}:{B}:{C}:{D}」を表示', '1:2:3:4')
345
+ await cmp('A,B,C,D,E = [1,2,3,4,5]; 「{A}:{B}:{C}:{D}:{E}」を表示', '1:2:3:4:5')
346
+ })
335
347
  it('もし文で「ならば」の前の空行でエラー #1079', async () => {
336
348
  await cmp('A=5;もし、A > 3 ならば「OK」と表示;', 'OK')
337
349
  })
@@ -411,4 +423,8 @@ describe('basic', async () => {
411
423
  await cmp('《リンゴの値段》=500;《リンゴの値段》を表示', '500') // #672 大なり記号ではなく、二重カッコであることに注意
412
424
  await cmp('${リンゴの値段}=500;${リンゴの値段}を表示', '500') // #1836
413
425
  })
426
+ it('特別名前トークンのテスト #672 #1836', async () => {
427
+ await cmp('《リンゴの値段》=500;《リンゴの値段》を表示', '500') // #672 大なり記号ではなく、二重カッコであることに注意
428
+ await cmp('${リンゴの値段}=500;${リンゴの値段}を表示', '500') // #1836
429
+ })
414
430
  })
@@ -287,4 +287,11 @@ describe('calc_test.js', async () => {
287
287
  await cmp('N="2";Nを1減らす。Nを表示。', '1')
288
288
  await cmp('N="2";Nを"1"減らす。Nを表示。', '1')
289
289
  })
290
+
291
+ it('文字列を「足す」命令に与えた時、算術演算する #1958', async () => {
292
+ await cmp('"1"に"3"を足して表示。', '4')
293
+ await cmp('1に"3"を足して表示', '4')
294
+ await cmp('"1"に3を足して表示', '4')
295
+ await cmp('1nに3nを足して表示', '4')
296
+ })
290
297
  })
@@ -777,5 +777,38 @@ describe('plugin_system_test', async () => {
777
777
  await cmp('「A」と「B」と「C」と「D」を連結して表示', 'ABCD')
778
778
  await cmp('「A」と「B」を連結して表示', 'AB')
779
779
  await cmp('「A」を連結して表示', 'A')
780
+ await cmp('「A」と「B」と「C」と「D」を文字列連結して表示', 'ABCD')
781
+ })
782
+ it('文字右部分で元の文字列の長さを超える場合の処理がおかしい #1975', async () => {
783
+ await cmp('「12345」の0文字右部分を表示', '')
784
+ await cmp('「12345」の1文字右部分を表示', '5')
785
+ await cmp('「12345」の3文字右部分を表示', '345')
786
+ await cmp('「12345」の6文字右部分を表示', '12345')
787
+ })
788
+ it('関数「合計」を追加 #1991', async () => {
789
+ await cmp('1と2と3を合計して表示', '6')
790
+ await cmp('1と2と3の合計を表示', '6')
791
+ await cmp('[4,5,6]の合計を表示', '15')
792
+ })
793
+ it('半角スペースを全角変換すると＀になる #1999', async () => {
794
+ await cmp('「あ う」を全角変換して表示', 'あ う')
795
+ await cmp('「あ う」を英数記号半角変換して表示', 'あ う')
796
+ await cmp('「ABC 123 !@#」を全角変換して表示', 'ABC 123 !@#')
797
+ await cmp('「ABC 123 !@#」を英数記号半角変換して表示', 'ABC 123 !@#')
798
+ })
799
+ it('「配列要素作成」で引数に配列を取れるように #2013', async () => {
800
+ // 数値指定
801
+ await cmp('0を2だけ配列要素作成してJSONエンコードして表示', '[0,0]')
802
+ await cmp('3を3だけ配列要素作成してJSONエンコードして表示', '[3,3,3]')
803
+ // 1次元指定
804
+ await cmp('0を[2]だけ配列要素作成してJSONエンコードして表示', '[0,0]')
805
+ // 2次元指定
806
+ await cmp('0を[1,2]だけ配列要素作成してJSONエンコードして表示', '[[0,0]]')
807
+ await cmp('0を[1,3]だけ配列要素作成してJSONエンコードして表示', '[[0,0,0]]')
808
+ await cmp('0を[2,2]だけ配列要素作成してJSONエンコードして表示', '[[0,0],[0,0]]')
809
+ // 3次元指定
810
+ await cmp('0を[2,2,2]だけ配列要素作成してJSONエンコードして表示', '[[[0,0],[0,0]],[[0,0],[0,0]]]')
811
+ // オブジェクト指定
812
+ await cmp('[1,2,3]を[2,2]だけ配列要素作成してJSONエンコードして表示', '[[[1,2,3],[1,2,3]],[[1,2,3],[1,2,3]]]')
780
813
  })
781
814
  })
package/doc/files.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # なでしこを構成するファイルたち
2
2
 
3
- ## src/nako3.mjs
3
+ ## core/src/nako3.mjs
4
4
 
5
5
  なでしこコンパイラ本体。なでしこのソースコードをJSに変換する。変換処理は、次のように行われる。
6
6
 
@@ -9,15 +9,15 @@
9
9
  - (3) 構文木(中間表現)
10
10
  - (3) JavaScriptソース
11
11
 
12
- ## src/nako_prepare.mjs
12
+ ## core/src/nako_prepare.mjs
13
13
 
14
14
  なでしこのソースコードの前置処理を行うもの。主に全角半角の変換処理を行う。
15
15
 
16
- ## src/nako_parser3.mjs
16
+ ## core/src/nako_parser3.mjs
17
17
 
18
18
  なでしこ構文から構文木を生成するもの。
19
19
 
20
- ## src/nako_gen.mjs
20
+ ## core/src/nako_gen.mjs
21
21
 
22
22
  構文木を元に、JavaScriptのコードを生成するもの。
23
23
 
package/doc/plugins.md CHANGED
@@ -207,7 +207,7 @@ const value = sys.__getSysVar('変数名')
207
207
  sys.__setSysVar('変数名', value)
208
208
  ```
209
209
 
210
- なお、プラグインでは、次のメソッドが使えるようになる。(すべてsrc/plugin_system.jsで定義されている。システム関数の初期化時に、これらの関数が追加される)
210
+ なお、プラグインでは、次のメソッドが使えるようになる。(すべてcore/src/plugin_system.mjsで定義されている。システム関数の初期化時に、これらの関数が追加される)
211
211
 
212
212
  - sys.__findVar(name)
213
213
  - sys.__exec(name, params)