Esempio n. 1
0
File: gentype.c Progetto: nunb/ponyc
bool gentype(compile_t* c, ast_t* ast, gentype_t* g)
{
  memset(g, 0, sizeof(gentype_t));

  if(ast == NULL)
    return false;

  if(contains_dontcare(ast))
    return true;

  g->ast = ast;
  g->type_name = genname_type(ast);
  g->desc_name = genname_descriptor(g->type_name);

  switch(ast_id(ast))
  {
    case TK_NOMINAL:
      return make_nominal(c, ast, g, false);

    case TK_TUPLETYPE:
      return make_tuple(c, ast, g);

    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
      // Just a raw object pointer.
      g->underlying = ast_id(ast);
      g->use_type = c->object_ptr;
      return true;

    default: {}
  }

  assert(0);
  return false;
}
Esempio n. 2
0
File: reach.c Progetto: DevL/ponyc
static reachable_type_t* add_tuple(reachable_method_stack_t** s,
  reachable_types_t* r, uint32_t* next_type_id, ast_t* type)
{
  if(contains_dontcare(type))
    return NULL;

  const char* type_name = genname_type(type);
  reachable_type_t* t = reach_type(r, type_name);

  if(t != NULL)
    return t;

  t = add_reachable_type(r, type, type_name);
  t->type_id = ++(*next_type_id);

  ast_t* child = ast_child(type);

  while(child != NULL)
  {
    add_type(s, r, next_type_id, child);
    child = ast_sibling(child);
  }

  return t;
}
Esempio n. 3
0
static reachable_type_t* add_tuple(reachable_method_stack_t** s,
  reachable_types_t* r, uint32_t* next_type_id, ast_t* type)
{
  if(contains_dontcare(type))
    return NULL;

  reachable_type_t* t = reach_type(r, type);

  if(t != NULL)
    return t;

  t = add_reachable_type(r, type);
  t->type_id = ++(*next_type_id);

  t->field_count = (uint32_t)ast_childcount(t->ast);
  t->fields = (reachable_field_t*)calloc(t->field_count,
    sizeof(reachable_field_t));
  size_t index = 0;

  ast_t* child = ast_child(type);

  while(child != NULL)
  {
    t->fields[index].ast = ast_dup(child);
    t->fields[index].type = add_type(s, r, next_type_id, child);;
    index++;

    child = ast_sibling(child);
  }

  return t;
}
Esempio n. 4
0
static bool contains_dontcare(ast_t* ast)
{
  switch(ast_id(ast))
  {
    case TK_DONTCARE:
      return true;

    case TK_TUPLETYPE:
    {
      ast_t* child = ast_child(ast);

      while(child != NULL)
      {
        if(contains_dontcare(child))
          return true;

        child = ast_sibling(child);
      }

      return false;
    }

    default: {}
  }

  return false;
}
Esempio n. 5
0
LLVMValueRef gen_tuple(compile_t* c, ast_t* ast)
{
  ast_t* child = ast_child(ast);

  if(ast_sibling(child) == NULL)
    return gen_expr(c, child);

  deferred_reification_t* reify = c->frame->reify;

  ast_t* type = deferred_reify(reify, ast_type(ast), c->opt);

  // If we contain '_', we have no usable value.
  if(contains_dontcare(type))
  {
    ast_free_unattached(type);
    return GEN_NOTNEEDED;
  }

  reach_type_t* t = reach_type(c->reach, type);
  compile_type_t* c_t = (compile_type_t*)t->c_type;
  int count = LLVMCountStructElementTypes(c_t->primitive);
  size_t buf_size = count * sizeof(LLVMTypeRef);
  LLVMTypeRef* elements = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size);
  LLVMGetStructElementTypes(c_t->primitive, elements);

  LLVMValueRef tuple = LLVMGetUndef(c_t->primitive);
  int i = 0;

  while(child != NULL)
  {
    LLVMValueRef value = gen_expr(c, child);

    if(value == NULL)
    {
      ponyint_pool_free_size(buf_size, elements);
      return NULL;
    }

    // We'll have an undefined element if one of our source elements is a
    // variable declaration. This is ok, since the tuple value will never be
    // used.
    if(value == GEN_NOVALUE || value == GEN_NOTNEEDED)
    {
      ponyint_pool_free_size(buf_size, elements);
      return value;
    }

    ast_t* child_type = deferred_reify(reify, ast_type(child), c->opt);
    value = gen_assign_cast(c, elements[i], value, child_type);
    ast_free_unattached(child_type);
    tuple = LLVMBuildInsertValue(c->builder, tuple, value, i++, "");
    child = ast_sibling(child);
  }

  ponyint_pool_free_size(buf_size, elements);
  return tuple;
}
Esempio n. 6
0
static reach_type_t* add_tuple(reach_t* r, ast_t* type, pass_opt_t* opt)
{
  if(contains_dontcare(type))
    return NULL;

  reach_type_t* t = reach_type(r, type);

  if(t != NULL)
    return t;

  t = add_reach_type(r, type);
  t->underlying = TK_TUPLETYPE;
  t->type_id = r->next_type_id++;

  t->field_count = (uint32_t)ast_childcount(t->ast);
  t->fields = (reach_field_t*)calloc(t->field_count,
    sizeof(reach_field_t));

  printbuf_t* mangle = printbuf_new();
  printbuf(mangle, "%d", t->field_count);

  ast_t* child = ast_child(type);
  size_t index = 0;

  while(child != NULL)
  {
    t->fields[index].ast = ast_dup(child);
    t->fields[index].type = add_type(r, child, opt);
    printbuf(mangle, "%s", t->fields[index].type->mangle);
    index++;

    child = ast_sibling(child);
  }

  t->mangle = stringtab(mangle->m);
  printbuf_free(mangle);
  return t;
}
Esempio n. 7
0
LLVMValueRef gen_tuple(compile_t* c, ast_t* ast)
{
  ast_t* child = ast_child(ast);

  if(ast_sibling(child) == NULL)
    return gen_expr(c, child);

  ast_t* type = ast_type(ast);

  // If we contain TK_DONTCARE, we have no usable value.
  if(contains_dontcare(type))
    return GEN_NOTNEEDED;

  reach_type_t* t = reach_type(c->reach, type);
  LLVMValueRef tuple = LLVMGetUndef(t->primitive);
  int i = 0;

  while(child != NULL)
  {
    LLVMValueRef value = gen_expr(c, child);

    if(value == NULL)
      return NULL;

    // We'll have an undefined element if one of our source elements is a
    // variable declaration. This is ok, since the tuple value will never be
    // used.
    if(value == GEN_NOVALUE)
      return GEN_NOTNEEDED;

    tuple = LLVMBuildInsertValue(c->builder, tuple, value, i++, "");
    child = ast_sibling(child);
  }

  return tuple;
}