Exemplo n.º 1
0
Arquivo: reach.c Projeto: DevL/ponyc
static void reachable_method(reachable_method_stack_t** s,
  reachable_types_t* r, uint32_t* next_type_id, ast_t* type,
  const char* name, ast_t* typeargs)
{
  switch(ast_id(type))
  {
    case TK_NOMINAL:
    {
      reachable_type_t* t = add_type(s, r, next_type_id, type);
      add_method(s, t, name, typeargs);
      break;
    }

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

      while(child != NULL)
      {
        ast_t* find = lookup_try(NULL, NULL, child, name);

        if(find != NULL)
          reachable_method(s, r, next_type_id, child, name, typeargs);

        child = ast_sibling(child);
      }

      break;
    }

    default:
      assert(0);
  }
}
Exemplo n.º 2
0
static void add_rmethod_to_subtypes(reach_t* r, reach_type_t* t,
  reach_method_name_t* n, reach_method_t* m, pass_opt_t* opt)
{
  switch(ast_id(t->ast))
  {
    case TK_NOMINAL:
    {
      ast_t* def = (ast_t*)ast_data(t->ast);

      switch(ast_id(def))
      {
        case TK_INTERFACE:
        case TK_TRAIT:
        {
          // Add to subtypes if we're an interface or trait.
          size_t i = HASHMAP_BEGIN;
          reach_type_t* t2;

          while((t2 = reach_type_cache_next(&t->subtypes, &i)) != NULL)
            add_rmethod_to_subtype(r, t2, n, m, opt);

          break;
        }

        default: {}
      }
      return;
    }

    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    {
      ast_t* child = ast_child(t->ast);

      while(child != NULL)
      {
        ast_t* find = lookup_try(NULL, NULL, child, n->name);

        if(find != NULL)
        {
          reach_type_t* t2 = add_type(r, child, opt);
          add_rmethod_to_subtype(r, t2, n, m, opt);
          ast_free_unattached(find);
        }

        child = ast_sibling(child);
      }
      return;
    }

    default: {}
  }

  assert(0);
}
Exemplo n.º 3
0
Arquivo: reach.c Projeto: DevL/ponyc
static void add_special(reachable_method_stack_t** s, reachable_type_t* t,
  ast_t* type, const char* special)
{
  special = stringtab(special);
  ast_t* find = lookup_try(NULL, NULL, type, special);

  if(find != NULL)
  {
    add_method(s, t, special, NULL);
    ast_free_unattached(find);
  }
}
Exemplo n.º 4
0
static bool is_constructed_from(pass_opt_t* opt, ast_t* ast, ast_t* type)
{
  ast_t* parent = ast_parent(ast);

  if(ast_id(parent) != TK_DOT)
    return false;

  AST_GET_CHILDREN(parent, left, right);
  ast_t* find = lookup_try(opt, parent, type, ast_name(right));

  if(find == NULL)
    return false;

  bool ok = ast_id(find) == TK_NEW;
  ast_free_unattached(find);
  return ok;
}
Exemplo n.º 5
0
static ast_t* get_fun(gentype_t* g, const char* name, ast_t* typeargs)
{
  ast_t* this_type = set_cap_and_ephemeral(g->ast, TK_REF, TK_NONE);
  ast_t* fun = lookup_try(NULL, NULL, this_type, name);
  ast_free_unattached(this_type);
  assert(fun != NULL);

  if(typeargs != NULL)
  {
    ast_t* typeparams = ast_childidx(fun, 2);
    ast_t* r_fun = reify(typeparams, fun, typeparams, typeargs);
    ast_free_unattached(fun);
    fun = r_fun;
    assert(fun != NULL);
  }

  return fun;
}
Exemplo n.º 6
0
static void add_special(reach_t* r, reach_type_t* t, ast_t* type,
  const char* special, pass_opt_t* opt)
{
  special = stringtab(special);
  ast_t* find = lookup_try(NULL, NULL, type, special);

  if(find != NULL)
  {
    switch(ast_id(find))
    {
      case TK_NEW:
      case TK_FUN:
      case TK_BE:
      {
        reachable_method(r, t->ast, special, NULL, opt);
        ast_free_unattached(find);
        break;
      }

      default: {}
    }
  }
}
Exemplo n.º 7
0
bool expr_this(pass_opt_t* opt, ast_t* ast)
{
  typecheck_t* t = &opt->check;

  if(t->frame->def_arg != NULL)
  {
    ast_error(opt->check.errors, ast,
      "can't reference 'this' in a default argument");
    return false;
  }

  sym_status_t status;
  ast_get(ast, stringtab("this"), &status);

  if(status == SYM_CONSUMED)
  {
    ast_error(opt->check.errors, ast,
      "can't use a consumed 'this' in an expression");
    return false;
  }

  assert(status == SYM_NONE);
  token_id cap = cap_for_this(t);

  if(!cap_sendable(cap) && (t->frame->recover != NULL))
  {
    ast_t* parent = ast_parent(ast);
    if(ast_id(parent) != TK_DOT)
      cap = TK_TAG;
  }

  bool make_arrow = false;

  if(cap == TK_BOX)
  {
    cap = TK_REF;
    make_arrow = true;
  }

  ast_t* type = type_for_this(opt, ast, cap, TK_NONE, false);

  if(make_arrow)
  {
    BUILD(arrow, ast, NODE(TK_ARROW, NODE(TK_THISTYPE) TREE(type)));
    type = arrow;
  }

  // Get the nominal type, which may be the right side of an arrow type.
  ast_t* nominal;
  bool arrow;

  if(ast_id(type) == TK_NOMINAL)
  {
    nominal = type;
    arrow = false;
  } else {
    nominal = ast_childidx(type, 1);
    arrow = true;
  }

  ast_t* typeargs = ast_childidx(nominal, 2);
  ast_t* typearg = ast_child(typeargs);

  while(typearg != NULL)
  {
    if(!expr_nominal(opt, &typearg))
    {
      ast_error(opt->check.errors, ast, "couldn't create a type for 'this'");
      ast_free(type);
      return false;
    }

    typearg = ast_sibling(typearg);
  }

  if(!expr_nominal(opt, &nominal))
  {
    ast_error(opt->check.errors, ast, "couldn't create a type for 'this'");
    ast_free(type);
    return false;
  }

  // Unless this is a field lookup, treat an incomplete `this` as a tag.
  ast_t* parent = ast_parent(ast);
  bool incomplete_ok = false;

  if((ast_id(parent) == TK_DOT) && (ast_child(parent) == ast))
  {
    ast_t* right = ast_sibling(ast);
    assert(ast_id(right) == TK_ID);
    ast_t* find = lookup_try(opt, ast, nominal, ast_name(right));

    if(find != NULL)
    {
      switch(ast_id(find))
      {
        case TK_FVAR:
        case TK_FLET:
        case TK_EMBED:
          incomplete_ok = true;
          break;

        default: {}
      }
    }
  }

  if(!incomplete_ok && is_this_incomplete(t, ast))
  {
    ast_t* tag_type = set_cap_and_ephemeral(nominal, TK_TAG, TK_NONE);
    ast_replace(&nominal, tag_type);
  }

  if(arrow)
    type = ast_parent(nominal);
  else
    type = nominal;

  ast_settype(ast, type);
  return true;
}