From 72dadc608de05441c934a6e003d9a6898ecd51c8 Mon Sep 17 00:00:00 2001 From: Janggun Lee Date: Tue, 25 Feb 2025 00:28:55 +0900 Subject: [PATCH] Various quality-of-life improvements (ideas from @33577 ) * Very basic `hello_main.c` * Big starting hint to `write_c` * Better error messages on failed test * TODO: also improve it for asmgen, but not sure how to do it in a good way --- examples/c/array.c | 4 +-- examples/c/array3.c | 6 ++-- examples/c/array4.c | 6 ++-- examples/c/array5.c | 4 +-- examples/c/bar.c | 9 ++++-- examples/c/bitwise.c | 14 ++++----- examples/c/cmp.c | 12 +++++--- examples/c/comma.c | 3 +- examples/c/complement.c | 2 +- examples/c/cond.c | 3 +- examples/c/cond_and_loop.c | 9 ++++-- examples/c/fib2.c | 2 +- examples/c/fibonacci.c | 2 +- examples/c/float.c | 8 +++--- examples/c/foo.c | 9 ++++-- examples/c/foo2.c | 2 +- examples/c/foo3.c | 4 +-- examples/c/foo4.c | 12 ++++---- examples/c/for_continue_break.c | 7 +++-- examples/c/gcd.c | 9 ++++-- examples/c/hello_main.c | 3 ++ examples/c/lost_copy.c | 14 ++++----- examples/c/negate.c | 9 ++++-- examples/c/pointer.c | 14 ++++----- examples/c/simple.c | 5 ++-- examples/c/simple_for.c | 7 ++--- examples/c/simple_if.c | 2 +- examples/c/sizeof4.c | 3 +- examples/c/struct.c | 12 ++++---- examples/c/struct2.c | 14 ++++----- examples/c/struct4.c | 11 +++---- examples/c/swap.c | 16 +++++------ examples/c/switch-in-loop.c | 30 +++++++++---------- examples/c/temp2.c | 48 +++++++++++++++++-------------- examples/c/typecast.c | 2 +- examples/c/while_continue_break.c | 9 +++--- examples/ir0/hello_main.ir | 13 +++++++++ examples/ir1/hello_main.ir | 10 +++++++ examples/ir2/hello_main.ir | 10 +++++++ examples/ir3/hello_main.ir | 10 +++++++ examples/ir4/hello_main.ir | 10 +++++++ examples/opt/hello_main.ir | 10 +++++++ src/c/ast_equiv.rs | 10 ------- src/c/mod.rs | 1 - src/c/write_c.rs | 1 + src/ir/mod.rs | 1 + src/lib.rs | 2 +- src/tests.rs | 28 ++++++++++++------ src/write_base.rs | 4 +-- tests/test_examples.rs | 36 +++++++++++++++++++---- 50 files changed, 290 insertions(+), 182 deletions(-) create mode 100644 examples/c/hello_main.c create mode 100644 examples/ir0/hello_main.ir create mode 100644 examples/ir1/hello_main.ir create mode 100644 examples/ir2/hello_main.ir create mode 100644 examples/ir3/hello_main.ir create mode 100644 examples/ir4/hello_main.ir create mode 100644 examples/opt/hello_main.ir diff --git a/examples/c/array.c b/examples/c/array.c index 110d0f9..538b801 100644 --- a/examples/c/array.c +++ b/examples/c/array.c @@ -1,4 +1,4 @@ -int sum(int len, int *p) { +int sum(int len, int* p) { int result = 0; for (int i = 0; i < len; i++) { result += p[i]; @@ -10,7 +10,7 @@ int sum(int len, int *p) { int main() { int a[5]; int len = 5; - + for (int i = 0; i < len; i++) { a[i] = i; } diff --git a/examples/c/array3.c b/examples/c/array3.c index 414b3bd..5334adf 100644 --- a/examples/c/array3.c +++ b/examples/c/array3.c @@ -1,12 +1,12 @@ -int* foo(int a[10]){ +int* foo(int a[10]) { return a; } int main() { int a[10]; - + for (int i = 0; i < 10; i++) { - (foo(a))[i] = i; + (foo(a))[i] = i; } return a[5] == 5; diff --git a/examples/c/array4.c b/examples/c/array4.c index a374bc5..5b5b63f 100644 --- a/examples/c/array4.c +++ b/examples/c/array4.c @@ -1,9 +1,9 @@ int main() { int a[10]; - int *p = a; - + int* p = a; + for (int i = 0; i < 10; i++) { - *(p++) = i; + *(p++) = i; } return a[5] == 5; diff --git a/examples/c/array5.c b/examples/c/array5.c index 39bc446..1184774 100644 --- a/examples/c/array5.c +++ b/examples/c/array5.c @@ -5,10 +5,10 @@ int main() { int a[5] = {init, 2, 3, 4, -5}; int sum = 0; - for(int i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) { sum += a[i]; sum += g_a[i]; } - + return sum; } diff --git a/examples/c/bar.c b/examples/c/bar.c index 4cd8b0b..63449d5 100644 --- a/examples/c/bar.c +++ b/examples/c/bar.c @@ -1,8 +1,11 @@ -int bar(int x, int y, int z){ +int bar(int x, int y, int z) { int arith_mean = (x + y + z) / 3; int ugly_mean = (((x + y) / 2) * 2 + z) / 3; - if (x == y) { return y; } - else { return z; } + if (x == y) { + return y; + } else { + return z; + } } int main() { diff --git a/examples/c/bitwise.c b/examples/c/bitwise.c index abc7bb6..43e4ab7 100644 --- a/examples/c/bitwise.c +++ b/examples/c/bitwise.c @@ -2,12 +2,12 @@ int main() { unsigned char a = -1; unsigned char b = -128; unsigned char c = 127; - unsigned char d = b | a; // -1 (255) - unsigned char e = b & a; // -128 (128) - unsigned char f = b & c; // 0 (0) - unsigned char g = b | c; // -1 (255) - unsigned char h = -1 ^ -1; // 0 (0) - unsigned char i = -1 ^ 0; // -1 (255) - + unsigned char d = b | a; // -1 (255) + unsigned char e = b & a; // -128 (128) + unsigned char f = b & c; // 0 (0) + unsigned char g = b | c; // -1 (255) + unsigned char h = -1 ^ -1; // 0 (0) + unsigned char i = -1 ^ 0; // -1 (255) + return d == 255 && e == 128 && f == 0 && g == 255 && h == 0 && i == 255; } diff --git a/examples/c/cmp.c b/examples/c/cmp.c index 4d68ddf..91da943 100644 --- a/examples/c/cmp.c +++ b/examples/c/cmp.c @@ -1,11 +1,15 @@ int int_greater_than(int i, unsigned int j) { - if (i > j) return 1; - else return 0; + if (i > j) + return 1; + else + return 0; } int char_greater_than(char i, unsigned char j) { - if (i > j) return 1; - else return 0; + if (i > j) + return 1; + else + return 0; } int main() { diff --git a/examples/c/comma.c b/examples/c/comma.c index 294bf93..f51bb79 100644 --- a/examples/c/comma.c +++ b/examples/c/comma.c @@ -1,5 +1,4 @@ -int main() -{ +int main() { int y = 2; int x = (y += 2, 2, y + 3); return x == 7; diff --git a/examples/c/complement.c b/examples/c/complement.c index f63b1b0..2750877 100644 --- a/examples/c/complement.c +++ b/examples/c/complement.c @@ -1,4 +1,4 @@ -int nonce = 1; // For random input +int nonce = 1; // For random input int main() { int a = ~nonce; diff --git a/examples/c/cond.c b/examples/c/cond.c index e12f409..1a4ec01 100644 --- a/examples/c/cond.c +++ b/examples/c/cond.c @@ -1,5 +1,4 @@ -int main() -{ +int main() { int y = 1; int x = 0; return ((x == y) ? 2 : 5) == 5; diff --git a/examples/c/cond_and_loop.c b/examples/c/cond_and_loop.c index 1e33551..ffed084 100644 --- a/examples/c/cond_and_loop.c +++ b/examples/c/cond_and_loop.c @@ -1,4 +1,4 @@ -int nonce = 1; // For random input +int nonce = 1; // For random input int main() { int i; @@ -8,8 +8,11 @@ int main() { int loop_num = nonce % 100; for (i = 0; i < loop_num; ((i % 2) ? (i += 2) : ++i)) { - if (i % 2) { p += q; } - else { p += r; } + if (i % 2) { + p += q; + } else { + p += r; + } } return p; diff --git a/examples/c/fib2.c b/examples/c/fib2.c index 94b0cda..a65fe3a 100644 --- a/examples/c/fib2.c +++ b/examples/c/fib2.c @@ -1,4 +1,4 @@ -int (fibonacci)(int n) { +int fibonacci(int n) { if (n < 2) { return n; } diff --git a/examples/c/fibonacci.c b/examples/c/fibonacci.c index 151c39d..c067fe8 100644 --- a/examples/c/fibonacci.c +++ b/examples/c/fibonacci.c @@ -1,4 +1,4 @@ -int nonce = 1; // For random input +int nonce = 1; // For random input int fibonacci(int n) { if (n < 2) { diff --git a/examples/c/float.c b/examples/c/float.c index d8f50ac..f140863 100644 --- a/examples/c/float.c +++ b/examples/c/float.c @@ -14,22 +14,22 @@ double average(int len, int a[10]) { int sum = 0; int i; - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { sum += a[i]; } - return (double) sum / len; + return (double)sum / len; } int main() { int a[10]; int len = 10; - + for (int i = 0; i < len; i++) { a[i] = i; } float avg = average(len, a); - + return is_close(avg, 4.5, 1e-09, 0.1); } diff --git a/examples/c/foo.c b/examples/c/foo.c index 879caed..816744e 100644 --- a/examples/c/foo.c +++ b/examples/c/foo.c @@ -1,6 +1,9 @@ -int foo(int x, int y, int z){ - if (x == y) { return y; } - else { return z; } +int foo(int x, int y, int z) { + if (x == y) { + return y; + } else { + return z; + } } int main() { diff --git a/examples/c/foo2.c b/examples/c/foo2.c index 150600b..d4252b0 100644 --- a/examples/c/foo2.c +++ b/examples/c/foo2.c @@ -4,6 +4,6 @@ int main() { int i = 0; int k = 0; } - + return 1; } diff --git a/examples/c/foo3.c b/examples/c/foo3.c index 95906a6..96b8b47 100644 --- a/examples/c/foo3.c +++ b/examples/c/foo3.c @@ -1,11 +1,11 @@ -int nonce = 1; // For random input +int nonce = 1; // For random input int g = 10; int foo(int, int k); int main() { int i = g; - + return foo(i, i); } diff --git a/examples/c/foo4.c b/examples/c/foo4.c index bbe4a38..d3a49d1 100644 --- a/examples/c/foo4.c +++ b/examples/c/foo4.c @@ -1,15 +1,15 @@ int foo(int i, int j, int k) { - return i + j + k; + return i + j + k; } -int (* foo2())(int, int, int){ - return foo; +int (*foo2())(int, int, int) { + return foo; } -int (* (* foo3())())(int, int, int){ - return foo2; +int (*(*foo3())())(int, int, int) { + return foo2; } int main() { - return foo3()()(2, 2, 2) == 6; + return foo3()()(2, 2, 2) == 6; } diff --git a/examples/c/for_continue_break.c b/examples/c/for_continue_break.c index f15b59a..91ee964 100644 --- a/examples/c/for_continue_break.c +++ b/examples/c/for_continue_break.c @@ -1,9 +1,10 @@ int foo() { int sum = 0; - for(int i = 0; ;) { - if(i == 5) break; - if(i == 3) { + for (int i = 0;;) { + if (i == 5) + break; + if (i == 3) { i++; continue; } diff --git a/examples/c/gcd.c b/examples/c/gcd.c index 7c64ed6..823642a 100644 --- a/examples/c/gcd.c +++ b/examples/c/gcd.c @@ -2,9 +2,12 @@ int gcd(int a, int b) { a = (a > 0) ? a : -a; b = (b > 0) ? b : -b; - while(a != b) { - if(a > b) { a -= b; } - else { b -= a; } + while (a != b) { + if (a > b) { + a -= b; + } else { + b -= a; + } } return a; diff --git a/examples/c/hello_main.c b/examples/c/hello_main.c new file mode 100644 index 0000000..6346e2d --- /dev/null +++ b/examples/c/hello_main.c @@ -0,0 +1,3 @@ +int main() { + return 1; +} diff --git a/examples/c/lost_copy.c b/examples/c/lost_copy.c index dcabfe9..2ab89c8 100644 --- a/examples/c/lost_copy.c +++ b/examples/c/lost_copy.c @@ -1,9 +1,9 @@ int main() { - int i = 0; - int result = 0; - do { - result = i; - i++; - } while (i < 4); - return result; + int i = 0; + int result = 0; + do { + result = i; + i++; + } while (i < 4); + return result; } diff --git a/examples/c/negate.c b/examples/c/negate.c index d38f42d..f69f180 100644 --- a/examples/c/negate.c +++ b/examples/c/negate.c @@ -1,6 +1,9 @@ -int foo(int x, int y, int z){ - if (!(x == y)) { return y; } - else { return z; } +int foo(int x, int y, int z) { + if (!(x == y)) { + return y; + } else { + return z; + } } int main() { diff --git a/examples/c/pointer.c b/examples/c/pointer.c index 21bebce..77bd1e3 100644 --- a/examples/c/pointer.c +++ b/examples/c/pointer.c @@ -1,15 +1,15 @@ -int* foo(int *a){ - return a; +int* foo(int* a) { + return a; } -int main(){ +int main() { int a = 1; - int *p = &a; - int **p2 = &*&p; - int *p3 = *&p; + int* p = &a; + int** p2 = &*&p; + int* p3 = *&p; *&*foo(*p2) += 1; *foo(p3) += 1; - + return a == 3; } diff --git a/examples/c/simple.c b/examples/c/simple.c index ddec5b3..eede3b2 100644 --- a/examples/c/simple.c +++ b/examples/c/simple.c @@ -1,7 +1,6 @@ -int nonce = 1; // For random input +int nonce = 1; // For random input -int main() -{ +int main() { int x = nonce; return x; } diff --git a/examples/c/simple_for.c b/examples/c/simple_for.c index 6073bcc..5597a80 100644 --- a/examples/c/simple_for.c +++ b/examples/c/simple_for.c @@ -1,9 +1,8 @@ -int main() -{ +int main() { int i; int sum = 0; - for (i = 0; i < 11; ++i) { - sum += i; + for (i = 0; i < 11; ++i) { + sum += i; } return sum == 55; } diff --git a/examples/c/simple_if.c b/examples/c/simple_if.c index 46dd19a..c76bd7f 100644 --- a/examples/c/simple_if.c +++ b/examples/c/simple_if.c @@ -1,4 +1,4 @@ -int (fibonacci)(int n) { +int fibonacci(int n) { if (n < 2) { n += 2; } diff --git a/examples/c/sizeof4.c b/examples/c/sizeof4.c index 965e079..c3a7a9e 100644 --- a/examples/c/sizeof4.c +++ b/examples/c/sizeof4.c @@ -1,5 +1,4 @@ -int main() -{ +int main() { int a = 3; int b = sizeof(!(a++)); return a + b; diff --git a/examples/c/struct.c b/examples/c/struct.c index ab3d164..28b5119 100644 --- a/examples/c/struct.c +++ b/examples/c/struct.c @@ -1,9 +1,9 @@ typedef struct { - char a; - struct { - int b[4][5]; - }; - double c; + char a; + struct { + int b[4][5]; + }; + double c; } Temp; void init(int row, int col, int arr[4][5]) { @@ -21,6 +21,6 @@ int main() { Temp temp2; temp2 = temp; - + return temp2.b[2][3] == 6; } diff --git a/examples/c/struct2.c b/examples/c/struct2.c index 8141865..3384b1e 100644 --- a/examples/c/struct2.c +++ b/examples/c/struct2.c @@ -1,18 +1,18 @@ typedef struct { - char a; - struct { - int b[4]; - }; - long c; + char a; + struct { + int b[4]; + }; + long c; } Temp; int main() { const Temp temp = {1, {{2, 3, 4, 5}}, 6}; - + Temp temp2; temp2 = temp; int sum = temp2.a + temp2.b[2] + temp2.c; - + return sum == 11; } diff --git a/examples/c/struct4.c b/examples/c/struct4.c index f43dd63..121e770 100644 --- a/examples/c/struct4.c +++ b/examples/c/struct4.c @@ -1,19 +1,16 @@ -int nonce = 1; // For random input +int nonce = 1; // For random input -struct Foo -{ +struct Foo { int x; }; -struct Foo f() -{ +struct Foo f() { struct Foo x; x.x = nonce; return x; } -int main() -{ +int main() { int x = f().x; return x; } diff --git a/examples/c/swap.c b/examples/c/swap.c index e0de075..d2684d6 100644 --- a/examples/c/swap.c +++ b/examples/c/swap.c @@ -1,10 +1,10 @@ int main() { - int a = 1; - int b = 2; - do { - int t = a; - a = b; - b = t; - } while (b == 1); - return a * 10 + b; + int a = 1; + int b = 2; + do { + int t = a; + a = b; + b = t; + } while (b == 1); + return a * 10 + b; } diff --git a/examples/c/switch-in-loop.c b/examples/c/switch-in-loop.c index 7994878..87a1e43 100644 --- a/examples/c/switch-in-loop.c +++ b/examples/c/switch-in-loop.c @@ -1,18 +1,18 @@ int main() { - int i = 0; - int c = 0; - while (i < 10) { - i++; - switch (i) { - case (1): { - continue; - break; - } - default: { - break; - } + int i = 0; + int c = 0; + while (i < 10) { + i++; + switch (i) { + case (1): { + continue; + break; + } + default: { + break; + } + } + c++; } - c++; - } - return c; + return c; } diff --git a/examples/c/temp2.c b/examples/c/temp2.c index fd3ed93..ded578c 100644 --- a/examples/c/temp2.c +++ b/examples/c/temp2.c @@ -1,29 +1,33 @@ -struct color { int number; char name; }; +struct color { + int number; + char name; +}; int main() { - int temp = 0; - temp += sizeof(unsigned char); - temp += _Alignof(unsigned char); + int temp = 0; + temp += sizeof(unsigned char); + temp += _Alignof(unsigned char); - struct color c = {1, 2}; - temp += c.name; - struct color *cp = &c; - temp += cp->name; + struct color c = {1, 2}; + temp += c.name; + struct color* cp = &c; + temp += cp->name; - for(int i = 0, j = 0; i < 10; ++i) { - if ( i == 2 && j == 0) break; - temp += i; - } - - switch(temp) { - case 1: { - temp = 0; - break; + for (int i = 0, j = 0; i < 10; ++i) { + if (i == 2 && j == 0) + break; + temp += i; } - default: { - break; - } - } - return temp; + switch (temp) { + case 1: { + temp = 0; + break; + } + default: { + break; + } + } + + return temp; } diff --git a/examples/c/typecast.c b/examples/c/typecast.c index 7ee0b79..115f3d3 100644 --- a/examples/c/typecast.c +++ b/examples/c/typecast.c @@ -1,5 +1,5 @@ char temp = 0x00L; -int main(){ +int main() { return (temp = 0xEF36L) >= (2L); } diff --git a/examples/c/while_continue_break.c b/examples/c/while_continue_break.c index 30d3eac..77a5d7a 100644 --- a/examples/c/while_continue_break.c +++ b/examples/c/while_continue_break.c @@ -1,19 +1,20 @@ -int nonce = 1; // For random input +int nonce = 1; // For random input int foo() { int sum = 0; int i = 0; int continue_num = nonce % 98; - while(i < 100) { - if(i == continue_num) { + while (i < 100) { + if (i == continue_num) { i++; continue; } sum += i; i++; - if(i == continue_num + 2) break; + if (i == continue_num + 2) + break; } return sum; diff --git a/examples/ir0/hello_main.ir b/examples/ir0/hello_main.ir new file mode 100644 index 0000000..566a6b9 --- /dev/null +++ b/examples/ir0/hello_main.ir @@ -0,0 +1,13 @@ + +fun i32 @main () { +init: + bid: b0 + allocations: + + +block b0: + ret 1:i32 + +block b1: + ret 1:i32 +} diff --git a/examples/ir1/hello_main.ir b/examples/ir1/hello_main.ir new file mode 100644 index 0000000..e051dba --- /dev/null +++ b/examples/ir1/hello_main.ir @@ -0,0 +1,10 @@ + +fun i32 @main () { +init: + bid: b0 + allocations: + + +block b0: + ret 0:i32 +} diff --git a/examples/ir2/hello_main.ir b/examples/ir2/hello_main.ir new file mode 100644 index 0000000..2585836 --- /dev/null +++ b/examples/ir2/hello_main.ir @@ -0,0 +1,10 @@ + +fun i32 @main () { +init: + bid: b0 + allocations: + + +block b0: + ret 1:i32 +} diff --git a/examples/ir3/hello_main.ir b/examples/ir3/hello_main.ir new file mode 100644 index 0000000..2585836 --- /dev/null +++ b/examples/ir3/hello_main.ir @@ -0,0 +1,10 @@ + +fun i32 @main () { +init: + bid: b0 + allocations: + + +block b0: + ret 1:i32 +} diff --git a/examples/ir4/hello_main.ir b/examples/ir4/hello_main.ir new file mode 100644 index 0000000..2585836 --- /dev/null +++ b/examples/ir4/hello_main.ir @@ -0,0 +1,10 @@ + +fun i32 @main () { +init: + bid: b0 + allocations: + + +block b0: + ret 1:i32 +} diff --git a/examples/opt/hello_main.ir b/examples/opt/hello_main.ir new file mode 100644 index 0000000..2585836 --- /dev/null +++ b/examples/opt/hello_main.ir @@ -0,0 +1,10 @@ + +fun i32 @main () { +init: + bid: b0 + allocations: + + +block b0: + ret 1:i32 +} diff --git a/src/c/ast_equiv.rs b/src/c/ast_equiv.rs index b4b0318..a3cc24e 100644 --- a/src/c/ast_equiv.rs +++ b/src/c/ast_equiv.rs @@ -522,13 +522,3 @@ impl IsEquiv for AlignOf { self.0.is_equiv(&other.0) } } - -pub(crate) fn assert_ast_equiv(lhs: &TranslationUnit, rhs: &TranslationUnit) { - if !lhs.is_equiv(rhs) { - panic!( - r#"assertion failed: `(left.is_equiv(right))` - left: `{lhs:?}`, - right: `{rhs:?}`"# - ) - } -} diff --git a/src/c/mod.rs b/src/c/mod.rs index 5d6e942..47d24a7 100644 --- a/src/c/mod.rs +++ b/src/c/mod.rs @@ -2,5 +2,4 @@ mod ast_equiv; mod parse; mod write_c; -pub(crate) use ast_equiv::assert_ast_equiv; pub use parse::Parse; diff --git a/src/c/write_c.rs b/src/c/write_c.rs index b7eeb1a..7cad180 100644 --- a/src/c/write_c.rs +++ b/src/c/write_c.rs @@ -18,6 +18,7 @@ impl WriteString for Node { } impl WriteLine for TranslationUnit { + /// VERY BIG HINT: You should start by understanding the [`writeln!`](https://doc.rust-lang.org/std/macro.writeln.html) macro. fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> { todo!() } diff --git a/src/ir/mod.rs b/src/ir/mod.rs index 8c552d5..4626c14 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -192,6 +192,7 @@ pub struct Block { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Instruction { Nop, + // TODO: Explain what this is, why this is needed. Value { value: Operand, }, diff --git a/src/lib.rs b/src/lib.rs index 2926685..e05d071 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,4 +67,4 @@ pub use opt::{ }; pub use tests::*; pub use utils::*; -pub(crate) use write_base::write; +pub use write_base::write; diff --git a/src/tests.rs b/src/tests.rs index 57cfb88..a2cf847 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -71,12 +71,11 @@ fn modify_asm(unit: &mut asm::Asm, rand_num: i32) { } // Rust sets an exit code of 101 when the process panicked. -// So, we decide KECC sets an exit code of 102 after 101 when the test skipped. +// Set exit code of 102 after 101 to denote that the test skipped. const SKIP_TEST: i32 = 102; /// Tests write_c. pub fn test_write_c(path: &Path) { - // Check if the file has .c extension assert_eq!(path.extension(), Some(std::ffi::OsStr::new("c"))); let unit = Parse .translate(&path) @@ -91,9 +90,17 @@ pub fn test_write_c(path: &Path) { let new_unit = Parse .translate(&temp_file_path.as_path()) .expect("parse failed while parsing the output from implemented printer"); - drop(temp_file); - c::assert_ast_equiv(&unit, &new_unit); - temp_dir.close().expect("temp dir deletion failed"); + + if !unit.is_equiv(&new_unit) { + let mut buf = String::new(); + // FIXME: For some reason we cannot reuse `temp_file`. + let _ = File::open(&temp_file_path) + .unwrap() + .read_to_string(&mut buf) + .unwrap(); + + panic!("[write-c] Failed to correctly write {path:?}.\n\n[incorrect result]\n\n{buf}"); + } } /// Tests irgen. @@ -171,12 +178,10 @@ pub fn test_irgen(path: &Path) { } let status = some_or_exit!(status.code(), SKIP_TEST); - drop(temp_file); - temp_dir.close().expect("temp dir deletion failed"); // Interpret resolved ir let args = Vec::new(); - let result = ir::interp(&ir, args).unwrap_or_else(|interp_error| panic!("{}", interp_error)); + let result = ir::interp(&ir, args).unwrap_or_else(|interp_error| panic!("{interp_error}")); // We only allow a main function whose return type is `int` let (value, width, is_signed) = result.get_int().expect("non-integer value occurs"); assert_eq!(width, 32); @@ -187,7 +192,12 @@ pub fn test_irgen(path: &Path) { // typecasted to `unsigned char`. However, during `creduce` to reduce the code, typecasting may // be nullified. So, we truncate the result value to byte size one more time here. println!("clang (expected): {}, kecc: {}", status as u8, value as u8); - assert_eq!(status as u8, value as u8); + if status as u8 != value as u8 { + stderr().lock().write_fmt(format_args!( + "[irgen] Failed to correctly generate {path:?}.\n\n [incorrect ir]" + )); + write(&ir, &mut stderr()).unwrap(); + } } /// Tests irparse. diff --git a/src/write_base.rs b/src/write_base.rs index 037cf12..f89268b 100644 --- a/src/write_base.rs +++ b/src/write_base.rs @@ -6,7 +6,7 @@ pub(crate) fn write_indent(indent: usize, write: &mut dyn Write) -> Result<()> { } /// A trait for writing a type to a `Write` stream with a new line. -pub(crate) trait WriteLine { +pub trait WriteLine { /// Write `self` to `write`, starting at `indent` number of double spaces, with a newline at the /// end. fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()>; @@ -44,6 +44,6 @@ impl WriteString for Option { } /// Write `t` to `write`. -pub(crate) fn write(t: &T, write: &mut dyn Write) -> Result<()> { +pub fn write(t: &T, write: &mut dyn Write) -> Result<()> { t.write_line(0, write) } diff --git a/tests/test_examples.rs b/tests/test_examples.rs index 6ef08cd..4c5680d 100644 --- a/tests/test_examples.rs +++ b/tests/test_examples.rs @@ -15,7 +15,6 @@ where continue; } - println!("[testing {path:?}]"); f(&path); } } @@ -44,6 +43,8 @@ fn test_opt_between_dirs>(from: &Path, to: &Pat } } +const HELLO_MAIN: &str = "hello_main"; + const IRGEN_SMALL_TEST_IGNORE_LIST: [&str; 12] = [ "examples/c/array.c", "examples/c/array2.c", @@ -84,14 +85,24 @@ const ASMGEN_SMALL_TEST_IGNORE_LIST: [&str; 12] = [ #[test] fn test_examples_write_c() { - test_dir(Path::new("examples/c"), OsStr::new("c"), test_write_c); + println!("[testing write_c for \"examples/c/{HELLO_MAIN}.c\"]"); + test_write_c(Path::new(&format!("examples/c/{HELLO_MAIN}.c"))); + test_dir(Path::new("examples/c"), OsStr::new("c"), |path| { + if !path.to_str().unwrap().contains(HELLO_MAIN) { + println!("[testing write_c for {path:?}]"); + test_write_c(path) + } + }); } #[test] fn test_examples_irgen_small() { + println!("[testing irgen for \"examples/c/{HELLO_MAIN}.c\"]"); + test_irgen(Path::new(&format!("examples/c/{HELLO_MAIN}.c"))); test_dir(Path::new("examples/c"), OsStr::new("c"), |path| { let path_str = &path.to_str().expect("`path` must be transformed to `&str`"); - if !IRGEN_SMALL_TEST_IGNORE_LIST.contains(path_str) { + if !IRGEN_SMALL_TEST_IGNORE_LIST.contains(path_str) && !path_str.contains(HELLO_MAIN) { + println!("[testing irgen for {path:?}]"); test_irgen(path) } }); @@ -101,7 +112,8 @@ fn test_examples_irgen_small() { fn test_examples_irgen_large() { test_dir(Path::new("examples/c"), OsStr::new("c"), |path| { let path_str = &path.to_str().expect("`path` must be transformed to `&str`"); - if IRGEN_SMALL_TEST_IGNORE_LIST.contains(path_str) { + if IRGEN_SMALL_TEST_IGNORE_LIST.contains(path_str) && !path_str.contains(HELLO_MAIN) { + println!("[testing irgen for {path:?}]"); test_irgen(path) } }); @@ -201,6 +213,14 @@ fn test_examples_optimize() { #[test] fn test_examples_asmgen_small() { + for dir in ASMGEN_TEST_DIR_LIST.iter() { + test_dir(Path::new(dir), OsStr::new("ir"), |path| { + if path.to_str().unwrap().contains(HELLO_MAIN) { + println!("[testing asmgen for {path:?}]"); + test_asmgen(path) + } + }); + } for dir in ASMGEN_TEST_DIR_LIST.iter() { test_dir(Path::new(dir), OsStr::new("ir"), |path| { let file_name = &path @@ -208,7 +228,9 @@ fn test_examples_asmgen_small() { .expect("`path` must have a file name") .to_str() .expect("must be transformable to `&str`"); - if !ASMGEN_SMALL_TEST_IGNORE_LIST.contains(file_name) { + if !ASMGEN_SMALL_TEST_IGNORE_LIST.contains(file_name) && !file_name.contains(HELLO_MAIN) + { + println!("[testing asmgen for {path:?}]"); test_asmgen(path) } }); @@ -224,7 +246,9 @@ fn test_examples_asmgen_large() { .expect("`path` must have a file name") .to_str() .expect("must be transformable to `&str`"); - if ASMGEN_SMALL_TEST_IGNORE_LIST.contains(file_name) { + if ASMGEN_SMALL_TEST_IGNORE_LIST.contains(file_name) && !file_name.contains(HELLO_MAIN) + { + println!("[testing asmgen for {path:?}]"); test_asmgen(path) } });