nadesiko3 3.2.37 → 3.2.41

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 (52) hide show
  1. package/README.md +14 -12
  2. package/demo/browsers.html +10 -10
  3. package/doc/SETUP.md +7 -21
  4. package/doc/browsers.md +10 -10
  5. package/package.json +4 -6
  6. package/release/_hash.txt +52 -52
  7. package/release/_script-tags.txt +13 -13
  8. package/release/command.json +1 -1
  9. package/release/command.json.js +1 -1
  10. package/release/command_cnako3.json +1 -1
  11. package/release/command_list.json +1 -1
  12. package/release/editor.js +1 -1
  13. package/release/nako_gen_async.js +1 -1
  14. package/release/nako_gen_async.js.LICENSE.txt +12 -0
  15. package/release/plugin_caniuse.js +1 -1
  16. package/release/plugin_caniuse.js.LICENSE.txt +16 -0
  17. package/release/plugin_csv.js +1 -1
  18. package/release/plugin_csv.js.LICENSE.txt +16 -0
  19. package/release/plugin_datetime.js +1 -1
  20. package/release/plugin_datetime.js.LICENSE.txt +12 -0
  21. package/release/plugin_kansuji.js +1 -1
  22. package/release/plugin_kansuji.js.LICENSE.txt +12 -0
  23. package/release/plugin_markup.js +1 -1
  24. package/release/plugin_markup.js.LICENSE.txt +16 -0
  25. package/release/plugin_turtle.js +1 -1
  26. package/release/plugin_turtle.js.LICENSE.txt +16 -0
  27. package/release/plugin_webworker.js +1 -1
  28. package/release/plugin_webworker.js.LICENSE.txt +16 -0
  29. package/release/stats.json +1 -1
  30. package/release/version.js +1 -1
  31. package/release/wnako3.js +1 -1
  32. package/release/wnako3webworker.js +1 -1
  33. package/release/wnako3webworker.js.LICENSE.txt +20 -0
  34. package/release/yoyakugo.json +1 -0
  35. package/src/browsers.json +1 -1
  36. package/src/browsers.txt +18 -19
  37. package/src/cnako3.js +0 -8
  38. package/src/nako_from_dncl.js +55 -18
  39. package/src/nako_gen.js +22 -2
  40. package/src/nako_gen_async.js +2 -1
  41. package/src/nako_lex_rules.js +4 -3
  42. package/src/nako_parser3.js +42 -2
  43. package/src/nako_parser_const.js +3 -1
  44. package/src/nako_reserved_words.js +1 -0
  45. package/src/nako_version.js +2 -2
  46. package/src/plugin_browser_dom_basic.js +18 -2
  47. package/src/plugin_browser_dom_parts.js +18 -0
  48. package/src/plugin_math.js +8 -0
  49. package/src/plugin_system.js +33 -0
  50. package/test/common/dncl_test.js +26 -0
  51. package/test/common/lex_test.js +3 -0
  52. package/test/common/plugin_system_test.js +4 -0
@@ -142,6 +142,10 @@
142
142
  !*** ./node_modules/core-js/internals/fails.js ***!
143
143
  \*************************************************/
144
144
 
145
+ /*!*************************************************!*\
146
+ !*** ./node_modules/core-js/internals/queue.js ***!
147
+ \*************************************************/
148
+
145
149
  /*!**************************************************!*\
146
150
  !*** ./node_modules/core-js/internals/export.js ***!
147
151
  \**************************************************/
@@ -706,6 +710,10 @@
706
710
  !*** ./node_modules/core-js/internals/add-to-unscopables.js ***!
707
711
  \**************************************************************/
708
712
 
713
+ /*!**************************************************************!*\
714
+ !*** ./node_modules/core-js/internals/array-slice-simple.js ***!
715
+ \**************************************************************/
716
+
709
717
  /*!**************************************************************!*\
710
718
  !*** ./node_modules/core-js/internals/host-report-errors.js ***!
711
719
  \**************************************************************/
@@ -802,6 +810,10 @@
802
810
  !*** ./node_modules/core-js/internals/engine-is-ios-pebble.js ***!
