コンパイラ作成(107) 配列と単項演算子の優先順位

今回の目標 配列を実装したときに先送りしちゃった件をなんとかするよ。 // 配列 int main() { int a[10]; a[0] = 42; printf("-a[0] = %d\n", -a[0]); } 本来は-(a[0])と評価しなくちゃいけないんだけど、(-a)[0]って解釈しちゃっててコンパイルに失敗して…

コンパイラ作成(106) バグ修正

バグ エラー処理周りのチェックをしていてバグを見つけたよ。 // 配列 int main() { double a[10], *p = a; a[0) = 42; a[1] = 55; printf("*p = %f\n", *p); } 配列の閉じ括弧が間違ってる場合。エラーにならずにコンパイル通っちゃってたよ。 read_el # 式…

コンパイラ作成(105) 引数が配列の関数

今回の目標 コマンドライン引数を表示できるように対応するよ。 // コマンドライン int main(int argc, char *argv[]) { for(int i = 0; i < argc; i = i + 1) printf("argv[%d]=%s\n", i, argv[i]); } 関数定義の解析さえ頑張れば大丈夫かな。 function 引…

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

今回の目標 ポインタに[]演算子を適用できるようにするよ。 // ポインタと配列演算子 int main() { char *p = "myc"; for(int i = 0; i < 3; i = i + 1) putchar(p[i]); putchar('\n'); } 配列演算子っていう呼び方で合ってるんだろうか。 codegen_els 型チ…

コンパイラ作成(103) int型以外のポインタの間接参照

今回の目標 前回に続きバグ修正。 // 配列 int main() { double a[10], *p = a; a[0] = 42; a[1] = 55; printf("*p = %f\n", *p); } 間接参照演算子もdouble型とかに対応できてなかったよ。 codegen_unaryop 間接参照演算子の処理のところを修正。 elsif op.…

コンパイラ作成(102) int型以外の配列の参照

今回の目標 色々試してたらバグが見つかったよ。 // 配列 int main() { double a[10]; a[0] = 42; a[1] = 55; printf("a[0] = %f\n", a[0]); } 配列の参照だけどint型以外の場合上手く行ってなかった。バグっていうか未サポートってところかな。 codegen_lva…

コンパイラ作成(101) 配列への代入

今回の目標 今回は代入だよ。 // 配列 int main() { int a[10]; a[0] = 42; printf("a[0] = %d\n", a[0]); } まずは単純な場合から。 codegen_assign 今回、大きく書き換えたよ。 # 代入のコード生成 def codegen_assign(el) if el.size != 3 then perror en…

コンパイラ作成(100) 配列の参照

今回の目標 今回は配列の参照だよ。 // 配列 int main() { int a[10], *p; p = a; *p = 42; printf("a[0] = %d\n", a[0]); printf("0[a] = %d\n", 0[a]); printf("10 + a[0] = %d\n", 10 + a[0]); printf("10 + 0[a] = %d\n", 10 + 0[a]); } 配列への代入は…

コンパイラ作成(99) 配列のポインタへの変換

今回の目標 配列の実装を進めるよ。 // 配列 int main() { int a[10], *p; p = a; printf("p = %016lx\n", p); } 簡単そうなところから。 ヘルパーメソッド # 配列型? def is_array_type?(type) return type.match(/\[.*\]$/) end # 配列型→pointer型 def a…

コンパイラ作成(98) 配列の宣言

今回の目標 いきなりだけど配列に手を出してみるよ。 // 配列 int main() { int a[10], b; } まずは配列変数の宣言から。 Lexer gettokenの修正。 # symbolの切り出し elsif m = @line[@idx,@line.length] .match(/^(==|!=|<=|>=|=|<|>|\+|\-|\*|\/|\%|&|:|,…

コンパイラ作成(97) return文での型変換

今回の目標 int型→double型の型変換。 // int型→double型 double func(void) { return 5; } int main() { double x; x = func(); printf("x = %f\n", x); } 最近、return文のとこばかりだな。 statement return文の処理を修正。 if kind == TK::RESERVE && s…

コンパイラ作成(96) 型変換のバグ修正

バグ修正 プログラム眺めてたらバグを見っけたよ。 // double型 double dadd(double a, double b) { printf("dadd: %f %f\n", a, b); return a + b; } int main() { double x = 12.3, y = -2.8; printf("%f %f %f\n", x, y, dadd(5.4, 3.2)); printf("%d %d …

