#include #include #include #include #include #include // clang-format off static void test_indexed_params ML99_EVAL(ML99_indexedParams(ML99_list(v(int, long long, const char *)))) // clang-format on { int i = _0; long long ll = _1; const char *str = _2; (void)i; (void)ll; (void)str; } static int test_fn_ptr(const char *str, long long x) { (void)str; (void)x; return 123; } int main(void) { // ML99_braced { struct TestBraced ML99_EVAL(ML99_braced(v(int a, b, c;))); } // ML99_semicoloned { ML99_EVAL(ML99_semicoloned(v(struct TestSemicoloned { int a, b, c; }))); } // ML99_assign(Stmt) { int x = 0; ML99_EVAL(ML99_assign(v(x), v(5))); assert(5 == x); ML99_EVAL(ML99_assignStmt(v(x), v(7))) assert(7 == x); } // ML99_assignInitializerList(Stmt) { typedef struct { int x, y; } Point; ML99_EVAL(ML99_assignInitializerList(v(Point p1), v(.x = 2, .y = 3))); assert(2 == p1.x); assert(3 == p1.y); ML99_EVAL(ML99_assignInitializerListStmt(v(Point p2), v(.x = 5, .y = 7))) assert(5 == p2.x); assert(7 == p2.y); } #define F(a, b, c) ML99_ASSERT_UNEVAL(a == 1 && b == 2 && c == 3) // ML99_invoke(Stmt) { ML99_EVAL(ML99_invoke(v(F), v(1, 2, 3))); ML99_EVAL(ML99_invokeStmt(v(F), v(1, 2, 3))) } #undef F // ML99_prefixedBlock { ML99_EVAL(ML99_prefixedBlock(v(if (1)), v(goto end_prefixed_block;))) // Unreachable code. assert(0); end_prefixed_block:; } // ML99_typedef { ML99_EVAL(ML99_typedef(v(Point), v(struct { int x, y; }))); Point point = {5, 7}; point.x = 1; point.y = 2; (void)point; } // ML99_struct { ML99_EVAL(ML99_struct(v(Point), v(int x, y;))); struct Point point = {5, 7}; point.x = 1; point.y = 2; (void)point; } // ML99_anonStruct { typedef ML99_EVAL(ML99_anonStruct(v(int x, y;))) Point; Point point = {5, 7}; point.x = 1; point.y = 2; (void)point; } // ML99_union { ML99_EVAL(ML99_union(v(Point), v(int x, y;))); union Point point; point.x = 1; point.y = 2; (void)point; } // ML99_anonUnion { typedef ML99_EVAL(ML99_anonUnion(v(int x, y;))) Point; Point point; point.x = 1; point.y = 2; (void)point; } // ML99_enum { ML99_EVAL(ML99_enum(v(MyEnum), v(Foo, Bar))); enum MyEnum foo = Foo, bar = Bar; (void)foo; (void)bar; } // ML99_anonEnum { typedef ML99_EVAL(ML99_anonEnum(v(Foo, Bar))) MyEnum; MyEnum foo = Foo, bar = Bar; (void)foo; (void)bar; } // ML99_fnPtr(Stmt) { { ML99_EVAL(ML99_fnPtr(v(int), v(ptr), v(const char *str), v(long long x))) = test_fn_ptr; assert(test_fn_ptr == ptr); } { ML99_EVAL(ML99_fnPtrStmt(v(int), v(ptr), v(const char *str), v(long long x))) ptr = test_fn_ptr; (void)ptr; } } #define CHECK_EXPAND(args) CHECK(args) #define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 0 && y == 1 && z == 2) #define F_IMPL(x) v(, x) #define F_ARITY 1 // ML99_repeat { CHECK_EXPAND(ML99_EVAL(ML99_repeat(v(3), v(F)))); } #undef CHECK #undef F_IMPL #undef F_ARITY #define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 5 && y == 5 && z == 5) // ML99_times { CHECK_EXPAND(ML99_EVAL(ML99_times(v(3), v(, 5)))); } #undef CHECK #undef CHECK_EXPAND // ML99_indexedParams { ML99_ASSERT_UNEVAL(ML99_IDENT_EQ( ML99_C_KEYWORD_DETECTOR, void, ML99_EVAL(ML99_untuple(ML99_indexedParams(ML99_nil()))))); (void)test_indexed_params; } // ML99_indexedFields { ML99_ASSERT_EMPTY(ML99_indexedFields(ML99_nil())); struct { ML99_EVAL(ML99_indexedFields(ML99_list(v(int, long long, const char *)))) } data = {0}; int i = data._0; long long ll = data._1; const char *str = data._2; (void)i; (void)ll; (void)str; } // clang-format off // ML99_indexedInitializerList { // When N=0. { const struct { int _0; long long _1; const char *_2; } test = ML99_EVAL(ML99_indexedInitializerList(v(0))); assert(0 == test._0); assert(0 == test._1); assert(0 == test._2); } // When N>0. { int _0 = 123; long long _1 = 149494456; const char *_2 = "abc"; struct { int i; long long ll; const char *str; } data = ML99_EVAL(ML99_indexedInitializerList(v(3))); (void)data; } } // ML99_indexedArgs { ML99_ASSERT_EMPTY(ML99_indexedArgs(v(0))); int _0 = 123; long long _1 = 149494456; const char *_2 = "abc"; const struct { int i; long long ll; const char *str; } test = { ML99_EVAL(ML99_indexedArgs(v(3))) }; assert(test.i == _0); assert(test.ll == _1); assert(test.str == _2); } // clang-format on return 0; }