aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-01-24 01:43:01 +0900
committernsfisis <nsfisis@gmail.com>2026-01-24 01:43:01 +0900
commitc780cbb6acd0e0526f2d305138190392bdc8cdd7 (patch)
treedf1edba6eb5778a00e1f4c8a5051414d5bb37e71
parentd179d944c0633d3aa2420009335791b115f67052 (diff)
downloadducc-c780cbb6acd0e0526f2d305138190392bdc8cdd7.tar.gz
ducc-c780cbb6acd0e0526f2d305138190392bdc8cdd7.tar.zst
ducc-c780cbb6acd0e0526f2d305138190392bdc8cdd7.zip
refactor: organize test files
-rw-r--r--tests/arithmetic_operators.c9
-rw-r--r--tests/assignment_operators.c64
-rw-r--r--tests/bitwise_operators.c38
-rw-r--r--tests/bool_type.c10
-rw-r--r--tests/cli.sh79
-rw-r--r--tests/comma_operator.sh36
-rw-r--r--tests/command_line_args.sh18
-rw-r--r--tests/comments.sh24
-rw-r--r--tests/comparison_operators.c12
-rw-r--r--tests/compile_errors.sh32
-rw-r--r--tests/compiler_output.sh16
-rw-r--r--tests/compiler_version.sh6
-rw-r--r--tests/define_macros.sh91
-rw-r--r--tests/empty_preprocessor.sh2
-rw-r--r--tests/enums.sh48
-rw-r--r--tests/ex_fizzbuzz.sh106
-rw-r--r--tests/ex_hello.sh7
-rw-r--r--tests/examples.sh (renamed from tests/example_programs.sh)114
-rw-r--r--tests/expressions.sh (renamed from tests/cast_expressions.sh)138
-rw-r--r--tests/function_macros.sh110
-rw-r--r--tests/function_pointers.sh24
-rw-r--r--tests/functions.c (renamed from tests/function_basics.c)13
-rw-r--r--tests/functions.sh148
-rw-r--r--tests/global_variables.c36
-rw-r--r--tests/goto.sh2
-rw-r--r--tests/identifiers.sh15
-rw-r--r--tests/implicit_return.sh18
-rw-r--r--tests/include.sh189
-rw-r--r--tests/include_errors.sh63
-rw-r--r--tests/include_guards.sh25
-rw-r--r--tests/include_local.sh99
-rw-r--r--tests/increment_operators.sh28
-rw-r--r--tests/keywords.sh14
-rw-r--r--tests/literals.c (renamed from tests/char_literals.c)15
-rw-r--r--tests/local_variables.c38
-rw-r--r--tests/logical_operators.sh67
-rw-r--r--tests/macro_operators.sh134
-rw-r--r--tests/macros.sh426
-rw-r--r--tests/number_literals.c8
-rw-r--r--tests/operators.c122
-rw-r--r--tests/pointer_basics.sh79
-rw-r--r--tests/pointers.sh (renamed from tests/array_basics.sh)155
-rw-r--r--tests/predefined_macros.sh54
-rw-r--r--tests/printf.sh2
-rw-r--r--tests/recursive_functions.c13
-rw-r--r--tests/short_type.sh16
-rw-r--r--tests/stdlib_declarations.sh21
-rw-r--r--tests/string_operations.sh71
-rw-r--r--tests/struct_arrays.sh33
-rw-r--r--tests/struct_basics.sh137
-rw-r--r--tests/struct_initialization.sh107
-rw-r--r--tests/structs.sh364
-rw-r--r--tests/ternary_operator.c6
-rw-r--r--tests/tokenize.sh (renamed from tests/line_continuation.sh)60
-rw-r--r--tests/typedef_struct.sh84
-rw-r--r--tests/types.sh (renamed from tests/sizeof_operator.sh)69
-rw-r--r--tests/undef.sh33
-rw-r--r--tests/variables.c74
-rw-r--r--tests/variadic_functions.sh51
-rw-r--r--tests/void_functions.sh48
60 files changed, 1969 insertions, 1952 deletions
diff --git a/tests/arithmetic_operators.c b/tests/arithmetic_operators.c
deleted file mode 100644
index e7cfe95..0000000
--- a/tests/arithmetic_operators.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <helpers.h>
-
-int main() {
- ASSERT_EQ(42, 42);
- ASSERT_EQ(21, 5 + 20 - 4);
- ASSERT_EQ(26, 2 * 3 + 4 * 5);
- ASSERT_EQ(197, (((3 + 5) / 2) + (5 * (9 - 6)) * (5 + 6 * 7)) % 256);
- ASSERT_EQ(30, (-10 + 20 * -3) + 100);
-}
diff --git a/tests/assignment_operators.c b/tests/assignment_operators.c
deleted file mode 100644
index 1edc574..0000000
--- a/tests/assignment_operators.c
+++ /dev/null
@@ -1,64 +0,0 @@
-#include <helpers.h>
-
-int main() {
- int i = 0;
- for (; i < 5; i += 1) {
- }
- ASSERT_EQ(5, i);
-
- for (i = 5; i >= 0; i -= 1)
- ;
- ASSERT_EQ(-1, i);
-
- int x = 123;
- x *= 456;
- ASSERT_EQ(56088, x);
-
- int y = 120;
- y /= 5;
- ASSERT_EQ(24, y);
-
- int z = 17;
- z %= 7;
- ASSERT_EQ(3, z);
-
- int a = 0x05;
- a |= 0x0A;
- ASSERT_EQ(0x0F, a);
-
- int b = 0x0F;
- b &= 0x0A;
- ASSERT_EQ(0x0A, b);
-
- int c = 7;
- c |= 8;
- ASSERT_EQ(15, c);
-
- int d = 15;
- d &= 6;
- ASSERT_EQ(6, d);
-
- int e = 0x0F;
- e ^= 0x05;
- ASSERT_EQ(0x0A, e);
-
- int f = 3;
- f <<= 2;
- ASSERT_EQ(12, f);
-
- int g = 16;
- g >>= 2;
- ASSERT_EQ(4, g);
-
- int h = -16;
- h >>= 2;
- ASSERT_EQ(-4, h);
-
- int j = 1;
- j <<= 4;
- ASSERT_EQ(16, j);
-
- int k = 64;
- k >>= 3;
- ASSERT_EQ(8, k);
-}
diff --git a/tests/bitwise_operators.c b/tests/bitwise_operators.c
deleted file mode 100644
index e8a5619..0000000
--- a/tests/bitwise_operators.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <helpers.h>
-
-int main() {
- ASSERT_EQ(123, 0 | 123);
- ASSERT_EQ(460, 12 | 456);
-
- ASSERT_EQ(8, 1 << 3);
- ASSERT_EQ(336, 21 << 4);
- ASSERT_EQ(13, 111 >> 3);
- ASSERT_EQ(0, 15 >> 14);
-
- int a = 5;
- int b = 3;
- ASSERT_EQ(1, a & b);
- ASSERT_EQ(7, a | b);
- ASSERT_EQ(6, a ^ b);
- ASSERT_EQ(4, 2 + 3 & 4);
-
- int c = 1 + 2 & 3;
- int d = 4 & 5 ^ 6;
- int e = 1 ^ 2 | 3;
- int f = 0 | 1 & 2;
- ASSERT_EQ(3, c);
- ASSERT_EQ(2, d);
- ASSERT_EQ(3, e);
- ASSERT_EQ(0, f);
-
- ASSERT_EQ(-1, ~0);
- ASSERT_EQ(-2, ~1);
- ASSERT_EQ(-6, ~5);
- ASSERT_EQ(0, ~(-1));
- ASSERT_EQ(5, ~(-6));
-
- int x = 10;
- ASSERT_EQ(-11, ~x);
- ASSERT_EQ(-1, ~(x & 0));
- ASSERT_EQ(-16, ~(x | 5));
-}
diff --git a/tests/bool_type.c b/tests/bool_type.c
deleted file mode 100644
index 7313410..0000000
--- a/tests/bool_type.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <helpers.h>
-
-int main() {
- bool b1 = true, b0 = false;
- ASSERT_EQ(1, b1);
- ASSERT_EQ(0, b0);
- ASSERT_EQ(1, sizeof(b1));
- ASSERT_EQ(1, sizeof(b0));
- ASSERT_EQ(1, sizeof(bool));
-}
diff --git a/tests/cli.sh b/tests/cli.sh
new file mode 100644
index 0000000..fc8a481
--- /dev/null
+++ b/tests/cli.sh
@@ -0,0 +1,79 @@
+# --version
+expected="ducc v0.3.0"
+
+if [[ "$("$ducc" --version)" != "$expected" ]]; then
+ echo "invalid output" >&2
+ exit 1
+fi
+
+# assembly output
+cat > foo.c <<'EOF'
+int main() {}
+EOF
+
+"$ducc" -o bar.s foo.c
+if [[ $? -ne 0 ]]; then
+ exit 1
+fi
+gcc -o a.out bar.s
+./a.out "$@"
+exit_code=$?
+
+if [[ $exit_code -ne 0 ]]; then
+ echo "invalid exit code: $exit_code" >&2
+ exit 1
+fi
+
+# argc/argv
+cat <<'EOF' > expected
+argc = 4
+argv[1] = hoge
+argv[2] = piyo
+argv[3] = fuga
+EOF
+test_diff hoge piyo fuga<<'EOF'
+int printf();
+
+int main(int argc, char** argv) {
+ printf("argc = %d\n", argc);
+ int i;
+ for (i = 1; i < argc; ++i) {
+ printf("argv[%d] = %s\n", i, argv[i]);
+ }
+ return 0;
+}
+EOF
+
+# compile errors
+cat <<'EOF' > expected
+main.c:2: undefined function: f
+EOF
+test_compile_error <<'EOF'
+int main() {
+ f();
+}
+EOF
+
+# TODO: improve error message
+# cat <<'EOF' > expected
+# main.c:1: expected ';' or '{', but got '}'
+# EOF
+cat <<'EOF' > expected
+main.c:1: expected ';', but got '}'
+EOF
+
+test_compile_error <<'EOF'
+int main() }
+EOF
+
+# TODO: improve error message
+# cat <<'EOF' > expected
+# main.c:1: expected ';' or '{', but got '}'
+# EOF
+cat <<'EOF' > expected
+main.c:1: expected ';', but got '123'
+EOF
+
+test_compile_error <<'EOF'
+int main() 123
+EOF
diff --git a/tests/comma_operator.sh b/tests/comma_operator.sh
deleted file mode 100644
index b754cf5..0000000
--- a/tests/comma_operator.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-cat <<'EOF' > expected
-0 0
-1 1
-2 2
-3 3
-4 4
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-int main() {
- int i = 1000;
- int j = 1000;
- for (i = 0, j = 0; i < 5; i++, j++) {
- printf("%d %d\n", i, j);
- }
-}
-EOF
-
-cat <<'EOF' > expected
-1 2 3 4
-0 0 5
-EOF
-
-test_diff <<'EOF'
-int printf();
-int x, y, z = 5;
-int main() {
- int a, b;
- a = 1, b = 2;
- int c = 3, d = 4;
- printf("%d %d %d %d\n", a, b, c, d);
- printf("%d %d %d\n", x, y, z);
-}
-EOF
diff --git a/tests/command_line_args.sh b/tests/command_line_args.sh
deleted file mode 100644
index 7286815..0000000
--- a/tests/command_line_args.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-cat <<'EOF' > expected
-argc = 4
-argv[1] = hoge
-argv[2] = piyo
-argv[3] = fuga
-EOF
-test_diff hoge piyo fuga<<'EOF'
-int printf();
-
-int main(int argc, char** argv) {
- printf("argc = %d\n", argc);
- int i;
- for (i = 1; i < argc; ++i) {
- printf("argv[%d] = %s\n", i, argv[i]);
- }
- return 0;
-}
-EOF
diff --git a/tests/comments.sh b/tests/comments.sh
deleted file mode 100644
index 1318f93..0000000
--- a/tests/comments.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-cat <<'EOF' > expected
-EOF
-test_diff <<'EOF'
-// TODO: check if the token is at the beginning of line.
-// TODO: check if skipped whitespaces do not contain line breaks.
-int main() {
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-EOF
-
-test_diff <<'EOF'
-/* lorem ipsum */
-/*
-lorem ipsum
-*/
-// /*
-/* /*
- */
-int/**/main() {
-}
-EOF
diff --git a/tests/comparison_operators.c b/tests/comparison_operators.c
deleted file mode 100644
index 7e0600d..0000000
--- a/tests/comparison_operators.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <helpers.h>
-
-int main() {
- ASSERT_EQ(1, 0 == 0);
- ASSERT_EQ(0, 123 != 123);
- ASSERT_EQ(1, 123 != 456);
- ASSERT_EQ(0, 123 == 124);
- ASSERT_EQ(1, 123 < 567);
- ASSERT_EQ(1, 123 <= 567);
- ASSERT_EQ(1, 123 <= 123);
- ASSERT_EQ(0, 123 < 123);
-}
diff --git a/tests/compile_errors.sh b/tests/compile_errors.sh
deleted file mode 100644
index e99282b..0000000
--- a/tests/compile_errors.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-cat <<'EOF' > expected
-main.c:2: undefined function: f
-EOF
-test_compile_error <<'EOF'
-int main() {
- f();
-}
-EOF
-
-# TODO: improve error message
-# cat <<'EOF' > expected
-# main.c:1: expected ';' or '{', but got '}'
-# EOF
-cat <<'EOF' > expected
-main.c:1: expected ';', but got '}'
-EOF
-
-test_compile_error <<'EOF'
-int main() }
-EOF
-
-# TODO: improve error message
-# cat <<'EOF' > expected
-# main.c:1: expected ';' or '{', but got '}'
-# EOF
-cat <<'EOF' > expected
-main.c:1: expected ';', but got '123'
-EOF
-
-test_compile_error <<'EOF'
-int main() 123
-EOF
diff --git a/tests/compiler_output.sh b/tests/compiler_output.sh
deleted file mode 100644
index 33c4f17..0000000
--- a/tests/compiler_output.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-cat > foo.c <<'EOF'
-int main() {}
-EOF
-
-"$ducc" -o bar.s foo.c
-if [[ $? -ne 0 ]]; then
- exit 1
-fi
-gcc -o a.out bar.s
-./a.out "$@"
-exit_code=$?
-
-if [[ $exit_code -ne 0 ]]; then
- echo "invalid exit code: $exit_code" >&2
- exit 1
-fi
diff --git a/tests/compiler_version.sh b/tests/compiler_version.sh
deleted file mode 100644
index 76ba104..0000000
--- a/tests/compiler_version.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-expected="ducc v0.3.0"
-
-if [[ "$("$ducc" --version)" != "$expected" ]]; then
- echo "invalid output" >&2
- exit 1
-fi
diff --git a/tests/define_macros.sh b/tests/define_macros.sh
deleted file mode 100644
index c92560f..0000000
--- a/tests/define_macros.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-cat <<'EOF' > expected
-EOF
-test_diff <<'EOF'
-#define A 1
-int main() {
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-1,2,3
-EOF
-test_diff <<'EOF'
-int printf();
-
-#define A 1
-#define B 2
-#define C 3
-
-int main() {
- printf("%d,%d,%d\n", A, B, C);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-0,0,0,0
-EOF
-test_diff <<'EOF'
-int printf();
-
-#define NULL 0
-#define TK_EOF 0
-#define TY_UNKNOWN 0
-#define AST_UNKNOWN 0
-
-int main() {
- printf("%d,%d,%d,%d\n", NULL, TK_EOF, TY_UNKNOWN, AST_UNKNOWN);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-42,123
-EOF
-test_diff <<'EOF'
-int printf();
-
-#define A foo_a
-#define B foo_b
-
-int main() {
- int foo_a = 42;
- int foo_b = 123;
-
- printf("%d,%d\n", A, B);
-
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-123
-EOF
-
-test_diff <<'EOF'
-#define foo() 123
-
-int printf();
-
-int main() {
- printf("%d\n", foo());
-}
-EOF
-
-cat <<'EOF' > expected
-579
-975
-EOF
-
-test_diff <<'EOF'
-#define foo 123 + 456
-#define bar() 321 + 654
-
-int printf();
-
-int main() {
- printf("%d\n", foo);
- printf("%d\n", bar());
-}
-EOF
diff --git a/tests/empty_preprocessor.sh b/tests/empty_preprocessor.sh
index 5a744a8..c9000b3 100644
--- a/tests/empty_preprocessor.sh
+++ b/tests/empty_preprocessor.sh
@@ -1,4 +1,4 @@
-touch expected
+> expected
test_diff <<'EOF'
#
#
diff --git a/tests/enums.sh b/tests/enums.sh
deleted file mode 100644
index 3fc15a0..0000000
--- a/tests/enums.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-cat <<'EOF' > expected
-4
-0,1,2
-EOF
-test_diff <<'EOF'
-int printf();
-
-enum E {
- A,
- B,
- C,
-};
-
-int main() {
- enum E x = A;
- printf("%d\n", sizeof(enum E));
- printf("%d,%d,%d\n", A, B, C);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-10,11,20,21
-0,5,6,6
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-enum E1 {
- A = 10,
- B,
- C = 20,
- D,
-};
-
-enum E2 {
- E,
- F = 5,
- G,
- H = G,
-};
-
-int main() {
- printf("%d,%d,%d,%d\n", A, B, C, D);
- printf("%d,%d,%d,%d\n", E, F, G, H);
-}
-EOF
diff --git a/tests/ex_fizzbuzz.sh b/tests/ex_fizzbuzz.sh
deleted file mode 100644
index b7a9e6b..0000000
--- a/tests/ex_fizzbuzz.sh
+++ /dev/null
@@ -1,106 +0,0 @@
-set -e
-
-cat <<'EOF' > expected
-1
-2
-Fizz
-4
-Buzz
-Fizz
-7
-8
-Fizz
-Buzz
-11
-Fizz
-13
-14
-FizzBuzz
-16
-17
-Fizz
-19
-Buzz
-Fizz
-22
-23
-Fizz
-Buzz
-26
-Fizz
-28
-29
-FizzBuzz
-31
-32
-Fizz
-34
-Buzz
-Fizz
-37
-38
-Fizz
-Buzz
-41
-Fizz
-43
-44
-FizzBuzz
-46
-47
-Fizz
-49
-Buzz
-Fizz
-52
-53
-Fizz
-Buzz
-56
-Fizz
-58
-59
-FizzBuzz
-61
-62
-Fizz
-64
-Buzz
-Fizz
-67
-68
-Fizz
-Buzz
-71
-Fizz
-73
-74
-FizzBuzz
-76
-77
-Fizz
-79
-Buzz
-Fizz
-82
-83
-Fizz
-Buzz
-86
-Fizz
-88
-89
-FizzBuzz
-91
-92
-Fizz
-94
-Buzz
-Fizz
-97
-98
-Fizz
-Buzz
-EOF
-
-test_example fizzbuzz
diff --git a/tests/ex_hello.sh b/tests/ex_hello.sh
deleted file mode 100644
index 750c14a..0000000
--- a/tests/ex_hello.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-set -e
-
-cat <<'EOF' > expected
-Hello, World!
-EOF
-
-test_example hello
diff --git a/tests/example_programs.sh b/tests/examples.sh
index 24b3f29..6b15ed8 100644
--- a/tests/example_programs.sh
+++ b/tests/examples.sh
@@ -1,3 +1,117 @@
+# hello
+cat <<'EOF' > expected
+Hello, World!
+EOF
+
+test_example hello
+
+# fizzbuzz
+cat <<'EOF' > expected
+1
+2
+Fizz
+4
+Buzz
+Fizz
+7
+8
+Fizz
+Buzz
+11
+Fizz
+13
+14
+FizzBuzz
+16
+17
+Fizz
+19
+Buzz
+Fizz
+22
+23
+Fizz
+Buzz
+26
+Fizz
+28
+29
+FizzBuzz
+31
+32
+Fizz
+34
+Buzz
+Fizz
+37
+38
+Fizz
+Buzz
+41
+Fizz
+43
+44
+FizzBuzz
+46
+47
+Fizz
+49
+Buzz
+Fizz
+52
+53
+Fizz
+Buzz
+56
+Fizz
+58
+59
+FizzBuzz
+61
+62
+Fizz
+64
+Buzz
+Fizz
+67
+68
+Fizz
+Buzz
+71
+Fizz
+73
+74
+FizzBuzz
+76
+77
+Fizz
+79
+Buzz
+Fizz
+82
+83
+Fizz
+Buzz
+86
+Fizz
+88
+89
+FizzBuzz
+91
+92
+Fizz
+94
+Buzz
+Fizz
+97
+98
+Fizz
+Buzz
+EOF
+
+test_example fizzbuzz
+
+# example programs
cat <<'EOF' > expected
1
2
diff --git a/tests/cast_expressions.sh b/tests/expressions.sh
index b493e04..dadfade 100644
--- a/tests/cast_expressions.sh
+++ b/tests/expressions.sh
@@ -1,3 +1,141 @@
+# logical operators
+cat <<'EOF' > expected
+foo
+EOF
+test_diff <<'EOF'
+int printf();
+
+int foo() {
+ printf("foo\n");
+ return 0;
+}
+
+int bar() {
+ printf("bar\n");
+ return 1;
+}
+
+int main() {
+ if (foo() && bar()) {
+ printf("baz\n");
+ }
+
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+foo
+bar
+baz
+EOF
+test_diff <<'EOF'
+int printf();
+
+int foo() {
+ printf("foo\n");
+ return 0;
+}
+
+int bar() {
+ printf("bar\n");
+ return 1;
+}
+
+int main() {
+ if (foo() || bar()) {
+ printf("baz\n");
+ }
+
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+0
+1
+0
+EOF
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ printf("%d\n", !1);
+ printf("%d\n", !0);
+ printf("%d\n", !23);
+ return 0;
+}
+EOF
+
+# increment/decrement operators
+cat <<'EOF' > expected
+44
+44
+46
+46
+44
+42
+42
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ int a = 42;
+ ++a;
+ a++;
+ printf("%d\n", a);
+ printf("%d\n", a++);
+ printf("%d\n", ++a);
+ printf("%d\n", a);
+ --a;
+ a--;
+ printf("%d\n", a--);
+ printf("%d\n", --a);
+ printf("%d\n", a);
+}
+EOF
+
+# comma operator
+cat <<'EOF' > expected
+0 0
+1 1
+2 2
+3 3
+4 4
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ int i = 1000;
+ int j = 1000;
+ for (i = 0, j = 0; i < 5; i++, j++) {
+ printf("%d %d\n", i, j);
+ }
+}
+EOF
+
+cat <<'EOF' > expected
+1 2 3 4
+0 0 5
+EOF
+
+test_diff <<'EOF'
+int printf();
+int x, y, z = 5;
+int main() {
+ int a, b;
+ a = 1, b = 2;
+ int c = 3, d = 4;
+ printf("%d %d %d %d\n", a, b, c, d);
+ printf("%d %d %d\n", x, y, z);
+}
+EOF
+
+# cast expressions
cat <<'EOF' > expected
65
65
diff --git a/tests/function_macros.sh b/tests/function_macros.sh
deleted file mode 100644
index 1108650..0000000
--- a/tests/function_macros.sh
+++ /dev/null
@@ -1,110 +0,0 @@
-cat <<'EOF' > expected
-42
-246
-221
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-#define A(x) x
-#define B(x) x+x
-#define C(x, y) x*y
-
-int main() {
- printf("%d\n", A(42));
- printf("%d\n", B
- (123));
- printf("%d\n", C (13, 17));
-}
-EOF
-
-cat <<'EOF' > expected
-123
-EOF
-test_diff <<'EOF'
-#define A(x) x
-
-int printf();
-
-int main() {
- printf("%d\n", A ( 123 ));
-}
-EOF
-
-cat <<'EOF' > expected
-main.c:4: expected ')', but got '<new-line>'
-EOF
-test_compile_error <<'EOF'
-#define A(x) x
-
-int main() {
-#if A (
- 123) < A(345)
- printf("1\n");
-#endif
-}
-EOF
-
-cat <<'EOF' > expected
-42
-100 200
-300
-0
-1 2 3
-15
-42
-123
-879
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-#define ADD(a, b) ((a) + (b))
-#define PRINT_TWO(x, y) printf("%d %d\n", x, y)
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define NESTED(x) (x)
-#define CONCAT3(a, b, c) a ## b ## c
-
-int main() {
- printf("%d\n", ADD(40, 2));
- PRINT_TWO(100, 200);
- printf("%d\n", MAX(100 + 200, 250));
- printf("%d\n");
- NESTED((printf("1 "), printf("2 "), printf("3\n"), 0));
-
- int x = 5, y = 10;
- printf("%d\n", ADD(x + 2, y - 2));
- printf("%d\n", ADD(MAX(10, 20), MAX(15 + 5, 22)));
- printf("%d\n", ADD( 100 , 23 ));
- printf("%d\n", ADD(NESTED((100 + 200)), MAX((123 + 456), (111 + 222))));
-}
-EOF
-
-cat <<'EOF' > expected
-int printf ( const char *, ...);
-
-int main () {
- int foo = 42;
- printf ( %d\n, foo);
-
- int a = 123;
- printf ( %d\n, a);
-}
-EOF
-test_cpp <<'EOF'
-int printf(const char*, ...);
-
-int main() {
-#define foo foo
- int foo = 42;
- printf("%d\n", foo);
-
-#define a b
-#define b c
-#define c a
- int a = 123;
- printf("%d\n", a);
-}
-EOF
diff --git a/tests/function_pointers.sh b/tests/function_pointers.sh
deleted file mode 100644
index cddc623..0000000
--- a/tests/function_pointers.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-cat <<'EOF' > expected
-a
-h
-g
-EOF
-
-test_diff <<'EOF'
-int* f1(int a);
-int (*f2)(int a);
-
-extern int atexit (void (*) (void));
-extern int atexit (void (*fn) (void));
-
-int printf(const char*, ...);
-
-void g() { printf("g\n"); }
-void h() { printf("h\n"); }
-
-int main() {
- atexit(g);
- atexit(h);
- printf("a\n");
-}
-EOF
diff --git a/tests/function_basics.c b/tests/functions.c
index 83fb66e..e9e622e 100644
--- a/tests/function_basics.c
+++ b/tests/functions.c
@@ -96,7 +96,17 @@ int f9(int select, int a, int b, int c, int d, S e, int f, int g) {
}
}
+// recursive functions
+int fib(int n) {
+ if (n <= 1) {
+ return 1;
+ } else {
+ return fib(n - 1) + fib(n - 2);
+ }
+}
+
int main() {
+ // function basics
ASSERT_EQ(66, foo());
ASSERT_EQ(10, 10 * f(1, 2, 3, 4, 5, 6));
ASSERT_EQ(20, 10 * f2(1, 2, 3, 4, 5, 6));
@@ -126,4 +136,7 @@ int main() {
ASSERT_EQ(6, f9(5, 1, 2, 3, 4, s, 7, 8));
ASSERT_EQ(7, f9(6, 1, 2, 3, 4, s, 7, 8));
ASSERT_EQ(8, f9(7, 1, 2, 3, 4, s, 7, 8));
+
+ // recursive functions
+ ASSERT_EQ(89, fib(10));
}
diff --git a/tests/functions.sh b/tests/functions.sh
new file mode 100644
index 0000000..ddae9b2
--- /dev/null
+++ b/tests/functions.sh
@@ -0,0 +1,148 @@
+# function pointers
+cat <<'EOF' > expected
+a
+h
+g
+EOF
+
+test_diff <<'EOF'
+int* f1(int a);
+int (*f2)(int a);
+
+extern int atexit (void (*) (void));
+extern int atexit (void (*fn) (void));
+
+int printf(const char*, ...);
+
+void g() { printf("g\n"); }
+void h() { printf("h\n"); }
+
+int main() {
+ atexit(g);
+ atexit(h);
+ printf("a\n");
+}
+EOF
+
+# void functions
+cat <<'EOF' > expected
+123
+EOF
+test_diff <<'EOF'
+int printf();
+
+void foo_bar(int hoge_piyo) {
+ printf("%d\n", hoge_piyo);
+}
+
+int main() {
+ foo_bar(123);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+EOF
+test_diff <<'EOF'
+struct S {
+ int a;
+};
+
+struct S* f();
+
+struct S* g() {}
+
+int main() {
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+hi
+EOF
+test_diff <<'EOF'
+int printf();
+
+void f() {
+ printf("hi\n");
+ return;
+}
+
+int main() {
+ f();
+ return 0;
+}
+EOF
+
+# variadic functions
+cat <<'EOF' > expected
+123
+456 789
+EOF
+
+test_diff <<'EOF'
+#include <stdarg.h>
+
+int fprintf();
+
+struct FILE;
+typedef struct FILE FILE;
+
+extern FILE* stdout;
+
+int vfprintf(FILE*, const char*, va_list);
+
+void fatal_error(const char* msg, ...) {
+ va_list args;
+ va_start(args, msg);
+ vfprintf(stdout, msg, args);
+ va_end(args);
+ fprintf(stdout, "\n");
+}
+
+int main() {
+ fatal_error("%d", 123);
+ fatal_error("%d %d", 456, 789);
+ return 0;
+}
+EOF
+
+test_exit_code 0 <<'EOF'
+#include <stdarg.h>
+#include <helpers.h>
+
+int sum(int n, ...) {
+ va_list args;
+ va_start(args, n);
+ int s = 0;
+ for (int i = 0; i < n; ++i) {
+ s += va_arg(args, int);
+ }
+ va_end(args);
+ return s;
+}
+
+int main() {
+ ASSERT_EQ(400, sum(5, 100, 90, 80, 70, 60));
+}
+EOF
+
+# implicit return
+# C99: 5.1.2.2.3
+test_exit_code 0 <<'EOF'
+int main() {
+}
+EOF
+
+test_exit_code 0 <<'EOF'
+int main() {
+ 1 + 2 + 3;
+}
+EOF
+
+test_exit_code 0 <<'EOF'
+int main() {
+ if (1);
+ else return 1;
+}
+EOF
diff --git a/tests/global_variables.c b/tests/global_variables.c
deleted file mode 100644
index 20e0a64..0000000
--- a/tests/global_variables.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <helpers.h>
-
-int printf(const char*, ...);
-int strcmp(const char*, const char*);
-
-int a;
-int* b = &a;
-int c[10];
-int* d = c;
-int e, *f = e, g[10], *h = g;
-
-char i = 42;
-short j = 123;
-int k = 999;
-
-char l[6] = "hello";
-
-int main() {
- *b = 123;
- ASSERT_EQ(123, a);
-
- d[2] = 42;
- ASSERT_EQ(42, c[2]);
-
- *f = 456;
- ASSERT_EQ(456, e);
-
- h[5] = 789;
- ASSERT_EQ(789, g[5]);
-
- ASSERT_EQ(42, i);
- ASSERT_EQ(123, j);
- ASSERT_EQ(999, k);
-
- ASSERT_EQ(0, strcmp("hello", l));
-}
diff --git a/tests/goto.sh b/tests/goto.sh
index 1e28a51..4d00031 100644
--- a/tests/goto.sh
+++ b/tests/goto.sh
@@ -1,4 +1,4 @@
-touch expected
+> expected
test_diff <<'EOF'
int main() {
goto end;
diff --git a/tests/identifiers.sh b/tests/identifiers.sh
deleted file mode 100644
index ae00bd3..0000000
--- a/tests/identifiers.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-cat <<'EOF' > expected
-42,123
-EOF
-test_diff <<'EOF'
-int printf();
-
-int main() {
- int _a = 42;
- int _b = 123;
-
- printf("%d,%d\n", _a, _b);
-
- return 0;
-}
-EOF
diff --git a/tests/implicit_return.sh b/tests/implicit_return.sh
deleted file mode 100644
index 20a8bed..0000000
--- a/tests/implicit_return.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-# C99: 5.1.2.2.3
-test_exit_code 0 <<'EOF'
-int main() {
-}
-EOF
-
-test_exit_code 0 <<'EOF'
-int main() {
- 1 + 2 + 3;
-}
-EOF
-
-test_exit_code 0 <<'EOF'
-int main() {
- if (1);
- else return 1;
-}
-EOF
diff --git a/tests/include.sh b/tests/include.sh
new file mode 100644
index 0000000..33cabb4
--- /dev/null
+++ b/tests/include.sh
@@ -0,0 +1,189 @@
+cat <<'EOF' > header.h
+int add(int a, int b) {
+ return a + b;
+}
+
+int printf(const char*, ...);
+EOF
+
+cat <<'EOF' > expected
+8
+EOF
+test_diff <<'EOF'
+#include "header.h"
+
+int main() {
+ printf("%d\n", add(5, 3));
+ return 0;
+}
+EOF
+
+mkdir -p foo
+cat <<'EOF' > bar.h
+#include "baz.h"
+EOF
+cat <<'EOF' > baz.h
+#define A 123
+EOF
+cat <<'EOF' > foo/bar.h
+#include "baz.h"
+EOF
+cat <<'EOF' > foo/baz.h
+#define A 456
+EOF
+
+cat <<'EOF' > expected
+123
+456
+EOF
+test_diff <<'EOF'
+int printf(const char*, ...);
+
+int main() {
+#include "bar.h"
+ printf("%d\n", A);
+
+#undef A
+
+#include "foo/bar.h"
+ printf("%d\n", A);
+}
+EOF
+
+cat <<'EOF' > expected
+12
+EOF
+
+cat <<'EOF' > math.h
+int multiply(int a, int b) {
+ return a * b;
+}
+EOF
+
+cat <<'EOF' > calc.h
+#include "math.h"
+
+int calculate(int x) {
+ return multiply(x, 2);
+}
+
+int printf(const char*, ...);
+EOF
+
+test_diff <<'EOF'
+#include "calc.h"
+
+int main() {
+ printf("%d\n", calculate(6));
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+42
+EOF
+
+cat <<'EOF' > header.h
+#define A 42
+EOF
+
+test_diff <<'EOF'
+#include "header.h"
+
+int printf();
+
+int main() {
+ printf("%d\n", A);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+42
+EOF
+
+cat <<'EOF' > header.h
+#ifndef HEADER_H
+#define HEADER_H
+
+int f() { return 42; }
+
+#endif
+EOF
+
+test_diff <<'EOF'
+#include "header.h"
+#include "header.h"
+#include "header.h"
+
+int printf();
+
+int main() {
+ printf("%d\n", HEADER_H HEADER_H HEADER_H f() HEADER_H HEADER_H HEADER_H);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+main.c:1: cannot open include file: "nonexistent.h"
+EOF
+
+test_compile_error <<'EOF'
+#include "nonexistent.h"
+
+int main() {
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+include depth limit exceeded
+EOF
+
+# Create circular include files
+cat <<'EOF' > a.h
+#include "b.h"
+int a() { return 1; }
+EOF
+
+cat <<'EOF' > b.h
+#include "a.h"
+int b() { return 2; }
+EOF
+
+test_compile_error <<'EOF'
+#include "a.h"
+
+int main() {
+ a() + b();
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+main.c:1: cannot open include file: "hoge.h"
+EOF
+
+test_compile_error <<'EOF'
+#include "hoge.h"
+EOF
+
+cat <<'EOF' > expected
+main.c:1: cannot resolve include file name: <hoge.h>
+EOF
+
+test_compile_error <<'EOF'
+#include <hoge.h>
+EOF
+
+cat <<'EOF' > expected
+42
+EOF
+
+test_exit_code 0 <<'EOF'
+#ifdef FOO
+#include FOO
+#endif
+
+int main() { 1 < 2; }
+EOF
diff --git a/tests/include_errors.sh b/tests/include_errors.sh
deleted file mode 100644
index e0f856e..0000000
--- a/tests/include_errors.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-cat <<'EOF' > expected
-main.c:1: cannot open include file: "nonexistent.h"
-EOF
-
-test_compile_error <<'EOF'
-#include "nonexistent.h"
-
-int main() {
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-include depth limit exceeded
-EOF
-
-# Create circular include files
-cat <<'EOF' > a.h
-#include "b.h"
-int a() { return 1; }
-EOF
-
-cat <<'EOF' > b.h
-#include "a.h"
-int b() { return 2; }
-EOF
-
-test_compile_error <<'EOF'
-#include "a.h"
-
-int main() {
- a() + b();
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-main.c:1: cannot open include file: "hoge.h"
-EOF
-
-test_compile_error <<'EOF'
-#include "hoge.h"
-EOF
-
-cat <<'EOF' > expected
-main.c:1: cannot resolve include file name: <hoge.h>
-EOF
-
-test_compile_error <<'EOF'
-#include <hoge.h>
-EOF
-
-cat <<'EOF' > expected
-42
-EOF
-
-test_exit_code 0 <<'EOF'
-#ifdef FOO
-#include FOO
-#endif
-
-int main() { 1 < 2; }
-EOF
diff --git a/tests/include_guards.sh b/tests/include_guards.sh
deleted file mode 100644
index f8f0462..0000000
--- a/tests/include_guards.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-cat <<'EOF' > expected
-42
-EOF
-
-cat <<'EOF' > header.h
-#ifndef HEADER_H
-#define HEADER_H
-
-int f() { return 42; }
-
-#endif
-EOF
-
-test_diff <<'EOF'
-#include "header.h"
-#include "header.h"
-#include "header.h"
-
-int printf();
-
-int main() {
- printf("%d\n", HEADER_H HEADER_H HEADER_H f() HEADER_H HEADER_H HEADER_H);
- return 0;
-}
-EOF
diff --git a/tests/include_local.sh b/tests/include_local.sh
deleted file mode 100644
index 05c42b7..0000000
--- a/tests/include_local.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-cat <<'EOF' > header.h
-int add(int a, int b) {
- return a + b;
-}
-
-int printf(const char*, ...);
-EOF
-
-cat <<'EOF' > expected
-8
-EOF
-test_diff <<'EOF'
-#include "header.h"
-
-int main() {
- printf("%d\n", add(5, 3));
- return 0;
-}
-EOF
-
-mkdir -p foo
-cat <<'EOF' > bar.h
-#include "baz.h"
-EOF
-cat <<'EOF' > baz.h
-#define A 123
-EOF
-cat <<'EOF' > foo/bar.h
-#include "baz.h"
-EOF
-cat <<'EOF' > foo/baz.h
-#define A 456
-EOF
-
-cat <<'EOF' > expected
-123
-456
-EOF
-test_diff <<'EOF'
-int printf(const char*, ...);
-
-int main() {
-#include "bar.h"
- printf("%d\n", A);
-
-#undef A
-
-#include "foo/bar.h"
- printf("%d\n", A);
-}
-EOF
-
-cat <<'EOF' > expected
-12
-EOF
-
-cat <<'EOF' > math.h
-int multiply(int a, int b) {
- return a * b;
-}
-EOF
-
-cat <<'EOF' > calc.h
-#include "math.h"
-
-int calculate(int x) {
- return multiply(x, 2);
-}
-
-int printf(const char*, ...);
-EOF
-
-test_diff <<'EOF'
-#include "calc.h"
-
-int main() {
- printf("%d\n", calculate(6));
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-42
-EOF
-
-cat <<'EOF' > header.h
-#define A 42
-EOF
-
-test_diff <<'EOF'
-#include "header.h"
-
-int printf();
-
-int main() {
- printf("%d\n", A);
- return 0;
-}
-EOF
diff --git a/tests/increment_operators.sh b/tests/increment_operators.sh
deleted file mode 100644
index e7fb221..0000000
--- a/tests/increment_operators.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-cat <<'EOF' > expected
-44
-44
-46
-46
-44
-42
-42
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-int main() {
- int a = 42;
- ++a;
- a++;
- printf("%d\n", a);
- printf("%d\n", a++);
- printf("%d\n", ++a);
- printf("%d\n", a);
- --a;
- a--;
- printf("%d\n", a--);
- printf("%d\n", --a);
- printf("%d\n", a);
-}
-EOF
diff --git a/tests/keywords.sh b/tests/keywords.sh
deleted file mode 100644
index 0bdb6f7..0000000
--- a/tests/keywords.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-cat <<'EOF' > expected
-
-
-int printf ();
-int main () {}
-EOF
-
-test_cpp <<'EOF'
-// A keyword is treated as a normal identifier in preprocessing phase.
-#define auto int
-
-auto printf();
-auto main() {}
-EOF
diff --git a/tests/char_literals.c b/tests/literals.c
index cc592ff..7b84ea1 100644
--- a/tests/char_literals.c
+++ b/tests/literals.c
@@ -1,6 +1,13 @@
#include <helpers.h>
int main() {
+ // number literals
+ ASSERT_EQ(0, 0);
+ ASSERT_EQ(291, 0x123);
+ ASSERT_EQ(3405691582, 0xcafebabe);
+ ASSERT_EQ(436, 0664);
+
+ // char literals
ASSERT_EQ(97, 'a');
ASSERT_EQ(48, '0');
ASSERT_EQ(92, '\\');
@@ -22,4 +29,12 @@ int main() {
ASSERT_EQ(0, '\0');
ASSERT_EQ(27, '\e');
+
+ // bool type
+ bool b1 = true, b0 = false;
+ ASSERT_EQ(1, b1);
+ ASSERT_EQ(0, b0);
+ ASSERT_EQ(1, sizeof(b1));
+ ASSERT_EQ(1, sizeof(b0));
+ ASSERT_EQ(1, sizeof(bool));
}
diff --git a/tests/local_variables.c b/tests/local_variables.c
deleted file mode 100644
index ac63f04..0000000
--- a/tests/local_variables.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <helpers.h>
-
-int main() {
- int foo;
- foo = 42;
- ASSERT_EQ(42, foo);
-
- int bar;
- bar = 28;
- ASSERT_EQ(70, foo + bar);
-
- int a1;
- int a2;
- int a3;
- int a4;
- int a5;
- int a6;
- int a7;
- int a8;
- int a9;
-
- a1 = 1;
- a2 = 2;
- a3 = 3;
- a4 = 4;
- a5 = 5;
- a6 = 6;
- a7 = 7;
- a8 = 8;
- a9 = 9;
-
- ASSERT_EQ(45, a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + 0);
-
- int d = 2, e = d, f = d + e;
- ASSERT_EQ(2, d);
- ASSERT_EQ(2, e);
- ASSERT_EQ(4, f);
-}
diff --git a/tests/logical_operators.sh b/tests/logical_operators.sh
deleted file mode 100644
index b4332e5..0000000
--- a/tests/logical_operators.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-cat <<'EOF' > expected
-foo
-EOF
-test_diff <<'EOF'
-int printf();
-
-int foo() {
- printf("foo\n");
- return 0;
-}
-
-int bar() {
- printf("bar\n");
- return 1;
-}
-
-int main() {
- if (foo() && bar()) {
- printf("baz\n");
- }
-
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-foo
-bar
-baz
-EOF
-test_diff <<'EOF'
-int printf();
-
-int foo() {
- printf("foo\n");
- return 0;
-}
-
-int bar() {
- printf("bar\n");
- return 1;
-}
-
-int main() {
- if (foo() || bar()) {
- printf("baz\n");
- }
-
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-0
-1
-0
-EOF
-test_diff <<'EOF'
-int printf();
-
-int main() {
- printf("%d\n", !1);
- printf("%d\n", !0);
- printf("%d\n", !23);
- return 0;
-}
-EOF
diff --git a/tests/macro_operators.sh b/tests/macro_operators.sh
deleted file mode 100644
index 2954d53..0000000
--- a/tests/macro_operators.sh
+++ /dev/null
@@ -1,134 +0,0 @@
-cat <<'EOF' > expected
-int printf ();
-
-
-int foobar = 100;
-int prefix_test = 200;
-int test_suffix = 300;
-
-int var_1 = 10;
-int var_2 = 20;
-
-int var_A = 30;
-
-int number_12 = 12;
-
-int bazqux = 42;
-
-int main () {
- printf ( foobar=%d\n, foobar);
- printf ( prefix_test=%d\n, prefix_test);
- printf ( test_suffix=%d\n, test_suffix);
- printf ( var_1=%d\n, var_1);
- printf ( var_2=%d\n, var_2);
- printf ( var_A=%d\n, var_A);
- printf ( number_12=%d\n, number_12);
- return 0;
-}
-EOF
-
-test_cpp <<'EOF'
-int printf();
-
-#define CONCAT(a, b) a##b
-#define PREFIX(name) prefix_##name
-#define SUFFIX(name) name##_suffix
-
-int CONCAT(foo, bar) = 100;
-int PREFIX(test) = 200;
-int SUFFIX(test) = 300;
-
-#define MAKE_VAR(n) var_##n
-int MAKE_VAR(1) = 10;
-int MAKE_VAR(2) = 20;
-
-#define A 0
-int MAKE_VAR(A) = 30;
-
-#define NUMBER(x, y) number_##x##y
-int NUMBER(1, 2) = 12;
-
-#define CONCAT2(a, b) a ## b
-int CONCAT2(baz, qux) = 42;
-
-int main() {
- printf("foobar=%d\n", foobar);
- printf("prefix_test=%d\n", prefix_test);
- printf("test_suffix=%d\n", test_suffix);
- printf("var_1=%d\n", var_1);
- printf("var_2=%d\n", var_2);
- printf("var_A=%d\n", var_A);
- printf("number_12=%d\n", number_12);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-int printf ( const char *, ...);
-
-
-int H ( int n) { return n; }
-
-int main () {
- printf ( %d\n, H ( 123));
-}
-EOF
-
-test_cpp <<'EOF'
-int printf(const char*, ...);
-
-#define F(x) CHECK(G(x))
-#define G(x) CHECK(H(x))
-#define CHECK(x) x
-
-int H(int n) { return n; }
-
-int main() {
- printf("%d\n", F(123));
-}
-EOF
-
-test_exit_code 0 <<'EOF'
-#include <helpers.h>
-
-int strcmp(const char*, const char*);
-
-#define FOO 42
-
-#define TO_STRING(x) TO_STRING_HELPER(x)
-#define TO_STRING_HELPER(x) #x
-#define BAR TO_STRING(FOO)
-
-#define TO_STRING2(x) #x
-#define BAZ TO_STRING2(FOO)
-
-int main() {
- ASSERT_EQ(0, strcmp("42", BAR));
- ASSERT_EQ(0, strcmp("FOO", BAZ));
-}
-EOF
-
-test_exit_code 0 <<'EOF'
-#include <helpers.h>
-
-#define CONCAT3(x, y, z) x##y##z
-#define FOO CONCAT3(, 2, 3)
-#define BAR CONCAT3(1, , 3)
-#define BAZ CONCAT3(1, 2, )
-
-int main() {
- ASSERT_EQ(23, FOO);
- ASSERT_EQ(13, BAR);
- ASSERT_EQ(12, BAZ);
-}
-EOF
-
-cat <<'EOF' > expected
-foo
-EOF
-
-test_cpp <<'EOF'
-#define CONCAT(x, y) x ## y
-#define CONCAT2(name, r) CONCAT(name, r)
-CONCAT2(foo,)
-EOF
diff --git a/tests/macros.sh b/tests/macros.sh
new file mode 100644
index 0000000..69baae5
--- /dev/null
+++ b/tests/macros.sh
@@ -0,0 +1,426 @@
+cat <<'EOF' > expected
+EOF
+test_diff <<'EOF'
+#define A 1
+int main() {
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+1,2,3
+EOF
+test_diff <<'EOF'
+int printf();
+
+#define A 1
+#define B 2
+#define C 3
+
+int main() {
+ printf("%d,%d,%d\n", A, B, C);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+0,0,0,0
+EOF
+test_diff <<'EOF'
+int printf();
+
+#define NULL 0
+#define TK_EOF 0
+#define TY_UNKNOWN 0
+#define AST_UNKNOWN 0
+
+int main() {
+ printf("%d,%d,%d,%d\n", NULL, TK_EOF, TY_UNKNOWN, AST_UNKNOWN);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+42,123
+EOF
+test_diff <<'EOF'
+int printf();
+
+#define A foo_a
+#define B foo_b
+
+int main() {
+ int foo_a = 42;
+ int foo_b = 123;
+
+ printf("%d,%d\n", A, B);
+
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+123
+EOF
+
+test_diff <<'EOF'
+#define foo() 123
+
+int printf();
+
+int main() {
+ printf("%d\n", foo());
+}
+EOF
+
+cat <<'EOF' > expected
+579
+975
+EOF
+
+test_diff <<'EOF'
+#define foo 123 + 456
+#define bar() 321 + 654
+
+int printf();
+
+int main() {
+ printf("%d\n", foo);
+ printf("%d\n", bar());
+}
+EOF
+
+cat <<'EOF' > expected
+42
+246
+221
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+#define A(x) x
+#define B(x) x+x
+#define C(x, y) x*y
+
+int main() {
+ printf("%d\n", A(42));
+ printf("%d\n", B
+ (123));
+ printf("%d\n", C (13, 17));
+}
+EOF
+
+cat <<'EOF' > expected
+123
+EOF
+test_diff <<'EOF'
+#define A(x) x
+
+int printf();
+
+int main() {
+ printf("%d\n", A ( 123 ));
+}
+EOF
+
+cat <<'EOF' > expected
+main.c:4: expected ')', but got '<new-line>'
+EOF
+test_compile_error <<'EOF'
+#define A(x) x
+
+int main() {
+#if A (
+ 123) < A(345)
+ printf("1\n");
+#endif
+}
+EOF
+
+cat <<'EOF' > expected
+42
+100 200
+300
+0
+1 2 3
+15
+42
+123
+879
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+#define ADD(a, b) ((a) + (b))
+#define PRINT_TWO(x, y) printf("%d %d\n", x, y)
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define NESTED(x) (x)
+#define CONCAT3(a, b, c) a ## b ## c
+
+int main() {
+ printf("%d\n", ADD(40, 2));
+ PRINT_TWO(100, 200);
+ printf("%d\n", MAX(100 + 200, 250));
+ printf("%d\n");
+ NESTED((printf("1 "), printf("2 "), printf("3\n"), 0));
+
+ int x = 5, y = 10;
+ printf("%d\n", ADD(x + 2, y - 2));
+ printf("%d\n", ADD(MAX(10, 20), MAX(15 + 5, 22)));
+ printf("%d\n", ADD( 100 , 23 ));
+ printf("%d\n", ADD(NESTED((100 + 200)), MAX((123 + 456), (111 + 222))));
+}
+EOF
+
+cat <<'EOF' > expected
+int printf ( const char *, ...);
+
+int main () {
+ int foo = 42;
+ printf ( %d\n, foo);
+
+ int a = 123;
+ printf ( %d\n, a);
+}
+EOF
+test_cpp <<'EOF'
+int printf(const char*, ...);
+
+int main() {
+#define foo foo
+ int foo = 42;
+ printf("%d\n", foo);
+
+#define a b
+#define b c
+#define c a
+ int a = 123;
+ printf("%d\n", a);
+}
+EOF
+
+cat <<'EOF' > expected
+int printf ();
+
+
+int foobar = 100;
+int prefix_test = 200;
+int test_suffix = 300;
+
+int var_1 = 10;
+int var_2 = 20;
+
+int var_A = 30;
+
+int number_12 = 12;
+
+int bazqux = 42;
+
+int main () {
+ printf ( foobar=%d\n, foobar);
+ printf ( prefix_test=%d\n, prefix_test);
+ printf ( test_suffix=%d\n, test_suffix);
+ printf ( var_1=%d\n, var_1);
+ printf ( var_2=%d\n, var_2);
+ printf ( var_A=%d\n, var_A);
+ printf ( number_12=%d\n, number_12);
+ return 0;
+}
+EOF
+
+test_cpp <<'EOF'
+int printf();
+
+#define CONCAT(a, b) a##b
+#define PREFIX(name) prefix_##name
+#define SUFFIX(name) name##_suffix
+
+int CONCAT(foo, bar) = 100;
+int PREFIX(test) = 200;
+int SUFFIX(test) = 300;
+
+#define MAKE_VAR(n) var_##n
+int MAKE_VAR(1) = 10;
+int MAKE_VAR(2) = 20;
+
+#define A 0
+int MAKE_VAR(A) = 30;
+
+#define NUMBER(x, y) number_##x##y
+int NUMBER(1, 2) = 12;
+
+#define CONCAT2(a, b) a ## b
+int CONCAT2(baz, qux) = 42;
+
+int main() {
+ printf("foobar=%d\n", foobar);
+ printf("prefix_test=%d\n", prefix_test);
+ printf("test_suffix=%d\n", test_suffix);
+ printf("var_1=%d\n", var_1);
+ printf("var_2=%d\n", var_2);
+ printf("var_A=%d\n", var_A);
+ printf("number_12=%d\n", number_12);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+int printf ( const char *, ...);
+
+
+int H ( int n) { return n; }
+
+int main () {
+ printf ( %d\n, H ( 123));
+}
+EOF
+
+test_cpp <<'EOF'
+int printf(const char*, ...);
+
+#define F(x) CHECK(G(x))
+#define G(x) CHECK(H(x))
+#define CHECK(x) x
+
+int H(int n) { return n; }
+
+int main() {
+ printf("%d\n", F(123));
+}
+EOF
+
+test_exit_code 0 <<'EOF'
+#include <helpers.h>
+
+int strcmp(const char*, const char*);
+
+#define FOO 42
+
+#define TO_STRING(x) TO_STRING_HELPER(x)
+#define TO_STRING_HELPER(x) #x
+#define BAR TO_STRING(FOO)
+
+#define TO_STRING2(x) #x
+#define BAZ TO_STRING2(FOO)
+
+int main() {
+ ASSERT_EQ(0, strcmp("42", BAR));
+ ASSERT_EQ(0, strcmp("FOO", BAZ));
+}
+EOF
+
+test_exit_code 0 <<'EOF'
+#include <helpers.h>
+
+#define CONCAT3(x, y, z) x##y##z
+#define FOO CONCAT3(, 2, 3)
+#define BAR CONCAT3(1, , 3)
+#define BAZ CONCAT3(1, 2, )
+
+int main() {
+ ASSERT_EQ(23, FOO);
+ ASSERT_EQ(13, BAR);
+ ASSERT_EQ(12, BAZ);
+}
+EOF
+
+cat <<'EOF' > expected
+foo
+EOF
+
+test_cpp <<'EOF'
+#define CONCAT(x, y) x ## y
+#define CONCAT2(name, r) CONCAT(name, r)
+CONCAT2(foo,)
+EOF
+
+cat <<'EOF' > expected
+1
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ printf("%d\n", __ducc__);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+main.c
+main.c
+main.c
+EOF
+
+cat <<'EOF' > header.h
+#define A __FILE__
+EOF
+
+test_diff <<'EOF'
+#define B __FILE__
+#include "header.h"
+int printf();
+int main() {
+ printf("%s\n", __FILE__);
+ printf("%s\n", B);
+ printf("%s\n", A);
+}
+EOF
+
+cat <<'EOF' > expected
+5
+6 6
+7 7
+EOF
+
+cat <<'EOF' > header.h
+#define A __LINE__
+EOF
+
+test_diff <<'EOF'
+#define B __LINE__
+#include "header.h"
+int printf();
+int main() {
+ printf("%d\n", __LINE__);
+ printf("%d %d\n", B, B);
+ printf("%d %d\n", A, A);
+}
+EOF
+
+cat <<'EOF' > expected
+int printf ();
+
+int main () {
+
+ printf ( A is defined\n);
+
+
+ printf ( A is undefined\n);
+}
+EOF
+
+test_cpp <<'EOF'
+int printf();
+
+int main() {
+#define A 1
+
+#ifdef A
+ printf("A is defined\n");
+#else
+ printf("A is undefined\n");
+#endif
+
+#undef A
+
+#ifdef A
+ printf("A is defined\n");
+#else
+ printf("A is undefined\n");
+#endif
+}
+EOF
diff --git a/tests/number_literals.c b/tests/number_literals.c
deleted file mode 100644
index c28e4e3..0000000
--- a/tests/number_literals.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <helpers.h>
-
-int main() {
- ASSERT_EQ(0, 0);
- ASSERT_EQ(291, 0x123);
- ASSERT_EQ(3405691582, 0xcafebabe);
- ASSERT_EQ(436, 0664);
-}
diff --git a/tests/operators.c b/tests/operators.c
new file mode 100644
index 0000000..9e9ba08
--- /dev/null
+++ b/tests/operators.c
@@ -0,0 +1,122 @@
+#include <helpers.h>
+
+int main() {
+ // arithmetic operators
+ ASSERT_EQ(42, 42);
+ ASSERT_EQ(21, 5 + 20 - 4);
+ ASSERT_EQ(26, 2 * 3 + 4 * 5);
+ ASSERT_EQ(197, (((3 + 5) / 2) + (5 * (9 - 6)) * (5 + 6 * 7)) % 256);
+ ASSERT_EQ(30, (-10 + 20 * -3) + 100);
+
+ // comparison operators
+ ASSERT_EQ(1, 0 == 0);
+ ASSERT_EQ(0, 123 != 123);
+ ASSERT_EQ(1, 123 != 456);
+ ASSERT_EQ(0, 123 == 124);
+ ASSERT_EQ(1, 123 < 567);
+ ASSERT_EQ(1, 123 <= 567);
+ ASSERT_EQ(1, 123 <= 123);
+ ASSERT_EQ(0, 123 < 123);
+
+ // bitwise operators
+ ASSERT_EQ(123, 0 | 123);
+ ASSERT_EQ(460, 12 | 456);
+
+ ASSERT_EQ(8, 1 << 3);
+ ASSERT_EQ(336, 21 << 4);
+ ASSERT_EQ(13, 111 >> 3);
+ ASSERT_EQ(0, 15 >> 14);
+
+ int a = 5;
+ int b = 3;
+ ASSERT_EQ(1, a & b);
+ ASSERT_EQ(7, a | b);
+ ASSERT_EQ(6, a ^ b);
+ ASSERT_EQ(4, 2 + 3 & 4);
+
+ int c = 1 + 2 & 3;
+ int d = 4 & 5 ^ 6;
+ int e = 1 ^ 2 | 3;
+ int f = 0 | 1 & 2;
+ ASSERT_EQ(3, c);
+ ASSERT_EQ(2, d);
+ ASSERT_EQ(3, e);
+ ASSERT_EQ(0, f);
+
+ ASSERT_EQ(-1, ~0);
+ ASSERT_EQ(-2, ~1);
+ ASSERT_EQ(-6, ~5);
+ ASSERT_EQ(0, ~(-1));
+ ASSERT_EQ(5, ~(-6));
+
+ int x = 10;
+ ASSERT_EQ(-11, ~x);
+ ASSERT_EQ(-1, ~(x & 0));
+ ASSERT_EQ(-16, ~(x | 5));
+
+ // assignment operators
+ int i = 0;
+ for (; i < 5; i += 1) {
+ }
+ ASSERT_EQ(5, i);
+
+ for (i = 5; i >= 0; i -= 1)
+ ;
+ ASSERT_EQ(-1, i);
+
+ x = 123;
+ x *= 456;
+ ASSERT_EQ(56088, x);
+
+ int y = 120;
+ y /= 5;
+ ASSERT_EQ(24, y);
+
+ int z = 17;
+ z %= 7;
+ ASSERT_EQ(3, z);
+
+ a = 0x05;
+ a |= 0x0A;
+ ASSERT_EQ(0x0F, a);
+
+ b = 0x0F;
+ b &= 0x0A;
+ ASSERT_EQ(0x0A, b);
+
+ c = 7;
+ c |= 8;
+ ASSERT_EQ(15, c);
+
+ d = 15;
+ d &= 6;
+ ASSERT_EQ(6, d);
+
+ e = 0x0F;
+ e ^= 0x05;
+ ASSERT_EQ(0x0A, e);
+
+ f = 3;
+ f <<= 2;
+ ASSERT_EQ(12, f);
+
+ int g = 16;
+ g >>= 2;
+ ASSERT_EQ(4, g);
+
+ int h = -16;
+ h >>= 2;
+ ASSERT_EQ(-4, h);
+
+ int j = 1;
+ j <<= 4;
+ ASSERT_EQ(16, j);
+
+ int k = 64;
+ k >>= 3;
+ ASSERT_EQ(8, k);
+
+ // ternary operator
+ ASSERT_EQ(2, 1 ? 2 : 3);
+ ASSERT_EQ(5, 0 ? 4 : 5);
+}
diff --git a/tests/pointer_basics.sh b/tests/pointer_basics.sh
deleted file mode 100644
index 6faa421..0000000
--- a/tests/pointer_basics.sh
+++ /dev/null
@@ -1,79 +0,0 @@
-cat <<'EOF' > expected
-EOF
-test_diff <<'EOF'
-int main() {
- int a1;
- int* a2;
- char a3;
- char* a4;
- long a5;
- long* a6;
- void* a8;
- int** a10;
- char** a12;
- long** a14;
- void** a16;
- int*** a18;
- char*** a20;
- long*** a22;
- void*** a24;
- int* const* const* a25;
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-42 42
-EOF
-test_diff <<'EOF'
-int printf();
-
-int main() {
- int x;
- int* y;
- y = &x;
- *y = 42;
- printf("%d %d\n", x, *y);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-3
-3
-3
-EOF
-test_diff <<'EOF'
-int printf();
-
-int main() {
- char c;
- int i;
- long l;
- c = 42;
- i = 42*2;
- l = 42*3;
-
- char* cp1;
- char* cp2;
- int* ip1;
- int* ip2;
- long* lp1;
- long* lp2;
-
- cp1 = &c;
- cp2 = &c + 3;
-
- ip1 = &i;
- ip2 = &i + 3;
-
- lp1 = &l;
- lp2 = &l + 3;
-
- printf("%d\n", cp2 - cp1);
- printf("%d\n", ip2 - ip1);
- printf("%d\n", lp2 - lp1);
-
- return 0;
-}
-EOF
diff --git a/tests/array_basics.sh b/tests/pointers.sh
index e50a3c0..bbd4ed4 100644
--- a/tests/array_basics.sh
+++ b/tests/pointers.sh
@@ -1,3 +1,85 @@
+# pointer basics
+cat <<'EOF' > expected
+EOF
+test_diff <<'EOF'
+int main() {
+ int a1;
+ int* a2;
+ char a3;
+ char* a4;
+ long a5;
+ long* a6;
+ void* a8;
+ int** a10;
+ char** a12;
+ long** a14;
+ void** a16;
+ int*** a18;
+ char*** a20;
+ long*** a22;
+ void*** a24;
+ int* const* const* a25;
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+42 42
+EOF
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ int x;
+ int* y;
+ y = &x;
+ *y = 42;
+ printf("%d %d\n", x, *y);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+3
+3
+3
+EOF
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ char c;
+ int i;
+ long l;
+ c = 42;
+ i = 42*2;
+ l = 42*3;
+
+ char* cp1;
+ char* cp2;
+ int* ip1;
+ int* ip2;
+ long* lp1;
+ long* lp2;
+
+ cp1 = &c;
+ cp2 = &c + 3;
+
+ ip1 = &i;
+ ip2 = &i + 3;
+
+ lp1 = &l;
+ lp2 = &l + 3;
+
+ printf("%d\n", cp2 - cp1);
+ printf("%d\n", ip2 - ip1);
+ printf("%d\n", lp2 - lp1);
+
+ return 0;
+}
+EOF
+
+# arrays
cat <<'EOF' > expected
42
EOF
@@ -160,3 +242,76 @@ int main() {
printf("%zu\n", sizeof(c));
}
EOF
+
+# string operations
+> expected
+test_diff <<'EOF'
+int main() {
+ "";
+ return 0;
+}
+EOF
+
+> expected
+test_diff <<'EOF'
+int main() {
+ "abc";
+ return 0;
+}
+EOF
+
+> expected
+test_diff <<'EOF'
+int main() {
+ "\"foo\"bar\\\n\"";
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+abc
+defghijkl
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ printf("abc\n");
+ printf("def" "ghi"
+ "jkl\n");
+}
+EOF
+
+cat <<'EOF' > expected
+h
+l
+,
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ char* h = " hello,world" + 1;
+ printf("%c\n", *h);
+ printf("%c\n", h[2]);
+ printf("%c\n", *(h + 5));
+}
+EOF
+
+cat <<'EOF' > expected
+105
+0
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ char* s = "hi";
+ while (*s++) {
+ printf("%d\n", *s);
+ }
+}
+EOF
diff --git a/tests/predefined_macros.sh b/tests/predefined_macros.sh
deleted file mode 100644
index ada2fdd..0000000
--- a/tests/predefined_macros.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-cat <<'EOF' > expected
-1
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-int main() {
- printf("%d\n", __ducc__);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-main.c
-main.c
-main.c
-EOF
-
-cat <<'EOF' > header.h
-#define A __FILE__
-EOF
-
-test_diff <<'EOF'
-#define B __FILE__
-#include "header.h"
-int printf();
-int main() {
- printf("%s\n", __FILE__);
- printf("%s\n", B);
- printf("%s\n", A);
-}
-EOF
-
-cat <<'EOF' > expected
-5
-6 6
-7 7
-EOF
-
-cat <<'EOF' > header.h
-#define A __LINE__
-EOF
-
-test_diff <<'EOF'
-#define B __LINE__
-#include "header.h"
-int printf();
-int main() {
- printf("%d\n", __LINE__);
- printf("%d %d\n", B, B);
- printf("%d %d\n", A, A);
-}
-EOF
diff --git a/tests/printf.sh b/tests/printf.sh
index 7c4454c..ec805dc 100644
--- a/tests/printf.sh
+++ b/tests/printf.sh
@@ -1,4 +1,4 @@
-touch expected
+> expected
test_diff <<'EOF'
int printf();
diff --git a/tests/recursive_functions.c b/tests/recursive_functions.c
deleted file mode 100644
index b81824a..0000000
--- a/tests/recursive_functions.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <helpers.h>
-
-int fib(int n) {
- if (n <= 1) {
- return 1;
- } else {
- return fib(n - 1) + fib(n - 2);
- }
-}
-
-int main() {
- ASSERT_EQ(89, fib(10));
-}
diff --git a/tests/short_type.sh b/tests/short_type.sh
deleted file mode 100644
index b298a98..0000000
--- a/tests/short_type.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-cat <<'EOF' > expected
-2 42
-8 123
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-int main() {
- short a = 42;
- printf("%zu %hd\n", sizeof(a), a);
- short* b = &a;
- *b = 123;
- printf("%zu %hd\n", sizeof(b), *b);
-}
-EOF
diff --git a/tests/stdlib_declarations.sh b/tests/stdlib_declarations.sh
deleted file mode 100644
index efd6a30..0000000
--- a/tests/stdlib_declarations.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-cat <<'EOF' > expected
-EOF
-test_diff <<'EOF'
-typedef long size_t;
-
-int atoi(const char*);
-void* calloc(size_t, size_t);
-void exit(int);
-int getchar(void);
-int isalnum(int);
-int isalpha(int);
-int isdigit(int);
-int isspace(int);
-void* memcpy(void*, void*, size_t);
-int printf(const char*, ...);
-int sprintf(char*, const char*, ...);
-int strcmp(const char*, const char*);
-char* strstr(const char*, const char*);
-
-int main() { return 0; }
-EOF
diff --git a/tests/string_operations.sh b/tests/string_operations.sh
deleted file mode 100644
index 2466145..0000000
--- a/tests/string_operations.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-touch expected
-test_diff <<'EOF'
-int main() {
- "";
- return 0;
-}
-EOF
-
-touch expected
-test_diff <<'EOF'
-int main() {
- "abc";
- return 0;
-}
-EOF
-
-touch expected
-test_diff <<'EOF'
-int main() {
- "\"foo\"bar\\\n\"";
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-abc
-defghijkl
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-int main() {
- printf("abc\n");
- printf("def" "ghi"
- "jkl\n");
-}
-EOF
-
-cat <<'EOF' > expected
-h
-l
-,
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-int main() {
- char* h = " hello,world" + 1;
- printf("%c\n", *h);
- printf("%c\n", h[2]);
- printf("%c\n", *(h + 5));
-}
-EOF
-
-cat <<'EOF' > expected
-105
-0
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-int main() {
- char* s = "hi";
- while (*s++) {
- printf("%d\n", *s);
- }
-}
-EOF
diff --git a/tests/struct_arrays.sh b/tests/struct_arrays.sh
deleted file mode 100644
index 628c0d3..0000000
--- a/tests/struct_arrays.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-cat <<'EOF' > expected
-20
-10
-20
-30
-40
-50
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-struct S {
- int a[5];
-};
-
-int main() {
- struct S x;
- x.a[0] = 10;
- x.a[1] = 20;
- x.a[2] = 30;
- x.a[3] = 40;
- x.a[4] = 50;
-
- printf("%zu\n", sizeof(struct S));
-
- printf("%d\n", x.a[0]);
- printf("%d\n", x.a[1]);
- printf("%d\n", x.a[2]);
- printf("%d\n", x.a[3]);
- printf("%d\n", x.a[4]);
-}
-EOF
diff --git a/tests/struct_basics.sh b/tests/struct_basics.sh
deleted file mode 100644
index 13a50a5..0000000
--- a/tests/struct_basics.sh
+++ /dev/null
@@ -1,137 +0,0 @@
-cat <<'EOF' > expected
-EOF
-test_diff <<'EOF'
-struct Token {
- int kind;
- char* value;
-};
-
-struct Define {
- char* from;
- struct Token* to;
-};
-
-struct AstNode;
-
-struct Type {
- int kind;
- struct Type* to;
- struct AstNode* members;
-};
-
-struct AstNode {
- int kind;
- struct AstNode* next;
- struct AstNode* last;
- char* name;
- struct AstNode* func_params;
- struct AstNode* func_body;
- int int_value;
- struct AstNode* expr1;
- struct AstNode* expr2;
- struct AstNode* expr3;
- int op;
- struct Type* ty;
- int var_index;
- struct AstNode* node1;
- struct AstNode* node2;
- char** str_literals;
-};
-
-struct LVar {
- char* name;
- struct Type* ty;
-};
-
-struct Func {
- char* name;
- struct Type* ty;
-};
-
-struct Parser {
- struct Token* tokens;
- int pos;
- struct LVar* locals;
- int n_locals;
- struct Func* funcs;
- int n_funcs;
- char** str_literals;
- int n_str_literals;
-};
-
-struct CodeGen {
- int next_label;
- int* loop_labels;
-};
-
-int main() {
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-42
-123
-EOF
-test_diff <<'EOF'
-struct S {
- int a;
- int b;
-};
-
-int printf();
-void* calloc();
-
-int main() {
- struct S* sp;
- sp = calloc(1, sizeof(struct S));
- sp->a = 42;
- printf("%d\n", sp->a);
- (*sp).b = 123;
- printf("%d\n", (*sp).b);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-42
-EOF
-test_diff <<'EOF'
-void* calloc();
-int printf();
-
-struct T;
-
-struct S {
- struct T* a;
-};
-
-struct T {
- int b;
-};
-
-int main() {
- struct S* s = calloc(1, sizeof(struct S));
- s->a = calloc(1, sizeof(struct T));
- s->a->b = 42;
- printf("%d\n", s->a->b);
- return 0;
-}
-EOF
-
-test_exit_code 0 <<'EOF'
-#include <helpers.h>
-
-struct S {
- int a, b;
-};
-
-struct T {
- short *a, b, c[12];
-};
-
-int main() {
- ASSERT_EQ(8, sizeof(struct S));
- ASSERT_EQ(40, sizeof(struct T));
-}
-EOF
diff --git a/tests/struct_initialization.sh b/tests/struct_initialization.sh
deleted file mode 100644
index f2c92cf..0000000
--- a/tests/struct_initialization.sh
+++ /dev/null
@@ -1,107 +0,0 @@
-cat <<'EOF' > expected
-0
-1
-EOF
-test_diff <<'EOF'
-int printf();
-void* calloc();
-
-struct S {
- int a;
- int b;
-};
-
-int main() {
- struct S* s = calloc(1, sizeof(struct S));
- s->b = 1;
- printf("%ld\n", s->a);
- printf("%ld\n", s->b);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-123 456
-0 0
-123 456
-EOF
-
-test_diff <<'EOF'
-struct S {
- int a;
- int b;
-};
-typedef struct S S;
-
-void* calloc();
-int printf();
-
-int main() {
- S* s1 = calloc(1, sizeof(S));
- S* s2 = calloc(1, sizeof(S));
- s1->a = 123;
- s1->b = 456;
- printf("%d %d\n", s1->a, s1->b);
- printf("%d %d\n", s2->a, s2->b);
- *s2 = *s1;
- printf("%d %d\n", s2->a, s2->b);
-}
-EOF
-
-cat <<'EOF' > expected
-123 456
-0 0
-123 456
-EOF
-
-test_diff <<'EOF'
-struct S {
- long a;
- long b;
-};
-typedef struct S S;
-
-void* calloc();
-int printf();
-
-int main() {
- S* s1 = calloc(1, sizeof(S));
- S* s2 = calloc(1, sizeof(S));
- s1->a = 123;
- s1->b = 456;
- printf("%d %d\n", s1->a, s1->b);
- printf("%d %d\n", s2->a, s2->b);
- *s2 = *s1;
- printf("%d %d\n", s2->a, s2->b);
-}
-EOF
-
-cat <<'EOF' > expected
-123 456
-0 0
-123 456
-EOF
-
-test_diff <<'EOF'
-struct S {
- long a;
- long b;
-};
-typedef struct S S;
-
-void* calloc();
-int printf();
-
-int main() {
- S s1;
- S s2;
- s1.a = 123;
- s1.b = 456;
- s2.a = 0;
- s2.b = 0;
- printf("%d %d\n", s1.a, s1.b);
- printf("%d %d\n", s2.a, s2.b);
- s2 = s1;
- printf("%d %d\n", s2.a, s2.b);
-}
-EOF
diff --git a/tests/structs.sh b/tests/structs.sh
new file mode 100644
index 0000000..4c8ff6d
--- /dev/null
+++ b/tests/structs.sh
@@ -0,0 +1,364 @@
+cat <<'EOF' > expected
+EOF
+test_diff <<'EOF'
+struct Token {
+ int kind;
+ char* value;
+};
+
+struct Define {
+ char* from;
+ struct Token* to;
+};
+
+struct AstNode;
+
+struct Type {
+ int kind;
+ struct Type* to;
+ struct AstNode* members;
+};
+
+struct AstNode {
+ int kind;
+ struct AstNode* next;
+ struct AstNode* last;
+ char* name;
+ struct AstNode* func_params;
+ struct AstNode* func_body;
+ int int_value;
+ struct AstNode* expr1;
+ struct AstNode* expr2;
+ struct AstNode* expr3;
+ int op;
+ struct Type* ty;
+ int var_index;
+ struct AstNode* node1;
+ struct AstNode* node2;
+ char** str_literals;
+};
+
+struct LVar {
+ char* name;
+ struct Type* ty;
+};
+
+struct Func {
+ char* name;
+ struct Type* ty;
+};
+
+struct Parser {
+ struct Token* tokens;
+ int pos;
+ struct LVar* locals;
+ int n_locals;
+ struct Func* funcs;
+ int n_funcs;
+ char** str_literals;
+ int n_str_literals;
+};
+
+struct CodeGen {
+ int next_label;
+ int* loop_labels;
+};
+
+int main() {
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+42
+123
+EOF
+test_diff <<'EOF'
+struct S {
+ int a;
+ int b;
+};
+
+int printf();
+void* calloc();
+
+int main() {
+ struct S* sp;
+ sp = calloc(1, sizeof(struct S));
+ sp->a = 42;
+ printf("%d\n", sp->a);
+ (*sp).b = 123;
+ printf("%d\n", (*sp).b);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+42
+EOF
+test_diff <<'EOF'
+void* calloc();
+int printf();
+
+struct T;
+
+struct S {
+ struct T* a;
+};
+
+struct T {
+ int b;
+};
+
+int main() {
+ struct S* s = calloc(1, sizeof(struct S));
+ s->a = calloc(1, sizeof(struct T));
+ s->a->b = 42;
+ printf("%d\n", s->a->b);
+ return 0;
+}
+EOF
+
+test_exit_code 0 <<'EOF'
+#include <helpers.h>
+
+struct S {
+ int a, b;
+};
+
+struct T {
+ short *a, b, c[12];
+};
+
+int main() {
+ ASSERT_EQ(8, sizeof(struct S));
+ ASSERT_EQ(40, sizeof(struct T));
+}
+EOF
+
+cat <<'EOF' > expected
+20
+10
+20
+30
+40
+50
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+struct S {
+ int a[5];
+};
+
+int main() {
+ struct S x;
+ x.a[0] = 10;
+ x.a[1] = 20;
+ x.a[2] = 30;
+ x.a[3] = 40;
+ x.a[4] = 50;
+
+ printf("%zu\n", sizeof(struct S));
+
+ printf("%d\n", x.a[0]);
+ printf("%d\n", x.a[1]);
+ printf("%d\n", x.a[2]);
+ printf("%d\n", x.a[3]);
+ printf("%d\n", x.a[4]);
+}
+EOF
+
+cat <<'EOF' > expected
+0
+1
+EOF
+test_diff <<'EOF'
+int printf();
+void* calloc();
+
+struct S {
+ int a;
+ int b;
+};
+
+int main() {
+ struct S* s = calloc(1, sizeof(struct S));
+ s->b = 1;
+ printf("%ld\n", s->a);
+ printf("%ld\n", s->b);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+123 456
+0 0
+123 456
+EOF
+
+test_diff <<'EOF'
+struct S {
+ int a;
+ int b;
+};
+typedef struct S S;
+
+void* calloc();
+int printf();
+
+int main() {
+ S* s1 = calloc(1, sizeof(S));
+ S* s2 = calloc(1, sizeof(S));
+ s1->a = 123;
+ s1->b = 456;
+ printf("%d %d\n", s1->a, s1->b);
+ printf("%d %d\n", s2->a, s2->b);
+ *s2 = *s1;
+ printf("%d %d\n", s2->a, s2->b);
+}
+EOF
+
+cat <<'EOF' > expected
+123 456
+0 0
+123 456
+EOF
+
+test_diff <<'EOF'
+struct S {
+ long a;
+ long b;
+};
+typedef struct S S;
+
+void* calloc();
+int printf();
+
+int main() {
+ S* s1 = calloc(1, sizeof(S));
+ S* s2 = calloc(1, sizeof(S));
+ s1->a = 123;
+ s1->b = 456;
+ printf("%d %d\n", s1->a, s1->b);
+ printf("%d %d\n", s2->a, s2->b);
+ *s2 = *s1;
+ printf("%d %d\n", s2->a, s2->b);
+}
+EOF
+
+cat <<'EOF' > expected
+123 456
+0 0
+123 456
+EOF
+
+test_diff <<'EOF'
+struct S {
+ long a;
+ long b;
+};
+typedef struct S S;
+
+void* calloc();
+int printf();
+
+int main() {
+ S s1;
+ S s2;
+ s1.a = 123;
+ s1.b = 456;
+ s2.a = 0;
+ s2.b = 0;
+ printf("%d %d\n", s1.a, s1.b);
+ printf("%d %d\n", s2.a, s2.b);
+ s2 = s1;
+ printf("%d %d\n", s2.a, s2.b);
+}
+EOF
+
+cat <<'EOF' > expected
+42
+EOF
+test_diff <<'EOF'
+void* calloc();
+int printf();
+
+struct S {
+ int x;
+};
+typedef struct S S;
+
+int main() {
+ S* s = calloc(1, sizeof(S));
+ s->x = 42;
+ printf("%d\n", s->x);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+4
+EOF
+test_diff <<'EOF'
+struct S0;
+typedef struct S0 S0;
+
+struct S1 {
+ int x;
+};
+
+struct S2 {
+ int x;
+};
+
+struct S3 {
+ int x;
+};
+
+struct S4 {
+ int x;
+};
+
+struct S0 {
+ int x;
+};
+
+int printf(const char*, ...);
+int main() {
+ printf("%zu\n", sizeof(S0));
+}
+EOF
+
+cat <<'EOF' > expected
+8
+4
+4
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+typedef struct {
+ int x;
+ int y;
+} S;
+
+typedef union {
+ int a;
+ char b;
+} U;
+
+typedef enum {
+ RED,
+ GREEN,
+ BLUE
+} E;
+
+int main() {
+ printf("%zu\n", sizeof(S));
+ printf("%zu\n", sizeof(U));
+ printf("%zu\n", sizeof(E));
+}
+EOF
diff --git a/tests/ternary_operator.c b/tests/ternary_operator.c
deleted file mode 100644
index 1f46dbe..0000000
--- a/tests/ternary_operator.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <helpers.h>
-
-int main() {
- ASSERT_EQ(2, 1 ? 2 : 3);
- ASSERT_EQ(5, 0 ? 4 : 5);
-}
diff --git a/tests/line_continuation.sh b/tests/tokenize.sh
index 89f4543..2db9640 100644
--- a/tests/line_continuation.sh
+++ b/tests/tokenize.sh
@@ -1,3 +1,47 @@
+# comments
+cat <<'EOF' > expected
+EOF
+test_diff <<'EOF'
+// TODO: check if the token is at the beginning of line.
+// TODO: check if skipped whitespaces do not contain line breaks.
+int main() {
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+EOF
+
+test_diff <<'EOF'
+/* lorem ipsum */
+/*
+lorem ipsum
+*/
+// /*
+/* /*
+ */
+int/**/main() {
+}
+EOF
+
+# identifiers
+cat <<'EOF' > expected
+42,123
+EOF
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ int _a = 42;
+ int _b = 123;
+
+ printf("%d,%d\n", _a, _b);
+
+ return 0;
+}
+EOF
+
+# line continuation
cat <<'EOF' > expected
10 20
100 300 500
@@ -54,3 +98,19 @@ test_diff < main_cr.c
# Mixed
printf 'int printf(const char*, ...);\nint main() {\r\n printf("Hello World\\n");\r printf("Line con\\\r\ntinues\\n");\n return 0;\r\n}\r\n' > main_mixed.c
test_diff < main_mixed.c
+
+# keywords
+cat <<'EOF' > expected
+
+
+int printf ();
+int main () {}
+EOF
+
+test_cpp <<'EOF'
+// A keyword is treated as a normal identifier in preprocessing phase.
+#define auto int
+
+auto printf();
+auto main() {}
+EOF
diff --git a/tests/typedef_struct.sh b/tests/typedef_struct.sh
deleted file mode 100644
index 593d903..0000000
--- a/tests/typedef_struct.sh
+++ /dev/null
@@ -1,84 +0,0 @@
-cat <<'EOF' > expected
-42
-EOF
-test_diff <<'EOF'
-void* calloc();
-int printf();
-
-struct S {
- int x;
-};
-typedef struct S S;
-
-int main() {
- S* s = calloc(1, sizeof(S));
- s->x = 42;
- printf("%d\n", s->x);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-4
-EOF
-test_diff <<'EOF'
-struct S0;
-typedef struct S0 S0;
-
-struct S1 {
- int x;
-};
-
-struct S2 {
- int x;
-};
-
-struct S3 {
- int x;
-};
-
-struct S4 {
- int x;
-};
-
-struct S0 {
- int x;
-};
-
-int printf(const char*, ...);
-int main() {
- printf("%zu\n", sizeof(S0));
-}
-EOF
-
-cat <<'EOF' > expected
-8
-4
-4
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-typedef struct {
- int x;
- int y;
-} S;
-
-typedef union {
- int a;
- char b;
-} U;
-
-typedef enum {
- RED,
- GREEN,
- BLUE
-} E;
-
-int main() {
- printf("%zu\n", sizeof(S));
- printf("%zu\n", sizeof(U));
- printf("%zu\n", sizeof(E));
-}
-EOF
diff --git a/tests/sizeof_operator.sh b/tests/types.sh
index c8df5da..892f85b 100644
--- a/tests/sizeof_operator.sh
+++ b/tests/types.sh
@@ -1,3 +1,22 @@
+# short type
+cat <<'EOF' > expected
+2 42
+8 123
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+int main() {
+ short a = 42;
+ printf("%zu %hd\n", sizeof(a), a);
+ short* b = &a;
+ *b = 123;
+ printf("%zu %hd\n", sizeof(b), *b);
+}
+EOF
+
+# sizeof operator
cat <<'EOF' > expected
sizeof(int) = 4
sizeof(int*) = 8
@@ -174,3 +193,53 @@ int main() {
return 0;
}
EOF
+
+# enums
+cat <<'EOF' > expected
+4
+0,1,2
+EOF
+test_diff <<'EOF'
+int printf();
+
+enum E {
+ A,
+ B,
+ C,
+};
+
+int main() {
+ enum E x = A;
+ printf("%d\n", sizeof(enum E));
+ printf("%d,%d,%d\n", A, B, C);
+ return 0;
+}
+EOF
+
+cat <<'EOF' > expected
+10,11,20,21
+0,5,6,6
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+enum E1 {
+ A = 10,
+ B,
+ C = 20,
+ D,
+};
+
+enum E2 {
+ E,
+ F = 5,
+ G,
+ H = G,
+};
+
+int main() {
+ printf("%d,%d,%d,%d\n", A, B, C, D);
+ printf("%d,%d,%d,%d\n", E, F, G, H);
+}
+EOF
diff --git a/tests/undef.sh b/tests/undef.sh
deleted file mode 100644
index 27d03c6..0000000
--- a/tests/undef.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-cat <<'EOF' > expected
-int printf ();
-
-int main () {
-
- printf ( A is defined\n);
-
-
- printf ( A is undefined\n);
-}
-EOF
-
-test_cpp <<'EOF'
-int printf();
-
-int main() {
-#define A 1
-
-#ifdef A
- printf("A is defined\n");
-#else
- printf("A is undefined\n");
-#endif
-
-#undef A
-
-#ifdef A
- printf("A is defined\n");
-#else
- printf("A is undefined\n");
-#endif
-}
-EOF
diff --git a/tests/variables.c b/tests/variables.c
new file mode 100644
index 0000000..0bd2127
--- /dev/null
+++ b/tests/variables.c
@@ -0,0 +1,74 @@
+#include <helpers.h>
+
+int printf(const char*, ...);
+int strcmp(const char*, const char*);
+
+// global variables
+int g_a;
+int* g_b = &g_a;
+int g_c[10];
+int* g_d = g_c;
+int g_e, *g_f = g_e, g_g[10], *g_h = g_g;
+
+char g_i = 42;
+short g_j = 123;
+int g_k = 999;
+
+char g_l[6] = "hello";
+
+int main() {
+ // global variables
+ *g_b = 123;
+ ASSERT_EQ(123, g_a);
+
+ g_d[2] = 42;
+ ASSERT_EQ(42, g_c[2]);
+
+ *g_f = 456;
+ ASSERT_EQ(456, g_e);
+
+ g_h[5] = 789;
+ ASSERT_EQ(789, g_g[5]);
+
+ ASSERT_EQ(42, g_i);
+ ASSERT_EQ(123, g_j);
+ ASSERT_EQ(999, g_k);
+
+ ASSERT_EQ(0, strcmp("hello", g_l));
+
+ // local variables
+ int foo;
+ foo = 42;
+ ASSERT_EQ(42, foo);
+
+ int bar;
+ bar = 28;
+ ASSERT_EQ(70, foo + bar);
+
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ int a8;
+ int a9;
+
+ a1 = 1;
+ a2 = 2;
+ a3 = 3;
+ a4 = 4;
+ a5 = 5;
+ a6 = 6;
+ a7 = 7;
+ a8 = 8;
+ a9 = 9;
+
+ ASSERT_EQ(45, a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + 0);
+
+ int d = 2, e = d, f = d + e;
+ ASSERT_EQ(2, d);
+ ASSERT_EQ(2, e);
+ ASSERT_EQ(4, f);
+}
diff --git a/tests/variadic_functions.sh b/tests/variadic_functions.sh
deleted file mode 100644
index 155fc1a..0000000
--- a/tests/variadic_functions.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-cat <<'EOF' > expected
-123
-456 789
-EOF
-
-test_diff <<'EOF'
-#include <stdarg.h>
-
-int fprintf();
-
-struct FILE;
-typedef struct FILE FILE;
-
-extern FILE* stdout;
-
-int vfprintf(FILE*, const char*, va_list);
-
-void fatal_error(const char* msg, ...) {
- va_list args;
- va_start(args, msg);
- vfprintf(stdout, msg, args);
- va_end(args);
- fprintf(stdout, "\n");
-}
-
-int main() {
- fatal_error("%d", 123);
- fatal_error("%d %d", 456, 789);
- return 0;
-}
-EOF
-
-test_exit_code 0 <<'EOF'
-#include <stdarg.h>
-#include <helpers.h>
-
-int sum(int n, ...) {
- va_list args;
- va_start(args, n);
- int s = 0;
- for (int i = 0; i < n; ++i) {
- s += va_arg(args, int);
- }
- va_end(args);
- return s;
-}
-
-int main() {
- ASSERT_EQ(400, sum(5, 100, 90, 80, 70, 60));
-}
-EOF
diff --git a/tests/void_functions.sh b/tests/void_functions.sh
deleted file mode 100644
index 656c2c1..0000000
--- a/tests/void_functions.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-cat <<'EOF' > expected
-123
-EOF
-test_diff <<'EOF'
-int printf();
-
-void foo_bar(int hoge_piyo) {
- printf("%d\n", hoge_piyo);
-}
-
-int main() {
- foo_bar(123);
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-EOF
-test_diff <<'EOF'
-struct S {
- int a;
-};
-
-struct S* f();
-
-struct S* g() {}
-
-int main() {
- return 0;
-}
-EOF
-
-cat <<'EOF' > expected
-hi
-EOF
-test_diff <<'EOF'
-int printf();
-
-void f() {
- printf("hi\n");
- return;
-}
-
-int main() {
- f();
- return 0;
-}
-EOF