File: Synopsis/Processors/Linker.py 1
2
3
4
5
6
7
8
9from Synopsis.Processor import Composite, Parameter
10from Synopsis import ASG
11from Synopsis.QualifiedName import *
12from Synopsis.Processors import TemplateLinker
13
14class Linker(Composite, ASG.Visitor):
15 """Visitor that removes duplicate declarations"""
16
17 remove_empty_modules = Parameter(True, 'Remove empty modules.')
18 sort_modules = Parameter(True, 'Sort module content alphabetically.')
19 sxr_prefix = Parameter('', 'Compile sxr data, if defined.')
20
21 def process(self, ir, **kwds):
22
23 self.set_parameters(kwds)
24 self.ir = self.merge_input(ir)
25
26 root = ASG.MetaModule("", QualifiedName())
27 self.__scopes = [root]
28 global_dict = {}
29 self.__dict_map = {id(root) : global_dict}
30 self.__dicts = [global_dict]
31
32 self.types = self.ir.asg.types
33
34 try:
35 for d in self.ir.asg.declarations:
36 d.accept(self)
37 self.ir.asg.declarations = root.declarations
38 except TypeError, e:
39 import traceback
40 traceback.print_exc()
41 print 'linker error :', e
42
43 for file in self.ir.files.values():
44 self.visit_source_file(file)
45
46 self.ir = TemplateLinker.TemplateLinker().process(self.ir, debug=self.debug)
47
48 if self.remove_empty_modules:
49 import ModuleFilter
50 self.ir = ModuleFilter.ModuleFilter().process(self.ir, debug=self.debug)
51
52 if self.sort_modules:
53 import ModuleSorter
54 self.ir = ModuleSorter.ModuleSorter().process(self.ir, debug=self.debug)
55
56 if self.sxr_prefix:
57 import SXRCompiler
58 sxrcompiler = SXRCompiler.SXRCompiler(prefix=self.sxr_prefix)
59 self.ir = sxrcompiler.process(self.ir, debug=self.debug)
60
61
62 output = self.output
63 self.ir = Composite.process(self, self.ir, input=[], output='')
64 self.output = output
65
66 return self.output_and_return_ir()
67
68 def lookup(self, name):
69 """look whether the current scope already contains
70 a declaration with the given name"""
71
72 return self.__dicts[-1].get(name)
73
74 def append(self, declaration):
75 """append declaration to the current scope"""
76
77 self.__scopes[-1].declarations.append(declaration)
78 self.__dicts[-1][declaration.name] = declaration
79
80 def push(self, scope):
81 """push new scope on the stack"""
82
83 self.__scopes.append(scope)
84 dict = self.__dict_map.setdefault(id(scope), {})
85 self.__dicts.append(dict)
86
87 def pop(self):
88 """restore the previous scope"""
89
90 del self.__scopes[-1]
91 del self.__dicts[-1]
92
93 def top(self):
94
95 return self.__scopes[-1]
96
97 def top_dict(self):
98
99 return self.__dicts[-1]
100
101 def link_type(self, type):
102 "Returns the same or new proxy type"
103
104 self.__type = type
105 if type is not None: type.accept(self)
106 return self.__type
107
108
109
110 def visit_builtin_type_id(self, type):
111
112 if self.types.has_key(type.name):
113 self.__type = self.types[type.name]
114
115 def visit_unknown_type_id(self, type):
116
117 if self.types.has_key(type.name):
118 self.__type = self.types[type.name]
119
120 def visit_declared_type_id(self, type):
121
122 if self.types.has_key(type.name):
123 self.__type = self.types[type.name]
124 else:
125 print "Couldn't find declared type-id:",type.name
126
127 def visit_template_id(self, type):
128
129
130 if not self.types.has_key(type.name):
131 return
132 declared = self.types[type.name]
133 if isinstance(declared, ASG.UnknownTypeId):
134
135 return
136 elif not isinstance(declared, ASG.DeclaredTypeId):
137 print "Warning: template declaration was not a declaration:",type.name,declared.__class__.__name__
138 return
139 decl = declared.declaration
140 if not hasattr(decl, 'template'):
141
142 return
143 if decl.template:
144 self.__type = decl.template
145 else:
146 print "Warning: template type disappeared:",type.name
147
148 def visit_modifier_type_id(self, type):
149
150 alias = self.link_type(type.alias)
151 if alias is not type.alias:
152 type.alias = alias
153 self.__type = type
154
155 def visit_array_type_id(self, type):
156
157 alias = self.link_type(type.alias)
158 if alias is not type.alias:
159 type.alias = alias
160 self.__type = type
161
162 def visit_parametrized_type_id(self, type):
163
164 templ = self.link_type(type.template)
165 if templ is not type.template:
166 type.template = templ
167 type.parameters = [self.link_type(p) for p in type.parameters]
168 self.__type = type
169
170 def visit_function_type_id(self, type):
171
172 ret = self.link_type(type.return_type)
173 if ret is not type.return_type:
174 type.return_type = ret
175 type.parameters = [self.link_type(p) for p in type.parameters]
176 self.__type = type
177
178
179
180 def visit_source_file(self, file):
181 """Resolves any duplicates in the list of declarations from this
182 file"""
183
184 types = self.types
185
186
187 declarations = file.declarations
188 file.declarations = []
189
190 for d in declarations:
191
192
193 if types.has_key(d.name):
194 declared = types[d.name]
195 if isinstance(declared, ASG.DeclaredTypeId):
196 d = declared.declaration
197
198 if d not in file.declarations:
199 file.declarations.append(d)
200
201
202
203 def visit_module(self, module):
204
205
206 metamodule = self.lookup(module.name)
207 if metamodule is None:
208 metamodule = ASG.MetaModule(module.type,module.name)
209 self.append(metamodule)
210 elif not isinstance(metamodule, ASG.MetaModule):
211 raise TypeError, 'symbol type mismatch: Synopsis.ASG.Module and %s both match "%s"'%(metamodule.__class__, str(module.name))
212
213 metamodule.module_declarations.append(module)
214
215
216 self.merge_comments(metamodule, module)
217
218 self.push(metamodule)
219 for d in module.declarations:
220 d.accept(self)
221 module.declarations = []
222 self.pop()
223
224
225 def visit_group(self, group):
226
227 previous = self.lookup(group.name)
228 if not previous:
229 self.append(group)
230 elif isinstance(previous, ASG.Group):
231 previous.declarations.append(group.declarations)
232 self.merge_comments(previous, group)
233 group = previous
234 else:
235 raise TypeError, 'symbol type mismatch: Synopsis.ASG.Group and %s both match "%s"'%(previous.__class__, str(previous.name))
236
237 self.push(group)
238 for d in group.declarations:
239 d.accept(self)
240 self.pop()
241
242
243 def merge_comments(self, metamodule, module):
244 """Append the module comments into the metamodule."""
245
246 if module.annotations.has_key('comments'):
247 new_comments = module.annotations['comments']
248 metamodule.annotations.setdefault('comments', [])
249 comments = metamodule.annotations['comments']
250 if comments[-len(new_comments):] != new_comments:
251 comments.extend(new_comments)
252
253
254 def visit_meta_module(self, module):
255
256
257 metamodule = self.lookup(module.name)
258 if metamodule is None:
259 metamodule = ASG.MetaModule(module.type,module.name)
260 self.append(metamodule)
261 elif not isinstance(metamodule, ASG.MetaModule):
262 raise TypeError, 'symbol type mismatch: Synopsis.ASG.MetaModule and %s both match "%s"'%(metamodule.__class__, '::'.join(module.name))
263
264 metamodule.module_declarations.extend(module.module_declarations)
265 self.merge_comments(metamodule, module)
266 self.push(metamodule)
267 for d in module.declarations:
268 d.accept(self)
269 module.declarations = []
270 self.pop()
271
272
273 def add_declaration(self, decl):
274 """Adds a declaration to the current (top) scope.
275 If there is already a Forward declaration, then this replaces it
276 unless this is also a Forward.
277 """
278
279 name = decl.name
280 dict = self.__dicts[-1]
281 decls = self.top().declarations
282 if dict.has_key(name):
283 prev = dict[name]
284 if not isinstance(prev, ASG.Forward):
285 return
286 if not isinstance(decl, ASG.Forward):
287 decls.remove(prev)
288 decls.append(decl)
289 dict[name] = decl
290 return
291 decls.append(decl)
292 dict[name] = decl
293
294 def visit_builtin(self, builtin):
295 """preserve builtins unconditionally"""
296
297 self.top().declarations.append(builtin)
298
299 def visit_named_type(self, decl):
300
301 name = decl.name
302 if self.lookup(decl.name): return
303 self.add_declaration(decl)
304
305 visit_declaration = add_declaration
306 visit_forward = add_declaration
307 visit_enum = add_declaration
308
309 def visit_function(self, func):
310 if not isinstance(self.top(), (ASG.Class, ASG.ClassTemplate)):
311 for d in self.top().declarations:
312 if not isinstance(d, ASG.Function): continue
313 if func.name == d.name:
314 return
315 ret = self.link_type(func.return_type)
316 if ret is not func.return_type:
317 func.return_type = ret
318 for param in func.parameters:
319 self.visit_parameter(param)
320 self.top().declarations.append(func)
321
322
323 visit_operation = visit_function
324
325 def visit_variable(self, var):
326
327
328 vt = self.link_type(var.vtype)
329 if vt is not var.vtype:
330 var.vtype = vt
331 self.add_declaration(var)
332
333 def visit_typedef(self, tdef):
334
335 alias = self.link_type(tdef.alias)
336 if alias is not tdef.alias:
337 tdef.alias = alias
338 self.add_declaration(tdef)
339
340 def visit_class(self, class_):
341
342 prev = self.lookup(class_.name)
343 if prev:
344 if isinstance(prev, ASG.Forward):
345
346 self.top().declarations.remove(prev)
347 del self.top_dict()[class_.name]
348 elif isinstance(prev, (ASG.Class, ASG.ClassTemplate)):
349
350
351
352 self.push(prev)
353 for d in class_.declarations:
354 if isinstance(d, (ASG.Class, ASG.ClassTemplate)):
355 d.accept(self)
356 self.pop()
357 return
358 else:
359 raise TypeError, 'symbol type mismatch: Synopsis.ASG.Class and %s both match "%s"'%(prev.__class__, '::'.join(class_.name))
360 self.add_declaration(class_)
361 for p in class_.parents:
362 p.accept(self)
363 declarations = class_.declarations
364 class_.declarations = []
365 self.push(class_)
366 for d in declarations:
367 d.accept(self)
368 self.pop()
369
370 def visit_inheritance(self, parent):
371
372 type = parent.parent
373 if isinstance(type, (ASG.DeclaredTypeId, ASG.UnknownTypeId)):
374 ltype = self.link_type(type)
375 if ltype is not type:
376 parent.parent = ltype
377 elif isinstance(type, ASG.ParametrizedTypeId):
378 ltype = self.link_type(type.template)
379 if ltype is not type.template:
380
381 if not isinstance(ltype, ASG.DeclaredTypeId):
382
383 return
384 decl = ltype.declaration
385 if isinstance(decl, ASG.ClassTemplate):
386 type.template = decl.template
387 else:
388
389 pass
390
391 def visit_parameter(self, param):
392
393 type = self.link_type(param.type)
394 if type is not param.type:
395 param.type = type
396
397 def visit_const(self, const):
398
399 ct = self.link_type(const.ctype)
400 if ct is not const.ctype:
401 const.ctype = ct
402 self.add_declaration(const)
403
Generated on Thu Apr 16 16:27:13 2009 by
synopsis (version devel)