static ast_result_t flatten_isect(pass_opt_t* opt, ast_t* ast) { // Flatten intersections without testing subtyping. This is to preserve any // type guarantees that an element in the intersection might make. // If there are more than 2 children, this has already been flattened. if(ast_childcount(ast) > 2) return AST_OK; AST_EXTRACT_CHILDREN(ast, left, right); if((opt->check.frame->constraint == NULL) && (opt->check.frame->iftype_constraint == NULL) && (opt->check.frame->provides == NULL) && !is_compat_type(left, right)) { ast_add(ast, right); ast_add(ast, left); ast_error(opt->check.errors, ast, "intersection types cannot include reference capabilities that are not " "locally compatible"); return AST_ERROR; } flatten_typeexpr_element(ast, left, TK_ISECTTYPE); flatten_typeexpr_element(ast, right, TK_ISECTTYPE); return AST_OK; }
static bool is_arrow_compat_arrow(ast_t* a, ast_t* b) { // S = this | A {#read, #send, #share, #any} // K = N k | A {iso, trn, ref, val, box, tag} | K->K | (empty) // L = S | K // T = N k | A k | L->T // // forall K' in S . K->S->T1 {S |-> K'} ~ T2 {S |-> K'} // --- // K->S->T1 ~ T2 ast_t* r_a; ast_t* r_b; if(viewpoint_reifypair(a, b, &r_a, &r_b)) { bool ok = is_compat_type(r_a, r_b); ast_free_unattached(r_a); ast_free_unattached(r_b); return ok; } // No elements need reification. // // lowerbound(T1->T2) ~ lowerbound(T3->T4) // --- // T1->T2 ~ T3->T4 r_a = viewpoint_lower(a); if(r_a == NULL) return false; r_b = viewpoint_lower(b); if(r_b == NULL) { ast_free_unattached(r_a); return false; } bool ok = is_compat_type(r_a, r_b); ast_free_unattached(r_a); ast_free_unattached(r_b); return ok; }
static bool is_arrow_compat_nominal(ast_t* a, ast_t* b) { // lowerbound(T1->T2) ~ N k // --- // T1->T2 ~ N k ast_t* a_lower = viewpoint_lower(a); if(a == NULL) return false; bool ok = is_compat_type(a_lower, b); ast_free_unattached(a_lower); return ok; }
static bool is_union_compat_x(ast_t* a, ast_t* b) { // T1 ~ T3 or T2 ~ T3 // --- // (T1 | T2) ~ T3 for(ast_t* child = ast_child(a); child != NULL; child = ast_sibling(child)) { if(is_compat_type(child, b)) return true; } return false; }
static bool is_tuple_compat_tuple(ast_t* a, ast_t* b) { // T1 ~ T3 // T2 ~ T4 // --- // (T1, T2) ~ (T3, T4) ast_t* a_child = ast_child(a); ast_t* b_child = ast_child(b); while((a_child != NULL) && (b_child != NULL)) { if(!is_compat_type(a_child, b_child)) return false; a_child = ast_sibling(a_child); b_child = ast_sibling(b_child); } return (a_child == NULL) && (b_child == NULL); }
static bool is_arrow_compat_typeparam(ast_t* a, ast_t* b) { // forall k' in k . T1->T2 {A k |-> A k'} ~ A k' // --- // T1->T2 ~ A k ast_t* r_a = viewpoint_reifytypeparam(a, b); ast_t* r_b = viewpoint_reifytypeparam(b, b); if(r_a != NULL) { bool ok = is_compat_type(r_a, r_b); ast_free_unattached(r_a); ast_free_unattached(r_b); return ok; } // lowerbound(T1->T2) ~ A k // --- // T1->T2 ~ A k return is_arrow_compat_nominal(a, b); }