int check_while(is_while* node, is_label* label) { int errors = 0; char *string; int mylabel = ++label_counter; /* setting label for use with loops and break/continue */ if (label) node->scope = scope_new(symbol_new_loop(label->name, node->line, mylabel), false); else node->scope = scope_new(symbol_new_loop(NULL, node->line, mylabel), false); scope_push(node->scope); errors += check_expr(node->cond); if (errors == 0) { if (!type_native_assign_able(t_type_native_bool, node->cond->s_type)) { errors++; pretty_error(node->line, "invalid while condition: expected boolean, got %s", string = string_type_decl(node->cond->s_type)); free(string); } } errors += check_stmt(node->body); node->terminates = node->body->terminates; scope_pop(); return errors; }
int check_do_while(is_do_while* node, is_label* label) { int errors = 0; int mylabel = ++label_counter; /* setting label for use with loops and break/continue */ if (label) node->scope = scope_new(symbol_new_loop(label->name, node->line, mylabel), false); else node->scope = scope_new(symbol_new_loop(NULL, node->line, mylabel), false); scope_push(node->scope); errors += check_stmt(node->body); if (errors == 0) node->terminates = node->body->terminates; errors += check_expr(node->cond); if (errors == 0) { if (!type_native_assign_able(t_type_native_bool, node->cond->s_type)) { errors++; pretty_error(node->line, "invalid do..while condition (must be boolean)"); } } scope_pop(); return errors; }
main() { int choice; char buffer[32]; scope_t *top_scope = NULL; node_t *tmp = NULL; fprintf(stderr, "0.search 1.search_all 2.insert 3.new_scope 4.del_scope \n"); while (1) { scanf("%d", &choice); switch(choice) { case 0: scanf("%s", buffer); tmp = scope_search(top_scope, buffer); if (tmp != NULL) { fprintf(stderr, "Found[%s]\n", tmp->name); } else { fprintf(stderr, "Not found[%s]\n", buffer); } break; case 1: scanf("%s", buffer); tmp = scope_search_all(top_scope, buffer); if (tmp != NULL) { fprintf(stderr, "Found[%s]\n", tmp->name); } else { fprintf(stderr, "Not found[%s]\n", buffer); } break; case 2: scanf("%s", buffer); tmp = scope_insert(top_scope, buffer); if (tmp != NULL) { fprintf(stderr, "Insert[%s]\n", tmp->name); } else { fprintf(stderr, "Cannot Insert[%s]\n", buffer); } break; case 3: top_scope = scope_push(top_scope); break; case 4: top_scope = scope_pop(top_scope); break; } } }
int check_for(is_for* node, is_label* label) { int errors = 0, cond_errors; char* typeA; int mylabel = ++label_counter; /* setting label for use with loops and break/continue */ if (label) node->scope = scope_new(symbol_new_loop(label->name, node->line, mylabel), false); else node->scope = scope_new(symbol_new_loop(NULL, node->line, mylabel), false); scope_push(node->scope); if (node->init) errors += check_for_init(node->init); if (node->cond) { cond_errors = check_for_cond(node->cond); if (cond_errors == 0) { if (!type_native_assign_able(t_type_native_bool, node->cond->s_type)) { cond_errors++; pretty_error(node->line, "for conditional is not boolean (is of type %s)", typeA = string_type_decl(node->cond->s_type)); free(typeA); } } errors += cond_errors; } if (node->inc) errors += check_for_inc(node->inc); errors += check_stmt(node->body); if (errors == 0) node->terminates = (node->body ? node->body->terminates : true); scope_pop(); return errors; }
int check_switch(is_switch* node) { int errors = 0; int mylabel = ++label_counter; /* setting label for use with break */ char *type; if (node->label) errors += check_label(node->label); errors += check_expr(node->expr); if (errors == 0) { if (node->expr->s_type->type == t_type_decl_array_decl) { errors++; type = string_type_decl(node->expr->s_type); pretty_error(node->line, "switch statement expression must be of object type (got %s)", type); free(type); } } if (errors == 0) { if (node->label) node->scope = scope_new(symbol_new_switch(node->label->name, node->line, mylabel, node->expr->s_type->data.type_object, symtab->framepos++), false); else node->scope = scope_new(symbol_new_switch(NULL, node->line, mylabel, node->expr->s_type->data.type_object, symtab->framepos++), false); scope_push(node->scope); check_switch_stmt_list(node->list, node); if (errors == 0) node->terminates = (node->list ? node->list->terminates : true); scope_pop(); } return errors; }
static void interpret_routine(struct program *program, struct routine *routine, struct scope **scope, int arg_count, struct var **args) { assert(routine); if (routine->library_routine) { routine->library_routine(*scope, arg_count, args); scope_gc(*scope); return; } *scope = scope_push(*scope, routine->var_count); for (int i = 0; i < arg_count && i < routine->parameter_count; i++) { scope_refer(*scope, i, args[i]); } int exit_code = interpret_stmts(program, routine->stmt_count, routine->stmts, scope); assert(exit_code == EXIT_CODE_RETURN || exit_code == EXIT_CODE_FALLTHROUGH); *scope = scope_pop(*scope); if (*scope) { scope_gc(*scope); } }
int check_class_def(is_class_def* node) { int errors = 0; SYMBOL* symbol; symbol = scope_lookup(symtab, node->id->name, t_symbol_class); if (symbol) { errors++; pretty_error(node->line, "class \"%s\" is already defined (previous declaration was here: %d)", node->id->name, symbol->line); } else scope_insert(symtab, symbol = symbol_new_class(node->id->name, node->line)); node->scope = scope_new(symbol, true); /* FIXME: this should be in application and not in class def, because theoretically class should be able to access other classes */ scope_push(node->scope); errors += check_class_stmt_list(node->body, true); if (errors == 0) { symbol = scope_lookup(symtab, "main", t_symbol_func); if (!symbol) { errors++; pretty_error(node->line, "missing main entry point"); } } errors += check_class_stmt_list(node->body, false); scope_pop(); 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_stmt(is_stmt* node) { int errors = 0; /* ; empty statement */ if (!node) return 0; switch (node->type) { case t_stmt_stmt_list: node->data.stmt_list.scope = scope_new(NULL, false); scope_push(node->data.stmt_list.scope); errors += check_stmt_list(node->data.stmt_list.list); scope_pop(); if (errors == 0) node->terminates = node->data.stmt_list.list->terminated; break; case t_stmt_var_stmt: errors += check_var_stmt(node->data.var, false); break; case t_stmt_assign: errors += check_assign_op(node->data.assign); break; case t_stmt_incr: errors += check_incr_op(node->data.incr); break; case t_stmt_if: errors += check_if(node->data.if_stmt); if (errors == 0) node->terminates = node->data.if_stmt->terminates; break; case t_stmt_loop: errors += check_loop_stmt(node->data.loop); if (errors == 0) node->terminates = node->data.loop->terminates; break; case t_stmt_func_call: errors += check_func_call(node->data.func_call); break; case t_stmt_switch: errors += check_switch(node->data.switch_stmt); if (errors == 0) node->terminates = node->data.switch_stmt->terminates; break; case t_stmt_break: errors += check_break(node->data.break_stmt); node->terminates = true; break; case t_stmt_continue: errors += check_continue(node->data.continue_stmt); node->terminates = true; break; case t_stmt_return: errors += check_return(node->data.return_stmt); node->terminates = true; break; } return errors; }