コンパイラ作成(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, s…

コンパイラ作成(94) 値を返さないreturn文

今回の目標 単純なreturn文。 // 関数の呼び出し void sub(void) { return; } int main() { sub(); printf("%d\n",42); } これサポートしてなかったよ。 statement return文の処理。 def statement(kind, str) if kind == TK::RESERVE && str == "return" th…

コンパイラ作成(93) int型→double型の変換

今回の目標 型変換を頑張るよ。 // int型→double型 int func(void) { return 5; } int func2(double a) { return 10; } int main() { int a = 12; double x, *p = &x; x = a; printf("x = %f\n", x); x = x * 2; printf("x = %f\n", x); x = x - a; printf("…

コンパイラ作成(92) 引数の無い関数の定義でのvoid

今回の目標 いくつかテストしてる時に気が付いたんだけど、voidを使って関数に引数が無いことを明示する記述の仕方、まだ対応してなかったよ。 // 関数の呼び出し int answer(void) { // Answer to the Ultimate Question of Life, the Universe, and Everyt…

コンパイラ作成(91) 浮動小数点数リテラルの処理

今回の目標 重複したリテラルを一個に纏めるよ。 // double型 double dadd(double a, double b) { printf("dadd: %f %f\n", a, b); return a + b; } int main() { double x = 12.3, y = -2.8; printf("%f %f %f\n", x, y, dadd(5.4, 3.2)); printf("%d %d %f…

コンパイラ作成(90) ネストした関数呼出

今回の目標 double型引数の関数呼出が入子になってる場合に対応するよ。 // double型 double dadd(double a, double b) { printf("dadd: %f %f\n", a, b); return a + b; } int main() { double x = 12.3, y = -2.8; printf("%f %f %f\n", x, y, dadd(5.4, 3…

コンパイラ作成(89) 式のエラーチェック

今回の目標 前回に続きエラーチェック。 // 壊れてる式 int main() { int i; i = ; } 壊れた代入。 codegen_assign # 代入のコード生成 def codegen_assign(el) if el.size != 3 then perror end if el[2] == nil then perror "broken expression" end type_…

コンパイラ作成(88) 式のエラーチェック

今回の目標 double型関連にちょっと疲れたんで別の事やるよ。壊れてる式をチェックしてエラーに。 // 壊れてる式 int main() { 1 + ; } // 壊れてる式 int main() { + ; } // 壊れてる式 int main() { / ; } // 壊れてる式 int main() { int i; i++; } ちょ…

コンパイラ作成(87) 引数がdouble型の関数定義

今回の目標 double型の関数だよ。 // double型 double dadd(double a, double b) { return a + b; } int main() { double x = 12.3, y = -2.8, z = dadd(x, y); printf("%f + %f = %f\n", x, y, z); } 引数も返値もdouble型の場合。 function # レジスタで渡…

コンパイラ作成(86) double型の単項マイナス演算子

今回の目標 今回は単項マイナス演算子だよ。 // double型 int main() { double x = 4.5, y = -x; printf("x = %f\ny = %f\n", x, y); } コード生成部 codegen_unaryopの該当部分を修正。 # 単行演算子のコード生成 def codegen_unaryop(op, operand) type = …

コンパイラ作成(85) double型の比較演算子

今回の目標 前回の残りの比較演算をサポートするよ。 // double型の比較 int main() { double x; x = 1.5; if( x != 1.5 ) printf("true\n"); else printf("false\n"); x = 1.0; if( x != 1.5 ) printf("true\n"); else printf("false\n"); } コード生成部 …

コンパイラ作成(84) double型の等価演算子

今回の目標 等価演算子をサポートするよ。 // double型の乱数 int main() { double x; x = 1.5; if( x == 1.5 ) printf("true\n"); else printf("false\n"); x = 1.0; if( x == 1.5 ) printf("true\n"); else printf("false\n"); } コード生成部 まずはここ…

コンパイラ作成(83) double型を返す関数の呼出

今回の目標 sqrtをコールしてみるよ。 // double型 extern double sqrt(double x); int main() { printf("%f\n", 2.0 * sqrt(2.0)); } 前回、関数コールに不安があったんだけど、やってみたらやっぱり駄目だったよ。見直してみたら未修正のところがあった。 …

コンパイラ作成(82) double型の複雑な四則演算

今回の目標 前回に続き四則演算。 // double型 int main() { printf("%f\n", 2.0 + 5.0 / 2.0); } 前回対応できなかった複雑な式。 コード生成部 codegen_elsの括弧の処理部と関数呼出の処理部を修正。 def codegen_els(op, operand, type_l) ostr = mnemoni…

Haskellのお勉強(4) 素数

素数の表示 Haskellだけど細々と勉強続けてるよ。でもなかなか進まない。解説サイト見たりしてるんだけどさ、書かれてる内容は理解できても、それを実際のプログラミングの中でどう活かせば良いのかが分からないんだよね。ということでまた簡単なとこから。 …

vlangを試してみた

vlang 巷で話題になってるvlangを触ってみたよ。 vlang.io 奇麗なページでしっかりしたプログラミング言語なのかと思ったけど、一人だけで作ってるんだね。正直出来はまだまだって感じみたいだ。コンパイラの中身をちょこっと見てみたけど、C言語へのトラン…

コンパイラ作成(81) double型の単純な四則演算

今回の目標 double型の計算を実装するよ。 // double型 int main() { double a = 2.7, b = 5.1, c; c = a + b; printf("%f + %f = %f\n", a, b, c); c = a - b; printf("%f - %f = %f\n", a, b, c); c = a * b; printf("%f * %f = %f\n", a, b, c); c = a / …

コンパイラ作成(80) double型引数の関数呼出

今回の目標 前回サボった関数呼出を頑張るよ。 // double型 int main() { int a = 15, b = 25; double d = 10.78; double e = 0.13e-3; printf("a = %d d = %f e = %e b = %d\n", a, d, e, b); } int型、double型を混ぜてprintfに渡してる。 関数コール # 関…