nadesiko3 3.7.2 → 3.7.3
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 +266 -263
- package/core/package.json +1 -1
- package/core/src/nako3.mts +1 -1
- package/core/src/nako_core_version.mjs +2 -2
- package/core/src/nako_core_version.mts +2 -2
- package/core/src/nako_parser3.mjs +30 -19
- package/core/src/nako_parser3.mts +31 -18
- package/core/src/plugin_system.mjs +48 -2
- package/core/src/plugin_system.mts +47 -3
- package/core/test/basic_test.mjs +16 -0
- package/core/test/calc_test.mjs +7 -0
- package/core/test/plugin_system_test.mjs +12 -0
- package/doc/files.md +4 -4
- package/doc/plugins.md +1 -1
- package/package.json +3 -3
- package/release/_hash.txt +28 -28
- package/release/_script-tags.txt +33 -33
- 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 +1 -1
- package/release/edit_main.js.map +2 -2
- package/release/editor.js +1 -1
- package/release/version.js +1 -1
- package/release/version_main.js +1 -1
- package/release/version_main.js.map +1 -1
- package/release/wnako3.js +8 -8
- package/release/wnako3.js.map +3 -3
- package/release/wnako3webworker.js +41 -41
- package/release/wnako3webworker.js.map +3 -3
- package/src/nako_version.mjs +2 -2
- package/src/nako_version.mts +2 -2
- package/src/plugin_browser_crypto.mts +1 -1
- package/src/plugin_browser_dom_parts.mjs +19 -4
- package/src/plugin_browser_dom_parts.mts +19 -5
package/core/package.json
CHANGED
package/core/src/nako3.mts
CHANGED
|
@@ -9,7 +9,7 @@ import { Ast, AstBlocks } from './nako_ast.mjs'
|
|
|
9
9
|
// parser / lexer
|
|
10
10
|
import { NakoParser } from './nako_parser3.mjs'
|
|
11
11
|
import { NakoLexer } from './nako_lexer.mjs'
|
|
12
|
-
import { NakoPrepare
|
|
12
|
+
import { NakoPrepare } from './nako_prepare.mjs'
|
|
13
13
|
import { NakoGen, generateJS, NakoGenOptions, NakoGenResult } from './nako_gen.mjs'
|
|
14
14
|
import { convertInlineIndent, convertIndentSyntax } from './nako_indent_inline.mjs'
|
|
15
15
|
import { convertDNCL } from './nako_from_dncl.mjs'
|
|
@@ -402,11 +402,18 @@ export class NakoParser extends NakoParserBase {
|
|
|
402
402
|
this.localvars.set(fnName, { 'type': 'var', 'value': '' });
|
|
403
403
|
}
|
|
404
404
|
block = this.yBlock();
|
|
405
|
+
// 「ここまで」のチェック
|
|
405
406
|
if (this.check('ここまで')) {
|
|
406
|
-
this.get();
|
|
407
|
+
this.get(); // skip 'ここまで'
|
|
407
408
|
}
|
|
408
409
|
else {
|
|
409
|
-
|
|
410
|
+
// 「ここまで」が見当たらない
|
|
411
|
+
const nextWordO = this.peek();
|
|
412
|
+
let nextWord = JSON.stringify(nextWordO);
|
|
413
|
+
if (nextWordO && nextWordO.type && nextWordO.value) {
|
|
414
|
+
nextWord = nextWordO.value;
|
|
415
|
+
}
|
|
416
|
+
throw NakoSyntaxError.fromNode(`『ここまで』がありません。関数定義の末尾に必要です。『${nextWord}』の前に『ここまで』を記述してください。`, def);
|
|
410
417
|
}
|
|
411
418
|
this.loadStack();
|
|
412
419
|
}
|
|
@@ -1409,6 +1416,9 @@ export class NakoParser extends NakoParserBase {
|
|
|
1409
1416
|
if (!word || (word.type !== 'word' && word.type !== 'func' && word.type !== 'ref_array')) {
|
|
1410
1417
|
throw NakoSyntaxError.fromNode('代入文で代入先の変数が見当たりません。『(変数名)に(値)を代入』のように使います。', dainyu);
|
|
1411
1418
|
}
|
|
1419
|
+
if (word.type === 'func') {
|
|
1420
|
+
throw NakoSyntaxError.fromNode('関数『' + word.name + '』に代入できません。『(変数名)に(値)を代入』のように使います。', dainyu);
|
|
1421
|
+
}
|
|
1412
1422
|
// 配列への代入
|
|
1413
1423
|
if (word.type === 'ref_array') {
|
|
1414
1424
|
const indexArray = word.index || [];
|
|
@@ -1949,9 +1959,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1949
1959
|
};
|
|
1950
1960
|
}
|
|
1951
1961
|
}
|
|
1952
|
-
if (this.accept(['定数', 'word', 'eq'
|
|
1953
|
-
const
|
|
1954
|
-
const
|
|
1962
|
+
if (this.accept(['定数', 'word', 'eq'])) {
|
|
1963
|
+
const constName = this.y[1];
|
|
1964
|
+
const word = this.createVar(constName, true, this.isExportDefault);
|
|
1965
|
+
const astValue = this.yCalc() || this.yNop();
|
|
1955
1966
|
return {
|
|
1956
1967
|
type: 'def_local_var',
|
|
1957
1968
|
name: word.value,
|
|
@@ -1961,7 +1972,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
1961
1972
|
end: this.peekSourceMap()
|
|
1962
1973
|
};
|
|
1963
1974
|
}
|
|
1964
|
-
if (this.accept(['定数', 'word', '{', 'word', '}', 'eq'
|
|
1975
|
+
if (this.accept(['定数', 'word', '{', 'word', '}', 'eq'])) {
|
|
1965
1976
|
let isExport = this.isExportDefault;
|
|
1966
1977
|
const attr = this.y[3].value;
|
|
1967
1978
|
if (attr === '公開') {
|
|
@@ -1977,7 +1988,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
1977
1988
|
this.logger.warn(`不明な定数属性『${attr}』が指定されています。`);
|
|
1978
1989
|
}
|
|
1979
1990
|
const word = this.createVar(this.y[1], true, isExport);
|
|
1980
|
-
const astValue = this.
|
|
1991
|
+
const astValue = this.yCalc() || this.yNop();
|
|
1981
1992
|
return {
|
|
1982
1993
|
type: 'def_local_var',
|
|
1983
1994
|
name: word.value,
|
|
@@ -1989,7 +2000,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
1989
2000
|
};
|
|
1990
2001
|
}
|
|
1991
2002
|
// 複数定数への代入 #563
|
|
1992
|
-
if (this.accept(['定数', this.yJSONArray, 'eq'
|
|
2003
|
+
if (this.accept(['定数', this.yJSONArray, 'eq'])) {
|
|
1993
2004
|
const names = this.y[1];
|
|
1994
2005
|
// check array
|
|
1995
2006
|
if (names && names.blocks instanceof Array) {
|
|
@@ -2003,7 +2014,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
2003
2014
|
throw NakoSyntaxError.fromNode('複数定数の代入文でエラー。『定数[A,B,C]=[1,2,3]』の書式で記述してください。', this.y[0]);
|
|
2004
2015
|
}
|
|
2005
2016
|
const namesAst = this._tokensToNodes(this.createVarList(names.blocks, true, this.isExportDefault));
|
|
2006
|
-
const astValue = this.
|
|
2017
|
+
const astValue = this.yCalc() || this.yNop();
|
|
2007
2018
|
return {
|
|
2008
2019
|
type: 'def_local_varlist',
|
|
2009
2020
|
names: namesAst,
|
|
@@ -2014,7 +2025,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
2014
2025
|
};
|
|
2015
2026
|
}
|
|
2016
2027
|
// 複数変数への代入 #563
|
|
2017
|
-
if (this.accept(['変数', this.yJSONArray, 'eq'
|
|
2028
|
+
if (this.accept(['変数', this.yJSONArray, 'eq'])) {
|
|
2018
2029
|
const names = this.y[1];
|
|
2019
2030
|
// check array
|
|
2020
2031
|
if (names && names.blocks instanceof Array) {
|
|
@@ -2028,7 +2039,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
2028
2039
|
throw NakoSyntaxError.fromNode('複数変数の代入文でエラー。『変数[A,B,C]=[1,2,3]』の書式で記述してください。', this.y[0]);
|
|
2029
2040
|
}
|
|
2030
2041
|
const namesAst = this._tokensToNodes(this.createVarList(names.blocks, false, this.isExportDefault));
|
|
2031
|
-
const astValue = this.
|
|
2042
|
+
const astValue = this.yCalc() || this.yNop();
|
|
2032
2043
|
return {
|
|
2033
2044
|
type: 'def_local_varlist',
|
|
2034
2045
|
names: namesAst,
|
|
@@ -2041,10 +2052,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
2041
2052
|
// 複数変数への代入 #563
|
|
2042
2053
|
if (this.check2(['word', 'comma', 'word'])) {
|
|
2043
2054
|
// 2 word
|
|
2044
|
-
if (this.accept(['word', 'comma', 'word', 'eq'
|
|
2055
|
+
if (this.accept(['word', 'comma', 'word', 'eq'])) {
|
|
2045
2056
|
let names = [this.y[0], this.y[2]];
|
|
2046
2057
|
names = this.createVarList(names, false, this.isExportDefault);
|
|
2047
|
-
const astValue = this.
|
|
2058
|
+
const astValue = this.yCalc() || this.yNop();
|
|
2048
2059
|
return {
|
|
2049
2060
|
type: 'def_local_varlist',
|
|
2050
2061
|
names,
|
|
@@ -2055,10 +2066,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
2055
2066
|
};
|
|
2056
2067
|
}
|
|
2057
2068
|
// 3 word
|
|
2058
|
-
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'eq'
|
|
2069
|
+
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'eq'])) {
|
|
2059
2070
|
let names = [this.y[0], this.y[2], this.y[4]];
|
|
2060
2071
|
names = this.createVarList(names, false, this.isExportDefault);
|
|
2061
|
-
const astValue = this.
|
|
2072
|
+
const astValue = this.yCalc() || this.yNop();
|
|
2062
2073
|
return {
|
|
2063
2074
|
type: 'def_local_varlist',
|
|
2064
2075
|
names,
|
|
@@ -2069,10 +2080,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
2069
2080
|
};
|
|
2070
2081
|
}
|
|
2071
2082
|
// 4 word
|
|
2072
|
-
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'eq'
|
|
2083
|
+
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'eq'])) {
|
|
2073
2084
|
let names = [this.y[0], this.y[2], this.y[4], this.y[6]];
|
|
2074
2085
|
names = this.createVarList(names, false, this.isExportDefault);
|
|
2075
|
-
const astValue = this.
|
|
2086
|
+
const astValue = this.yCalc() || this.yNop();
|
|
2076
2087
|
return {
|
|
2077
2088
|
type: 'def_local_varlist',
|
|
2078
2089
|
names,
|
|
@@ -2083,10 +2094,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
2083
2094
|
};
|
|
2084
2095
|
}
|
|
2085
2096
|
// 5 word
|
|
2086
|
-
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'eq'
|
|
2097
|
+
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'eq'])) {
|
|
2087
2098
|
let names = [this.y[0], this.y[2], this.y[4], this.y[6], this.y[8]];
|
|
2088
2099
|
names = this.createVarList(names, false, this.isExportDefault);
|
|
2089
|
-
const astValue = this.
|
|
2100
|
+
const astValue = this.yCalc() || this.yNop();
|
|
2090
2101
|
return {
|
|
2091
2102
|
type: 'def_local_varlist',
|
|
2092
2103
|
names,
|
|
@@ -344,7 +344,16 @@ export class NakoParser extends NakoParserBase {
|
|
|
344
344
|
this.localvars.set(fnName, { 'type': 'var', 'value': '' })
|
|
345
345
|
}
|
|
346
346
|
block = this.yBlock()
|
|
347
|
-
|
|
347
|
+
// 「ここまで」のチェック
|
|
348
|
+
if (this.check('ここまで')) {
|
|
349
|
+
this.get() // skip 'ここまで'
|
|
350
|
+
} else {
|
|
351
|
+
// 「ここまで」が見当たらない
|
|
352
|
+
const nextWordO = this.peek()
|
|
353
|
+
let nextWord = JSON.stringify(nextWordO)
|
|
354
|
+
if (nextWordO && nextWordO.type && nextWordO.value) { nextWord = nextWordO.value }
|
|
355
|
+
throw NakoSyntaxError.fromNode(`『ここまで』がありません。関数定義の末尾に必要です。『${nextWord}』の前に『ここまで』を記述してください。`, def)
|
|
356
|
+
}
|
|
348
357
|
this.loadStack()
|
|
349
358
|
} else {
|
|
350
359
|
this.saveStack()
|
|
@@ -1221,6 +1230,9 @@ export class NakoParser extends NakoParserBase {
|
|
|
1221
1230
|
if (!word || (word.type !== 'word' && word.type !== 'func' && word.type !== 'ref_array')) {
|
|
1222
1231
|
throw NakoSyntaxError.fromNode('代入文で代入先の変数が見当たりません。『(変数名)に(値)を代入』のように使います。', dainyu)
|
|
1223
1232
|
}
|
|
1233
|
+
if (word.type === 'func') {
|
|
1234
|
+
throw NakoSyntaxError.fromNode('関数『' + word.name + '』に代入できません。『(変数名)に(値)を代入』のように使います。', dainyu)
|
|
1235
|
+
}
|
|
1224
1236
|
// 配列への代入
|
|
1225
1237
|
if (word.type === 'ref_array') {
|
|
1226
1238
|
const indexArray = word.index || []
|
|
@@ -1691,9 +1703,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1691
1703
|
}
|
|
1692
1704
|
}
|
|
1693
1705
|
|
|
1694
|
-
if (this.accept(['定数', 'word', 'eq'
|
|
1695
|
-
const
|
|
1696
|
-
const
|
|
1706
|
+
if (this.accept(['定数', 'word', 'eq'])) {
|
|
1707
|
+
const constName = this.y[1]
|
|
1708
|
+
const word = this.createVar(constName, true, this.isExportDefault)
|
|
1709
|
+
const astValue = this.yCalc() || this.yNop()
|
|
1697
1710
|
return {
|
|
1698
1711
|
type: 'def_local_var',
|
|
1699
1712
|
name: (word as AstStrValue).value,
|
|
@@ -1704,12 +1717,12 @@ export class NakoParser extends NakoParserBase {
|
|
|
1704
1717
|
} as AstDefVar
|
|
1705
1718
|
}
|
|
1706
1719
|
|
|
1707
|
-
if (this.accept(['定数', 'word', '{', 'word', '}', 'eq'
|
|
1720
|
+
if (this.accept(['定数', 'word', '{', 'word', '}', 'eq'])) {
|
|
1708
1721
|
let isExport : boolean = this.isExportDefault
|
|
1709
1722
|
const attr = this.y[3].value
|
|
1710
1723
|
if (attr === '公開') { isExport = true } else if (attr === '非公開') { isExport = false } else if (attr === 'エクスポート') { isExport = true } else { this.logger.warn(`不明な定数属性『${attr}』が指定されています。`) }
|
|
1711
1724
|
const word = this.createVar(this.y[1], true, isExport)
|
|
1712
|
-
const astValue = this.
|
|
1725
|
+
const astValue = this.yCalc() || this.yNop()
|
|
1713
1726
|
return {
|
|
1714
1727
|
type: 'def_local_var',
|
|
1715
1728
|
name: (word as AstStrValue).value,
|
|
@@ -1722,7 +1735,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
1722
1735
|
}
|
|
1723
1736
|
|
|
1724
1737
|
// 複数定数への代入 #563
|
|
1725
|
-
if (this.accept(['定数', this.yJSONArray, 'eq'
|
|
1738
|
+
if (this.accept(['定数', this.yJSONArray, 'eq'])) {
|
|
1726
1739
|
const names = this.y[1]
|
|
1727
1740
|
// check array
|
|
1728
1741
|
if (names && names.blocks instanceof Array) {
|
|
@@ -1735,7 +1748,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
1735
1748
|
throw NakoSyntaxError.fromNode('複数定数の代入文でエラー。『定数[A,B,C]=[1,2,3]』の書式で記述してください。', this.y[0])
|
|
1736
1749
|
}
|
|
1737
1750
|
const namesAst = this._tokensToNodes(this.createVarList(names.blocks, true, this.isExportDefault))
|
|
1738
|
-
const astValue = this.
|
|
1751
|
+
const astValue = this.yCalc() || this.yNop()
|
|
1739
1752
|
return {
|
|
1740
1753
|
type: 'def_local_varlist',
|
|
1741
1754
|
names: namesAst,
|
|
@@ -1746,7 +1759,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
1746
1759
|
} as AstDefVarList
|
|
1747
1760
|
}
|
|
1748
1761
|
// 複数変数への代入 #563
|
|
1749
|
-
if (this.accept(['変数', this.yJSONArray, 'eq'
|
|
1762
|
+
if (this.accept(['変数', this.yJSONArray, 'eq'])) {
|
|
1750
1763
|
const names: AstBlocks = this.y[1]
|
|
1751
1764
|
// check array
|
|
1752
1765
|
if (names && names.blocks instanceof Array) {
|
|
@@ -1759,7 +1772,7 @@ export class NakoParser extends NakoParserBase {
|
|
|
1759
1772
|
throw NakoSyntaxError.fromNode('複数変数の代入文でエラー。『変数[A,B,C]=[1,2,3]』の書式で記述してください。', this.y[0])
|
|
1760
1773
|
}
|
|
1761
1774
|
const namesAst = this._tokensToNodes(this.createVarList(names.blocks as Token[], false, this.isExportDefault))
|
|
1762
|
-
const astValue = this.
|
|
1775
|
+
const astValue = this.yCalc() || this.yNop()
|
|
1763
1776
|
return {
|
|
1764
1777
|
type: 'def_local_varlist',
|
|
1765
1778
|
names: namesAst,
|
|
@@ -1773,10 +1786,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1773
1786
|
// 複数変数への代入 #563
|
|
1774
1787
|
if (this.check2(['word', 'comma', 'word'])) {
|
|
1775
1788
|
// 2 word
|
|
1776
|
-
if (this.accept(['word', 'comma', 'word', 'eq'
|
|
1789
|
+
if (this.accept(['word', 'comma', 'word', 'eq'])) {
|
|
1777
1790
|
let names = [this.y[0], this.y[2]]
|
|
1778
1791
|
names = this.createVarList(names, false, this.isExportDefault)
|
|
1779
|
-
const astValue = this.
|
|
1792
|
+
const astValue = this.yCalc() || this.yNop()
|
|
1780
1793
|
return {
|
|
1781
1794
|
type: 'def_local_varlist',
|
|
1782
1795
|
names,
|
|
@@ -1787,10 +1800,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1787
1800
|
} as AstDefVarList
|
|
1788
1801
|
}
|
|
1789
1802
|
// 3 word
|
|
1790
|
-
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'eq'
|
|
1803
|
+
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'eq'])) {
|
|
1791
1804
|
let names = [this.y[0], this.y[2], this.y[4]]
|
|
1792
1805
|
names = this.createVarList(names, false, this.isExportDefault)
|
|
1793
|
-
const astValue = this.
|
|
1806
|
+
const astValue = this.yCalc() || this.yNop()
|
|
1794
1807
|
return {
|
|
1795
1808
|
type: 'def_local_varlist',
|
|
1796
1809
|
names,
|
|
@@ -1801,10 +1814,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1801
1814
|
} as AstDefVarList
|
|
1802
1815
|
}
|
|
1803
1816
|
// 4 word
|
|
1804
|
-
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'eq'
|
|
1817
|
+
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'eq'])) {
|
|
1805
1818
|
let names = [this.y[0], this.y[2], this.y[4], this.y[6]]
|
|
1806
1819
|
names = this.createVarList(names, false, this.isExportDefault)
|
|
1807
|
-
const astValue = this.
|
|
1820
|
+
const astValue = this.yCalc() || this.yNop()
|
|
1808
1821
|
return {
|
|
1809
1822
|
type: 'def_local_varlist',
|
|
1810
1823
|
names,
|
|
@@ -1815,10 +1828,10 @@ export class NakoParser extends NakoParserBase {
|
|
|
1815
1828
|
} as AstDefVarList
|
|
1816
1829
|
}
|
|
1817
1830
|
// 5 word
|
|
1818
|
-
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'eq'
|
|
1831
|
+
if (this.accept(['word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'comma', 'word', 'eq'])) {
|
|
1819
1832
|
let names = [this.y[0], this.y[2], this.y[4], this.y[6], this.y[8]]
|
|
1820
1833
|
names = this.createVarList(names, false, this.isExportDefault)
|
|
1821
|
-
const astValue = this.
|
|
1834
|
+
const astValue = this.yCalc() || this.yNop()
|
|
1822
1835
|
return {
|
|
1823
1836
|
type: 'def_local_varlist',
|
|
1824
1837
|
names,
|
|
@@ -403,7 +403,39 @@ export default {
|
|
|
403
403
|
isVariableJosi: false,
|
|
404
404
|
pure: true,
|
|
405
405
|
fn: function (a, b) {
|
|
406
|
-
|
|
406
|
+
if (typeof (a) === 'bigint' || typeof (b) === 'bigint') {
|
|
407
|
+
return BigInt(a) + BigInt(b);
|
|
408
|
+
}
|
|
409
|
+
return parseFloat(a) + parseFloat(b);
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
'合計': {
|
|
413
|
+
type: 'func',
|
|
414
|
+
josi: [['と', 'を', 'の']],
|
|
415
|
+
isVariableJosi: true,
|
|
416
|
+
pure: true,
|
|
417
|
+
fn: function (...a) {
|
|
418
|
+
const sys = a.pop(); // remove NakoSystem
|
|
419
|
+
if (a.length >= 1 && a[0] instanceof Array) {
|
|
420
|
+
return sys.__exec('配列合計', [a[0], sys]);
|
|
421
|
+
}
|
|
422
|
+
let isBigInt = false;
|
|
423
|
+
let sum = 0;
|
|
424
|
+
for (const v of a) {
|
|
425
|
+
if (typeof (v) === 'bigint') {
|
|
426
|
+
isBigInt = true;
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
sum += parseFloat(v);
|
|
430
|
+
}
|
|
431
|
+
if (isBigInt) {
|
|
432
|
+
let bigsum = 0n;
|
|
433
|
+
for (const v of a) {
|
|
434
|
+
bigsum += BigInt(v);
|
|
435
|
+
}
|
|
436
|
+
return bigsum;
|
|
437
|
+
}
|
|
438
|
+
return sum;
|
|
407
439
|
}
|
|
408
440
|
},
|
|
409
441
|
'引': {
|
|
@@ -1259,6 +1291,16 @@ export default {
|
|
|
1259
1291
|
return a.join('');
|
|
1260
1292
|
},
|
|
1261
1293
|
},
|
|
1294
|
+
'文字列連結': {
|
|
1295
|
+
type: 'func',
|
|
1296
|
+
josi: [['と', 'を']],
|
|
1297
|
+
pure: true,
|
|
1298
|
+
isVariableJosi: true,
|
|
1299
|
+
fn: function (...a) {
|
|
1300
|
+
a.pop(); // NakoSystemを取り除く
|
|
1301
|
+
return a.join('');
|
|
1302
|
+
},
|
|
1303
|
+
},
|
|
1262
1304
|
'文字列分解': {
|
|
1263
1305
|
type: 'func',
|
|
1264
1306
|
josi: [['を', 'の', 'で']],
|
|
@@ -1347,7 +1389,11 @@ export default {
|
|
|
1347
1389
|
// return (s.substring(s.length - cnt, s.length))
|
|
1348
1390
|
// サロゲートペアを考慮
|
|
1349
1391
|
const strArray = Array.from(s);
|
|
1350
|
-
|
|
1392
|
+
let index = strArray.length - cnt;
|
|
1393
|
+
if (index < 0) {
|
|
1394
|
+
index = 0;
|
|
1395
|
+
}
|
|
1396
|
+
return strArray.slice(index, strArray.length).join('');
|
|
1351
1397
|
}
|
|
1352
1398
|
},
|
|
1353
1399
|
'区切': {
|
|
@@ -377,13 +377,45 @@ export default {
|
|
|
377
377
|
},
|
|
378
378
|
|
|
379
379
|
// @四則演算
|
|
380
|
-
'足': { // @AとBを足す // @たす
|
|
380
|
+
'足': { // @AとBを足す(算術演算を行う) // @たす
|
|
381
381
|
type: 'func',
|
|
382
382
|
josi: [['に', 'と'], ['を']],
|
|
383
383
|
isVariableJosi: false,
|
|
384
384
|
pure: true,
|
|
385
385
|
fn: function (a: any, b: any) {
|
|
386
|
-
|
|
386
|
+
if (typeof(a) === 'bigint' || typeof(b) === 'bigint') {
|
|
387
|
+
return BigInt(a) + BigInt(b)
|
|
388
|
+
}
|
|
389
|
+
return parseFloat(a) + parseFloat(b)
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
'合計': { // @引数(可変)に指定した値を全て合計して返す // @ごうけい
|
|
393
|
+
type: 'func',
|
|
394
|
+
josi: [['と', 'を', 'の']],
|
|
395
|
+
isVariableJosi: true,
|
|
396
|
+
pure: true,
|
|
397
|
+
fn: function (...a: any) {
|
|
398
|
+
const sys = a.pop() // remove NakoSystem
|
|
399
|
+
if (a.length >= 1 && a[0] instanceof Array) {
|
|
400
|
+
return sys.__exec('配列合計', [a[0], sys])
|
|
401
|
+
}
|
|
402
|
+
let isBigInt = false
|
|
403
|
+
let sum = 0
|
|
404
|
+
for (const v of a) {
|
|
405
|
+
if (typeof(v) === 'bigint') {
|
|
406
|
+
isBigInt = true
|
|
407
|
+
break
|
|
408
|
+
}
|
|
409
|
+
sum += parseFloat(v)
|
|
410
|
+
}
|
|
411
|
+
if (isBigInt) {
|
|
412
|
+
let bigsum = 0n
|
|
413
|
+
for (const v of a) {
|
|
414
|
+
bigsum += BigInt(v)
|
|
415
|
+
}
|
|
416
|
+
return bigsum
|
|
417
|
+
}
|
|
418
|
+
return sum
|
|
387
419
|
}
|
|
388
420
|
},
|
|
389
421
|
'引': { // @AからBを引く // @ひく
|
|
@@ -1206,6 +1238,16 @@ export default {
|
|
|
1206
1238
|
return a.join('')
|
|
1207
1239
|
},
|
|
1208
1240
|
},
|
|
1241
|
+
'文字列連結': { // @引数(可変)に指定した文字列を連結して文字列を返す // @もじれつれんけつ
|
|
1242
|
+
type: 'func',
|
|
1243
|
+
josi: [['と', 'を']],
|
|
1244
|
+
pure: true,
|
|
1245
|
+
isVariableJosi: true,
|
|
1246
|
+
fn: function (...a: any) {
|
|
1247
|
+
a.pop() // NakoSystemを取り除く
|
|
1248
|
+
return a.join('')
|
|
1249
|
+
},
|
|
1250
|
+
},
|
|
1209
1251
|
'文字列分解': { // @文字列Vを一文字ずつに分解して返す // @もじれつぶんかい
|
|
1210
1252
|
type: 'func',
|
|
1211
1253
|
josi: [['を', 'の', 'で']],
|
|
@@ -1290,7 +1332,9 @@ export default {
|
|
|
1290
1332
|
// return (s.substring(s.length - cnt, s.length))
|
|
1291
1333
|
// サロゲートペアを考慮
|
|
1292
1334
|
const strArray = Array.from(s)
|
|
1293
|
-
|
|
1335
|
+
let index = strArray.length - cnt
|
|
1336
|
+
if (index < 0) { index = 0 }
|
|
1337
|
+
return strArray.slice(index, strArray.length).join('')
|
|
1294
1338
|
}
|
|
1295
1339
|
},
|
|
1296
1340
|
'区切': { // @文字列Sを区切り文字Aで区切って配列で返す // @くぎる
|
package/core/test/basic_test.mjs
CHANGED
|
@@ -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
|
})
|
package/core/test/calc_test.mjs
CHANGED
|
@@ -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,17 @@ 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')
|
|
780
792
|
})
|
|
781
793
|
})
|
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.
|
|
210
|
+
なお、プラグインでは、次のメソッドが使えるようになる。(すべてcore/src/plugin_system.mjsで定義されている。システム関数の初期化時に、これらの関数が追加される)
|
|
211
211
|
|
|
212
212
|
- sys.__findVar(name)
|
|
213
213
|
- sys.__exec(name, params)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nadesiko3",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.3",
|
|
4
4
|
"description": "Japanese Programming Language",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.mjs",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"@types/node": "^22.0.2",
|
|
102
102
|
"@types/opener": "^1.4.3",
|
|
103
103
|
"@types/shell-quote": "^1.7.5",
|
|
104
|
-
"babel-loader": "^
|
|
104
|
+
"babel-loader": "^10.0.0",
|
|
105
105
|
"browserslist": "^4.23.0",
|
|
106
106
|
"buffer": "^6.0.3",
|
|
107
107
|
"chai": "^5.1.0",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"crypto-browserify": "^3.12.0",
|
|
112
112
|
"css-loader": "^7.1.1",
|
|
113
113
|
"es6-promise": "^4.2.8",
|
|
114
|
-
"esbuild": "0.25.
|
|
114
|
+
"esbuild": "0.25.1",
|
|
115
115
|
"eslint": "^8.57.0",
|
|
116
116
|
"eslint-config-standard": "^17.1.0",
|
|
117
117
|
"eslint-plugin-import": "^2.29.1",
|