GBA homebrew日記 このページをアンテナに追加 RSSフィード

2008-11-30

[] tiny basicを作る(その22)

if命令通りました。

ってこんなことで一喜一憂してちゃきりないか・・・。


ところでC言語限定の話ですけど、エラー処理について

少し困ったところがありました。


たとえば3階層目の関数が元締め(?)で、

6階層目あたりでエラーになったとします。

理想としては何事もなかったかのように3階層目まで戻り、

エラーでした!といえればOK。


ところがどうやって通知するかという話になると

これが結構厄介。


たとえば3〜6階層目までの関数の戻り値を

boolにしてしまうという方法があります。

でも戻り値の用途が固定されてしまい、使わなくてはいけない関数があるときは

isHoge()を作って事前確認することになりそうです。


次に思いつくのは

グローバル変数でbool isErrとか用意してしまう方法。

ただこれは分散ぎみになりますし、あんまりよくなさそうな(考えなくない(汗))ので却下。


最後に思いついたのはエラーになっても、そのまま進行してしまい、

3階層目に戻ってきたらまとめてチェックする方法です。

これだとエラーのまま進行しても差し支えないようにしなくてはいけないのが難点。

エラーチェックが元締めだけという利点もあります。


とりあえず、どれも一長一短ですが

今回は最後の方法を使ってみている部分(コード生成処理)があります。


今日の戦火です。↓

10 IF 1 = 1 THEN PRINT "C" ELSE PRINT "D"
20 IF 1 = 2 THEN PRINT "E" ELSE PRINT "F"
Init
------------------------------
Adr 10
PushNum 1
PushNum 1
Eq
Beq(8)
PushStr 0("C")
Print
Jump(13)
PatchBeq(8, 14)
PushStr 4("D")
Print
PatchJump(13, 17)
------------------------------
Adr 20
PushNum 1
PushNum 2
Eq
Beq(25)
PushStr 8("E")
Print
Jump(30)
PatchBeq(25, 31)
PushStr 12("F")
Print
PatchJump(30, 34)
------------------------------
DebugCodeBuf
[   0] -   17
[   1] -   10
[   2] -   29
[   3] -    1
[   4] -   29
[   5] -    1
[   6] -   23
[   7] -    8
[   8] -   14
[   9] -   31
[  10] -    0
[  11] -   14
[  12] -    9
[  13] -   17
[  14] -   31
[  15] -    4
[  16] -   14
[  17] -   17
[  18] -   20
[  19] -   29
[  20] -    1
[  21] -   29
[  22] -    2
[  23] -   23
[  24] -    8
[  25] -   31
[  26] -   31
[  27] -    8
[  28] -   14
[  29] -    9
[  30] -   34
[  31] -   31
[  32] -   12
[  33] -   14

TOTAL: 34
------------------------------
DebugWorkBuf
[   0] -    3
[   1] - 4322
[   2] -   22
[   3] -    0
[   4] -    3
[   5] - 4422
[   6] -   22
[   7] -    0
[   8] -    3
[   9] - 4522
[  10] -   22
[  11] -    0
[  12] -    3
[  13] - 4622
[  14] -   22
[  15] -    0

TOTAL: 16
------------------------------
Exec
------------------------------
Adr 10
PushNum
    Push[   0] - 1
    Push[   1] - 1
PushNum
    Push[   2] - 1
    Push[   3] - 1
    Pop [   3] - 1
    Pop [   2] - 1
    Pop [   1] - 1
    Pop [   0] - 1
Eq 1 == 1
Beq
PushStr
    Push[   0] - 0
    Push[   1] - 4
Print
    Pop [   1] - 4
    Pop [   0] - 0
--> "C"                          # Cと出力
Jump
------------------------------
Adr 20
PushNum
    Push[   0] - 1
    Push[   1] - 1
PushNum
    Push[   2] - 2
    Push[   3] - 1
    Pop [   3] - 1
    Pop [   2] - 2
    Pop [   1] - 1
    Pop [   0] - 1
Eq 1 == 2
Beq
PushStr
    Push[   0] - 12
    Push[   1] - 4
Print
    Pop [   1] - 4
    Pop [   0] - 12
--> "F"                          # Fと出力

[] tiny basicを作る(その21)

途中微妙にさぼりぎみでしたけれど

ようやくコード生成に成功しました!

10  IF 1 = 1 THEN PRINT "1" ELSE PRINT "2"
Init
------------------------------
Adr 10
PushNum 1
PushNum 1
Eq
Beq(8)
PushStr 0("1")
Print
Jump(13)
PatchBeq(8, 14)
PushStr 0("2")
Print
PatchJump(13, 17)
Exec
------------------------------
DebugCodeBuf
[   0] -   17    # Adr
[   1] -   10
[   2] -   29    # PushNum
[   3] -    1
[   4] -   29    # PushNum
[   5] -    1
[   6] -   23    # Eq
[   7] -    8    # Beq
[   8] -   14    # PatchBeqの分。
[   9] -   31    # PushStr
[  10] -    0
[  11] -   14    # Print
[  12] -    9    # Jump
[  13] -   17    # PatchJumpの分。
[  14] -   31    # PushStr
[  15] -    0
[  16] -   14    # Print

TOTAL: 17

残るはVsmExec関数と、テキストと変数の格納アドレスを保持するテーブル登録だけ。

2,3日中には完成すると思います。

yasuhoyasuho 2008/12/02 17:24 C++ならtry/catchですかね。Cだと実装方法にもよるけど、setjmp/longjmpを使うという手もあるかも。処理系のエラーハンドリングって、けっこう面倒ですよね。

akkera102akkera102 2008/12/02 23:08 Cの標準ライブラリを使わないことにしたせいで
setjmp/longjmpの存在を失念していました(>_<。

ARMの本も読んだのにアセンブラをまるで書いていないのは
恥ずかしいので、Google先生の参考資料を片手に
ちょっとだけ書いてみました。

最新の日記に更新しましたので
よかったら見てください。

> 処理系のエラーハンドリングって、けっこう面倒ですよね。

まったくおっしゃるとおりです。このところ設計とかテストについて
興味があって、どうすればうまいコードが書けるか試行錯誤しています。

・・・なんだかだんだんGBAとかゲームじゃない話になったりして(汗。

トラックバック - http://d.hatena.ne.jp/akkera102/20081130