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; }
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; }
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; }
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; }
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; }
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; }
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; }