nadesiko3 3.3.4 → 3.3.7
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 +1 -0
- package/batch/command_nakopad.txt +1 -0
- package/demo/browsers.html +1 -1
- package/demo/nako3/taberu.nako3 +5 -0
- package/doc/browsers.md +1 -1
- package/package.json +1 -1
- package/release/_hash.txt +24 -24
- package/release/_script-tags.txt +14 -14
- 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/editor.js +1 -1
- package/release/nako_gen_async.js +1 -1
- package/release/nako_gen_async.js.LICENSE.txt +20 -0
- package/release/plugin_caniuse.js +1 -1
- package/release/stats.json +1 -1
- package/release/version.js +1 -1
- package/release/wnako3.js +1 -1
- package/src/browsers.mjs +1 -1
- package/src/browsers.txt +0 -1
- package/src/cnako3mod.mjs +88 -64
- package/src/nako3.mjs +72 -53
- package/src/nako_gen.mjs +6 -12
- package/src/nako_global.mjs +2 -2
- package/src/nako_lex_rules.mjs +1 -1
- package/src/nako_lexer.mjs +83 -22
- package/src/nako_parser3.mjs +144 -33
- package/src/nako_parser_base.mjs +75 -6
- package/src/nako_version.mjs +2 -2
- package/src/plugin_system.mjs +27 -9
- package/test/common/nako_lexer_test.mjs +33 -0
- package/test/common/plugin_system_test.mjs +1 -1
- package/test/common/variable_scope_test.mjs +13 -0
- package/test/node/error_message_test.mjs +5 -3
- package/test/node/plugin_test.mjs +21 -3
- package/test/node/scope1.nako3 +10 -0
- package/test/node/scope2.nako3 +12 -0
- package/test/node/wnako3_editor_test.mjs +12 -0
- package/tools/nako3edit/index.nako3 +3 -0
package/src/browsers.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default {"and_chr":["100"],"and_ff":["99"],"and_qq":["10.4"],"and_uc":["12.12"],"android":["100"],"baidu":["7.12"],"chrome":["100","99","98","97"],"edge":["100","99","98"],"firefox":["99","98","97","91"],"ios_saf":["15.4","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.9.0","16.14.0","14.19.0"
|
|
1
|
+
export default {"and_chr":["100"],"and_ff":["99"],"and_qq":["10.4"],"and_uc":["12.12"],"android":["100"],"baidu":["7.12"],"chrome":["100","99","98","97"],"edge":["100","99","98"],"firefox":["99","98","97","91"],"ios_saf":["15.4","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.9.0","16.14.0","14.19.0"],"op_mini":["all"],"op_mob":["64"],"opera":["83","82"],"safari":["15.4","15.2-15.3","14.1"],"samsung":["16.0","15.0"]}
|
package/src/browsers.txt
CHANGED
package/src/cnako3mod.mjs
CHANGED
|
@@ -11,7 +11,6 @@ import PluginNode from './plugin_node.mjs'
|
|
|
11
11
|
import { NakoImportError } from './nako_errors.mjs'
|
|
12
12
|
import app from './commander_ja.mjs'
|
|
13
13
|
import nakoVersion from './nako_version.mjs'
|
|
14
|
-
import fetch from 'node-fetch'
|
|
15
14
|
|
|
16
15
|
// __dirname のために
|
|
17
16
|
import url from 'url'
|
|
@@ -131,16 +130,19 @@ export class CNako3 extends NakoCompiler {
|
|
|
131
130
|
this.cnakoMan(opt.man)
|
|
132
131
|
return
|
|
133
132
|
}
|
|
134
|
-
|
|
133
|
+
// 対応ブラウザを表示する
|
|
134
|
+
if (opt.browsers) {
|
|
135
135
|
this.cnakoBrowsers()
|
|
136
136
|
return
|
|
137
137
|
}
|
|
138
138
|
if (opt.mainfile) { this.filename = opt.mainfile }
|
|
139
|
-
|
|
139
|
+
// REPLを実行する
|
|
140
|
+
if (opt.repl) {
|
|
140
141
|
this.cnakoRepl(opt)
|
|
141
142
|
return
|
|
142
143
|
}
|
|
143
|
-
|
|
144
|
+
// ワンライナーで実行する
|
|
145
|
+
if (opt.one_liner) {
|
|
144
146
|
this.cnakoOneLiner(opt)
|
|
145
147
|
return
|
|
146
148
|
}
|
|
@@ -151,26 +153,38 @@ export class CNako3 extends NakoCompiler {
|
|
|
151
153
|
await this.nakoCompile(opt, src, false)
|
|
152
154
|
return
|
|
153
155
|
}
|
|
156
|
+
|
|
157
|
+
// ASTを出力する
|
|
154
158
|
if (opt.ast) {
|
|
159
|
+
try {
|
|
160
|
+
await this.loadDependencies(src, opt.mainfile, '')
|
|
161
|
+
} catch (e) {
|
|
162
|
+
if (this.numFailures > 0) { process.exit(1) }
|
|
163
|
+
}
|
|
155
164
|
this.outputAST(opt, src)
|
|
156
165
|
return
|
|
157
166
|
}
|
|
158
|
-
|
|
159
|
-
|
|
167
|
+
|
|
168
|
+
// テストを実行する
|
|
169
|
+
if (opt.test) {
|
|
170
|
+
try {
|
|
160
171
|
await this.loadDependencies(src, opt.mainfile, '')
|
|
161
172
|
this.test(src, opt.mainfile)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
await this.run(src, opt.mainfile)
|
|
165
|
-
}
|
|
166
|
-
if (opt.test && this.numFailures > 0) {
|
|
173
|
+
return
|
|
174
|
+
} catch (e) {
|
|
167
175
|
process.exit(1)
|
|
168
176
|
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ファイルを読んで実行する
|
|
180
|
+
try {
|
|
181
|
+
await this.run(src, opt.mainfile) // run はコンパイルと実行を行うメソッド
|
|
182
|
+
if (this.numFailures > 0) { process.exit(1) }
|
|
169
183
|
} catch (e) {
|
|
184
|
+
// エラーメッセージはloggerへ送られるため無視してよい
|
|
170
185
|
if (opt.debug || opt.trace) {
|
|
171
186
|
throw e
|
|
172
187
|
}
|
|
173
|
-
// エラーメッセージはloggerへ送られるため無視してよい
|
|
174
188
|
}
|
|
175
189
|
}
|
|
176
190
|
|
|
@@ -181,8 +195,9 @@ export class CNako3 extends NakoCompiler {
|
|
|
181
195
|
* @param {boolean} isTest
|
|
182
196
|
*/
|
|
183
197
|
async nakoCompile (opt, src, isTest) {
|
|
184
|
-
//
|
|
198
|
+
// 依存ライブラリなどを読み込む
|
|
185
199
|
await this.loadDependencies(src, this.filename, '')
|
|
200
|
+
// JSにコンパイル
|
|
186
201
|
const jscode = this.compileStandalone(src, this.filename, isTest)
|
|
187
202
|
console.log(opt.output)
|
|
188
203
|
fs.writeFileSync(opt.output, jscode, 'utf-8')
|
|
@@ -301,79 +316,88 @@ export class CNako3 extends NakoCompiler {
|
|
|
301
316
|
console.log(fs.readFileSync(fileMD, 'utf-8'))
|
|
302
317
|
}
|
|
303
318
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
* @param {string} filename
|
|
307
|
-
* @param {string} preCode
|
|
308
|
-
*/
|
|
309
|
-
async loadDependencies (code, filename, preCode) {
|
|
319
|
+
// (js|nako3) loader
|
|
320
|
+
getLoaderTools() {
|
|
310
321
|
/** @type {string[]} */
|
|
311
322
|
const log = []
|
|
312
|
-
const tools = {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
return { filePath: jspath, type: 'js' }
|
|
323
|
+
const tools = {}
|
|
324
|
+
tools.resolvePath = (name, token) => {
|
|
325
|
+
// JSプラグインのパスを解決する
|
|
326
|
+
if (/\.(js|mjs)(\.txt)?$/.test(name) || /^[^.]*$/.test(name)) {
|
|
327
|
+
const jspath = CNako3.findJSPluginFile(name, this.filename, __dirname, log)
|
|
328
|
+
if (jspath === '') {
|
|
329
|
+
throw new NakoImportError(`ファイル『${name}』が見つかりません。以下のパスを検索しました。\n${log.join('\n')}`, token.file, token.line)
|
|
321
330
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
331
|
+
return { filePath: jspath, type: 'js' }
|
|
332
|
+
}
|
|
333
|
+
// なでしこプラグインのパスを解決する
|
|
334
|
+
if (/\.nako3?(\.txt)?$/.test(name)) {
|
|
335
|
+
if (path.isAbsolute(name)) {
|
|
336
|
+
return { filePath: path.resolve(name), type: 'nako3' }
|
|
337
|
+
} else {
|
|
338
|
+
// filename が undefined のとき token.file が undefined になる。
|
|
339
|
+
if (token.file === undefined) {
|
|
340
|
+
throw new Error('ファイル名を指定してください。')
|
|
332
341
|
}
|
|
342
|
+
return { filePath: path.resolve(path.join(path.dirname(token.file), name)), type: 'nako3' }
|
|
333
343
|
}
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
|
|
344
|
+
}
|
|
345
|
+
return { filePath: name, type: 'invalid' }
|
|
346
|
+
}
|
|
347
|
+
tools.readNako3 = (name, token) => {
|
|
337
348
|
if (!fs.existsSync(name)) {
|
|
338
349
|
throw new NakoImportError(`ファイル ${name} が存在しません。`, token.file, token.line)
|
|
339
350
|
}
|
|
340
351
|
return { sync: true, value: fs.readFileSync(name).toString() }
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
}
|
|
352
|
+
}
|
|
353
|
+
tools.readJs = (filePath, token) => {
|
|
354
|
+
const content = {sync: false, value: null}
|
|
355
|
+
if (process.platform === 'win32') {
|
|
356
|
+
if (filePath.substring(1, 3) === ':\\') {
|
|
357
|
+
filePath = 'file://' + filePath
|
|
348
358
|
}
|
|
349
|
-
content.value = (
|
|
350
|
-
new Promise((resolve, reject) => {
|
|
351
|
-
import(filePath).then((mod) => {
|
|
352
|
-
// プラグインは export default で宣言されている? (moduleプラグインの場合)
|
|
353
|
-
const obj = Object.assign({}, mod)
|
|
354
|
-
resolve(() => { return obj.default })
|
|
355
|
-
}).catch((err) => {
|
|
356
|
-
const err2 = new NakoImportError(`ファイル『${filePath}』が読み込めません。${err}`, token.file, token.line)
|
|
357
|
-
reject(err2)
|
|
358
|
-
})
|
|
359
|
-
})
|
|
360
|
-
)
|
|
361
|
-
return content
|
|
362
359
|
}
|
|
360
|
+
content.value = (
|
|
361
|
+
new Promise((resolve, reject) => {
|
|
362
|
+
import(filePath).then((mod) => {
|
|
363
|
+
// プラグインは export default で宣言されている? (moduleプラグインの場合)
|
|
364
|
+
const obj = Object.assign({}, mod)
|
|
365
|
+
resolve(() => { return obj.default })
|
|
366
|
+
}).catch((err) => {
|
|
367
|
+
const err2 = new NakoImportError(`ファイル『${filePath}』が読み込めません。${err}`, token.file, token.line)
|
|
368
|
+
reject(err2)
|
|
369
|
+
})
|
|
370
|
+
})
|
|
371
|
+
)
|
|
372
|
+
return content
|
|
363
373
|
}
|
|
364
|
-
return
|
|
374
|
+
return tools
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* @param {string} code
|
|
379
|
+
* @param {string} filename
|
|
380
|
+
* @param {string} preCode
|
|
381
|
+
* @returns {Promise<void>}
|
|
382
|
+
*/
|
|
383
|
+
async loadDependencies (code, filename, preCode) {
|
|
384
|
+
const tools = this.getLoaderTools()
|
|
385
|
+
await super._loadDependencies(code, filename, preCode, tools)
|
|
365
386
|
}
|
|
366
387
|
|
|
367
388
|
/**
|
|
368
389
|
* @param {string} code
|
|
369
390
|
* @param {string} fname
|
|
370
391
|
* @param {string} [preCode]
|
|
392
|
+
* @returns {Promise<nakoGlobal>}
|
|
371
393
|
*/
|
|
372
394
|
async run (code, fname, preCode = '') {
|
|
373
395
|
// 取り込む文の処理
|
|
374
|
-
|
|
396
|
+
try {
|
|
397
|
+
await this.loadDependencies(code, fname, preCode)
|
|
398
|
+
} catch(err) {
|
|
375
399
|
this.logger.error(err)
|
|
376
|
-
}
|
|
400
|
+
}
|
|
377
401
|
// 実行
|
|
378
402
|
return this._runEx(code, fname, {}, preCode)
|
|
379
403
|
}
|
package/src/nako3.mjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { NakoParser } from './nako_parser3.mjs'
|
|
6
6
|
import { NakoLexer } from './nako_lexer.mjs'
|
|
7
7
|
import { NakoPrepare } from './nako_prepare.mjs'
|
|
8
|
-
import {
|
|
8
|
+
import { generateJS } from './nako_gen.mjs'
|
|
9
9
|
import { NakoGenASync } from './nako_gen_async.mjs'
|
|
10
10
|
import NakoIndent from './nako_indent.mjs'
|
|
11
11
|
import { convertDNCL } from './nako_from_dncl.mjs'
|
|
@@ -67,6 +67,7 @@ const cloneAsJSON = (x) => JSON.parse(JSON.stringify(x))
|
|
|
67
67
|
* line?: number
|
|
68
68
|
* column?: number
|
|
69
69
|
* }
|
|
70
|
+
* tag?: string
|
|
70
71
|
* genMode?: string
|
|
71
72
|
* checkInit?: boolean
|
|
72
73
|
* }} Ast
|
|
@@ -97,7 +98,7 @@ export class NakoCompiler {
|
|
|
97
98
|
/**
|
|
98
99
|
* @type {NakoGlobal[]}
|
|
99
100
|
*/
|
|
100
|
-
this.__globals = [] // 生成した NakoGlobalのインスタンスを保持
|
|
101
|
+
this.__globals = [] // 生成した NakoGlobal のインスタンスを保持
|
|
101
102
|
/** @type {Record<string, Record<string, NakoFunction>>} */
|
|
102
103
|
this.__module = {} // requireなどで取り込んだモジュールの一覧
|
|
103
104
|
/** @type {Record<string, NakoFunction>} */
|
|
@@ -178,8 +179,7 @@ export class NakoCompiler {
|
|
|
178
179
|
* プログラムが依存するファイルを再帰的に取得する。
|
|
179
180
|
* - .jsであれば評価してthis.addPluginFileを呼び出し、.nako3であればファイルをfetchしてdependenciesに保存し再帰する。
|
|
180
181
|
* - resolvePathはファイルを検索して正規化する必要がある。
|
|
181
|
-
* -
|
|
182
|
-
* (`instanceof Promise` はpolyfillで動作しない場合があるため、Promiseかどうかを明示する必要がある。)
|
|
182
|
+
* - readNako3やreadJsのsyncを確認してfalseならPromiseを返すので並列処理し、そうでなければ同期的に処理する。
|
|
183
183
|
* - readNako3はソースコードを返す。readJsはrequireあるいはevalする関数を返す。
|
|
184
184
|
* @param {string} code
|
|
185
185
|
* @param {string} filename
|
|
@@ -196,9 +196,50 @@ export class NakoCompiler {
|
|
|
196
196
|
/** @type {NakoCompiler['dependencies']} */
|
|
197
197
|
const dependencies = {}
|
|
198
198
|
const compiler = new NakoCompiler({ useBasicPlugin: true })
|
|
199
|
-
|
|
199
|
+
|
|
200
|
+
const loadJS = (item, tasks) => {
|
|
201
|
+
// jsならプラグインとして読み込む。
|
|
202
|
+
const obj = tools.readJs(item.filePath, item.firstToken)
|
|
203
|
+
if (obj.sync) {
|
|
204
|
+
dependencies[item.filePath].addPluginFile = () => {
|
|
205
|
+
this.addPluginFile(item.value, item.filePath, dependencies[item.filePath].funclist = obj.value(), false)
|
|
206
|
+
}
|
|
207
|
+
} else {
|
|
208
|
+
tasks.push(obj.value.then((res) => {
|
|
209
|
+
dependencies[item.filePath].addPluginFile = () => {
|
|
210
|
+
this.addPluginFile(item.value, item.filePath, dependencies[item.filePath].funclist = res(), false)
|
|
211
|
+
}
|
|
212
|
+
}))
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const loadNako3 = (item, tasks) => {
|
|
216
|
+
// nako3ならファイルを読んでdependenciesに保存する。
|
|
217
|
+
const content = tools.readNako3(item.filePath, item.firstToken)
|
|
218
|
+
/** @param {string} code */
|
|
219
|
+
const registerFile = (code) => {
|
|
220
|
+
// シンタックスハイライトの高速化のために、事前にファイルが定義する関数名のリストを取り出しておく。
|
|
221
|
+
// preDefineFuncはトークン列に変更を加えるため、事前にクローンしておく。
|
|
222
|
+
// 「プラグイン名設定」を行う (#956)
|
|
223
|
+
const modName = NakoLexer.filenameToModName(item.filePath)
|
|
224
|
+
code = `『${modName}』にプラグイン名設定;` + code + ';『メイン』にプラグイン名設定;'
|
|
225
|
+
const tokens = this.rawtokenize(code, 0, item.filePath)
|
|
226
|
+
dependencies[item.filePath].tokens = tokens
|
|
227
|
+
/** @type {import('./nako_lexer.mjs').FuncList} */
|
|
228
|
+
const funclist = {}
|
|
229
|
+
NakoLexer.preDefineFunc(cloneAsJSON(tokens), this.logger, funclist)
|
|
230
|
+
dependencies[item.filePath].funclist = funclist
|
|
231
|
+
|
|
232
|
+
// 再帰
|
|
233
|
+
return loadRec(code, item.filePath, '')
|
|
234
|
+
}
|
|
235
|
+
if (content.sync) {
|
|
236
|
+
registerFile(content.value)
|
|
237
|
+
} else {
|
|
238
|
+
tasks.push(content.value.then((res) => registerFile(res)))
|
|
239
|
+
}
|
|
240
|
+
}
|
|
200
241
|
/** @param {string} code @param {string} filename @param {string} preCode @returns {Promise<unknown> | void} */
|
|
201
|
-
const
|
|
242
|
+
const loadRec = (code, filename, preCode) => {
|
|
202
243
|
/** @type {Promise<unknown>[]} */
|
|
203
244
|
const tasks = []
|
|
204
245
|
// 取り込みが必要な情報一覧を調べる(トークン分割して、取り込みタグを得る)
|
|
@@ -217,55 +258,21 @@ export class NakoCompiler {
|
|
|
217
258
|
// 初回の読み込み
|
|
218
259
|
dependencies[item.filePath] = { tokens: [], alias: new Set([item.value]), addPluginFile: () => {}, funclist: {} }
|
|
219
260
|
if (item.type === 'js' || item.type === 'mjs') {
|
|
220
|
-
|
|
221
|
-
const obj = tools.readJs(item.filePath, item.firstToken)
|
|
222
|
-
if (obj.sync) {
|
|
223
|
-
dependencies[item.filePath].addPluginFile = () => {
|
|
224
|
-
this.addPluginFile(item.value, item.filePath, dependencies[item.filePath].funclist = obj.value(), false)
|
|
225
|
-
}
|
|
226
|
-
} else {
|
|
227
|
-
tasks.push(obj.value.then((res) => {
|
|
228
|
-
dependencies[item.filePath].addPluginFile = () => {
|
|
229
|
-
this.addPluginFile(item.value, item.filePath, dependencies[item.filePath].funclist = res(), false)
|
|
230
|
-
}
|
|
231
|
-
}))
|
|
232
|
-
}
|
|
261
|
+
loadJS(item, tasks)
|
|
233
262
|
} else if (item.type === 'nako3') {
|
|
234
|
-
|
|
235
|
-
const content = tools.readNako3(item.filePath, item.firstToken)
|
|
236
|
-
/** @param {string} code */
|
|
237
|
-
const registerFile = (code) => {
|
|
238
|
-
// シンタックスハイライトの高速化のために、事前にファイルが定義する関数名のリストを取り出しておく。
|
|
239
|
-
// preDefineFuncはトークン列に変更を加えるため、事前にクローンしておく。
|
|
240
|
-
// 「プラグイン名設定」を行う (#956)
|
|
241
|
-
code = `『${item.filePath}』にプラグイン名設定;` + code + ';『メイン』にプラグイン名設定;'
|
|
242
|
-
const tokens = this.rawtokenize(code, 0, item.filePath)
|
|
243
|
-
dependencies[item.filePath].tokens = tokens
|
|
244
|
-
/** @type {import('./nako_lexer').FuncList} */
|
|
245
|
-
const funclist = {}
|
|
246
|
-
NakoLexer.preDefineFunc(cloneAsJSON(tokens), this.logger, funclist)
|
|
247
|
-
dependencies[item.filePath].funclist = funclist
|
|
248
|
-
|
|
249
|
-
// 再帰
|
|
250
|
-
return inner(code, item.filePath, '')
|
|
251
|
-
}
|
|
252
|
-
if (content.sync) {
|
|
253
|
-
registerFile(content.value)
|
|
254
|
-
} else {
|
|
255
|
-
tasks.push(content.value.then((res) => registerFile(res)))
|
|
256
|
-
}
|
|
263
|
+
loadNako3(item, tasks)
|
|
257
264
|
} else {
|
|
258
265
|
throw new NakoImportError(`ファイル『${item.value}』を読み込めません。ファイルが存在しないか未対応の拡張子です。`, item.firstToken.file, item.firstToken.line)
|
|
259
266
|
}
|
|
260
267
|
}
|
|
261
|
-
|
|
262
268
|
if (tasks.length > 0) {
|
|
263
269
|
return Promise.all(tasks)
|
|
264
270
|
}
|
|
271
|
+
return undefined
|
|
265
272
|
}
|
|
266
273
|
|
|
267
274
|
try {
|
|
268
|
-
const result =
|
|
275
|
+
const result = loadRec(code, filename, preCode)
|
|
269
276
|
|
|
270
277
|
// 非同期な場合のエラーハンドリング
|
|
271
278
|
if (result !== undefined) {
|
|
@@ -303,7 +310,6 @@ export class NakoCompiler {
|
|
|
303
310
|
const { code: code2, insertedLines, deletedLines } = NakoIndent.convert(code, filename)
|
|
304
311
|
// DNCL構文 (#1140)
|
|
305
312
|
const code3 = convertDNCL(code2, filename)
|
|
306
|
-
|
|
307
313
|
// 全角半角の統一処理
|
|
308
314
|
const preprocessed = this.prepare.convert(code3)
|
|
309
315
|
|
|
@@ -312,15 +318,14 @@ export class NakoCompiler {
|
|
|
312
318
|
const offsetToLineColumn = new OffsetToLineColumn(code)
|
|
313
319
|
|
|
314
320
|
// トークン分割
|
|
315
|
-
/** @type {import('./nako_lexer').Token[]} */
|
|
321
|
+
/** @type {import('./nako_lexer.mjs').Token[]} */
|
|
316
322
|
let tokens
|
|
317
323
|
try {
|
|
318
|
-
tokens = this.lexer.
|
|
324
|
+
tokens = this.lexer.tokenize(preprocessed.map((v) => v.text).join(''), line, filename)
|
|
319
325
|
} catch (err) {
|
|
320
326
|
if (!(err instanceof InternalLexerError)) {
|
|
321
327
|
throw err
|
|
322
328
|
}
|
|
323
|
-
|
|
324
329
|
// エラー位置をソースコード上の位置に変換して返す
|
|
325
330
|
const dest = indentationSyntaxSourceMapping.map(tokenizationSourceMapping.map(err.preprocessedCodeStartOffset), tokenizationSourceMapping.map(err.preprocessedCodeEndOffset))
|
|
326
331
|
/** @type {number | undefined} */
|
|
@@ -360,10 +365,12 @@ export class NakoCompiler {
|
|
|
360
365
|
* 単語の属性を構文解析に先立ち補正する
|
|
361
366
|
* @param {TokenWithSourceMap[]} tokens トークンのリスト
|
|
362
367
|
* @param {boolean} isFirst 最初の呼び出しかどうか
|
|
368
|
+
* @param {string} filename
|
|
363
369
|
* @returns コード (なでしこ)
|
|
364
370
|
*/
|
|
365
|
-
converttoken (tokens, isFirst) {
|
|
366
|
-
|
|
371
|
+
converttoken (tokens, isFirst, filename) {
|
|
372
|
+
const tok = this.lexer.replaceTokens(tokens, isFirst, filename)
|
|
373
|
+
return tok
|
|
367
374
|
}
|
|
368
375
|
|
|
369
376
|
/**
|
|
@@ -430,7 +437,7 @@ export class NakoCompiler {
|
|
|
430
437
|
const commentTokens = tokens.filter((t) => t.type === 'line_comment' || t.type === 'range_comment')
|
|
431
438
|
.map((v) => ({ ...v })) // clone
|
|
432
439
|
|
|
433
|
-
tokens = this.converttoken(tokens, false)
|
|
440
|
+
tokens = this.converttoken(tokens, false, filename)
|
|
434
441
|
|
|
435
442
|
return { tokens, commentTokens }
|
|
436
443
|
}
|
|
@@ -502,13 +509,23 @@ export class NakoCompiler {
|
|
|
502
509
|
t.type = 'require'
|
|
503
510
|
}
|
|
504
511
|
}
|
|
512
|
+
if (requireStatementTokens.length >= 3) {
|
|
513
|
+
// modList を更新
|
|
514
|
+
for (let i = 0; i < requireStatementTokens.length; i += 3) {
|
|
515
|
+
let modName = requireStatementTokens[i + 1].value
|
|
516
|
+
modName = NakoLexer.filenameToModName(modName)
|
|
517
|
+
if (this.lexer.modList.indexOf(modName) < 0) {
|
|
518
|
+
this.lexer.modList.push(modName)
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
505
522
|
|
|
506
523
|
// convertTokenで消されるコメントのトークンを残す
|
|
507
524
|
/** @type {TokenWithSourceMap[]} */
|
|
508
525
|
const commentTokens = tokens.filter((t) => t.type === 'line_comment' || t.type === 'range_comment')
|
|
509
526
|
.map((v) => ({ ...v })) // clone
|
|
510
527
|
|
|
511
|
-
tokens = this.converttoken(tokens, true)
|
|
528
|
+
tokens = this.converttoken(tokens, true, filename)
|
|
512
529
|
|
|
513
530
|
for (let i = 0; i < tokens.length; i++) {
|
|
514
531
|
if (tokens[i].type === 'code') {
|
|
@@ -543,7 +560,7 @@ export class NakoCompiler {
|
|
|
543
560
|
let ast
|
|
544
561
|
try {
|
|
545
562
|
this.parser.genMode = 'sync' // set default
|
|
546
|
-
ast = this.parser.parse(lexerOutput.tokens)
|
|
563
|
+
ast = this.parser.parse(lexerOutput.tokens, filename)
|
|
547
564
|
} catch (err) {
|
|
548
565
|
if (typeof err.startOffset !== 'number') {
|
|
549
566
|
throw NakoSyntaxError.fromNode(err.message, lexerOutput.tokens[this.parser.index])
|
|
@@ -643,6 +660,7 @@ export class NakoCompiler {
|
|
|
643
660
|
* @param {boolean} isReset
|
|
644
661
|
* @param {boolean | string} isTest テストかどうか。stringの場合は1つのテストのみ。
|
|
645
662
|
* @param {string} [preCode]
|
|
663
|
+
* @returns {nakoGlobal}
|
|
646
664
|
*/
|
|
647
665
|
_run (code, fname, isReset, isTest, preCode = '') {
|
|
648
666
|
const opts = {
|
|
@@ -665,6 +683,7 @@ export class NakoCompiler {
|
|
|
665
683
|
* @param {Partial<CompilerOptions>} opts
|
|
666
684
|
* @param {string} [preCode]
|
|
667
685
|
* @param {NakoGlobal} [nakoGlobal] ナデシコ命令でスコープを共有するため
|
|
686
|
+
* @returns {nakoGlobal}
|
|
668
687
|
*/
|
|
669
688
|
_runEx (code, fname, opts, preCode = '', nakoGlobal) {
|
|
670
689
|
// コンパイル
|
package/src/nako_gen.mjs
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { NakoSyntaxError, NakoError, NakoRuntimeError } from './nako_errors.mjs'
|
|
8
|
+
import { NakoLexer } from './nako_lexer.mjs'
|
|
8
9
|
import nakoVersion from './nako_version.mjs'
|
|
9
10
|
const isIE11 = () => {
|
|
10
11
|
if (typeof(window) == 'object' && window.navigator && window.navigator.userAgent) {
|
|
@@ -359,7 +360,7 @@ export class NakoGen {
|
|
|
359
360
|
josi: t.name.meta.josi,
|
|
360
361
|
fn: '',
|
|
361
362
|
type: 'func',
|
|
362
|
-
asyncFn:
|
|
363
|
+
asyncFn: t.asyncFn
|
|
363
364
|
}
|
|
364
365
|
funcList.push({name: name, node: t})
|
|
365
366
|
}
|
|
@@ -390,16 +391,7 @@ export class NakoGen {
|
|
|
390
391
|
}
|
|
391
392
|
this.varsSet = { isFunction: false, names: initialNames, readonly: new Set() }
|
|
392
393
|
this.varslistSet = this.__self.__varslist.map((v) => ({ isFunction: false, names: new Set(Object.keys(v)), readonly: new Set() }))
|
|
393
|
-
this.varslistSet[2] = this.varsSet
|
|
394
|
-
|
|
395
|
-
// 非同期関数(asyncFn)があるかどうかテストする
|
|
396
|
-
// 後ほど改めて再度同じ関数を呼ぶため、警告などは抑止する
|
|
397
|
-
const tmpWarn = this.warnUndefinedVar
|
|
398
|
-
this.warnUndefinedVar = false // 未定義の変数の警告を抑止 #1192
|
|
399
|
-
for (let ff of funcList) {
|
|
400
|
-
this.convDefFuncCommon(ff.node, ff.name)
|
|
401
|
-
}
|
|
402
|
-
this.warnUndefinedVar = tmpWarn
|
|
394
|
+
this.varslistSet[2] = this.varsSet
|
|
403
395
|
}
|
|
404
396
|
|
|
405
397
|
/**
|
|
@@ -436,6 +428,8 @@ export class NakoGen {
|
|
|
436
428
|
case 'nop':
|
|
437
429
|
break
|
|
438
430
|
case 'block':
|
|
431
|
+
const modName = NakoLexer.filenameToModName(node.file)
|
|
432
|
+
code += `;__self.__modName='${modName}';\n`
|
|
439
433
|
for (let i = 0; i < node.block.length; i++) {
|
|
440
434
|
const b = node.block[i]
|
|
441
435
|
code += this._convGen(b, false)
|
|
@@ -1184,7 +1178,7 @@ export class NakoGen {
|
|
|
1184
1178
|
throw NakoSyntaxError.fromNode(`関数『${funcName}』が見当たりません。有効プラグイン=[` + this.getPluginList().join(', ') + ']', node)
|
|
1185
1179
|
}
|
|
1186
1180
|
// どの関数を呼び出すのか関数を特定する
|
|
1187
|
-
/** @type {import('./nako3').NakoFunction} */
|
|
1181
|
+
/** @type {import('./nako3.mjs').NakoFunction} */
|
|
1188
1182
|
let func
|
|
1189
1183
|
if (res.i === 0) { // plugin function
|
|
1190
1184
|
func = this.__self.funclist[funcName]
|
package/src/nako_global.mjs
CHANGED
|
@@ -6,8 +6,8 @@ import { NakoRuntimeError } from './nako_errors.mjs'
|
|
|
6
6
|
*/
|
|
7
7
|
export class NakoGlobal {
|
|
8
8
|
/**
|
|
9
|
-
* @param {import('./nako3')} compiler
|
|
10
|
-
* @param {import('./nako_gen')} gen
|
|
9
|
+
* @param {import('./nako3.mjs')} compiler
|
|
10
|
+
* @param {import('./nako_gen.mjs')} gen
|
|
11
11
|
*/
|
|
12
12
|
constructor (compiler, gen) {
|
|
13
13
|
// ユーザーのプログラムから編集される変数
|
package/src/nako_lex_rules.mjs
CHANGED
|
@@ -39,7 +39,7 @@ export const rules = [
|
|
|
39
39
|
{ name: 'もし', pattern: /^もしも?/ },
|
|
40
40
|
// 「ならば」は助詞として定義している
|
|
41
41
|
{ name: '違えば', pattern: /^違(えば)?/ },
|
|
42
|
-
// 「回」「間」「繰返」「反復」「抜」「続」「戻」「代入」「条件分岐」などは
|
|
42
|
+
// 「回」「間」「繰返」「反復」「抜」「続」「戻」「代入」「条件分岐」などは NakoLexer._replaceWord で word から変換
|
|
43
43
|
// @see nako_reserved_words.js
|
|
44
44
|
{ name: 'shift_r0', pattern: /^>>>/ },
|
|
45
45
|
{ name: 'shift_r', pattern: /^>>/ },
|