コード例 #1
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
bool is_eqtype(ast_t* a, ast_t* b)
{
  if((ast_id(a) == TK_NOMINAL) && (ast_id(b) == TK_NOMINAL))
    return is_nominal_eq_nominal(a, b);

  return is_subtype(a, b) && is_subtype(b, a);
}
コード例 #2
0
ファイル: subtype.c プロジェクト: jersey99/ponyc
static bool is_x_sub_union(ast_t* sub, ast_t* super, errorframe_t* errors)
{
  // TODO: a tuple may be a subtype of a union of tuples without being a
  // subtype of any one element of the union.

  // T1 <: T2 or T1 <: T3
  // ---
  // T1 <: (T2 | T3)
  for(ast_t* child = ast_child(super);
    child != NULL;
    child = ast_sibling(child))
  {
    if(is_subtype(sub, child, NULL))
      return true;
  }

  if(errors != NULL)
  {
    for(ast_t* child = ast_child(super);
      child != NULL;
      child = ast_sibling(child))
    {
      is_subtype(sub, child, errors);
    }

    ast_error_frame(errors, sub, "%s is not a subtype of any element of %s",
      ast_print_type(sub), ast_print_type(super));
  }

  return false;
}
コード例 #3
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
// 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;
}
コード例 #4
0
ファイル: matchtype.c プロジェクト: mgist/ponyc
static matchtype_t is_nominal_match_entity(ast_t* operand, ast_t* pattern)
{
  AST_GET_CHILDREN(operand, o_pkg, o_id, o_typeargs, o_cap, o_eph);
  AST_GET_CHILDREN(pattern, p_pkg, p_id, p_typeargs, p_cap, p_eph);

  // We say the pattern provides the operand if it is a subtype after changing
  // it to have the same refcap as the operand.
  token_id tcap = ast_id(p_cap);
  token_id teph = ast_id(p_eph);
  ast_t* r_operand = set_cap_and_ephemeral(operand, tcap, teph);
  bool provides = is_subtype(pattern, r_operand, false);
  ast_free_unattached(r_operand);

  // If the pattern doesn't provide the operand, reject the match.
  if(!provides)
    return MATCHTYPE_REJECT;

  // If the operand does provide the pattern, but the operand refcap can't
  // match the pattern refcap, deny the match.
  if(!is_cap_match_cap(ast_id(o_cap), ast_id(o_eph), tcap, teph))
    return MATCHTYPE_DENY;

  // Otherwise, accept the match.
  return MATCHTYPE_ACCEPT;
}
コード例 #5
0
ファイル: reach.c プロジェクト: Sendence/ponyc
static void add_traits_to_type(reach_t* r, reach_type_t* t,
  pass_opt_t* opt)
{
  size_t i = HASHMAP_BEGIN;
  reach_type_t* t2;

  while((t2 = reach_types_next(&r->types, &i)) != NULL)
  {
    if(ast_id(t2->ast) != TK_NOMINAL)
      continue;

    ast_t* def = (ast_t*)ast_data(t2->ast);

    switch(ast_id(def))
    {
      case TK_INTERFACE:
      case TK_TRAIT:
        if(is_subtype(t->ast, t2->ast, NULL, opt))
        {
          reach_type_cache_put(&t->subtypes, t2);
          reach_type_cache_put(&t2->subtypes, t);
          add_methods_to_type(r, t2, t, opt);
        }
        break;

      default: {}
    }
  }
}
コード例 #6
0
ファイル: traits.c プロジェクト: lzpfmh/ponyc
// Check that the given delegate target is in the entity's provides list and
// is a legal type for the field
static bool check_delegate(ast_t* entity, ast_t* field_type,
  ast_t* delegated)
{
  assert(entity != NULL);
  assert(field_type != NULL);
  assert(delegated != NULL);

  if(!is_subtype(field_type, delegated, true))
  {
    ast_error(delegated, "field not a subtype of delegate");
    ast_error(field_type, "field type: %s", ast_print_type(field_type));
    ast_error(delegated, "delegate type: %s", ast_print_type(delegated));
    return false;
  }

  ast_t* provides = ast_childidx(entity, 3);
  void* del_def = ast_data(delegated);

  for(ast_t* p = ast_child(provides); p != NULL; p = ast_sibling(p))
  {
    if(ast_data(p) == del_def)
      return true;
  }

  assert(ast_id(delegated) == TK_NOMINAL);
  ast_error(delegated,
    "cannot delegate to %s, containing entity does not provide it",
    ast_name(ast_childidx(delegated, 1)));
  return false;
}
コード例 #7
0
ファイル: traits.c プロジェクト: lzpfmh/ponyc
// Check that the given method is compatible with the existing definition.
// Return the method that ends up being in the entity or NULL on error.
// Stages 2A, 2B and 2C.
static ast_t* add_method(ast_t* entity, ast_t* existing_method,
  ast_t* new_method, ast_t** last_method)
{
  assert(entity != NULL);
  assert(new_method != NULL);
  assert(last_method != NULL);

  const char* name = ast_name(ast_childidx(new_method, 1));
  const char* entity_name = ast_name(ast_child(entity));

  if(existing_method == NULL)
  {
    // This method is new to the entity.
    // Stage 2C.
    ast_t* case_clash = ast_get_case(entity, name, NULL);

    if(case_clash != NULL)
    {
      ast_error(case_clash, "in %s method name %s differs only in case",
        entity_name, name);
      ast_error(new_method, "clashing method is here");
      return NULL;
    }

    attach_method_t(new_method, NULL, false);
    ast_list_append(ast_childidx(entity, 4), last_method, new_method);
    ast_set(entity, name, new_method, SYM_DEFINED);
    return *last_method;
  }

  method_t* info = (method_t*)ast_data(existing_method);
  assert(info != NULL);

  if(info->local_def)
  {
    // Existing method is a local definition, new method must be a subtype
    // Stage 2A
    if(is_subtype(existing_method, new_method, true))
      return existing_method;

    ast_error(existing_method,
      "local method %s is not compatible with provided version", name);
    ast_error(new_method, "clashing method is here");

    return NULL;
  }

  // Both method versions came from the provides list, their signatures must
  // match exactly
  // Stage 2B
  if(compare_signatures(existing_method, new_method))
    return existing_method;

  ast_error(entity, "clashing definitions of method %s provided, local "
    "disambiguation required", name);
  ast_error(existing_method, "provided here");
  ast_error(new_method, "and here");

  return NULL;
}
コード例 #8
0
ファイル: reference.c プロジェクト: Potpourri/ponyc
bool expr_field(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, type, init);

  if(ast_id(init) != TK_NONE)
  {
    // Initialiser type must match declared type.
    if(!coerce_literals(&init, type, opt))
      return false;

    ast_t* init_type = ast_type(init);

    if(is_typecheck_error(init_type))
      return false;

    init_type = alias(init_type);

    if(!is_subtype(init_type, type))
    {
      ast_error(init,
        "field/param initialiser is not a subtype of the field/param type");
      ast_error(type, "field/param type: %s", ast_print_type(type));
      ast_error(init, "initialiser type: %s", ast_print_type(init_type));
      ast_free_unattached(init_type);
      return false;
    }

    ast_free_unattached(init_type);
  }

  ast_settype(ast, type);
  return true;
}
コード例 #9
0
ファイル: reach.c プロジェクト: DevL/ponyc
static void add_traits_to_type(reachable_method_stack_t** s,
  reachable_types_t* r, reachable_type_t* t)
{
  size_t i = HASHMAP_BEGIN;
  reachable_type_t* t2;

  while((t2 = reachable_types_next(r, &i)) != NULL)
  {
    if(ast_id(t2->type) == TK_TUPLETYPE)
      continue;

    ast_t* def = (ast_t*)ast_data(t2->type);

    switch(ast_id(def))
    {
      case TK_INTERFACE:
      case TK_TRAIT:
        if(is_subtype(t->type, t2->type, NULL))
        {
          reachable_type_cache_put(&t->subtypes, t2);
          reachable_type_cache_put(&t2->subtypes, t);
          add_methods_to_type(s, t2, t);
        }
        break;

      default: {}
    }
  }
}
コード例 #10
0
ファイル: polytype.c プロジェクト: bubble-07/ConCurC
//Returns "true" if a is a subtype of b
int is_subtype(polytype a, polytype b) {
    if (polytype_trivial_eq(b, Top)) {
        return 1; //Everything is a subtype of "top"
    }
    //Is A possibly a subtype of b?
    if (Type_graph_possiblesubtype(UniverseGraph, a, b)) {
        //Is A the same as B?
        if (polytype_trivial_eq(a, b)) {
            return 1;
        }
        //Otherwise, must not be, so recurse on b's children
        //TODO: Eliminate instantiation here!
        polytype_dynarray b_subtypes = typeslot_dynarray_instantiate(polytype_get_subtypes(b));
        int i;
        for (i=0; i < b_subtypes.size; i++) {
            //If a is a subtype of any subtype of b
            if (is_subtype(a, b_subtypes.begin[i])) {
                //Then it's a subtype of b
                return 1;
            }
        }
    }
    //In all other cases, it can't be a subtype of b
    return 0;
}
コード例 #11
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
// The subtype is an arrow, the supertype is an arrow.
static bool is_arrow_sub_arrow(ast_t* sub, ast_t* super)
{
  // If the supertype is also a viewpoint and the viewpoint is the same, then
  // we are a subtype if our adapted type is a subtype of the supertype's
  // adapted type.
  AST_GET_CHILDREN(sub, sub_left, sub_right);
  AST_GET_CHILDREN(super, super_left, super_right);

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

        default:
          return false;
      }
      break;

    case TK_BOXTYPE:
      if(ast_id(super_left) != TK_BOXTYPE)
        return false;
      break;

    default:
      if(!is_eqtype(sub_left, super_left))
        return false;
      break;
  }

  return is_subtype(sub_right, super_right);
}
コード例 #12
0
ファイル: subtype.c プロジェクト: jersey99/ponyc
static bool is_union_sub_x(ast_t* sub, ast_t* super, errorframe_t* errors)
{
  // T1 <: T3
  // T2 <: T3
  // ---
  // (T1 | T2) <: T3
  for(ast_t* child = ast_child(sub);
    child != NULL;
    child = ast_sibling(child))
  {
    if(!is_subtype(child, super, errors))
    {
      if(errors != NULL)
      {
        ast_error_frame(errors, child,
          "not every element of %s is a subtype of %s",
          ast_print_type(sub), ast_print_type(super));
      }

      return false;
    }
  }

  return true;
}
コード例 #13
0
ファイル: subtype.c プロジェクト: jersey99/ponyc
static bool is_x_sub_isect(ast_t* sub, ast_t* super, errorframe_t* errors)
{
  // T1 <: T2
  // T1 <: T3
  // ---
  // T1 <: (T2 & T3)
  for(ast_t* child = ast_child(super);
    child != NULL;
    child = ast_sibling(child))
  {
    if(!is_subtype(sub, child, errors))
    {
      if(errors != NULL)
      {
        ast_error_frame(errors, sub,
          "%s is not a subtype of every element of %s",
          ast_print_type(sub), ast_print_type(super));
      }

      return false;
    }
  }

  return true;
}
コード例 #14
0
ファイル: subtype.c プロジェクト: jersey99/ponyc
static bool is_typeparam_sub_x(ast_t* sub, ast_t* super, errorframe_t* errors)
{
  if(is_typeparam_base_sub_x(sub, super, false))
    return true;

  // upperbound(A k) <: T
  // ---
  // A k <: T
  ast_t* sub_upper = typeparam_upper(sub);

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

    return false;
  }

  bool ok = is_subtype(sub_upper, super, errors);
  ast_free_unattached(sub_upper);
  return ok;
}
コード例 #15
0
ファイル: matchtype.c プロジェクト: awaidmann/ponyc
static matchtype_t is_entity_match_trait(ast_t* operand, ast_t* pattern,
  pass_opt_t* opt)
{
  AST_GET_CHILDREN(operand, o_pkg, o_id, o_typeargs, o_cap, o_eph);
  AST_GET_CHILDREN(pattern, p_pkg, p_id, p_typeargs, p_cap, p_eph);

  token_id tcap = ast_id(p_cap);
  token_id teph = ast_id(p_eph);
  ast_t* r_operand = set_cap_and_ephemeral(operand, tcap, teph);
  bool provides = is_subtype(r_operand, pattern, NULL, opt);
  ast_free_unattached(r_operand);

  // If the operand doesn't provide the pattern (trait or interface), reject
  // the match.
  if(!provides)
    return MATCHTYPE_REJECT;

  // If the operand does provide the pattern, but the operand refcap can't
  // match the pattern refcap, deny the match.
  if(!is_cap_match_cap(ast_id(o_cap), ast_id(o_eph), tcap, teph))
    return MATCHTYPE_DENY;

  // Otherwise, accept the match.
  return MATCHTYPE_ACCEPT;
}
コード例 #16
0
ファイル: reference.c プロジェクト: tmmcguire/ponyc
bool expr_param(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, type, init);
  ast_settype(ast, type);
  bool ok = true;

  if(ast_id(init) != TK_NONE)
  {
    // Initialiser type must match declared type.
    if(!coerce_literals(&init, type, opt))
      return false;

    ast_t* init_type = ast_type(init);

    if(is_typecheck_error(init_type))
      return false;

    init_type = alias(init_type);
    errorframe_t err = NULL;

    if(!is_subtype(init_type, type, &err, opt))
    {
      errorframe_t err2 = NULL;
      ast_error_frame(&err2, init,
        "default argument is not a subtype of the parameter type");
      errorframe_append(&err2, &err);
      errorframe_report(&err2, opt->check.errors);
      ok = false;
    }

    ast_free_unattached(init_type);
  }

  return ok;
}
コード例 #17
0
ファイル: traits.c プロジェクト: abingham/ponyc
// Find the most general method from the given list (if any)
// Return NULL if no most general found
static ast_t* most_general_method(ast_t* list, ast_t* entity, const char* name)
{
  assert(list != NULL);
  assert(entity != NULL);
  assert(name != NULL);

  for(ast_t* p = ast_child(list); p != NULL; p = ast_sibling(p))
  {
    bool is_p_best = true;

    for(ast_t* q = ast_child(list); q != NULL; q = ast_sibling(q))
    {
      if(ast_id(p) != ast_id(q))
      {
        ast_error(entity, "Clashing types for method %s provided by traits",
          name);
        return NULL;
      }

      if(!is_subtype(p, q))
      {
        // p is less general than q
        is_p_best = false;
        break;
      }
    }

    if(is_p_best)
      return p;
  }

  ast_error(entity, "Clashing types for method %s provided by traits", name);
  return NULL;
}
コード例 #18
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
// 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;
}
コード例 #19
0
ファイル: call.c プロジェクト: awaidmann/ponyc
static token_id partial_application_cap(pass_opt_t* opt, ast_t* ftype,
  ast_t* receiver, ast_t* positional)
{
  // Check if the apply method in the generated object literal can accept a box
  // receiver. If not, it must be a ref receiver. It can accept a box receiver
  // if box->receiver <: lhs->receiver and box->arg <: lhs->param.
  AST_GET_CHILDREN(ftype, cap, typeparams, params, result);

  ast_t* type = ast_type(receiver);
  ast_t* view_type = viewpoint_type(ast_from(type, TK_BOX), type);
  ast_t* need_type = set_cap_and_ephemeral(type, ast_id(cap), TK_NONE);

  bool ok = is_subtype(view_type, need_type, NULL, opt);
  ast_free_unattached(view_type);
  ast_free_unattached(need_type);

  if(!ok)
    return TK_REF;

  ast_t* param = ast_child(params);
  ast_t* arg = ast_child(positional);

  while(arg != NULL)
  {
    if(ast_id(arg) != TK_NONE)
    {
      type = ast_type(arg);
      view_type = viewpoint_type(ast_from(type, TK_BOX), type);
      need_type = ast_childidx(param, 1);

      ok = is_subtype(view_type, need_type, NULL, opt);
      ast_free_unattached(view_type);
      ast_free_unattached(need_type);

      if(!ok)
        return TK_REF;
    }

    arg = ast_sibling(arg);
    param = ast_sibling(param);
  }

  return TK_BOX;
}
コード例 #20
0
ファイル: reference.c プロジェクト: Preetam/ponyc
static bool check_return_type(ast_t* ast)
{
  AST_GET_CHILDREN(ast, cap, id, typeparams, params, type, can_error, body);
  ast_t* body_type = ast_type(body);

  if(is_typecheck_error(body_type))
    return false;

  // The last statement is an error, and we've already checked any return
  // expressions in the method.
  if(is_control_type(body_type))
    return true;

  // If it's a compiler intrinsic, ignore it.
  if(ast_id(body_type) == TK_COMPILE_INTRINSIC)
    return true;

  // The body type must match the return type, without subsumption, or an alias
  // of the body type must be a subtype of the return type.
  ast_t* a_type = alias(type);
  ast_t* a_body_type = alias(body_type);
  bool ok = true;

  errorframe_t info = NULL;
  if(!is_subtype(body_type, type, &info) ||
    !is_subtype(a_body_type, a_type, &info))
  {
    errorframe_t frame = NULL;
    ast_t* last = ast_childlast(body);
    ast_error_frame(&frame, last, "function body isn't the result type");
    ast_error_frame(&frame, type, "function return type: %s",
      ast_print_type(type));
    ast_error_frame(&frame, body_type, "function body type: %s",
      ast_print_type(body_type));
    errorframe_append(&frame, &info);
    errorframe_report(&frame);
    ok = false;
  }

  ast_free_unattached(a_type);
  ast_free_unattached(a_body_type);
  return ok;
}
コード例 #21
0
ファイル: reference.c プロジェクト: pap/ponyc
bool expr_field(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, type, init);

  // An embedded field must have a known, non-actor type.
  if(ast_id(ast) == TK_EMBED)
  {
    if(!is_known(type) || is_actor(type))
    {
      ast_error(ast, "embedded fields must always be primitives or classes");
      return false;
    }
  }

  if(ast_id(init) != TK_NONE)
  {
    // Initialiser type must match declared type.
    if(!coerce_literals(&init, type, opt))
      return false;

    ast_t* init_type = ast_type(init);

    if(is_typecheck_error(init_type))
      return false;

    init_type = alias(init_type);

    if(!is_subtype(init_type, type))
    {
      ast_error(init,
        "field/param initialiser is not a subtype of the field/param type");
      ast_error(type, "field/param type: %s", ast_print_type(type));
      ast_error(init, "initialiser type: %s", ast_print_type(init_type));
      ast_free_unattached(init_type);
      return false;
    }

    // If it's an embedded field, check for a constructor result.
    if(ast_id(ast) == TK_EMBED)
    {
      if((ast_id(init) != TK_CALL) ||
        (ast_id(ast_childidx(init, 2)) != TK_NEWREF))
      {
        ast_error(ast,
          "an embedded field must be initialised using a constructor");
        return false;
      }
    }

    ast_free_unattached(init_type);
  }

  ast_settype(ast, type);
  return true;
}
コード例 #22
0
ファイル: matchtype.c プロジェクト: ozra/ponyc
static matchtype_t could_subtype_trait_nominal(ast_t* sub, ast_t* super)
{
  ast_t* def = (ast_t*)ast_data(super);

  switch(ast_id(def))
  {
    case TK_INTERFACE:
    case TK_TRAIT:
      return could_subtype_trait_trait(sub, super);

    case TK_PRIMITIVE:
    case TK_CLASS:
    case TK_ACTOR:
    {
      // Super must provide sub, ignoring cap/eph, else reject.
      AST_GET_CHILDREN(super, sup_pkg, sup_id, sup_typeargs, sup_cap, sup_eph);
      ast_t* r_type = set_cap_and_ephemeral(sub,
        ast_id(sup_cap), ast_id(sup_eph));

      if(!is_subtype(super, r_type))
      {
        ast_free_unattached(r_type);
        return MATCHTYPE_REJECT;
      }

      // Sub cap/eph must be a subtype of super cap/eph, else deny.
      if(!is_subtype(sub, r_type))
      {
        ast_free_unattached(r_type);
        return MATCHTYPE_DENY;
      }

      // Otherwise, accept.
      return MATCHTYPE_ACCEPT;
    }

    default: {}
  }

  assert(0);
  return MATCHTYPE_DENY;
}
コード例 #23
0
ファイル: assemble.c プロジェクト: jonas-l/ponyc
static ast_t* type_typeexpr(token_id t, ast_t* l_type, ast_t* r_type)
{
  bool is_union = t == TK_UNIONTYPE;

  if(l_type == NULL)
    return r_type;

  if(r_type == NULL)
    return l_type;

  if(is_subtype(l_type, r_type))
  {
    if(is_union)
      return r_type;
    else
      return l_type;
  }

  if(is_subtype(r_type, l_type))
  {
    if(is_union)
      return l_type;
    else
      return r_type;
  }

  ast_t* type = ast_from(l_type, t);
  append_to_typeexpr(type, l_type, is_union);
  append_to_typeexpr(type, r_type, is_union);

  // If there's only one element, remove the type expression node.
  ast_t* child = ast_child(type);

  if(ast_sibling(child) == NULL)
  {
    child = ast_dup(child);
    ast_free_unattached(type);
    type = child;
  }

  return type;
}
コード例 #24
0
ファイル: matchtype.c プロジェクト: ozra/ponyc
static matchtype_t could_subtype_trait_trait(ast_t* sub, ast_t* super)
{
  // Sub cap/eph must be a subtype of super cap/eph, else deny.
  // Otherwise, accept.
  AST_GET_CHILDREN(super, sup_pkg, sup_id, sup_typeargs, sup_cap, sup_eph);
  ast_t* r_type = set_cap_and_ephemeral(sub, ast_id(sup_cap), ast_id(sup_eph));
  bool ok = is_subtype(sub, r_type);
  ast_free_unattached(r_type);

  return ok ? MATCHTYPE_ACCEPT : MATCHTYPE_DENY;
}
コード例 #25
0
ファイル: subtype.c プロジェクト: jersey99/ponyc
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;
}
コード例 #26
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
bool is_signed(pass_opt_t* opt, ast_t* type)
{
  if(type == NULL)
    return false;

  ast_t* builtin = type_builtin(opt, type, "Signed");

  if(builtin == NULL)
    return false;

  bool ok = is_subtype(type, builtin);
  ast_free_unattached(builtin);
  return ok;
}
コード例 #27
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
// The subtype is a typeparam, the supertype could be anything.
static bool is_typeparam_subtype(ast_t* sub, ast_t* super)
{
  switch(ast_id(super))
  {
    case TK_TYPEPARAMREF:
      if(is_typeparam_sub_typeparam(sub, super))
        return true;
      break;

    case TK_UNIONTYPE:
      if(is_subtype_union(sub, super))
        return true;
      break;

    case TK_ISECTTYPE:
      if(is_subtype_isect(sub, super))
        return true;
      break;

    case TK_ARROW:
      if(is_subtype_arrow(sub, super))
        return true;
      break;

    default: {}
  }

  // We can be a subtype if our upper bounds, ie our constraint, is a subtype.
  ast_t* sub_def = (ast_t*)ast_data(sub);
  ast_t* constraint = ast_childidx(sub_def, 1);

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

    if(constraint_def == sub_def)
      return false;
  }

  // Constraint must be modified with sub ephemerality.
  AST_GET_CHILDREN(sub, name, cap, eph);
  ast_t* r_constraint = set_cap_and_ephemeral(constraint, TK_NONE,
    ast_id(eph));

  bool ok = is_subtype(r_constraint, super);
  ast_free_unattached(r_constraint);

  return ok;
}
コード例 #28
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
// The subtype is a union, the supertype could be anything.
static bool is_union_subtype(ast_t* sub, ast_t* super)
{
  // All elements of the union must be a subtype of super.
  ast_t* child = ast_child(sub);

  while(child != NULL)
  {
    if(!is_subtype(child, super))
      return false;

    child = ast_sibling(child);
  }

  return true;
}
コード例 #29
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
// The subtype is either a nominal or a tuple, the super type is an isect.
static bool is_subtype_isect(ast_t* sub, ast_t* super)
{
  // Must be a subtype of all elements of the intersection.
  ast_t* child = ast_child(super);

  while(child != NULL)
  {
    if(!is_subtype(sub, child))
      return false;

    child = ast_sibling(child);
  }

  return true;
}
コード例 #30
0
ファイル: subtype.c プロジェクト: pengzj/ponyc
// The subtype is either a nominal or a tuple, the super type is a union.
static bool is_subtype_union(ast_t* sub, ast_t* super)
{
  // Must be a subtype of one element of the union.
  ast_t* child = ast_child(super);

  while(child != NULL)
  {
    if(is_subtype(sub, child))
      return true;

    child = ast_sibling(child);
  }

  return false;
}