예제 #1
0
파일: flatten.c 프로젝트: aturley/ponyc
ast_result_t flatten_typeparamref(pass_opt_t* opt, ast_t* ast)
{
  ast_t* cap_ast = cap_fetch(ast);
  token_id cap = ast_id(cap_ast);

  typeparam_set_cap(ast);

  token_id set_cap = ast_id(cap_ast);

  if((cap != TK_NONE) && (cap != set_cap))
  {
    ast_t* def = (ast_t*)ast_data(ast);
    ast_t* constraint = typeparam_constraint(ast);

    if(constraint != NULL)
    {
      ast_error(opt->check.errors, cap_ast, "can't specify a capability on a "
        "type parameter that differs from the constraint");
      ast_error_continue(opt->check.errors, constraint,
        "constraint definition is here");

      if(ast_parent(constraint) != def)
      {
        ast_error_continue(opt->check.errors, def,
          "type parameter definition is here");
      }
    } else {
      ast_error(opt->check.errors, cap_ast, "a type parameter with no "
        "constraint can only have #any as its capability");
      ast_error_continue(opt->check.errors, def,
        "type parameter definition is here");
    }

    return AST_ERROR;
  }

  return AST_OK;
}
예제 #2
0
파일: subtype.c 프로젝트: jersey99/ponyc
static bool is_fun_sub_fun(ast_t* sub, ast_t* super, errorframe_t* errors)
{
  token_id tsub = ast_id(sub);
  token_id tsuper = ast_id(super);

  switch(tsub)
  {
    case TK_NEW:
    case TK_BE:
    case TK_FUN:
      break;

    default:
      return false;
  }

  switch(tsuper)
  {
    case TK_NEW:
    case TK_BE:
    case TK_FUN:
      break;

    default:
      return false;
  }

  AST_GET_CHILDREN(sub, sub_cap, sub_id, sub_typeparams, sub_params);
  AST_GET_CHILDREN(super, super_cap, super_id, super_typeparams, super_params);

  // Must have the same name.
  if(ast_name(sub_id) != ast_name(super_id))
  {
    if(errors != NULL)
    {
      ast_error_frame(errors, sub,
        "method %s is not a subtype of method %s: they have different names",
        ast_name(sub_id), ast_name(super_id));
    }

    return false;
  }

  // A constructor can only be a subtype of a constructor.
  if(((tsub == TK_NEW) || (tsuper == TK_NEW)) && (tsub != tsuper))
  {
    if(errors != NULL)
      ast_error_frame(errors, sub,
        "only a constructor can be a subtype of a constructor");

    return false;
  }

  // Must have the same number of type parameters.
  if(ast_childcount(sub_typeparams) != ast_childcount(super_typeparams))
  {
    if(errors != NULL)
      ast_error_frame(errors, sub,
        "methods have a different number of type parameters");

    return false;
  }

  // Must have the same number of parameters.
  if(ast_childcount(sub_params) != ast_childcount(super_params))
  {
    if(errors != NULL)
      ast_error_frame(errors, sub,
        "methods have a different number of parameters");

    return false;
  }

  ast_t* r_sub = sub;

  if(ast_id(super_typeparams) != TK_NONE)
  {
    // Reify sub with the type parameters of super.
    BUILD(typeargs, super_typeparams, NODE(TK_TYPEARGS));
    ast_t* super_typeparam = ast_child(super_typeparams);

    while(super_typeparam != NULL)
    {
      AST_GET_CHILDREN(super_typeparam, super_id, super_constraint);

      BUILD(typearg, super_typeparam,
        NODE(TK_TYPEPARAMREF, TREE(super_id) NONE NONE));

      ast_t* def = ast_get(super_typeparam, ast_name(super_id), NULL);
      ast_setdata(typearg, def);
      typeparam_set_cap(typearg);
      ast_append(typeargs, typearg);

      super_typeparam = ast_sibling(super_typeparam);
    }

    r_sub = reify(sub, sub_typeparams, typeargs);
    ast_free_unattached(typeargs);
  }

  bool ok = is_reified_fun_sub_fun(r_sub, super, errors);

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

  return ok;
}