Esempio n. 1
0
// The subtype is a pointer, the supertype could be anything.
static bool is_pointer_subtype(ast_t* sub, ast_t* super)
{
  switch(ast_id(super))
  {
    case TK_NOMINAL:
    {
      // Must be a Pointer, and the type argument must be the same.
      return is_pointer(super) &&
        is_eq_typeargs(sub, super) &&
        is_sub_cap_and_ephemeral(sub, super);
    }

    case TK_TYPEPARAMREF:
    {
      // We must be a subtype of the constraint.
      ast_t* def = (ast_t*)ast_data(super);
      ast_t* constraint = ast_childidx(def, 1);

      return is_pointer_subtype(sub, constraint);
    }

    case TK_ARROW:
    {
      // We must be a subtype of the lower bounds.
      ast_t* lower = viewpoint_lower(super);
      bool ok = is_pointer_subtype(sub, lower);
      ast_free_unattached(lower);
      return ok;
    }

    default: {}
  }

  return false;
}
Esempio n. 2
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;
}
Esempio n. 3
0
// The subtype is an arrow, the supertype could be anything.
static bool is_arrow_subtype(ast_t* sub, ast_t* super)
{
  switch(ast_id(super))
  {
    case TK_UNIONTYPE:
      // A->B <: (C | D)
      if(is_subtype_union(sub, super))
        return true;
      break;

    case TK_ISECTTYPE:
      // A->B <: (C & D)
      if(is_subtype_isect(sub, super))
        return true;
      break;

    case TK_TYPEPARAMREF:
    {
      // A->B <: C
      ast_t* right = ast_child(sub);

      switch(ast_id(right))
      {
        case TK_THISTYPE:
        case TK_BOXTYPE:
          break;

        default:
          if(is_eqtype(right, super))
          {
            // C->B <: C
            // If we are adapted by the supertype, we are a subtype if our
            // lower bounds is a subtype of super.
            ast_t* lower = viewpoint_lower(sub);
            bool ok = is_subtype(lower, super);
            ast_free_unattached(lower);
            return ok;
          }
          break;
      }
      break;
    }

    case TK_ARROW:
      // A->B <: C->D
      if(is_arrow_sub_arrow(sub, super))
        return true;
      break;

    default: {}
  }

  // Otherwise, we are a subtype if our upper bounds is a subtype of super.
  ast_t* upper = viewpoint_upper(sub);
  bool ok = is_subtype(upper, super);
  ast_free_unattached(upper);
  return ok;
}
Esempio n. 4
0
ast_t* viewpoint_lower(ast_t* type)
{
  switch(ast_id(type))
  {
    case TK_TUPLETYPE:
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    {
      // Adapt all elements.
      ast_t* r_type = ast_from(type, ast_id(type));
      ast_t* child = ast_child(type);

      while(child != NULL)
      {
        ast_append(r_type, viewpoint_lower(child));
        child = ast_sibling(child);
      }

      return r_type;
    }

    case TK_NOMINAL:
      return viewpoint_lower_for_type(type, 3);

    case TK_TYPEPARAMREF:
      return viewpoint_lower_for_type(type, 1);

    case TK_ARROW:
    {
      AST_GET_CHILDREN(type, left, right);

      // If left is a boxtype, right's lower bounds is its actual type.
      if(ast_id(left) == TK_BOXTYPE)
        return viewpoint_cap(TK_BOX, TK_NONE, right);

      // If left is a thistype or a typeparamref type, right's lower bounds is
      // calculated on its own.
      return viewpoint_lower(right);
    }

    default: {}
  }

  return NULL;
}
Esempio n. 5
0
// The subtype is a nominal, typeparamref or tuple, the super type is an arrow.
static bool is_subtype_arrow(ast_t* sub, ast_t* super)
{
  // Must be a subtype of the lower bounds.
  ast_t* lower = viewpoint_lower(super);
  bool ok = is_subtype(sub, lower);
  ast_free_unattached(lower);

  return ok;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
static matchtype_t is_arrow_match_nominal(ast_t* operand, ast_t* pattern)
{
  // lowerbound(T1->T2) match T3
  // ---
  // (T1->T2) match T3
  ast_t* operand_lower = viewpoint_lower(operand);
  matchtype_t ok = is_matchtype(operand_lower, pattern);
  ast_free_unattached(operand_lower);
  return ok;
}
Esempio n. 8
0
static matchtype_t could_subtype_with_arrow(ast_t* sub, ast_t* super)
{
  // Check the lower bounds of super.
  ast_t* lower = viewpoint_lower(super);
  matchtype_t ok = could_subtype(sub, lower);

  if(lower != sub)
    ast_free_unattached(lower);

  return ok;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
ast_t* viewpoint_cap(token_id cap, token_id eph, ast_t* type)
{
  if(cap == TK_TAG)
    return NULL;

  switch(ast_id(type))
  {
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    case TK_TUPLETYPE:
    {
      // Adapt all elements.
      ast_t* r_type = ast_from(type, ast_id(type));
      ast_t* child = ast_child(type);

      while(child != NULL)
      {
        ast_append(r_type, viewpoint_cap(cap, eph, child));
        child = ast_sibling(child);
      }

      return r_type;
    }

    case TK_NOMINAL:
      return viewpoint_for_type(cap, eph, type, 3);

    case TK_TYPEPARAMREF:
      return viewpoint_for_type(cap, eph, type, 1);

    case TK_ARROW:
    {
      // Adapt the lower bounds.
      ast_t* lower = viewpoint_lower(type);
      ast_t* r_type = viewpoint_cap(cap, eph, lower);

      if(r_type != lower)
        ast_free_unattached(lower);

      return r_type;
    }

    default: {}
  }

  assert(0);
  return NULL;
}
Esempio n. 11
0
static matchtype_t could_subtype_arrow(ast_t* sub, ast_t* super)
{
  if(ast_id(super) == TK_ARROW)
  {
    // If we have the same viewpoint, check the right side.
    AST_GET_CHILDREN(sub, sub_left, sub_right);
    AST_GET_CHILDREN(super, super_left, super_right);
    bool check = false;

    switch(ast_id(sub_left))
    {
      case TK_THISTYPE:
        switch(ast_id(super_left))
        {
          case TK_THISTYPE:
          case TK_BOXTYPE:
            check = true;
            break;

          default: {}
        }
        break;

      case TK_BOXTYPE:
        check = ast_id(super_left) == TK_BOXTYPE;
        break;

      default:
        check = is_eqtype(sub_left, super_left);
        break;
    }

    if(check)
      return could_subtype(sub_right, super_right);
  }

  // Check the lower bounds.
  ast_t* lower = viewpoint_lower(sub);
  matchtype_t ok = could_subtype(super, lower);

  if(lower != sub)
    ast_free_unattached(lower);

  return ok;
}
Esempio n. 12
0
// The subtype is a nominal, the super type is a typeparam.
static bool is_nominal_sub_typeparam(ast_t* sub, ast_t* super)
{
  // Must be a subtype of the lower bounds of the constraint.
  ast_t* def = (ast_t*)ast_data(super);
  ast_t* constraint = ast_childidx(def, 1);

  if(ast_id(constraint) == TK_NOMINAL)
  {
    ast_t* constraint_def = (ast_t*)ast_data(constraint);

    switch(ast_id(constraint_def))
    {
      case TK_PRIMITIVE:
      case TK_CLASS:
      case TK_ACTOR:
      {
        // Constraint must be modified with super ephemerality.
        AST_GET_CHILDREN(super, name, cap, eph);
        ast_t* r_constraint = set_cap_and_ephemeral(constraint, TK_NONE,
          ast_id(eph));

        // Must be a subtype of the constraint.
        bool ok = is_subtype(sub, constraint);
        ast_free_unattached(r_constraint);

        if(!ok)
          return false;

        // Capability must be a subtype of the lower bounds of the typeparam.
        ast_t* lower = viewpoint_lower(super);
        ok = is_sub_cap_and_ephemeral(sub, lower);
        ast_free_unattached(lower);
        return ok;
      }

      default: {}
    }
  }

  return false;
}
Esempio n. 13
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;
}
Esempio n. 14
0
static bool is_typeparam_sub_arrow(ast_t* sub, ast_t* super,
  errorframe_t* errors)
{
  // forall k' in k . A k' <: lowerbound(T1->T2 {A k |-> A k'})
  // ---
  // A k <: T1->T2
  ast_t* r_sub = viewpoint_reifytypeparam(sub, sub);
  ast_t* r_super = viewpoint_reifytypeparam(super, sub);

  if(r_sub != NULL)
  {
    bool ok = is_subtype(r_sub, r_super, errors);
    ast_free_unattached(r_sub);
    ast_free_unattached(r_super);
    return ok;
  }

  // If there is only a single instantiation, calculate the lower bounds.
  //
  // A k <: lowerbound(T1->T2)
  // ---
  // A k <: T1->T2
  ast_t* super_lower = viewpoint_lower(super);

  if(super_lower == NULL)
  {
    if(errors != NULL)
    {
      ast_error_frame(errors, sub,
        "%s is not a subtype of %s: the supertype has no lower bounds",
        ast_print_type(sub), ast_print_type(super));
    }

    return false;
  }

  bool ok = is_subtype(sub, super_lower, errors);
  ast_free_unattached(super_lower);
  return ok;
}
Esempio n. 15
0
static bool is_nominal_sub_arrow(ast_t* sub, ast_t* super,
  errorframe_t* errors)
{
  // N k <: lowerbound(T1->T2)
  // ---
  // N k <: T1->T2
  ast_t* super_lower = viewpoint_lower(super);

  if(super_lower == NULL)
  {
    if(errors != NULL)
    {
      ast_error_frame(errors, sub,
        "%s is not a subtype of %s: the supertype has no lower bounds",
        ast_print_type(sub), ast_print_type(super));
    }

    return false;
  }

  bool ok = is_subtype(sub, super_lower, errors);
  ast_free_unattached(super_lower);
  return ok;
}
Esempio n. 16
0
ast_t* viewpoint_lower(ast_t* type)
{
  // T = N | A
  // s = {k}
  // upper(s p'->T k p) = union[k' in s](T (k'->k) eph(s, p', p))
  // eph(s, p', p) = { unalias(p) if p' = ^, exists k in s . k in {iso, trn}
  //                 { p          otherwise
  assert(ast_id(type) == TK_ARROW);
  AST_GET_CHILDREN(type, left, right);
  ast_t* r_right = right;

  switch(ast_id(right))
  {
    case TK_NOMINAL:
    case TK_TYPEPARAMREF:
      break;

    case TK_ARROW:
      // Arrow types are right associative.
      r_right = viewpoint_lower(right);

      if(r_right == NULL)
        return NULL;
      break;

    default:
      assert(0);
      return NULL;
  }

  token_id l_cap = TK_NONE;
  token_id l_eph = TK_NONE;

  switch(ast_id(left))
  {
    case TK_ISO:
    case TK_TRN:
    case TK_REF:
    case TK_VAL:
    case TK_BOX:
    case TK_TAG:
      l_cap = ast_id(left);
      break;

    case TK_THISTYPE:
      l_cap = TK_CAP_READ;
      break;

    case TK_NOMINAL:
    case TK_TYPEPARAMREF:
    {
      ast_t* left_cap = cap_fetch(left);
      ast_t* left_eph = ast_sibling(left_cap);

      l_cap = ast_id(left_cap);
      l_eph = ast_id(left_eph);
      break;
    }

    default:
      assert(0);
      return NULL;
  }

  ast_t* right_cap = cap_fetch(r_right);
  ast_t* right_eph = ast_sibling(right_cap);

  token_id r_cap = ast_id(right_cap);
  token_id r_eph = ast_id(right_eph);

  // No result: left side could be a tag.
  if(!cap_view_lower(l_cap, l_eph, &r_cap, &r_eph))
    return NULL;

  ast_t* rr_right = set_cap_and_ephemeral(r_right, r_cap, r_eph);

  if(r_right != right)
    ast_free_unattached(r_right);

  return rr_right;
}
Esempio n. 17
0
static bool is_arrow_sub_arrow(ast_t* sub, ast_t* super, errorframe_t* errors)
{
  // 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_sub;
  ast_t* r_super;

  if(viewpoint_reifypair(sub, super, &r_sub, &r_super))
  {
    bool ok = is_subtype(r_sub, r_super, errors);
    ast_free_unattached(r_sub);
    ast_free_unattached(r_super);
    return ok;
  }

  // No elements need reification.
  //
  // upperbound(T1->T2) <: lowerbound(T3->T4)
  // ---
  // T1->T2 <: T3->T4
  ast_t* sub_upper = viewpoint_upper(sub);
  ast_t* super_lower = viewpoint_lower(super);
  bool ok = true;

  if(sub_upper == NULL)
  {
    if(errors != NULL)
    {
      ast_error_frame(errors, sub,
        "%s is not a subtype of %s: the subtype has no upper bounds",
        ast_print_type(sub), ast_print_type(super));
    }

    ok = false;
  }

  if(super_lower == NULL)
  {
    if(errors != NULL)
    {
      ast_error_frame(errors, sub,
        "%s is not a subtype of %s: the supertype has no lower bounds",
        ast_print_type(sub), ast_print_type(super));
    }

    ok = false;
  }

  if(ok)
    ok = is_subtype(sub_upper, super_lower, errors);

  ast_free_unattached(sub_upper);
  ast_free_unattached(super_lower);
  return ok;
}