nadesiko3 3.3.13 → 3.3.16
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/README.md +12 -0
- package/demo/nako3/aaa/bbb/ccc.nako3 +2 -0
- package/demo/nako3/aaa/p1.nako3 +4 -0
- package/demo/nako3/aaa.nako3 +5 -0
- package/package.json +1 -1
- package/release/_hash.txt +8 -8
- package/release/_script-tags.txt +14 -14
- package/release/stats.json +1 -1
- package/release/version.js +1 -1
- package/release/wnako3.js +1 -1
- package/src/cnako3mod.mjs +143 -71
- package/src/nako3.mjs +19 -20
- package/src/nako_gen.mjs +25 -33
- package/src/nako_version.mjs +2 -2
- package/src/plugin_node.mjs +12 -10
- package/src/wnako3.mjs +53 -23
- package/tools/nako3edit/run.mjs +1 -1
package/src/cnako3mod.mjs
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
/**
|
|
3
2
|
* コマンドライン版のなでしこ3をモジュールとして定義
|
|
4
3
|
* 実際には cnako3.js から読み込まれる
|
|
5
4
|
*/
|
|
6
5
|
import fs from 'fs'
|
|
7
6
|
import { exec } from 'child_process'
|
|
8
|
-
import path from 'path'
|
|
7
|
+
import path, { resolve } from 'path'
|
|
9
8
|
import { NakoCompiler } from './nako3.mjs'
|
|
10
9
|
import PluginNode from './plugin_node.mjs'
|
|
11
10
|
import { NakoImportError } from './nako_errors.mjs'
|
|
@@ -23,7 +22,7 @@ export class CNako3 extends NakoCompiler {
|
|
|
23
22
|
super({ useBasicPlugin: true })
|
|
24
23
|
this.silent = false
|
|
25
24
|
if (!opts.nostd) {
|
|
26
|
-
this.addPluginFile('PluginNode', path.join(__dirname, 'plugin_node.
|
|
25
|
+
this.addPluginFile('PluginNode', path.join(__dirname, 'plugin_node.mjs'), PluginNode)
|
|
27
26
|
}
|
|
28
27
|
this.__varslist[0]['ナデシコ種類'] = 'cnako3'
|
|
29
28
|
}
|
|
@@ -61,12 +60,23 @@ export class CNako3 extends NakoCompiler {
|
|
|
61
60
|
|
|
62
61
|
/**
|
|
63
62
|
* コマンドライン引数を解析
|
|
64
|
-
* @returns {{
|
|
63
|
+
* @returns {{
|
|
64
|
+
* warn: boolean,
|
|
65
|
+
* debug: boolean,
|
|
66
|
+
* compile: any | boolean,
|
|
67
|
+
* test: any | boolean,
|
|
68
|
+
* one_liner: any | boolean,
|
|
69
|
+
* trace: any | boolean,
|
|
70
|
+
* run: any | boolean,
|
|
71
|
+
* repl: any | boolean,
|
|
72
|
+
* source: any | string,
|
|
73
|
+
* mainfile: any | string,
|
|
74
|
+
* }}
|
|
65
75
|
*/
|
|
66
76
|
checkArguments () {
|
|
67
77
|
const app = this.registerCommands()
|
|
68
78
|
|
|
69
|
-
/** @type {import('./nako_logger').LogLevel} */
|
|
79
|
+
/** @type {import('./nako_logger.mjs').LogLevel} */
|
|
70
80
|
let logLevel = 'error'
|
|
71
81
|
if (app.trace) {
|
|
72
82
|
logLevel = 'trace'
|
|
@@ -99,21 +109,23 @@ export class CNako3 extends NakoCompiler {
|
|
|
99
109
|
}
|
|
100
110
|
args.mainfile = app.args[0]
|
|
101
111
|
args.output = app.output
|
|
112
|
+
|
|
113
|
+
// todo: ESModule 対応の '.mjs' のコードを履く #1217
|
|
114
|
+
const ext = '.js'
|
|
102
115
|
if (/\.(nako|nako3|txt|bak)$/.test(args.mainfile)) {
|
|
103
116
|
if (!args.output) {
|
|
104
117
|
if (args.test) {
|
|
105
|
-
args.output = args.mainfile.replace(/\.(nako|nako3)$/, '.spec
|
|
118
|
+
args.output = args.mainfile.replace(/\.(nako|nako3)$/, '.spec' + ext)
|
|
106
119
|
} else {
|
|
107
|
-
|
|
108
|
-
args.output = args.mainfile.replace(/\.(nako|nako3)$/, '.js')
|
|
120
|
+
args.output = args.mainfile.replace(/\.(nako|nako3)$/, ext)
|
|
109
121
|
}
|
|
110
122
|
}
|
|
111
123
|
} else {
|
|
112
124
|
if (!args.output) {
|
|
113
125
|
if (args.test) {
|
|
114
|
-
args.output = args.mainfile + '.spec
|
|
126
|
+
args.output = args.mainfile + '.spec' + ext
|
|
115
127
|
} else {
|
|
116
|
-
args.output = args.mainfile +
|
|
128
|
+
args.output = args.mainfile + ext
|
|
117
129
|
}
|
|
118
130
|
}
|
|
119
131
|
args.mainfile += '.nako3'
|
|
@@ -201,6 +213,28 @@ export class CNako3 extends NakoCompiler {
|
|
|
201
213
|
const jscode = this.compileStandalone(src, this.filename, isTest)
|
|
202
214
|
console.log(opt.output)
|
|
203
215
|
fs.writeFileSync(opt.output, jscode, 'utf-8')
|
|
216
|
+
|
|
217
|
+
/*
|
|
218
|
+
// 実行に必要なファイルをコピー
|
|
219
|
+
const nakoRuntime = __dirname
|
|
220
|
+
const outRuntime = path.join(path.dirname(opt.output), 'nako3runtime')
|
|
221
|
+
if (!fs.existsSync(outRuntime)) { fs.mkdirSync(outRuntime) }
|
|
222
|
+
for (let mod of ['nako_version.mjs', 'nako_errors.mjs', 'plugin_node.mjs']) {
|
|
223
|
+
fs.copyFileSync(path.join(nakoRuntime, mod), path.join(outRuntime, mod))
|
|
224
|
+
}
|
|
225
|
+
// todo: 必要に応じてnode_modulesをコピー (時間が掛かりすぎるのでコピーしない)
|
|
226
|
+
const dstModule = path.join(path.dirname(opt.output), 'node_modules')
|
|
227
|
+
const orgModule = path.join(__dirname, '..', 'node_modules')
|
|
228
|
+
if (!fs.existsSync(dstModule)) {
|
|
229
|
+
fs.mkdirSync(dstModule)
|
|
230
|
+
fse.copySync(path.join(orgModule), path.join(dstModule))
|
|
231
|
+
}
|
|
232
|
+
// or 以下のコピーだと依存ファイルがコピーされない package.jsonを見てコピーする必要がある
|
|
233
|
+
for (let mod of ['fs-extra', 'iconv-lite', 'opener', 'clipboardy', 'sendkeys-js']) {
|
|
234
|
+
fse.copySync(path.join(orgModule, mod), path.join(dstModule, mod))
|
|
235
|
+
}
|
|
236
|
+
*/
|
|
237
|
+
|
|
204
238
|
if (opt.run) {
|
|
205
239
|
exec(`node ${opt.output}`, function (err, stdout, stderr) {
|
|
206
240
|
if (err) { console.log('[ERROR]', stderr) }
|
|
@@ -321,43 +355,57 @@ export class CNako3 extends NakoCompiler {
|
|
|
321
355
|
/** @type {string[]} */
|
|
322
356
|
const log = []
|
|
323
357
|
const tools = {}
|
|
324
|
-
tools.resolvePath = (name, token) => {
|
|
325
|
-
//
|
|
326
|
-
|
|
327
|
-
|
|
358
|
+
tools.resolvePath = (name, token, fromFile) => {
|
|
359
|
+
// 最初に拡張子があるかどうかをチェック
|
|
360
|
+
// JSプラグインか?
|
|
361
|
+
if (/\.(js|mjs)(\.txt)?$/.test(name)) {
|
|
362
|
+
const jspath = CNako3.findJSPluginFile(name, fromFile, __dirname, log)
|
|
328
363
|
if (jspath === '') {
|
|
329
|
-
throw new NakoImportError(
|
|
364
|
+
throw new NakoImportError(`JSプラグイン『${name}』が見つかりません。以下のパスを検索しました。\n${log.join('\n')}`, token.file, token.line)
|
|
330
365
|
}
|
|
331
366
|
return { filePath: jspath, type: 'js' }
|
|
332
367
|
}
|
|
333
|
-
//
|
|
334
|
-
if (/\.nako3
|
|
368
|
+
// なでしこプラグインか?
|
|
369
|
+
if (/\.(nako3|nako)(\.txt)?$/.test(name)) {
|
|
335
370
|
if (path.isAbsolute(name)) {
|
|
336
371
|
return { filePath: path.resolve(name), type: 'nako3' }
|
|
337
372
|
} else {
|
|
338
373
|
// filename が undefined のとき token.file が undefined になる。
|
|
339
|
-
if (token.file === undefined) {
|
|
340
|
-
|
|
341
|
-
}
|
|
342
|
-
return { filePath: path.resolve(path.join(path.dirname(token.file), name)), type: 'nako3' }
|
|
374
|
+
if (token.file === undefined) { throw new Error('ファイル名を指定してください。') }
|
|
375
|
+
const dir = path.dirname(fromFile)
|
|
376
|
+
return { filePath: path.resolve(path.join(dir, name)), type: 'nako3' }
|
|
343
377
|
}
|
|
344
378
|
}
|
|
345
|
-
|
|
379
|
+
// 拡張子がない、あるいは、(.js|.mjs|.nako3|.nako)以外はJSモジュールと見なす
|
|
380
|
+
const jspath2 = CNako3.findJSPluginFile(name, fromFile, __dirname, log)
|
|
381
|
+
if (jspath2 === '') {
|
|
382
|
+
throw new NakoImportError(`JSプラグイン『${name}』が見つかりません。以下のパスを検索しました。\n${log.join('\n')}`, token.file, token.line)
|
|
383
|
+
}
|
|
384
|
+
return { filePath: jspath2, type: 'js' }
|
|
346
385
|
}
|
|
347
386
|
tools.readNako3 = (name, token) => {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
|
|
387
|
+
// ファイルチェックだけ先に実行
|
|
388
|
+
if (!fs.existsSync(name)) {
|
|
389
|
+
throw new NakoImportError(`ファイル ${name} が存在しません。`, token.file, token.line)
|
|
390
|
+
}
|
|
391
|
+
// 非同期で読み込む
|
|
392
|
+
const loader = {task: null}
|
|
393
|
+
loader.task = (new Promise((resolve, reject) => {
|
|
394
|
+
fs.readFile(name, {encoding: 'utf-8'}, (err, data) => {
|
|
395
|
+
if (err) { return reject(err) }
|
|
396
|
+
resolve(data)
|
|
397
|
+
})
|
|
398
|
+
}))
|
|
399
|
+
return loader
|
|
352
400
|
}
|
|
353
401
|
tools.readJs = (filePath, token) => {
|
|
354
|
-
const
|
|
402
|
+
const loader = {task: null}
|
|
355
403
|
if (process.platform === 'win32') {
|
|
356
404
|
if (filePath.substring(1, 3) === ':\\') {
|
|
357
405
|
filePath = 'file://' + filePath
|
|
358
406
|
}
|
|
359
407
|
}
|
|
360
|
-
|
|
408
|
+
loader.task = (
|
|
361
409
|
new Promise((resolve, reject) => {
|
|
362
410
|
import(filePath).then((mod) => {
|
|
363
411
|
// プラグインは export default で宣言されている? (moduleプラグインの場合)
|
|
@@ -369,7 +417,7 @@ export class CNako3 extends NakoCompiler {
|
|
|
369
417
|
})
|
|
370
418
|
})
|
|
371
419
|
)
|
|
372
|
-
return
|
|
420
|
+
return loader
|
|
373
421
|
}
|
|
374
422
|
return tools
|
|
375
423
|
}
|
|
@@ -412,87 +460,111 @@ export class CNako3 extends NakoCompiler {
|
|
|
412
460
|
*/
|
|
413
461
|
static findJSPluginFile (pname, filename, srcDir, log = []) {
|
|
414
462
|
log.length = 0
|
|
463
|
+
/** @type {Object<string,boolean>} */
|
|
415
464
|
const cachePath = {}
|
|
416
|
-
/**
|
|
417
|
-
|
|
465
|
+
/** キャッシュ付きでファイルがあるか検索
|
|
466
|
+
* @param {string} f
|
|
467
|
+
* @returns {boolean}
|
|
468
|
+
*/
|
|
469
|
+
const exists = (f) => {
|
|
418
470
|
// 同じパスを何度も検索することがないように
|
|
419
|
-
if (cachePath[f]) { return
|
|
420
|
-
cachePath[f] = true
|
|
421
|
-
log.push(f)
|
|
471
|
+
if (cachePath[f]) { return cachePath[f] }
|
|
422
472
|
const stat = fs.statSync(f, {throwIfNoEntry: false})
|
|
423
|
-
|
|
424
|
-
return
|
|
473
|
+
const b = !!(stat && stat.isFile())
|
|
474
|
+
return cachePath[f] = b
|
|
425
475
|
}
|
|
426
|
-
|
|
427
|
-
|
|
476
|
+
/** 普通にファイルをチェック
|
|
477
|
+
* @param {string} pathTest
|
|
478
|
+
* @param {string} desc
|
|
479
|
+
* @returns {boolean}
|
|
480
|
+
*/
|
|
481
|
+
const fCheck = (pathTest, desc) => {
|
|
428
482
|
// 素直に指定されたパスをチェック
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
return
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
483
|
+
const bExists = exists(pathTest)
|
|
484
|
+
log.push(`[${desc}] ${pathTest}, ${bExists}`)
|
|
485
|
+
return bExists
|
|
486
|
+
}
|
|
487
|
+
/** 通常 + package.json のパスを調べる
|
|
488
|
+
* @param {string} pathTest
|
|
489
|
+
* @param {string} desc
|
|
490
|
+
* @returns {string}
|
|
491
|
+
*/
|
|
492
|
+
const fCheckEx = (pathTest, desc) => {
|
|
493
|
+
// 直接JSファイルが指定された?
|
|
494
|
+
if (/\.(js|mjs)$/.test(pathTest)) {
|
|
495
|
+
if (fCheck(pathTest, desc)) { return pathTest }
|
|
496
|
+
}
|
|
497
|
+
// 指定パスのpackage.jsonを調べる
|
|
498
|
+
const json = path.join(pathTest, 'package.json')
|
|
499
|
+
if (fCheck(json, desc+'/package.json')) {
|
|
440
500
|
// package.jsonを見つけたので、メインファイルを調べて取り込む (CommonJSモジュール対策)
|
|
441
501
|
const json_txt = fs.readFileSync(json, 'utf-8')
|
|
442
502
|
const obj = JSON.parse(json_txt)
|
|
443
|
-
if (!obj['main']) { return
|
|
444
|
-
const mainFile = path.join(pathTest,
|
|
503
|
+
if (!obj['main']) { return '' }
|
|
504
|
+
const mainFile = path.resolve(path.join(pathTest, obj['main']))
|
|
445
505
|
return mainFile
|
|
446
506
|
}
|
|
447
|
-
return
|
|
507
|
+
return ''
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// URL指定か?
|
|
511
|
+
if (pname.substring(0, 8) === 'https://') {
|
|
512
|
+
return pname
|
|
448
513
|
}
|
|
449
514
|
// 各パスを検索していく
|
|
450
515
|
const p1 = pname.substring(0, 1)
|
|
451
516
|
// フルパス指定か?
|
|
452
|
-
if (p1 === '/' || pname.substring(1, 3).toLowerCase() === ':\\') {
|
|
453
|
-
|
|
454
|
-
const fileFullpath = fCheckEx(pname)
|
|
517
|
+
if (p1 === '/' || pname.substring(1, 3).toLowerCase() === ':\\' || pname.substring(0, 6) === 'file:/') {
|
|
518
|
+
const fileFullpath = fCheckEx(pname, 'fullpath')
|
|
455
519
|
if (fileFullpath) { return fileFullpath }
|
|
456
520
|
return '' // フルパスの場合別のフォルダは調べない
|
|
457
521
|
}
|
|
458
522
|
// 相対パスか?
|
|
459
523
|
if (p1 === '.' || pname.indexOf('/') >= 0) {
|
|
460
524
|
// 相対パス指定なので、なでしこのプログラムからの相対指定を調べる
|
|
461
|
-
const pathRelative = path.resolve(path.dirname(filename))
|
|
462
|
-
const fileRelative = fCheckEx(pathRelative)
|
|
525
|
+
const pathRelative = path.join(path.resolve(path.dirname(filename)), pname)
|
|
526
|
+
const fileRelative = fCheckEx(pathRelative, 'relpath')
|
|
463
527
|
if (fileRelative) { return fileRelative }
|
|
464
528
|
return '' // 相対パスの場合も別のフォルダは調べない
|
|
465
529
|
}
|
|
466
530
|
// plugin_xxx.mjs のようにファイル名のみが指定された場合のみ、いくつかのパスを調べる
|
|
467
531
|
// 母艦パス(元ファイルと同じフォルダ)か?
|
|
468
|
-
const
|
|
469
|
-
const fileScript = fCheckEx(
|
|
532
|
+
const testScriptPath = path.join(path.resolve(path.dirname(filename)), pname)
|
|
533
|
+
const fileScript = fCheckEx(testScriptPath, 'scriptPath')
|
|
470
534
|
if (fileScript) { return fileScript }
|
|
471
535
|
|
|
472
|
-
// ランタイムパス/src
|
|
473
|
-
const pathRuntimeSrc = path.resolve(srcDir) // cnako3mod.mjs は ランタイム/src に配置されていることが前提
|
|
474
|
-
const fileRuntimeSrc =
|
|
536
|
+
// ランタイムパス/src/<plugin>
|
|
537
|
+
const pathRuntimeSrc = path.join(path.resolve(srcDir), pname) // cnako3mod.mjs は ランタイム/src に配置されていることが前提
|
|
538
|
+
const fileRuntimeSrc = fCheckEx(pathRuntimeSrc, 'runtimeSrcPath')
|
|
475
539
|
if (fileRuntimeSrc) { return fileRuntimeSrc }
|
|
476
540
|
|
|
477
|
-
//
|
|
478
|
-
|
|
479
|
-
|
|
541
|
+
// 環境変数をチェック
|
|
542
|
+
// 環境変数 NAKO_LIB か?
|
|
543
|
+
if (process.env.NAKO_LIB) {
|
|
544
|
+
const NAKO_LIB = path.join(path.resolve(process.env.NAKO_LIB), pname)
|
|
545
|
+
const fileLib = fCheckEx(NAKO_LIB, 'NAKO_LIB')
|
|
546
|
+
if (fileLib) { return fileLib }
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// ランタイムパス/node_modules/<plugin>
|
|
550
|
+
const pathRuntime = path.join(path.resolve(__dirname), 'node_modules', pname)
|
|
551
|
+
const fileRuntime = fCheckEx(pathRuntime, 'runtime')
|
|
480
552
|
if (fileRuntime) { return fileRuntime }
|
|
481
553
|
|
|
482
554
|
// 環境変数 NAKO_HOMEか?
|
|
483
555
|
if (process.env.NAKO_HOME) {
|
|
484
|
-
const NAKO_HOME = path.resolve(process.env.NAKO_HOME)
|
|
485
|
-
const fileHome = fCheckEx(NAKO_HOME)
|
|
556
|
+
const NAKO_HOME = path.join(path.resolve(process.env.NAKO_HOME), 'node_modules', pname)
|
|
557
|
+
const fileHome = fCheckEx(NAKO_HOME, 'NAKO_HOME')
|
|
486
558
|
if (fileHome) { return fileHome }
|
|
487
559
|
// NAKO_HOME/src ?
|
|
488
|
-
const pathNakoHomeSrc = path.join(NAKO_HOME, 'src')
|
|
489
|
-
const fileNakoHomeSrc =
|
|
560
|
+
const pathNakoHomeSrc = path.join(NAKO_HOME, 'src', pname)
|
|
561
|
+
const fileNakoHomeSrc = fCheckEx(pathNakoHomeSrc, 'NAKO_HOME/src')
|
|
490
562
|
if (fileNakoHomeSrc) { return fileNakoHomeSrc }
|
|
491
563
|
}
|
|
492
564
|
// 環境変数 NODE_PATH (global) 以下にあるか?
|
|
493
565
|
if (process.env.NODE_PATH) {
|
|
494
|
-
const pathNode = path.resolve(process.env.NODE_PATH)
|
|
495
|
-
const fileNode = fCheckEx(pathNode)
|
|
566
|
+
const pathNode = path.join(path.resolve(process.env.NODE_PATH), pname)
|
|
567
|
+
const fileNode = fCheckEx(pathNode, 'NODE_PATH')
|
|
496
568
|
if (fileNode) { return fileNode }
|
|
497
569
|
}
|
|
498
570
|
// Nodeのパス検索には任せない(importで必ず失敗するので)
|
package/src/nako3.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
/**
|
|
3
2
|
* nadesiko v3
|
|
4
3
|
*/
|
|
@@ -177,18 +176,20 @@ export class NakoCompiler {
|
|
|
177
176
|
|
|
178
177
|
/**
|
|
179
178
|
* プログラムが依存するファイルを再帰的に取得する。
|
|
180
|
-
* -
|
|
181
|
-
* -
|
|
182
|
-
*
|
|
183
|
-
* - readNako3はソースコードを返す。readJsはrequireあるいはevalする関数を返す。
|
|
179
|
+
* - 依存するファイルがJavaScriptファイルの場合、そのファイルを実行して評価結果をthis.addPluginFileに渡す。
|
|
180
|
+
* - 依存するファイルがなでしこ言語の場合、ファイルの中身を取得して変数に保存し、再帰する。
|
|
181
|
+
*
|
|
184
182
|
* @param {string} code
|
|
185
183
|
* @param {string} filename
|
|
186
184
|
* @param {string} preCode
|
|
187
185
|
* @param {{
|
|
188
|
-
* resolvePath: (name: string, token: TokenWithSourceMap) => { type: 'nako3' | 'js' | 'invalid', filePath: string }
|
|
189
|
-
* readNako3: (filePath: string, token: TokenWithSourceMap) => {
|
|
190
|
-
* readJs: (filePath: string, token: TokenWithSourceMap) => {
|
|
191
|
-
* }} tools
|
|
186
|
+
* resolvePath: (name: string, token: TokenWithSourceMap, fromFile: string) => { type: 'nako3' | 'js' | 'invalid', filePath: string }
|
|
187
|
+
* readNako3: (filePath: string, token: TokenWithSourceMap) => { task: Promise<string> }
|
|
188
|
+
* readJs: (filePath: string, token: TokenWithSourceMap) => { task: Promise<() => object> }
|
|
189
|
+
* }} tools - 実行環境 (ブラウザ or Node.js) によって外部ファイルの取得・実行方法は異なるため、引数でそれらを行う関数を受け取る。
|
|
190
|
+
* - resolvePath は指定した名前をもつファイルを検索し、正規化されたファイル名を返す関数。返されたファイル名はreadNako3かreadJsの引数になる。
|
|
191
|
+
* - readNako3は指定されたファイルの中身を返す関数。
|
|
192
|
+
* - readJsは指定したファイルをJavaScriptのプログラムとして実行し、`export default` でエクスポートされた値を返す関数。
|
|
192
193
|
* @returns {Promise<unknown> | void}
|
|
193
194
|
* @protected
|
|
194
195
|
*/
|
|
@@ -200,10 +201,12 @@ export class NakoCompiler {
|
|
|
200
201
|
const loadJS = (item, tasks) => {
|
|
201
202
|
// jsならプラグインとして読み込む。(ESMでは必ず動的に読む)
|
|
202
203
|
const obj = tools.readJs(item.filePath, item.firstToken)
|
|
203
|
-
tasks.push(obj.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
tasks.push(obj.task.then((res) => {
|
|
205
|
+
const pluginFuncs = res()
|
|
206
|
+
this.addPluginFile(item.value, item.filePath, pluginFuncs, false)
|
|
207
|
+
dependencies[item.filePath].funclist = pluginFuncs
|
|
208
|
+
dependencies[item.filePath].addPluginFile = () => { this.addPluginFile(item.value, item.filePath, pluginFuncs, false) }
|
|
209
|
+
}))
|
|
207
210
|
}
|
|
208
211
|
const loadNako3 = (item, tasks) => {
|
|
209
212
|
// nako3ならファイルを読んでdependenciesに保存する。
|
|
@@ -221,15 +224,11 @@ export class NakoCompiler {
|
|
|
221
224
|
const funclist = {}
|
|
222
225
|
NakoLexer.preDefineFunc(cloneAsJSON(tokens), this.logger, funclist)
|
|
223
226
|
dependencies[item.filePath].funclist = funclist
|
|
224
|
-
|
|
225
227
|
// 再帰
|
|
226
228
|
return loadRec(code, item.filePath, '')
|
|
227
229
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
} else {
|
|
231
|
-
tasks.push(content.value.then((res) => registerFile(res)))
|
|
232
|
-
}
|
|
230
|
+
// 取り込み構文における問題を減らすため、必ず非同期でプログラムを読み込む仕様とした #1219
|
|
231
|
+
tasks.push(content.task.then((res) => registerFile(res)))
|
|
233
232
|
}
|
|
234
233
|
/** @param {string} code @param {string} filename @param {string} preCode @returns {Promise<unknown> | void} */
|
|
235
234
|
const loadRec = (code, filename, preCode) => {
|
|
@@ -238,7 +237,7 @@ export class NakoCompiler {
|
|
|
238
237
|
// 取り込みが必要な情報一覧を調べる(トークン分割して、取り込みタグを得る)
|
|
239
238
|
const tags = NakoCompiler.listRequireStatements(compiler.rawtokenize(code, 0, filename, preCode))
|
|
240
239
|
// パスを解決する
|
|
241
|
-
const tagsResolvePath = tags.map((v) => ({ ...v, ...tools.resolvePath(v.value, v.firstToken) }))
|
|
240
|
+
const tagsResolvePath = tags.map((v) => ({ ...v, ...tools.resolvePath(v.value, v.firstToken, filename) }))
|
|
242
241
|
// 取り込み開始
|
|
243
242
|
for (const item of tagsResolvePath) {
|
|
244
243
|
// 2回目以降の読み込み
|
package/src/nako_gen.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* file: nako_gen.js
|
|
3
2
|
* パーサーが生成した中間オブジェクトを実際のJavaScriptのコードに変換する。
|
|
4
3
|
* なお速度優先で忠実にJavaScriptのコードを生成する。
|
|
5
4
|
*/
|
|
@@ -7,12 +6,6 @@
|
|
|
7
6
|
import { NakoSyntaxError, NakoError, NakoRuntimeError } from './nako_errors.mjs'
|
|
8
7
|
import { NakoLexer } from './nako_lexer.mjs'
|
|
9
8
|
import nakoVersion from './nako_version.mjs'
|
|
10
|
-
const isIE11 = () => {
|
|
11
|
-
if (typeof(window) == 'object' && window.navigator && window.navigator.userAgent) {
|
|
12
|
-
return (window.navigator.userAgent.indexOf('MSIE') >= 0)
|
|
13
|
-
}
|
|
14
|
-
return false
|
|
15
|
-
}
|
|
16
9
|
|
|
17
10
|
// なでしこで定義した関数の開始コードと終了コード
|
|
18
11
|
const topOfFunction = '(function(){\n'
|
|
@@ -1546,7 +1539,7 @@ export class NakoGen {
|
|
|
1546
1539
|
|
|
1547
1540
|
|
|
1548
1541
|
/**
|
|
1549
|
-
* @param {import('./nako3')} com
|
|
1542
|
+
* @param {import('./nako3.mjs').NakoCompiler} com
|
|
1550
1543
|
* @param {Ast} ast
|
|
1551
1544
|
* @param {boolean | string} isTest 文字列なら1つのテストだけを実行する
|
|
1552
1545
|
*/
|
|
@@ -1573,21 +1566,19 @@ export function generateJS (com, ast, isTest) {
|
|
|
1573
1566
|
}
|
|
1574
1567
|
// async method
|
|
1575
1568
|
if (gen.numAsyncFn > 0) {
|
|
1576
|
-
|
|
1577
|
-
if (canAsync) {
|
|
1578
|
-
js = `
|
|
1569
|
+
js = `
|
|
1579
1570
|
// <nadesiko3::gen::async>
|
|
1580
1571
|
(async () => { // async::main
|
|
1581
1572
|
${js}
|
|
1582
1573
|
}).call(this).catch(err => {
|
|
1583
|
-
if (
|
|
1584
|
-
err
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1574
|
+
if (typeof(NakoRuntimeError) === 'undefined') { NakoRuntimeError = this.NakoRuntimeError }
|
|
1575
|
+
if (!(err instanceof NakoRuntimeError)) {
|
|
1576
|
+
err = new NakoRuntimeError(err, this.__varslist[0].line);
|
|
1577
|
+
}
|
|
1578
|
+
this.logger.error(err);
|
|
1579
|
+
throw err;
|
|
1588
1580
|
}); // async::main
|
|
1589
1581
|
// <nadesiko3::gen::async>\n`
|
|
1590
|
-
}
|
|
1591
1582
|
}
|
|
1592
1583
|
|
|
1593
1584
|
// デバッグメッセージ
|
|
@@ -1595,36 +1586,37 @@ throw err;
|
|
|
1595
1586
|
// todo: 将来的に mjs のコードを履くように修正する
|
|
1596
1587
|
const standaloneJSCode = `\
|
|
1597
1588
|
// <standaloneCode>
|
|
1589
|
+
// 将来的に ESModule に対応する #1217
|
|
1590
|
+
// import path from 'path'
|
|
1591
|
+
// import PluginNode from './nako3runtime/plugin_node.mjs'
|
|
1592
|
+
// import {NakoRuntimeError} from './nako3runtime/nako_errors.mjs'
|
|
1593
|
+
|
|
1598
1594
|
const path = require('path')
|
|
1599
|
-
const nakoVersion = ${JSON.stringify(nakoVersion)};
|
|
1600
1595
|
${NakoError.toString()}
|
|
1601
|
-
${NakoRuntimeError.toString()}
|
|
1602
|
-
|
|
1603
|
-
|
|
1596
|
+
${NakoRuntimeError.toString()}
|
|
1597
|
+
const nakoVersion = ${JSON.stringify(nakoVersion)};
|
|
1598
|
+
const self = this
|
|
1599
|
+
self.logger = {
|
|
1604
1600
|
error: (message) => { console.error(message) },
|
|
1605
1601
|
send: (level, message) => { console.log(message) },
|
|
1606
1602
|
};
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1603
|
+
self.__varslist = [{}, {}, {}];
|
|
1604
|
+
self.__vars = self.__varslist[2];
|
|
1605
|
+
self.__module = {};
|
|
1606
|
+
self.__locals = {};
|
|
1607
|
+
self.__genMode = 'sync';
|
|
1612
1608
|
try {
|
|
1613
1609
|
${gen.getVarsCode()}
|
|
1614
1610
|
${js}
|
|
1615
1611
|
} catch (err) {
|
|
1616
1612
|
if (!(err instanceof NakoRuntimeError)) {
|
|
1617
|
-
err = new NakoRuntimeError(err, __varslist[0].line);
|
|
1613
|
+
err = new NakoRuntimeError(err, self.__varslist[0].line);
|
|
1618
1614
|
}
|
|
1619
|
-
|
|
1615
|
+
self.logger.error(err);
|
|
1620
1616
|
throw err;
|
|
1621
1617
|
}
|
|
1622
|
-
//
|
|
1623
|
-
} // end of __nako3safunc function
|
|
1624
|
-
__nako3safunc();
|
|
1625
1618
|
// </standaloneCode>
|
|
1626
|
-
`
|
|
1627
|
-
|
|
1619
|
+
`
|
|
1628
1620
|
return {
|
|
1629
1621
|
// なでしこの実行環境ありの場合
|
|
1630
1622
|
runtimeEnv: js,
|
package/src/nako_version.mjs
CHANGED
package/src/plugin_node.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* file: plugin_node.
|
|
2
|
+
* file: plugin_node.mjs
|
|
3
3
|
* node.js のためのプラグイン
|
|
4
4
|
*/
|
|
5
5
|
import fs from 'fs'
|
|
@@ -11,9 +11,8 @@ import iconv from 'iconv-lite'
|
|
|
11
11
|
import opener from 'opener'
|
|
12
12
|
import clipboardy from 'clipboardy'
|
|
13
13
|
import assert from 'assert'
|
|
14
|
-
//
|
|
15
|
-
import
|
|
16
|
-
import { stdin as input, stdout as output } from 'process'
|
|
14
|
+
// 「標準入力取得時」「尋」で利用
|
|
15
|
+
import readline from 'readline'
|
|
17
16
|
// ハッシュ関数で利用
|
|
18
17
|
import crypto from 'crypto'
|
|
19
18
|
import os from 'os'
|
|
@@ -585,11 +584,15 @@ export default {
|
|
|
585
584
|
josi: [['と', 'を']],
|
|
586
585
|
pure: true,
|
|
587
586
|
asyncFn: true,
|
|
588
|
-
fn:
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
587
|
+
fn: function (msg, sys) {
|
|
588
|
+
return new Promise((resolve, _reject) => {
|
|
589
|
+
const rl = readline.createInterface(process.stdin, process.stdout)
|
|
590
|
+
rl.question(msg, (buf) => {
|
|
591
|
+
rl.close()
|
|
592
|
+
if (buf && buf.match(/^[0-9.]+$/)) { buf = parseFloat(buf) }
|
|
593
|
+
resolve(buf)
|
|
594
|
+
})
|
|
595
|
+
})
|
|
593
596
|
}
|
|
594
597
|
},
|
|
595
598
|
// @テスト
|
|
@@ -598,7 +601,6 @@ export default {
|
|
|
598
601
|
josi: [['と'], ['が']],
|
|
599
602
|
pure: true,
|
|
600
603
|
fn: function (a, b, sys) {
|
|
601
|
-
|
|
602
604
|
assert.strictEqual(a, b)
|
|
603
605
|
}
|
|
604
606
|
},
|