gassign * build_assign (enum tree_code code, tree op1, tree op2, tree lhs) { if (lhs == NULL_TREE) lhs = make_ssa_name (get_expr_type (code, op1)); return gimple_build_assign (lhs, code, op1, op2); }
void validate_array_indices(Exprs *indices, char *id, int line_no, sym_table *table, char *scope_id, symbol *array_sym) { int p_num = 1; Decl *d = (Decl *) array_sym->sym_value; Intervals *is = d->array; while (indices != NULL) { Expr *e = indices->first; Type t = get_expr_type(e, NULL, table, scope_id, line_no); if (t != INT_TYPE) { print_array_index_error(indices, id, line_no, p_num, t); isValid = FALSE; } else if (e->kind == EXPR_CONST) { //Now check bounds for static //We now know it's int and Interval *i = is->first; int val = e->constant.val.int_val; if (i->lower > val || val > i->upper) { //Then we have out of bounds here. print_array_outofbounds_error(indices, id, line_no, p_num, i); e->inferred_type = INVALID_TYPE; } } is = is->rest; indices = indices->rest; p_num++; } }
void analyse_function(Function *f, sym_table *prog, char *scope_id, int line_no) { //Find the scope of the function scope *called = find_scope(f->id, prog); //Find the scope if (!called) { //Ooops this is an error. Report it. print_undefined_proc_call_error(f, line_no); isValid = FALSE; return; } Params *fcallee = (Params *) called->params; Exprs *fcaller = f->args; //Check number of variables int call_no = count_list((void *)fcaller); int expect_no = count_list((void *)fcallee); if (call_no != expect_no) { print_func_pmismatch_error(f, fcallee, line_no, expect_no, call_no); isValid = FALSE; } else { //Go through each variable and try match. We know these are the same //lenght now. int par_num = 1; while (fcallee != NULL) { Expr *e = fcaller->first; Param *p = fcallee->first; Type caller = get_expr_type(e, NULL, prog, scope_id, line_no); if (caller != p->type && p->ind == VAL_IND) { if ((caller == INT_TYPE) && (p->type == FLOAT_TYPE)) { // This is valid, we can cast an int val into a float val } else { //Then the parameter calls are incorrect print_func_ptype_error(par_num, caller, p->type, f, line_no); isValid = FALSE; } } else if (caller != p->type && p->ind == REF_IND) { if ((caller == FLOAT_TYPE) && (p->type == INT_TYPE)) { // This is valid, we can cast an int into a float to store // in the ref. } else { //Then the parameter calls are incorrect print_func_ptype_error(par_num, caller, p->type, f, line_no); isValid = FALSE; } } else if (caller != p->type && caller != INVALID_TYPE) { //Then the parameter calls are incorrect print_func_ptype_error(par_num, caller, p->type, f, line_no); isValid = FALSE; } fcallee = fcallee->rest; fcaller = fcaller->rest; par_num ++; } } }
gassign * build_assign (enum tree_code code, tree op1, int val, tree lhs) { tree op2 = build_int_cst (TREE_TYPE (op1), val); if (lhs == NULL_TREE) lhs = make_ssa_name (get_expr_type (code, op1)); return gimple_build_assign (lhs, code, op1, op2); }
void analyse_while(While *loop, sym_table *table, char *scope_id, int line_no) { //Analyse condition Type c = get_expr_type(loop->cond, NULL, table, scope_id, line_no); if (c != BOOL_TYPE) { print_while_error(loop->cond, c, line_no); isValid = FALSE; } //Analyse statement analyse_statements(loop->body, table, scope_id); }
void analyse_assign(Assign *a, sym_table *table, char *scope_id, int line_no) { //Get the type of the left and right analysis then ensure they match. Type left = get_expr_type(a->asg_ident, NULL, table, scope_id, line_no); Type right = get_expr_type(a->asg_expr, NULL, table, scope_id, line_no); //Check they are both valid and equivalent if (left == INVALID_TYPE || right == INVALID_TYPE) { return; } //We can assign ints to floats but not the other way around if (left == right || (left == FLOAT_TYPE && right == INT_TYPE)) { //All good, return return; } else { //Not good. Let the user know print_assign_error( a, left, right, line_no); isValid = FALSE; } }
void analyse_if(Cond *ifcond, sym_table *table, char *scope_id, int line_no) { //Analyse condition Type c = get_expr_type(ifcond->cond, NULL, table, scope_id, line_no); if (c != BOOL_TYPE) { print_if_error(ifcond->cond, c, line_no); isValid = FALSE; } //Analyse then branch analyse_statements(ifcond->then_branch, table, scope_id); //Analyse else branch analyse_statements(ifcond->else_branch, table, scope_id); }
Type get_expr_type(Expr *e, Expr *parent, sym_table *table, char *scope_id, int line_no) { //Find the type of an expression ExprKind kind = e->kind; // Switch on kind to print switch (kind) { case EXPR_ID: //Find the symbol and get it's type if (retrieve_symbol(e->id, scope_id, table)) { //Lets check the type Type t = get_type(retrieve_symbol(e->id, scope_id, table)); e->inferred_type = t; return t; } else { //Not good. Let the user know. print_undefined_variable_error(e, parent, line_no); isValid = FALSE; e->inferred_type = INVALID_TYPE; return INVALID_TYPE; } break; case EXPR_CONST: if (e != NULL) { //f**k c. Type t = get_const_type(e); e->inferred_type = t; return t; } break; case EXPR_BINOP: //We need the types of each expression //Then we determine the type if allowed using the binop return get_binop_type(get_expr_type(e->e1, e, table, scope_id, line_no), get_expr_type(e->e2, e, table, scope_id, line_no), e->binop, line_no, e); break; case EXPR_UNOP: //Get the type of the expression //Then we determine the type if allowed using the binop return get_unop_type(get_expr_type(e->e1, e, table, scope_id, line_no), e->unop, line_no, e); break; case EXPR_ARRAY: //We need to check array dimensions, then check all expressions are //int equiv. if (validate_array_dims(e, scope_id, table)) { symbol *a = retrieve_symbol(e->id, scope_id, table); validate_array_indices(e->indices, e->id, line_no, table, scope_id, a); e->inferred_type = get_type(a); return e->inferred_type; } else { symbol *a = retrieve_symbol(e->id, scope_id, table); if (a != NULL) { // Now check if a is an array if (a->bounds == NULL) { print_not_array_error(e, a->sym_value, line_no); } else { Decl *d = (Decl *) a->sym_value; print_array_dims_error(e, count_array(d->array), count_list(e->indices), line_no); } isValid = FALSE; } else { print_undefined_variable_error(e, NULL, line_no); isValid = FALSE; } e->inferred_type = INVALID_TYPE; return INVALID_TYPE; } return INVALID_TYPE; break; } return INVALID_TYPE; }
void analyse_write(Expr *write, sym_table *table, char *scope_id, int line_no) { //We just need to check the type is valid or that it is a constant, // so we try get the symbol and if we fail then we can't write. get_expr_type(write, NULL, table, scope_id, line_no); }
void analyse_read(Expr *read, sym_table *table, char *scope_id, int line_no) { //We just need to check the type is valid, so we try get the symbol and if //we fail then we can't read. get_expr_type(read, NULL, table, scope_id, line_no); }