先日公式BBSに例外処理のマクロがありまして
http://hsp.tv/play/pforum.php?mode=all&num=32385
それは、どう書く?orzを参考にしていまして
http://ja.doukaku.org/comment/8783/
著作権どうしよう?だなんて考えながらマクロ(?)を書きました
作成に二日かかったので
作成時間2〜4時間くらいで書いたままサイトにUPしてなかったんですけど
UPしてみます
公式BBSのは関数から例外が返って来ないんですけど
例外処理って普通の返り値と例外の二つ返す仕組みだとか
どこかで読んだ気がするんですけれど
なら返り値は引数に代入して
一つしかないけど返り値で例外を返せばいいじゃないか?という仕様です
例外の値は数値っぽいんですけど
しっかり設計しないといけなそうなので
例外の値は文字列にしました
文字列が等しければcatchという流れです
catchとfinallyは構造がまんまswitchではないか?
と思いまんまswitch使用して呼び方が違うだけです
FILE名:FILE_EX.hsp
以下TESTコード
http://hsp.tv/play/pforum.php?mode=all&num=32385
それは、どう書く?orzを参考にしていまして
http://ja.doukaku.org/comment/8783/
著作権どうしよう?だなんて考えながらマクロ(?)を書きました
作成に二日かかったので
作成時間2〜4時間くらいで書いたままサイトにUPしてなかったんですけど
UPしてみます
公式BBSのは関数から例外が返って来ないんですけど
例外処理って普通の返り値と例外の二つ返す仕組みだとか
どこかで読んだ気がするんですけれど
なら返り値は引数に代入して
一つしかないけど返り値で例外を返せばいいじゃないか?という仕様です
例外の値は数値っぽいんですけど
しっかり設計しないといけなそうなので
例外の値は文字列にしました
文字列が等しければcatchという流れです
catchとfinallyは構造がまんまswitchではないか?
と思いまんまswitch使用して呼び方が違うだけです
FILE名:FILE_EX.hsp
#module EX
// ユニークラベル操作
// ユニークラベル取り出し。スタック維持
#define global __p_u_label %tEX_unique_label *%p
// ユニークラベルをpop
#define global __o_u_label %tEX_unique_label *%o
goto *@f
// 変数をグローバル変数として扱いたいのでアクセサ付きとする
#deffunc __set_EX_val str p
__EX_val=p
return
#defcfunc __get_EX_val
return __EX_val
*@
// アクセサ変数を空文字代入でRESET
#define global throw_RESET __set_EX_val ""
// 文字列をアクセサ変数に代入してユニークラベルにJUMP
#define global try_throw(%1) __set_EX_val %1:goto __p_u_label
// ユニークラベルをスタックに積む
#define global try_begin %tEX_unique_label %i0
// 空命令
#define global try_end /**/
// ユニークラベルを取り出して、そこがswitch文の開始
#define global b_catch __o_u_label:switch(__get_EX_val())
// switch文終了
#define global b_catch_end swend
// catchはcase文
#define global catch_begin(%1) case %1
#define global catch_end swbreak
// finallyはdefault文
#define global finally_begin default
#define global finally_end swbreak
// throwすると見せかけてreturnするだけ
#define global throw(%1) return %1
// 例外文字列が""か"nil"でなければ例外を投げる
#define global Does_try_throw(%1) __on_does_throw=%1:\
if (__on_does_throw!="")&(__on_does_throw!="nil"){try_throw __on_does_throw}
// 例外文字列が""か"nil"でなければ例外を返す
#define global Does_throw(%1) __on_does_throw=%1:\
if (__on_does_throw!="")&(__on_does_throw!="nil"){throw __on_does_throw}
#global |
以下TESTコード
#include "FILE_EX.hsp" goto *@f #defcfunc throw_a01 throw "a01" #defcfunc throw_a02 throw "a02" #defcfunc throw_abc throw "abc" #defcfunc throw_null throw "" #defcfunc throw_nil throw "nil" *@ // TEST例外処理の流れ try_begin try_throw "a01" try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end try_begin try_throw "a02" try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end try_begin try_throw "abc" try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end // TEST例外が返ってくる try_begin try_throw throw_a01() try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end try_begin try_throw throw_a02() try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end try_begin try_throw throw_abc() try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end // Does_try_throwのTEST try_begin Does_try_throw throw_a01() try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end try_begin Does_try_throw throw_null() mes "null throw" goto *@f try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end *@ try_begin Does_try_throw throw_nil() mes "nil throw" goto *@f try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end *@ goto *@f // Does_throwのTEST用関数 #defcfunc throw_call_a01 Does_throw throw_a01() return "" // Does_throwのTEST用関数 #defcfunc throw_call_null Does_throw throw_null() return "" *@ // Does_throwのTEST try_begin Does_try_throw throw_call_a01() mes "null throw" goto *@f try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end *@ // Does_throwのTEST try_begin Does_try_throw throw_call_null() mes "null throw" goto *@f try_end b_catch catch_begin "a01" mes "EX:This is a01" catch_end catch_begin "a02" mes "EX:This is a02" catch_end finally_begin mes "EX:This is fin" finally_end b_catch_end *@ |