SymbolTable.py revision 6999
1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
2# Copyright (c) 2009 The Hewlett-Packard Development Company
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28from m5.util import code_formatter
29
30from slicc.generate import html
31from slicc.symbols.StateMachine import StateMachine
32from slicc.symbols.Type import Type
33from slicc.util import Location
34
35class SymbolTable(object):
36    def __init__(self, slicc):
37        self.slicc = slicc
38
39        self.sym_vec = []
40        self.sym_map_vec = [ {} ]
41        self.machine_components = {}
42
43        pairs = {}
44        pairs["enumeration"] = "yes"
45        MachineType = Type(self, "MachineType", Location("init", 0), pairs)
46        self.newSymbol(MachineType)
47
48        pairs = {}
49        pairs["primitive"] = "yes"
50        pairs["external"] = "yes"
51        void = Type(self, "void", Location("init", 0), pairs)
52        self.newSymbol(void)
53
54    def __repr__(self):
55        return "[SymbolTable]" # FIXME
56
57    def codeFormatter(self, *args, **kwargs):
58        return self.slicc.codeFormatter(*args, **kwargs)
59
60    def newSymbol(self, sym):
61        self.registerSym(str(sym), sym)
62        self.sym_vec.append(sym)
63
64    def registerSym(self, id, sym):
65        # Check for redeclaration (in the current frame only)
66        if id in self.sym_map_vec[-1]:
67            sym.error("Symbol '%s' redeclared in same scope.", id)
68
69        # FIXME - warn on masking of a declaration in a previous frame
70        self.sym_map_vec[-1][id] = sym
71
72    def find(self, ident, types=None):
73        for sym_map in reversed(self.sym_map_vec):
74            try:
75                symbol = sym_map[ident]
76            except KeyError:
77                continue
78
79            if types is not None:
80                if not isinstance(symbol, types):
81                    symbol.error("Symbol '%s' is not of types '%s'.",
82                                 symbol,
83                                 types)
84
85            return symbol
86
87        return None
88
89    def newMachComponentSym(self, symbol):
90        # used to cheat-- that is, access components in other machines
91        machine = self.find("current_machine", StateMachine)
92        if machine:
93            self.machine_components[str(machine)][str(symbol)] = symbol
94
95    def newCurrentMachine(self, sym):
96        self.registerGlobalSym(str(sym), sym)
97        self.registerSym("current_machine", sym)
98        self.sym_vec.append(sym)
99
100        self.machine_components[str(sym)] = {}
101
102    @property
103    def state_machine(self):
104        return self.find("current_machine", StateMachine)
105
106    def pushFrame(self):
107        self.sym_map_vec.append({})
108
109    def popFrame(self):
110        assert len(self.sym_map_vec) > 0
111        self.sym_map_vec.pop()
112
113    def registerGlobalSym(self, ident, symbol):
114        # Check for redeclaration (global frame only)
115        if ident in self.sym_map_vec[0]:
116            symbol.error("Symbol '%s' redeclared in global scope." % ident)
117
118        self.sym_map_vec[0][ident] = symbol
119
120    def getAllType(self, type):
121        for symbol in self.sym_vec:
122            if isinstance(symbol, type):
123                yield symbol
124
125    def writeCodeFiles(self, path):
126        code = self.codeFormatter()
127        code('''
128/** Auto generated C++ code started by $__file__:$__line__ */
129
130#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
131''')
132        for symbol in self.sym_vec:
133            if isinstance(symbol, Type) and not symbol.isPrimitive:
134                code('#include "mem/protocol/${{symbol.c_ident}}.hh"')
135
136        code.write(path, "Types.hh")
137
138        for symbol in self.sym_vec:
139            symbol.writeCodeFiles(path)
140
141    def writeHTMLFiles(self, path):
142        machines = list(self.getAllType(StateMachine))
143        if len(machines) > 1:
144            name = "%s_table.html" % machines[0].ident
145        else:
146            name = "empty.html"
147
148        code = self.codeFormatter()
149        code('''
150<html>
151<head>
152<title>$path</title>
153</head>
154<frameset rows="*,30">
155    <frame name="Table" src="$name">
156    <frame name="Status" src="empty.html">
157</frameset>
158</html>
159''')
160        code.write(path, "index.html")
161
162        code = self.codeFormatter()
163        code("<HTML></HTML>")
164        code.write(path, "empty.html")
165
166        for symbol in self.sym_vec:
167            symbol.writeHTMLFiles(path)
168
169__all__ = [ "SymbolTable" ]
170