#include "symbol_checking.hh"
#include "type_checking.hh"
#include "visitor.hh"
#include "options.hh"
using namespace std;
using namespace ast;
using namespace symbol_checking;
using namespace type_checking;
// global scopes
static symbol_map_t globals_map;
static symbol_map_t parameters_map;
static symbol_map_t locals_map;
// exceptions
void
Redefinition::print_error_msg (std::ostream &os)
{
std::cerr << "Symbol " << _symbol
<< " redefining previously declared variable."
<< std::endl;
}
// symbol definitions
namespace symbol_checking {
class SymbolDefinitionVisitor : public Visitor {
SymbolTable &_scope;
void define_globals (DProg &dprog);
void define_parameters (DProg &dprog);
void define_locals (DProg &dprog);
public:
SymbolDefinitionVisitor(SymbolTable &scope)
: _scope(scope)
{};
virtual void visit (RExpr &rexpr);
virtual void visit (WhereExpr &where_expr);
virtual void visit (Range &range);
virtual void visit (Values &values);
virtual void visit (SimpleFun &simple_fun);
virtual void visit (FunCallExpr &fun_call_expr);
virtual void visit (MatrixExpr &matrix_expr);
virtual void visit (BinOpExpr &binop_expr);
virtual void visit (DProg &dprog);
};
class GlobalsDefine : public Visitor {
SymbolTable &_scope;
public:
GlobalsDefine(SymbolTable &scope)
: _scope(scope)
{};
virtual void visit (ValDeclaration &val_def);
virtual void visit (FunDeclaration &fun_def);
virtual void visit (MatrixDeclaration &matrix_def);
};
class ParametersDefine : public Visitor {
SymbolTable &_scope;
public:
ParametersDefine(SymbolTable &scope)
: _scope(scope)
{};
virtual void visit (ValDeclaration &val_def);
virtual void visit (FunDeclaration &fun_def);
virtual void visit (MatrixDeclaration &matrix_def);
virtual void visit (RExpr &rexpr);
virtual void visit (IDExpr &id_expr);
virtual void visit (Update &update);
};
class LocalsDefine : public Visitor {
SymbolTable &_scope;
public:
LocalsDefine(SymbolTable &scope)
: _scope(scope)
{};
virtual void visit (ValDeclaration &val_def);
virtual void visit (FunDeclaration &fun_def);
virtual void visit (MatrixDeclaration &matrix_def);
};
};
void
SymbolDefinitionVisitor::define_globals (DProg &dprog)
{
GlobalsDefine gdef(_scope);
const list<Declaration*> *globals = dprog.globals();
list<Declaration*>::const_iterator g_itr;
for (g_itr = globals->begin(); g_itr != globals->end(); ++g_itr)
(*g_itr)->accept(gdef);
}
void
SymbolDefinitionVisitor::define_parameters (DProg &dprog)
{
ParametersDefine pdef(_scope);
const list<Declaration*> *parameters = dprog.parameters();
list<Declaration*>::const_iterator p_itr;
for (p_itr = parameters->begin(); p_itr != parameters->end(); ++p_itr)
(*p_itr)->accept(pdef);
// matrices being updated are assumed parameters (unless
// explicitly declared)
const list<Update*> *update_list = dprog.update_list();
list<Update*>::const_iterator u_itr;
for (u_itr = update_list->begin(); u_itr != update_list->end(); ++u_itr)
(*u_itr)->accept(pdef);
// all the outer 'where' expression bounds should be parameters
const list<RExpr*> *rexpr_list = dprog.rexpr_list();
list<RExpr*>::const_iterator re_itr;
for (re_itr = rexpr_list->begin(); re_itr != rexpr_list->end(); ++re_itr)
(*re_itr)->accept(pdef);
}
void
SymbolDefinitionVisitor::define_locals (DProg &dprog)
{
LocalsDefine ldef(_scope);
const list<Declaration*> *locals = dprog.locals();
list<Declaration*>::const_iterator itr;
for (itr = locals->begin(); itr != locals->end(); ++itr)
(*itr)->accept(ldef);
}
void
SymbolDefinitionVisitor::visit (RExpr &rexpr)
{
if (_scope.lookup_this_scope(rexpr.index()) != 0)
throw new Redefinition(rexpr, rexpr.index());
_scope.define_symbol(rexpr.index(), new IndexType(rexpr.index()));
}
void
SymbolDefinitionVisitor::visit (WhereExpr &where_expr)
{
const list<RExpr*> *rexpr_list = where_expr.rexpr_list();
list<RExpr*>::const_iterator re_itr;
for (re_itr = rexpr_list->begin(); re_itr != rexpr_list->end(); ++re_itr)
(*re_itr)->accept(*this);
}
void
SymbolDefinitionVisitor::visit (Range &range)
{
// new indices defined in where_expr in range
range.where_expr()->accept(*this);
}
void
SymbolDefinitionVisitor::visit (Values &values)
{
// nothing new defined in Values
}
void
SymbolDefinitionVisitor::visit (MatrixExpr &matrix_expr)
{
// matrix and functions are implicitly defined unless strict_decl
if (options::strict_decl) return;
if (_scope.lookup(matrix_expr.id()) == 0)
{
parameters_map[matrix_expr.id()] =
new MatrixType(matrix_expr.id(),
matrix_expr.expr_list()->size());
}
}
void
SymbolDefinitionVisitor::visit (FunCallExpr &fun_call_expr)
{
if (_scope.lookup(fun_call_expr.id()) == 0)
{
globals_map[fun_call_expr.id()] =
new FunctionType(fun_call_expr.id(),
fun_call_expr.expr_list()->size());
}
}
void
SymbolDefinitionVisitor::visit (BinOpExpr &binop_expr)
{
binop_expr.left()->accept(*this);
binop_expr.right()->accept(*this);
}
void
SymbolDefinitionVisitor::visit (SimpleFun &simple_fun)
{
// traverse to get implicit definitions unless strict
if (options::strict_decl) return;
simple_fun.expr()->accept(*this);
}
void
SymbolDefinitionVisitor::visit (DProg &dprog)
{
define_globals(dprog);
define_locals(dprog); // we need to define locals before parameters,
// since parameters are also implicitly defined
define_parameters(dprog);
const list<RExpr*> *rexpr_list = dprog.rexpr_list();
list<RExpr*>::const_iterator re_itr;
for (re_itr = rexpr_list->begin(); re_itr != rexpr_list->end(); ++re_itr)
(*re_itr)->accept(*this);
}
void
GlobalsDefine::visit (ValDeclaration &val_def)
{
if (_scope.lookup(val_def.name()) != 0)
throw new Redefinition(val_def, val_def.name());
globals_map[val_def.name()] =
new ValType(val_def.name(), val_def.type());
}
void
GlobalsDefine::visit (FunDeclaration &fun_def)
{
if (_scope.lookup(fun_def.name()) != 0)
throw new Redefinition(fun_def, fun_def.name());
globals_map[fun_def.name()] =
new FunctionType(fun_def.name(), fun_def.parameter_types(),
fun_def.return_type());
}
void
GlobalsDefine::visit (MatrixDeclaration &matrix_def)
{
if (_scope.lookup(matrix_def.name()) != 0)
throw new Redefinition(matrix_def, matrix_def.name());
globals_map[matrix_def.name()] =
new MatrixType(matrix_def.name(), matrix_def.dim_list(),
matrix_def.type());
}
void
ParametersDefine::visit (ValDeclaration &val_def)
{
if (_scope.lookup(val_def.name()) != 0)
throw new Redefinition(val_def, val_def.name());
parameters_map[val_def.name()] =
new ValType(val_def.name(), val_def.type());
}
void
ParametersDefine::visit (FunDeclaration &fun_def)
{
std::cerr << "Parameter functions is currently not supported.\n"
<< "Sorry.\n"
<< std::endl;
exit(4);
}
void
ParametersDefine::visit (MatrixDeclaration &matrix_def)
{
if (_scope.lookup(matrix_def.name()) != 0)
throw new Redefinition(matrix_def, matrix_def.name());
parameters_map[matrix_def.name()] =
new MatrixType(matrix_def.name(), matrix_def.dim_list(),
matrix_def.type());
}
void
ParametersDefine::visit (RExpr &rexpr)
{
rexpr.begin()->accept(*this);
rexpr.end()->accept(*this);
}
void
ParametersDefine::visit (IDExpr &id_expr)
{
// implicit definition if non-strict
if (options::strict_decl) return;
if (_scope.lookup(id_expr.id()) == 0)
{
parameters_map[id_expr.id()]
= new ValType(id_expr.id(), TYPE_INT);
}
}
void
ParametersDefine::visit (Update &update)
{
// implicit definition if non-strict
if (options::strict_upd_decl) return;
if (_scope.lookup(update.name()) == 0)
{
parameters_map[update.name()] =
new MatrixType(update.name(),
update.indices()->size(),
update.type());
}
}
void
LocalsDefine::visit (ValDeclaration &val_def)
{
std::cerr << "Local values are currently not supported.\n"
<< "Sorry.\n"
<< std::endl;
exit(4);
}
void
LocalsDefine::visit (FunDeclaration &fun_def)
{
std::cerr << "Local functions are currently not supported.\n"
<< "Sorry.\n"
<< std::endl;
exit(4);
}
void
LocalsDefine::visit (MatrixDeclaration &matrix_def)
{
if (_scope.lookup(matrix_def.name()) != 0)
throw new Redefinition(matrix_def, matrix_def.name());
locals_map[matrix_def.name()] =
new MatrixType(matrix_def.name(), matrix_def.dim_list(),
matrix_def.type());
}
// symbol table
SymbolTable::SymbolTable(Ast &ast, SymbolTable *outer_scope)
: _outer_scope(outer_scope)
{
SymbolDefinitionVisitor sdv(*this);
ast.accept(sdv);
}
const tinfo_t*
SymbolTable::lookup_this_scope (const char *symbol) const
{
symbol_map_t::const_iterator i = _this_scope.find(symbol);
if (i != _this_scope.end()) return i->second;
else return 0;
}
const tinfo_t*
SymbolTable::lookup_local_scopes (const char *symbol) const
{
const tinfo_t *tinfo = lookup_this_scope(symbol);
if (tinfo != 0) return tinfo;
else if (_outer_scope != 0) return _outer_scope->lookup(symbol);
else return 0;
}
const tinfo_t*
SymbolTable::lookup_global_scopes (const char *symbol)
{
symbol_map_t::const_iterator i = globals_map.find(symbol);
if (i != globals_map.end()) return i->second;
i = parameters_map.find(symbol);
if (i != parameters_map.end()) return i->second;
i = locals_map.find(symbol);
if (i != locals_map.end()) return i->second;
return 0;
}
const tinfo_t*
SymbolTable::lookup (const char *symbol) const
{
const tinfo_t *tinfo = lookup_local_scopes(symbol);
if (tinfo != 0) return tinfo;
else return lookup_global_scopes(symbol);
}
void
SymbolTable::define_symbol (const char *symbol, tinfo_t *tinfo)
{
_this_scope[symbol] = tinfo;
}
// access to global scopes.
set<tinfo_t*> *
symbol_checking::globals ()
{
static set<tinfo_t*> *symbols = 0;
if (!symbols)
{
symbols = new set<tinfo_t*>;
symbol_map_t::const_iterator i;
for (i = globals_map.begin(); i != globals_map.end(); ++i)
symbols->insert(i->second);
}
return symbols;
}
set<tinfo_t*> *
symbol_checking::parameters ()
{
static set<tinfo_t*> *symbols = 0;
if (!symbols)
{
symbols = new set<tinfo_t*>;
symbol_map_t::const_iterator i;
for (i = parameters_map.begin(); i != parameters_map.end(); ++i)
symbols->insert(i->second);
}
return symbols;
}
set<tinfo_t*> *
symbol_checking::locals ()
{
static set<tinfo_t*> *symbols = 0;
if (!symbols)
{
symbols = new set<tinfo_t*>;
symbol_map_t::const_iterator i;
for (i = locals_map.begin(); i != locals_map.end(); ++i)
symbols->insert(i->second);
}
return symbols;
}
syntax highlighted by Code2HTML, v. 0.9.1