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.
Files changed (40) hide show
  1. package/batch/command.txt +1 -0
  2. package/batch/command_nakopad.txt +1 -0
  3. package/demo/browsers.html +1 -1
  4. package/demo/nako3/taberu.nako3 +5 -0
  5. package/doc/browsers.md +1 -1
  6. package/package.json +1 -1
  7. package/release/_hash.txt +24 -24
  8. package/release/_script-tags.txt +14 -14
  9. package/release/command.json +1 -1
  10. package/release/command.json.js +1 -1
  11. package/release/command_cnako3.json +1 -1
  12. package/release/command_list.json +1 -1
  13. package/release/editor.js +1 -1
  14. package/release/nako_gen_async.js +1 -1
  15. package/release/nako_gen_async.js.LICENSE.txt +20 -0
  16. package/release/plugin_caniuse.js +1 -1
  17. package/release/stats.json +1 -1
  18. package/release/version.js +1 -1
  19. package/release/wnako3.js +1 -1
  20. package/src/browsers.mjs +1 -1
  21. package/src/browsers.txt +0 -1
  22. package/src/cnako3mod.mjs +88 -64
  23. package/src/nako3.mjs +72 -53
  24. package/src/nako_gen.mjs +6 -12
  25. package/src/nako_global.mjs +2 -2
  26. package/src/nako_lex_rules.mjs +1 -1
  27. package/src/nako_lexer.mjs +83 -22
  28. package/src/nako_parser3.mjs +144 -33
  29. package/src/nako_parser_base.mjs +75 -6
  30. package/src/nako_version.mjs +2 -2
  31. package/src/plugin_system.mjs +27 -9
  32. package/test/common/nako_lexer_test.mjs +33 -0
  33. package/test/common/plugin_system_test.mjs +1 -1
  34. package/test/common/variable_scope_test.mjs +13 -0
  35. package/test/node/error_message_test.mjs +5 -3
  36. package/test/node/plugin_test.mjs +21 -3
  37. package/test/node/scope1.nako3 +10 -0
  38. package/test/node/scope2.nako3 +12 -0
  39. package/test/node/wnako3_editor_test.mjs +12 -0
  40. 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","12.22.0"],"op_mini":["all"],"op_mob":["64"],"opera":["83","82"],"safari":["15.4","15.2-15.3","14.1"],"samsung":["16.0","15.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
@@ -25,7 +25,6 @@ kaios 2.5
25
25
  node 17.9.0
26
26
  node 16.14.0
27
27
  node 14.19.0
28
- node 12.22.0
29
28
  op_mini all
30
29
  op_mob 64
31
30
  opera 83
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
- if (opt.browsers) { // 対応ブラウザを表示する
133
+ // 対応ブラウザを表示する
134
+ if (opt.browsers) {
135
135
  this.cnakoBrowsers()
136
136
  return
137
137
  }
138
138
  if (opt.mainfile) { this.filename = opt.mainfile }
139
- if (opt.repl) { // REPLを実行する
139
+ // REPLを実行する
140
+ if (opt.repl) {
140
141
  this.cnakoRepl(opt)
141
142
  return
142
143
  }
143
- if (opt.one_liner) { // ワンライナーで実行する
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
- try {
159
- if (opt.test) {
167
+
168
+ // テストを実行する
169
+ if (opt.test) {
170
+ try {
160
171
  await this.loadDependencies(src, opt.mainfile, '')
161
172
  this.test(src, opt.mainfile)
162
- } else {
163
- // run はコンパイルと実行を行うメソッド
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
- // system
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
- * @param {string} code
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
- resolvePath: (name, token) => {
314
- // JSプラグインのパスを解決する
315
- if (/\.(js|mjs)(\.txt)?$/.test(name) || /^[^.]*$/.test(name)) {
316
- const jspath = CNako3.findJSPluginFile(name, this.filename, __dirname, log)
317
- if (jspath === '') {
318
- throw new NakoImportError(`ファイル『${name}』が見つかりません。以下のパスを検索しました。\n${log.join('\n')}`, token.file, token.line)
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
- if (/\.nako3?(\.txt)?$/.test(name)) {
324
- if (path.isAbsolute(name)) {
325
- return { filePath: path.resolve(name), type: 'nako3' }
326
- } else {
327
- // filename undefined のとき token.file undefined になる。
328
- if (token.file === undefined) {
329
- throw new Error('ファイル名を指定してください。')
330
- }
331
- return { filePath: path.resolve(path.join(path.dirname(token.file), name)), type: 'nako3' }
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
- return { filePath: name, type: 'invalid' }
335
- },
336
- readNako3: (name, token) => {
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
- readJs: (filePath, token) => {
343
- const content = {sync: false, value: null}
344
- if (process.platform === 'win32') {
345
- if (filePath.substring(1, 3) === ':\\') {
346
- filePath = 'file://' + filePath
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 super._loadDependencies(code, filename, preCode, tools)
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
- await this.loadDependencies(code, fname, preCode).catch((err) => {
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 { NakoGen, generateJS } from './nako_gen.mjs'
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
- * - needNako3needJsがPromiseを返すなら並列処理し、処理の終了を知らせるためのPromiseを返す。そうでなければ同期的に処理する。
182
- * (`instanceof Promise` はpolyfillで動作しない場合があるため、Promiseかどうかを明示する必要がある。)
182
+ * - readNako3readJsの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 inner = (code, filename, preCode) => {
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
- // jsならプラグインとして読み込む。
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
- // nako3ならファイルを読んでdependenciesに保存する。
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 = inner(code, filename, preCode)
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.setInput(preprocessed.map((v) => v.text).join(''), line, filename)
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
- return this.lexer.setInput2(tokens, isFirst)
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: false
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]
@@ -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
  // ユーザーのプログラムから編集される変数
@@ -39,7 +39,7 @@ export const rules = [
39
39
  { name: 'もし', pattern: /^もしも?/ },
40
40
  // 「ならば」は助詞として定義している
41
41
  { name: '違えば', pattern: /^違(えば)?/ },
42
- // 「回」「間」「繰返」「反復」「抜」「続」「戻」「代入」「条件分岐」などは replaceWord で word から変換
42
+ // 「回」「間」「繰返」「反復」「抜」「続」「戻」「代入」「条件分岐」などは NakoLexer._replaceWord で word から変換
43
43
  // @see nako_reserved_words.js
44
44
  { name: 'shift_r0', pattern: /^>>>/ },
45
45
  { name: 'shift_r', pattern: /^>>/ },