nadesiko3 3.3.48 → 3.3.49

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 (105) hide show
  1. package/core/.editorconfig +6 -0
  2. package/core/.eslintrc.cjs +33 -0
  3. package/core/.github/dependabot.yml +7 -0
  4. package/core/.github/workflows/nodejs.yml +37 -0
  5. package/core/.github/workflows/super-linter.yml +61 -0
  6. package/core/.github/workflows/textlint.yml +199 -0
  7. package/core/LICENSE +21 -0
  8. package/core/README.md +66 -0
  9. package/core/batch/build_nako_version.nako3 +42 -0
  10. package/core/command/snako.mjs +105 -0
  11. package/core/command/snako.mts +116 -0
  12. package/core/index.mjs +21 -0
  13. package/core/index.mts +21 -0
  14. package/core/package.json +47 -0
  15. package/core/sample/hello.nako3 +7 -0
  16. package/core/sample/hoge.mjs +4 -0
  17. package/core/sample/hoge.mts +6 -0
  18. package/core/src/nako3.mjs +858 -0
  19. package/core/src/nako3.mts +967 -0
  20. package/core/src/nako_colors.mjs +78 -0
  21. package/core/src/nako_colors.mts +86 -0
  22. package/core/src/nako_core_version.mjs +8 -0
  23. package/core/src/nako_core_version.mts +19 -0
  24. package/core/src/nako_csv.mjs +185 -0
  25. package/core/src/nako_csv.mts +188 -0
  26. package/core/src/nako_errors.mjs +173 -0
  27. package/core/src/nako_errors.mts +197 -0
  28. package/core/src/nako_from_dncl.mjs +255 -0
  29. package/core/src/nako_from_dncl.mts +250 -0
  30. package/core/src/nako_gen.mjs +1648 -0
  31. package/core/src/nako_gen.mts +1719 -0
  32. package/core/src/nako_gen_async.mjs +1659 -0
  33. package/core/src/nako_gen_async.mts +1732 -0
  34. package/core/src/nako_global.mjs +107 -0
  35. package/core/src/nako_global.mts +138 -0
  36. package/core/src/nako_indent.mjs +445 -0
  37. package/core/src/nako_indent.mts +492 -0
  38. package/core/src/nako_josi_list.mjs +38 -0
  39. package/core/src/nako_josi_list.mts +45 -0
  40. package/core/src/nako_lex_rules.mjs +253 -0
  41. package/core/src/nako_lex_rules.mts +260 -0
  42. package/core/src/nako_lexer.mjs +609 -0
  43. package/core/src/nako_lexer.mts +612 -0
  44. package/core/src/nako_logger.mjs +199 -0
  45. package/core/src/nako_logger.mts +232 -0
  46. package/core/src/nako_parser3.mjs +2439 -0
  47. package/core/src/nako_parser3.mts +2195 -0
  48. package/core/src/nako_parser_base.mjs +370 -0
  49. package/core/src/nako_parser_base.mts +370 -0
  50. package/core/src/nako_parser_const.mjs +37 -0
  51. package/core/src/nako_parser_const.mts +37 -0
  52. package/core/src/nako_prepare.mjs +304 -0
  53. package/core/src/nako_prepare.mts +315 -0
  54. package/core/src/nako_reserved_words.mjs +38 -0
  55. package/core/src/nako_reserved_words.mts +38 -0
  56. package/core/src/nako_source_mapping.mjs +207 -0
  57. package/core/src/nako_source_mapping.mts +262 -0
  58. package/core/src/nako_test.mjs +37 -0
  59. package/core/src/nako_types.mjs +25 -0
  60. package/core/src/nako_types.mts +151 -0
  61. package/core/src/plugin_csv.mjs +49 -0
  62. package/core/src/plugin_csv.mts +50 -0
  63. package/core/src/plugin_math.mjs +328 -0
  64. package/core/src/plugin_math.mts +326 -0
  65. package/core/src/plugin_promise.mjs +91 -0
  66. package/core/src/plugin_promise.mts +91 -0
  67. package/core/src/plugin_system.mjs +2832 -0
  68. package/core/src/plugin_system.mts +2690 -0
  69. package/core/src/plugin_test.mjs +34 -0
  70. package/core/src/plugin_test.mts +34 -0
  71. package/core/test/array_test.mjs +34 -0
  72. package/core/test/basic_test.mjs +344 -0
  73. package/core/test/calc_test.mjs +140 -0
  74. package/core/test/core_module_test.mjs +23 -0
  75. package/core/test/debug_test.mjs +16 -0
  76. package/core/test/dncl_test.mjs +94 -0
  77. package/core/test/error_message_test.mjs +210 -0
  78. package/core/test/error_test.mjs +16 -0
  79. package/core/test/flow_test.mjs +373 -0
  80. package/core/test/func_call.mjs +160 -0
  81. package/core/test/func_test.mjs +149 -0
  82. package/core/test/indent_test.mjs +364 -0
  83. package/core/test/lex_test.mjs +168 -0
  84. package/core/test/literal_test.mjs +73 -0
  85. package/core/test/nako_lexer_test.mjs +35 -0
  86. package/core/test/nako_logger_test.mjs +76 -0
  87. package/core/test/nako_logger_test.mts +78 -0
  88. package/core/test/plugin_csv_test.mjs +38 -0
  89. package/core/test/plugin_promise_test.mjs +18 -0
  90. package/core/test/plugin_system_test.mjs +630 -0
  91. package/core/test/prepare_test.mjs +96 -0
  92. package/core/test/re_test.mjs +22 -0
  93. package/core/test/side_effects_test.mjs +92 -0
  94. package/core/test/variable_scope_test.mjs +149 -0
  95. package/core/tsconfig.json +101 -0
  96. package/package.json +4 -2
  97. package/release/_hash.txt +12 -12
  98. package/release/_script-tags.txt +14 -14
  99. package/release/editor.js +1 -1
  100. package/release/stats.json +1 -1
  101. package/release/version.js +1 -1
  102. package/release/wnako3.js +1 -1
  103. package/src/nako_version.mjs +2 -2
  104. package/src/nako_version.mts +2 -2
  105. package/test/async/async_basic_test.mjs +3 -3
