diff --git a/src/ast/ast.h b/src/ast/ast.h index 5de67682..d51b9baa 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -62,6 +62,14 @@ typedef enum AstType { // expression // assignment-expression AST_ASSIGN_EXPR, + AST_MUL_ASSIGN_EXPR, + AST_DIV_ASSIGN_EXPR, + AST_MOD_ASSIGN_EXPR, + AST_ADD_ASSIGN_EXPR, + AST_SUB_ASSIGN_EXPR, + AST_AND_ASSIGN_EXPR, + AST_XOR_ASSIGN_EXPR, + AST_OR_ASSIGN_EXPR, // conditional-expression AST_COND_EXPR, // logical-OR-expression diff --git a/src/ctoken/ctoken.c b/src/ctoken/ctoken.c index 1daa9a21..cb04bd37 100644 --- a/src/ctoken/ctoken.c +++ b/src/ctoken/ctoken.c @@ -13,7 +13,8 @@ char* ctoken_types[] = { "identifier", "integer-constant", "character-constant", "string-literal", // punctuators "[", "]", "(", ")", "{", "}", ".", "->", "++", "--", "&", "*", "+", "-", "~", "!", "/", "%", "<", ">", - "<=", ">=", "==", "!=", "^", "|", "&&", "||", "?", ":", ";", "=", ",", "EOF"}; + "<=", ">=", "==", "!=", "^", "|", "&&", "||", "?", ":", ";", "=", + "*=", "/=", "%=", "+=", "-=", "&=", "^=", "|=", ",", "EOF"}; CToken* new_base_ctoken(CTokenType type); diff --git a/src/ctoken/ctoken.h b/src/ctoken/ctoken.h index fdd3c34b..7e4cdcf9 100644 --- a/src/ctoken/ctoken.h +++ b/src/ctoken/ctoken.h @@ -62,6 +62,14 @@ typedef enum CTokenType { CTOKEN_COLON, CTOKEN_SEMICOLON, CTOKEN_EQUAL, + CTOKEN_ASTERISK_EQUAL, + CTOKEN_SLASH_EQUAL, + CTOKEN_PERCENT_EQUAL, + CTOKEN_PLUS_EQUAL, + CTOKEN_MINUS_EQUAL, + CTOKEN_AND_EQUAL, + CTOKEN_CARET_EQUAL, + CTOKEN_VBAR_EQUAL, CTOKEN_COMMA, CTOKEN_EOF, } CTokenType; diff --git a/src/immcgen/expression.c b/src/immcgen/expression.c index 4ee4bdfc..a18484f1 100644 --- a/src/immcgen/expression.c +++ b/src/immcgen/expression.c @@ -10,19 +10,11 @@ Vector* gen_assignment_expr_immcode(Immcgen* immcgen) { Vector* codes = new_vector(&t_immc); - Srt* srt = immcgen->srt; ImmcOpe* src = gen_child_reg_immcope(immcgen, codes, 1); ImmcOpe* dst = gen_child_ptr_immcope(immcgen, codes, 0); - switch (srt->type) { - case SRT_ASSIGN_EXPR: - vector_push(codes, new_inst_immc(IMMC_INST_STORE, dst, src, NULL)); - break; - default: - fprintf(stderr, "unexpected srt type %d\n", srt->type); - exit(1); - } + vector_push(codes, new_inst_immc(IMMC_INST_STORE, dst, src, NULL)); update_non_void_expr_register(immcgen, src); return codes; diff --git a/src/lexer/util.c b/src/lexer/util.c index 24fda18c..1a68f00c 100644 --- a/src/lexer/util.c +++ b/src/lexer/util.c @@ -155,6 +155,14 @@ Map* new_punctuator_map(void) { ctoken_map_add(punctuator_map, ":", CTOKEN_COLON); ctoken_map_add(punctuator_map, ";", CTOKEN_SEMICOLON); ctoken_map_add(punctuator_map, "=", CTOKEN_EQUAL); + ctoken_map_add(punctuator_map, "*=", CTOKEN_ASTERISK_EQUAL); + ctoken_map_add(punctuator_map, "/=", CTOKEN_SLASH_EQUAL); + ctoken_map_add(punctuator_map, "%=", CTOKEN_PERCENT_EQUAL); + ctoken_map_add(punctuator_map, "+=", CTOKEN_PLUS_EQUAL); + ctoken_map_add(punctuator_map, "-=", CTOKEN_MINUS_EQUAL); + ctoken_map_add(punctuator_map, "&=", CTOKEN_AND_EQUAL); + ctoken_map_add(punctuator_map, "^=", CTOKEN_CARET_EQUAL); + ctoken_map_add(punctuator_map, "|=", CTOKEN_VBAR_EQUAL); ctoken_map_add(punctuator_map, ",", CTOKEN_COMMA); return punctuator_map; diff --git a/src/parser/expression.c b/src/parser/expression.c index 24c4ade9..4261e86a 100644 --- a/src/parser/expression.c +++ b/src/parser/expression.c @@ -39,6 +39,38 @@ ParserReturn* parse_assignment_expr(Parser* parser) { parser->index++; vector_push(stack, new_ast(AST_ASSIGN_EXPR, 1, ast)); break; + case CTOKEN_ASTERISK_EQUAL: + parser->index++; + vector_push(stack, new_ast(AST_MUL_ASSIGN_EXPR, 1, ast)); + break; + case CTOKEN_SLASH_EQUAL: + parser->index++; + vector_push(stack, new_ast(AST_DIV_ASSIGN_EXPR, 1, ast)); + break; + case CTOKEN_PERCENT_EQUAL: + parser->index++; + vector_push(stack, new_ast(AST_MOD_ASSIGN_EXPR, 1, ast)); + break; + case CTOKEN_PLUS_EQUAL: + parser->index++; + vector_push(stack, new_ast(AST_ADD_ASSIGN_EXPR, 1, ast)); + break; + case CTOKEN_MINUS_EQUAL: + parser->index++; + vector_push(stack, new_ast(AST_SUB_ASSIGN_EXPR, 1, ast)); + break; + case CTOKEN_AND_EQUAL: + parser->index++; + vector_push(stack, new_ast(AST_AND_ASSIGN_EXPR, 1, ast)); + break; + case CTOKEN_CARET_EQUAL: + parser->index++; + vector_push(stack, new_ast(AST_XOR_ASSIGN_EXPR, 1, ast)); + break; + case CTOKEN_VBAR_EQUAL: + parser->index++; + vector_push(stack, new_ast(AST_OR_ASSIGN_EXPR, 1, ast)); + break; default: parser->index = index; delete_ast(ast); diff --git a/src/resolver/expression.c b/src/resolver/expression.c index 8853fe50..cfa75f24 100644 --- a/src/resolver/expression.c +++ b/src/resolver/expression.c @@ -16,6 +16,16 @@ ResolverReturn* resolve_expr(Resolver* resolver) { case AST_ASSIGN_EXPR: resolverret_assign(&srt, &errs, resolve_assignment_expr(resolver)); break; + case AST_MUL_ASSIGN_EXPR: + case AST_DIV_ASSIGN_EXPR: + case AST_MOD_ASSIGN_EXPR: + case AST_ADD_ASSIGN_EXPR: + case AST_SUB_ASSIGN_EXPR: + case AST_OR_ASSIGN_EXPR: + case AST_XOR_ASSIGN_EXPR: + case AST_AND_ASSIGN_EXPR: + resolverret_assign(&srt, &errs, resolve_compound_assignment_expr(resolver)); + break; case AST_COND_EXPR: resolverret_assign(&srt, &errs, resolve_conditional_expr(resolver)); break; @@ -143,6 +153,60 @@ ResolverReturn* resolve_assignment_expr(Resolver* resolver) { return new_resolverret(srt); } +ResolverReturn* resolve_compound_assignment_expr(Resolver* resolver) { + Srt* srt = NULL; + Vector* errs = NULL; + + Ast* ast = resolver->ast; + Ast* lhs_ast = vector_at(ast->children, 0); + Ast* rhs_ast = vector_at(ast->children, 1); + + Ast* binop_ast = NULL; + switch (ast->type) { + case AST_MUL_ASSIGN_EXPR: + binop_ast = new_ast(AST_MUL_EXPR, 0); + break; + case AST_DIV_ASSIGN_EXPR: + binop_ast = new_ast(AST_DIV_EXPR, 0); + break; + case AST_MOD_ASSIGN_EXPR: + binop_ast = new_ast(AST_MOD_EXPR, 0); + break; + case AST_ADD_ASSIGN_EXPR: + binop_ast = new_ast(AST_ADD_EXPR, 0); + break; + case AST_SUB_ASSIGN_EXPR: + binop_ast = new_ast(AST_SUB_EXPR, 0); + break; + case AST_OR_ASSIGN_EXPR: + binop_ast = new_ast(AST_OR_EXPR, 0); + break; + case AST_XOR_ASSIGN_EXPR: + binop_ast = new_ast(AST_XOR_EXPR, 0); + break; + case AST_AND_ASSIGN_EXPR: + binop_ast = new_ast(AST_AND_EXPR, 0); + break; + default: + fprintf(stderr, "\x1b[1;31mfatal error\x1b[0m: " + "unreachable statement (in resolve_compound_assignment_expr)\n"); + exit(1); + } + + vector_push(binop_ast->children, ast_copy(lhs_ast)); + vector_push(binop_ast->children, ast_copy(rhs_ast)); + + resolver->ast = new_ast(AST_ASSIGN_EXPR, 2, ast_copy(lhs_ast), binop_ast); + resolverret_assign(&srt, &errs, resolve_assignment_expr(resolver)); + delete_ast(resolver->ast); + resolver->ast = ast; + if (errs != NULL) { + return new_resolverret_errors(errs); + } + + return new_resolverret(srt); +} + ResolverReturn* resolve_conditional_expr(Resolver* resolver) { Srt* srt = NULL; Srt* condition_srt = NULL; @@ -422,7 +486,7 @@ ResolverReturn* resolve_equality_expr(Resolver* resolver) { err = new_error("operands of pointer == pointer are not compatible"); } else { err = new_error("binary == expression should be " - "either arithmetic == arithmetic or pointer == pointer\n"); + "either arithmetic == arithmetic or pointer == pointer"); } vector_push(errs, err); break; @@ -436,7 +500,7 @@ ResolverReturn* resolve_equality_expr(Resolver* resolver) { err = new_error("operands of pointer != pointer are not compatible"); } else { err = new_error("binary != expression should be " - "either arithmetic != arithmetic or pointer != pointer\n"); + "either arithmetic != arithmetic or pointer != pointer"); } vector_push(errs, err); break; @@ -446,7 +510,7 @@ ResolverReturn* resolve_equality_expr(Resolver* resolver) { break; default: fprintf(stderr, "\x1b[1;31mfatal error\x1b[0m: " - "unreachable statement (in resolve_equality_expr)\n"); + "unreachable statement (in resolve_equality_expr)"); exit(1); } @@ -646,7 +710,7 @@ ResolverReturn* resolve_add_expr(Resolver* resolver) { errs = new_vector(&t_error); err = new_error("binary + expression should be either arithmetic + arithmetic, " - "pointer + integer, or integer + pointer\n"); + "pointer + integer, or integer + pointer"); vector_push(errs, err); delete_srt(lhs_srt); @@ -706,7 +770,7 @@ ResolverReturn* resolve_subtract_expr(Resolver* resolver) { err = new_error("operands of pointer - pointer are not compatible"); } else { err = new_error("binary - expression should be either arithmetic - arithmetic, " - "pointer - integer, or pointer - pointer\n"); + "pointer - integer, or pointer - pointer"); } vector_push(errs, err); @@ -901,7 +965,7 @@ ResolverReturn* resolve_address_expr(Resolver* resolver) { (child_srt->type != SRT_IDENT_EXPR || !dtype_isobject(child_srt->dtype))) { errs = new_vector(&t_error); err = new_error("operand of unary & is neither a function designator, " - "a indirection, nor an object lvalue\n"); + "a indirection, nor an object lvalue"); vector_push(errs, err); delete_srt(child_srt); return new_resolverret_errors(errs); diff --git a/src/resolver/expression.h b/src/resolver/expression.h index 6cb1e387..06fa52e1 100644 --- a/src/resolver/expression.h +++ b/src/resolver/expression.h @@ -5,6 +5,7 @@ ResolverReturn* resolve_expr(Resolver* resolver); ResolverReturn* resolve_assignment_expr(Resolver* resolver); +ResolverReturn* resolve_compound_assignment_expr(Resolver* resolver); ResolverReturn* resolve_conditional_expr(Resolver* resolver); ResolverReturn* resolve_logical_expr(Resolver* resolver); ResolverReturn* resolve_bitwise_expr(Resolver* resolver); diff --git a/test-fixtures/assignment/expected.txt b/test-fixtures/assignment/expected.txt new file mode 100644 index 00000000..72163fe1 --- /dev/null +++ b/test-fixtures/assignment/expected.txt @@ -0,0 +1,33 @@ +3 +2 +6 +5 + +9 +1 +8 + +5 +5 + +2 +2 + +6 +6 + +1 +1 + +0 +0 + +1 +1 + +3 +3 + +2 +2 + diff --git a/test-fixtures/assignment/main.c b/test-fixtures/assignment/main.c new file mode 100644 index 00000000..9dccead5 --- /dev/null +++ b/test-fixtures/assignment/main.c @@ -0,0 +1,73 @@ +void put_int(int x); +void put_blank_line(void); + +void simple_assignment(void) { + int first, second, third; + + first = 3; + second = first - 1; + third = first * second; + + put_int(first); + put_int(second); + put_int(third); + put_int(third - (first - second)); + put_blank_line(); + + third = (first = 9) - (second = 1); + put_int(first); + put_int(second); + put_int(third); + put_blank_line(); +} + +void compound_assignment(void) { + int x; + + x = 3; + put_int(x += 2); + put_int(x); + put_blank_line(); + + x = 3; + put_int(x -= 1); + put_int(x); + put_blank_line(); + + x = 3; + put_int(x *= 2); + put_int(x); + put_blank_line(); + + x = 3; + put_int(x /= 2); + put_int(x); + put_blank_line(); + + x = 3; + put_int(x %= 3); + put_int(x); + put_blank_line(); + + x = 3; + put_int(x &= 1); + put_int(x); + put_blank_line(); + + x = 3; + put_int(x |= 1); + put_int(x); + put_blank_line(); + + x = 3; + put_int(x ^= 1); + put_int(x); + put_blank_line(); +} + +int main(void) { + simple_assignment(); + compound_assignment(); + + return 0; +} diff --git a/test-fixtures/variable/expected.txt b/test-fixtures/variable/expected.txt deleted file mode 100644 index 604dafbe..00000000 --- a/test-fixtures/variable/expected.txt +++ /dev/null @@ -1,8 +0,0 @@ -3 -2 -6 -5 - -9 -1 -8 diff --git a/test-fixtures/variable/main.c b/test-fixtures/variable/main.c deleted file mode 100644 index b5e44230..00000000 --- a/test-fixtures/variable/main.c +++ /dev/null @@ -1,23 +0,0 @@ -void put_int(int x); - -int main(void) { - int first, second, third; - void put_blank_line(void); - - first = 3; - second = first - 1; - third = first * second; - - put_int(first); - put_int(second); - put_int(third); - put_int(third - (first - second)); - put_blank_line(); - - third = (first = 9) - (second = 1); - put_int(first); - put_int(second); - put_int(third); - - return 0; -} diff --git a/tests/lexer/test_lexer.c b/tests/lexer/test_lexer.c index d532a136..193df4f2 100644 --- a/tests/lexer/test_lexer.c +++ b/tests/lexer/test_lexer.c @@ -417,13 +417,45 @@ void test_read_statement_while(void) { } void test_read_assignment_expr(void) { - char* input = "x86 = 64;"; + char* input = "x86 = 64; x += 1; x -= 1; x *= 2; x /= 2; x %= 2; x &= 1; x ^= 1; x |= 1;"; Vector* expected = new_vector(&t_ctoken); vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x86"))); vector_push(expected, new_ctoken(CTOKEN_EQUAL)); vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 64))); vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); + vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(expected, new_ctoken(CTOKEN_PLUS_EQUAL)); + vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 1))); + vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); + vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(expected, new_ctoken(CTOKEN_MINUS_EQUAL)); + vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 1))); + vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); + vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(expected, new_ctoken(CTOKEN_ASTERISK_EQUAL)); + vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 2))); + vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); + vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(expected, new_ctoken(CTOKEN_SLASH_EQUAL)); + vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 2))); + vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); + vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(expected, new_ctoken(CTOKEN_PERCENT_EQUAL)); + vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 2))); + vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); + vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(expected, new_ctoken(CTOKEN_AND_EQUAL)); + vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 1))); + vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); + vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(expected, new_ctoken(CTOKEN_CARET_EQUAL)); + vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 1))); + vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); + vector_push(expected, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(expected, new_ctoken(CTOKEN_VBAR_EQUAL)); + vector_push(expected, new_iliteral_ctoken(CTOKEN_INT, new_signed_iliteral(INTEGER_INT, 1))); + vector_push(expected, new_ctoken(CTOKEN_SEMICOLON)); vector_push(expected, new_ctoken(CTOKEN_EOF)); run_lexer_test(input, expected); diff --git a/tests/parser/test_expression.c b/tests/parser/test_expression.c index 2188a6d2..36ba9e98 100644 --- a/tests/parser/test_expression.c +++ b/tests/parser/test_expression.c @@ -4,6 +4,14 @@ #include "../testlib/testlib.h" void test_parse_assignment_expr(void); +void test_parse_multiply_assignment_expr(void); +void test_parse_division_assignment_expr(void); +void test_parse_modulo_assignment_expr(void); +void test_parse_add_assignment_expr(void); +void test_parse_subtract_assignment_expr(void); +void test_parse_bitwise_inclusive_or_assignment_expr(void); +void test_parse_bitwise_exclusive_or_assignment_expr(void); +void test_parse_bitwise_and_assignment_expr(void); void test_parse_conditional_expr(void); void test_parse_logical_or_expr(void); void test_parse_logical_and_expr(void); @@ -49,6 +57,14 @@ void run_expr_parser_test(Vector* input, Ast* expected); CU_Suite* add_test_suite_expr_parser(void) { CU_Suite* suite = CU_add_suite("test_suite_expr_parser", NULL, NULL); CU_ADD_TEST(suite, test_parse_assignment_expr); + CU_ADD_TEST(suite, test_parse_multiply_assignment_expr); + CU_ADD_TEST(suite, test_parse_division_assignment_expr); + CU_ADD_TEST(suite, test_parse_modulo_assignment_expr); + CU_ADD_TEST(suite, test_parse_add_assignment_expr); + CU_ADD_TEST(suite, test_parse_subtract_assignment_expr); + CU_ADD_TEST(suite, test_parse_bitwise_inclusive_or_assignment_expr); + CU_ADD_TEST(suite, test_parse_bitwise_exclusive_or_assignment_expr); + CU_ADD_TEST(suite, test_parse_bitwise_and_assignment_expr); CU_ADD_TEST(suite, test_parse_conditional_expr); CU_ADD_TEST(suite, test_parse_logical_or_expr); CU_ADD_TEST(suite, test_parse_logical_and_expr); @@ -99,7 +115,9 @@ void test_parse_assignment_expr(void) { vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); vector_push(input, new_ctoken(CTOKEN_EQUAL)); vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("p"))); - vector_push(input, new_ctoken(CTOKEN_VBAR_VBAR)); + vector_push(input, new_ctoken(CTOKEN_QUESTION)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("p"))); + vector_push(input, new_ctoken(CTOKEN_COLON)); vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("q"))); vector_push(input, new_ctoken(CTOKEN_EOF)); @@ -109,7 +127,8 @@ void test_parse_assignment_expr(void) { new_identifier_ast(AST_IDENT_EXPR, new_string("x"))), new_ast(AST_ASSIGN_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("y")), - new_ast(AST_LOR_EXPR, 2, // non-terminal + new_ast(AST_COND_EXPR, 3, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("p")), new_identifier_ast(AST_IDENT_EXPR, new_string("p")), new_identifier_ast(AST_IDENT_EXPR, new_string("q"))))); @@ -118,6 +137,166 @@ void test_parse_assignment_expr(void) { delete_ast(expected); } +void test_parse_multiply_assignment_expr(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_ASTERISK_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); + vector_push(input, new_ctoken(CTOKEN_ASTERISK_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("z"))); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Ast* expected = new_ast(AST_MUL_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_ast(AST_MUL_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("y")), + new_identifier_ast(AST_IDENT_EXPR, new_string("z")))); + + run_expr_parser_test(input, expected); + + delete_ast(expected); +} + +void test_parse_division_assignment_expr(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_SLASH_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); + vector_push(input, new_ctoken(CTOKEN_SLASH_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("z"))); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Ast* expected = new_ast(AST_DIV_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_ast(AST_DIV_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("y")), + new_identifier_ast(AST_IDENT_EXPR, new_string("z")))); + + run_expr_parser_test(input, expected); + + delete_ast(expected); +} + +void test_parse_modulo_assignment_expr(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_PERCENT_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); + vector_push(input, new_ctoken(CTOKEN_PERCENT_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("z"))); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Ast* expected = new_ast(AST_MOD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_ast(AST_MOD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("y")), + new_identifier_ast(AST_IDENT_EXPR, new_string("z")))); + + run_expr_parser_test(input, expected); + + delete_ast(expected); +} + +void test_parse_add_assignment_expr(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_PLUS_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); + vector_push(input, new_ctoken(CTOKEN_PLUS_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("z"))); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Ast* expected = new_ast(AST_ADD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_ast(AST_ADD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("y")), + new_identifier_ast(AST_IDENT_EXPR, new_string("z")))); + + run_expr_parser_test(input, expected); + + delete_ast(expected); +} + +void test_parse_subtract_assignment_expr(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_MINUS_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); + vector_push(input, new_ctoken(CTOKEN_MINUS_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("z"))); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Ast* expected = new_ast(AST_SUB_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_ast(AST_SUB_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("y")), + new_identifier_ast(AST_IDENT_EXPR, new_string("z")))); + + run_expr_parser_test(input, expected); + + delete_ast(expected); +} + +void test_parse_bitwise_inclusive_or_assignment_expr(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_VBAR_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); + vector_push(input, new_ctoken(CTOKEN_VBAR_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("z"))); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Ast* expected = new_ast(AST_OR_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_ast(AST_OR_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("y")), + new_identifier_ast(AST_IDENT_EXPR, new_string("z")))); + + run_expr_parser_test(input, expected); + + delete_ast(expected); +} + +void test_parse_bitwise_exclusive_or_assignment_expr(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_CARET_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); + vector_push(input, new_ctoken(CTOKEN_CARET_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("z"))); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Ast* expected = new_ast(AST_XOR_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_ast(AST_XOR_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("y")), + new_identifier_ast(AST_IDENT_EXPR, new_string("z")))); + + run_expr_parser_test(input, expected); + + delete_ast(expected); +} + +void test_parse_bitwise_and_assignment_expr(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_AND_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("y"))); + vector_push(input, new_ctoken(CTOKEN_AND_EQUAL)); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("z"))); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Ast* expected = new_ast(AST_AND_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_ast(AST_AND_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("y")), + new_identifier_ast(AST_IDENT_EXPR, new_string("z")))); + + run_expr_parser_test(input, expected); + + delete_ast(expected); +} + void test_parse_conditional_expr(void) { Vector* input = new_vector(&t_ctoken); vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); diff --git a/tests/parser/test_expression_error.c b/tests/parser/test_expression_error.c index 08cd8b24..2a53c4a6 100644 --- a/tests/parser/test_expression_error.c +++ b/tests/parser/test_expression_error.c @@ -4,6 +4,14 @@ #include "../testlib/testlib.h" void test_parse_assignment_expr_error(void); +void test_parse_multiply_assignment_expr_error(void); +void test_parse_division_assignment_expr_error(void); +void test_parse_modulo_assignment_expr_error(void); +void test_parse_add_assignment_expr_error(void); +void test_parse_subtract_assignment_expr_error(void); +void test_parse_bitwise_inclusive_or_assignment_expr_error(void); +void test_parse_bitwise_exclusive_or_assignment_expr_error(void); +void test_parse_bitwise_and_assignment_expr_error(void); void test_parse_conditional_expr_error_condition(void); void test_parse_conditional_expr_error_lhs(void); void test_parse_conditional_expr_error_colon(void); @@ -51,6 +59,14 @@ void run_expr_parser_error_test(Vector* input, Set* typedef_names_set, Error* ex CU_Suite* add_test_suite_expr_parser_error(void) { CU_Suite* suite = CU_add_suite("test_suite_expr_parser_error", NULL, NULL); CU_ADD_TEST(suite, test_parse_assignment_expr_error); + CU_ADD_TEST(suite, test_parse_multiply_assignment_expr_error); + CU_ADD_TEST(suite, test_parse_division_assignment_expr_error); + CU_ADD_TEST(suite, test_parse_modulo_assignment_expr_error); + CU_ADD_TEST(suite, test_parse_add_assignment_expr_error); + CU_ADD_TEST(suite, test_parse_subtract_assignment_expr_error); + CU_ADD_TEST(suite, test_parse_bitwise_inclusive_or_assignment_expr_error); + CU_ADD_TEST(suite, test_parse_bitwise_exclusive_or_assignment_expr_error); + CU_ADD_TEST(suite, test_parse_bitwise_and_assignment_expr_error); CU_ADD_TEST(suite, test_parse_conditional_expr_error_condition); CU_ADD_TEST(suite, test_parse_conditional_expr_error_lhs); CU_ADD_TEST(suite, test_parse_conditional_expr_error_colon); @@ -109,6 +125,118 @@ void test_parse_assignment_expr_error(void) { delete_error(expected); } +void test_parse_multiply_assignment_expr_error(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_ASTERISK_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_ASTERISK_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Error* expected = new_error("unexpected token *="); + + run_expr_parser_error_test(input, NULL, expected); + + delete_error(expected); +} + +void test_parse_division_assignment_expr_error(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_SLASH_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_SLASH_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Error* expected = new_error("unexpected token /="); + + run_expr_parser_error_test(input, NULL, expected); + + delete_error(expected); +} + +void test_parse_modulo_assignment_expr_error(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_PERCENT_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_PERCENT_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Error* expected = new_error("unexpected token %="); + + run_expr_parser_error_test(input, NULL, expected); + + delete_error(expected); +} + +void test_parse_add_assignment_expr_error(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_PLUS_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_PLUS_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Error* expected = new_error("unexpected token +="); + + run_expr_parser_error_test(input, NULL, expected); + + delete_error(expected); +} + +void test_parse_subtract_assignment_expr_error(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_MINUS_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_MINUS_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Error* expected = new_error("unexpected token -="); + + run_expr_parser_error_test(input, NULL, expected); + + delete_error(expected); +} + +void test_parse_bitwise_inclusive_or_assignment_expr_error(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_VBAR_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_VBAR_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Error* expected = new_error("unexpected token |="); + + run_expr_parser_error_test(input, NULL, expected); + + delete_error(expected); +} + +void test_parse_bitwise_exclusive_or_assignment_expr_error(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_CARET_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_CARET_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Error* expected = new_error("unexpected token ^="); + + run_expr_parser_error_test(input, NULL, expected); + + delete_error(expected); +} + +void test_parse_bitwise_and_assignment_expr_error(void) { + Vector* input = new_vector(&t_ctoken); + vector_push(input, new_identifier_ctoken(CTOKEN_IDENT, new_string("x"))); + vector_push(input, new_ctoken(CTOKEN_AND_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_AND_EQUAL)); + vector_push(input, new_ctoken(CTOKEN_EOF)); + + Error* expected = new_error("unexpected token &="); + + run_expr_parser_error_test(input, NULL, expected); + + delete_error(expected); +} + void test_parse_conditional_expr_error_condition(void) { Vector* input = new_vector(&t_ctoken); vector_push(input, new_ctoken(CTOKEN_QUESTION)); diff --git a/tests/resolver/test_expression.c b/tests/resolver/test_expression.c index 752d147f..f7d1c862 100644 --- a/tests/resolver/test_expression.c +++ b/tests/resolver/test_expression.c @@ -3,6 +3,16 @@ #include "../testlib/testlib.h" void test_resolve_assignment_expr(void); +void test_resolve_multiply_assignment_expr(void); +void test_resolve_division_assignment_expr(void); +void test_resolve_modulo_assignment_expr(void); +void test_resolve_add_assignment_expr(void); +void test_resolve_pointer_add_assignment_expr(void); +void test_resolve_subtract_assignment_expr(void); +void test_resolve_pointer_subtract_assignment_expr(void); +void test_resolve_bitwise_inclusive_or_assignment_expr(void); +void test_resolve_bitwise_exclusive_or_assignment_expr(void); +void test_resolve_bitwise_and_assignment_expr(void); void test_resolve_conditional_expr_arithmetic(void); void test_resolve_conditional_expr_pointer(void); void test_resolve_conditional_expr_struct(void); @@ -20,8 +30,7 @@ void test_resolve_greater_equal_expr(void); void test_resolve_add_expr(void); void test_resolve_subtract_expr(void); void test_resolve_pointer_add_expr(void); -void test_resolve_reversed_pointer_add_expr(void); -void test_resolve_pointer_subtract_expr(void); +void test_resolve_pointer_add_expr_reversed(void); void test_resolve_pointer_subtract_expr(void); void test_resolve_pointer_difference_expr(void); void test_resolve_multiply_expr(void); @@ -70,6 +79,16 @@ void run_local_expr_resolver_test(Ast* input, SymbolTable* symbol_table, TagTabl CU_Suite* add_test_suite_expr_resolver(void) { CU_Suite* suite = CU_add_suite("test_suite_expr_resolver", NULL, NULL); CU_ADD_TEST(suite, test_resolve_assignment_expr); + CU_ADD_TEST(suite, test_resolve_multiply_assignment_expr); + CU_ADD_TEST(suite, test_resolve_division_assignment_expr); + CU_ADD_TEST(suite, test_resolve_modulo_assignment_expr); + CU_ADD_TEST(suite, test_resolve_add_assignment_expr); + CU_ADD_TEST(suite, test_resolve_pointer_add_assignment_expr); + CU_ADD_TEST(suite, test_resolve_subtract_assignment_expr); + CU_ADD_TEST(suite, test_resolve_pointer_subtract_assignment_expr); + CU_ADD_TEST(suite, test_resolve_bitwise_inclusive_or_assignment_expr); + CU_ADD_TEST(suite, test_resolve_bitwise_exclusive_or_assignment_expr); + CU_ADD_TEST(suite, test_resolve_bitwise_and_assignment_expr); CU_ADD_TEST(suite, test_resolve_conditional_expr_arithmetic); CU_ADD_TEST(suite, test_resolve_conditional_expr_pointer); CU_ADD_TEST(suite, test_resolve_conditional_expr_struct); @@ -87,7 +106,7 @@ CU_Suite* add_test_suite_expr_resolver(void) { CU_ADD_TEST(suite, test_resolve_add_expr); CU_ADD_TEST(suite, test_resolve_subtract_expr); CU_ADD_TEST(suite, test_resolve_pointer_add_expr); - CU_ADD_TEST(suite, test_resolve_reversed_pointer_add_expr); + CU_ADD_TEST(suite, test_resolve_pointer_add_expr_reversed); CU_ADD_TEST(suite, test_resolve_pointer_subtract_expr); CU_ADD_TEST(suite, test_resolve_pointer_difference_expr); CU_ADD_TEST(suite, test_resolve_multiply_expr); @@ -162,6 +181,250 @@ void test_resolve_assignment_expr(void) { delete_srt(expected); } +void test_resolve_multiply_assignment_expr(void) { + Ast* input = new_ast(AST_MUL_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("y"), new_integer_dtype(DTYPE_CHAR)); + + Srt* expected = new_dtyped_srt( + SRT_ASSIGN_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(new_integer_dtype(DTYPE_INT)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x"))), + new_dtyped_srt( + SRT_MUL_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x")), + new_dtyped_srt(SRT_CAST_EXPR, new_integer_dtype(DTYPE_INT), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_CHAR), new_string("y"))))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_division_assignment_expr(void) { + Ast* input = new_ast(AST_DIV_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_CHAR)); + symboltable_define_memory(local_table, new_string("y"), new_integer_dtype(DTYPE_INT)); + + Srt* expected = new_dtyped_srt( + SRT_ASSIGN_EXPR, new_integer_dtype(DTYPE_CHAR), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(new_integer_dtype(DTYPE_CHAR)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_CHAR), new_string("x"))), + new_dtyped_srt( + SRT_CAST_EXPR, new_integer_dtype(DTYPE_CHAR), 1, // non-terminal + new_dtyped_srt( + SRT_DIV_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_dtyped_srt(SRT_CAST_EXPR, new_integer_dtype(DTYPE_INT), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_CHAR), new_string("x"))), + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("y"))))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_modulo_assignment_expr(void) { + Ast* input = new_ast(AST_MOD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("y"), new_integer_dtype(DTYPE_INT)); + + Srt* expected = new_dtyped_srt( + SRT_ASSIGN_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(new_integer_dtype(DTYPE_INT)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x"))), + new_dtyped_srt(SRT_MOD_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x")), + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("y")))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_add_assignment_expr(void) { + Ast* input = new_ast(AST_ADD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("y"), new_integer_dtype(DTYPE_CHAR)); + + Srt* expected = new_dtyped_srt( + SRT_ASSIGN_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(new_integer_dtype(DTYPE_INT)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x"))), + new_dtyped_srt( + SRT_ADD_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x")), + new_dtyped_srt(SRT_CAST_EXPR, new_integer_dtype(DTYPE_INT), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_CHAR), new_string("y"))))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_pointer_add_assignment_expr(void) { + Ast* input = new_ast(AST_ADD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("p")), + new_iliteral_ast(AST_INT_EXPR, new_signed_iliteral(INTEGER_INT, 4))); + + SymbolTable* local_table = new_symboltable(); + DType* pointer_dtype = new_pointer_dtype(new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("p"), pointer_dtype); + + Srt* expected = + new_dtyped_srt(SRT_ASSIGN_EXPR, dtype_copy(pointer_dtype), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(dtype_copy(pointer_dtype)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, dtype_copy(pointer_dtype), new_string("p"))), + new_dtyped_srt(SRT_PADD_EXPR, dtype_copy(pointer_dtype), 2, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, dtype_copy(pointer_dtype), new_string("p")), + new_iliteral_srt(SRT_INT_EXPR, new_integer_dtype(DTYPE_INT), + new_signed_iliteral(INTEGER_INT, 4)))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_subtract_assignment_expr(void) { + Ast* input = new_ast(AST_SUB_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_iliteral_ast(AST_INT_EXPR, new_signed_iliteral(INTEGER_INT, 2))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + + Srt* expected = new_dtyped_srt( + SRT_ASSIGN_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(new_integer_dtype(DTYPE_INT)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x"))), + new_dtyped_srt( + SRT_SUB_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x")), + new_iliteral_srt(SRT_INT_EXPR, new_integer_dtype(DTYPE_INT), new_signed_iliteral(INTEGER_INT, 2)))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_pointer_subtract_assignment_expr(void) { + Ast* input = new_ast(AST_SUB_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("p")), + new_ast(AST_NEG_EXPR, 1, // non-terminal + new_iliteral_ast(AST_INT_EXPR, new_signed_iliteral(INTEGER_INT, 8)))); + + SymbolTable* local_table = new_symboltable(); + DType* pointer_dtype = new_pointer_dtype(new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("p"), pointer_dtype); + + Srt* expected = + new_dtyped_srt(SRT_ASSIGN_EXPR, dtype_copy(pointer_dtype), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(dtype_copy(pointer_dtype)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, dtype_copy(pointer_dtype), new_string("p"))), + new_dtyped_srt(SRT_PSUB_EXPR, dtype_copy(pointer_dtype), 2, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, dtype_copy(pointer_dtype), new_string("p")), + new_dtyped_srt(SRT_NEG_EXPR, new_integer_dtype(DTYPE_INT), 1, // non-terminal + new_iliteral_srt(SRT_INT_EXPR, new_integer_dtype(DTYPE_INT), + new_signed_iliteral(INTEGER_INT, 8))))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_bitwise_inclusive_or_assignment_expr(void) { + Ast* input = new_ast(AST_OR_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_CHAR)); + symboltable_define_memory(local_table, new_string("y"), new_integer_dtype(DTYPE_INT)); + + Srt* expected = new_dtyped_srt( + SRT_ASSIGN_EXPR, new_integer_dtype(DTYPE_CHAR), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(new_integer_dtype(DTYPE_CHAR)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_CHAR), new_string("x"))), + new_dtyped_srt( + SRT_CAST_EXPR, new_integer_dtype(DTYPE_CHAR), 1, // non-terminal + new_dtyped_srt( + SRT_OR_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_dtyped_srt(SRT_CAST_EXPR, new_integer_dtype(DTYPE_INT), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_CHAR), new_string("x"))), + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("y"))))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_bitwise_exclusive_or_assignment_expr(void) { + Ast* input = new_ast(AST_XOR_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_iliteral_ast(AST_INT_EXPR, new_unsigned_iliteral(INTEGER_UNSIGNED_INT, 0xFFFF))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + + Srt* expected = new_dtyped_srt( + SRT_ASSIGN_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(new_integer_dtype(DTYPE_INT)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x"))), + new_dtyped_srt( + SRT_CAST_EXPR, new_integer_dtype(DTYPE_INT), 1, // non-terminal + new_dtyped_srt( + SRT_XOR_EXPR, new_integer_dtype(DTYPE_UNSIGNED_INT), 2, // non-terminal + new_dtyped_srt(SRT_CAST_EXPR, new_integer_dtype(DTYPE_UNSIGNED_INT), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("x"))), + new_iliteral_srt(SRT_INT_EXPR, new_integer_dtype(DTYPE_UNSIGNED_INT), + new_unsigned_iliteral(INTEGER_UNSIGNED_INT, 0xFFFF))))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + +void test_resolve_bitwise_and_assignment_expr(void) { + Ast* input = new_ast(AST_AND_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_CHAR)); + symboltable_define_memory(local_table, new_string("y"), new_integer_dtype(DTYPE_INT)); + + Srt* expected = new_dtyped_srt( + SRT_ASSIGN_EXPR, new_integer_dtype(DTYPE_CHAR), 2, // non-terminal + new_dtyped_srt(SRT_ADDR_EXPR, new_pointer_dtype(new_integer_dtype(DTYPE_CHAR)), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_CHAR), new_string("x"))), + new_dtyped_srt( + SRT_CAST_EXPR, new_integer_dtype(DTYPE_CHAR), 1, // non-terminal + new_dtyped_srt( + SRT_AND_EXPR, new_integer_dtype(DTYPE_INT), 2, // non-terminal + new_dtyped_srt(SRT_CAST_EXPR, new_integer_dtype(DTYPE_INT), 1, // non-terminal + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_CHAR), new_string("x"))), + new_identifier_srt(SRT_IDENT_EXPR, new_integer_dtype(DTYPE_INT), new_string("y"))))); + + run_local_expr_resolver_test(input, local_table, NULL, expected, NULL); + + delete_srt(expected); +} + void test_resolve_logical_or_expr(void) { Ast* input = new_ast(AST_LOR_EXPR, 2, // non-terminal new_ast(AST_LOR_EXPR, 2, // non-terminal @@ -643,7 +906,7 @@ void test_resolve_pointer_add_expr(void) { delete_srt(expected); } -void test_resolve_reversed_pointer_add_expr(void) { +void test_resolve_pointer_add_expr_reversed(void) { Ast* input = new_ast(AST_ADD_EXPR, 2, // non-terminal new_iliteral_ast(AST_INT_EXPR, new_signed_iliteral(INTEGER_INT, 2)), new_identifier_ast(AST_IDENT_EXPR, new_string("ptr"))); diff --git a/tests/resolver/test_expression_error.c b/tests/resolver/test_expression_error.c index a58b8e2f..58ee8be7 100644 --- a/tests/resolver/test_expression_error.c +++ b/tests/resolver/test_expression_error.c @@ -2,11 +2,21 @@ #include "../../src/resolver/expression.h" #include "../testlib/testlib.h" -void test_resolve_assign_expr_error_unassignable(void); -void test_resolve_assign_expr_error_void(void); -void test_resolve_assign_expr_error_unmodifiable(void); -void test_resolve_assign_expr_error_lhs(void); -void test_resolve_assign_expr_error_rhs(void); +void test_resolve_assignment_expr_error_unassignable(void); +void test_resolve_assignment_expr_error_void(void); +void test_resolve_assignment_expr_error_unmodifiable(void); +void test_resolve_assignment_expr_error_lhs(void); +void test_resolve_assignment_expr_error_rhs(void); +void test_resolve_multiply_assignment_expr_error_non_arithmetic(void); +void test_resolve_division_assignment_expr_error_non_arithmetic(void); +void test_resolve_modulo_assignment_expr_error_non_integer(void); +void test_resolve_add_assignment_expr_error_operand_dtype(void); +void test_resolve_add_assignment_expr_error_int_and_pointer(void); +void test_resolve_subtract_assignment_expr_error_operand_dtype(void); +void test_resolve_subtract_assignment_expr_error_pointer_diff(void); +void test_resolve_bitwise_inclusive_or_assignment_expr_error_non_integer(void); +void test_resolve_bitwise_exclusive_or_assignment_expr_error_non_integer(void); +void test_resolve_bitwise_add_assignment_expr_error_non_integer(void); void test_resolve_conditional_expr_error_condition_child(void); void test_resolve_conditional_expr_error_condition_non_scalar(void); void test_resolve_conditional_expr_error_lhs(void); @@ -22,16 +32,13 @@ void test_resolve_logical_and_expr_error_non_scalar_lhs(void); void test_resolve_logical_and_expr_error_non_scalar_rhs(void); void test_resolve_logical_and_expr_error_lhs(void); void test_resolve_logical_and_expr_error_rhs(void); -void test_resolve_bitwise_inclusive_or_expr_error_non_integer_lhs(void); -void test_resolve_bitwise_inclusive_or_expr_error_non_integer_rhs(void); +void test_resolve_bitwise_inclusive_or_expr_error_non_integer(void); void test_resolve_bitwise_inclusive_or_expr_error_lhs(void); void test_resolve_bitwise_inclusive_or_expr_error_rhs(void); -void test_resolve_bitwise_exclusive_or_expr_error_non_integer_lhs(void); -void test_resolve_bitwise_exclusive_or_expr_error_non_integer_rhs(void); +void test_resolve_bitwise_exclusive_or_expr_error_non_integer(void); void test_resolve_bitwise_exclusive_or_expr_error_lhs(void); void test_resolve_bitwise_exclusive_or_expr_error_rhs(void); -void test_resolve_bitwise_and_expr_error_non_integer_lhs(void); -void test_resolve_bitwise_and_expr_error_non_integer_rhs(void); +void test_resolve_bitwise_and_expr_error_non_integer(void); void test_resolve_bitwise_and_expr_error_lhs(void); void test_resolve_bitwise_and_expr_error_rhs(void); void test_resolve_equal_expr_error_operand_dtype(void); @@ -129,11 +136,21 @@ void run_expr_resolver_error_test(Ast* input, SymbolTable* symbol_table, TagTabl CU_Suite* add_test_suite_expr_resolver_error(void) { CU_Suite* suite = CU_add_suite("test_suite_expr_resolver_error", NULL, NULL); - CU_ADD_TEST(suite, test_resolve_assign_expr_error_unassignable); - CU_ADD_TEST(suite, test_resolve_assign_expr_error_void); - CU_ADD_TEST(suite, test_resolve_assign_expr_error_unmodifiable); - CU_ADD_TEST(suite, test_resolve_assign_expr_error_lhs); - CU_ADD_TEST(suite, test_resolve_assign_expr_error_rhs); + CU_ADD_TEST(suite, test_resolve_assignment_expr_error_unassignable); + CU_ADD_TEST(suite, test_resolve_assignment_expr_error_void); + CU_ADD_TEST(suite, test_resolve_assignment_expr_error_unmodifiable); + CU_ADD_TEST(suite, test_resolve_assignment_expr_error_lhs); + CU_ADD_TEST(suite, test_resolve_assignment_expr_error_rhs); + CU_ADD_TEST(suite, test_resolve_multiply_assignment_expr_error_non_arithmetic); + CU_ADD_TEST(suite, test_resolve_division_assignment_expr_error_non_arithmetic); + CU_ADD_TEST(suite, test_resolve_modulo_assignment_expr_error_non_integer); + CU_ADD_TEST(suite, test_resolve_add_assignment_expr_error_operand_dtype); + CU_ADD_TEST(suite, test_resolve_add_assignment_expr_error_int_and_pointer); + CU_ADD_TEST(suite, test_resolve_subtract_assignment_expr_error_operand_dtype); + CU_ADD_TEST(suite, test_resolve_subtract_assignment_expr_error_pointer_diff); + CU_ADD_TEST(suite, test_resolve_bitwise_inclusive_or_assignment_expr_error_non_integer); + CU_ADD_TEST(suite, test_resolve_bitwise_exclusive_or_assignment_expr_error_non_integer); + CU_ADD_TEST(suite, test_resolve_bitwise_add_assignment_expr_error_non_integer); CU_ADD_TEST(suite, test_resolve_conditional_expr_error_condition_child); CU_ADD_TEST(suite, test_resolve_conditional_expr_error_condition_non_scalar); CU_ADD_TEST(suite, test_resolve_conditional_expr_error_lhs); @@ -149,16 +166,13 @@ CU_Suite* add_test_suite_expr_resolver_error(void) { CU_ADD_TEST(suite, test_resolve_logical_and_expr_error_non_scalar_rhs); CU_ADD_TEST(suite, test_resolve_logical_and_expr_error_lhs); CU_ADD_TEST(suite, test_resolve_logical_and_expr_error_rhs); - CU_ADD_TEST(suite, test_resolve_bitwise_inclusive_or_expr_error_non_integer_lhs); - CU_ADD_TEST(suite, test_resolve_bitwise_inclusive_or_expr_error_non_integer_rhs); + CU_ADD_TEST(suite, test_resolve_bitwise_inclusive_or_expr_error_non_integer); CU_ADD_TEST(suite, test_resolve_bitwise_inclusive_or_expr_error_lhs); CU_ADD_TEST(suite, test_resolve_bitwise_inclusive_or_expr_error_rhs); - CU_ADD_TEST(suite, test_resolve_bitwise_exclusive_or_expr_error_non_integer_lhs); - CU_ADD_TEST(suite, test_resolve_bitwise_exclusive_or_expr_error_non_integer_rhs); + CU_ADD_TEST(suite, test_resolve_bitwise_exclusive_or_expr_error_non_integer); CU_ADD_TEST(suite, test_resolve_bitwise_exclusive_or_expr_error_lhs); CU_ADD_TEST(suite, test_resolve_bitwise_exclusive_or_expr_error_rhs); - CU_ADD_TEST(suite, test_resolve_bitwise_and_expr_error_non_integer_lhs); - CU_ADD_TEST(suite, test_resolve_bitwise_and_expr_error_non_integer_rhs); + CU_ADD_TEST(suite, test_resolve_bitwise_and_expr_error_non_integer); CU_ADD_TEST(suite, test_resolve_bitwise_and_expr_error_lhs); CU_ADD_TEST(suite, test_resolve_bitwise_and_expr_error_rhs); CU_ADD_TEST(suite, test_resolve_equal_expr_error_operand_dtype); @@ -254,7 +268,7 @@ CU_Suite* add_test_suite_expr_resolver_error(void) { return suite; } -void test_resolve_assign_expr_error_unassignable(void) { +void test_resolve_assignment_expr_error_unassignable(void) { Ast* input = new_ast(AST_ASSIGN_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); @@ -271,7 +285,7 @@ void test_resolve_assign_expr_error_unassignable(void) { delete_vector(expected); } -void test_resolve_assign_expr_error_void(void) { +void test_resolve_assignment_expr_error_void(void) { Ast* input = new_ast(AST_ASSIGN_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), new_ast(AST_CALL_EXPR, 2, // non-terminal @@ -291,7 +305,7 @@ void test_resolve_assign_expr_error_void(void) { delete_vector(expected); } -void test_resolve_assign_expr_error_unmodifiable(void) { +void test_resolve_assignment_expr_error_unmodifiable(void) { Ast* input = new_ast(AST_ASSIGN_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); @@ -308,7 +322,7 @@ void test_resolve_assign_expr_error_unmodifiable(void) { delete_vector(expected); } -void test_resolve_assign_expr_error_lhs(void) { +void test_resolve_assignment_expr_error_lhs(void) { Ast* input = new_ast(AST_ASSIGN_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); @@ -321,7 +335,7 @@ void test_resolve_assign_expr_error_lhs(void) { delete_vector(expected); } -void test_resolve_assign_expr_error_rhs(void) { +void test_resolve_assignment_expr_error_rhs(void) { Ast* input = new_ast(AST_ASSIGN_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); @@ -337,6 +351,179 @@ void test_resolve_assign_expr_error_rhs(void) { delete_vector(expected); } +void test_resolve_multiply_assignment_expr_error_non_arithmetic(void) { + Ast* input = new_ast(AST_MUL_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("p")), + new_iliteral_ast(AST_INT_EXPR, new_signed_iliteral(INTEGER_INT, 5))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_INT))); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("binary * expression should be arithmetic * arithmetic")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_division_assignment_expr_error_non_arithmetic(void) { + Ast* input = new_ast(AST_DIV_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("i")), + new_identifier_ast(AST_IDENT_EXPR, new_string("p"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("i"), new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_INT))); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("binary / expression should be arithmetic / arithmetic")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_modulo_assignment_expr_error_non_integer(void) { + Ast* input = new_ast(AST_MOD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("p")), + new_identifier_ast(AST_IDENT_EXPR, new_string("q"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_CHAR))); + symboltable_define_memory(local_table, new_string("q"), new_pointer_dtype(new_integer_dtype(DTYPE_INT))); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("binary %% expression should be integer %% integer")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_add_assignment_expr_error_operand_dtype(void) { + Ast* input = new_ast(AST_ADD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("p")), + new_identifier_ast(AST_IDENT_EXPR, new_string("q"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_INT))); + symboltable_define_memory(local_table, new_string("q"), new_pointer_dtype(new_integer_dtype(DTYPE_CHAR))); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("binary + expression should be either arithmetic + arithmetic, " + "pointer + integer, or integer + pointer")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_add_assignment_expr_error_int_and_pointer(void) { + Ast* input = new_ast(AST_ADD_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("p"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_INT))); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("expression is not assignable to lvalue")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_subtract_assignment_expr_error_operand_dtype(void) { + Ast* input = new_ast(AST_SUB_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("structure"))); + + Vector* members = new_vector(&t_dstructmember); + vector_push(members, new_dstructmember(new_string("member"), new_integer_dtype(DTYPE_INT))); + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("structure"), new_unnamed_struct_dtype(members)); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("binary - expression should be either arithmetic - arithmetic, " + "pointer - integer, or pointer - pointer")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_subtract_assignment_expr_error_pointer_diff(void) { + Ast* input = new_ast(AST_SUB_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("p")), + new_identifier_ast(AST_IDENT_EXPR, new_string("q"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_INT))); + symboltable_define_memory(local_table, new_string("q"), new_pointer_dtype(new_integer_dtype(DTYPE_INT))); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("expression is not assignable to lvalue")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_bitwise_inclusive_or_assignment_expr_error_non_integer(void) { + Ast* input = new_ast(AST_OR_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("p"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_CHAR))); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("binary | expression should be integer | integer")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_bitwise_exclusive_or_assignment_expr_error_non_integer(void) { + Ast* input = new_ast(AST_XOR_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("p")), + new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_INT))); + symboltable_define_memory(local_table, new_string("y"), new_integer_dtype(DTYPE_INT)); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("binary ^ expression should be integer ^ integer")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + +void test_resolve_bitwise_add_assignment_expr_error_non_integer(void) { + Ast* input = new_ast(AST_AND_ASSIGN_EXPR, 2, // non-terminal + new_identifier_ast(AST_IDENT_EXPR, new_string("x")), + new_identifier_ast(AST_IDENT_EXPR, new_string("p"))); + + SymbolTable* local_table = new_symboltable(); + symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_INT)); + symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_CHAR))); + + Vector* expected = new_vector(&t_error); + vector_push(expected, new_error("binary & expression should be integer & integer")); + + run_expr_resolver_error_test(input, local_table, NULL, expected); + + delete_vector(expected); +} + void test_resolve_conditional_expr_error_condition_child(void) { Ast* input = new_ast(AST_COND_EXPR, 3, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), @@ -609,7 +796,7 @@ void test_resolve_logical_and_expr_error_rhs(void) { delete_vector(expected); } -void test_resolve_bitwise_inclusive_or_expr_error_non_integer_lhs(void) { +void test_resolve_bitwise_inclusive_or_expr_error_non_integer(void) { Ast* input = new_ast(AST_OR_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("p")), new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); @@ -626,23 +813,6 @@ void test_resolve_bitwise_inclusive_or_expr_error_non_integer_lhs(void) { delete_vector(expected); } -void test_resolve_bitwise_inclusive_or_expr_error_non_integer_rhs(void) { - Ast* input = new_ast(AST_OR_EXPR, 2, // non-terminal - new_identifier_ast(AST_IDENT_EXPR, new_string("x")), - new_identifier_ast(AST_IDENT_EXPR, new_string("p"))); - - SymbolTable* local_table = new_symboltable(); - symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_UNSIGNED_INT)); - symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_CHAR))); - - Vector* expected = new_vector(&t_error); - vector_push(expected, new_error("binary | expression should be integer | integer")); - - run_expr_resolver_error_test(input, local_table, NULL, expected); - - delete_vector(expected); -} - void test_resolve_bitwise_inclusive_or_expr_error_lhs(void) { Ast* input = new_ast(AST_OR_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), @@ -672,24 +842,7 @@ void test_resolve_bitwise_inclusive_or_expr_error_rhs(void) { delete_vector(expected); } -void test_resolve_bitwise_exclusive_or_expr_error_non_integer_lhs(void) { - Ast* input = new_ast(AST_XOR_EXPR, 2, // non-terminal - new_identifier_ast(AST_IDENT_EXPR, new_string("p")), - new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); - - SymbolTable* local_table = new_symboltable(); - symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_CHAR))); - symboltable_define_memory(local_table, new_string("y"), new_integer_dtype(DTYPE_INT)); - - Vector* expected = new_vector(&t_error); - vector_push(expected, new_error("binary ^ expression should be integer ^ integer")); - - run_expr_resolver_error_test(input, local_table, NULL, expected); - - delete_vector(expected); -} - -void test_resolve_bitwise_exclusive_or_expr_error_non_integer_rhs(void) { +void test_resolve_bitwise_exclusive_or_expr_error_non_integer(void) { Ast* input = new_ast(AST_XOR_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), new_identifier_ast(AST_IDENT_EXPR, new_string("p"))); @@ -735,7 +888,7 @@ void test_resolve_bitwise_exclusive_or_expr_error_rhs(void) { delete_vector(expected); } -void test_resolve_bitwise_and_expr_error_non_integer_lhs(void) { +void test_resolve_bitwise_and_expr_error_non_integer(void) { Ast* input = new_ast(AST_AND_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("p")), new_identifier_ast(AST_IDENT_EXPR, new_string("y"))); @@ -752,23 +905,6 @@ void test_resolve_bitwise_and_expr_error_non_integer_lhs(void) { delete_vector(expected); } -void test_resolve_bitwise_and_expr_error_non_integer_rhs(void) { - Ast* input = new_ast(AST_AND_EXPR, 2, // non-terminal - new_identifier_ast(AST_IDENT_EXPR, new_string("x")), - new_identifier_ast(AST_IDENT_EXPR, new_string("p"))); - - SymbolTable* local_table = new_symboltable(); - symboltable_define_memory(local_table, new_string("x"), new_integer_dtype(DTYPE_LONG)); - symboltable_define_memory(local_table, new_string("p"), new_pointer_dtype(new_integer_dtype(DTYPE_CHAR))); - - Vector* expected = new_vector(&t_error); - vector_push(expected, new_error("binary & expression should be integer & integer")); - - run_expr_resolver_error_test(input, local_table, NULL, expected); - - delete_vector(expected); -} - void test_resolve_bitwise_and_expr_error_lhs(void) { Ast* input = new_ast(AST_AND_EXPR, 2, // non-terminal new_identifier_ast(AST_IDENT_EXPR, new_string("x")), @@ -809,7 +945,7 @@ void test_resolve_equal_expr_error_operand_dtype(void) { Vector* expected = new_vector(&t_error); vector_push(expected, new_error("binary == expression should be " - "either arithmetic == arithmetic or pointer == pointer\n")); + "either arithmetic == arithmetic or pointer == pointer")); run_expr_resolver_error_test(input, local_table, NULL, expected); @@ -873,7 +1009,7 @@ void test_resolve_not_equal_expr_error_operand_dtype(void) { Vector* expected = new_vector(&t_error); vector_push(expected, new_error("binary != expression should be " - "either arithmetic != arithmetic or pointer != pointer\n")); + "either arithmetic != arithmetic or pointer != pointer")); run_expr_resolver_error_test(input, local_table, NULL, expected); @@ -1183,7 +1319,7 @@ void test_resolve_add_expr_error_operand_dtype(void) { Vector* expected = new_vector(&t_error); vector_push(expected, new_error("binary + expression should be either arithmetic + arithmetic, " - "pointer + integer, or integer + pointer\n")); + "pointer + integer, or integer + pointer")); run_expr_resolver_error_test(input, local_table, NULL, expected); @@ -1229,7 +1365,7 @@ void test_resolve_subtract_expr_error_operand_dtype(void) { Vector* expected = new_vector(&t_error); vector_push(expected, new_error("binary - expression should be either arithmetic - arithmetic, " - "pointer - integer, or pointer - pointer\n")); + "pointer - integer, or pointer - pointer")); run_expr_resolver_error_test(input, local_table, NULL, expected); @@ -1577,7 +1713,7 @@ void test_resolve_address_expr_error_operand_dtype(void) { Vector* expected = new_vector(&t_error); vector_push(expected, new_error("operand of unary & is neither a function designator, " - "a indirection, nor an object lvalue\n")); + "a indirection, nor an object lvalue")); run_expr_resolver_error_test(input, NULL, NULL, expected); diff --git a/tests/testlib/testlib.c b/tests/testlib/testlib.c index a57f4358..1abe334e 100644 --- a/tests/testlib/testlib.c +++ b/tests/testlib/testlib.c @@ -488,11 +488,6 @@ void testlib_assert_error_equal(Error* actual, Error* expected) { } testlib_assert_string_equal(actual->message, expected->message); - if (strcmp(actual->message, expected->message) != 0) { - printf("actual: %s\n", actual->message); - printf("expected: %s\n", expected->message); - return; - } } void testlib_assert_string_equal(char* actual, char* expected) {