void symbol_delete(SYMBOL* symbol) { int i; free(symbol->id); switch (symbol->type) { case t_symbol_var: free_type_decl(symbol->data.var_data.type); break; case t_symbol_class: break; case t_symbol_loop: break; case t_symbol_func: free_type_decl(symbol->data.func_data.type); for (i = 0; i < symbol->data.func_data.nArgs; i++) free_func_def_arg(symbol->data.func_data.args[i]); free(symbol->data.func_data.args); break; case t_symbol_switch: free_type_object(symbol->data.switch_data.type); break; } free(symbol); }
void free_type_decls(typedecllist_t type_decls) { for (unsigned i = 0; i < type_decls.size; ++i) { free_type_decl(type_decls.data[i]); } list_free(type_decls); }
int check_return(is_return* node) { int errors = 0; SCOPE* scope; is_type_decl *type = NULL, *typeR; char *typeA, *typeB; if (node->value) { errors += check_expr(node->value); typeR = node->value->s_type; } else { type = new_type_decl_void(node->line); typeR = type; } if (errors == 0) { scope = scope_get_by_name(symtab, NULL, t_symbol_func); node->symbol = scope->symbol; if (!type_type_equal(typeR, node->symbol->data.func_data.type)) { typeA = string_type_decl(typeR); typeB = string_type_decl(node->symbol->data.func_data.type); errors++; pretty_error(node->line, "invalid return type %s should be of type %s", typeA, typeB ); free(typeA); free(typeB); } } if (type) free_type_decl(type); return errors; }
int check_func_def(is_func_def* node, bool first_pass) { SYMBOL* symbol; SCOPE* tempscope; int label; int errors = 0; is_type_decl *tmpType = NULL; if (first_pass) { errors += check_type_decl(node->type); symbol = scope_lookup(symtab, node->id->name, t_symbol_func); if (symbol) { pretty_error(node->line, "symbol \"%s\" is already defined (previous declaration was here: %d)", node->id->name, symbol->line); errors++; } else { tempscope = scope_new(NULL, false); scope_push(tempscope); errors += check_func_def_args(node->args); scope_pop(); if (strcmp(node->id->name, "main") == 0) { label = 0; if (node->args) /* no args is valid */ { if (node->args->length == 1) /* main may must not have more than two arguments */ { tmpType = insert_type_decl_array(insert_array_decl(insert_type_object(t_type_native_string), new_dims_empty_list(0, 1))); /* must be an array of Strings */ if (!type_type_equal(tmpType,node->args->node->type)) { errors++; pretty_error(node->line, "main function arguments do not match any valid prototypes"); } free_type_decl(tmpType); } else { errors++; pretty_error(node->line, "main function arguments do not match any valid prototypes"); } } tmpType = insert_type_decl_object(insert_type_object(t_type_native_int)); /* return value must be int or void */ if (!type_type_equal(tmpType,node->type)) { free_type_decl(tmpType); tmpType = new_type_decl_void(0); /* check for void */ if (!type_type_equal(tmpType,node->type)) /* none; errors occurred */ { errors++; pretty_error(node->line, "main function return type does not match any valid types (nor int nor void)"); } } free_type_decl(tmpType); } else label = ++label_counter; symbol = symbol_new_func(node->id->name, node->line, node->type, node->args, label); scope_delete(tempscope); scope_insert(symtab, symbol); node->scope = scope_new(symbol, false); } } else { scope_push(node->scope); errors += check_func_def_args(node->args); /* this will not give errors */ errors += check_stmt_list(node->body); if ((!node->body || !node->body->terminated) && !(node->type->type == t_type_decl_type_object && node->type->data.type_object->type == t_type_native_void)) { pretty_error(node->line, "reached end of non void function"); errors++; } scope_pop(); } return errors; }
int check_var_defs(is_var_defs* node, bool first_pass) { int errors = 0; SYMBOL *symbol; is_type_decl *type = NULL; is_var_def_list *it; errors += check_type_decl(node->type); errors += check_var_def_list(node->list); for (it = node->list; it != NULL; it = it->next) { symbol = scope_local_lookup(symtab, it->node->left->id->name, t_symbol_var); if (symbol) { errors++; pretty_error(it->node->line, "symbol \"%s\" is already defined (previous declaration was here: %d)", it->node->left->id->name, symbol->line); } else { if (it->node->left->empty->size != 0) { if (node->type->type != t_type_decl_array_decl) { /* create a new type_decl (array) with it->node->left->data.empty->size dimensions */ type = insert_type_decl_array(insert_array_decl(insert_type_object(node->type->data.type_object->type), new_dims_empty_list(node->type->line, it->node->left->empty->size))); } else { /* type is already a type_decl_array, only dims update is needed */ type = duplicate_type_decl(node->type); type->data.array->dims->size += it->node->left->empty->size; } } else /* no dims updates are needed; even if the type is "dimmed" this is only a copy of the type */ type = duplicate_type_decl(node->type); if (first_pass) symbol = scope_insert(symtab, symbol_new_var(it->node->left->id->name, node->line, type, true, globalpos++)); else symbol = scope_insert(symtab, symbol_new_var(it->node->left->id->name, node->line, type, false, symtab->framepos++)); it->node->left->symbol = symbol; if (it->node->var_init) /* check initialization if it exists */ { if (type_var_init_assign_able(type, (type->type == t_type_decl_array_decl ? type->data.array->dims->size : 0), it->node->var_init)) /* if initialization is valid */ symbol->data.var_data.initialized = true; else { errors++; pretty_error(it->node->line, "variable \"%s\" initalization is invalid", it->node->left->id->name); } } } free_type_decl(type); } return errors; }