Exemplo n.º 1
0
bool safe_to_autorecover(ast_t* receiver_type, ast_t* type)
{
  switch(ast_id(receiver_type))
  {
    case TK_ISECTTYPE:
    {
      ast_t* child = ast_child(receiver_type);

      while(child != NULL)
      {
        if(safe_field_write(cap_single(child), type))
          return true;

        child = ast_sibling(child);
      }

      return false;
    }

    case TK_UNIONTYPE:
    {
      ast_t* child = ast_child(receiver_type);

      while(child != NULL)
      {
        if(!safe_field_write(cap_single(child), type))
          return false;

        child = ast_sibling(child);
      }

      return true;
    }

    case TK_NOMINAL:
    case TK_TYPEPARAMREF:
      return safe_field_write(cap_single(receiver_type), type);

    case TK_ARROW:
    {
      ast_t* upper = viewpoint_upper(receiver_type);
      bool ok = safe_to_autorecover(upper, type);

      if(upper != receiver_type)
        ast_free_unattached(upper);

      return ok;
    }

    default: {}
  }

  assert(0);
  return false;
}
Exemplo n.º 2
0
static trace_t trace_type_nominal(ast_t* type)
{
  switch(ast_id((ast_t*)ast_data(type)))
  {
    case TK_INTERFACE:
    case TK_TRAIT:
      switch(cap_single(type))
      {
        case TK_VAL:
          return TRACE_VAL_UNKNOWN;

        case TK_TAG:
          return TRACE_TAG_UNKNOWN;

        default: {}
      }

      return TRACE_MUT_UNKNOWN;

    case TK_PRIMITIVE:
    {
      if(is_machine_word(type))
        return TRACE_MACHINE_WORD;

      return TRACE_PRIMITIVE;
    }

    case TK_STRUCT:
    case TK_CLASS:
      if(is_maybe(type))
        return TRACE_MAYBE;

      switch(cap_single(type))
      {
        case TK_VAL:
          return TRACE_VAL_KNOWN;

        case TK_TAG:
          return TRACE_TAG_KNOWN;

        default: {}
      }

      return TRACE_MUT_KNOWN;

    case TK_ACTOR:
      return TRACE_TAG_KNOWN;

    default: {}
  }

  pony_assert(0);
  return TRACE_NONE;
}
Exemplo n.º 3
0
static trace_t trace_type_nominal(ast_t* type)
{
  switch(ast_id((ast_t*)ast_data(type)))
  {
    case TK_INTERFACE:
    case TK_TRAIT:
      switch(cap_single(type))
      {
        case TK_VAL:
          return TRACE_UNKNOWN_VAL;

        case TK_TAG:
          return TRACE_TAG_OR_ACTOR;

        default: {}
      }

      return TRACE_UNKNOWN;

    case TK_PRIMITIVE:
      return TRACE_PRIMITIVE;

    case TK_STRUCT:
    case TK_CLASS:
      if(is_maybe(type))
        return TRACE_MAYBE;

      switch(cap_single(type))
      {
        case TK_VAL:
          return TRACE_KNOWN_VAL;

        case TK_TAG:
          return TRACE_TAG;

        default: {}
      }

      return TRACE_KNOWN;

    case TK_ACTOR:
      return TRACE_ACTOR;

    default: {}
  }

  assert(0);
  return TRACE_NONE;
}
Exemplo n.º 4
0
static bool trace_as_tag(compile_t* c, LLVMValueRef value, ast_t* type)
{
  switch(ast_id(type))
  {
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    {
      ast_t* child = ast_child(type);

      while(child != NULL)
      {
        if(!trace_as_tag(c, value, child))
          return false;

        child = ast_sibling(child);
      }

      return true;
    }

    case TK_TUPLETYPE:
      return false;

    case TK_NOMINAL:
      return cap_single(type) == TK_TAG;

    default: {}
  }

  assert(0);
  return false;
}
Exemplo n.º 5
0
Arquivo: cap.c Projeto: jonas-l/ponyc
token_id cap_from_constraint(ast_t* type)
{
  switch(ast_id(type))
  {
    case TK_UNIONTYPE:
    {
      ast_t* child = ast_child(type);
      token_id cap = cap_from_constraint(child);
      child = ast_sibling(child);

      while(child != NULL)
      {
        cap = cap_union_constraint(cap, cap_from_constraint(child));
        child = ast_sibling(child);
      }

      return cap;
    }

    case TK_ISECTTYPE:
    {
      ast_t* child = ast_child(type);
      token_id cap = cap_from_constraint(child);
      child = ast_sibling(child);

      while(child != NULL)
      {
        cap = cap_isect_constraint(cap, cap_from_constraint(child));
        child = ast_sibling(child);
      }

      return cap;
    }

    case TK_NOMINAL:
    case TK_TYPEPARAMREF:
      return cap_typeparam(cap_single(type));

    case TK_ARROW:
    {
      AST_GET_CHILDREN(type, left, right);
      return cap_from_constraint(right);
    }

    default: {}
  }

  assert(0);
  return TK_NONE;
}
Exemplo n.º 6
0
static ast_t* make_arrow_type(ast_t* left, ast_t* right)
{
  switch(ast_id(right))
  {
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    case TK_TUPLETYPE:
    {
      ast_t* type = ast_from(right, ast_id(right));
      ast_t* child = ast_child(right);

      while(child != NULL)
      {
        ast_append(type, make_arrow_type(left, child));
        child = ast_sibling(child);
      }

      return type;
    }

    case TK_NOMINAL:
    case TK_TYPEPARAMREF:
    {
      switch(cap_single(right))
      {
        case TK_VAL:
        case TK_TAG:
          return right;

        default: {}
      }

      return make_single_arrow(left, right);
    }

    case TK_ARROW:
      return make_single_arrow(left, right);

    default: {}
  }

  assert(0);
  return NULL;
}
Exemplo n.º 7
0
static bool safe_field_write(token_id cap, ast_t* type)
{
  switch(ast_id(type))
  {
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    case TK_TUPLETYPE:
    {
      // Safe to write if every component is safe to write.
      ast_t* child = ast_child(type);

      while(child != NULL)
      {
        if(!safe_field_write(cap, child))
          return false;

        child = ast_sibling(child);
      }

      return true;
    }

    case TK_ARROW:
    {
      ast_t* upper = viewpoint_upper(type);
      bool ok = safe_field_write(cap, upper);

      if(upper != type)
        ast_free_unattached(upper);

      return ok;
    }

    case TK_NOMINAL:
    case TK_TYPEPARAMREF:
      return cap_safetowrite(cap, cap_single(type));

    default: {}
  }

  assert(0);
  return false;
}
Exemplo n.º 8
0
bool safe_to_write(ast_t* ast, ast_t* type)
{
  switch(ast_id(ast))
  {
    case TK_VAR:
    case TK_LET:
    case TK_VARREF:
    case TK_DONTCARE:
      return true;

    case TK_FVARREF:
    case TK_FLETREF:
    case TK_EMBEDREF:
    {
      // If the ast is x.f, we need the type of x, which will be a nominal
      // type or an arrow type, since we were able to lookup a field on it.
      AST_GET_CHILDREN(ast, left, right);
      ast_t* l_type = ast_type(left);

      // Any viewpoint adapted type will not be safe to write to.
      if(ast_id(l_type) != TK_NOMINAL)
        return false;

      token_id l_cap = cap_single(l_type);

      // If the RHS is safe to write, we're done.
      if(safe_field_write(l_cap, type))
        return true;

      // If the field type (without adaptation) is safe, then it's ok as
      // well. So iso.tag = ref should be allowed.
      ast_t* r_type = ast_type(right);
      return safe_field_write(l_cap, r_type);
    }

    case TK_TUPLE:
    {
      // At this point, we know these will be the same length.
      assert(ast_id(type) == TK_TUPLETYPE);
      ast_t* child = ast_child(ast);
      ast_t* type_child = ast_child(type);

      while(child != NULL)
      {
        if(!safe_to_write(child, type_child))
          return false;

        child = ast_sibling(child);
        type_child = ast_sibling(type_child);
      }

      assert(type_child == NULL);
      return true;
    }

    case TK_SEQ:
    {
      // Occurs when there is a tuple on the left. Each child of the tuple will
      // be a sequence, but only sequences with a single writeable child are
      // valid. Other types won't appear here.
      return safe_to_write(ast_child(ast), type);
    }

    default: {}
  }

  assert(0);
  return false;
}
Exemplo n.º 9
0
ast_result_t pass_flatten(ast_t** astp, pass_opt_t* options)
{
  ast_t* ast = *astp;

  switch(ast_id(ast))
  {
    case TK_UNIONTYPE:
      return flatten_union(options, ast);

    case TK_ISECTTYPE:
      return flatten_isect(options, ast);

    case TK_NEW:
    {
      switch(ast_id(options->check.frame->type))
      {
        case TK_CLASS:
          return flatten_constructor(options, ast);

        case TK_ACTOR:
          return flatten_async(options, ast);

        default: {}
      }
      break;
    }

    case TK_BE:
      return flatten_async(options, ast);

    case TK_ARROW:
      return flatten_arrow(options, astp);

    case TK_TYPEPARAMREF:
      return flatten_typeparamref(options, ast);

    case TK_EMBED:
    {
      // An embedded field must have a known, class type.
      AST_GET_CHILDREN(ast, id, type, init);
      bool ok = true;

      if(ast_id(type) != TK_NOMINAL)
        ok = false;

      ast_t* def = (ast_t*)ast_data(type);

      if(def == NULL)
      {
        ok = false;
      } else {
        switch(ast_id(def))
        {
          case TK_STRUCT:
          case TK_CLASS:
            break;

          default:
            ok = false;
            break;
        }
      }

      if(!ok)
      {
        ast_error(options->check.errors, type,
          "embedded fields must be classes or structs");
        return AST_ERROR;
      }

      if(cap_single(type) == TK_TAG)
      {
        ast_error(options->check.errors, type, "embedded fields cannot be tag");
        return AST_ERROR;
      }

      return AST_OK;
    }

    case TK_ACTOR:
    case TK_CLASS:
    case TK_STRUCT:
    case TK_PRIMITIVE:
    case TK_TRAIT:
    case TK_INTERFACE:
      return flatten_provides_list(options, ast, 3);

    default: {}
  }

  return AST_OK;
}