static type endpoint_type(endp p) { type t = NULL; if (p->args_node) { if (p->function) t = type_function_return_type(p->function->type); else if (p->interface) t = p->interface->type; } else { if (p->function) t = p->function->type; else if (p->interface) { t = p->interface->type; /* We don't normally include the generic parameters in the interface's type, but we do here to allow correct matching */ if (p->interface->gparms) t = make_generic_type(t, p->interface->gparms); } } return t; }
void set_interface_functions_gparms(environment fns, typelist gparms) { env_scanner scanif; const char *fnname; void *fnentry; env_scan(fns->id_env, &scanif); while (env_next(&scanif, &fnname, &fnentry)) { data_declaration fndecl = fnentry; /* Push generic args onto fn type and decl */ fndecl->gparms = gparms; fndecl->type = make_generic_type(fndecl->type, gparms); } }
Type* Namespace::Search(const string& name) { // an exact match wins Type* result = Find(name); if (result != NULL) { return result; } // try the class names // our language doesn't allow you to not specify outer classes // when referencing an inner class. that could be changed, and this // would be the place to do it, but I don't think the complexity in // scoping rules is worth it. int N = m_types.size(); for (int i=0; i<N; i++) { if (m_types[i]->Name() == name) { return m_types[i]; } } // we got to here and it's not a generic, give up if (name.find('<') == name.npos) { return NULL; } // remove any whitespace string normalized = normalize_generic(name); // find the part before the '<', find a generic for it ssize_t baseIndex = normalized.find('<'); string base(normalized.c_str(), baseIndex); const Generic* g = search_generic(base); if (g == NULL) { return NULL; } // For each of the args, do a recursive search on it. We don't allow // generics within generics like Java does, because we're really limiting // them to just built-in container classes, at least for now. Our syntax // ensures this right now as well. vector<Type*> args; size_t start = baseIndex + 1; size_t end = start; while (normalized[start] != '\0') { end = normalized.find(',', start); if (end == normalized.npos) { end = normalized.find('>', start); } string s(normalized.c_str()+start, end-start); Type* t = this->Search(s); if (t == NULL) { // maybe we should print a warning here? return NULL; } args.push_back(t); start = end+1; } // construct a GenericType, add it to our name set so they always get // the same object, and return it. result = make_generic_type(g->package, g->name, args); if (result == NULL) { return NULL; } this->Add(result); return this->Find(result->QualifiedName()); }