Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

template.cc

Go to the documentation of this file.
00001 // AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
00002 
00003 #include "template.h"
00004 #include "template_i.h"
00005 
00006 
00007 #line 38 "template.cpp"
00008 
00009 /***************************** Template_thing ****************************/
00010 
00011 
00012 Template_thing::Template_thing()
00013     : tree(0)
00014 { }
00015 
00016 #line 45 "template.cpp"
00017 
00018 void
00019 Template_thing::add_args_from_ptree(Ptree* list, Abstract_scope* scope)
00020 {
00021     for (Ptree* p = list; p != 0; (p = p->Cdr()) && (p = p->Cdr())) {
00022         Ptree* ele = p->Car();
00023         if (ele->Car()->IsLeaf() && (ele->Car()->Eq("class") || ele->Car()->Eq("typename"))) {
00024             /* [class NAME] */
00025             assert(ele->Second());
00026             assert(ele->Second()->IsLeaf());
00027             add_type_arg(ele->Second()->ToString());
00028         } else {
00029             compile_error("invalid template argument");
00030         }
00031     }
00032 }
00033 
00034 #line 61 "template.cpp"
00035 
00036 void
00037 Template_thing::add_type_arg(std::string name)
00038 {
00039     arg_names.push_back(name);   
00040 }
00041 
00042 #line 67 "template.cpp"
00043 
00044 int
00045 Template_thing::get_num_args() const
00046 {
00047     return arg_names.size();
00048 }
00049 
00050 #line 73 "template.cpp"
00051 
00052 std::string
00053 Template_thing::get_type_arg(int i) const
00054 {
00055     assert(i >= 0 && i < arg_names.size());
00056     return arg_names[i];
00057 }
00058 
00059 #line 80 "template.cpp"
00060 
00061 void
00062 Template_thing::set_tree(Ptree* tree)
00063 {
00064     this->tree = tree;
00065 }
00066 
00067 #line 86 "template.cpp"
00068 
00069 Ptree*
00070 Template_thing::get_tree() const
00071 {
00072     return tree;
00073 }
00074 
00075 #line 100 "template.cpp"
00076 
00077 
00078 Template_spec::Template_spec(Type_vector args, Class_symbol* defn)
00079     : args(args), defn(defn), code(0)
00080 { }
00081 
00082 #line 105 "template.cpp"
00083 
00084 
00085 Template_spec::~Template_spec()
00086 { }
00087 
00088 #line 109 "template.cpp"
00089 
00090 void
00091 Template_spec::add_code(Ptree* tree)
00092 {
00093     if (!tree)
00094         return;
00095     assert(!tree->IsLeaf());
00096     code = Ptree::Append(code, tree);
00097 }
00098 
00099 #line 118 "template.cpp"
00100 
00101 bool
00102 Template_spec::matches(const Type_vector& rhs) const
00103 {
00104     if (args.size() != rhs.size())
00105         return false;
00106     for (Type_vector::size_type i = 0; i < args.size(); ++i)
00107         if (rhs[i] != args[i])
00108             return false;
00109     return true;
00110 }
00111 
00112 #line 152 "template.cpp"
00113 
00114 
00115 Template_defn_scope::Template_defn_scope(Abstract_scope* parent,
00116                                          const Template_thing* arg_names,
00117                                          const Type_vector* arg_types,
00118                                          std::string class_name,
00119                                          std::string tpl_name)
00120     : Abstract_scope(parent)
00121 {
00122     assert(arg_names);
00123     assert(arg_types);
00124     assert(arg_types->size() == arg_names->get_num_args());
00125 
00126     for (unsigned i = 0; i < arg_types->size(); ++i)
00127         things[arg_names->get_type_arg(i)] = new Typedef_symbol((*arg_types)[i]);
00128 }
00129 
00130 #line 168 "template.cpp"
00131 
00132 
00133 Template_defn_scope::~Template_defn_scope()
00134 { }
00135 
00136 #line 172 "template.cpp"
00137 
00138 Symbol_pair
00139 Template_defn_scope::lookup_here(std::string name, bool for_decl)
00140 {
00141     Typedef_symbol* s = things[name];
00142     return Symbol_pair(s, 0);
00143 }
00144 
00145 #line 179 "template.cpp"
00146 
00147 Variable_symbol*
00148 Template_defn_scope::add_variable(Storage_class_specifier s, Type t, Ptree* n,
00149                                   Ptree* i, Ptree* b)
00150 {
00151     assert(!"add_variable");
00152 }
00153 
00154 #line 186 "template.cpp"
00155 
00156 Function_signature*
00157 Template_defn_scope::add_function_decl(Storage_class_specifier s, Function_specifier_set f,
00158                                        Type t, const Symbol_name& n)
00159 {
00160     return get_parent()->add_function_decl(s, f, t, n);
00161 }
00162 
00163 #line 193 "template.cpp"
00164 
00165 void
00166 Template_defn_scope::add_function_implementation(Function_signature* sig, Block_scope* sco, Ptree* b, Ptree* i)
00167 {
00168     get_parent()->add_function_implementation(sig, sco, b, i);
00169 }
00170 
00171 #line 199 "template.cpp"
00172 
00173 void
00174 Template_defn_scope::add_symbol(std::string name, Symbol* s)
00175 {
00176     assert(!"add_symbol");
00177 }
00178 
00179 #line 205 "template.cpp"
00180 
00181 std::string
00182 Template_defn_scope::get_unique_name(std::string name)
00183 {
00184     assert(!"get_unique_name");
00185 }
00186 
00187 #line 211 "template.cpp"
00188 
00189 Type
00190 Template_defn_scope::get_this_type() const
00191 {
00192     assert(!"get_this_type");
00193 }
00194 
00195 #line 224 "template.cpp"
00196 
00197 
00198 Template_class_adder::Template_class_adder(std::string mangled_name, std::string real_name)
00199     : mangled_name(mangled_name), real_name(real_name)
00200 { }
00201 
00202 #line 229 "template.cpp"
00203 
00204 Class_symbol*
00205 Template_class_adder::add_class(Abstract_scope* scope, std::string name, Symbol::Kind k)
00206 {
00207     assert(dynamic_cast<Template_defn_scope*>(scope));
00208 
00209     Class_symbol* csym = new Class_symbol(k, scope, real_name);
00210     csym->set_status(Symbol::st_Declared);
00211     scope->get_parent()->add_symbol(mangled_name, csym);
00212     return csym;
00213 }
00214 
00215 #line 240 "template.cpp"
00216 
00217 /************************* Template_class_symbol *************************/
00218 
00219 
00220 Template_class_symbol::Template_class_symbol(Abstract_scope* scope)
00221     : definition(0), defined_in_scope(scope)
00222 {
00223     set_status(st_Declared);
00224 }
00225 
00226 #line 249 "template.cpp"
00227 
00228 
00229 Template_class_symbol::~Template_class_symbol()
00230 { }
00231 
00232 #line 253 "template.cpp"
00233 
00234 Symbol::Kind
00235 Template_class_symbol::get_kind() const
00236 {
00237     return k_ClassTemplate;
00238 }
00239 
00240 #line 259 "template.cpp"
00241 
00242 void
00243 Template_class_symbol::set_definition(Template_thing* def)
00244 {
00245     assert(!is_defined());
00246     definition = def;
00247     set_status(st_Defined);
00248 }
00249 
00250 #line 267 "template.cpp"
00251 
00252 void
00253 Template_class_symbol::add_member(Template_thing* def)
00254 {
00255     members.push_back(def);
00256 }
00257 
00258 #line 273 "template.cpp"
00259 
00260 Class_symbol*
00261 Template_class_symbol::get_specialisation(const Type_vector& types)
00262 {
00263     for (unsigned i = 0; i < special.size(); ++i)
00264         if (special[i]->matches(types))
00265             return special[i]->get_class();
00266 
00267     if (!definition)
00268         compile_error("Requesting specialisation of undefined template class");
00269 
00270     std::string mangle = Symbol_name::get_mangled_template_name(get_basename(), types);
00271 
00272     /* We have to make a new specialisation. Let's boogie. */
00273     Template_defn_scope* tds = new Template_defn_scope(defined_in_scope,
00274                                                        definition,
00275                                                        &types,
00276                                                        get_basename(),
00277                                                        mangle);
00278     Template_class_adder adder(mangle, get_basename());
00279     Class_symbol* csym = parse_class(definition->get_tree(), tds, 0, false, adder);
00280     Template_spec* spec = new Template_spec(types, csym);
00281     special.push_back(spec);
00282     // std::cout << " ... done class\n";
00283 
00284     /* process all members we have so far */
00285     Ptree* code = 0;
00286     for (unsigned i = 0; i < members.size(); ++i) {
00287         tds = new Template_defn_scope(defined_in_scope, members[i], &types, get_basename(), mangle);
00288         Annotator anno(&Source::instance(), tds);
00289         anno.visit_and_catch(members[i]->get_tree());
00290         spec->add_code(anno.get_output());
00291     }
00292 
00293     return csym;
00294 }
00295 
00296 #line 309 "template.cpp"
00297 
00298 Class_symbol*
00299 Template_class_symbol::get_specialisation_from_ptree(Ptree* tree, Abstract_scope* sco)
00300 {
00301     Type_vector tv;
00302     parse_template_arg_list(tree, sco, &tv);
00303     return get_specialisation(tv);
00304 }
00305 
00306 #line 326 "template.cpp"
00307 
00308 
00309 Template_visitor::Template_visitor(Source* s, Abstract_scope* scope, const Template_thing& args)
00310     : Paranoid_visitor<Tpl_RT>(s),
00311       Ptree_visitor<Tpl_RT>(s), current_scope(scope),
00312       args(args)
00313 { }
00314 
00315 #line 333 "template.cpp"
00316 
00317 Tpl_RT
00318 Template_visitor::visit_type_declaration(Ptree* storagespec, Ptree* typespec)
00319 {
00320     if (storagespec && (storagespec->Eq("friend") || storagespec->Car()->Eq("friend"))) {
00321         // FIXME? I think we can ignore friends because we don't do protection
00322         return 0;
00323     }
00324 
00325     if (storagespec)
00326         bogus_ptree_error("type declarations may not have storage specifiers", storagespec);
00327 
00328     if (!typespec) {
00329         compile_warning("neat idea: template `;'", storagespec);
00330     } else {
00331         /* "template<class T> class X */
00332         declare_class(typespec);
00333     }
00334     return 0;
00335 }
00336 
00337 #line 353 "template.cpp"
00338 
00344 Tpl_RT
00345 Template_visitor::visit_name_declaration(Ptree* storagespec, Ptree* typespec, Ptree* decllist)
00346 {
00347     /* "template<...> friend" */
00348     if (storagespec && (storagespec->Eq("friend") || storagespec->Car()->Eq("friend"))) {
00349         // FIXME? I think we can ignore friends because we don't do protection
00350         return 0;
00351     }
00352 
00353     // HACK around OpenC++ limitations:
00354     HACK_EXPLICIT(typespec, storagespec);
00355 
00356     /* template<...> TYPE DECLARATOR... */
00357     for (Ptree* p = decllist; p != 0; (p = p->Cdr()) && (p = p->Cdr())) {
00358         Ptree* decl = p->Car();
00359         Ptree* declared_name = get_name_from_declarator(decl, current_scope);
00360         if (!declared_name)
00361             compile_error("unnamed template?");
00362         declare_name(declared_name, new PtreeDeclaration(storagespec, Ptree::List(typespec, decl)));
00363     }
00364     return 0;
00365 }
00366 
00367 #line 381 "template.cpp"
00368 
00369 Tpl_RT
00370 Template_visitor::visit_function(Ptree* storagespec, Ptree* typespec,
00371                                  PtreeDeclarator* decl, PtreeBlock* block)
00372 {
00373     HACK_EXPLICIT(typespec, storagespec);
00374 
00375     /* template<...> TYPE DECLARATOR BLOCK */
00376     Ptree* declared_name = get_name_from_declarator(decl, current_scope);
00377     if (!declared_name)
00378         compile_error("unnamed template?");
00379 
00380     // FIXME? Michael dissects it and I build it again
00381     declare_name(declared_name, new PtreeDeclaration(storagespec,
00382                                                      Ptree::List(typespec, decl, block)));
00383     return 0;
00384 }
00385 
00386 #line 398 "template.cpp"
00387 
00388 void
00389 Template_visitor::declare_name(Ptree* p, Ptree* tree)
00390 {
00391     /* Figure out which template this goes into */
00392     /* FIXME? Code duplication from Symbol_name */
00393     if (!Symbol_name::is_qualified_name(p)) {
00394         // "template<class T> void foo()"
00395         compile_error("unqualified name in template definition?");
00396     }
00397 
00398     bool look_global = true;
00399     Abstract_scope* scope = current_scope;
00400     if (p->Car()->Eq("::")) {
00401         scope = scope->get_global_scope();
00402         look_global = false;
00403         p = p->Cdr();
00404     }
00405 
00406     while (p && p->Cdr()) {
00407         Ptree* ele = p->Car();
00408         if (ele->IsLeaf()) {
00409             /* class or namespace name */
00410             if (look_global) {
00411                 Abstract_scope* s;
00412                 while (scope && !(s = Symbol_name::lookup_symbol_in_scope(ele, scope, scope)))
00413                     scope = scope->get_parent();
00414                 if (!scope)
00415                     compile_error("no such scope " + std::string(ele->ToString()));
00416                 scope = s;
00417             } else {
00418                 scope = Symbol_name::lookup_symbol_in_scope(ele, scope, scope);
00419                 if (!scope)
00420                     compile_error("no such scope " + std::string(ele->ToString()));
00421             }
00422             look_global = false;
00423             p = p->Cdr();
00424             expect_ptree(p->Car(), "::");
00425             p = p->Cdr();
00426         } else {
00427             /* template name */
00428             std::string tpl_name = ele->First()->ToString();
00429             Template_class_symbol* tcs;
00430             Symbol_pair sp;
00431             if (look_global)
00432                 sp = scope->lookup_unqualified(tpl_name);
00433             else
00434                 sp = scope->lookup_here(tpl_name, false);
00435             if (!sp || !(tcs = dynamic_cast<Template_class_symbol*>(sp.tag)))
00436                 compile_error("no such template " + tpl_name);
00437 
00438             /* we know that it's a template. Add it to the class. */
00439             Template_thing* thing = new Template_thing(args);
00440             thing->set_tree(tree);
00441             tcs->add_member(thing);
00442             break;
00443         }
00444     }
00445     if (!p)
00446         // happens for template functions
00447         compile_error("template without a template expression in name");
00448 }
00449 
00450 #line 460 "template.cpp"
00451 
00452 void
00453 Template_visitor::declare_class(Ptree* class_tree)
00454 {
00455     Ptree* name = class_tree->Second();
00456     if (!name || (!name->IsLeaf() && !name->First()))
00457         compile_error("nameless template not allowed");
00458     
00459     Symbol_name sym_name(name, current_scope, false);
00460     Symbol_pair p = (sym_name.is_qualified()
00461                      ? sym_name.lookup_for_decl()
00462                      : current_scope->lookup_here(sym_name.get_name(), true));
00463     Template_class_symbol* tcs;
00464     if (sym_name.is_qualified())
00465         compile_error("template specialisation not supported");
00466     if (!p) {
00467         if (sym_name.is_qualified())
00468             compile_error("can't define scoped name");
00469         tcs = new Template_class_symbol(current_scope);
00470         current_scope->add_symbol(sym_name.get_name(), tcs);
00471     } else {
00472         tcs = dynamic_cast<Template_class_symbol*>(p.tag);
00473         if (!tcs)
00474             compile_error(sym_name.get_name() + " is not a class template");
00475     }
00476     if (class_tree->Length() > 2) {
00477         if (tcs->is_defined())
00478             compile_error(tcs->get_name() + " already has a definition");
00479 
00480         Template_thing* tt = new Template_thing(args);
00481         tt->set_tree(class_tree);
00482         tcs->set_definition(tt);
00483     }
00484 }
00485 
00486 #line 494 "template.cpp"
00487 
00488 void
00489 visit_template(Ptree* arglist, Ptree* content, Abstract_scope* scope)
00490 {
00491     Template_thing tt;
00492     tt.add_args_from_ptree(arglist, scope);
00493     
00494     Template_visitor tvis(&Source::instance(), scope, tt);
00495     tvis.visit(content);
00496 }
00497 
00498 #line 504 "template.cpp"
00499 
00500 void
00501 parse_template_arg_list(Ptree* arglist, Abstract_scope* scope, Type_vector* output)
00502 {
00503     expect_ptree(arglist->Car(), '<');
00504     expect_ptree(arglist->Third(), '>');
00505 
00506     for (Ptree* p = arglist->Second(); p != 0; (p = p->Cdr()) && (p = p->Cdr())) {
00507         Ptree* typ = p->Car();
00508         Type t = parse_type(typ->Car(), scope, 0, false);
00509         if (!parse_abstract_declarator(typ->Second(), scope, &t))
00510             compile_error("invalid template parameter");
00511         output->push_back(t);
00512     }
00513 }

Generated on Mon Feb 10 17:32:57 2003 for VFiasco Semantics Compiler by doxygen1.2.15