File: Synopsis/Processors/ScopeStripper.py
  1#
  2# Copyright (C) 2000 Stefan Seefeld
  3# Copyright (C) 2000 Stephen Davies
  4# All rights reserved.
  5# Licensed to the public under the terms of the GNU LGPL (>= 2),
  6# see the file COPYING for details.
  7#
  8
  9from Synopsis.Processor import *
 10from Synopsis import ASG
 11
 12class ScopeStripper(Processor, ASG.Visitor):
 13    """Strip common prefix from the declaration's name.
 14    Keep a list of root nodes, such that children whos parent
 15    scopes are not accepted but which themselfs are correct can
 16    be maintained as new root nodes."""
 17
 18    scope = Parameter('', 'strip all but the given scope')
 19
 20    def __init__(self, **kwds):
 21
 22        Processor.__init__(self, **kwds)
 23        self.declarations = []
 24        self.inside = False
 25        self._scope = ()
 26
 27    def process(self, ir, **kwds):
 28
 29        self.set_parameters(kwds)
 30        if not self.scope: raise MissingArgument('scope')
 31        self.ir = self.merge_input(ir)
 32        if '::' in self.scope:
 33            self._scope = tuple(self.scope.split('::'))
 34        else:
 35            self._scope = tuple(self.scope.split('.'))
 36
 37        # strip prefixes and remove non-matching declarations
 38        self.strip_declarations(self.ir.asg.declarations)
 39
 40        # Remove types not in strip
 41        self.strip_types(self.ir.asg.types)
 42
 43        return self.output_and_return_ir()
 44
 45
 46    def strip_name(self, name):
 47
 48        depth = len(self._scope)
 49        if name[:depth] == self._scope:
 50            if len(name) == depth: return None
 51            return name[depth:]
 52        return None
 53
 54
 55    def strip_declarations(self, declarations):
 56
 57        for decl in declarations:
 58            decl.accept(self)
 59        declarations[:] = self.declarations
 60
 61
 62    def strip_types(self, types):
 63        # Remove the empty type (caused by C++ with extract_tails)
 64        if types.has_key(()): del types[()]
 65        for name, type in types.items():
 66            try:
 67                del types[name]
 68                name = self.strip_name(name)
 69                if name:
 70                    type.name = name
 71                    types[name] = type
 72            except:
 73                print "ERROR Processing:", name, types[name]
 74                raise
 75
 76
 77    def strip(self, declaration):
 78        """test whether the declaration matches one of the prefixes, strip
 79        it off, and return success. Success means that the declaration matches
 80        the prefix set and thus should not be removed from the ASG."""
 81
 82        passed = False
 83        if not self._scope: return True
 84        depth = len(self._scope)
 85        name = declaration.name
 86        if name[:depth] == self._scope and len(name) > depth:
 87            if self.verbose: print "symbol", '::'.join(name),
 88            declaration.name = name[depth:]
 89            if self.verbose: print "stripped to", '::'.join(declaration.name)
 90            passed = True
 91        if self.verbose and not passed:
 92            print "symbol", '::'.join(declaration.name), "removed"
 93        return passed
 94
 95
 96    def visit_scope(self, scope):
 97
 98        root = self.strip(scope) and not self.inside
 99        if root:
100            self.inside = True
101            self.declarations.append(scope)
102        for declaration in scope.declarations:
103            declaration.accept(self)
104        if root: self.inside = False
105
106
107    def visit_class(self, class_):
108
109        self.visit_scope(class_)
110
111
112    def visit_class_template(self, class_):
113
114        self.visit_class(class_)
115        templ = class_.template
116        if templ:
117            name = self.strip_name(templ.name)
118            if name: templ.name = name
119
120
121    def visit_declaration(self, decl):
122
123        if self.strip(decl) and not self.inside:
124            self.declarations.append(decl)
125
126
127    def visit_enumerator(self, enumerator):
128
129        self.strip(enumerator)
130
131
132    def visit_enum(self, enum):
133
134        self.visit_declaration(enum)
135        for e in enum.enumerators:
136            e.accept(self)
137
138
139    def visit_function(self, function):
140
141        self.visit_declaration(function)
142        for parameter in function.parameters:
143            parameter.accept(self)
144
145
146    def visit_parameter(self, parameter):
147
148        self.strip(parameter)
149
150
151    def visit_function_template(self, function):
152
153        self.visit_function(function)
154        if function.template:
155            name = self.strip_name(function.template.name)
156            if name: function.template.name = name
157
158
159    def visit_operation(self, operation):
160
161        self.visit_function(operation)
162
163
164    def visit_operation_template(self, operation):
165
166        self.visit_function_template(operation)
167
168
169    def visit_meta_module(self, module):
170
171        self.visit_scope(module)
172        for d in module.module_declarations:
173            name = self.strip_name(d.name)
174            if name: d.name = name
175