Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for statement #129

Merged
merged 9 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef enum AstType {
AST_NULL_STMT,
AST_IF_STMT,
AST_WHILE_STMT,
AST_FOR_STMT,

// expression
// assignment-expression
Expand Down
4 changes: 2 additions & 2 deletions src/ctoken/ctoken.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ BaseType t_ctoken = {

char* ctoken_types[] = {
// non-punctuators
"char", "else", "enum", "if", "int", "long", "return", "sizeof", "struct", "typedef", "unsigned", "void", "while",
"identifier", "integer-constant", "character-constant", "string-literal",
"char", "else", "enum", "for", "if", "int", "long", "return", "sizeof", "struct", "typedef", "unsigned", "void",
"while", "identifier", "integer-constant", "character-constant", "string-literal",
// punctuators
"[", "]", "(", ")", "{", "}", ".", "->", "++", "--", "&", "*", "+", "-", "~", "!", "/", "%", "<", ">",
"<=", ">=", "==", "!=", "^", "|", "&&", "||", "?", ":", ";", "=",
Expand Down
1 change: 1 addition & 0 deletions src/ctoken/ctoken.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ typedef enum CTokenType {
CTOKEN_KEYWORD_CHAR,
CTOKEN_KEYWORD_ELSE,
CTOKEN_KEYWORD_ENUM,
CTOKEN_KEYWORD_FOR,
CTOKEN_KEYWORD_IF,
CTOKEN_KEYWORD_INT,
CTOKEN_KEYWORD_LONG,
Expand Down
7 changes: 7 additions & 0 deletions src/immcgen/immcgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ Vector* immcgen_generate_immcode(Immcgen* immcgen) {
case SRT_WHILE_STMT:
codes = gen_while_stmt_immcode(immcgen);
break;
case SRT_FOR_STMT:
immcgen->symbol_table = symboltable_enter_scope(immcgen->symbol_table);
immcgen->tag_table = tagtable_enter_scope(immcgen->tag_table);
codes = gen_for_stmt_immcode(immcgen);
immcgen->tag_table = tagtable_exit_scope(immcgen->tag_table);
immcgen->symbol_table = symboltable_exit_scope(immcgen->symbol_table);
break;
case SRT_ASSIGN_EXPR:
codes = gen_assignment_expr_immcode(immcgen);
break;
Expand Down
37 changes: 31 additions & 6 deletions src/immcgen/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,39 @@ Vector* gen_while_stmt_immcode(Immcgen* immcgen) {
ImmcOpe* begin_label = new_label_immcope_from_id(begin_label_id);
vector_push(codes, new_inst_immc(IMMC_INST_JMP, begin_label, NULL, NULL));

Immc* end_code = vector_at(codes, vector_size(codes) - 1);
if (end_code->type == IMMC_LABEL) {
// reuse label created by child
free(end_label->label_name);
end_label->label_name = new_string(end_code->label->name);
return codes;
vector_push(codes, new_label_immc_from_id(IMMC_LABEL_NORMAL, IMMC_VIS_NONE, end_label_id));

return codes;
}

Vector* gen_for_stmt_immcode(Immcgen* immcgen) {
Vector* codes = new_vector(&t_immc);

immcgen->label_id++;
int begin_label_id = immcgen->label_id;
immcgen->label_id++;
int end_label_id = immcgen->label_id;

append_child_immcode(immcgen, codes, 0);

vector_push(codes, new_label_immc_from_id(IMMC_LABEL_NORMAL, IMMC_VIS_NONE, begin_label_id));

Srt* srt = immcgen->srt;
Srt* controling_stmt_srt = vector_at(immcgen->srt->children, 1);
if (controling_stmt_srt->type == SRT_EXPR_STMT) {
ImmcOpe* end_label = new_label_immcope_from_id(end_label_id);
immcgen->srt = controling_stmt_srt;
append_child_jmp_false_immcode(immcgen, codes, 0, end_label);
immcgen->srt = srt;
}

append_child_immcode(immcgen, codes, 3);

append_child_immcode(immcgen, codes, 2);

ImmcOpe* begin_label = new_label_immcope_from_id(begin_label_id);
vector_push(codes, new_inst_immc(IMMC_INST_JMP, begin_label, NULL, NULL));

vector_push(codes, new_label_immc_from_id(IMMC_LABEL_NORMAL, IMMC_VIS_NONE, end_label_id));

return codes;
Expand Down
1 change: 1 addition & 0 deletions src/immcgen/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ Vector* gen_expression_stmt_immcode(Immcgen* immcgen);
Vector* gen_null_stmt_immcode(void);
Vector* gen_if_else_stmt_immcode(Immcgen* immcgen);
Vector* gen_while_stmt_immcode(Immcgen* immcgen);
Vector* gen_for_stmt_immcode(Immcgen* immcgen);

#endif
1 change: 1 addition & 0 deletions src/lexer/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Map* new_keyword_map(void) {
ctoken_map_add(keyword_map, "char", CTOKEN_KEYWORD_CHAR);
ctoken_map_add(keyword_map, "else", CTOKEN_KEYWORD_ELSE);
ctoken_map_add(keyword_map, "enum", CTOKEN_KEYWORD_ENUM);
ctoken_map_add(keyword_map, "for", CTOKEN_KEYWORD_FOR);
ctoken_map_add(keyword_map, "if", CTOKEN_KEYWORD_IF);
ctoken_map_add(keyword_map, "int", CTOKEN_KEYWORD_INT);
ctoken_map_add(keyword_map, "long", CTOKEN_KEYWORD_LONG);
Expand Down
74 changes: 67 additions & 7 deletions src/parser/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ ParserReturn* parse_stmt(Parser* parser) {
return parse_if_else_stmt(parser);
case CTOKEN_KEYWORD_WHILE:
return parse_while_stmt(parser);
case CTOKEN_KEYWORD_FOR:
return parse_for_stmt(parser);
default:
return parse_expression_stmt(parser);
}
Expand All @@ -41,13 +43,7 @@ ParserReturn* parse_compound_stmt(Parser* parser) {
break;
}

int may_decl = -1;
errint_assign(&may_decl, &err, blockitem_may_decl(parser));
if (err != NULL) {
break;
}

if (may_decl) {
if (item_may_decl(parser)) {
parserret_assign(&child_ast, &err, parse_decl(parser));
} else {
parserret_assign(&child_ast, &err, parse_stmt(parser));
Expand Down Expand Up @@ -216,3 +212,67 @@ ParserReturn* parse_while_stmt(Parser* parser) {

return new_parserret(ast);
}

ParserReturn* parse_for_stmt(Parser* parser) {
Ast* ast = new_ast(AST_FOR_STMT, 0);
Ast* child_ast = NULL;
Error* err = NULL;

err = consume_ctoken(parser, CTOKEN_KEYWORD_FOR);
if (err != NULL) {
delete_ast(ast);
return new_parserret_error(err);
}

err = consume_ctoken(parser, CTOKEN_LPAREN);
if (err != NULL) {
delete_ast(ast);
return new_parserret_error(err);
}

if (item_may_decl(parser)) {
parserret_assign(&child_ast, &err, parse_decl(parser));
} else {
parserret_assign(&child_ast, &err, parse_expression_stmt(parser));
}
if (err != NULL) {
delete_ast(ast);
return new_parserret_error(err);
}
vector_push(ast->children, child_ast);

parserret_assign(&child_ast, &err, parse_expression_stmt(parser));
if (err != NULL) {
delete_ast(ast);
return new_parserret_error(err);
}
vector_push(ast->children, child_ast);

CToken* ctoken = vector_at(parser->ctokens, parser->index);
if (ctoken->type == CTOKEN_RPAREN) {
parser->index++;
vector_push(ast->children, new_ast(AST_NULL_STMT, 0));
} else {
parserret_assign(&child_ast, &err, parse_expr(parser));
if (err != NULL) {
delete_ast(ast);
return new_parserret_error(err);
}
vector_push(ast->children, new_ast(AST_EXPR_STMT, 1, child_ast));

err = consume_ctoken(parser, CTOKEN_RPAREN);
if (err != NULL) {
delete_ast(ast);
return new_parserret_error(err);
}
}

parserret_assign(&child_ast, &err, parse_stmt(parser));
if (err != NULL) {
delete_ast(ast);
return new_parserret_error(err);
}
vector_push(ast->children, child_ast);

return new_parserret(ast);
}
1 change: 1 addition & 0 deletions src/parser/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ ParserReturn* parse_return_stmt(Parser* parser);
ParserReturn* parse_expression_stmt(Parser* parser);
ParserReturn* parse_if_else_stmt(Parser* parser);
ParserReturn* parse_while_stmt(Parser* parser);
ParserReturn* parse_for_stmt(Parser* parser);

#endif
6 changes: 2 additions & 4 deletions src/parser/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@ ErrorableInt* external_may_function_definition(Parser* parser) {
return new_errint(ctoken->type == CTOKEN_LBRACE);
}

ErrorableInt* blockitem_may_decl(Parser* parser) {
int item_may_decl(Parser* parser) {
CToken* ctoken = vector_at(parser->ctokens, parser->index);
int may_decl =
ctoken_is_storage_class_specifier(ctoken) || ctoken_is_type_specifier(ctoken, parser->typedef_names_set);
return new_errint(may_decl);
return ctoken_is_storage_class_specifier(ctoken) || ctoken_is_type_specifier(ctoken, parser->typedef_names_set);
}

int ctoken_is_storage_class_specifier(CToken* ctoken) {
Expand Down
2 changes: 1 addition & 1 deletion src/parser/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "./parser.h"

ErrorableInt* external_may_function_definition(Parser* parser);
ErrorableInt* blockitem_may_decl(Parser* parser);
int item_may_decl(Parser* parser);
int ctoken_is_storage_class_specifier(CToken* ctoken);
int ctoken_is_type_specifier(CToken* ctoken, Set* typedef_names_set);
Error* consume_ctoken(Parser* parser, CTokenType ctoken_type);
Expand Down
90 changes: 90 additions & 0 deletions src/resolver/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ ResolverReturn* resolve_stmt(Resolver* resolver) {
case AST_WHILE_STMT:
resolverret_assign(&srt, &errs, resolve_while_stmt(resolver));
break;
case AST_FOR_STMT:
resolver->symbol_table = symboltable_enter_scope(resolver->symbol_table);
resolver->tag_table = tagtable_enter_scope(resolver->tag_table);
resolverret_assign(&srt, &errs, resolve_for_stmt(resolver));
resolver->symbol_table = symboltable_exit_scope(resolver->symbol_table);
resolver->tag_table = tagtable_exit_scope(resolver->tag_table);
break;
default:
fprintf(stderr, "\x1b[1;31mfatal error\x1b[0m: "
"unreachable statement (in resolve_stmt)\n");
Expand Down Expand Up @@ -254,3 +261,86 @@ ResolverReturn* resolve_while_stmt(Resolver* resolver) {

return new_resolverret(srt);
}

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

resolver->ast = vector_at(ast->children, 0);
int decl_init = resolver->ast->type == AST_DECL;
if (decl_init) {
resolverret_assign(&child_srt, &errs, resolve_decl(resolver));
} else {
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);

if (decl_init) {
int num_children = vector_size(child_srt->children);
for (int i = 0; i < num_children; i++) {
Srt* init_decl_srt = vector_at(child_srt->children, i);
Srt* decl_srt = vector_at(init_decl_srt->children, 0);
if (decl_srt->dtype->type != DTYPE_TYPEDEF) {
continue;
}

errs = new_vector(&t_error);
err = new_error("typedef in for statement initializer is not allowed");
vector_push(errs, err);
delete_srt(srt);
return new_resolverret_errors(errs);
}
}

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);

if (child_srt->type == SRT_EXPR_STMT) {
Srt* controling_expr_srt = vector_at(child_srt->children, 0);
if (!dtype_isscalar(controling_expr_srt->dtype)) {
errs = new_vector(&t_error);
err = new_error("condition of for statement should have scalar type");
vector_push(errs, err);
delete_srt(srt);
return new_resolverret_errors(errs);
}
}

resolver->ast = vector_at(ast->children, 2);
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);

resolver->ast = vector_at(ast->children, 3);
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);
}
1 change: 1 addition & 0 deletions src/resolver/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ ResolverReturn* resolve_expression_stmt(Resolver* resolver);
ResolverReturn* resolve_null_stmt(void);
ResolverReturn* resolve_if_else_stmt(Resolver* resolver);
ResolverReturn* resolve_while_stmt(Resolver* resolver);
ResolverReturn* resolve_for_stmt(Resolver* resolver);

#endif
1 change: 1 addition & 0 deletions src/srt/srt.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ typedef enum SrtType {
SRT_NULL_STMT,
SRT_IF_STMT,
SRT_WHILE_STMT,
SRT_FOR_STMT,

// expression
// assignment-expression
Expand Down
17 changes: 17 additions & 0 deletions test-fixtures/for/expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
0
1
2
3
4

2
4
8
16
32
64
128
256
512
1024
2048
22 changes: 22 additions & 0 deletions test-fixtures/for/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
void put_int(int x);
void put_str(char* str);
void put_blank_line(void);

int main(void) {
for (; 0;) {
put_str("ERROR: for loop should not be executed");
}

for (int i = 0; i < 5; i++) {
put_int(i);
}
put_blank_line();

int i = 0, y = 0, z = 1;
for (i = 0; i < 11; i++) {
z = 2 * z;
put_int(z);
}

return 0;
}
4 changes: 1 addition & 3 deletions test-fixtures/x-mergesort/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,8 @@ int main(void) {
int array[10] = {13, 3, 9, 8, 5, 1, 4, 11, 2, 7};
merge_sort(array, 0, 9);

int i = 0;
while (i < 10) {
for (int i = 0; i < 10; ++i) {
put_int(array[i]);
i++;
}

return 0;
Expand Down
Loading