File: Synopsis/Processors/ModuleFilter.py
 1#
 2# Copyright (C) 2000 Stefan Seefeld
 3# All rights reserved.
 4# Licensed to the public under the terms of the GNU LGPL (>= 2),
 5# see the file COPYING for details.
 6#
 7
 8from Synopsis.Processor import Processor, Parameter
 9from Synopsis import ASG
10
11class ModuleFilter(Processor, ASG.Visitor):
12    """A processor that filters modules."""
13
14    modules = Parameter([], 'List of modules to be filtered out.')
15    remove_empty = Parameter(True, 'Whether or not to remove empty modules.')
16
17    def process(self, ir, **kwds):
18
19        self.set_parameters(kwds)
20        self.ir = self.merge_input(ir)
21
22        self.__scopestack = []
23        self.__currscope = []
24
25        for decl in self.ir.asg.declarations:
26           decl.accept(self)
27        self.ir.asg.declarations[:] = self.__currscope
28
29        return self.output_and_return_ir()
30
31    def push(self):
32        """Pushes the current scope onto the stack and starts a new one"""
33
34        self.__scopestack.append(self.__currscope)
35        self.__currscope = []
36
37    def pop(self, decl):
38        """Pops the current scope from the stack, and appends the given
39        declaration to it"""
40
41        self.__currscope = self.__scopestack.pop()
42        self.__currscope.append(decl)
43
44    def pop_only(self):
45        """Only pops, doesn't append to scope"""
46
47        self.__currscope = self.__scopestack.pop()
48
49    def add(self, decl):
50        """Adds the given decl to the current scope"""
51
52        self.__currscope.append(decl)
53
54    def visit_declaration(self, decl):
55        """Adds declaration to scope"""
56
57        self.add(decl)
58
59    visit_builtin = visit_declaration
60    visit_group = visit_declaration
61    visit_scope = visit_declaration
62    visit_enum = visit_declaration
63
64    def visit_module(self, module):
65        """Visits all children of the module, and if there are no declarations
66        after that removes the module"""
67
68        if module.name in self.modules:
69            return
70
71        self.push()
72        for d in module.declarations:
73            d.accept(self)
74        module.declarations = self.__currscope
75        # count the number of non-forward declarations in the current scope
76        count = reduce(lambda x, y: x + y,
77                       [not isinstance(x, (ASG.Forward, ASG.Builtin))
78                                       for x in self.__currscope],
79                       0)
80        if not self.remove_empty or count: self.pop(module)
81        else: self.pop_only()
82