aiscript
aiscript copied to clipboard
ラッパーとしてのreturn,break,continueが残ってしまっている
if
式・match
式・ブロック式で、return
文・break
文・continue
文を使用するとラッパーが外れずに残ってしまう。
break
文・continue
文は普通の関数でも残ってしまう。
例
<: eval { return 1 } // == return
<: eval { break } // == break
<: eval { continue } // == continue
<: if true { return 1 } // == return
<: if true { break } // == break
<: if true { continue } // == continue
@r() { return 1 }
@b() { break }
@c() { continue }
<: r() // == 1 (これが正常)
<: b() // == break
<: c() // == continue
解決案
return
文に関しては関数呼び出しでしているのと同様に~~ブロック式の処理に~~外すべき場所でunWrapRet
を挟む。
if
式のブロックとブロック式のブロックが同じノードでreturn
をどう処理すべきか区別できないので、ブロックの呼び出し元(代入文等)で処理する?
https://github.com/syuilo/aiscript/blob/master/src/interpreter/index.ts#L427-L429
グローバルスコープ直下のifやブロック式にreturn、関数の直下にbreakやcontinueが存在していること自体がおかしいのでエラーにしてもいいような気がします…
returnに関しては関数内でも普通に取り出せてしまうけどどう扱うべきだろう 禁止するとして構文解析レベルで処理するかプラグインの段階で処理するか
@fff() {
let a = eval {
return 1
}
<: a // return<null>
let b = if true {
return 1
}
<: b // return<null>
}
- グローバルスコープ直下にreturn|break|continueがあったらエラー
- 関数スコープ直下にbreak|continueがあったらエラー
- return|break|continueを含むif|evalがexprとして扱われていたらエラー
これらを実装できればよさそうですかね? 個人的には、1.と2.はreturn文の処理内でスコープ名をチェックするような処理で済ませられるならそれがシンプルでいいと思います。 3.に関しては構文解析レベルのエラーにしたほうが早い気がします。