static matchtype_t is_isect_match_x(ast_t* operand, ast_t* pattern, errorframe_t* errorf, bool report_reject, pass_opt_t* opt) { matchtype_t ok = MATCHTYPE_ACCEPT; for(ast_t* child = ast_child(operand); child != NULL; child = ast_sibling(child)) { switch(is_x_match_x(child, pattern, NULL, false, opt)) { case MATCHTYPE_ACCEPT: break; case MATCHTYPE_REJECT: // If any type in the operand isect rejects a match, then the entire // operand isect rejects match. ok = MATCHTYPE_REJECT; break; case MATCHTYPE_DENY: // If any type in the operand isect denies a match, then the entire // operand isect is denied a match. ok = MATCHTYPE_DENY; break; } if(ok == MATCHTYPE_DENY) break; } if((ok != MATCHTYPE_ACCEPT) && (errorf != NULL)) { if(ok == MATCHTYPE_DENY) report_reject = false; for(ast_t* child = ast_child(operand); child != NULL; child = ast_sibling(child)) { is_x_match_x(child, pattern, errorf, report_reject, opt); } if(ok == MATCHTYPE_DENY) { ast_error_frame(errorf, pattern, "matching %s with %s could violate capabilities", ast_print_type(operand), ast_print_type(pattern)); } else if(report_reject) { ast_error_frame(errorf, pattern, "not every element of %s can match %s", ast_print_type(operand), ast_print_type(pattern)); } } return ok; }
static matchtype_t is_x_match_union(ast_t* operand, ast_t* pattern, pass_opt_t* opt) { matchtype_t ok = MATCHTYPE_REJECT; for(ast_t* child = ast_child(pattern); child != NULL; child = ast_sibling(child)) { switch(is_x_match_x(operand, child, opt)) { case MATCHTYPE_ACCEPT: // If any type in the pattern union accepts a match, the entire pattern // union accepts a match. ok = MATCHTYPE_ACCEPT; break; case MATCHTYPE_REJECT: break; case MATCHTYPE_DENY: // If any type in the pattern union denies a match, the entire pattern // union denies a match. return MATCHTYPE_DENY; } } return ok; }
static matchtype_t is_isect_match_x(ast_t* operand, ast_t* pattern, pass_opt_t* opt) { matchtype_t ok = MATCHTYPE_ACCEPT; for(ast_t* child = ast_child(operand); child != NULL; child = ast_sibling(child)) { switch(is_x_match_x(child, pattern, opt)) { case MATCHTYPE_ACCEPT: break; case MATCHTYPE_REJECT: // If any type in the operand isect rejects a match, then the entire // operand isect rejects match. ok = MATCHTYPE_REJECT; break; case MATCHTYPE_DENY: // If any type in the operand isect denies a match, then the entire // operand isect is denied a match. return MATCHTYPE_DENY; } } return ok; }
static matchtype_t is_arrow_match_x(ast_t* operand, ast_t* pattern, pass_opt_t* opt) { // upperbound(this->T1) match T2 // --- // (this->T1) match T2 // lowerbound(T1->T2) match T3 // --- // (T1->T2) match T3 ast_t* operand_view; AST_GET_CHILDREN(operand, left, right); if(ast_id(left) == TK_THISTYPE) operand_view = viewpoint_upper(operand); else operand_view = viewpoint_lower(operand); if(operand_view == NULL) return MATCHTYPE_DENY; matchtype_t ok = is_x_match_x(operand_view, pattern, opt); ast_free_unattached(operand_view); return ok; }
static matchtype_t is_tuple_match_tuple(ast_t* operand, ast_t* pattern, pass_opt_t* opt) { // Must be a pairwise match. if(ast_childcount(operand) != ast_childcount(pattern)) return MATCHTYPE_REJECT; ast_t* operand_child = ast_child(operand); ast_t* pattern_child = ast_child(pattern); matchtype_t ok = MATCHTYPE_ACCEPT; while(operand_child != NULL) { switch(is_x_match_x(operand_child, pattern_child, opt)) { case MATCHTYPE_ACCEPT: break; case MATCHTYPE_REJECT: ok = MATCHTYPE_REJECT; break; case MATCHTYPE_DENY: return MATCHTYPE_DENY; } operand_child = ast_sibling(operand_child); pattern_child = ast_sibling(pattern_child); } return ok; }
static matchtype_t is_x_match_arrow(ast_t* operand, ast_t* pattern, errorframe_t* errorf, bool report_reject, pass_opt_t* opt) { // T1 match upperbound(T2->T3) // --- // T1 match T2->T3 ast_t* pattern_upper = viewpoint_upper(pattern); if(pattern_upper == NULL) { if((errorf != NULL) && report_reject) { ast_error_frame(errorf, pattern, "%s cannot match %s: the pattern type has no upper bounds", ast_print_type(operand), ast_print_type(pattern)); } return MATCHTYPE_REJECT; } matchtype_t ok = is_x_match_x(operand, pattern_upper, errorf, report_reject, opt); ast_free_unattached(pattern_upper); return ok; }
static matchtype_t is_x_match_typeparam(ast_t* operand, ast_t* pattern, pass_opt_t* opt) { ast_t* pattern_upper = typeparam_upper(pattern); // An unconstrained typeparam can match anything. if(pattern_upper == NULL) return MATCHTYPE_ACCEPT; // Otherwise, match the constraint. matchtype_t ok = is_x_match_x(operand, pattern_upper, opt); ast_free_unattached(pattern_upper); return ok; }
static matchtype_t is_typeparam_match_x(ast_t* operand, ast_t* pattern, pass_opt_t* opt) { ast_t* operand_upper = typeparam_upper(operand); // An unconstrained typeparam could match anything. if(operand_upper == NULL) return MATCHTYPE_ACCEPT; // Check if the constraint can match the pattern. matchtype_t ok = is_x_match_x(operand_upper, pattern, opt); ast_free_unattached(operand_upper); return ok; }
static matchtype_t is_x_match_arrow(ast_t* operand, ast_t* pattern, pass_opt_t* opt) { // T1 match upperbound(T2->T3) // --- // T1 match T2->T3 ast_t* pattern_upper = viewpoint_upper(pattern); if(pattern_upper == NULL) return MATCHTYPE_REJECT; matchtype_t ok = is_x_match_x(operand, pattern_upper, opt); ast_free_unattached(pattern_upper); return ok; }
static matchtype_t is_nominal_match_tuple(ast_t* operand, ast_t* pattern, errorframe_t* errorf, bool report_reject, pass_opt_t* opt) { if(!is_top_type(operand, true)) { if((errorf != NULL) && report_reject) { ast_t* operand_def = (ast_t*)ast_data(operand); ast_error_frame(errorf, pattern, "%s cannot match %s: the pattern type is a tuple", ast_print_type(operand), ast_print_type(pattern)); ast_error_frame(errorf, operand_def, "this might be possible if the " "match type were an empty interface, such as the Any type"); } return MATCHTYPE_REJECT; } ast_t* child = ast_child(pattern); while(child != NULL) { matchtype_t r = is_x_match_x(operand, child, errorf, false, opt); pony_assert(r != MATCHTYPE_REJECT); if(r == MATCHTYPE_DENY) { if(errorf != NULL) { ast_error_frame(errorf, pattern, "matching %s with %s could violate capabilities", ast_print_type(operand), ast_print_type(pattern)); } return r; } child = ast_sibling(child); } return MATCHTYPE_ACCEPT; }
static matchtype_t is_arrow_match_x(ast_t* operand, ast_t* pattern, errorframe_t* errorf, bool report_reject, pass_opt_t* opt) { // upperbound(this->T1) match T2 // --- // (this->T1) match T2 // lowerbound(T1->T2) match T3 // --- // (T1->T2) match T3 ast_t* operand_view; AST_GET_CHILDREN(operand, left, right); if(ast_id(left) == TK_THISTYPE) operand_view = viewpoint_upper(operand); else operand_view = viewpoint_lower(operand); if(operand_view == NULL) { if(errorf != NULL) { // this->X always has an upper bound. pony_assert(ast_id(left) != TK_THISTYPE); ast_error_frame(errorf, pattern, "matching %s with %s could violate capabilities: " "the match type has no lower bounds", ast_print_type(operand), ast_print_type(pattern)); } return MATCHTYPE_DENY; } matchtype_t ok = is_x_match_x(operand_view, pattern, errorf, report_reject, opt); ast_free_unattached(operand_view); return ok; }
matchtype_t is_matchtype(ast_t* operand, ast_t* pattern, pass_opt_t* opt) { return is_x_match_x(operand, pattern, opt); }
matchtype_t is_matchtype(ast_t* operand, ast_t* pattern, errorframe_t* errorf, pass_opt_t* opt) { return is_x_match_x(operand, pattern, errorf, true, opt); }
static matchtype_t is_tuple_match_tuple(ast_t* operand, ast_t* pattern, errorframe_t* errorf, bool report_reject, pass_opt_t* opt) { // Must be a pairwise match. if(ast_childcount(operand) != ast_childcount(pattern)) { if((errorf != NULL) && report_reject) { ast_error_frame(errorf, pattern, "%s cannot match %s: they have a different number of elements", ast_print_type(operand), ast_print_type(pattern)); } return MATCHTYPE_REJECT; } ast_t* operand_child = ast_child(operand); ast_t* pattern_child = ast_child(pattern); matchtype_t ok = MATCHTYPE_ACCEPT; while(operand_child != NULL) { switch(is_x_match_x(operand_child, pattern_child, NULL, false, opt)) { case MATCHTYPE_ACCEPT: break; case MATCHTYPE_REJECT: ok = MATCHTYPE_REJECT; break; case MATCHTYPE_DENY: ok = MATCHTYPE_DENY; break; } if(ok != MATCHTYPE_ACCEPT) break; operand_child = ast_sibling(operand_child); pattern_child = ast_sibling(pattern_child); } if((ok != MATCHTYPE_ACCEPT) && (errorf != NULL)) { if(ok == MATCHTYPE_DENY) report_reject = false; operand_child = ast_child(operand); pattern_child = ast_child(pattern); while(operand_child != NULL) { is_x_match_x(operand_child, pattern_child, errorf, report_reject, opt); operand_child = ast_sibling(operand_child); pattern_child = ast_sibling(pattern_child); } if(ok == MATCHTYPE_DENY) { ast_error_frame(errorf, pattern, "matching %s with %s could violate capabilities", ast_print_type(operand), ast_print_type(pattern)); } else if(report_reject) { ast_error_frame(errorf, pattern, "%s cannot pairwise match %s", ast_print_type(operand), ast_print_type(pattern)); } } return ok; }