Exemple #1
0
ast_t* viewpoint_type(ast_t* l_type, ast_t* r_type)
{
  switch(ast_id(l_type))
  {
    case TK_TUPLETYPE:
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    {
      // Only occurs in codegen.
      return r_type;
    }

    case TK_NOMINAL:
    {
      if(ast_id(r_type) == TK_ARROW)
        return make_arrow_type(l_type, r_type);

      AST_GET_CHILDREN(l_type, pkg, id, typeargs, cap, eph);
      token_id tcap = ast_id(cap);

      if(tcap == TK_CAP_READ)
        return make_arrow_type(l_type, r_type);

      return viewpoint_cap(tcap, ast_id(eph), r_type);
    }

    case TK_TYPEPARAMREF:
    {
      if(ast_id(r_type) == TK_ARROW)
        return make_arrow_type(l_type, r_type);

      AST_GET_CHILDREN(l_type, id, cap, eph);
      token_id tcap = ast_id(cap);

      if(tcap == TK_CAP_READ)
        return make_arrow_type(l_type, r_type);

      return viewpoint_cap(tcap, ast_id(eph), r_type);
    }

    case TK_ARROW:
    case TK_BOXTYPE:
    case TK_THISTYPE:
      return make_arrow_type(l_type, r_type);

    default: {}
  }

  return NULL;
}
Exemple #2
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;
}
Exemple #3
0
ast_t* viewpoint_type(ast_t* l_type, ast_t* r_type)
{
  switch(ast_id(l_type))
  {
    case TK_TUPLETYPE:
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    {
      // Only occurs in codegen.
      return r_type;
    }

    case TK_NOMINAL:
    {
      if(ast_id(r_type) == TK_ARROW)
        return make_arrow_type(l_type, r_type);

      AST_GET_CHILDREN(l_type, pkg, id, typeargs, cap, eph);
      return viewpoint_cap(ast_id(cap), ast_id(eph), r_type);
    }

    case TK_TYPEPARAMREF:
    {
      if(ast_id(r_type) == TK_ARROW)
        return make_arrow_type(l_type, r_type);

      // If the left side is a type parameter, return an arrow type if the
      // capability is box, otherwise adapt the type.
      AST_GET_CHILDREN(l_type, id, cap, eph);
      token_id tcap = ast_id(cap);

      if(tcap == TK_BOX_GENERIC)
        return make_arrow_type(l_type, r_type);

      return viewpoint_cap(tcap, ast_id(eph), r_type);
    }

    case TK_ARROW:
    case TK_BOXTYPE:
    case TK_THISTYPE:
      return make_arrow_type(l_type, r_type);

    default: {}
  }

  return NULL;
}
Exemple #4
0
static token_id partial_application_cap(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_cap(TK_BOX, TK_NONE, type);
  ast_t* need_type = set_cap_and_ephemeral(type, ast_id(cap), TK_NONE);

  bool ok = is_subtype(view_type, need_type);
  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_cap(TK_BOX, TK_NONE, type);
      need_type = ast_childidx(param, 1);

      ok = is_subtype(view_type, need_type);
      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;
}
Exemple #5
0
ast_t* viewpoint_upper(ast_t* type)
{
  if(ast_id(type) == TK_ARROW)
  {
    AST_GET_CHILDREN(type, left, right);
    ast_t* r_right = viewpoint_upper(right);
    return viewpoint_cap(TK_BOX, TK_NONE, r_right);
  }

  return type;
}
Exemple #6
0
bool flatten_arrows(ast_t** astp, bool errors)
{
  ast_t* ast = *astp;
  ast_t* node_type = ast_type(ast);

  if(node_type != NULL)
  {
    if(!flatten_arrows(&node_type, errors))
      return false;
  }

  if(ast_id(ast) == TK_ARROW)
  {
    AST_GET_CHILDREN(ast, left, right);
    ast_t* flat;

    if(!flatten_arrows(&right, errors))
      return false;

    if((ast_id(left) == TK_BOXTYPE) && (ast_id(right) != TK_ARROW))
      flat = viewpoint_cap(TK_BOX, TK_NONE, right);
    else
      flat = viewpoint_type(left, right);

    if(flat == NULL)
    {
      if(errors)
        ast_error(ast, "can't flatten arrow type");

      return false;
    }

    ast_replace(astp, flat);
    return true;
  }

  ast_t* child = ast_child(ast);

  while(child != NULL)
  {
    if(!flatten_arrows(&child, errors))
      return false;

    child = ast_sibling(child);
  }

  return true;
}
Exemple #7
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;
}