//check parametertypes of funcall and give type of function to info_type node *CTfuncall(node *arg_node, info *arg_info){ DBUG_ENTER("CTfuncall"); //check parameter types, if there are any if(FUNCALL_ARGS(arg_node)!=NULL){ node *args = FUNCALL_ARGS(arg_node); //check param type against expression type node * param = FUNDEF_PARAMS(FSYMBOL_FUNCTION(FUNCALL_DECL(arg_node))); EXPRS_EXPRS(args) = TRAVdo(EXPRS_EXPRS(args), arg_info); type exprtype = INFO_TYPE(arg_info); type paramtype = PARAM_TYPE(param); if(exprtype != paramtype){ CTIerrorLine(NODE_LINE(arg_node), "argument type does not match function definition"); } //keep checking till there are no parameters left while(EXPRS_NEXT(args)!=NULL){ args = EXPRS_NEXT(args); param = PARAM_NEXT(param); EXPRS_EXPRS(args) = TRAVdo(EXPRS_EXPRS(args), arg_info); exprtype = INFO_TYPE(arg_info); paramtype = PARAM_TYPE(param); if(exprtype != paramtype){ CTIerrorLine(NODE_LINE(arg_node), "argument type does not match function definition"); } } } //set info_type to return type of the function INFO_TYPE(arg_info) = FUNDEF_TYPE(FSYMBOL_FUNCTION(FUNCALL_DECL(arg_node))); DBUG_RETURN(arg_node); }
node *LVARglobaldef( node *arg_node, info *arg_info) { char *var_name; DBUG_ENTER("LVARglobaldef"); var_name = VAR_NAME(GLOBALDEF_ID( arg_node)); /* set declaration of this global variable */ VAR_DECL(GLOBALDEF_ID( arg_node) ) = arg_node; /* check for duplicated variable declaration */ if(hashmap_contains(arg_info->global, var_name)) { CTIerror(":%d: error: '%s' has already been defined in this context", NODE_LINE(arg_node), var_name); CTIerror(":%d: error: location of earlier definition", NODE_LINE((node *)hashmap_get(arg_info->global, var_name))); DBUG_RETURN(arg_node); } /* add global variabele declaration to hashmap */ hashmap_add(arg_info->global, var_name, arg_node); DBUG_RETURN( arg_node); }
//check type of monop with operand node *CTmonop(node *arg_node, info *arg_info){ DBUG_ENTER("CTmonop"); //get type of operand in info_type MONOP_OPERAND(arg_node) = TRAVdo(MONOP_OPERAND(arg_node), arg_info); //check if type is boolean. if(MONOP_OP(arg_node) == MO_not && INFO_TYPE(arg_info) != T_boolean){ CTIerrorLine(NODE_LINE(arg_node), "!(not) can only be used with a boolean operand"); } else{ MONOP_OPTYPE(arg_node) = T_boolean; } if(MONOP_OP(arg_node) == MO_neg && INFO_TYPE(arg_info) == T_boolean){ CTIerrorLine(NODE_LINE(arg_node), "-(neg) can only be used with a boolean operand"); } else if(INFO_TYPE(arg_info) == T_int){ MONOP_OPTYPE(arg_node) = T_int; } else{ MONOP_OPTYPE(arg_node) = T_float; } DBUG_RETURN(arg_node); }
node *CTfor(node *arg_node, info *arg_info){ DBUG_ENTER("CTfor"); FOR_START(arg_node) = TRAVdo(FOR_START(arg_node), arg_info); if (INFO_TYPE(arg_info) != T_int){ CTIerrorLine(NODE_LINE(arg_node), "Start type does not match int"); } FOR_STOP(arg_node) = TRAVdo(FOR_STOP(arg_node), arg_info); if(INFO_TYPE(arg_info) != T_int){ CTIerrorLine(NODE_LINE(arg_node), "Stop type does not match int"); } if(FOR_STEP(arg_node) != NULL){ FOR_STEP(arg_node) = TRAVdo(FOR_STEP(arg_node), arg_info); if(INFO_TYPE(arg_info) != T_int){ CTIerrorLine(NODE_LINE(arg_node), "Step type does not match int"); } } if(FOR_BLOCK(arg_node) != NULL){ FOR_BLOCK(arg_node) = TRAVdo(FOR_BLOCK(arg_node), arg_info); } else if (FOR_BLOCKSINGLE(arg_node) != NULL){ FOR_BLOCKSINGLE(arg_node) = TRAVdo(FOR_BLOCKSINGLE(arg_node), arg_info); } DBUG_RETURN(arg_node); }
//check types of operands of binop and rewrite binop if neccessary node * CTbinop(node *arg_node, info *arg_info){ DBUG_ENTER("CTbinop"); node *leftexpr = BINOP_LEFT(arg_node); node *rightexpr = BINOP_RIGHT(arg_node); //compare types of operands BINOP_LEFT(arg_node) = TRAVdo(BINOP_LEFT(arg_node), arg_info); type typeleft = INFO_TYPE(arg_info); BINOP_RIGHT(arg_node) = TRAVdo(BINOP_RIGHT(arg_node), arg_info); type typeright = INFO_TYPE(arg_info); if(typeleft != typeright){ CTIerrorLine(NODE_LINE(arg_node), "Types of left and right expressions of the binop do not match"); } //check if the right type of operands are used with the right operators if((BINOP_OP(arg_node) == BO_and || BINOP_OP(arg_node) == BO_or)&&INFO_TYPE(arg_info)!=T_boolean){ CTIerrorLine(NODE_LINE(arg_node), "The used &&(and) or ||(or) operator can only compare two booleans"); } if((BINOP_OP(arg_node) == BO_lt || BINOP_OP(arg_node) == BO_le ||BINOP_OP(arg_node) == BO_gt || BINOP_OP(arg_node) == BO_ge) && INFO_TYPE(arg_info) == T_boolean){ CTIerrorLine(NODE_LINE(arg_node), "The used operator can only compare two integers or floats"); } if(BINOP_OP(arg_node) == BO_add ||BINOP_OP(arg_node) == BO_mul ||BINOP_OP(arg_node) == BO_sub ||BINOP_OP(arg_node) == BO_div || BINOP_OP(arg_node) == BO_mod ){ BINOP_OPTYPE(arg_node) = typeleft; } //set info_type to boolean if(BINOP_OP(arg_node) == BO_lt || BINOP_OP(arg_node) == BO_le ||BINOP_OP(arg_node) == BO_gt || BINOP_OP(arg_node) == BO_ge || BINOP_OP(arg_node) == BO_eq || BINOP_OP(arg_node) == BO_ne || BINOP_OP(arg_node) == BO_and || BINOP_OP(arg_node) == BO_or){ INFO_TYPE(arg_info) = T_boolean; BINOP_OPTYPE(arg_node) = typeleft; } else{ BINOP_OPTYPE(arg_node) = typeleft; } //rewrite and if(BINOP_OP(arg_node)==BO_and){ node *then = TBmakeBool(0); arg_node = TBmakeConditionexpr(leftexpr, then, rightexpr); } //rewrite or else if(BINOP_OP(arg_node) == BO_or){ node *orthen = TBmakeBool(1); arg_node = TBmakeConditionexpr(leftexpr, rightexpr, orthen); } DBUG_RETURN(arg_node); }
node *TRAVdo(node *arg_node, info *arg_info) { DBUG_ASSERT( (arg_node != NULL), "Trav: tried to traverse into subtree NULL !"); DBUG_ASSERT( (NODE_TYPE( arg_node) <= MAX_NODES), "Trav: illegal node type !"); DBUG_ASSERT( (travstack != NULL), "no traversal on stack!"); global.line = NODE_LINE( arg_node); if (pretable[ travstack->traversal] != NULL) { arg_node = pretable[ travstack->traversal]( arg_node, arg_info); } arg_node = (travstack->funs[ NODE_TYPE( arg_node)])( arg_node, arg_info); if (posttable[ travstack->traversal] != NULL) { arg_node = posttable[ travstack->traversal]( arg_node, arg_info); } return( arg_node); }
//check type assign node *CTassign(node *arg_node, info *arg_info){ DBUG_ENTER("CTassign"); //compare varlet type with assignent expression type ASSIGN_LET(arg_node) = TRAVdo(ASSIGN_LET(arg_node), arg_info); type vartype = INFO_TYPE(arg_info); ASSIGN_EXPR(arg_node) = TRAVdo(ASSIGN_EXPR(arg_node), arg_info); type exprtype = INFO_TYPE(arg_info); if(vartype != exprtype){ CTIerrorLine(NODE_LINE(arg_node), "The expression type of the assign does not match the variable type"); } DBUG_RETURN(arg_node); }
//check type of return of function against function type node *CTfundef(node *arg_node, info *arg_info){ DBUG_ENTER("CTfundef"); INFO_HASRETURN(arg_info) = 0; INFO_FUNTYPE(arg_info) = 999; FUNDEF_FUNBODY(arg_node) = TRAVopt(FUNDEF_FUNBODY(arg_node), arg_info); if(INFO_HASRETURN(arg_info) == 0){ INFO_FUNTYPE(arg_info) = T_unknown; } if(FUNDEF_TYPE(arg_node) != INFO_FUNTYPE(arg_info) && FUNDEF_EXTERN(arg_node) == FALSE){ CTIerrorLine(NODE_LINE(arg_node), "Return type does not match function type fun: %d ret: %d", FUNDEF_TYPE(arg_node), INFO_TYPE(arg_info)); } DBUG_RETURN(arg_node); }
//check vardec type with initialisation node *CTvardec(node *arg_node, info *arg_info){ DBUG_ENTER("CTvardec"); //only check if there is a initialisation if(VARDEC_INIT(arg_node)!= NULL){ VARDEC_INIT(arg_node) = TRAVdo(VARDEC_INIT(arg_node), arg_info); type vartype = INFO_TYPE(arg_info); if(vartype != VARDEC_TYPE(arg_node)){ CTIerrorLine(NODE_LINE(arg_node), "Initialisation value does not match the type of the declared variable"); } } //ga verder met traversal VARDEC_NEXT(arg_node) = TRAVopt(VARDEC_NEXT(arg_node), arg_info); DBUG_RETURN(arg_node); }
node *TRAVdo(node *arg_node, info *arg_info) { nodetype arg_node_type; char *old_file = global.nodefile; int old_line = global.nodeline; int old_col = global.nodecol; /* * check whether the node is non null as this * is a common reason for segfaults */ DBUG_ASSERT( (arg_node != NULL), "tried to traverse a node which is NULL!"); /* * Make sure the location will be set * correctly in case MakeXxx is called. */ global.nodefile = NODE_FILE(arg_node); global.nodeline = NODE_LINE(arg_node); global.nodecol = NODE_COL( arg_node); /* * Save node type as it might be modified during traversal */ arg_node_type = NODE_TYPE( arg_node); if (pretable[ travstack->traversal] != NULL) { arg_node = pretable[ travstack->traversal]( arg_node, arg_info); } arg_node = (travstack->funs[ arg_node_type])( arg_node, arg_info); if (posttable[ travstack->traversal] != NULL) { arg_node = posttable[ travstack->traversal]( arg_node, arg_info); } global.nodefile = old_file; global.nodeline = old_line; global.nodecol = old_col; return( arg_node); }
node *LVARvar( node *arg_node, info *arg_info) { char *var_name; node *var_dec; DBUG_ENTER("LVARvar"); var_name = VAR_NAME(arg_node); /* check for local variable declaration */ var_dec = hashmap_get(arg_info->local, var_name); /* check for global variable declaration */ if(!var_dec) var_dec = hashmap_get(arg_info->global, var_name); if(var_dec) VAR_DECL(arg_node) = var_dec; else CTIerror(":%d: error: unknown identifier '%s'", NODE_LINE(arg_node), var_name); DBUG_RETURN( arg_node); }