803
811
  \****************************************************************/
804
812
 
813
+ /*!****************************************************************!*\
814
+ !*** ./node_modules/core-js/internals/function-bind-native.js ***!
815
+ \****************************************************************/
816
+
805
817
  /*!****************************************************************!*\
806
818
  !*** ./node_modules/core-js/internals/length-of-array-like.js ***!
807
819
  \****************************************************************/
@@ -926,6 +938,10 @@
926
938
  !*** ./node_modules/core-js/internals/typed-array-constructor.js ***!
927
939
  \*******************************************************************/
928
940
 
941
+ /*!*******************************************************************!*\
942
+ !*** ./node_modules/core-js/internals/v8-prototype-define-bug.js ***!
943
+ \*******************************************************************/
944
+
929
945
  /*!*******************************************************************!*\
930
946
  !*** ./node_modules/core-js/modules/es.string.from-code-point.js ***!
931
947
  \*******************************************************************/
@@ -978,6 +994,10 @@
978
994
  !*** ./node_modules/core-js/internals/array-species-constructor.js ***!
979
995
  \*********************************************************************/
980
996
 
997
+ /*!*********************************************************************!*\
998
+ !*** ./node_modules/core-js/internals/validate-arguments-length.js ***!
999
+ \*********************************************************************/
1000
+
981
1001
  /*!*********************************************************************!*\
982
1002
  !*** ./node_modules/core-js/internals/well-known-symbol-wrapped.js ***!
983
1003
  \*********************************************************************/
@@ -6,6 +6,7 @@
6
6
  "繰返",
7
7
  "増繰返",
8
8
  "減繰返",
9
+ "後判定",
9
10
  "反復",
10
11
  "抜",
11
12
  "続",
package/src/browsers.json CHANGED
@@ -1 +1 @@
1
- {"and_chr":["95"],"and_ff":["92"],"and_qq":["10.4"],"and_uc":["12.12"],"android":["95"],"baidu":["7.12"],"chrome":["95","94","93","92"],"edge":["95","94"],"firefox":["94","93","92","91","78"],"ie":["11"],"ios_saf":["15","14.5-14.8","14.0-14.4","13.4-13.7","12.2-12.5"],"kaios":["2.5"],"node":["17.0.0","16.12.0","14.18.0","12.22.0"],"op_mini":["all"],"op_mob":["64"],"opera":["81","80","79"],"safari":["15","14.1","13.1"],"samsung":["15.0","14.0"]}
1
+ {"and_chr":["97"],"and_ff":["96"],"and_qq":["10.4"],"and_uc":["12.12"],"android":["97"],"baidu":["7.12"],"chrome":["98","97","96","93"],"edge":["98","97","96"],"firefox":["96","95","91","78"],"ie":["11"],"ios_saf":["15.2-15.3","15.0-15.1","14.5-14.8","14.0-14.4","12.2-12.5"],"kaios":["2.5"],"node":["17.0.0","16.12.0","14.18.0","12.22.0"],"op_mini":["all"],"op_mob":["64"],"opera":["83","82"],"safari":["15.2-15.3","15.1","14.1"],"samsung":["16.0","15.0"]}
package/src/browsers.txt CHANGED
@@ -1,25 +1,25 @@
1
- and_chr 95
2
- and_ff 92
1
+ and_chr 97
2
+ and_ff 96
3
3
  and_qq 10.4
4
4
  and_uc 12.12
5
- android 95
5
+ android 97
6
6
  baidu 7.12
7
- chrome 95
8
- chrome 94
7
+ chrome 98
8
+ chrome 97
9
+ chrome 96
9
10
  chrome 93
10
- chrome 92
11
- edge 95
12
- edge 94
13
- firefox 94
14
- firefox 93
15
- firefox 92
11
+ edge 98
12
+ edge 97
13
+ edge 96
14
+ firefox 96
15
+ firefox 95
16
16
  firefox 91
17
17
  firefox 78
18
18
  ie 11
19
- ios_saf 15
19
+ ios_saf 15.2-15.3
20
+ ios_saf 15.0-15.1
20
21
  ios_saf 14.5-14.8
21
22
  ios_saf 14.0-14.4
22
- ios_saf 13.4-13.7
23
23
  ios_saf 12.2-12.5
24
24
  kaios 2.5
25
25
  node 17.0.0
@@ -28,11 +28,10 @@ node 14.18.0
28
28
  node 12.22.0
29
29
  op_mini all
30
30
  op_mob 64
31
- opera 81
32
- opera 80
33
- opera 79
34
- safari 15
31
+ opera 83
32
+ opera 82
33
+ safari 15.2-15.3
34
+ safari 15.1
35
35
  safari 14.1
36
- safari 13.1
36
+ samsung 16.0
37
37
  samsung 15.0
38
- samsung 14.0
package/src/cnako3.js CHANGED
@@ -3,14 +3,6 @@
3
3
  /**
4
4
  * コマンドライン版のなでしこ3
5
5
  */
6
- const fetch = require('node-fetch')
7
- if (typeof globalThis !== 'undefined' && typeof globalThis.fetch === 'undefined') {
8
- globalThis.fetch = fetch
9
- } else
10
- if (typeof global !== 'undefined' && typeof global.fetch === 'undefined') {
11
- global.fetch = fetch
12
- }
13
-
14
6
  const fs = require('fs')
15
7
  const exec = require('child_process').exec
16
8
 
@@ -56,12 +56,43 @@ function make_spaces(n) {
56
56
  function dncl2nako(src, filename) {
57
57
  // 全角半角を統一
58
58
  src = conv2half(src)
59
- // 行頭の「|」はインデントを表す記号
59
+ // 行頭の「|」はインデントを表す記号なので無視する
60
+ // 後判定の「繰り返し,」を「後判定で繰り返す」に置換する
60
61
  const a = src.split('\n')
61
62
  for (let i = 0; i < a.length; i++) {
62
- a[i] = a[i].replace(/^(\s*[|\s]+)(.*$)/, (m0, m1, m2) => {
63
+ // インデントを消す
64
+ let line = a[i]
65
+ a[i] = line.replace(/^(\s*[|\s]+)(.*$)/, (m0, m1, m2) => {
63
66
  return make_spaces(m1.length) + m2
64
67
  })
68
+ line = a[i]
69
+ // 後判定の繰り返しの実装のため
70
+ const line2 = line.replace(/^\s+/, '').replace(/\s+$/, '')
71
+ if (line2 === '繰り返し,' || line2 === '繰り返し') {
72
+ a[i] = '後判定で繰り返し'
73
+ }
74
+ const r = line.match(/^\s*を,?(.+)になるまで(繰り返す|実行する)/)
75
+ if (r) {
76
+ a[i] = `ここまで、(${r[1]})になるまでの間`
77
+ continue
78
+ }
79
+ // 『もしj>hakosuならばhakosu←jを実行する』のような単文のもし文
80
+ const rif = line.match(/^もし(.+)を実行する(。|.)*/)
81
+ if (rif) {
82
+ const sent = dncl2nako(rif[1], filename)
83
+ a[i] = `もし、${sent};`
84
+ continue
85
+ }
86
+ //'のすべての値を0にする'
87
+ //'のすべての要素を0にする'
88
+ //'のすべての要素に0を代入する'
89
+ const rall = line.match(/^(.+?)のすべての(要素|値)(を|に)(.+?)(にする|を代入)/)
90
+ if (rall) {
91
+ const varname = rall[1]
92
+ const v = rall[4]
93
+ a[i] = `${varname} = [${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v},${v}]`
94
+ continue
95
+ }
65
96
  }
66
97
  src = a.join('\n')
67
98
  // ---------------------------------
@@ -78,9 +109,10 @@ function dncl2nako(src, filename) {
78
109
  'を実行し、そうでなければ': '違えば',
79
110
  'を繰り返す': 'ここまで',
80
111
  '改行なしで表示': '連続無改行表示',
81
- 'のすべての値を0にする': '=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]',
82
112
  'ずつ増やしながら':'ずつ増やし繰り返す',
83
113
  'ずつ減らしながら':'ずつ減らし繰り返す',
114
+ '二進で表示': '二進表示',
115
+ 'でないならば': 'でなければ',
84
116
  }
85
117
  let peekChar = () => src.charAt(0)
86
118
  let nextChar = () => {
@@ -133,27 +165,31 @@ function dncl2nako(src, filename) {
133
165
  continue
134
166
  }
135
167
  // 表示を連続表示に置き換える
136
- if (src.substring(0, 3) === 'を表示') {
168
+ const ch3 = src.substring(0, 3)
169
+ if (ch3 === 'を表示') {
137
170
  result += 'を連続表示'
138
171
  src = src.substring(3)
139
172
  continue
140
173
  }
141
- // 1行先読み
142
- let line = ''
143
- const i = src.indexOf('\n')
144
- if (i >= 0) {
145
- line = src.substring(0, i)
146
- } else {
147
- line = src
174
+ if (src.substring(0, 4) === 'を 表示') {
175
+ result += 'を連続表示'
176
+ src = src.substring(4)
177
+ continue
148
178
  }
149
- // 『もしj>hakosuならばhakosu←jを実行する』のような単文のもし文
150
- const rif = line.match(/^もし(.+)を実行する(。|.)*/)
151
- if (rif) {
152
- const sent = dncl2nako(rif[1], filename)
153
- result += `もし、${sent};`
154
- src = src.substring(rif[0].length)
179
+ // 乱数を乱数範囲に置き換える
180
+ if (src.substring(0, 2) === '乱数' && src.substring(0, 4) !== '乱数範囲') {
181
+ result += '乱数範囲'
182
+ src = src.substring(2)
155
183
  continue
156
- }
184
+ }
185
+ // 増やす・減らすの前に「だけ」を追加する #1149
186
+ if (ch3 === '増やす' || ch3 === '減らす') {
187
+ if (result.substring(result.length - 2) !== 'だけ') {
188
+ result += 'だけ'
189
+ }
190
+ result += ch3
191
+ src = src.substring(3)
192
+ }
157
193
  // 一覧から単純な変換
158
194
  {
159
195
  let flag = false
@@ -216,6 +252,7 @@ function conv2half(src) {
216
252
  if (cHalf === '{') { cHalf = '[' }
217
253
  if (cHalf === '}') { cHalf = ']' }
218
254
  if (cHalf === '←') { cHalf = '=' }
255
+ if (cHalf === '÷') { cHalf = '÷÷' } // #1152
219
256
  result += cHalf
220
257
  }
221
258
  return result
package/src/nako_gen.js CHANGED
@@ -522,6 +522,9 @@ try {
522
522
  case 'while':
523
523
  code += this.convWhile(node)
524
524
  break
525
+ case 'atohantei':
526
+ code += this.convAtohantei(node)
527
+ break
525
528
  case 'switch':
526
529
  code += this.convSwitch(node)
527
530
  break
@@ -1046,6 +1049,20 @@ try {
1046
1049
  return this.convLineno(node, false) + code
1047
1050
  }
1048
1051
 
1052
+ convAtohantei (node) {
1053
+ const id = this.loop_id++
1054
+ const varId = `$nako_i${id}`
1055
+ const cond = this._convGen(node.cond, true)
1056
+ const block = this.convGenLoop(node.block)
1057
+ const code =
1058
+ `for(;;) {\n` +
1059
+ ` ${block}\n` +
1060
+ ` let ${varId} = ${cond};\n` +
1061
+ ` if (${varId}) { continue } else { break }\n` +
1062
+ '}\n\n'
1063
+ return this.convLineno(node, false) + code
1064
+ }
1065
+
1049
1066
  convSwitch (node) {
1050
1067
  const value = this._convGen(node.value, true)
1051
1068
  const cases = node.cases
@@ -1357,7 +1374,8 @@ try {
1357
1374
  or: '||',
1358
1375
  shift_l: '<<',
1359
1376
  shift_r: '>>',
1360
- shift_r0: '>>>'
1377
+ shift_r0: '>>>',
1378
+ '÷': '/'
1361
1379
  }
1362
1380
  let op = node.operator // 演算子
1363
1381
  let right = this._convGen(node.right, true)
@@ -1371,7 +1389,9 @@ try {
1371
1389
  }
1372
1390
  }
1373
1391
  // 階乗
1374
- if (op === '^') { return '(Math.pow(' + left + ',' + right + '))' }
1392
+ if (op === '^') { return `(Math.pow(${left}, ${right}))` }
1393
+ // 整数の割り算 #1152
1394
+ if (op === '÷÷') { return `(Math.floor(${left} / ${right}))` }
1375
1395
 
1376
1396
  // 一般的なオペレータに変換
1377
1397
  if (OP_TBL[op]) { op = OP_TBL[op] }
@@ -1573,7 +1573,8 @@ try {
1573
1573
  or: '||',
1574
1574
  shift_l: '<<',
1575
1575
  shift_r: '>>',
1576
- shift_r0: '>>>'
1576
+ shift_r0: '>>>',
1577
+ '÷': '/'
1577
1578
  }
1578
1579
  const op = node.operator // 演算子
1579
1580
  // 値はスタックに載せられる
@@ -64,7 +64,8 @@ module.exports = {
64
64
  { name: '+', pattern: /^\+/ },
65
65
  { name: '-', pattern: /^-/ },
66
66
  { name: '*', pattern: /^(×|\*)/ },
67
- { name: '/', pattern: /^(÷|\/)/ },
67
+ { name: '÷÷', pattern: /^÷÷/ }, // 整数の割り算
68
+ { name: '÷', pattern: /^(÷|\/)/ }, // 普通の割り算
68
69
  { name: '%', pattern: /^%/ },
69
70
  { name: '^', pattern: /^\^/ },
70
71
  { name: '&', pattern: /^&/ },
@@ -154,7 +155,7 @@ function cbWordParser (src, isTrimOkurigana = true) {
154
155
  // 助詞の判定
155
156
  const j = josiRE.exec(src)
156
157
  if (j) {
157
- josi = j[0]
158
+ josi = j[0].replace(/^\s+/, '')
158
159
  src = src.substr(j[0].length)
159
160
  // 助詞の直後にある「,」を飛ばす #877
160
161
  if (src.charAt(0) === ',') { src = src.substr(1) }
@@ -229,7 +230,7 @@ function cbString (beginTag, closeTag, src) {
229
230
  // 文字列直後の助詞を取得
230
231
  const j = josiRE.exec(src)
231
232
  if (j) {
232
- josi = j[0]
233
+ josi = j[0].replace(/^\s+/, '')
233
234
  src = src.substr(j[0].length)
234
235
  // 助詞の後のカンマ #877
235
236
  if (src.charAt(0) === ',') { src = src.substr(1) }
@@ -100,6 +100,7 @@ class NakoParser extends NakoParserBase {
100
100
  // 最初の語句が決まっている構文
101
101
  if (this.check('eol')) { return this.yEOL() }
102
102
  if (this.check('もし')) { return this.yIF() }
103
+ if (this.check('後判定')) { return this.yAtohantei() }
103
104
  if (this.check('エラー監視')) { return this.yTryExcept() }
104
105
  if (this.check('逐次実行')) { return this.yTikuji() }
105
106
  if (this.accept(['抜ける'])) { return { type: 'break', josi: '', ...map, end: this.peekSourceMap() } }
@@ -277,12 +278,13 @@ class NakoParser extends NakoParserBase {
277
278
  let a = this.yGetArg()
278
279
  if (!a) { return null }
279
280
  // console.log('yIFCond=', a, this.peek())
281
+
280
282
  // チェック : AがBならば
281
283
  if (a.josi === 'が') {
282
284
  const tmpI = this.index
283
285
  const b = this.yGetArg()
284
286
  const naraba = this.get()
285
- if (b && b.type !== 'func' && naraba && naraba.type === 'ならば') {
287
+ if ((b && b.type !== 'func') && (naraba && naraba.type === 'ならば')) {
286
288
  return {
287
289
  type: 'op',
288
290
  operator: (naraba.value === 'でなければ') ? 'noteq' : 'eq',
@@ -729,6 +731,42 @@ class NakoParser extends NakoParserBase {
729
731
  }
730
732
  }
731
733
 
734
+ /** @returns {Ast | null} */
735
+ yAtohantei () {
736
+ const map = this.peekSourceMap()
737
+ if (this.check('後判定')) { this.get() } // skip 後判定
738
+ if (this.check('繰返')) { this.get() } // skip 繰り返す
739
+ if (this.check('ここから')) { this.get() }
740
+ const block = this.yBlock()
741
+ if (this.check('ここまで')) { this.get() }
742
+ if (this.check('comma')) { this.get() }
743
+ let cond = this.yGetArg() // 条件
744
+ let bUntil = false
745
+ const t = this.peek()
746
+ if (t && t.value === 'なる' && (t.josi === 'まで' || t.josi === 'までの')) {
747
+ this.get() // skip なるまで
748
+ bUntil = true
749
+ }
750
+ if (this.check('間')) { this.get() } // skip 間
751
+ if (bUntil) { // 条件を反転する
752
+ cond = {
753
+ type: 'not',
754
+ value: cond,
755
+ josi: '',
756
+ ...map,
757
+ end: this.peekSourceMap()
758
+ }
759
+ }
760
+ return {
761
+ type: 'atohantei',
762
+ cond,
763
+ block,
764
+ josi: '',
765
+ ...map,
766
+ end: this.peekSourceMap()
767
+ }
768
+ }
769
+
732
770
  /** @returns {Ast | null} */
733
771
  yFor () {
734
772
  const map = this.peekSourceMap()
@@ -743,7 +781,9 @@ class NakoParser extends NakoParserBase {
743
781
  if (incdec.type == 'word' && (incdec.value === '増' || incdec.value === '減')) {
744
782
  kurikaesu.type = incdec.value + kurikaesu.type
745
783
  // ↑ typeを増繰返 | 減繰返 に変換
746
- } else {
784
+ }
785
+ // 普通の繰り返しの場合
786
+ else {
747
787
  this.stack.push(incdec) // 違ったので改めて追加
748
788
  }
749
789
  let vInc = null
@@ -21,7 +21,9 @@ const opPriority = {
21
21
  'shift_r0': 4,
22
22
  // * /
23
23
  '*': 5,
24
- '/': 5,
24
+ '/': 5, // 一般的な割り算
25
+ '÷': 5, // 一般的な割り算
26
+ '÷÷': 5, // 整数の割り算
25
27
  '%': 5,
26
28
  // ^
27
29
  '^': 6
@@ -11,6 +11,7 @@ module.exports = {
11
11
  '繰返': '繰返',
12
12
  '増繰返': '増繰返', // (#1140)
13
13
  '減繰返': '減繰返',
14
+ '後判定': '後判定', // (#1147)
14
15
  '反復': '反復',
15
16
  '抜': '抜ける',
16
17
  '続': '続ける',
@@ -1,8 +1,8 @@
1
1
  // なでしこバージョン
2
2
  const nakoVersion = {
3
- version: '3.2.37',
3
+ version: '3.2.41',
4
4
  major: 3,
5
5
  minor: 2,
6
- patch: 37
6
+ patch: 41
7
7
  }
8
8
  module.exports = nakoVersion
@@ -97,9 +97,15 @@ module.exports = {
97
97
  pure: true,
98
98
  fn: function (dom) {
99
99
  if (typeof (dom) === 'string') { dom = document.querySelector(dom) }
100
-
100
+ if (!dom.tagName) {
101
+ console.log('[DOMテキスト取得]でタグ名が取得できません。', dom)
102
+ return ''
103
+ }
101
104
  const tag = dom.tagName.toUpperCase()
102
- if (tag === 'INPUT' || tag === 'TEXTAREA') { return dom.value } else if (tag === 'SELECT') {
105
+ // input or textarea
106
+ if (tag === 'INPUT' || tag === 'TEXTAREA') { return dom.value }
107
+ // select
108
+ if (tag === 'SELECT') {
103
109
  const idx = dom.selectedIndex
104
110
  if (idx < 0) { return null }
105
111
  return dom.options[idx].value
@@ -316,5 +322,15 @@ module.exports = {
316
322
  if (typeof pa === 'string') { pa = document.querySelector(pa) }
317
323
  pa.removeChild(el)
318
324
  }
325
+ },
326
+ '注目': { // @DOMの要素Aにフォーカスする(カーソルを移動する) // @ちゅうもく
327
+ type: 'func',
328
+ josi: [['を', 'へ', 'に']],
329
+ pure: true,
330
+ fn: function (el) {
331
+ if (typeof el === 'string') { el = document.querySelector(el) }
332
+ if (el.focus) { el.focus() }
333
+ },
334
+ return_none: true
319
335
  }
320
336
  }
@@ -168,6 +168,24 @@ module.exports = {
168
168
  return dom
169
169
  }
170
170
  },
171
+ 'セレクトボックスアイテム設定': { // @配列データをセレクトボックスdomのアイテムに差し替える // @せれくとぼっくすあいてむさくせい
172
+ type: 'func',
173
+ josi: [['を'], ['へ','に']],
174
+ pure: false,
175
+ fn: function (options, dom, sys) {
176
+ if (typeof(dom) === 'stirng') { dom = document.querySelector(dom) }
177
+ // 既存のoptionsをクリア
178
+ dom.options.length = 0
179
+ // アイテムを追加
180
+ for (let i = 0; i < options.length; i++) {
181
+ const item = document.createElement('option')
182
+ item.value = options[i]
183
+ item.appendChild(document.createTextNode(options[i]))
184
+ dom.appendChild(item)
185
+ }
186
+ },
187
+ return_none: true
188
+ },
171
189
  '色選択ボックス作成': { // @色選択ボックス(input[type='color'])を作成しDOMオブジェクトを返す // @いろせんたくぼっくすさくせい
172
190
  type: 'func',
173
191
  josi: [],
@@ -220,6 +220,14 @@ const PluginMath = {
220
220
  return Math.floor(Math.random() * a)
221
221
  }
222
222
  },
223
+ '乱数範囲': { // @AからBまでの範囲の乱数を返す // @らんすうはんい
224
+ type: 'func',
225
+ josi: [['から'],['までの','の']],
226
+ pure: true,
227
+ fn: function (a, b) {
228
+ return (Math.floor(Math.random() * (b - a + 1)) + a)
229
+ }
230
+ },
223
231
  'SQRT': { // @Aの平方根を返す // @SQRT
224
232
  type: 'func',
225
233
  josi: [['の']],
@@ -305,6 +305,22 @@ const PluginSystem = {
305
305
  return a % b
306
306
  }
307
307
  },
308
+ '偶数': { // @Aが偶数なら真を返す // @ぐうすう
309
+ type: 'func',
310
+ josi: [['が']],
311
+ pure: true,
312
+ fn: function (a) {
313
+ return (a % 2 == 0)
314
+ }
315
+ },
316
+ '奇数': { // @Aが奇数なら真を返す // @きすう
317
+ type: 'func',
318
+ josi: [['が']],
319
+ pure: true,
320
+ fn: function (a) {
321
+ return (a % 2 == 1)
322
+ }
323
+ },
308
324
  '二乗': { // @Aを二乗する // @にじょう
309
325
  type: 'func',
310
326
  josi: [['の', 'を']],
@@ -700,6 +716,23 @@ const PluginSystem = {
700
716
  return parseInt(v).toString(n)
701
717
  }
702
718
  },
719
+ '二進': { // @値Vを2進数に変換 // @にしん
720
+ type: 'func',
721
+ josi: [['を', 'の', 'から']],
722
+ pure: true,
723
+ fn: function (v) {
724
+ return parseInt(v).toString(2)
725
+ }
726
+ },
727
+ '二進表示': { // @値Vを2進数に変換して表示 // @にしんひょうじ
728
+ type: 'func',
729
+ josi: [['を', 'の', 'から']],
730
+ pure: true,
731
+ fn: function (v, sys) {
732
+ const s = parseInt(v).toString(2)
733
+ sys.__exec('表示', [s, sys])
734
+ }
735
+ },
703
736
  'RGB': { // @HTML用のカラーコードを返すRGB(R,G,B)で各値は0-255 // @RGB
704
737
  type: 'func',
705
738
  josi: [['と'], ['の'], ['で']],
@@ -60,6 +60,32 @@ describe('dncl (#1140)', () => {
60
60
  cmpNako('!DNCLモード\nx←10,y←20\n"("とxと","とyと")"を表示する。', '(10,20)')
61
61
  cmpNako('!DNCLモード\nx←10,y←20,z←30\n"("とxと","とyと","とzと")"を表示する。', '(10,20,30)')
62
62
  cmpNako('!DNCLモード\nx←10,y←20\n「<」とxと","とyと「>」を表示する。', '<10,20>')
63
+ // #1079
64
+ cmpNako('!DNCLモード\nx←10,y←20\n「<」 と x と "," と y と 「>」 を 表示する。', '<10,20>')
65
+ })
66
+ it('乱数エミュレート #1146', () => {
67
+ cmpNako('!DNCLモード\nr ← 乱数 (5,10)\nもし(rが5以上)かつ(rが10以下)ならば「OK」と表示する。', 'OK')
68
+ cmpNako('!DNCLモード\nr ← 乱数 (1,6)\nもし(rが1以上)かつ(rが6以下)ならば「OK」と表示する。', 'OK')
69
+ })
70
+ it('二進 #1146', () => {
71
+ cmpNako('!DNCLモード\nA← 二進 (9)\nAを表示する。', '1001')
72
+ cmpNako('!DNCLモード\nA← 二進 (255)\nAを表示する。', '11111111')
73
+ cmpNako('!DNCLモード\n二進で表示 (255)', '11111111')
74
+ })
75
+ it('減らす・増やす #1149', () => {
76
+ cmpNako('!DNCLモード\nsaihu←1000。syuppi←500。saihuをsyuppi減らす。saihuを表示する。', '500')
77
+ cmpNako('!DNCLモード\nsaihu←1000。syuppi←500。saihuをsyuppi増やす。saihuを表示する。', '1500')
78
+ })
79
+ it('DNCLで「もし」文の否定形が動かない #1148', () =>{
80
+ cmpNako('!DNCLモード\nkosu←1\nもし、kosu>27でないならば\n|「OK」を表示する。\nを実行する。\n', 'OK')
81
+ })
82
+ it('DNCLで後判定のループが動かない #1147', () =>{
83
+ cmpNako('!DNCLモード\nA←1\n繰り返し,\nAを表示する\nAを1増やす\nを,A>3になるまで実行する\n', '1\n2\n3')
84
+ cmpNako('!DNCLモード\nA←1\n繰り返し,\nAを表示する\nAを1だけ増やす\nを,A>3になるまで実行する\n', '1\n2\n3')
85
+ })
86
+ it('DNCLで÷は整数の割り算 #1152', () =>{
87
+ cmpNako('!DNCLモード\n7/2を表示する', '3.5')
88
+ cmpNako('!DNCLモード\n7÷2を表示する', '3')
63
89
  })
64
90
  })
65
91
 
@@ -143,4 +143,7 @@ describe('lex_test', () => {
143
143
  cmp('もし、3=3ならば \n『OK』と表示;違えば;「NG」と表示;ここまで。', 'OK')
144
144
  cmp('もし、3=3ならば \n『OK』と表示;違えば;「NG」と表示;ここまで。', 'OK')
145
145
  })
146
+ it('助詞の前後に空白があるとエラーになる問題 #1079', () => {
147
+ cmp('x=1;x と 2 と "3" を連続表示', '123')
148
+ })
146
149
  })
@@ -595,4 +595,8 @@ describe('plugin_system_test', () => {
595
595
  cmp('3の二乗を表示', '9')
596
596
  cmp('2の3のべき乗を表示', '8')
597
597
  })
598
+ it('『偶数』『奇数』 #1146', () => {
599
+ cmp('もし4が偶数ならば「OK」と表示。', 'OK')
600
+ cmp('もし3が奇数ならば「OK」と表示。', 'OK')
601
+ })
598
602
  })