Modules |
Files |
Inheritance Tree |
Inheritance Graph |
Name Index |
Config
File: Synopsis/Parser/C++/syn/builder.cc
1| // Synopsis C++ Parser: builder.cc source file
2| // Implementation of the Builder class
3|
4| // $Id: builder.cc,v 1.44 2003/01/27 06:53:37 chalky Exp $
5| //
6| // This file is a part of Synopsis.
7| // Copyright (C) 2002 Stephen Davies
8| //
9| // Synopsis is free software; you can redistribute it and/or modify it
10| // under the terms of the GNU General Public License as published by
11| // the Free Software Foundation; either version 2 of the License, or
12| // (at your option) any later version.
13| //
14| // This program is distributed in the hope that it will be useful,
15| // but WITHOUT ANY WARRANTY; without even the implied warranty of
16| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17| // General Public License for more details.
18| //
19| // You should have received a copy of the GNU General Public License
20| // along with this program; if not, write to the Free Software
21| // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22| // 02111-1307, USA.
23|
24| // $Log: builder.cc,v $
25| // Revision 1.44 2003/01/27 06:53:37 chalky
26| // Added macro support for C++.
27| //
28| // Revision 1.43 2003/01/16 10:19:03 chalky
29| // Prevent true, false and null appearing in output
30| //
31| // Revision 1.42 2002/12/12 17:25:34 chalky
32| // Implemented Include support for C++ parser. A few other minor fixes.
33| //
34| // Revision 1.41 2002/12/09 08:27:34 chalky
35| // initialise m_file
36| //
37| // Revision 1.40 2002/12/09 04:01:00 chalky
38| // Added multiple file support to parsers, changed AST datastructure to handle
39| // new information, added a demo to demo/C++. AST Declarations now have a
40| // reference to a SourceFile (which includes a filename) instead of a filename.
41| //
42| // Revision 1.39 2002/11/17 12:11:43 chalky
43| // Reformatted all files with astyle --style=ansi, renamed fakegc.hh
44| //
45| //
46|
47| #include <map>
48| #include <typeinfo>
49| #include <sstream>
50| #include <algorithm>
51|
52| #include "builder.hh"
53| #include "type.hh"
54| #include "dict.hh"
55| #include "swalker.hh"
56| #include "scopeinfo.hh"
57| #include "lookup.hh"
58| #include "typeinfo.hh"
59|
60| // for debugging
61| #include "dumper.hh"
62| #include "strace.hh"
63|
64| //. Simplify names. Typically only used for accessing vectors and iterators
65| using namespace Types;
66| using namespace AST;
67|
68|
69| ScopedName extend(const ScopedName& name, const std::string& str)
70| {
71| ScopedName ret = name;
72| ret.push_back(str);
73| return ret;
74| }
75|
76|
77|
78| namespace
79| {
80|
81|
82| template <typename T>
83| class ostream_ptr_iterator
84| {
85| std::ostream* out;
86| const char* sep;
87| public:
88| ostream_ptr_iterator(std::ostream& o, const char* s) : out(&o), sep(s)
89| {}
90| ostream_ptr_iterator<T>& operator =(const T* value)
91| {
92| *out << *value;
93| if (sep)
94| *out << sep;
95| return *this;
96| }
97| ostream_ptr_iterator<T>& operator *()
98| {
99| return *this;
100| }
101| ostream_ptr_iterator<T>& operator ++()
102| {
103| return *this;
104| }
105| ostream_ptr_iterator<T>& operator ++(int)
106| {
107| return *this;
108| }
109| };
110| }
111|
112|
113|
114|
115| std::ostream& operator <<(std::ostream& out, const ScopedName& vec)
116| {
117| return out << join(vec, "::");
118| }
119|
120|
121|
122|
123|
124| struct Builder::Private
125| {
126| typedef std::map<AST::Scope*, ScopeInfo*> ScopeMap;
127| ScopeMap map;
128|
129|
130| typedef std::map<ScopedName, std::vector<AST::Reference> > RefMap;
131| RefMap refs;
132|
133|
134| Declaration::vector builtin_decls;
135| };
136|
137| //
138| // Class Builder
139| //
140|
141| Builder::Builder(AST::SourceFile* file)
142| {
143| m_file = NULL;
144| m_unique = 1;
145| m = new Private;
146| ScopedName name;
147| m_scope = m_global = new AST::Namespace(file, 0, "global", name);
148| ScopeInfo* global = find_info(m_global);
149| m_scopes.push_back(global);
150|
151| Types::Base* t_bool, *t_null;
152| AST::Declaration* decl;
153| global->dict->insert(create_base("char"));
154| global->dict->insert(t_bool = create_base("bool"));
155| global->dict->insert(create_base("short"));
156| global->dict->insert(create_base("int"));
157| global->dict->insert(create_base("long"));
158| global->dict->insert(create_base("unsigned"));
159| global->dict->insert(create_base("unsigned long"));
160| global->dict->insert(create_base("float"));
161| global->dict->insert(create_base("double"));
162| global->dict->insert(create_base("void"));
163| global->dict->insert(create_base("..."));
164| global->dict->insert(create_base("long long"));
165| global->dict->insert(create_base("long double"));
166| global->dict->insert(t_null = create_base("__null_t"));
167| // Add a variables for true
168| name.clear();
169| name.push_back("true");
170| decl = new AST::Variable(file, -1, "variable", name, t_bool, false);
171| global->dict->insert(decl);
172| m->builtin_decls.push_back(decl);
173| // Add a variable for false
174| name.clear();
175| name.push_back("false");
176| decl = new AST::Variable(file, -1, "variable", name, t_bool, false);
177| global->dict->insert(decl);
178| m->builtin_decls.push_back(decl);
179| // Add a variable for null pointer types (g++ #defines NULL to __null)
180| name.clear();
181| name.push_back("__null");
182| decl = new AST::Variable(file, -1, "variable", name, t_null, false);
183| global->dict->insert(decl);
184| m->builtin_decls.push_back(decl);
185|
186| // Create the Lookup helper
187| m_lookup = new Lookup(this);
188| }
189|
190| Builder::~Builder()
191| {
192| // TODO Delete all ...
193| delete m_lookup;
194| delete m;
195| }
196|
197| //. Finds or creates a cached Scope
198| ScopeInfo* Builder::find_info(AST::Scope* decl)
199| {
200| Private::ScopeMap::iterator iter = m->map.find(decl);
201| if (iter == m->map.end())
202| {
203| ScopeInfo* scope = new ScopeInfo(decl);
204| m->map.insert(Private::ScopeMap::value_type(decl, scope));
205| return scope;
206| }
207| return iter->second;
208| }
209|
210| void Builder::set_access(AST::Access axs)
211| {
212| m_scopes.back()->access = axs;
213| }
214|
215| void Builder::set_file(AST::SourceFile* file)
216| {
217| m_file = file;
218| }
219|
220| const Declaration::vector& Builder::builtin_decls() const
221| {
222| return m->builtin_decls;
223| }
224|
225| //
226| // AST Methods
227| //
228|
229| void Builder::add(AST::Declaration* decl, bool is_template)
230| {
231| ScopeInfo* scopeinfo;
232| AST::Declaration::vector* decls;
233| if (is_template)
234| {
235| scopeinfo = m_scopes[m_scopes.size()-2];
236| decls = &scopeinfo->scope_decl->declarations();
237| }
238| else
239| {
240| scopeinfo = m_scopes.back();
241| decls = &m_scope->declarations();
242| }
243| // Set access
244| decl->set_access(scopeinfo->access);
245| // Add to name dictionary
246| scopeinfo->dict->insert(decl);
247|
248| const std::string& scope_type = scopeinfo->scope_decl->type();
249| if (scope_type != "local" && scope_type != "function")
250| {
251| // Add declaration
252| decls->push_back(decl);
253| // Add to SourceFile
254| decl->file()->declarations().push_back(decl);
255| }
256| }
257|
258| void Builder::add(Types::Named* type)
259| {
260| // Add to name dictionary
261| m_scopes.back()->dict->insert(type);
262| }
263|
264| void Builder::add_macros(const std::vector<AST::Macro*>& macros)
265| {
266| std::vector<AST::Macro*>::const_iterator iter;
267| for (iter = macros.begin(); iter != macros.end(); iter++)
268| m_global->declarations().push_back(*iter);
269|
270| }
271|
272| AST::Namespace* Builder::start_namespace(const std::string& n, NamespaceType nstype)
273| {
274| std::string name = n, type_str;
275| AST::Namespace* ns = 0;
276| bool generated = false;
277| // Decide what to do based on the given namespace type
278| switch (nstype)
279| {
280| case NamespaceNamed:
281| type_str = "namespace";
282| {
283| Dictionary* dict = scopeinfo()->dict;
284| if (dict->has_key(name))
285| try
286| {
287| ns = Types::declared_cast<AST::Namespace>(dict->lookup(name));
288| }
289| catch (const Types::wrong_type_cast&)
290| { }
291| }
292| break;
293| case NamespaceAnon:
294| type_str = "module";
295| {
296| size_t slash_at = name.rfind('/');
297| if (slash_at != std::string::npos)
298| name.erase(0, slash_at + 1);
299| name = "{" + name + "}";
300| }
301| break;
302| case NamespaceUnique:
303| type_str = "local";
304| { // name is empty or the type. Encode it with a unique number
305| if (!name.size())
306| name = "ns";
307| int count = m_scopes.back()->getCount(name);
308| std::ostringstream buf;
309| buf << '`' << name;
310| if (count > 1)
311| buf << count;
312| name = buf.str();
313| }
314| break;
315| case NamespaceTemplate:
316| type_str = "template";
317| { // name is empty or the type. Encode it with a unique number
318| if (!name.size())
319| name = "template";
320| int count = m_scopes.back()->getCount(name);
321| std::ostringstream buf;
322| buf << '`' << name << count;
323| name = buf.str();
324| }
325| break;
326| }
327| // Create a new namespace object unless we already found one
328| if (ns == NULL)
329| {
330| generated = true;
331| // Create the namspace
332| if (nstype == NamespaceTemplate)
333| ns = new AST::Namespace(m_file, 0, type_str, m_scope->name());
334| else
335| {
336|
337| ScopedName ns_name = extend(m_scope->name(), name);
338| ns = new AST::Namespace(m_file, 0, type_str, ns_name);
339| add(ns);
340| }
341| }
342|
343| ScopeInfo* ns_info = find_info(ns);
344| ScopeInfo* current = m_scopes.back();
345| // For anon namespaces, we insert the anon ns into the parent search
346| if (nstype == NamespaceAnon && generated)
347| current->search.push_back(ns_info);
348| // Initialize search to same as parent scope if we generated a new NS
349| if (generated)
350| std::copy(current->search.begin(), current->search.end(),
351| std::back_inserter(ns_info->search));
352|
353| // Push stack
354| m_scopes.push_back(ns_info);
355| m_scope = ns;
356| return ns;
357| }
358|
359| void Builder::end_namespace()
360| {
361| // TODO: Check if it is a namespace...
362| m_scopes.pop_back();
363| m_scope = m_scopes.back()->scope_decl;
364| }
365|
366| // Utility class to recursively add base classes to given search
367| void Builder::add_class_bases(AST::Class* clas, ScopeSearch& search)
368| {
369| AST::Inheritance::vector::iterator inh_iter = clas->parents().begin();
370| while (inh_iter != clas->parents().end())
371| {
372| AST::Inheritance* inh = *inh_iter++;
373| Types::Type* type = inh->parent();
374| try
375| {
376| AST::Class* base = Types::declared_cast<AST::Class>(type);
377|
378| ScopeInfo* scope = find_info(base);
379| search.push_back(scope);
380| // Recursively add..
381| add_class_bases(base, search);
382| }
383| catch (const Types::wrong_type_cast&)
384| {
385| }
386| }
387| }
388|
389| void Builder::update_class_base_search()
390| {
391| ScopeInfo* scope = m_scopes.back();
392| AST::Class* clas = dynamic_cast<AST::Class*>(scope->scope_decl);
393| if (!clas)
394| return;
395| ScopeSearch search = scope->search;
396| ScopeSearch::iterator iter = search.begin();
397| scope->search.clear();
398| // Add the scope itself
399| scope->search.push_back(*iter++);
400| // Add base classes
401| add_class_bases(clas, scope->search);
402| // Add containing scopes, stored in search
403| while (iter != search.end())
404| scope->search.push_back(*iter++);
405| }
406|
407| AST::Class* Builder::start_class(int lineno, const std::string& type, const std::string& name, AST::Parameter::vector* templ_params)
408| {
409|
410| ScopedName class_name;
411| if (templ_params)
412| class_name = extend(m_scopes[m_scopes.size()-2]->scope_decl->name(), name);
413| else
414| class_name = extend(m_scope->name(), name);
415|
416| AST::Class* ns = new AST::Class(m_file, lineno, type, class_name);
417| // Create template type
418| if (templ_params)
419| {
420| Types::Template* templ = new Types::Template(class_name, ns, *templ_params);
421| ns->set_template_type(templ);
422| add(ns, true);
423| }
424| else
425| add(ns);
426|
427| ScopeInfo* ns_info = find_info(ns);
428| ns_info->access = (type == "struct" ? AST::Public : AST::Private);
429| std::copy(scopeinfo()->search.begin(), scopeinfo()->search.end(),
430| std::back_inserter(ns_info->search));
431| m_scopes.push_back(ns_info);
432| m_scope = ns;
433| return ns;
434| }
435|
436| // Declaration of a previously forward declared class (ie: must find and
437| // replace previous forward declaration in the appropriate place)
438| AST::Class* Builder::start_class(int lineno, const std::string& type, const ScopedName& names)
439| {
440|
441| Types::Named* named = m_lookup->lookupType(names);
442|
443| Types::Unknown* unknown = dynamic_cast<Types::Unknown*>(named);
444| if (!unknown)
445| {
446| Types::Declared* declared = dynamic_cast<Types::Declared*>(named);
447| if (!declared)
448| {
449| std::cerr << "Fatal: Qualified class name did not reference a declared type." << std::endl;
450| exit(1);
451| }
452| AST::Forward* forward = dynamic_cast<AST::Forward*>(declared->declaration());
453| if (!forward)
454| {
455| std::cerr << "Fatal: Qualified class name did not reference a forward declaration." << std::endl;
456| exit(1);
457| }
458| }
459|
460| AST::Class* ns = new AST::Class(m_file, lineno, type, named->name());
461|
462| ScopedName scope_name = names;
463| scope_name.pop_back();
464| Types::Declared* scope_type = dynamic_cast<Types::Declared*>(m_lookup->lookupType(scope_name));
465| if (!scope_type)
466| {
467| std::cerr << "Fatal: Qualified class name was not in a declaration." << std::endl;
468| exit(1);
469| }
470| AST::Scope* scope = dynamic_cast<AST::Scope*>(scope_type->declaration());
471| if (!scope)
472| {
473| std::cerr << "Fatal: Qualified class name was not in a scope." << std::endl;
474| exit(1);
475| }
476| // Set access
477| //decl->setAccess(m_scopes.back()->access);
478| // Add declaration
479| scope->declarations().push_back(ns);
480|
481| ScopeInfo* scope_info = find_info(scope);
482| scope_info->dict->insert(ns);
483|
484| ScopeInfo* ns_info = find_info(ns);
485| ns_info->access = (type == "struct" ? AST::Public : AST::Private);
486| std::copy(scope_info->search.begin(), scope_info->search.end(),
487| std::back_inserter(ns_info->search));
488| m_scopes.push_back(ns_info);
489| m_scope = ns;
490| return ns;
491| }
492|
493| void Builder::end_class()
494| {
495| // Check if it is a class...
496| m_scopes.pop_back();
497| m_scope = m_scopes.back()->scope_decl;
498| }
499|
500| AST::Namespace* Builder::start_template()
501| {
502| return start_namespace("", NamespaceTemplate);
503| }
504|
505| void Builder::end_template()
506| {
507| end_namespace();
508| }
509|
510|
511| //. Start function impl scope
512| void Builder::start_function_impl(const ScopedName& name)
513| {
514| STrace trace("Builder::start_function_impl");
515|
516| AST::Namespace* ns = new AST::Namespace(m_file, 0, "function", name);
517| ScopeInfo* ns_info = find_info(ns);
518| ScopeInfo* scope_info;
519| if (name.size() > 1)
520| {
521|
522| std::vector<std::string> scope_name = name;
523| scope_name.pop_back();
524| scope_name.insert(scope_name.begin(), "");
525| Types::Declared* scope_type = dynamic_cast<Types::Declared*>(m_lookup->lookupType(scope_name));
526| if (!scope_type)
527| {
528| throw ERROR("Warning: Qualified func name was not in a declaration. Parent scope is:" << scope_name);
529| }
530| AST::Scope* scope = dynamic_cast<AST::Scope*>(scope_type->declaration());
531| if (!scope)
532| {
533| throw ERROR("Warning: Qualified func name was not in a scope.");
534| }
535| scope_info = find_info(scope);
536| }
537| else
538| {
539| scope_info = find_info(m_global);
540| }
541| // Add to name dictionary TODO: this is for debugging only!
542| scope_info->dict->insert(ns);
543| // Push stack. Search is this Class plus enclosing scopes. bases added later
544| std::copy(scope_info->search.begin(), scope_info->search.end(),
545| std::back_inserter(ns_info->search));
546|
547| m_scopes.push_back(ns_info);
548| m_scope = ns;
549| }
550|
551| //. End function impl scope
552| void Builder::end_function_impl()
553| {
554| m_scopes.pop_back();
555| m_scope = m_scopes.back()->scope_decl;
556| }
557|
558| //. Add an function
559| AST::Function* Builder::add_function(int line, const std::string& name,
560| const std::vector<std::string>& premod, Types::Type* ret,
561| const std::string& realname, AST::Parameter::vector* templ_params)
562| {
563|
564| AST::Scope* parent_scope;
565| if (templ_params)
566| parent_scope = m_scopes[m_scopes.size()-2]->scope_decl;
567| else
568| parent_scope = m_scope;
569|
570|
571| ScopedName func_name = extend(parent_scope->name(), name);
572|
573|
574|
575| AST::Function* func;
576| if (dynamic_cast<AST::Class*>(parent_scope))
577| func = new AST::Operation(m_file, line, "member function", func_name, premod, ret, realname);
578| else
579| func = new AST::Function(m_file, line, "function", func_name, premod, ret, realname);
580|
581| // Create template type
582| if (templ_params)
583| {
584| Types::Template* templ = new Types::Template(func_name, func, *templ_params);
585| func->set_template_type(templ);
586| add(func, true);
587| }
588| else
589| add(func);
590| return func;
591| }
592|
593| //. Add a variable
594| AST::Variable* Builder::add_variable(int line, const std::string& name, Types::Type* vtype, bool constr, const std::string& type)
595| {
596|
597| ScopedName scope = m_scope->name();
598| scope.push_back(name);
599| AST::Variable* var = new AST::Variable(m_file, line, type, scope, vtype, constr);
600| add(var);
601| return var;
602| }
603|
604| void Builder::add_this_variable()
605| {
606|
607| AST::Scope* func_ns = m_scope;
608| ScopedName name = func_ns->name();
609| name.pop_back();
610| name.insert(name.begin(), std::string());
611| Types::Named* clas_named = m_lookup->lookupType(name, false);
612| AST::Class* clas;
613| try
614| {
615| clas = Types::declared_cast<AST::Class>(clas_named);
616| }
617| catch (const Types::wrong_type_cast& )
618| // Not in a method -- so dont add a 'this'
619| {
620| return;
621| }
622|
623|
624| Types::Type::Mods pre, post;
625| post.push_back("*");
626| Types::Modifier* t_this = new Types::Modifier(clas->declared(), pre, post);
627| add_variable(-1, "this", t_this, false, "this");
628| }
629|
630| //. Add a typedef
631| AST::Typedef* Builder::add_typedef(int line, const std::string& name, Types::Type* alias, bool constr)
632| {
633|
634| ScopedName scoped_name = extend(m_scope->name(), name);
635|
636| AST::Typedef* tdef = new AST::Typedef(m_file, line, "typedef", scoped_name, alias, constr);
637| add(tdef);
638| return tdef;
639| }
640|
641| //. Add an enumerator
642| AST::Enumerator* Builder::add_enumerator(int line, const std::string& name, const std::string& value)
643| {
644| ScopedName scoped_name = extend(m_scope->name(), name);
645| AST::Enumerator* enumor = new AST::Enumerator(m_file, line, "enumerator", scoped_name, value);
646| add(enumor->declared());
647| return enumor;
648| }
649|
650| //. Add an enum
651| AST::Enum* Builder::add_enum(int line, const std::string& name, const std::vector<AST::Enumerator*>& enumors)
652| {
653| ScopedName scoped_name = extend(m_scope->name(), name);
654| AST::Enum* theEnum = new AST::Enum(m_file, line, "enum", scoped_name);
655| theEnum->enumerators() = enumors;
656| add(theEnum);
657| return theEnum;
658| }
659|
660| //. Add tail comment
661| AST::Declaration* Builder::add_tail_comment(int line)
662| {
663| ScopedName name;
664| name.push_back("dummy");
665| AST::Declaration* decl = new AST::Declaration(m_file, line, "dummy", name);
666| add(decl);
667| return decl;
668| }
669|
670|
671|
672| class InheritanceAdder
673| {
674| std::list<AST::Class*>& open_list;
675| public:
676| InheritanceAdder(std::list<AST::Class*>& l) : open_list(l)
677| {}
678| InheritanceAdder(const InheritanceAdder& i) : open_list(i.open_list)
679| {}
680| void operator() (AST::Inheritance* i)
681| {
682| try
683| {
684| open_list.push_back(Types::declared_cast<AST::Class>(i->parent()));
685| }
686| catch (const Types::wrong_type_cast&)
687| {
688| }
689| }
690| };
691|
692|
693| //. Maps a scoped name into a vector of scopes and the final type. Returns
694| //. true on success.
695| bool Builder::mapName(const ScopedName& names, std::vector<AST::Scope*>& o_scopes, Types::Named*& o_type)
696| {
697| STrace trace("Builder::mapName");
698| AST::Scope* ast_scope = m_global;
699| ScopedName::const_iterator iter = names.begin();
700| ScopedName::const_iterator last = names.end();
701| last--;
702| ScopedName scoped_name;
703|
704| // Start scope name at global level
705| scoped_name.push_back("");
706|
707| // Sanity check
708| if (iter == names.end())
709| return false;
710|
711| // Loop through all containing scopes
712| while (iter != last)
713| {
714| //const std::string& name = *iter++;
715| scoped_name.push_back(*iter++);
716| Types::Named* type = m_lookup->lookupType(scoped_name);
717| if (!type)
718| {
719| LOG("Warning: failed to lookup " << scoped_name << " in global scope");
720| return false;
721| }
722| try
723| {
724| ast_scope = Types::declared_cast<AST::Scope>(type);
725| }
726| catch (const Types::wrong_type_cast&)
727| {
728| LOG("Warning: looked up scope wasnt a scope!" << scoped_name);
729| return false;
730| }
731| o_scopes.push_back(ast_scope);
732| }
733|
734| // iter now == last, which can be any type
735| scoped_name.push_back(*iter);
736| Types::Named* type = m_lookup->lookupType(scoped_name, true);
737| if (!type)
738| {
739| //find_info(ast_scope)->dict->dump();
740| LOG("\nWarning: final type lookup wasn't found!" << *iter);
741| return false;
742| }
743|
744| o_type = type;
745| return true;
746| }
747|
748|
749| Types::Unknown* Builder::create_unknown(const std::string& name)
750| {
751|
752| ScopedName u_name = extend(m_scope->name(), name);
753| Types::Unknown* unknown = new Types::Unknown(u_name);
754| return unknown;
755| }
756|
757| Types::Unknown* Builder::add_unknown(const std::string& name)
758| {
759| if (m_scopes.back()->dict->has_key(name) == false)
760| add(create_unknown(name));
761| return NULL;
762| }
763|
764| AST::Forward* Builder::add_forward(int lineno, const std::string& name, AST::Parameter::vector* templ_params)
765| {
766| if (!templ_params)
767| {
768| add_unknown(name);
769| return NULL;
770| }
771|
772| ScopeInfo* parent_scope = m_scopes[m_scopes.size()-2];
773| ScopedName scoped_name = extend(parent_scope->scope_decl->name(), name);
774| if (parent_scope->dict->has_key(name) == true)
775| return NULL;
776| AST::Forward* forward = new AST::Forward(m_file, lineno, "forward", scoped_name);
777| Types::Template* templ = new Types::Template(scoped_name, NULL, *templ_params);
778| forward->set_template_type(templ);
779| add(forward, true);
780| return NULL;
781| }
782|
783| Types::Base* Builder::create_base(const std::string& name)
784| {
785| return new Types::Base(extend(m_scope->name(), name));
786| }
787|
788| Types::Dependent* Builder::create_dependent(const std::string& name)
789| {
790| return new Types::Dependent(extend(m_scope->name(), name));
791| }
792|
793| std::string Builder::dump_search(ScopeInfo* scope)
794| {
795| ScopeSearch& search = scope->search;
796| std::ostringstream buf;
797| buf << "Search for ";
798| if (scope->scope_decl->name().size() == 0)
799| buf << "global";
800| else
801| buf << m_scope->name();
802| buf << " is now: ";
803| ScopeSearch::iterator iter = search.begin();
804| while (iter != search.end())
805| {
806| buf << (iter==search.begin() ? "" : ", ");
807| const ScopedName& name = (*iter)->scope_decl->name();
808| if (name.size())
809| if ( (*iter)->is_using )
810| buf << "(" << name << ")";
811| else
812| buf << name;
813| else
814| buf << "global";
815| ++iter;
816| }
817| //buf << std::ends;
818| return buf.str();
819| }
820|
821|
822| class Builder::EqualScope
823| {
824| AST::Scope* target;
825| public:
826| EqualScope(ScopeInfo* t)
827| {
828| target = t->scope_decl;
829| }
830| bool operator()(ScopeInfo* s)
831| {
832| return s->scope_decl == target;
833| }
834| };
835|
836| void Builder::do_add_using_namespace(ScopeInfo* target, ScopeInfo* scope)
837| {
838| STrace trace("Builder::addUsingNamespace");
839|
840|
841| ScopeSearch& uses = scope->using_scopes;
842| if (std::find_if(uses.begin(), uses.end(), EqualScope(target)) != uses.end())
843| // Already using
844| return;
845| // Else add it
846| scope->using_scopes.push_back(target);
847| target->used_by.push_back(scope);
848|
849| ScopedName& target_name = target->scope_decl->name();
850|
851|
852|
853|
854| ScopeSearch& search = scope->search;
855| LOG(dump_search(scope));
856| ScopeSearch::iterator iter = search.end();
857|
858| --iter;
859| while (iter != search.begin())
860| {
861|
862| --iter;
863| ScopedName& search_name = (*iter)->scope_decl->name();
864| if (target_name.size() < search_name.size())
865| // Search is more nested than the target
866| break;
867| if (search_name.size() < 1)
868| // Global NS..
869| continue;
870| if (target_name[search_name.size()-1] != search_name.back())
871|
872| break;
873| }
874| // Move back to last which was common, so we can insert before it
875| if (*iter != search.back() && iter != search.begin())
876| iter++;
877|
878|
879|
880| ScopeInfo* new_scope = new ScopeInfo(target);
881| search.insert(iter, new_scope);
882|
883| LOG(dump_search(scope));
884|
885|
886| ScopeSearch used_by_copy = scope->used_by;
887| iter = used_by_copy.begin();
888| while (iter != used_by_copy.end())
889| do_add_using_namespace(target, *iter++);
890| }
891|
892| // Add a namespace using declaration.
893| void Builder::add_using_namespace(Types::Named* type)
894| {
895| STrace trace("Builder::usingNamespace");
896| AST::Scope* ast_scope = Types::declared_cast<AST::Scope>(type);
897| ScopeInfo* target = find_info(ast_scope);
898| do_add_using_namespace(target, m_scopes.back());
899| }
900|
901|
902| // Add a namespace alias using declaration.
903| void Builder::add_aliased_using_namespace(Types::Named* type, const std::string& alias)
904| {
905| STrace trace("Builder::usingNamespace");
906|
907|
908| AST::Namespace* ns = Types::declared_cast<AST::Namespace>(type);
909|
910|
911| ScopedName new_name = extend(m_scope->name(), alias);
912| Types::Declared* declared = new Types::Declared(new_name, ns);
913|
914| // Add to current scope
915| add(declared);
916| }
917|
918| // Add a using declaration.
919| void Builder::add_using_declaration(Types::Named* type)
920| {
921| // Add it to the current scope
922| add(type);
923| }
924|
925|