コンパイラ作成(36) バグ修正
バグ3件
比較演算子を追加しようと思ってたんだけど、その前にテストを色々やってたら、バグが3件も見つかったよ。
// 正しくない式 int main() { int a, b; != b; }
妙竹林な代入ね。コンパイルエラーにならずに、コンパイラが異常終了しちゃったよ。
// 代入 int main() { int a, b; a = 10; b = a; printf("b = %d\n",b); }
a=b;っていう単純な場合のチェックが抜けてたよ。これも異常終了。
// 関数の閉じ中括弧がない int main() { int a, b; a = b;
最後がこれ。関数の閉じ中括弧が無い場合。異常終了はしないけど、動作が怪しくてエラーメッセージもおかしかった。
codegen_assign
代入2件の修正。
# 代入のコード生成 def codegen_assign(el) if el.size != 3 then perror end if !el[2].kind_of?(Array) && el[2].kind == TK::NUMBER then codegen " mov eax, " + el[2].str elsif !el[2].kind_of?(Array) && el[2].kind == TK::ID then v = @lvars[el[2].str] if v == nil then perror "undeclared variable \"" + el[2].str + "\"" end codegen " mov eax, dword ptr [rbp - " + v[1].to_s + "]" else codegen_el el[2] end if el[0].kind_of?(Array) then perror end if el[0].kind != TK::ID then perror end v = @lvars[el[0].str] if v == nil then perror "undeclared variable \"" + el[0].str + "\"" end codegen " mov dword ptr [rbp - " + v[1].to_s + "], eax" end
修正というかコーディングが足りてなかったよ。
function
3件目の修正。
# 関数の構文解析 def function() @labelcnt = 0 @lvars = Hash.new @lvarsize = 0; rettype = nil kind, str = @lex.gettoken if kind == TK::RESERVE && str == "int" then rettype = str kind, str = @lex.gettoken end if kind == TK::EOF then return false end if kind != TK::ID then perror "expected identifier" end @funcname = str kind, str = @lex.gettoken if kind != TK::SYMBOL || str != "(" then perror end kind, str = @lex.gettoken if kind != TK::SYMBOL || str != ")" then perror end codegen ".global "+@funcname codegen @funcname+":" codegen " push rbp" codegen " mov rbp, rsp" codegen " sub rsp, 64" kind, str = @lex.gettoken if kind != TK::SYMBOL || str != "{" then perror end kind, str = @lex.gettoken loop do kind, str = statement kind, str if kind == TK::SYMBOL && str == "}" then break end if kind == TK::EOF then perror "expected '}'" end end codegen ".RET_" + @funcname + ":" codegen " add rsp, 64" codegen " pop rbp" codegen " ret" if @functions[@funcname] != nil then perror "redefinition of \"" + @funcname + "\"" end @functions[@funcname] = [rettype,[]] p @lvars if $opt_d # デバッグ用 @funcname = nil return true end
ここもTK::EOFの場合のチェックが入ってなかったよ。異常終了しなかったのは偶然助かってただけだった。