コンパイラ作成(104) ポインタを配列として扱う

今回の目標

ポインタに[]演算子を適用できるようにするよ。

// ポインタと配列演算子
int main()
{
    char *p = "myc";
    for(int i = 0; i < 3; i = i + 1)
        putchar(p[i]);
    putchar('\n');
}

配列演算子っていう呼び方で合ってるんだろうか。

codegen_els

型チェックの処理を修正。

    # 型チェック
    if type_l == "double" && type_r == "int" then
      if str != "r10d" then
        codegen "  mov    r10d, #{str}"
      end
      codegen "  cvtsi2sd xmm9, r10d"
      str = "xmm9"
      type_r = type_l
    elsif type_l == "int" && type_r == "double" then
      codegen "  cvtsi2sd xmm8, eax"
      type_l = type_r
    end
    if type_l != type_r then
      if is_pointer_type?(type_l) && type_r == "int" then
        if op.str != "+" && op.str != "-" && op.str != "[]" then
          perror "mismatched types to binary operation"
        end
      elsif type_l == "int" && is_pointer_type?(type_r) then
        if op.str != "+" && op.str != "-" && op.str != "[]" then
          perror "mismatched types to binary operation"
        end
      elsif is_array_type?(type_l) && type_r == "int" then
        if op.str != "[]" then
          perror "mismatched types to binary operation"
        end
      elsif type_l == "int" && is_array_type?(type_r) then
        if op.str != "[]" then
          perror "mismatched types to binary operation"
        end
      else
        perror "mismatched types to binary operation"
      end
    elsif is_pointer_type? type_l then
      perror "mismatched types to binary operation"
    elsif type_l == "double" && op.str == "%" then
      perror "mismatched types to binary operation"
    end

ポインタ型のときも[]演算子を弾かないように修正。

      if is_pointer_type?(type_l) && type_r == "int" then
        # ポインタ型+int型の処理
        codegen_pointer_int type_l, op, ostr, str
        if op.str == "[]" then
          codegen_lval_to_rval type_l
        end
      elsif type_l == "int" && is_pointer_type?(type_r) then
        # int型+ポインタ型の処理
        codegen_int_pointer type_r, op, ostr, str
        type_l = type_r
        if op.str == "[]" then
          codegen_lval_to_rval type_l
        end
      elsif is_array_type?(type_l) && type_r == "int" then
        # 配列+int型の処理
        type_l = array_to_pointer type_l
        codegen_pointer_int type_l, op, ostr, str
        type_l = type_l[0,type_l.length-1]
        codegen_lval_to_rval type_l
      elsif type_l == "int" && is_array_type?(type_r) then
        # int型+配列の処理
        type_r = array_to_pointer type_r
        codegen_int_pointer type_r, op, ostr, str
        type_l = type_r[0,type_r.length-1]
        codegen_lval_to_rval type_l
      else
        codegen "  " + ostr + " #{reg}, " + str
      end

codegen_lval_to_rvalをコールするよう修正。

動作テスト
~/myc$ myc q8.myc
~/myc$ ./q8
myc
~/myc$ 

ちゃんと動いたよ。今回は時間が取れなかったんでコーディング2分テスト2分で終わったよ。次回は何にするかな。配列を引数とする関数かな。main(int argc, char *argv[])をコンパイルできるようにしたいな。