#ifndef TYPE_CHECKING_HH #define TYPE_CHECKING_HH #include "visitor.hh" #include #include #include #include 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 *_dim_exprs; ast::basic_type_t _cell_type; public: MatrixType(const char *name, const std::list *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(arity, new ast::IntegerExpr(0,0))), _cell_type(cell_type) {}; const std::list *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 *_parameter_types; ast::basic_type_t _return_type; public: FunctionType(const char *name, const std::list *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(arity, ast::TYPE_INT)), _return_type(return_type) { }; const std::list *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 *global_symbols(); std::set *parameters(); }; inline std::ostream & operator<<(std::ostream &os, const type_checking::TypeInfo &tinfo) { tinfo.print(os); return os; } #endif // TYPE_CHECKING_HH