blob: 8af3685f8c2cf9dc78e92d015459c65ea11b0403 [file] [log] [blame]
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* 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.
*/
/*
* SymbolTable.cc
*
* Description: See SymbolTable.hh
*
* $Id$
*
* */
#include "mem/slicc/symbols/SymbolTable.hh"
#include "mem/slicc/generator/fileio.hh"
#include "mem/slicc/generator/html_gen.hh"
#include "mem/slicc/generator/mif_gen.hh"
#include "mem/slicc/symbols/Action.hh"
SymbolTable g_sym_table;
SymbolTable::SymbolTable()
{
m_sym_map_vec.setSize(1);
m_depth = 0;
{
Map<string, string> pairs;
pairs.add("enumeration", "yes");
newSym(new Type("MachineType", Location(), pairs));
}
{
Map<string, string> pairs;
pairs.add("primitive", "yes");
pairs.add("external", "yes");
newSym(new Type("void", Location(), pairs));
}
}
SymbolTable::~SymbolTable()
{
int size = m_sym_vec.size();
for(int i=0; i<size; i++) {
delete m_sym_vec[i];
}
}
void SymbolTable::newSym(Symbol* sym_ptr)
{
registerSym(sym_ptr->toString(), sym_ptr);
m_sym_vec.insertAtBottom(sym_ptr); // Holder for the allocated Sym objects.
}
void SymbolTable::newMachComponentSym(Symbol* sym_ptr)
{
// used to cheat-- that is, access components in other machines
StateMachine* mach_ptr = getStateMachine("current_machine");
if (mach_ptr != NULL) {
m_machine_component_map_vec.lookup(mach_ptr->toString()).add(sym_ptr->toString(), sym_ptr);
}
}
Var* SymbolTable::getMachComponentVar(string mach, string ident)
{
Symbol* s = m_machine_component_map_vec.lookup(mach).lookup(ident);
return dynamic_cast<Var*>(s);
}
void SymbolTable::registerSym(string id, Symbol* sym_ptr)
{
// Check for redeclaration (in the current frame only)
if (m_sym_map_vec[m_depth].exist(id)) {
sym_ptr->error("Symbol '" + id + "' redeclared in same scope.");
}
// FIXME - warn on masking of a declaration in a previous frame
m_sym_map_vec[m_depth].add(id, sym_ptr);
}
void SymbolTable::registerGlobalSym(string id, Symbol* sym_ptr)
{
// Check for redeclaration (global frame only)
if (m_sym_map_vec[0].exist(id)) {
sym_ptr->error("Global symbol '" + id + "' redeclared in global scope.");
}
m_sym_map_vec[0].add(id, sym_ptr);
}
Symbol* SymbolTable::getSym(string ident) const
{
for (int i=m_depth; i>=0; i--) {
if (m_sym_map_vec[i].exist(ident)) {
return m_sym_map_vec[i].lookup(ident);
}
}
return NULL;
}
void SymbolTable::newCurrentMachine(StateMachine* sym_ptr)
{
registerGlobalSym(sym_ptr->toString(), sym_ptr);
registerSym("current_machine", sym_ptr);
m_sym_vec.insertAtBottom(sym_ptr); // Holder for the allocated Sym objects.
Map<string, Symbol*> m;
m_machine_component_map_vec.add(sym_ptr->toString(),m);
}
Type* SymbolTable::getType(string ident) const
{
return dynamic_cast<Type*>(getSym(ident));
}
Var* SymbolTable::getVar(string ident) const
{
return dynamic_cast<Var*>(getSym(ident));
}
Func* SymbolTable::getFunc(string ident) const
{
return dynamic_cast<Func*>(getSym(ident));
}
StateMachine* SymbolTable::getStateMachine(string ident) const
{
return dynamic_cast<StateMachine*>(getSym(ident));
}
void SymbolTable::pushFrame()
{
m_depth++;
m_sym_map_vec.expand(1);
m_sym_map_vec[m_depth].clear();
}
void SymbolTable::popFrame()
{
m_depth--;
assert(m_depth >= 0);
m_sym_map_vec.expand(-1);
}
void SymbolTable::writeCFiles(string path) const
{
int size = m_sym_vec.size();
{
// Write the Types.hh include file for the types
ostringstream sstr;
sstr << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl;
sstr << endl;
sstr << "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl;
for(int i=0; i<size; i++) {
Type* type = dynamic_cast<Type*>(m_sym_vec[i]);
if (type != NULL && !type->isPrimitive()) {
sstr << "#include \"mem/protocol/" << type->cIdent() << ".hh" << "\"" << endl;
}
}
conditionally_write_file(path + "/Types.hh", sstr);
}
// Write all the symbols
for(int i=0; i<size; i++) {
m_sym_vec[i]->writeCFiles(path + '/');
}
writeControllerFactory(path);
}
void SymbolTable::writeControllerFactory(string path) const
{
ostringstream sstr;
int size = m_sym_vec.size();
sstr << "/** \\file ControllerFactory.hh " << endl;
sstr << " * Auto generatred C++ code started by " << __FILE__ << ":" << __LINE__ << endl;
sstr << " */" << endl << endl;
sstr << "#ifndef CONTROLLERFACTORY_H" << endl;
sstr << "#define CONTROLLERFACTORY_H" << endl;
sstr << endl;
Vector< string > controller_types;
// includes
sstr << "#include <string>" << endl;
sstr << "class Network;" << endl;
sstr << "class AbstractController;" << endl;
sstr << endl;
sstr << "class ControllerFactory {" << endl;
sstr << "public:" << endl;
sstr << " static AbstractController* createController(const std::string & controller_type, const std::string & name);" << endl;
sstr << "};" << endl;
sstr << endl;
sstr << "#endif // CONTROLLERFACTORY_H" << endl;
conditionally_write_file(path + "/ControllerFactory.hh", sstr);
// ControllerFactory.cc file
sstr.str("");
sstr << "/** \\file ControllerFactory.cc " << endl;
sstr << " * Auto generatred C++ code started by " << __FILE__ << ":" << __LINE__ << endl;
sstr << " */" << endl << endl;
// includes
sstr << "#include \"mem/protocol/ControllerFactory.hh\"" << endl;
sstr << "#include \"mem/ruby/slicc_interface/AbstractController.hh\"" << endl;
sstr << "#include \"mem/protocol/MachineType.hh\"" << endl;
for(int i=0; i<size; i++) {
StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
if (machine != NULL) {
sstr << "#include \"mem/protocol/" << machine->getIdent() << "_Controller.hh\"" << endl;
controller_types.insertAtBottom(machine->getIdent());
}
}
sstr << endl;
sstr << "AbstractController* ControllerFactory::createController(const std::string & controller_type, const std::string & name) {" << endl;
for (int i=0;i<controller_types.size();i++) {
sstr << " if (controller_type == \"" << controller_types[i] << "\")" << endl;
sstr << " return new " << controller_types[i] << "_Controller(name);" << endl;
}
sstr << " assert(0); // invalid controller type" << endl;
sstr << " return NULL;" << endl;
sstr << "}" << endl;
conditionally_write_file(path + "/ControllerFactory.cc", sstr);
}
Vector<StateMachine*> SymbolTable::getStateMachines() const
{
Vector<StateMachine*> machine_vec;
int size = m_sym_vec.size();
for(int i=0; i<size; i++) {
StateMachine* type = dynamic_cast<StateMachine*>(m_sym_vec[i]);
if (type != NULL) {
machine_vec.insertAtBottom(type);
}
}
return machine_vec;
}
void SymbolTable::writeHTMLFiles(string path) const
{
// Create index.html
{
ostringstream out;
createHTMLindex(path, out);
conditionally_write_file(path + "index.html", out);
}
// Create empty.html
{
ostringstream out;
out << "<HTML></HTML>";
conditionally_write_file(path + "empty.html", out);
}
// Write all the symbols
int size = m_sym_vec.size();
for(int i=0; i<size; i++) {
m_sym_vec[i]->writeHTMLFiles(path);
}
}
void write_file(string filename, ostringstream& sstr)
{
ofstream out;
out.open(filename.c_str());
out << sstr.str();
out.close();
}
void SymbolTable::writeMIFFiles(string path) const
{
int size = m_sym_vec.size();
for(int i=0; i<size; i++) {
ostringstream states, events, actions, transitions;
StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
if (machine != NULL) {
printStateTableMIF(*machine, states);
write_file(path + machine->getIdent() + "_states.mif", states);
printEventTableMIF(*machine, events);
write_file(path + machine->getIdent() + "_events.mif", events);
printActionTableMIF(*machine, actions);
write_file(path + machine->getIdent() + "_actions.mif", actions);
printTransitionTableMIF(*machine, transitions);
write_file(path + machine->getIdent() + "_transitions.mif", transitions);
}
}
}
void SymbolTable::print(ostream& out) const
{
out << "[SymbolTable]"; // FIXME
}