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); } }