EXPRESSION *make_unary_expression(NODE_TYPE type, EXPRESSION *a, int source_line) { EXPRESSION *expr = create_ast_node(type, source_line); tree_add_child(expr, a); expr->type = a->type; return expr; }
EXPRESSION *make_tuple(EXPRESSION *expr1, EXPRESSION *expr2, int source_line) { EXPRESSION *node; if (tree_is_type(expr1, EXPR_TUPLE)) node = expr1; else { node = create_ast_node(EXPR_TUPLE, source_line); tree_add_child(node, expr1); node->type = create_ast_node(TYPE_TUPLE, source_line); tree_add_child(node->type, expr1->type); } tree_add_child(node, expr2); tree_add_child(node->type, expr2->type); return node; }
TYPE *make_map_type(TYPE *t1, TYPE *t2, int source_line) { TYPE *type = create_ast_node(TYPE_MAP, source_line); tree_add_child(type, t1); tree_add_child(type, t2); return type; }
STATEMENT *make_assignment(EXPRESSION *n, EXPRESSION *v, int source_line) { NODE *node = create_ast_node(STMT_ASSIGN, source_line); tree_add_child(node, n); tree_add_child(node, v); return CAST_TO_STATEMENT(node); }
DECLARATION *make_declaration(TYPE *type, char *name, int source_line) { DECLARATION *decl = create_ast_node(DEF_VARIABLE, source_line); decl->type = type; decl->name = name; return decl; }
EXPRESSION *make_integer_direct(int val, int source_line) { INTEGER *expr = create_ast_node(EXPR_INTEGER, source_line); expr->value = val; expr->super.type = make_primitive_type(TYPE_INT, source_line); return CAST_TO_EXPRESSION(expr); }
STATEMENT *make_test(EXPRESSION *c, int source_line) { if (source_line == 0 && c) source_line = CAST_TO_AST(c)->source_line; NODE *node = create_ast_node(STMT_TEST, source_line); tree_add_child(node, c); return CAST_TO_STATEMENT(node); }
EXPRESSION *make_call(EXPRESSION *var, EXPRESSION *args, int source_line) { EXPRESSION *expr = create_ast_node(EXPR_CALL, source_line); tree_add_child(expr, var); tree_add_child(expr, args); expr->type = tree_get_child(var->type, 1); return expr; }
STATEMENT *make_while(EXPRESSION *c, STATEMENT *s1, int source_line) { if (source_line == 0 && c) source_line = CAST_TO_AST(c)->source_line; NODE *node = create_ast_node(STMT_WHILE, source_line); tree_add_child(node, c); tree_add_child(node, make_block(NULL, s1, 0)); return CAST_TO_STATEMENT(node); }
STATEMENT *make_for(STATEMENT *init, EXPRESSION *c, STATEMENT *step, STATEMENT *body, int source_line) { NODE *node = create_ast_node(STMT_FOR, source_line); tree_add_child(node, init); tree_add_child(node, c); tree_add_child(node, step); tree_add_child(node, body); return CAST_TO_STATEMENT(node); }
FUNCTION *make_function(TYPE *type, char *name, DECLARATION *args, int source_line) { FUNCTION *func = create_ast_node(DEF_FUNCTION, source_line); DECLARATION *decl = CAST_TO_DECLARATION(func); decl->name = name; decl->type = make_map_type(args->type, type, source_line); decl->flags |= DECL_STATIC; tree_add_child(func, NULL); tree_add_child(func, args); return func; }
ast_node create_int_astnode(int val){ assert(val < 1000); ast_node node = create_ast_node(INT_LITERAL_N); char *name = calloc(100, sizeof(char)); sprintf(name, "__%d", val); node->value_string = name; node->value_int = val; return node; }
STATEMENT *make_statements(STATEMENT *s1, STATEMENT *s2, int source_line) { NODE *node; if (tree_is_type(s1, STMT_SEQUENCE)) node = CAST_TO_NODE(s1); else { node = create_ast_node(STMT_SEQUENCE, source_line); tree_add_child(node, s1); } tree_add_child(node, s2); return CAST_TO_STATEMENT(node); }
TYPE *make_tuple_type(TYPE *t1, TYPE *t2, int source_line) { NODE *node; if (tree_is_type(t1, TYPE_TUPLE)) node = CAST_TO_NODE(t1); else { node = create_ast_node(TYPE_TUPLE, source_line); tree_add_child(node, t1); } tree_add_child(node, t2); return CAST_TO_TYPE(node); }
EXPRESSION *make_closure(MODULE *mod, TYPE *type, DECLARATION *args, BLOCK *body, int source_line) { static int next_id = 0; char name[100]; sprintf(name, "closure%d", next_id++); char *str = add_string(mod, name, strlen(name)); FUNCTION *func = make_function(type, str, args, source_line); tree_get_child(func, 0) = body; EXPRESSION *expr = create_ast_node(EXPR_CLOSURE, source_line); tree_add_child(expr, func); expr->type = make_map_type(args->type, type, source_line); /* Add new function to module. */ tree_add_child(mod, func); add_to_hash(mod->table, str, strlen(str), func); return expr; }
STATEMENT *make_block(HASH *table, STATEMENT *stmt, int source_line) { if (tree_is_type(stmt, STMT_BLOCK)) return stmt; if (source_line == 0 && stmt) source_line = CAST_TO_AST(stmt)->source_line; BLOCK *block = CAST_TO_BLOCK(create_ast_node(STMT_BLOCK, source_line)); block->table = table ? table : create_hash(10, key_type_copyable); if (tree_is_type(stmt, STMT_SEQUENCE)) { int i; for (i = 0; i < tree_num_children(stmt); i++) tree_add_child(block, tree_get_child(stmt, i)); } else tree_add_child(block, stmt); return CAST_TO_STATEMENT(block); }
EXPRESSION *get_input_tuple(FUNCTION *func) { int source_line = CAST_TO_AST(func)->source_line; EXPRESSION *tuple = create_ast_node(EXPR_TUPLE, source_line); DECLARATION *args = tree_get_child(func, 1); if (!args) return make_empty_tuple(source_line); int i; for (i = 0; i < tree_num_children(args); i++) { DECLARATION *v = tree_get_child(args, i); EXPRESSION *arg = make_variable(v->name, CAST_TO_AST(v)->source_line); arg->type = v->type; ((VARIABLE *) arg)->decl = v; tree_add_child(tuple, arg); } if (tree_num_children(tuple) == 1) return tree_get_child(tuple, 0); return tuple; }
STATEMENT *make_return(EXPRESSION *c, int source_line) { NODE *node = create_ast_node(STMT_RETURN, source_line); tree_add_child(node, c); return CAST_TO_STATEMENT(node); }
STATEMENT *make_pass(int source_line) { NODE *node = create_ast_node(STMT_PASS, source_line); return CAST_TO_STATEMENT(node); }
STATEMENT *make_join(int source_line) { NODE *node = create_ast_node(STMT_JOIN, source_line); return CAST_TO_STATEMENT(node); }
STATEMENT *make_enter(int source_line) { NODE *node = create_ast_node(STMT_ENTER, source_line); return CAST_TO_STATEMENT(node); }
EXPRESSION *make_empty_tuple(int source_line) { NODE *node; node = create_ast_node(EXPR_TUPLE, source_line); return CAST_TO_EXPRESSION(node); }
STATEMENT *make_restart(int source_line) { NODE *node = create_ast_node(STMT_RESTART, source_line); return CAST_TO_STATEMENT(node); }
TYPE *make_primitive_type(NODE_TYPE type, int source_line) { TYPE *t = create_ast_node(type, source_line); return t; }
EXPRESSION *make_variable(char *name, int source_line) { VARIABLE *expr = create_ast_node(EXPR_VARIABLE, source_line); expr->name = name; return CAST_TO_EXPRESSION(expr); }
EXPRESSION *make_string(char *str, int source_line) { STRING *expr = create_ast_node(EXPR_STRING, source_line); expr->value = str; return CAST_TO_EXPRESSION(expr); }
/* * Checks that there is appropriate return for functions * Inserts an implicit return for void type functions * For every return statement, records to which function it returns to */ void check_return_helper(ast_node root, symboltable_t *symtab, ast_node funcnode) { ast_node child2; switch (root->node_type) { case FUNC_DECLARATION_N: funcnode = root; //last function seen child2 = root->left_child->right_sibling; //to SEQ_N assert(child2->node_type == SEQ_N); child2 = child2->left_child->right_sibling; // to STATEMENT_LIST_N assert(child2->node_type == STATEMENT_LIST_N); // fprintf(stderr, "\n\n before for %s at line %d \n\n", NODE_NAME(child2->node_type), child2->line_num); for (child2 = child2->left_child; child2 != NULL && child2->right_sibling != NULL; child2 = child2->right_sibling) { // fprintf(stderr, "\n\n child2 %s at line %d \n\n", NODE_NAME(child2->node_type), child2->line_num); } // assert(child2 != NULL); if(child2 == NULL && funcnode->return_type == INT_TYPE_N) { //child2 is null when the func is empty returnError = 1; fprintf(stderr, "Error: Returning wrong type for function %s declared at line %d\n", funcnode->value_string, funcnode->line_declared); } else if (child2 == NULL) {} //need this! don't delete this line or else having empty funcs will gen error else if((child2->node_type != RETURN_N)){ if(funcnode->return_type == INT_TYPE_N) { returnError = 1; fprintf(stderr, "1 line: %d | Error: No return statement in function %s\n", funcnode->line_num, funcnode->value_string); } else { child2->right_sibling = create_ast_node(RETURN_N); //insert implicit return for void functions child2->right_sibling->return_type = VOID_TYPE_N; child2->right_sibling->left_child = create_ast_node(VOID_TYPE_N); // fprintf(stderr, "\nIMPLICIT RETURN\n"); } } else if( (child2->node_type == RETURN_N) && (funcnode->return_type == INT_TYPE_N) ) { //fprintf(stderr, "detected return! and int main\n"); if(child2->left_child == NULL) { returnError = 1; fprintf(stderr, "2 line: %d | Error: Returning wrong type for function %s\n", child2->line_num, funcnode->value_string); } else { if(child2->left_child->return_type != INT_TYPE_N) { returnError = 1; fprintf(stderr, "3 line: %d | Error: Returning wrong type for function %s\n", child2->line_num, funcnode->value_string); } } } else if( (child2->node_type == RETURN_N) && (funcnode->return_type == VOID_TYPE_N) ) { //fprintf(stderr, "detected return! and void main\n"); if(child2->left_child != NULL) { //returning something returnError = 1; fprintf(stderr, "4 line: %d | Error: Returning wrong type for function %s\n", child2->line_num, funcnode->value_string); } } break; case RETURN_N: assert(root != NULL); assert(funcnode != NULL); root->return_to = funcnode; // fprintf(stderr,"\nreturn to %s at line %d\n", root->return_to->value_string, root->return_to->line_declared); break; default: break; } ast_node child; for (child = root->left_child; child != NULL; child = child->right_sibling) check_return_helper(child, symtab, funcnode); }
STATEMENT *make_continue(int source_line) { NODE *node = create_ast_node(STMT_CONTINUE, source_line); return CAST_TO_STATEMENT(node); }
STATEMENT *make_break(int source_line) { NODE *node = create_ast_node(STMT_BREAK, source_line); return CAST_TO_STATEMENT(node); }
STATEMENT *make_exit(int source_line) { NODE *node = create_ast_node(STMT_EXIT, source_line); return CAST_TO_STATEMENT(node); }