コンパイラ作成(95) return文での型のチェック
今回の目標
前回の続きでreturn文。
// 関数の呼び出し int *sub(void) { return 2.5; } int main() { printf("%d\n",sub()); }
型をチェックするよ。
expr
# 式の構文解析 def expr2(fkind,fstr,skind,sstr) el, kind, str = read_modify_el fkind, fstr, skind, sstr return kind, str, codegen_el(el) end
型の情報を返すようインターフェースを修正。
statement
return文の処理。
if kind == TK::RESERVE && str == "return" then # return文の処理 f = @functions[@funcname] kind, str = @lex.gettoken if kind != TK::SYMBOL && str != ";" then kind, str, type = expr kind, str if f[0] != type then if f[0] == "void" then perror "return a value at void function" else perror "return with incompatible result type" end end if f[0] == "double" then codegen " movsd xmm0, xmm8" end else if f[0] != "void" then perror "return no value at non-void function" end end codegen " jmp .RET_" + @funcname if kind != TK::SYMBOL || str != ";" then perror "expected ';' after return statement" end
exprからの型情報と関数情報テーブルの返値の型を見比べてエラーを出してるんだけど、色んな場合があって面倒だよ。
動作テスト
~/myc$ myc err45.myc err45.myc:4:15 error: return with incompatible result type ~/myc$
ちゃんとエラーになってるね。さらに別のパターンを二つチェックするよ。
// 関数の呼び出し void sub(void) { return 42; } int main() { printf("%d\n",sub()); }
void関数で値を返してる場合。
// 関数の呼び出し int sub(void) { return; } int main() { printf("%d\n",sub()); }
逆にvoid関数じゃないのに値を返してない場合。
~/myc$ myc err46.myc err46.myc:4:14 error: return a value at void function ~/myc$ myc err47.myc err47.myc:4:11 error: return no value at non-void function ~/myc$
大丈夫だね。一応これで全部のパターンチェックしたつもり。次回はreturn文でのint型→double型の変換をやるつもりだよ。