📄 statement.c
字号:
#include "error.h"#include "io.h"#include "salloc.h"#include "statement.h"int stackpointer = 0;int while_counter = 0;int global_if = 0;int global_end = 0;int global_repeat = 0;int global_for = 0;Statement *new_assignment_statement(Expression *lvalue, Expression *rvalue){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = assignment_stat; ASSIGNMENT_STAT(stat).lvalue = lvalue; ASSIGNMENT_STAT(stat).rvalue = rvalue; return stat;}Statement *new_compound_statement(List *declarations, List *statements, Scope *scope){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = compound_stat; COMPOUND_STAT(stat).declarations = declarations; COMPOUND_STAT(stat).statements = statements; COMPOUND_STAT(stat).scope = scope != 0 ? scope : current_scope; COMPOUND_STAT(stat).must_delete_scope = scope != 0; return stat;}Statement *new_delete_statement(Expression *expr){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = delete_stat; DELETE_STAT(stat).expression = expr; return stat;}Statement *new_expression_statement(Expression *expr){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = expr_stat; EXPR_STAT(stat).expression = expr; return stat;}Statement *new_for_statement(Expression *loop_variable, Expression *begin_value, Expression *end_value, Expression *increment_value, Statement *body){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = for_stat; FOR_STAT(stat).loop_variable = loop_variable; FOR_STAT(stat).begin_value = begin_value; FOR_STAT(stat).end_value = end_value; FOR_STAT(stat).increment_value = increment_value; FOR_STAT(stat).body = body; return stat;}Statement *new_if_statement(Expression *condition, Statement *then_body, Statement *else_body){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = if_stat; IF_STAT(stat).condition = condition; IF_STAT(stat).then_body = then_body; IF_STAT(stat).else_body = else_body; return stat;}Statement *new_repeat_statement(Statement *body, Expression *condition){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = repeat_stat; LOOP_STAT(stat).condition = condition; LOOP_STAT(stat).body = body; return stat;}Statement *new_return_statement(Expression *return_value, Token *token){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = return_stat; RETURN_STAT(stat).return_value = return_value; RETURN_STAT(stat).token = token; return stat;}Statement *new_while_statement(Expression *condition, Statement *body){ Statement *stat = safe_malloc(sizeof(Statement)); stat->subtype = while_stat; LOOP_STAT(stat).condition = condition; LOOP_STAT(stat).body = body; return stat;}void delete_statement(Statement *stat){ if (stat!= 0) { switch (stat->subtype) { unsigned i; List *declarations, *statements; case assignment_stat: delete_expression(ASSIGNMENT_STAT(stat).lvalue); delete_expression(ASSIGNMENT_STAT(stat).rvalue); break; case compound_stat: declarations = COMPOUND_STAT(stat).declarations; statements = COMPOUND_STAT(stat).statements; for (i = 0; i < list_size(declarations); i ++) delete_declaration(list_index(declarations, i)); for (i = 0; i < list_size(statements); i ++) delete_statement(list_index(statements, i)); delete_list(declarations); delete_list(statements); if (COMPOUND_STAT(stat).must_delete_scope) delete_scope(COMPOUND_STAT(stat).scope); break; case delete_stat: delete_expression(DELETE_STAT(stat).expression); break; case expr_stat: delete_expression(EXPR_STAT(stat).expression); break; case for_stat: delete_expression(FOR_STAT(stat).loop_variable); delete_expression(FOR_STAT(stat).begin_value); delete_expression(FOR_STAT(stat).end_value); delete_expression(FOR_STAT(stat).increment_value); delete_statement(FOR_STAT(stat).body); break; case if_stat: delete_expression(IF_STAT(stat).condition); delete_statement(IF_STAT(stat).then_body); delete_statement(IF_STAT(stat).else_body); break; case repeat_stat: delete_expression(LOOP_STAT(stat).condition); delete_statement(LOOP_STAT(stat).body); break; case return_stat: delete_expression(RETURN_STAT(stat).return_value); delete_token(RETURN_STAT(stat).token); break; case while_stat: delete_expression(LOOP_STAT(stat).condition); delete_statement(LOOP_STAT(stat).body); break; } free(stat); }}static void type_check_assigment_statement(Statement *stat){ char *err; Expression *lvalue = ASSIGNMENT_STAT(stat).lvalue; Expression *rvalue = ASSIGNMENT_STAT(stat).rvalue; Type *ltype = type_check_expression(lvalue); Type *rtype = type_check_expression(rvalue); if (!types_compatible(ltype, rtype)) error(lvalue->token, "Incompatible types in assignment"); if (!is_lvalue_(lvalue, &err)) error(lvalue->token, "%s is not an lvalue", err);}static void type_check_compound_statement(Statement *stat, Declaration *subprog){ unsigned i; List *statements = COMPOUND_STAT(stat).statements; for (i = 0; i < list_size(statements); i ++) type_check_statement(list_index(statements, i), subprog);}static void type_check_delete_statement(Statement *stat){ Type *t = type_check_expression(DELETE_STAT(stat).expression); if (t != 0 && t->subtype != array_type && t->subtype != null_type) error(DELETE_STAT(stat).expression->token, "can only delete arrays or null expressions");}static void type_check_expression_statement(Statement *stat){ Type *t = type_check_expression(EXPR_STAT(stat).expression); if (t == 0) return; if (t->subtype == subprog_type) error(EXPR_STAT(stat).expression->token, "%s: a procedure or function may not be used as a value", EXPR_STAT(stat).expression->token->name); else if (EXPR_STAT(stat).expression->subtype == expr_eq) warning(EXPR_STAT(stat).expression->token, "the value of the equality operator is ignored (the assignment operator is ':=')");}static void type_check_for_statement(Statement *stat, Declaration *subprog){ struct for_stat *for_stat = &FOR_STAT(stat); Type *loop_type = type_check_expression(for_stat->loop_variable); Type *begin_type = type_check_expression(for_stat->begin_value); Type *end_type = type_check_expression(for_stat->end_value); Type *inc_type = type_check_expression(for_stat->increment_value); if (loop_type != 0 && loop_type->subtype != int_type) error(for_stat->loop_variable->token, "loop variable must be int"); if (begin_type != 0 && begin_type->subtype != int_type) error(for_stat->begin_value->token, "begin value must be int"); if (end_type != 0 && end_type->subtype != int_type) error(for_stat->end_value->token, "end value must be int"); if (inc_type != 0 && inc_type->subtype != int_type) error(for_stat->increment_value->token, "increment value must be int"); if (!is_lvalue(for_stat->loop_variable)) error(for_stat->loop_variable->token, "loop expression is not an lvalue"); type_check_statement(for_stat->body, subprog);}static void type_check_if_statement(Statement *stat, Declaration *subprog){ struct if_stat *if_stat = &IF_STAT(stat); Type *type = type_check_expression(if_stat->condition); if (type != 0 && type->subtype != bool_type) error(if_stat->condition->token, "if condition must be boolean"); type_check_statement(if_stat->then_body, subprog); type_check_statement(if_stat->else_body, subprog);}static void type_check_repetition_statement(Statement *stat, Declaration *subprog){ struct loop_stat *loop_stat = &LOOP_STAT(stat); Type *type = type_check_expression(loop_stat->condition); if (type != 0 && type->subtype != bool_type) error(loop_stat->condition->token, "loop condition must be boolean"); type_check_statement(loop_stat->body, subprog);}static void type_check_return_statement(Statement *stat, Declaration *subprog){ struct return_stat *ret_stat = &RETURN_STAT(stat); Expression *ret_val = ret_stat->return_value; if (subprog == 0) return; if (SUBPROG_DECL(subprog).return_type == 0) abort(); if (SUBPROG_DECL(subprog).return_type->subtype != void_type) if (ret_val != 0) { Type *type = type_check_expression(ret_val); if (!types_compatible(SUBPROG_DECL(subprog).return_type, type)) error(ret_val->token, "incompatible types in return statement"); } else error(ret_stat->token, "return statement must return value in function"); else if (ret_val != 0) error(ret_val->token, "return statement returns value in procedure");}void type_check_statement(Statement *stat, Declaration *subprog){ if (stat != 0) switch (stat->subtype) { case assignment_stat: type_check_assigment_statement(stat); break; case compound_stat: type_check_compound_statement(stat, subprog); break; case delete_stat: type_check_delete_statement(stat); break; case expr_stat: type_check_expression_statement(stat); break; case for_stat: type_check_for_statement(stat, subprog); break; case if_stat: type_check_if_statement(stat, subprog); break; case repeat_stat: case while_stat: type_check_repetition_statement(stat, subprog); break; case return_stat: type_check_return_statement(stat, subprog); }}static void generate_assignment_statement(Statement *stat){ generate_expression(ASSIGNMENT_STAT(stat).lvalue); putc('=', c_out); #ifdef DEBUG printf("="); #endif generate_expression(ASSIGNMENT_STAT(stat).rvalue); fprintf(c_out, ";\n"); #ifdef DEBUG printf(";\n"); #endif}static void generate_compound_statement(Statement *stat){ unsigned i; List *statements = COMPOUND_STAT(stat).statements; fprintf(c_out, "{\n"); #ifdef DEBUG printf("{\n"); #endif generate_declaration_list(COMPOUND_STAT(stat).declarations); for (i = 0; i < list_size(statements); i ++) generate_statement(list_index(statements, i)); fprintf(c_out, "}\n"); #ifdef DEBUG printf("}\n"); #endif}static void generate_delete_statement(Statement *stat){ Expression *expr = DELETE_STAT(stat).expression; fprintf(c_out, "delete_array("); #ifdef DEBUG printf("delete_array("); #endif generate_expression(expr); fprintf(c_out, ");\n"); #ifdef DEBUG printf(");\n"); #endif}static void generate_expression_statement(Statement *stat){ generate_expression(EXPR_STAT(stat).expression); fprintf(c_out, ";\n"); #ifdef DEBUG printf(";\n"); #endif}static void generate_for_statement(Statement *stat){ if (FOR_STAT(stat).increment_value != 0) { fprintf(c_out, "{int e,s;for("); #ifdef DEBUG printf("{int e,s;for("); #endif generate_expression(FOR_STAT(stat).loop_variable); putc('=', c_out); #ifdef DEBUG printf("="); #endif generate_expression(FOR_STAT(stat).begin_value); fprintf(c_out, ",e="); #ifdef DEBUG printf(",e="); #endif generate_expression(FOR_STAT(stat).end_value); fprintf(c_out, ",s="); #ifdef DEBUG printf(",s="); #endif generate_expression(FOR_STAT(stat).increment_value); fprintf(c_out, ";s<0?"); #ifdef DEBUG printf(";s<0?"); #endif generate_expression(FOR_STAT(stat).loop_variable); fprintf(c_out, ">=e:"); #ifdef DEBUG printf(">=e:"); #endif generate_expression(FOR_STAT(stat).loop_variable); fprintf(c_out, "<=e;"); #ifdef DEBUG printf("<=e;"); #endif generate_expression(FOR_STAT(stat).loop_variable); fprintf(c_out, "+=s){\n"); #ifdef DEBUG printf("+=s){\n"); #endif } else { fprintf(c_out, "{int e;for("); #ifdef DEBUG printf("{int e;for("); #endif generate_expression(FOR_STAT(stat).loop_variable); putc('=', c_out); #ifdef DEBUG printf("="); #endif generate_expression(FOR_STAT(stat).begin_value); fprintf(c_out, ",e="); #ifdef DEBUG printf(",e="); #endif generate_expression(FOR_STAT(stat).end_value); putc(';', c_out); #ifdef DEBUG printf(";"); #endif generate_expression(FOR_STAT(stat).loop_variable); fprintf(c_out, "<=e;"); #ifdef DEBUG printf("<=e;"); #endif generate_expression(FOR_STAT(stat).loop_variable); fprintf(c_out, "++){\n"); #ifdef DEBUG printf("++){\n"); #endif } generate_statement(FOR_STAT(stat).body); fprintf(c_out, "}}\n"); #ifdef DEBUG printf("}}\n"); #endif}static void generate_if_statement(Statement *stat){ fprintf(c_out, "if("); #ifdef DEBUG printf("if("); #endif generate_expression(IF_STAT(stat).condition); fprintf(c_out, "){\n"); #ifdef DEBUG printf("){\n"); #endif generate_statement(IF_STAT(stat).then_body); if (IF_STAT(stat).else_body != 0) { fprintf(c_out, "}else{\n"); #ifdef DEBUG printf("}else{\n"); #endif generate_statement(IF_STAT(stat).else_body); } fprintf(c_out, "}\n"); #ifdef DEBUG printf("}\n"); #endif}static void generate_repeat_statement(Statement *stat){ fprintf(c_out, "do{\n"); #ifdef DEBUG printf("do{\n"); #endif generate_statement(LOOP_STAT(stat).body); fprintf(c_out, "}while(!("); #ifdef DEBUG printf("}while(!("); #endif generate_expression(LOOP_STAT(stat).condition); fprintf(c_out, "));\n"); #ifdef DEBUG printf("));\n"); #endif}static void generate_return_statement(Statement *stat){ if (RETURN_STAT(stat).return_value == 0) { fprintf(c_out, "return;\n"); #ifdef DEBUG printf("return;\n"); #endif } else { fprintf(c_out, "return "); #ifdef DEBUG printf("return "); #endif generate_expression(RETURN_STAT(stat).return_value); fprintf(c_out, ";\n"); #ifdef DEBUG printf(";\n"); #endif }}static void generate_while_statement(Statement *stat){ fprintf(c_out, "while("); #ifdef DEBUG printf("while("); #endif generate_expression(LOOP_STAT(stat).condition); fprintf(c_out, "){\n"); #ifdef DEBUG printf("){\n"); #endif generate_statement(LOOP_STAT(stat).body); fprintf(c_out, "}\n"); #ifdef DEBUG printf("}\n"); #endif}void generate_statement(Statement *stat){ switch (stat->subtype) { case assignment_stat: generate_assignment_statement(stat); break; case compound_stat: generate_compound_statement(stat); break; case delete_stat: generate_delete_statement(stat); break; case expr_stat: generate_expression_statement(stat); break; case for_stat: generate_for_statement(stat); break; case if_stat: generate_if_statement(stat); break; case repeat_stat: generate_repeat_statement(stat); break; case return_stat: generate_return_statement(stat); break; case while_stat: generate_while_statement(stat); break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -