Skip to content

Commit

Permalink
implement resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
kumachan-mis committed Dec 9, 2023
1 parent 1c129ea commit 54d387b
Show file tree
Hide file tree
Showing 9 changed files with 617 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/resolver/declaration.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ ResolverReturn* resolve_declarator(Resolver* resolver) {

if (array_size_srt->type != SRT_ILITERAL_EXPR || iliteral_isunsigned(array_size_srt->iliteral)) {
errs = new_vector(&t_error);
err = new_error("only integer constant is supported as array size");
err = new_error("only signed integer constant is supported as array size");
vector_push(errs, err);
delete_srt(array_size_srt);
break;
Expand Down
5 changes: 5 additions & 0 deletions src/resolver/resolver.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Resolver* new_resolver(Ast* ast) {
resolver->symbol_table = new_symboltable();
resolver->tag_table = new_tagtable();
resolver->inside_loop = 0;
resolver->switch_cases = NULL;
resolver->switch_default_exists = 0;
resolver->return_dtype = NULL;
resolver->specifier_dtype = NULL;
resolver->default_enum_value = 0;
Expand All @@ -36,6 +38,9 @@ void delete_resolver(Resolver* resolver) {
}
delete_symboltable(resolver->symbol_table);
delete_tagtable(resolver->tag_table);
if (resolver->switch_cases != NULL) {
delete_set(resolver->switch_cases);
}
if (resolver->return_dtype != NULL) {
delete_dtype(resolver->return_dtype);
}
Expand Down
3 changes: 3 additions & 0 deletions src/resolver/resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define UMLCC_RESOLVER_H

#include "../ast/ast.h"
#include "../set/set.h"
#include "../symtab/symtab.h"
#include "../tagtab/tagtab.h"
#include "./resolverret.h"
Expand All @@ -13,6 +14,8 @@ typedef struct Resolver {
SymbolTable* symbol_table;
TagTable* tag_table;
int inside_loop;
Set* switch_cases;
int switch_default_exists;
DType* return_dtype;
DType* specifier_dtype;
int default_enum_value;
Expand Down
155 changes: 155 additions & 0 deletions src/resolver/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ ResolverReturn* resolve_stmt(Resolver* resolver) {
resolver->tag_table = tagtable_exit_scope(resolver->tag_table);
resolver->symbol_table = symboltable_exit_scope(resolver->symbol_table);
break;
case AST_CASE_STMT:
resolverret_assign(&srt, &errs, resolve_case_stmt(resolver));
break;
case AST_DEFAULT_STMT:
resolverret_assign(&srt, &errs, resolve_default_stmt(resolver));
break;
case AST_CONTINUE_STMT:
resolverret_assign(&srt, &errs, resolve_continue_stmt(resolver));
break;
Expand All @@ -37,6 +43,9 @@ ResolverReturn* resolve_stmt(Resolver* resolver) {
case AST_IF_STMT:
resolverret_assign(&srt, &errs, resolve_if_else_stmt(resolver));
break;
case AST_SWITCH_STMT:
resolverret_assign(&srt, &errs, resolve_switch_stmt(resolver));
break;
case AST_WHILE_STMT:
resolverret_assign(&srt, &errs, resolve_while_stmt(resolver));
break;
Expand All @@ -59,6 +68,104 @@ ResolverReturn* resolve_stmt(Resolver* resolver) {
return new_resolverret(srt);
}

ResolverReturn* resolve_case_stmt(Resolver* resolver) {
Srt* srt = new_srt(SRT_CASE_STMT, 0);
Srt* child_srt = NULL;
Vector* errs = NULL;
Error* err = NULL;
Ast* ast = resolver->ast;

if (resolver->switch_cases == NULL) {
errs = new_vector(&t_error);
err = new_error("case statement is not allowed outside of switch");
vector_push(errs, err);
delete_srt(srt);
return new_resolverret_errors(errs);
}

resolver->ast = vector_at(ast->children, 0);
resolverret_assign(&child_srt, &errs, resolve_expr(resolver));
resolver->ast = ast;
if (errs != NULL) {
delete_srt(srt);
return new_resolverret_errors(errs);
}

vector_push(srt->children, child_srt);

if (child_srt->type != SRT_ILITERAL_EXPR || iliteral_isunsigned(child_srt->iliteral)) {
errs = new_vector(&t_error);
err = new_error("only signed integer constant is supported as case label");
vector_push(errs, err);
delete_srt(srt);
return new_resolverret_errors(errs);
}

int* case_value_integer = new_integer(child_srt->iliteral->signed_value);
if (set_contains(resolver->switch_cases, case_value_integer)) {
errs = new_vector(&t_error);
err = new_error("value of case label is already used in switch");
vector_push(errs, err);
delete_srt(srt);
free(case_value_integer);
return new_resolverret_errors(errs);
}

set_add(resolver->switch_cases, case_value_integer);

resolver->ast = vector_at(ast->children, 1);
resolverret_assign(&child_srt, &errs, resolve_stmt(resolver));
resolver->ast = ast;

if (errs != NULL) {
delete_srt(srt);
return new_resolverret_errors(errs);
}

vector_push(srt->children, child_srt);

return new_resolverret(srt);
}

ResolverReturn* resolve_default_stmt(Resolver* resolver) {
Srt* srt = new_srt(SRT_DEFAULT_STMT, 0);
Srt* child_srt = NULL;
Vector* errs = NULL;
Error* err = NULL;
Ast* ast = resolver->ast;

if (resolver->switch_cases == NULL) {
errs = new_vector(&t_error);
err = new_error("default statement is not allowed outside of switch");
vector_push(errs, err);
delete_srt(srt);
return new_resolverret_errors(errs);
}

if (resolver->switch_default_exists) {
errs = new_vector(&t_error);
err = new_error("default statement is already used in switch");
vector_push(errs, err);
delete_srt(srt);
return new_resolverret_errors(errs);
}

resolver->switch_default_exists = 1;

resolver->ast = vector_at(ast->children, 0);
resolverret_assign(&child_srt, &errs, resolve_stmt(resolver));
resolver->ast = ast;

if (errs != NULL) {
delete_srt(srt);
return new_resolverret_errors(errs);
}

vector_push(srt->children, child_srt);

return new_resolverret(srt);
}

ResolverReturn* resolve_compound_stmt(Resolver* resolver) {
Srt* srt = new_srt(SRT_CMPD_STMT, 0);
Vector* errs = NULL;
Expand Down Expand Up @@ -253,6 +360,54 @@ ResolverReturn* resolve_if_else_stmt(Resolver* resolver) {
return new_resolverret(srt);
}

ResolverReturn* resolve_switch_stmt(Resolver* resolver) {
Srt* srt = new_srt(SRT_SWITCH_STMT, 0);
Srt* child_srt = NULL;
Vector* errs = NULL;
Error* err = NULL;
Ast* ast = resolver->ast;

resolver->ast = vector_at(ast->children, 0);
resolverret_assign(&child_srt, &errs, resolve_expr(resolver));
resolver->ast = ast;
if (errs != NULL) {
delete_srt(srt);
return new_resolverret_errors(errs);
}

child_srt = convert_to_ptr_if_array(child_srt);
child_srt = convert_to_ptr_if_function(child_srt);
vector_push(srt->children, child_srt);

if (!dtype_isinteger(child_srt->dtype)) {
errs = new_vector(&t_error);
err = new_error("expression of switch statement should have integer type");
vector_push(errs, err);
delete_srt(srt);
return new_resolverret_errors(errs);
}

Set* original_switch_cases = resolver->switch_cases;
int original_switch_default_exists = resolver->switch_default_exists;
resolver->switch_cases = new_set(&t_hashable_integer);

resolver->ast = vector_at(ast->children, 1);
resolverret_assign(&child_srt, &errs, resolve_stmt(resolver));
resolver->ast = ast;

delete_set(resolver->switch_cases);
resolver->switch_cases = original_switch_cases;
resolver->switch_default_exists = original_switch_default_exists;

if (errs != NULL) {
delete_srt(srt);
return new_resolverret_errors(errs);
}
vector_push(srt->children, child_srt);

return new_resolverret(srt);
}

ResolverReturn* resolve_while_stmt(Resolver* resolver) {
Srt* srt = new_srt(SRT_WHILE_STMT, 0);
Srt* child_srt = NULL;
Expand Down
3 changes: 3 additions & 0 deletions src/resolver/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
#include "./resolver.h"

ResolverReturn* resolve_stmt(Resolver* resolver);
ResolverReturn* resolve_case_stmt(Resolver* resolver);
ResolverReturn* resolve_default_stmt(Resolver* resolver);
ResolverReturn* resolve_compound_stmt(Resolver* resolver);
ResolverReturn* resolve_continue_stmt(Resolver* resolver);
ResolverReturn* resolve_break_stmt(Resolver* resolver);
ResolverReturn* resolve_return_stmt(Resolver* resolver);
ResolverReturn* resolve_expression_stmt(Resolver* resolver);
ResolverReturn* resolve_null_stmt(void);
ResolverReturn* resolve_if_else_stmt(Resolver* resolver);
ResolverReturn* resolve_switch_stmt(Resolver* resolver);
ResolverReturn* resolve_while_stmt(Resolver* resolver);
ResolverReturn* resolve_for_stmt(Resolver* resolver);

Expand Down
3 changes: 3 additions & 0 deletions src/srt/srt.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ typedef enum SrtType {

// statement
SRT_CMPD_STMT,
SRT_CASE_STMT,
SRT_DEFAULT_STMT,
SRT_CONTINUE_STMT,
SRT_BREAK_STMT,
SRT_RET_STMT,
SRT_EXPR_STMT,
SRT_NULL_STMT,
SRT_IF_STMT,
SRT_SWITCH_STMT,
SRT_WHILE_STMT,
SRT_FOR_STMT,

Expand Down
8 changes: 4 additions & 4 deletions tests/resolver/test_declaration_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void test_resolve_declarator_error_incomplete(void);
void test_resolve_array_error_functions(void);
void test_resolve_array_error_incomplete(void);
void test_resolve_array_error_size_non_positive(void);
void test_resolve_array_error_size_limit(void);
void test_resolve_array_error_size_limitation(void);
void test_resolve_struct_error_duplicated(void);
void test_resolve_struct_member_error_duplicated(void);
void test_resolve_struct_member_error_invalid(void);
Expand Down Expand Up @@ -55,7 +55,7 @@ CU_Suite* add_test_suite_decl_resolver_error(void) {
CU_ADD_TEST(suite, test_resolve_array_error_functions);
CU_ADD_TEST(suite, test_resolve_array_error_incomplete);
CU_ADD_TEST(suite, test_resolve_array_error_size_non_positive);
CU_ADD_TEST(suite, test_resolve_array_error_size_limit);
CU_ADD_TEST(suite, test_resolve_array_error_size_limitation);
CU_ADD_TEST(suite, test_resolve_struct_error_duplicated);
CU_ADD_TEST(suite, test_resolve_struct_member_error_duplicated);
CU_ADD_TEST(suite, test_resolve_struct_member_error_invalid);
Expand Down Expand Up @@ -235,7 +235,7 @@ void test_resolve_array_error_size_non_positive(void) {
delete_vector(expected);
}

void test_resolve_array_error_size_limit(void) {
void test_resolve_array_error_size_limitation(void) {
Ast* local_input = new_ast(
AST_DECL, 2, // non-terminal
new_ast(AST_DECL_SPECS, 1, // non-terminal
Expand All @@ -250,7 +250,7 @@ void test_resolve_array_error_size_limit(void) {
Ast* global_input = ast_copy(local_input);

Vector* expected = new_vector(&t_error);
vector_push(expected, new_error("only integer constant is supported as array size"));
vector_push(expected, new_error("only signed integer constant is supported as array size"));

run_local_decl_resolver_error_test(local_input, NULL, NULL, expected);
run_global_decl_resolver_error_test(global_input, NULL, NULL, expected);
Expand Down
Loading

0 comments on commit 54d387b

Please sign in to comment.