@@ -0,0 +1,207 @@
1
+ /** prepareとtokenizeのソースマッピング */
2
+ export class SourceMappingOfTokenization {
3
+ /**
4
+ * @param {number} sourceCodeLength
5
+ * @param {PreprocessItem[]} preprocessed
6
+ */
7
+ constructor(sourceCodeLength, preprocessed) {
8
+ /** @private @readonly */
9
+ this.sourceCodeLength = sourceCodeLength;
10
+ /** @private @readonly */
11
+ this.preprocessed = preprocessed;
12
+ let i = 0;
13
+ /** @private @readonly @type {number[]} */
14
+ this.cumulativeSum = [];
15
+ for (const el of preprocessed) {
16
+ this.cumulativeSum.push(i);
17
+ i += el.text.length;
18
+ }
19
+ /** @private */
20
+ this.lastIndex = 0;
21
+ /** @private */
22
+ this.lastPreprocessedCodePosition = 0;
23
+ }
24
+ /**
25
+ * preprocess後の文字列上のoffsetからソースコード上のoffsetへ変換
26
+ * @param {number} preprocessedCodePosition
27
+ * @returns {number}
28
+ */
29
+ map(preprocessedCodePosition) {
30
+ const i = this.findIndex(preprocessedCodePosition);
31
+ return Math.min(this.preprocessed[i].sourcePosition + (preprocessedCodePosition - this.cumulativeSum[i]), i === this.preprocessed.length - 1 ? this.sourceCodeLength : this.preprocessed[i + 1].sourcePosition - 1);
32
+ }
33
+ /**
34
+ * @param {number} preprocessedCodePosition
35
+ * @returns {number}
36
+ */
37
+ findIndex(preprocessedCodePosition) {
38
+ // 連続アクセスに対する高速化
39
+ if (preprocessedCodePosition < this.lastPreprocessedCodePosition) {
40
+ this.lastIndex = 0;
41
+ }
42
+ this.lastPreprocessedCodePosition = preprocessedCodePosition;
43
+ for (let i = this.lastIndex; i < this.preprocessed.length - 1; i++) {
44
+ if (preprocessedCodePosition < this.cumulativeSum[i + 1]) {
45
+ this.lastIndex = i;
46
+ return i;
47
+ }
48
+ }
49
+ this.lastIndex = this.preprocessed.length - 1;
50
+ return this.preprocessed.length - 1;
51
+ }
52
+ }
53
+ export class SourceMappingOfIndentSyntax {
54
+ /**
55
+ * @param {string} codeAfterProcessingIndentationSyntax
56
+ * @param {readonly number[]} linesInsertedByIndentationSyntax
57
+ * @param {readonly { lineNumber: number, len: number }[]} linesDeletedByIndentationSyntax
58
+ */
59
+ constructor(codeAfterProcessingIndentationSyntax, linesInsertedByIndentationSyntax, linesDeletedByIndentationSyntax) {
60
+ /** @private @type {{ offset: number, len: number }[]} */
61
+ this.lines = [];
62
+ /** @private @readonly */
63
+ this.linesInsertedByIndentationSyntax = linesInsertedByIndentationSyntax;
64
+ /** @private @readonly */
65
+ this.linesDeletedByIndentationSyntax = linesDeletedByIndentationSyntax;
66
+ let offset = 0;
67
+ for (const line of codeAfterProcessingIndentationSyntax.split('\n')) {
68
+ this.lines.push({ offset, len: line.length });
69
+ offset += line.length + 1;
70
+ }
71
+ /** @private */
72
+ this.lastLineNumber = 0;
73
+ /** @private */
74
+ this.lastOffset = 0;
75
+ }
76
+ /**
77
+ * @param {number | null} startOffset
78
+ * @param {number | null} endOffset
79
+ * @returns {{ startOffset: number | null, endOffset: number | null }}
80
+ */
81
+ map(startOffset, endOffset) {
82
+ if (startOffset === null) {
83
+ return { startOffset, endOffset };
84
+ }
85
+ // 何行目かを判定
86
+ const tokenLine = this.getLineNumber(startOffset);
87
+ for (const insertedLine of this.linesInsertedByIndentationSyntax) {
88
+ // インデント構文の処理後のソースコードの `insertedLine` 行目にあるトークンのソースマップ情報を削除する。
89
+ if (tokenLine === insertedLine) {
90
+ startOffset = null;
91
+ endOffset = null;
92
+ break;
93
+ }
94
+ // インデント構文の処理後のソースコードの `insertedLine` 行目以降にあるトークンのoffsetから
95
+ // `linesInsertedByIndentationSyntax[i]` 行目の文字数(\rを含む) を引く。
96
+ if (tokenLine > insertedLine) {
97
+ // "\n"の分1足す
98
+ startOffset -= this.lines[insertedLine].len + 1;
99
+ if (endOffset !== null) {
100
+ endOffset -= this.lines[insertedLine].len + 1;
101
+ }
102
+ }
103
+ }
104
+ for (const deletedLine of this.linesDeletedByIndentationSyntax) {
105
+ if (tokenLine >= deletedLine.lineNumber) {
106
+ // "\n"の分1足す
107
+ if (startOffset !== null) {
108
+ startOffset += deletedLine.len + 1;
109
+ }
110
+ if (endOffset !== null) {
111
+ endOffset += deletedLine.len + 1;
112
+ }
113
+ }
114
+ }
115
+ return { startOffset, endOffset };
116
+ }
117
+ /**
118
+ * @param {number} offset
119
+ * @returns {number}
120
+ * @private
121
+ */
122
+ getLineNumber(offset) {
123
+ // 連続アクセスに対する高速化
124
+ if (offset < this.lastOffset) {
125
+ this.lastLineNumber = 0;
126
+ }
127
+ this.lastOffset = offset;
128
+ for (let i = this.lastLineNumber; i < this.lines.length - 1; i++) {
129
+ if (offset < this.lines[i + 1].offset) {
130
+ this.lastLineNumber = i;
131
+ return i;
132
+ }
133
+ }
134
+ this.lastLineNumber = this.lines.length - 1;
135
+ return this.lines.length - 1;
136
+ }
137
+ }
138
+ /** offsetから (line, column) へ変換する。 */
139
+ export class OffsetToLineColumn {
140
+ /**
141
+ * @param {string} code
142
+ */
143
+ constructor(code) {
144
+ /** @private @type {number[]} */
145
+ this.lineOffsets = [];
146
+ // 各行の先頭位置を先に計算しておく
147
+ let offset = 0;
148
+ for (const line of code.split('\n')) {
149
+ this.lineOffsets.push(offset);
150
+ offset += line.length + 1;
151
+ }
152
+ /** @private */
153
+ this.lastLineNumber = 0;
154
+ /** @private */
155
+ this.lastOffset = 0;
156
+ }
157
+ /**
158
+ * @param {number} offset
159
+ * @param {boolean} oneBasedLineNumber trueのときlineを1から始める
160
+ * @returns {{ line: number, column: number }}
161
+ */
162
+ map(offset, oneBasedLineNumber) {
163
+ // 連続アクセスに対する高速化
164
+ if (offset < this.lastOffset) {
165
+ this.lastLineNumber = 0;
166
+ }
167
+ this.lastOffset = offset;
168
+ for (let i = this.lastLineNumber; i < this.lineOffsets.length - 1; i++) {
169
+ if (offset < this.lineOffsets[i + 1]) {
170
+ this.lastLineNumber = i;
171
+ return {
172
+ line: i + (oneBasedLineNumber ? 1 : 0),
173
+ column: offset - this.lineOffsets[i]
174
+ };
175
+ }
176
+ }
177
+ this.lastLineNumber = this.lineOffsets.length - 1;
178
+ return {
179
+ line: this.lineOffsets.length - 1 + (oneBasedLineNumber ? 1 : 0),
180
+ column: offset - this.lineOffsets[this.lineOffsets.length - 1]
181
+ };
182
+ }
183
+ }
184
+ /**
185
+ * preCodeの分、ソースマップのoffset、行数、列数を減らす。
186
+ * @type {<T extends {line?: number, column?: number, startOffset: number | null, endOffset: number | null }>(sourceMap: T, preCode: string) => T}
187
+ */
188
+ export function subtractSourceMapByPreCodeLength(sourceMap, preCode) {
189
+ // offsetは単純に引くだけでよい
190
+ if (typeof sourceMap.startOffset === 'number') {
191
+ sourceMap.startOffset -= preCode.length;
192
+ }
193
+ if (typeof sourceMap.endOffset === 'number') {
194
+ sourceMap.endOffset -= preCode.length;
195
+ }
196
+ // たとえば preCode = 'abc\ndef\nghi' のとき、line -= 2 して、先頭行なら column -= 3 もする。
197
+ if (preCode !== '') {
198
+ const lines = preCode.split('\n');
199
+ if (typeof sourceMap.line === 'number') {
200
+ sourceMap.line -= lines.length - 1;
201
+ }
202
+ if (sourceMap.line === 0 && typeof sourceMap.column === 'number') {
203
+ sourceMap.column -= lines[lines.length - 1].length;
204
+ }
205
+ }
206
+ return sourceMap;
207
+ }
@@ -0,0 +1,262 @@
1
+
2
+ interface PreprocessItem {
3
+ text: string;
4
+ sourcePosition: number
5
+ }
6
+
7
+ /** prepareとtokenizeのソースマッピング */
8
+ export class SourceMappingOfTokenization {
9
+ private readonly sourceCodeLength: number;
10
+ private readonly preprocessed: PreprocessItem[];
11
+ private readonly cumulativeSum: number[];
12
+ private lastIndex: number;
13
+ private lastPreprocessedCodePosition: number;
14
+ /**
15
+ * @param {number} sourceCodeLength
16
+ * @param {PreprocessItem[]} preprocessed
17
+ */
18
+ constructor (sourceCodeLength: number, preprocessed: PreprocessItem[]) {
19
+ /** @private @readonly */
20
+ this.sourceCodeLength = sourceCodeLength
21
+
22
+ /** @private @readonly */
23
+ this.preprocessed = preprocessed
24
+
25
+ let i = 0
26
+ /** @private @readonly @type {number[]} */
27
+ this.cumulativeSum = []
28
+ for (const el of preprocessed) {
29
+ this.cumulativeSum.push(i)
30
+ i += el.text.length
31
+ }
32
+
33
+ /** @private */
34
+ this.lastIndex = 0
35
+ /** @private */
36
+ this.lastPreprocessedCodePosition = 0
37
+ }
38
+
39
+ /**
40
+ * preprocess後の文字列上のoffsetからソースコード上のoffsetへ変換
41
+ * @param {number} preprocessedCodePosition
42
+ * @returns {number}
43
+ */
44
+ map (preprocessedCodePosition: number): number {
45
+ const i = this.findIndex(preprocessedCodePosition)
46
+ return Math.min(
47
+ this.preprocessed[i].sourcePosition + (preprocessedCodePosition - this.cumulativeSum[i]),
48
+ i === this.preprocessed.length - 1 ? this.sourceCodeLength : this.preprocessed[i + 1].sourcePosition - 1
49
+ )
50
+ }
51
+
52
+ /**
53
+ * @param {number} preprocessedCodePosition
54
+ * @returns {number}
55
+ */
56
+ findIndex (preprocessedCodePosition: number): number {
57
+ // 連続アクセスに対する高速化
58
+ if (preprocessedCodePosition < this.lastPreprocessedCodePosition) {
59
+ this.lastIndex = 0
60
+ }
61
+ this.lastPreprocessedCodePosition = preprocessedCodePosition
62
+
63
+ for (let i = this.lastIndex; i < this.preprocessed.length - 1; i++) {
64
+ if (preprocessedCodePosition < this.cumulativeSum[i + 1]) {
65
+ this.lastIndex = i
66
+ return i
67
+ }
68
+ }
69
+
70
+ this.lastIndex = this.preprocessed.length - 1
71
+ return this.preprocessed.length - 1
72
+ }
73
+ }
74
+
75
+ export class SourceMappingOfIndentSyntax {
76
+ private lines: { offset: number, len: number }[];
77
+ private readonly linesInsertedByIndentationSyntax: number[];
78
+ private readonly linesDeletedByIndentationSyntax: { lineNumber: number, len: number }[];
79
+ lastLineNumber: number;
80
+ lastOffset: number;
81
+ /**
82
+ * @param {string} codeAfterProcessingIndentationSyntax
83
+ * @param {readonly number[]} linesInsertedByIndentationSyntax
84
+ * @param {readonly { lineNumber: number, len: number }[]} linesDeletedByIndentationSyntax
85
+ */
86
+ constructor (
87
+ codeAfterProcessingIndentationSyntax: string,
88
+ linesInsertedByIndentationSyntax: number[],
89
+ linesDeletedByIndentationSyntax: { lineNumber: number, len: number }[]
90
+ ) {
91
+ /** @private @type {{ offset: number, len: number }[]} */
92
+ this.lines = []
93
+
94
+ /** @private @readonly */
95
+ this.linesInsertedByIndentationSyntax = linesInsertedByIndentationSyntax
96
+
97
+ /** @private @readonly */
98
+ this.linesDeletedByIndentationSyntax = linesDeletedByIndentationSyntax
99
+
100
+ let offset = 0
101
+ for (const line of codeAfterProcessingIndentationSyntax.split('\n')) {
102
+ this.lines.push({ offset, len: line.length })
103
+ offset += line.length + 1
104
+ }
105
+
106
+ /** @private */
107
+ this.lastLineNumber = 0
108
+ /** @private */
109
+ this.lastOffset = 0
110
+ }
111
+
112
+ /**
113
+ * @param {number | null} startOffset
114
+ * @param {number | null} endOffset
115
+ * @returns {{ startOffset: number | null, endOffset: number | null }}
116
+ */
117
+ map (startOffset: number | null, endOffset:number | null): { startOffset: number | null, endOffset: number | null } {
118
+ if (startOffset === null) {
119
+ return { startOffset, endOffset }
120
+ }
121
+
122
+ // 何行目かを判定
123
+ const tokenLine = this.getLineNumber(startOffset)
124
+
125
+ for (const insertedLine of this.linesInsertedByIndentationSyntax) {
126
+ // インデント構文の処理後のソースコードの `insertedLine` 行目にあるトークンのソースマップ情報を削除する。
127
+ if (tokenLine === insertedLine) {
128
+ startOffset = null
129
+ endOffset = null
130
+ break
131
+ }
132
+
133
+ // インデント構文の処理後のソースコードの `insertedLine` 行目以降にあるトークンのoffsetから
134
+ // `linesInsertedByIndentationSyntax[i]` 行目の文字数(\rを含む) を引く。
135
+ if (tokenLine > insertedLine) {
136
+ // "\n"の分1足す
137
+ startOffset -= this.lines[insertedLine].len + 1
138
+ if (endOffset !== null) {
139
+ endOffset -= this.lines[insertedLine].len + 1
140
+ }
141
+ }
142
+ }
143
+ for (const deletedLine of this.linesDeletedByIndentationSyntax) {
144
+ if (tokenLine >= deletedLine.lineNumber) {
145
+ // "\n"の分1足す
146
+ if (startOffset !== null) {
147
+ startOffset += deletedLine.len + 1
148
+ }
149
+ if (endOffset !== null) {
150
+ endOffset += deletedLine.len + 1
151
+ }
152
+ }
153
+ }
154
+
155
+ return { startOffset, endOffset }
156
+ }
157
+
158
+ /**
159
+ * @param {number} offset
160
+ * @returns {number}
161
+ * @private
162
+ */
163
+ getLineNumber (offset: number): number {
164
+ // 連続アクセスに対する高速化
165
+ if (offset < this.lastOffset) {
166
+ this.lastLineNumber = 0
167
+ }
168
+ this.lastOffset = offset
169
+
170
+ for (let i = this.lastLineNumber; i < this.lines.length - 1; i++) {
171
+ if (offset < this.lines[i + 1].offset) {
172
+ this.lastLineNumber = i
173
+ return i
174
+ }
175
+ }
176
+
177
+ this.lastLineNumber = this.lines.length - 1
178
+ return this.lines.length - 1
179
+ }
180
+ }
181
+
182
+ /** offsetから (line, column) へ変換する。 */
183
+ export class OffsetToLineColumn {
184
+ private lineOffsets: number[];
185
+ private lastLineNumber: number;
186
+ private lastOffset: number;
187
+ /**
188
+ * @param {string} code
189
+ */
190
+ constructor (code: string) {
191
+ /** @private @type {number[]} */
192
+ this.lineOffsets = []
193
+
194
+ // 各行の先頭位置を先に計算しておく
195
+ let offset = 0
196
+ for (const line of code.split('\n')) {
197
+ this.lineOffsets.push(offset)
198
+ offset += line.length + 1
199
+ }
200
+
201
+ /** @private */
202
+ this.lastLineNumber = 0
203
+ /** @private */
204
+ this.lastOffset = 0
205
+ }
206
+
207
+ /**
208
+ * @param {number} offset
209
+ * @param {boolean} oneBasedLineNumber trueのときlineを1から始める
210
+ * @returns {{ line: number, column: number }}
211
+ */
212
+ map (offset: number, oneBasedLineNumber: boolean):{ line: number, column: number } {
213
+ // 連続アクセスに対する高速化
214
+ if (offset < this.lastOffset) {
215
+ this.lastLineNumber = 0
216
+ }
217
+ this.lastOffset = offset
218
+
219
+ for (let i = this.lastLineNumber; i < this.lineOffsets.length - 1; i++) {
220
+ if (offset < this.lineOffsets[i + 1]) {
221
+ this.lastLineNumber = i
222
+ return {
223
+ line: i + (oneBasedLineNumber ? 1 : 0),
224
+ column: offset - this.lineOffsets[i]
225
+ }
226
+ }
227
+ }
228
+
229
+ this.lastLineNumber = this.lineOffsets.length - 1
230
+ return {
231
+ line: this.lineOffsets.length - 1 + (oneBasedLineNumber ? 1 : 0),
232
+ column: offset - this.lineOffsets[this.lineOffsets.length - 1]
233
+ }
234
+ }
235
+ }
236
+
237
+ /**
238
+ * preCodeの分、ソースマップのoffset、行数、列数を減らす。
239
+ * @type {<T extends {line?: number, column?: number, startOffset: number | null, endOffset: number | null }>(sourceMap: T, preCode: string) => T}
240
+ */
241
+ export function subtractSourceMapByPreCodeLength (sourceMap: any, preCode: string) {
242
+ // offsetは単純に引くだけでよい
243
+ if (typeof sourceMap.startOffset === 'number') {
244
+ sourceMap.startOffset -= preCode.length
245
+ }
246
+ if (typeof sourceMap.endOffset === 'number') {
247
+ sourceMap.endOffset -= preCode.length
248
+ }
249
+
250
+ // たとえば preCode = 'abc\ndef\nghi' のとき、line -= 2 して、先頭行なら column -= 3 もする。
251
+ if (preCode !== '') {
252
+ const lines = preCode.split('\n')
253
+ if (typeof sourceMap.line === 'number') {
254
+ sourceMap.line -= lines.length - 1
255
+ }
256
+ if (sourceMap.line === 0 && typeof sourceMap.column === 'number') {
257
+ sourceMap.column -= lines[lines.length - 1].length
258
+ }
259
+ }
260
+
261
+ return sourceMap
262
+ }
@@ -0,0 +1,37 @@
1
+ class NakoTest {
2
+ constructor () {
3
+ /** @type {{ name: string, f: () => void }[]} */
4
+ this.tests = []
5
+ }
6
+
7
+ /** @param {any} a, @param {any} b */
8
+ static assertStrictEqual (a, b) {
9
+ if (a !== b) {
10
+ throw new Error('')
11
+ }
12
+ }
13
+
14
+ /** @param {unknown} a */
15
+ static inspect (a) {
16
+ switch (typeof a) {
17
+ case 'bigint': return `bigint値『${a}』`
18
+ case 'boolean': return a + ''
19
+ case 'function': return `関数『${a.name}』`
20
+ case 'number': return `数値${a}`
21
+ case 'object':
22
+ if (a === null) {
23
+ return a + ''
24
+ }
25
+ try {
26
+ return `オブジェクト『${JSON.stringify(a)}』`
27
+ } catch (e) { // 循環参照など
28
+ return `オブジェクト『${a}』`
29
+ }
30
+ case 'string': return `文字列『${a}』`
31
+ case 'symbol': return `シンボル『${a.toString()}』`
32
+ case 'undefined': return a + ''
33
+ }
34
+ }
35
+ }
36
+
37
+ module.exports = NakoTest
@@ -0,0 +1,25 @@
1
+ /**
2
+ * なでしこ3 の TypeScript のための型定義
3
+ */
4
+ export function NewEmptyToken(type = '?', value = {}, line = 0, file = 'main.nako3') {
5
+ return {
6
+ type,
7
+ value,
8
+ line,
9
+ column: 0,
10
+ file,
11
+ josi: ''
12
+ };
13
+ }
14
+ /**
15
+ * コンパイルオプション
16
+ */
17
+ export class CompilerOptions {
18
+ constructor(initObj = {}) {
19
+ this.testOnly = initObj.testOnly || false;
20
+ this.resetEnv = initObj.resetEnv || false;
21
+ this.resetAll = initObj.resetAll || false;
22
+ this.preCode = initObj.preCode || '';
23
+ this.nakoGlobal = initObj.nakoGlobal || null;
24
+ }
25
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * なでしこ3 の TypeScript のための型定義
3
+ */
4
+
5
+ import { NakoGlobal } from './nako_global.mjs'
6
+
7
+ // 関数に関する定義
8
+ export type FuncArgs = string[][]
9
+
10
+ // FuncListの定義
11
+ export interface FuncListItem {
12
+ type: 'func' | 'var' | 'const' | 'test_func';
13
+ value?: any;
14
+ josi?: FuncArgs;
15
+ isVariableJosi?: boolean;
16
+ fn?: null | ((...args: any[]) => any) | string;
17
+ varnames?: string[];
18
+ funcPointers?: any[];
19
+ asyncFn?: boolean;
20
+ // eslint-disable-next-line camelcase
21
+ return_none?: boolean;
22
+ pure?: boolean;
23
+ name?: string;
24
+ }
25
+
26
+ // 関数の一覧
27
+ export type FuncList = {[key: string]: FuncListItem};
28
+
29
+ // トークンのメタ情報
30
+ export interface TokenMeta {
31
+ josi: FuncArgs | undefined;
32
+ varnames: string[] | undefined;
33
+ funcPointers: any[] | undefined;
34
+ }
35
+
36
+ // トークン
37
+ export interface Token {
38
+ type: string;
39
+ value: any;
40
+ line: number;
41
+ column: number;
42
+ file: string;
43
+ josi: string;
44
+ meta?: FuncListItem;
45
+ rawJosi?: string;
46
+ startOffset?: number | undefined;
47
+ endOffset?: number | undefined;
48
+ isDefinition?: boolean;
49
+ funcPointer?: boolean;
50
+ tag?: string;
51
+ preprocessedCodeOffset?: number | undefined;
52
+ preprocessedCodeLength?: number | undefined;
53
+ // eslint-disable-next-line no-use-before-define
54
+ name?: Token | Ast; // NakoPaserBase.nodeToStrの問題を回避するため
55
+ start?: number;
56
+ end?: number;
57
+ firstToken?: Token;
58
+ lastToken?: Token;
59
+ }
60
+
61
+ export function NewEmptyToken (type = '?', value: any = {}, line = 0, file = 'main.nako3'): Token {
62
+ return {
63
+ type,
64
+ value,
65
+ line,
66
+ column: 0,
67
+ file,
68
+ josi: ''
69
+ }
70
+ }
71
+
72
+ export interface Ast {
73
+ type: string;
74
+ cond?: Ast[] | Ast;
75
+ expr?: Ast[] | Ast; // todo: cond と共通化できそう
76
+ block?: Ast[] | Ast;
77
+ target?: Ast[] | Ast | null; // 反復
78
+ blocks?: Ast[]; // todo: 逐次実行でのみ使われるので、今後削除可能
79
+ errorBlock?: Ast[] | Ast; // todo: 逐次実行でのみ使われるので、今後削除可能
80
+ errBlock?: Ast[] | Ast; // todo: エラー監視の中でのみ使われる
81
+ cases?: any[]; // 条件分岐
82
+ operator?: string; // 演算子の場合
83
+ left?: Ast | Ast[]; // 演算子の場合
84
+ right?: Ast | Ast[]; // 演算子の場合
85
+ // eslint-disable-next-line camelcase
86
+ false_block?: Ast[] | Ast; // if
87
+ from?: Ast[] | Ast; // for
88
+ to?: Ast[] | Ast; // for
89
+ inc?: Ast[] | Ast | null; // for
90
+ word?: Ast | null; // for
91
+ name?: Token | Ast | null | string;
92
+ names?: Ast[];
93
+ args?: Ast[]; // 関数の引数
94
+ asyncFn?: boolean; // 関数の定義
95
+ meta?: any; // 関数の定義
96
+ setter?: boolean; // 関数の定義
97
+ index?: Ast[]; // 配列へのアクセスに利用
98
+ josi?: string;
99
+ value?: any;
100
+ mode?: string; // 文字列の展開などで利用
101
+ line: number;
102
+ column?: number;
103
+ file?: string;
104
+ startOffset?: number | undefined;
105
+ endOffset?: number | undefined;
106
+ rawJosi?: string;
107
+ vartype?: string;
108
+ end?: {
109
+ startOffset: number | undefined;
110
+ endOffset: number | undefined;
111
+ line?: number;
112
+ column?: number;
113
+ }
114
+ tag?: string;
115
+ genMode?: string;
116
+ checkInit?: boolean;
117
+ options?: { [key: string]: boolean };
118
+ }
119
+
120
+ export interface SourceMap {
121
+ startOffset: number | undefined;
122
+ endOffset: number | undefined;
123
+ file: string | undefined;
124
+ line: number;
125
+ column: number;
126
+ }
127
+
128
+ /**
129
+ * コンパイルオプション
130
+ */
131
+ export class CompilerOptions {
132
+ resetEnv: boolean; // 現在の環境をリセット
133
+ testOnly: boolean; // テストだけを実行する
134
+ resetAll: boolean; // 全ての環境をリセット
135
+ preCode: string; // 環境を構築するためのコード
136
+ nakoGlobal: NakoGlobal | null; // 実行に使う環境
137
+ constructor (initObj: any = {}) {
138
+ this.testOnly = initObj.testOnly || false
139
+ this.resetEnv = initObj.resetEnv || false
140
+ this.resetAll = initObj.resetAll || false
141
+ this.preCode = initObj.preCode || ''
142
+ this.nakoGlobal = initObj.nakoGlobal || null
143
+ }
144
+ }
145
+
146
+ export type NakoComEventName = 'finish' | 'beforeRun' | 'beforeGenerate' | 'afterGenerate' | 'beforeParse'
147
+
148
+ export interface NakoEvent {
149
+ eventName: NakoComEventName
150
+ callback: (event: any) => void
151
+ }