static void handle_stack(reachable_method_stack_t* s, reachable_types_t* r, uint32_t* next_type_id) { while(s != NULL) { reachable_method_t* m; s = reachable_method_stack_pop(s, &m); AST_GET_CHILDREN(m->r_fun, cap, id, typeparams, params, result, can_error, body); m->param_count = ast_childcount(params); m->params = (reachable_type_t**)ponyint_pool_alloc_size( m->param_count * sizeof(reachable_type_t*)); ast_t* param = ast_child(params); size_t i = 0; while(param != NULL) { AST_GET_CHILDREN(param, p_id, p_type); m->params[i++] = add_type(&s, r, next_type_id, p_type); param = ast_sibling(param); } m->result = add_type(&s, r, next_type_id, result); reachable_expr(&s, r, next_type_id, body); } }
static void handle_stack(reach_t* r, pass_opt_t* opt) { while(r->stack != NULL) { reach_method_t* m; r->stack = reach_method_stack_pop(r->stack, &m); ast_t* body = ast_childidx(m->r_fun, 6); reachable_expr(r, body, opt); } }
static void reachable_pattern(reachable_method_stack_t** s, reachable_types_t* r, uint32_t* next_type_id, ast_t* ast) { switch(ast_id(ast)) { case TK_DONTCARE: case TK_NONE: break; case TK_VAR: case TK_LET: { AST_GET_CHILDREN(ast, idseq, type); add_type(s, r, next_type_id, type); break; } case TK_TUPLE: case TK_SEQ: { ast_t* child = ast_child(ast); while(child != NULL) { reachable_pattern(s, r, next_type_id, child); child = ast_sibling(child); } break; } default: { reachable_method(s, r, next_type_id, ast_type(ast), stringtab("eq"), NULL); reachable_expr(s, r, next_type_id, ast); break; } } }
static void handle_stack(reachable_method_stack_t* s, reachable_types_t* r, uint32_t* next_type_id) { while(s != NULL) { reachable_method_t* m; s = reachable_method_stack_pop(s, &m); AST_GET_CHILDREN(m->r_fun, cap, id, typeparams, params, result, can_error, body); ast_t* param = ast_child(params); while(param != NULL) { AST_GET_CHILDREN(param, p_id, p_type); add_type(&s, r, next_type_id, p_type); param = ast_sibling(param); } add_type(&s, r, next_type_id, result); reachable_expr(&s, r, next_type_id, body); } }
static void reachable_pattern(reach_t* r, ast_t* ast, pass_opt_t* opt) { switch(ast_id(ast)) { case TK_DONTCARE: case TK_NONE: break; case TK_MATCH_CAPTURE: { AST_GET_CHILDREN(ast, idseq, type); add_type(r, type, opt); break; } case TK_TUPLE: case TK_SEQ: { ast_t* child = ast_child(ast); while(child != NULL) { reachable_pattern(r, child, opt); child = ast_sibling(child); } break; } default: { reachable_method(r, ast_type(ast), stringtab("eq"), NULL, opt); reachable_expr(r, ast, opt); break; } } }
static void reachable_expr(reachable_method_stack_t** s, reachable_types_t* r, uint32_t* next_type_id, ast_t* ast) { // If this is a method call, mark the method as reachable. switch(ast_id(ast)) { case TK_TRUE: case TK_FALSE: case TK_INT: case TK_FLOAT: case TK_STRING: { ast_t* type = ast_type(ast); if(type != NULL) reachable_method(s, r, next_type_id, type, stringtab("create"), NULL); break; } case TK_TUPLE: { ast_t* type = ast_type(ast); add_type(s, r, next_type_id, type); break; } case TK_CASE: { AST_GET_CHILDREN(ast, pattern, guard, body); reachable_pattern(s, r, next_type_id, pattern); reachable_expr(s, r, next_type_id, guard); reachable_expr(s, r, next_type_id, body); break; } case TK_CALL: reachable_call(s, r, next_type_id, ast); break; case TK_FFICALL: reachable_ffi(s, r, next_type_id, ast); break; case TK_ADDRESS: reachable_addressof(s, r, next_type_id, ast); break; case TK_IF: { AST_GET_CHILDREN(ast, cond, then_clause, else_clause); assert(ast_id(cond) == TK_SEQ); cond = ast_child(cond); if(ast_sibling(cond) == NULL) { if(ast_id(cond) == TK_TRUE) { reachable_expr(s, r, next_type_id, then_clause); return; } else if(ast_id(cond) == TK_FALSE) { reachable_expr(s, r, next_type_id, else_clause); return; } } break; } default: {} } // Traverse all child expressions looking for calls. ast_t* child = ast_child(ast); while(child != NULL) { reachable_expr(s, r, next_type_id, child); child = ast_sibling(child); } }
static void reachable_expr(reach_t* r, ast_t* ast, pass_opt_t* opt) { // If this is a method call, mark the method as reachable. switch(ast_id(ast)) { case TK_TRUE: case TK_FALSE: case TK_INT: case TK_FLOAT: case TK_STRING: { ast_t* type = ast_type(ast); if(type != NULL) reachable_method(r, type, stringtab("create"), NULL, opt); break; } case TK_LET: case TK_VAR: case TK_TUPLE: { ast_t* type = ast_type(ast); add_type(r, type, opt); break; } case TK_CASE: { AST_GET_CHILDREN(ast, pattern, guard, body); reachable_pattern(r, pattern, opt); reachable_expr(r, guard, opt); reachable_expr(r, body, opt); break; } case TK_CALL: reachable_call(r, ast, opt); break; case TK_FFICALL: reachable_ffi(r, ast, opt); break; case TK_ADDRESS: reachable_addressof(r, ast, opt); break; case TK_IF: { AST_GET_CHILDREN(ast, cond, then_clause, else_clause); assert(ast_id(cond) == TK_SEQ); cond = ast_child(cond); ast_t* type = ast_type(ast); if(is_result_needed(ast) && !is_control_type(type)) add_type(r, type, opt); if(ast_sibling(cond) == NULL) { if(ast_id(cond) == TK_TRUE) { reachable_expr(r, then_clause, opt); return; } else if(ast_id(cond) == TK_FALSE) { reachable_expr(r, else_clause, opt); return; } } break; } case TK_MATCH: case TK_WHILE: case TK_REPEAT: case TK_TRY: { ast_t* type = ast_type(ast); if(is_result_needed(ast) && !is_control_type(type)) add_type(r, type, opt); break; } default: {} } // Traverse all child expressions looking for calls. ast_t* child = ast_child(ast); while(child != NULL) { reachable_expr(r, child, opt); child = ast_sibling(child); } }