Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

「??」をカスタマイズできるようにする #1852 #1877

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion core/src/nako_lex_rules.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* なでしこ3字句解析のためのルール
*/

import { NakoLexerError } from './nako_errors.mjs'
import { josiRE, removeJosiMap } from './nako_josi_list.mjs'
import { TokenType } from './nako_token.mjs'

Expand Down
11 changes: 5 additions & 6 deletions core/src/nako_parser3.mts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class NakoParser extends NakoParserBase {
if (this.check('エラー監視')) { return this.yTryExcept() }
if (this.accept(['抜ける'])) { return { type: 'break', josi: '', ...map, end: this.peekSourceMap() } }
if (this.accept(['続ける'])) { return { type: 'continue', josi: '', ...map, end: this.peekSourceMap() } }
if (this.check('??')) { return this.yPrint() }
if (this.check('??')) { return this.yDebugPrint() }
// 実行モードの指定
if (this.accept(['DNCLモード'])) { return this.yDNCLMode(1) }
if (this.accept(['DNCL2モード'])) { return this.yDNCLMode(2) }
Expand Down Expand Up @@ -699,9 +699,8 @@ export class NakoParser extends NakoParserBase {

/**
* 表示(関数)を返す 「??」のエイリアスで利用 (#1745)
* @returns {AstCallFunc | null}
*/
yPrint (): AstCallFunc | null {
yDebugPrint (): AstCallFunc | null {
const map = this.peekSourceMap()
const t = this.get() // skip '??'
if (!t || t.value !== '??') {
Expand All @@ -711,11 +710,11 @@ export class NakoParser extends NakoParserBase {
if (!arg) {
throw NakoSyntaxError.fromNode('『??(計算式)』で指定してください。', map)
}
const meta = this.funclist.get('表示')
if (!meta) { throw new Error('関数『表示』が見つかりません。plugin_systemをシステムに追加してください。') }
const meta = this.funclist.get('ハテナ関数実行')
if (!meta) { throw new Error('関数『ハテナ関数実行』が見つかりません。plugin_systemをシステムに追加してください。') }
return {
type: 'func',
name: '表示',
name: 'ハテナ関数実行',
blocks: [arg],
josi: '',
meta,
Expand Down
1 change: 1 addition & 0 deletions core/src/plugin_api.mts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface NakoSystem {
__setSore(v: any): void;
__getSore(): any;
__loadScript(url: string): Promise<void>; // JSのスクリプトを読み込む (ex) グラフ描画(plguin_browser_chart.mts)
__hatena: (s: string, sys: NakoSystem) => void; // 「??」記法の関数キャッシュ #1852
logger: any; // Logger
// 便利なメソッド
__zero (s: string, keta: number): string; // 桁を指定してゼロ埋めする
Expand Down
66 changes: 65 additions & 1 deletion core/src/plugin_system.mts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ export default {
obj.__getProp = obj.__setProp = null
}
}

// 「??」ハテナ関数の設定
sys.__hatena = sys.__getSysVar('デバッグ表示')
}
},
'!クリア': {
Expand Down Expand Up @@ -2918,6 +2919,69 @@ export default {
}
},
// @デバッグ支援
'デバッグ表示': { // @デバッグ用にSを表示する // @でばっぐひょうじ
type: 'func',
josi: [['と', 'を', 'の']],
pure: true,
fn: function (s: any, sys: NakoSystem) {
// 行番号の情報を得る
const lineInfo: string = sys.__getSysVar('__line', 0) + '::'
const a = lineInfo.split(':', 2)
const no = parseInt(String(a[0]).replace('l', '')) + 1
const fname = a[1]
// オブジェクトならJSON文字列に変換
if (typeof s == 'object') {
s = JSON.stringify(s)
}
s = `${fname}(${no}): ${s}`
sys.__exec('表示', [s, sys])
},
return_none: true
},
'ハテナ関数設定': { // @ハテナ関数「?? (計算式)」の動作をカスタマイズする。文字列の配列を指定可能で、システム関数名か「js:code」を指定可能。 // @はてなかんすうせってい
type: 'func',
josi: [['を', 'の']],
pure: true,
fn: function (s: any, sys: NakoSystem) {
if (typeof s === 'function') {
sys.__hatena = s
return
}
if (typeof s === 'string') {
sys.__hatena = sys.__getSysVar(s, 'デバッグ表示')
return
}
if (s instanceof Array) {
const fa: ((s: string, sys: NakoSystem)=>string)[] = (s as Array<string>).map((fstr: string) => {
if (fstr.substring(0, 3) === 'JS:') {
const code = fstr.substring(3)
return sys.__evalJS(code, sys)
} else {
return sys.__getSysVar(fstr, 'デバッグ表示')
}
})
sys.__hatena = (p: any, sys: NakoSystem) => {
let param: any = p
for (const f of fa) {
param = f(param, sys)
}
return
}
return
}
sys.__hatena = sys.__getSysVar('デバッグ表示')
},
return_none: true
},
'ハテナ関数実行': { // @『ハテナ関数設定』で設定した関数を実行する // @はてなかんすうじっこう
type: 'func',
josi: [['の', 'を', 'と']],
pure: true,
fn: function (s: any, sys: NakoSystem) {
sys.__hatena(s, sys)
},
return_none: true
},
'エラー発生': { // @故意にエラーSを発生させる // @えらーはっせい
type: 'func',
josi: [['の', 'で']],
Expand Down
18 changes: 12 additions & 6 deletions core/test/plugin_system_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('plugin_system_test', async () => {
const g = await nako.runAsync(code, 'main.nako3')
assert.strictEqual(g.log, res)
}
const cmpex = async (/** @type {string} */ code, /** @type {name: string, message: string} */ exinfo) => {
const cmpex = async (/** @type {string} */ code, /** @type {{name: string, message: string}} */ exinfo) => {
const nako = new NakoCompiler()
nako.getLogger().debug('code=' + code)
try {
Expand Down Expand Up @@ -690,11 +690,6 @@ describe('plugin_system_test', async () => {
await cmp('A=[0,1,2,3];Aから0...5を参照してJSONエンコードして表示', '[0,1,2,3]') // 範囲を超えて指定もエラーにならない
await cmp('A=[0,1,2,3];Aから5...9を参照してJSONエンコードして表示', '[]') // 範囲を超えて指定もエラーにならない
})
it('「?? 計算式文」 #1745', async () => {
await cmp('??1+1', '2')
await cmp('??1+2*3', '7')
await cmp('??(1+2)*3', '9')
})
it('ASC/CHRの配列 #1853', async () => {
await cmp('["a","b","c"]のASCをJSON_Eして表示', '[97,98,99]') // 配列なら全ての文字のASC
await cmp('「abc」のASCをJSON_Eして表示', '97') // 文字列なら最初の文字のみ
Expand All @@ -707,4 +702,15 @@ describe('plugin_system_test', async () => {
await cmp('「 abc 」を右トリムして表示', ' abc')
await cmp('「 abc 」を末尾空白除去して表示', ' abc')
})
it('「?? 計算式文」 #1745', async () => {
await cmp('「表示」をハテナ関数設定; ?? 1+1', '2')
await cmp('「表示」をハテナ関数設定; ?? 1+2*3', '7')
await cmp('「表示」をハテナ関数設定; ?? (1+2)*3', '9')
})
it('「??」のカスタマイズ機能を追加 #1852', async () => {
await cmp('["JSON_E","表示"]をハテナ関数設定; ?? [1,2,3]', '[1,2,3]')
await cmp('["文字列分解", "ASC", "JSON_E","表示"]をハテナ関数設定; ?? "abc"', '[97,98,99]')
await cmp('["JS:Math.ceil","表示"]をハテナ関数設定; ?? 3.2', '4')
await cmp('[『JS:(function(v,sys){return Math.ceil(v);})』,"表示"]をハテナ関数設定; ?? 3.2', '4')
})
})
Loading