00001
00002
00003 #include "template.h"
00004 #include "template_i.h"
00005
00006
00007 #line 38 "template.cpp"
00008
00009
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
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
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
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
00283
00284
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
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
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
00348 if (storagespec && (storagespec->Eq("friend") || storagespec->Car()->Eq("friend"))) {
00349
00350 return 0;
00351 }
00352
00353
00354 HACK_EXPLICIT(typespec, storagespec);
00355
00356
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
00376 Ptree* declared_name = get_name_from_declarator(decl, current_scope);
00377 if (!declared_name)
00378 compile_error("unnamed template?");
00379
00380
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
00392
00393 if (!Symbol_name::is_qualified_name(p)) {
00394
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
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
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
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
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 }