#ifndef TYPE_CHECKING_HH
#define TYPE_CHECKING_HH
#include "visitor.hh"
#include <set>
#include <iostream>
#include <typeinfo>
#include <cassert>
namespace type_checking {
class TypeVisitor;
class TypeInfo {
const char *_name;
TypeInfo();
TypeInfo(TypeInfo&);
public:
TypeInfo(const char *name) : _name(name)
{}
virtual ~TypeInfo() {}
const char *name() const { return _name; }
virtual int arity() const = 0;
virtual void print(std::ostream &os) const = 0;
virtual void accept(TypeVisitor &v) = 0;
bool operator==(const TypeInfo &other) const
{
return (typeid(*this) == typeid(other)
&& (strcmp(name(),other.name()) == 0)
&& (arity() == other.arity()));
}
bool operator!=(const TypeInfo &other) const
{ return !((*this)==other); }
};
class MatrixType : public TypeInfo {
const std::list<ast::Expr*> *_dim_exprs;
ast::basic_type_t _cell_type;
public:
MatrixType(const char *name,
const std::list<ast::Expr*> *dim_exprs,
ast::basic_type_t cell_type = ast::TYPE_INT)
: TypeInfo(name), _dim_exprs(dim_exprs), _cell_type(cell_type)
{
assert(dim_exprs != 0);
};
MatrixType(const char *name, int arity,
ast::basic_type_t cell_type = ast::TYPE_INT)
: TypeInfo(name),
_dim_exprs(new std::list<ast::Expr*>(arity,
new ast::IntegerExpr(0,0))),
_cell_type(cell_type)
{};
const std::list<ast::Expr*> *dim_exprs() const { return _dim_exprs; }
ast::basic_type_t cell_type() const { return _cell_type; }
virtual int arity() const { return _dim_exprs->size(); }
virtual void print(std::ostream &os) const;
virtual void accept(TypeVisitor &v);
};
class FunctionType : public TypeInfo {
const std::list<ast::basic_type_t> *_parameter_types;
ast::basic_type_t _return_type;
public:
FunctionType(const char *name,
const std::list<ast::basic_type_t> *parameter_types,
ast::basic_type_t return_type = ast::TYPE_INT)
: TypeInfo(name),
_parameter_types(parameter_types),
_return_type(return_type)
{ assert(parameter_types != 0); };
FunctionType(const char *name, int arity,
ast::basic_type_t return_type = ast::TYPE_INT)
: TypeInfo(name),
_parameter_types(new std::list<ast::basic_type_t>(arity, ast::TYPE_INT)),
_return_type(return_type)
{ };
const std::list<ast::basic_type_t> *parameter_types() const
{ return _parameter_types; }
ast::basic_type_t return_type() const { return _return_type; }
virtual int arity() const { return _parameter_types->size(); }
virtual void print(std::ostream &os) const;
virtual void accept(TypeVisitor &v);
};
class ValType : public TypeInfo {
ast::basic_type_t _type;
public:
ValType(const char *name, ast::basic_type_t type)
: TypeInfo(name), _type(type) {};
ast::basic_type_t type() const { return _type; }
virtual int arity() const { return 0; }
virtual void print(std::ostream &os) const;
virtual void accept(TypeVisitor &v);
};
class IndexType : public TypeInfo {
public:
IndexType(const char *name)
: TypeInfo(name) {};
virtual int arity() const { return 0; }
virtual void print(std::ostream &os) const;
virtual void accept(TypeVisitor &v);
};
class TypeVisitor {
public:
virtual void visit(MatrixType &matrix_type) = 0;
virtual void visit(FunctionType &fun_type) = 0;
virtual void visit(ValType &val_type) = 0;
virtual void visit(IndexType &idx_type) = 0;
};
// Exceptions
class UndefinedSymbol : public ast::Exception {
const char *_symbol;
public:
UndefinedSymbol(const ast::Ast &ast, const char *symbol)
: ast::Exception(ast), _symbol(symbol)
{}
const char *symbol() const { return _symbol; }
virtual void print_error_msg(std::ostream &os);
};
class BuiltinNotDefined : public ast::Exception {
const char *_symbol;
public:
BuiltinNotDefined(const ast::Ast &ast, const char *symbol)
: ast::Exception(ast), _symbol(symbol)
{}
const char *symbol() const { return _symbol; }
virtual void print_error_msg(std::ostream &os);
};
class WrongType : public ast::Exception {
const TypeInfo *_expected;
const TypeInfo *_actual;
public:
WrongType(const ast::Ast &ast,
const TypeInfo *expected,
const TypeInfo *actual)
: ast::Exception(ast), _expected(expected), _actual(actual)
{}
virtual ~WrongType()
{ delete _expected; } // `actual' points into a symbol table
// and shouldn't be deleted.
const TypeInfo *expected() const { return _expected; }
const TypeInfo *actual() const { return _actual; }
virtual void print_error_msg(std::ostream &os);
};
// Type-checking functions
void check(ast::DProg* dprog);
std::set<TypeInfo*> *global_symbols();
std::set<TypeInfo*> *parameters();
};
inline std::ostream &
operator<<(std::ostream &os, const type_checking::TypeInfo &tinfo)
{
tinfo.print(os);
return os;
}
#endif // TYPE_CHECKING_HH
syntax highlighted by Code2HTML, v. 0.9.1