| # Copyright (c) 1999-2008 Mark D. Hill and David A. Wood |
| # Copyright (c) 2009 The Hewlett-Packard Development Company |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer; |
| # redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution; |
| # neither the name of the copyright holders nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| from m5.util import makeDir |
| |
| from slicc.generate import html |
| from slicc.symbols.StateMachine import StateMachine |
| from slicc.symbols.Type import Type |
| from slicc.util import Location |
| |
| class SymbolTable(object): |
| def __init__(self, slicc): |
| self.slicc = slicc |
| |
| self.sym_vec = [] |
| self.sym_map_vec = [ {} ] |
| self.machine_components = {} |
| |
| pairs = {} |
| pairs["primitive"] = "yes" |
| pairs["external"] = "yes" |
| location = Location("init", 0, no_warning=not slicc.verbose) |
| void = Type(self, "void", location, pairs) |
| self.newSymbol(void) |
| |
| def __repr__(self): |
| return "[SymbolTable]" # FIXME |
| |
| def codeFormatter(self, *args, **kwargs): |
| return self.slicc.codeFormatter(*args, **kwargs) |
| |
| def newSymbol(self, sym): |
| self.registerSym(str(sym), sym) |
| self.sym_vec.append(sym) |
| |
| def registerSym(self, id, sym): |
| # Check for redeclaration (in the current frame only) |
| if id in self.sym_map_vec[-1]: |
| sym.error("Symbol '%s' redeclared in same scope.", id) |
| |
| for sym_map in self.sym_map_vec: |
| if id in sym_map: |
| if type(sym_map[id]) != type(sym): |
| sym.error("Conflicting declaration of Symbol '%s'", id) |
| |
| # FIXME - warn on masking of a declaration in a previous frame |
| self.sym_map_vec[-1][id] = sym |
| |
| def find(self, ident, types=None): |
| for sym_map in reversed(self.sym_map_vec): |
| try: |
| symbol = sym_map[ident] |
| except KeyError: |
| continue |
| |
| if types is not None: |
| if not isinstance(symbol, types): |
| continue # there could be a name clash with other symbol |
| # so rather than producing an error, keep trying |
| |
| return symbol |
| |
| return None |
| |
| def newMachComponentSym(self, symbol): |
| # used to cheat-- that is, access components in other machines |
| machine = self.find("current_machine", StateMachine) |
| if machine: |
| self.machine_components[str(machine)][str(symbol)] = symbol |
| |
| def newCurrentMachine(self, sym): |
| self.registerGlobalSym(str(sym), sym) |
| self.registerSym("current_machine", sym) |
| self.sym_vec.append(sym) |
| |
| self.machine_components[str(sym)] = {} |
| |
| @property |
| def state_machine(self): |
| return self.find("current_machine", StateMachine) |
| |
| def pushFrame(self): |
| self.sym_map_vec.append({}) |
| |
| def popFrame(self): |
| assert len(self.sym_map_vec) > 0 |
| self.sym_map_vec.pop() |
| |
| def registerGlobalSym(self, ident, symbol): |
| # Check for redeclaration (global frame only) |
| if ident in self.sym_map_vec[0]: |
| symbol.error("Symbol '%s' redeclared in global scope." % ident) |
| |
| self.sym_map_vec[0][ident] = symbol |
| |
| def getAllType(self, type): |
| for symbol in self.sym_vec: |
| if isinstance(symbol, type): |
| yield symbol |
| |
| def writeCodeFiles(self, path, includes): |
| makeDir(path) |
| |
| code = self.codeFormatter() |
| |
| for include_path in includes: |
| code('#include "${{include_path}}"') |
| |
| for symbol in self.sym_vec: |
| if isinstance(symbol, Type) and not symbol.isPrimitive: |
| code('#include "mem/ruby/protocol/${{symbol.c_ident}}.hh"') |
| |
| code.write(path, "Types.hh") |
| |
| for symbol in self.sym_vec: |
| symbol.writeCodeFiles(path, includes) |
| |
| def writeHTMLFiles(self, path): |
| makeDir(path) |
| |
| machines = list(self.getAllType(StateMachine)) |
| if len(machines) > 1: |
| name = "%s_table.html" % machines[0].ident |
| else: |
| name = "empty.html" |
| |
| code = self.codeFormatter() |
| code(''' |
| <html> |
| <head> |
| <title>$path</title> |
| </head> |
| <frameset rows="*,30"> |
| <frame name="Table" src="$name"> |
| <frame name="Status" src="empty.html"> |
| </frameset> |
| </html> |
| ''') |
| code.write(path, "index.html") |
| |
| code = self.codeFormatter() |
| code("<HTML></HTML>") |
| code.write(path, "empty.html") |
| |
| for symbol in self.sym_vec: |
| symbol.writeHTMLFiles(path) |
| |
| __all__ = [ "SymbolTable" ] |