📄 expression.c
字号:
#include "error.h"#include "expression.h"#include "salloc.h"#include "statement.h"#include <assert.h>#include <string.h>#include <limits.h>#include <float.h>#include <errno.h>#include <ctype.h>#include "declaration.h"static void string_check_escapes(Token *t);List *string_list;int and_number;int global_equal,local_offset;Scope *record_expr_scope;Scope *expr_scope;Declaration *decl;Type *type;Expression *new_expression(Expr_subtype subtype, Token *token, Expression *left_operand, Expression *right_operand){ Expression *expr = safe_malloc(sizeof(Expression)); expr->subtype = subtype; expr->token = token; expr->operand [0] = left_operand; expr->operand [1] = right_operand; expr->type = 0; switch (subtype) { case expr_func_call: EXPR_FUNC_CALL(expr).formal_args = 0; EXPR_FUNC_CALL(expr).actual_args = 0; break; case expr_ident: EXPR_IDENT(expr).scope = 0; break; default: break; } return expr;}void delete_expression(Expression *expr){ if (expr != 0) { delete_token(expr->token); delete_expression(expr->operand [0]); delete_expression(expr->operand [1]); delete_type(expr->type); switch (expr->subtype) { List *actuals; unsigned i; case expr_func_call: actuals = EXPR_FUNC_CALL(expr).actual_args; for (i = 0; i < list_size(actuals); i ++) delete_expression(list_index(actuals, i)); delete_list(actuals); break; default: break; } free(expr); }}Bool is_lvalue_(Expression *expr, char **offence){ if (expr == 0 || expr->type == 0) return true; if (offence != NULL) *offence = expr->token->name; switch (expr->subtype) { case expr_ident: return expr->type->subtype != subprog_type; case expr_index: return true; case expr_func_call: if (offence != NULL) *offence = "a function call"; return false; case expr_dot: if (is_lvalue_(expr->operand[0],offence)) return true; default: return false; }}/* Type check expr, and see it is of the proper type */static Type *match_type(Expression *expr, Type_subtype subtype_set, const char *expected){ Type *type = type_check_expression(expr); if (type != 0 && (type->subtype & subtype_set) == 0) { error(expr->token, "expected %s type", expected); type = 0; } return type;}static void check_operands_compatibility(Expression *expr){ Expression *operand_0 = expr->operand [0], *operand_1 = expr->operand [1]; if (operand_0 != 0 && operand_1 != 0 && !types_compatible(operand_0->type, operand_1->type)) { error(expr->token, "incompatible types for %s operator\n", expr->token->name); } else { if (operand_0->subtype==record_type && operand_0->type!=0) { if (expr->subtype==expr_eq || expr->subtype==expr_ne) { error(expr->token,"connot compare structs\n"); } } }}static void type_check_expr_dot(Expression *expr){ if ((expr->operand[0]) != NULL){ Type *tempType = type_check_expression(expr->operand[0]); if (tempType==NULL) { return; } if ((tempType)->subtype == record_type) { Declaration *decl, *declTemp; Type *typeL; char *nameL; typeL = expr->operand[0]->type; nameL = RECORD_TYPE(typeL).decl->token->name; decl = RECORD_TYPE(typeL).decl; if (lookup_in_this_scope(RECORD_DECL(decl).member_scope,expr->operand[1]->token->name) != 0 ){ declTemp = lookup_in_this_scope(RECORD_DECL(decl).member_scope,expr->operand[1]->token->name); expr->type = VAR_DECL(declTemp).type; inc_ref_count(expr->type,1); } else {#ifdef DEBUG printf(" %s not found in memberscope\n",expr->operand[1]->token->name);#endif error(expr->operand[1]->token, "%s is not found in the member_scope \n ", expr->operand[1]->token->name); } } else {#ifdef DEBUG printf("Not a record type!\n");#endif error(expr->operand[0]->token, "The used type %s is not of record_type \n ", expr->operand[0]->token->name); } } else {#ifdef DEBUG printf("expr->operand[0] == NULL POINTER!!\n");#endif error(expr->operand[0]->token, "%s is a NULL pointer \n ", expr->operand[0]->token->name); } type_check_expression(expr->operand[1]); if ((expr->operand[1]) != NULL){#ifdef DEBUG printf("Not a NULL type!\n");#endif } else {#ifdef DEBUG printf("expr->operand[1] == NULL POINTER!!\n");#endif error(expr->operand[1]->token, "%s is a NULL pointer \n ", expr->operand[1]->token->name); }}static void type_check_function_call(Expression *expr){ List *formals, *actuals; unsigned i; Declaration *decl; Expression *func; Type *func_type; if (expr == 0) return; func = expr->operand [0]; func_type = type_check_expression(func); if (func_type == 0) return; if (func_type->subtype != subprog_type) { error(func->token, "called object is not a subprogram"); return; } if ((decl = SUBPROG_TYPE(func_type).decl) == 0) return; if ((expr->type = SUBPROG_DECL(decl).return_type) != 0) inc_ref_count(expr->type, 1); formals = EXPR_FUNC_CALL(expr).formal_args = SUBPROG_DECL(decl).formal_args; if (formals == 0) return; if ((actuals = EXPR_FUNC_CALL(expr).actual_args) == 0) return; if (list_size(formals) != list_size(actuals)) { error(expr->token, "parameter count mismatch"); return; } for (i = 0; i < list_size(actuals); i ++) { Declaration *formal_arg = list_index(formals, i); Type *formal_type = VAR_DECL(formal_arg).type; Expression *actual_arg = list_index(actuals, i); Type *actual_type = type_check_expression(actual_arg); Bool call_by_ref = formal_type != 0 && formal_type->call_by_ref; if (!types_compatible(formal_type, actual_type)) error(actual_arg->token, "argument %u: incompatible type", i + 1); if (call_by_ref && !is_lvalue(actual_arg)) error(actual_arg->token, "actual value of call-by-reference argument must be lvalue"); }}static void type_check_identifier(Expression *expr){ Declaration *decl; if (EXPR_IDENT(expr).scope != 0x0) { if ((decl = lookup(EXPR_IDENT(expr).scope, expr->token->name)) == 0) { error(expr->token, "%s not declared", expr->token->name); } else { switch (decl->subtype) { case subprog_decl: expr->type = SUBPROG_DECL(decl).type; break; case var_decl: expr->type = VAR_DECL(decl).type; if (VAR_DECL(decl).type->subtype == record_type) { expr_scope=RECORD_DECL(RECORD_TYPE( VAR_DECL(decl).type ).decl).member_scope; } break; case record_decl: error(expr->token,"error record %s seen as IDENTIFIER\n",expr->token->name); break; } } } else if (expr_scope != 0x0) { if ((decl = lookup(expr_scope,expr->token->name)) == 0) { error(expr->token, "%s not declared", expr->token->name); } else { switch (decl->subtype) { case subprog_decl: expr->type = SUBPROG_DECL(decl).type; break; case var_decl: expr->type = VAR_DECL(decl).type; if (VAR_DECL(decl).type->subtype == record_type) { expr_scope=RECORD_DECL(RECORD_TYPE( VAR_DECL(decl).type ).decl).member_scope; } break; case record_decl: error(expr->token,"error record %s seen as IDENTIFIER\n",expr->token->name); break; } } } inc_ref_count(expr->type, 1);}Type *type_check_expression(Expression *expr){ Token *token; if (expr == 0 || expr->subtype == 0) return 0; switch (expr->subtype) { Type *type; case expr_bool_const: expr->type = new_simple_type(bool_type); break; case expr_char_const: expr->type = new_simple_type(char_type); break; case expr_int_const: expr->type = new_simple_type(int_type); break; case expr_real_const: expr->type = new_simple_type(real_type); break; case expr_string_const: expr->type = new_array_type(new_simple_type(char_type)); string_check_escapes(expr->token); EXPR_STRING_CONST(expr).index = list_size(string_list); list_append(string_list, expr->token->name); break; case expr_null: expr->type = new_null_type(); break; case expr_and: case expr_or: match_type(expr->operand [0], bool_type, "bool"); match_type(expr->operand [1], bool_type, "bool"); expr->type = new_simple_type(bool_type); break; case expr_div: case expr_min: case expr_mul: case expr_plus: expr->type = match_type(expr->operand [0], arithmetic_type, "arithmetic"); match_type(expr->operand [1], arithmetic_type, "arithmetic"); check_operands_compatibility(expr); inc_ref_count(expr->type, 1); break; case expr_eq: case expr_ne: { Type *temptype1 = match_type(expr->operand [0], any_type, ""); Type *temptype2 = match_type(expr->operand [1], any_type, ""); if (temptype1 != 0 ){ if (temptype1->subtype == record_type) { error(expr->operand[0]->token, "Cannot compare structures or Unions\n"); } } else { error(expr->operand[0]->token, "Cannot check subtype of a nullpointer\n"); } if (temptype2 != 0 ){ if (temptype2->subtype == record_type) /*RECHTER KIND HEEFT NULL-TYPE nog controleren ERICK */ { error(expr->operand[1]->token, "Cannot compare structures or Unions\n"); } } else { error(expr->operand[1]->token, "Cannot check subtype of a nullpointer\n"); } check_operands_compatibility(expr); expr->type = new_simple_type(bool_type); } break; case expr_ge: case expr_gt: case expr_se: case expr_st: match_type(expr->operand [0], scalar_type, "scalar"); match_type(expr->operand [1], scalar_type, "scalar"); check_operands_compatibility(expr); expr->type = new_simple_type(bool_type); break; case expr_not: match_type(expr->operand [0], bool_type, "bool"); expr->type = new_simple_type(bool_type); break; case expr_unary_min: case expr_unary_plus: expr->type = match_type(expr->operand [0], arithmetic_type, "arithmetic"); inc_ref_count(expr->type, 1); break; case expr_ident: type_check_identifier(expr); break; case expr_new: match_type(expr->operand [0], int_type, "int"); break; case expr_index: if ((type = match_type(expr->operand[0], array_type, "array")) != 0) { expr->type = ARRAY_TYPE(type).base_type; inc_ref_count(expr->type, 1);/* expr_scope = EXPR_IDENT(expr->operand[0]).scope;*/ expr_scope = bepaal_scope(expr,true); token = bepaal_token(expr,true); decl = lookup(expr_scope,token->name); if (ARRAY_TYPE(VAR_DECL(decl).type).base_type->subtype == record_type) { expr_scope = RECORD_DECL(RECORD_TYPE(ARRAY_TYPE(VAR_DECL(decl).type).base_type).decl).member_scope; } } match_type(expr->operand [1], int_type, "int"); break; case expr_size: match_type(expr->operand [0], array_type, "array"); expr->type = new_simple_type(int_type); break; case expr_func_call: type_check_function_call(expr); break; case expr_dot: type_check_expr_dot(expr); break; default: error(expr->token,"Subtype cannot be NULL during typechecking"); break; } return expr->type;}static void generate_prefix_operator(Expression *expr, const char *symbol){ fprintf(c_out, "(%s", symbol);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -