Exemplo 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;
}
Exemplo n.º 2
0
// Both sub and super are nominal types.
static bool is_nominal_sub_nominal(ast_t* sub, ast_t* super)
{
  if(!is_sub_cap_and_ephemeral(sub, super))
    return false;

  ast_t* sub_def = (ast_t*)ast_data(sub);
  ast_t* super_def = (ast_t*)ast_data(super);

  // If we are the same nominal type, our typeargs must be the same.
  if(sub_def == super_def)
    return is_eq_typeargs(sub, super);

  switch(ast_id(super_def))
  {
    case TK_PRIMITIVE:
    case TK_CLASS:
    case TK_ACTOR:
      // If we aren't the same type, we can't be a subtype of a concrete type.
      return false;

    case TK_INTERFACE:
      // Check for an explicit provide or a structural subtype.
      return is_nominal_sub_trait(sub, super) ||
        is_nominal_sub_interface(sub, super);

    case TK_TRAIT:
      // Check for a nominal subtype.
      return is_nominal_sub_trait(sub, super);

    default: {}
  }

  return false;
}
Exemplo n.º 3
0
// The subtype is a typeparam, the supertype is a typeparam.
static bool is_typeparam_sub_typeparam(ast_t* sub, ast_t* super)
{
  // If the supertype is also a typeparam, we must be the same typeparam by
  // identity and be a subtype by cap and ephemeral.
  ast_t* sub_def = (ast_t*)ast_data(sub);
  ast_t* super_def = (ast_t*)ast_data(super);

  if(sub_def != super_def)
    return false;

  return is_sub_cap_and_ephemeral(sub, super);
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
static matchtype_t could_subtype_or_deny(ast_t* sub, ast_t* super)
{
  // At this point, sub must be a subtype of super.
  if(is_subtype(sub, super))
    return MATCHTYPE_ACCEPT;

  // If sub would be a subtype of super if it had super's capability and
  // ephemerality, we deny other matches.
  token_id cap, eph;

  switch(ast_id(super))
  {
    case TK_NOMINAL:
    {
      AST_GET_CHILDREN(super, sup_pkg, sup_id, sup_typeargs, sup_cap, sup_eph);
      cap = ast_id(sup_cap);
      eph = ast_id(sup_eph);
      break;
    }

    case TK_TYPEPARAMREF:
    {
      AST_GET_CHILDREN(super, sup_id, sup_cap, sup_eph);
      cap = ast_id(sup_cap);
      eph = ast_id(sup_eph);
      break;
    }

    default:
      assert(0);
      return MATCHTYPE_DENY;
  }

  ast_t* sub_def = (ast_t*)ast_data(sub);
  ast_t* super_def = (ast_t*)ast_data(super);
  ast_t* r_type = set_cap_and_ephemeral(sub, cap, eph);

  matchtype_t ok = MATCHTYPE_REJECT;

  if(is_subtype(r_type, super))
  {
    // Sub would be a subtype of super if their capabilities were the same.
    // Deny any match, since this would break capabilities.
    ok = MATCHTYPE_DENY;
  } else if(sub_def != super_def) {
    // Sub and super are unrelated types and sub is not a subtype of super.
    ok = MATCHTYPE_REJECT;
  } else if((sub_def == super_def) && is_sub_cap_and_ephemeral(sub, super)) {
    // Sub and super are the same base type, but have different type args.
    // Only accept if sub's type args are typeparamrefs and they could be a
    // subtype of super's type args.
    assert(ast_id(sub) == TK_NOMINAL);
    assert(ast_id(super) == TK_NOMINAL);

    AST_GET_CHILDREN(sub, sub_pkg, sub_id, sub_typeargs);
    AST_GET_CHILDREN(super, sup_pkg, sup_id, sup_typeargs);

    ast_t* sub_typearg = ast_child(sub_typeargs);
    ast_t* sup_typearg = ast_child(sup_typeargs);
    ok = MATCHTYPE_ACCEPT;

    while(sub_typearg != NULL)
    {
      if(!could_subtype_typearg(sub_typearg, sup_typearg))
      {
        ok = MATCHTYPE_REJECT;
        break;
      }

      sub_typearg = ast_sibling(sub_typearg);
      sup_typearg = ast_sibling(sup_typearg);
    }
  }

  ast_free_unattached(r_type);
  return ok;
}