Exemplo n.º 1
0
static bool is_nominal_sub_interface(ast_t* sub, ast_t* super)
{
  ast_t* sub_def = (ast_t*)ast_data(sub);
  ast_t* super_def = (ast_t*)ast_data(super);

  ast_t* sub_typeargs = ast_childidx(sub, 2);
  ast_t* super_typeargs = ast_childidx(super, 2);

  ast_t* sub_typeparams = ast_childidx(sub_def, 1);
  ast_t* super_typeparams = ast_childidx(super_def, 1);

  ast_t* super_members = ast_childidx(super_def, 4);
  ast_t* super_member = ast_child(super_members);

  while(super_member != NULL)
  {
    ast_t* super_member_id = ast_childidx(super_member, 1);
    ast_t* sub_member = ast_get(sub_def, ast_name(super_member_id), NULL);

    if(sub_member == NULL)
      return false;

    ast_t* r_sub_member = reify(sub_typeargs, sub_member, sub_typeparams,
      sub_typeargs);

    if(r_sub_member== NULL)
      return false;

    ast_t* r_super_member = reify(super_typeargs, super_member,
      super_typeparams, super_typeargs);

    if(r_super_member == NULL)
    {
      ast_free_unattached(r_sub_member);
      return false;
    }

    bool ok = is_fun_sub_fun(r_sub_member, r_super_member, sub, super);
    ast_free_unattached(r_sub_member);
    ast_free_unattached(r_super_member);

    if(!ok)
      return false;

    super_member = ast_sibling(super_member);
  }

  return true;
}
Exemplo n.º 2
0
bool is_subtype(ast_t* sub, ast_t* super)
{
  assert(sub != NULL);
  assert(super != NULL);

  if(ast_id(super) == TK_DONTCARE)
    return true;

  switch(ast_id(sub))
  {
    case TK_UNIONTYPE:
      return is_union_subtype(sub, super);

    case TK_ISECTTYPE:
      return is_isect_subtype(sub, super);

    case TK_TUPLETYPE:
      return is_tuple_subtype(sub, super);

    case TK_NOMINAL:
      return is_nominal_subtype(sub, super);

    case TK_TYPEPARAMREF:
      return is_typeparam_subtype(sub, super);

    case TK_ARROW:
      return is_arrow_subtype(sub, super);

    case TK_FUNTYPE:
    case TK_INFERTYPE:
    case TK_ERRORTYPE:
      return false;

    case TK_NEW:
    case TK_BE:
    case TK_FUN:
      return is_fun_sub_fun(sub, super, NULL, NULL);

    default: {}
  }

  assert(0);
  return false;
}
Exemplo n.º 3
0
static bool is_nominal_sub_interface(ast_t* sub, ast_t* super,
  errorframe_t* errors)
{
  // implements(N, I)
  // k <: k'
  // ---
  // N k <: I k
  ast_t* sub_def = (ast_t*)ast_data(sub);
  ast_t* super_def = (ast_t*)ast_data(super);

  // Add an assumption: sub <: super
  if(push_assume(sub, super))
    return true;

  bool ret = true;

  // A struct has no descriptor, so can't be a subtype of an interface.
  if(ast_id(sub_def) == TK_STRUCT)
  {
    ret = false;

    if(errors != NULL)
    {
      ast_error_frame(errors, sub,
        "%s is not a subtype of %s: a struct can't be a subtype of an "
        "interface",
        ast_print_type(sub), ast_print_type(super));
    }
  }

  if(!is_sub_cap_and_eph(sub, super, errors))
    ret = false;

  ast_t* sub_typeargs = ast_childidx(sub, 2);
  ast_t* sub_typeparams = ast_childidx(sub_def, 1);

  ast_t* super_typeargs = ast_childidx(super, 2);
  ast_t* super_typeparams = ast_childidx(super_def, 1);

  ast_t* super_members = ast_childidx(super_def, 4);
  ast_t* super_member = ast_child(super_members);

  while(super_member != NULL)
  {
    ast_t* super_member_id = ast_childidx(super_member, 1);
    ast_t* sub_member = ast_get(sub_def, ast_name(super_member_id), NULL);

    // If we don't provide a method, we aren't a subtype.
    if(sub_member == NULL)
    {
      if(errors != NULL)
      {
        ast_error_frame(errors, sub,
          "%s is not a subtype of %s: it has no method %s",
          ast_print_type(sub), ast_print_type(super),
          ast_name(super_member_id));
      }

      ret = false;
      super_member = ast_sibling(super_member);
      continue;
    }

    // Reify the method on the subtype.
    ast_t* r_sub_member = reify(sub_member, sub_typeparams, sub_typeargs);
    assert(r_sub_member != NULL);

    // Reify the method on the supertype.
    ast_t* r_super_member = reify(super_member, super_typeparams,
      super_typeargs);
    assert(r_super_member != NULL);

    // Check the reified methods.
    bool ok = is_fun_sub_fun(r_sub_member, r_super_member, errors);
    ast_free_unattached(r_sub_member);
    ast_free_unattached(r_super_member);

    if(!ok)
    {
      ret = false;

      if(errors != NULL)
      {
        ast_error_frame(errors, sub_member,
          "%s is not a subtype of %s: method %s has an incompatible signature",
          ast_print_type(sub), ast_print_type(super),
          ast_name(super_member_id));
      }
    }

    super_member = ast_sibling(super_member);
  }

  pop_assume();
  return ret;
}