static bool auto_recover_call(ast_t* ast, ast_t* receiver_type, ast_t* positional, ast_t* result) { // We can recover the receiver (ie not alias the receiver type) if all // arguments are safe and the result is either safe or unused. if(is_result_needed(ast) && !safe_to_autorecover(receiver_type, result)) return false; ast_t* arg = ast_child(positional); while(arg != NULL) { if(ast_id(arg) != TK_NONE) { ast_t* arg_type = ast_type(arg); if(is_typecheck_error(arg_type)) return false; ast_t* a_type = alias(arg_type); bool ok = safe_to_autorecover(receiver_type, a_type); ast_free_unattached(a_type); if(!ok) return false; } arg = ast_sibling(arg); } return true; }
bool safe_to_autorecover(ast_t* receiver_type, ast_t* type) { switch(ast_id(receiver_type)) { case TK_ISECTTYPE: { ast_t* child = ast_child(receiver_type); while(child != NULL) { if(safe_to_autorecover(child, type)) return true; child = ast_sibling(child); } return false; } case TK_UNIONTYPE: { ast_t* child = ast_child(receiver_type); while(child != NULL) { if(!safe_to_autorecover(child, type)) return false; child = ast_sibling(child); } return true; } case TK_NOMINAL: case TK_TYPEPARAMREF: return safe_field_write(cap_single(receiver_type), type); case TK_ARROW: { ast_t* upper = viewpoint_upper(receiver_type); bool ok = safe_to_autorecover(upper, type); if(upper != receiver_type) ast_free_unattached(upper); return ok; } default: {} } assert(0); return false; }
static bool auto_recover_call(ast_t* ast, ast_t* receiver_type, ast_t* positional, ast_t* result) { switch(ast_id(ast)) { case TK_FUNREF: case TK_FUNAPP: case TK_FUNCHAIN: break; default: pony_assert(0); break; } // We can recover the receiver (ie not alias the receiver type) if all // arguments are safe and the result is either safe or unused. // The result of a chained method is always unused. ast_t* call = ast_parent(ast); if(is_result_needed(call) && !safe_to_autorecover(receiver_type, result)) return false; ast_t* arg = ast_child(positional); while(arg != NULL) { if(ast_id(arg) != TK_NONE) { ast_t* arg_type = ast_type(arg); if(is_typecheck_error(arg_type)) return false; ast_t* a_type = alias(arg_type); bool ok = safe_to_autorecover(receiver_type, a_type); ast_free_unattached(a_type); if(!ok) return false; } arg = ast_sibling(arg); } return true; }