static void add_method(reachable_method_stack_t** s, reachable_type_t* t, const char* name, ast_t* typeargs) { reachable_method_name_t* n = reach_method_name(t, name); if(n == NULL) { n = POOL_ALLOC(reachable_method_name_t); n->name = name; reachable_methods_init(&n->r_methods, 0); reachable_method_names_put(&t->methods, n); } add_rmethod(s, t, n, typeargs); // Add to subtypes if we're an interface or trait. ast_t* def = (ast_t*)ast_data(t->type); switch(ast_id(def)) { case TK_INTERFACE: case TK_TRAIT: { size_t i = HASHMAP_BEGIN; reachable_type_t* t2; while((t2 = reachable_type_cache_next(&t->subtypes, &i)) != NULL) add_method(s, t2, name, typeargs); break; } default: {} } }
static void add_rmethod_to_subtype(reach_t* r, reach_type_t* t, reach_method_name_t* n, reach_method_t* m, pass_opt_t* opt) { // Add the method to the type if it isn't already there. reach_method_name_t* n2 = add_method_name(t, n->name); add_rmethod(r, t, n2, m->cap, m->typeargs, opt); // Add this mangling to the type if it isn't already there. reach_method_t* mangled = reach_mangled_get(&n2->r_mangled, m); if(mangled != NULL) return; mangled = POOL_ALLOC(reach_method_t); memset(mangled, 0, sizeof(reach_method_t)); mangled->name = m->name; mangled->mangled_name = m->mangled_name; mangled->full_name = make_full_name(t, mangled); mangled->cap = m->cap; mangled->r_fun = ast_dup(m->r_fun); mangled->typeargs = ast_dup(m->typeargs); mangled->forwarding = true; mangled->param_count = m->param_count; mangled->params = (reach_param_t*)ponyint_pool_alloc_size( mangled->param_count * sizeof(reach_param_t)); memcpy(mangled->params, m->params, m->param_count * sizeof(reach_param_t)); mangled->result = m->result; // Add to the mangled table only. reach_mangled_put(&n2->r_mangled, mangled); }
static void reachable_method(reach_t* r, ast_t* type, const char* name, ast_t* typeargs, pass_opt_t* opt) { reach_type_t* t = add_type(r, type, opt); reach_method_name_t* n = add_method_name(t, name); reach_method_t* m = add_rmethod(r, t, n, n->cap, typeargs, opt); if((n->id == TK_FUN) && ((n->cap == TK_BOX) || (n->cap == TK_TAG))) { // TODO: if it doesn't use this-> in a constructor, we could reuse the // function, which means always reuse in a fun tag bool subordinate = (n->cap == TK_TAG); reach_method_t* m2; if(t->underlying != TK_PRIMITIVE) { m2 = add_rmethod(r, t, n, TK_REF, typeargs, opt); if(subordinate) { m2->intrinsic = true; m->subordinate = m2; m = m2; } } m2 = add_rmethod(r, t, n, TK_VAL, typeargs, opt); if(subordinate) { m2->intrinsic = true; m->subordinate = m2; m = m2; } if(n->cap == TK_TAG) { m2 = add_rmethod(r, t, n, TK_BOX, typeargs, opt); m2->intrinsic = true; m->subordinate = m2; m = m2; } } }