Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
matchtype_t is_matchtype(ast_t* operand, ast_t* pattern, pass_opt_t* opt)
{
  return is_x_match_x(operand, pattern, opt);
}
Exemple #13
0
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);
}
Exemple #14
0
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;
}