- Timestamp:
- Dec 16, 2020, 4:01:57 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 8ba363e, c8025a21
- Parents:
- b3c8496 (diff), 3e5dd913 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 3 deleted
- 42 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
rb3c8496 r53449a4 55 55 56 56 // these need to be accessed in new FixInit now 57 ast:: Type *sizeType = nullptr;58 ast::FunctionDecl * dereferenceOperator = nullptr;59 ast::StructDecl * dtorStruct = nullptr;60 ast::FunctionDecl * dtorStructDestroy = nullptr;57 ast::ptr<ast::Type> sizeType = nullptr; 58 const ast::FunctionDecl * dereferenceOperator = nullptr; 59 const ast::StructDecl * dtorStruct = nullptr; 60 const ast::FunctionDecl * dtorStructDestroy = nullptr; 61 61 62 62 } … … 205 205 ftype->parameters = get<DeclarationWithType>().acceptL(node->params); 206 206 207 ftype->forall = get<TypeDecl>().acceptL( node->type->forall ); 207 ftype->forall = get<TypeDecl>().acceptL( node->type_params ); 208 if (!node->assertions.empty()) { 209 assert(!ftype->forall.empty()); 210 // find somewhere to place assertions back, for convenience it is the last slot 211 ftype->forall.back()->assertions = get<DeclarationWithType>().acceptL(node->assertions); 212 } 208 213 209 214 visitType(node->type, ftype); … … 233 238 const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) { 234 239 // base comes from constructor 235 decl->parameters = get<TypeDecl>().acceptL( node->params );236 240 decl->assertions = get<DeclarationWithType>().acceptL( node->assertions ); 237 241 declPostamble( decl, node ); … … 603 607 604 608 for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) { 605 rslt->add( src_i->first ,609 rslt->add( src_i->first.typeString(), 606 610 get<Type>().accept1(src_i->second) ); 607 }608 609 for (decltype(src->beginVar()) src_i = src->beginVar(); src_i != src->endVar(); src_i++) {610 rslt->addVar( src_i->first,611 get<Expression>().accept1(src_i->second) );612 611 } 613 612 … … 1213 1212 // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns ); 1214 1213 // ty->parameters = get<DeclarationWithType>().acceptL( node->params ); 1215 ty->forall = get<TypeDecl>().acceptL( node->forall ); 1214 1215 auto types = get<TypeInstType>().acceptL( node->forall ); 1216 for (auto t : types) { 1217 auto newT = new TypeDecl(*t->baseType); 1218 newT->name = t->name; // converted by typeString() 1219 for (auto asst : newT->assertions) delete asst; 1220 newT->assertions.clear(); 1221 ty->forall.push_back(newT); 1222 } 1223 auto assts = get<VariableExpr>().acceptL( node->assertions ); 1224 if (!assts.empty()) { 1225 assert(!types.empty()); 1226 for (auto asst : assts) { 1227 auto newDecl = new ObjectDecl(*strict_dynamic_cast<ObjectDecl*>(asst->var)); 1228 delete newDecl->type; 1229 newDecl->type = asst->result->clone(); 1230 newDecl->storageClasses.is_extern = true; // hack 1231 ty->forall.back()->assertions.push_back(newDecl); 1232 } 1233 } 1234 1216 1235 return visitType( node, ty ); 1217 1236 } 1218 1237 1219 1238 const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) { 1220 ty->forall = get<TypeDecl>().acceptL( old->forall );1221 1239 ty->parameters = get<Expression>().acceptL( old->params ); 1222 1240 ty->hoistType = old->hoistType; … … 1301 1319 ty = new TypeInstType{ 1302 1320 cv( node ), 1303 node-> name,1321 node->typeString(), 1304 1322 get<TypeDecl>().accept1( node->base ), 1305 1323 get<Attribute>().acceptL( node->attributes ) … … 1308 1326 ty = new TypeInstType{ 1309 1327 cv( node ), 1310 node-> name,1328 node->typeString(), 1311 1329 node->kind == ast::TypeDecl::Ftype, 1312 1330 get<Attribute>().acceptL( node->attributes ) … … 1433 1451 /// at conversion stage, all created nodes are guaranteed to be unique, therefore 1434 1452 /// const_casting out of smart pointers is permitted. 1435 std::unordered_map< const BaseSyntaxNode *, ast:: ptr<ast::Node> > cache = {};1453 std::unordered_map< const BaseSyntaxNode *, ast::readonly<ast::Node> > cache = {}; 1436 1454 1437 1455 // Local Utilities: … … 1567 1585 // can function type have attributes? seems not to be the case. 1568 1586 // visitType(old->type, ftype); 1587 1588 // collect assertions and put directly in FunctionDecl 1589 std::vector<ast::ptr<ast::DeclWithType>> assertions; 1590 for (auto & param: forall) { 1591 for (auto & asst: param->assertions) { 1592 assertf(asst->unique(), "newly converted decl must be unique"); 1593 assertions.emplace_back(asst); 1594 } 1595 auto mut = param.get_and_mutate(); 1596 assertf(mut == param, "newly converted decl must be unique"); 1597 mut->assertions.clear(); 1598 } 1569 1599 1570 1600 auto decl = new ast::FunctionDecl{ … … 1586 1616 cache.emplace( old, decl ); 1587 1617 1618 decl->assertions = std::move(assertions); 1588 1619 decl->withExprs = GET_ACCEPT_V(withExprs, Expr); 1589 1620 decl->stmts = GET_ACCEPT_1(statements, CompoundStmt); … … 1704 1735 cache.emplace( old, decl ); 1705 1736 decl->assertions = GET_ACCEPT_V(assertions, DeclWithType); 1706 decl->params = GET_ACCEPT_V(parameters, TypeDecl);1707 1737 decl->extension = old->extension; 1708 1738 decl->uniqueId = old->uniqueId; … … 1720 1750 ); 1721 1751 decl->assertions = GET_ACCEPT_V(assertions, DeclWithType); 1722 decl->params = GET_ACCEPT_V(parameters, TypeDecl);1723 1752 decl->extension = old->extension; 1724 1753 decl->uniqueId = old->uniqueId; … … 2070 2099 } 2071 2100 2101 // TypeSubstitution shouldn't exist yet in old. 2072 2102 ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) { 2073 2103 2074 2104 if (!old) return nullptr; 2075 2105 if (old->empty()) return nullptr; 2106 assert(false); 2107 2108 /* 2076 2109 ast::TypeSubstitution *rslt = new ast::TypeSubstitution(); 2077 2110 … … 2081 2114 } 2082 2115 2083 for (decltype(old->beginVar()) old_i = old->beginVar(); old_i != old->endVar(); old_i++) {2084 rslt->addVar( old_i->first,2085 getAccept1<ast::Expr>(old_i->second) );2086 }2087 2088 2116 return rslt; 2117 */ 2089 2118 } 2090 2119 … … 2614 2643 ty->params.emplace_back(v->get_type()); 2615 2644 } 2616 ty->forall = GET_ACCEPT_V( forall, TypeDecl ); 2645 // xxx - when will this be non-null? 2646 // will have to create dangling (no-owner) decls to be pointed to 2647 auto foralls = GET_ACCEPT_V( forall, TypeDecl ); 2648 2649 for (auto & param : foralls) { 2650 ty->forall.emplace_back(new ast::TypeInstType(param->name, param)); 2651 for (auto asst : param->assertions) { 2652 ty->assertions.emplace_back(new ast::VariableExpr({}, asst)); 2653 } 2654 } 2617 2655 visitType( old, ty ); 2618 2656 } 2619 2657 2620 2658 void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) { 2621 ty->forall = GET_ACCEPT_V( forall, TypeDecl );2622 2659 ty->params = GET_ACCEPT_V( parameters, Expr ); 2623 2660 ty->hoistType = old->hoistType; … … 2807 2844 ConverterOldToNew c; 2808 2845 ast::TranslationUnit unit; 2846 if (Validate::SizeType) { 2847 // this should be a BasicType. 2848 auto old = strict_dynamic_cast<BasicType *>(Validate::SizeType); 2849 ast::sizeType = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind }; 2850 } 2851 2809 2852 for(auto d : translationUnit) { 2810 2853 d->accept( c ); -
src/AST/Decl.cpp
rb3c8496 r53449a4 50 50 51 51 FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name, 52 std::vector<ptr<TypeDecl>>&& forall, 53 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 54 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 55 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs) 56 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)), 57 stmts( stmts ) { 58 FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs)); 59 for (auto & param : this->params) { 60 ftype->params.emplace_back(param->get_type()); 61 } 62 for (auto & ret : this->returns) { 63 ftype->returns.emplace_back(ret->get_type()); 64 } 65 ftype->forall = std::move(forall); 66 this->type = ftype; 67 } 52 std::vector<ptr<TypeDecl>>&& forall, 53 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 54 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 55 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs) 56 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)), 57 type_params(std::move(forall)), stmts( stmts ) { 58 FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs)); 59 for (auto & param : this->params) { 60 ftype->params.emplace_back(param->get_type()); 61 } 62 for (auto & ret : this->returns) { 63 ftype->returns.emplace_back(ret->get_type()); 64 } 65 for (auto & tp : this->type_params) { 66 ftype->forall.emplace_back(new TypeInstType(tp->name, tp)); 67 } 68 this->type = ftype; 69 } 68 70 69 71 -
src/AST/Decl.hpp
rb3c8496 r53449a4 132 132 std::vector< ptr<Expr> > withExprs; 133 133 134 std::vector<ptr<TypeDecl>> type_params; 135 std::vector<ptr<DeclWithType>> assertions; 136 134 137 FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall, 135 138 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, … … 154 157 public: 155 158 ptr<Type> base; 156 std::vector<ptr<TypeDecl>> params;157 159 std::vector<ptr<DeclWithType>> assertions; 158 160 … … 160 162 const CodeLocation & loc, const std::string & name, Storage::Classes storage, 161 163 const Type * b, Linkage::Spec spec = Linkage::Cforall ) 162 : Decl( loc, name, storage, spec ), base( b ), params(),assertions() {}164 : Decl( loc, name, storage, spec ), base( b ), assertions() {} 163 165 164 166 /// Produces a name for the kind of alias -
src/AST/Expr.cpp
rb3c8496 r53449a4 206 206 assert( aggregate->result ); 207 207 208 // Deep copy on result type avoids mutation on transitively multiply referenced object. 209 // 210 // Example, adapted from parts of builtins and bootloader: 211 // 212 // forall(dtype T) 213 // struct __Destructor { 214 // T * object; 215 // void (*dtor)(T *); 216 // }; 217 // 218 // forall(dtype S) 219 // void foo(__Destructor(S) &d) { 220 // if (d.dtor) { // here 221 // } 222 // } 223 // 224 // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve. Let d be the 225 // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level 226 // declaration of __Destructor. Consider the types e.result and d.type. In the old AST, one 227 // is a clone of the other. Ordinary new-AST use would set them up as a multiply-referenced 228 // object. 229 // 230 // e.result: PointerType 231 // .base: FunctionType 232 // .params.front(): ObjectDecl, the anonymous parameter of type T* 233 // .type: PointerType 234 // .base: TypeInstType 235 // let x = that 236 // let y = similar, except start from d.type 237 // 238 // Consider two code lines down, genericSubstitution(...).apply(result). 239 // 240 // Applying this chosen-candidate's type substitution means modifying x, substituting 241 // S for T. This mutation should affect x and not y. 242 243 result = deepCopy(mem->get_type()); 208 result = mem->get_type(); 244 209 245 210 // substitute aggregate generic parameters into member type -
src/AST/Expr.hpp
rb3c8496 r53449a4 112 112 113 113 bool hasSlots() const { return data.resnSlots; } 114 bool hasParams() const { return data.inferParams; } 114 115 115 116 ResnSlots& resnSlots() { -
src/AST/Fwd.hpp
rb3c8496 r53449a4 139 139 struct TranslationUnit; 140 140 // TODO: Get from the TranslationUnit: 141 extern Type *sizeType;142 extern FunctionDecl * dereferenceOperator;143 extern StructDecl * dtorStruct;144 extern FunctionDecl * dtorStructDestroy;141 extern ptr<Type> sizeType; 142 extern const FunctionDecl * dereferenceOperator; 143 extern const StructDecl * dtorStruct; 144 extern const FunctionDecl * dtorStructDestroy; 145 145 146 146 } -
src/AST/Pass.hpp
rb3c8496 r53449a4 34 34 35 35 #include "AST/SymbolTable.hpp" 36 37 #include "AST/ForallSubstitutionTable.hpp"38 36 39 37 // Private prelude header, needed for some of the magic tricks this class pulls off … … 66 64 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 67 65 // | WithSymbolTable - provides symbol table functionality 68 // | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation69 66 // 70 67 // Other Special Members: … … 258 255 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 259 256 260 /// Mutate forall-list, accounting for presence of type substitution map261 template<typename node_t>262 void mutate_forall( const node_t *& );263 264 257 public: 265 258 /// Logic to call the accept and mutate the parent if needed, delegates call to accept … … 287 280 /// Internal RAII guard for forall substitutions 288 281 struct guard_forall_subs { 289 guard_forall_subs( Pass<core_t> & pass, const ParameterizedType * type )282 guard_forall_subs( Pass<core_t> & pass, const FunctionType * type ) 290 283 : pass( pass ), type( type ) { __pass::forall::enter(pass.core, 0, type ); } 291 284 ~guard_forall_subs() { __pass::forall::leave(pass.core, 0, type ); } 292 285 Pass<core_t> & pass; 293 const ParameterizedType * type;286 const FunctionType * type; 294 287 }; 295 288 … … 398 391 }; 399 392 400 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl401 struct WithForallSubstitutor {402 ForallSubstitutionTable subs;403 };404 405 393 } 406 394 -
src/AST/Pass.impl.hpp
rb3c8496 r53449a4 367 367 } 368 368 369 370 template< typename core_t >371 template< typename node_t >372 void ast::Pass< core_t >::mutate_forall( const node_t *& node ) {373 if ( auto subs = __pass::forall::subs( core, 0 ) ) {374 // tracking TypeDecl substitution, full clone375 if ( node->forall.empty() ) return;376 377 node_t * mut = __pass::mutate<core_t>( node );378 mut->forall = subs->clone( node->forall, *this );379 node = mut;380 } else {381 // not tracking TypeDecl substitution, just mutate382 maybe_accept( node, &node_t::forall );383 }384 }385 369 } 386 370 … … 504 488 __pass::symtab::addId( core, 0, func ); 505 489 VISIT( 506 // parameter declarations are now directly here490 // parameter declarations 507 491 maybe_accept( node, &FunctionDecl::params ); 508 492 maybe_accept( node, &FunctionDecl::returns ); 509 // foralls are still in function type 510 maybe_accept( node, &FunctionDecl::type ); 493 // type params and assertions 494 maybe_accept( node, &FunctionDecl::type_params ); 495 maybe_accept( node, &FunctionDecl::assertions ); 511 496 // First remember that we are now within a function. 512 497 ValueGuard< bool > oldInFunction( inFunction ); … … 609 594 VISIT({ 610 595 guard_symtab guard { *this }; 611 maybe_accept( node, &TypeDecl::params );612 596 maybe_accept( node, &TypeDecl::base ); 613 597 }) … … 638 622 VISIT({ 639 623 guard_symtab guard { *this }; 640 maybe_accept( node, &TypedefDecl::params );641 624 maybe_accept( node, &TypedefDecl::base ); 642 625 }) … … 1760 1743 1761 1744 VISIT({ 1762 guard_forall_subs forall_guard { *this, node }; 1763 mutate_forall( node ); 1745 // guard_forall_subs forall_guard { *this, node }; 1746 // mutate_forall( node ); 1747 maybe_accept( node, &FunctionType::assertions ); 1764 1748 maybe_accept( node, &FunctionType::returns ); 1765 1749 maybe_accept( node, &FunctionType::params ); … … 1779 1763 VISIT({ 1780 1764 guard_symtab guard { *this }; 1781 guard_forall_subs forall_guard { *this, node };1782 mutate_forall( node );1783 1765 maybe_accept( node, &StructInstType::params ); 1784 1766 }) … … 1797 1779 VISIT({ 1798 1780 guard_symtab guard { *this }; 1799 guard_forall_subs forall_guard { *this, node };1800 mutate_forall( node );1801 1781 maybe_accept( node, &UnionInstType::params ); 1802 1782 }) … … 1812 1792 1813 1793 VISIT({ 1814 guard_forall_subs forall_guard { *this, node };1815 mutate_forall( node );1816 1794 maybe_accept( node, &EnumInstType::params ); 1817 1795 }) … … 1827 1805 1828 1806 VISIT({ 1829 guard_forall_subs forall_guard { *this, node };1830 mutate_forall( node );1831 1807 maybe_accept( node, &TraitInstType::params ); 1832 1808 }) … … 1843 1819 VISIT( 1844 1820 { 1845 guard_forall_subs forall_guard { *this, node };1846 mutate_forall( node );1847 1821 maybe_accept( node, &TypeInstType::params ); 1848 1822 } … … 1993 1967 { 1994 1968 bool mutated = false; 1995 std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;1969 std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map; 1996 1970 for ( const auto & p : node->typeEnv ) { 1997 1971 guard_symtab guard { *this }; … … 2006 1980 } 2007 1981 } 2008 2009 {2010 bool mutated = false;2011 std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;2012 for ( const auto & p : node->varEnv ) {2013 guard_symtab guard { *this };2014 auto new_node = p.second->accept( *this );2015 if (new_node != p.second) mutated = true;2016 new_map.insert({ p.first, new_node });2017 }2018 if (mutated) {2019 auto new_node = __pass::mutate<core_t>( node );2020 new_node->varEnv.swap( new_map );2021 node = new_node;2022 }2023 }2024 1982 ) 2025 1983 -
src/AST/Pass.proto.hpp
rb3c8496 r53449a4 396 396 // Some simple scoping rules 397 397 template<typename core_t> 398 static inline auto enter( core_t & core, int, const ast:: ParameterizedType * type )398 static inline auto enter( core_t & core, int, const ast::FunctionType * type ) 399 399 -> decltype( core.subs, void() ) { 400 400 if ( ! type->forall.empty() ) core.subs.beginScope(); … … 402 402 403 403 template<typename core_t> 404 static inline auto enter( core_t &, long, const ast:: ParameterizedType * ) {}405 406 template<typename core_t> 407 static inline auto leave( core_t & core, int, const ast:: ParameterizedType * type )404 static inline auto enter( core_t &, long, const ast::FunctionType * ) {} 405 406 template<typename core_t> 407 static inline auto leave( core_t & core, int, const ast::FunctionType * type ) 408 408 -> decltype( core.subs, void() ) { 409 409 if ( ! type->forall.empty() ) { core.subs.endScope(); } … … 411 411 412 412 template<typename core_t> 413 static inline auto leave( core_t &, long, const ast::ParameterizedType * ) {} 414 415 // Get the substitution table, if present 416 template<typename core_t> 417 static inline auto subs( core_t & core, int ) -> decltype( &core.subs ) { 418 return &core.subs; 419 } 420 421 template<typename core_t> 422 static inline ast::ForallSubstitutionTable * subs( core_t &, long ) { return nullptr; } 413 static inline auto leave( core_t &, long, const ast::FunctionType * ) {} 423 414 424 415 // Replaces a TypeInstType's base TypeDecl according to the table -
src/AST/Print.cpp
rb3c8496 r53449a4 146 146 } 147 147 148 void print( const ast:: ParameterizedType::ForallList & forall ) {148 void print( const ast::FunctionType::ForallList & forall ) { 149 149 if ( forall.empty() ) return; 150 150 os << "forall" << endl; 151 151 ++indent; 152 152 printAll( forall ); 153 os << indent; 154 --indent; 155 } 156 157 void print( const ast::FunctionType::AssertionList & assts ) { 158 if (assts.empty()) return; 159 os << "with assertions" << endl; 160 ++indent; 161 printAll(assts); 153 162 os << indent; 154 163 --indent; … … 206 215 void preprint( const ast::NamedTypeDecl * node ) { 207 216 if ( ! node->name.empty() ) { 208 if( deterministic_output && isUnboundType(node->name) ) os << "[unbound]:"; 209 else os << node->name << ": "; 217 os << node->name << ": "; 210 218 } 211 219 … … 224 232 } 225 233 226 if ( ! node->params.empty() ) {227 os << endl << indent << "... with parameters" << endl;228 ++indent;229 printAll( node->params );230 --indent;231 }232 233 234 if ( ! node->assertions.empty() ) { 234 235 os << endl << indent << "... with assertions" << endl; … … 266 267 } 267 268 268 void preprint( const ast:: ParameterizedType * node ) {269 void preprint( const ast::FunctionType * node ) { 269 270 print( node->forall ); 271 print( node->assertions ); 270 272 print( node->qualifiers ); 271 273 } 272 274 273 275 void preprint( const ast::BaseInstType * node ) { 274 print( node->forall );275 276 print( node->attributes ); 276 277 print( node->qualifiers ); … … 1383 1384 virtual const ast::Type * visit( const ast::TypeInstType * node ) override final { 1384 1385 preprint( node ); 1385 const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node-> name;1386 const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->typeString(); 1386 1387 os << "instance of type " << _name 1387 1388 << " (" << (node->kind == ast::TypeDecl::Ftype ? "" : "not ") << "function type)"; … … 1510 1511 os << indent << "Types:" << endl; 1511 1512 for ( const auto& i : *node ) { 1512 os << indent+1 << i.first << " -> ";1513 os << indent+1 << i.first.typeString() << " -> "; 1513 1514 indent += 2; 1514 1515 safe_print( i.second ); 1515 indent -= 2;1516 os << endl;1517 }1518 os << indent << "Non-types:" << endl;1519 for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {1520 os << indent+1 << i->first << " -> ";1521 indent += 2;1522 safe_print( i->second );1523 1516 indent -= 2; 1524 1517 os << endl; -
src/AST/SymbolTable.cpp
rb3c8496 r53449a4 414 414 415 415 void SymbolTable::addFunction( const FunctionDecl * func ) { 416 addTypes( func->type->forall ); 416 for (auto & td : func->type_params) { 417 addType(td); 418 } 419 for (auto & asst : func->assertions) { 420 addId(asst); 421 } 422 // addTypes( func->type->forall ); 417 423 addIds( func->returns ); 418 424 addIds( func->params ); -
src/AST/TranslationUnit.hpp
rb3c8496 r53449a4 29 29 std::map< UniqueId, Decl * > idMap; 30 30 31 Type * sizeType;32 FunctionDecl * dereference;33 StructDecl * dtorStruct;34 FunctionDecl * dtorDestroy;31 const Type * sizeType; 32 const FunctionDecl * dereference; 33 const StructDecl * dtorStruct; 34 const FunctionDecl * dtorDestroy; 35 35 } global; 36 36 }; -
src/AST/Type.cpp
rb3c8496 r53449a4 21 21 22 22 #include "Decl.hpp" 23 #include "ForallSubstitutor.hpp" // for substituteForall24 23 #include "Init.hpp" 25 24 #include "Common/utility.h" // for copy, move … … 92 91 // GENERATED END 93 92 94 // --- ParameterizedType95 96 void ParameterizedType::initWithSub(97 const ParameterizedType & o, Pass< ForallSubstitutor > & sub98 ) {99 forall = sub.core( o.forall );100 }101 102 93 // --- FunctionType 103 104 105 FunctionType::FunctionType( const FunctionType & o )106 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),107 isVarArgs( o.isVarArgs ) {108 Pass< ForallSubstitutor > sub;109 initWithSub( o, sub ); // initialize substitution map110 returns = sub.core( o.returns ); // apply to return and parameter types111 params = sub.core( o.params );112 }113 114 94 namespace { 115 95 bool containsTtype( const std::vector<ptr<Type>> & l ) { … … 123 103 bool FunctionType::isTtype() const { 124 104 return containsTtype( returns ) || containsTtype( params ); 125 }126 127 // --- BaseInstType128 129 void BaseInstType::initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ) {130 ParameterizedType::initWithSub( o, sub ); // initialize substitution131 params = sub.core( o.params ); // apply to parameters132 }133 134 BaseInstType::BaseInstType( const BaseInstType & o )135 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),136 hoistType( o.hoistType ) {137 Pass< ForallSubstitutor > sub;138 initWithSub( o, sub );139 105 } 140 106 … … 177 143 : BaseInstType( b->name, q, move(as) ), base( b ) {} 178 144 179 // --- TypeInstType180 181 TypeInstType::TypeInstType( const TypeInstType & o )182 : BaseInstType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {183 Pass< ForallSubstitutor > sub;184 initWithSub( o, sub ); // initialize substitution185 base = sub.core( o.base ); // apply to base type186 }187 188 145 void TypeInstType::set_base( const TypeDecl * b ) { 189 146 base = b; … … 222 179 // TODO: once TypeInstType representation is updated, it should properly check 223 180 // if the context id is filled. this is a temporary hack for now 224 return isUnboundType(typeInst->name); 225 } 226 return false; 227 } 228 229 bool isUnboundType(const std::string & tname) { 230 // xxx - look for a type name produced by renameTyVars. 231 232 // TODO: once TypeInstType representation is updated, it should properly check 233 // if the context id is filled. this is a temporary hack for now 234 if (std::count(tname.begin(), tname.end(), '_') >= 3) { 235 return true; 181 return typeInst->formal_usage > 0; 236 182 } 237 183 return false; -
src/AST/Type.hpp
rb3c8496 r53449a4 36 36 37 37 template< typename T > class Pass; 38 39 struct ForallSubstitutor;40 38 41 39 class Type : public Node { … … 267 265 }; 268 266 269 /// Base type for potentially forall-qualified types270 class ParameterizedType : public Type {271 protected:272 /// initializes forall with substitutor273 void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );274 public:275 using ForallList = std::vector<ptr<TypeDecl>>;276 277 ForallList forall;278 279 ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {},280 std::vector<ptr<Attribute>> && as = {} )281 : Type(q, std::move(as)), forall(std::move(fs)) {}282 283 ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )284 : Type(q, std::move(as)), forall() {}285 286 // enforce use of ForallSubstitutor to copy parameterized type287 ParameterizedType( const ParameterizedType & ) = delete;288 289 ParameterizedType( ParameterizedType && ) = default;290 291 // no need to change destructor, and operator= deleted in Node292 293 private:294 virtual ParameterizedType * clone() const override = 0;295 MUTATE_FRIEND296 };297 298 267 /// Function variable arguments flag 299 268 enum ArgumentFlag { FixedArgs, VariableArgs }; 300 269 301 270 /// Type of a function `[R1, R2](*)(P1, P2, P3)` 302 class FunctionType final : public ParameterizedType { 303 public: 271 class FunctionType final : public Type { 272 public: 273 using ForallList = std::vector<ptr<TypeInstType>>; 274 using AssertionList = std::vector<ptr<VariableExpr>>; 275 ForallList forall; 276 AssertionList assertions; 277 304 278 std::vector<ptr<Type>> returns; 305 279 std::vector<ptr<Type>> params; … … 313 287 314 288 FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} ) 315 : ParameterizedType(q), returns(), params(), isVarArgs(va) {}316 317 FunctionType( const FunctionType & o ) ;289 : Type(q), returns(), params(), isVarArgs(va) {} 290 291 FunctionType( const FunctionType & o ) = default; 318 292 319 293 /// true if either the parameters or return values contain a tttype … … 329 303 330 304 /// base class for types that refer to types declared elsewhere (aggregates and typedefs) 331 class BaseInstType : public ParameterizedType { 332 protected: 333 /// Initializes forall and parameters based on substitutor 334 void initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ); 305 class BaseInstType : public Type { 335 306 public: 336 307 std::vector<ptr<Expr>> params; … … 340 311 BaseInstType( 341 312 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 342 : ParameterizedType(q, std::move(as)), params(), name(n) {}313 : Type(q, std::move(as)), params(), name(n) {} 343 314 344 315 BaseInstType( 345 316 const std::string& n, std::vector<ptr<Expr>> && params, 346 317 CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 347 : ParameterizedType(q, std::move(as)), params(std::move(params)), name(n) {}348 349 BaseInstType( const BaseInstType & o ) ;318 : Type(q, std::move(as)), params(std::move(params)), name(n) {} 319 320 BaseInstType( const BaseInstType & o ) = default; 350 321 351 322 /// Gets aggregate declaration this type refers to … … 423 394 public: 424 395 readonly<TypeDecl> base; 396 // previously from renameTyVars; now directly use integer fields instead of synthesized strings 397 // a nonzero value of formal_usage indicates a formal type (only used in function type) 398 // a zero value of formal_usage indicates an actual type (referenced inside body of parametric structs and functions) 425 399 TypeDecl::Kind kind; 400 int formal_usage; 401 int expr_id; 402 403 // compact representation used for map lookups. 404 struct TypeEnvKey { 405 const TypeDecl * base; 406 int formal_usage; 407 int expr_id; 408 409 TypeEnvKey() = default; 410 TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0): base(base), formal_usage(formal_usage), expr_id(expr_id) {} 411 TypeEnvKey(const TypeInstType & inst): base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {} 412 std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; } 413 bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; } 414 415 }; 416 417 bool operator==(const TypeInstType & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; } 426 418 427 419 TypeInstType( … … 433 425 : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {} 434 426 435 TypeInstType( const TypeInstType & o ); 427 TypeInstType( const TypeInstType & o ) = default; 428 429 TypeInstType( const TypeEnvKey & key ) 430 : BaseInstType(key.base->name), base(key.base), kind(key.base->kind), formal_usage(key.formal_usage), expr_id(key.expr_id) {} 436 431 437 432 /// sets `base`, updating `kind` correctly … … 444 439 445 440 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 441 442 std::string typeString() const { 443 if (formal_usage > 0) return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + name; 444 else return name; 445 } 446 446 private: 447 447 TypeInstType * clone() const override { return new TypeInstType{ *this }; } … … 536 536 537 537 bool isUnboundType(const Type * type); 538 bool isUnboundType(const std::string & tname); 539 538 539 } 540 541 namespace std { 542 template<> 543 struct hash<typename ast::TypeInstType::TypeEnvKey> { 544 size_t operator() (const ast::TypeInstType::TypeEnvKey & x) const { 545 const size_t p = 1000007; 546 size_t res = reinterpret_cast<size_t>(x.base); 547 res = p * res + x.formal_usage; 548 res = p * res + x.expr_id; 549 return res; 550 } 551 }; 540 552 } 541 553 -
src/AST/TypeEnvironment.cpp
rb3c8496 r53449a4 52 52 for ( const auto & i : open ) { 53 53 if ( first ) { first = false; } else { out << ' '; } 54 out << i.first << "(" << i.second << ")";54 out << i.first.typeString() << "(" << i.second << ")"; 55 55 } 56 56 } … … 62 62 if(first) first = false; 63 63 else out << " "; 64 if( deterministic_output && isUnboundType(var) ) out << "[unbound]"; 65 else out << var; 64 65 if( deterministic_output ) out << "[unbound]"; 66 else out << "_" << var.formal_usage << "_" << var.expr_id << "_"; 67 68 out << var.base->name; 66 69 } 67 70 out << ")"; … … 79 82 } 80 83 81 const EqvClass * TypeEnvironment::lookup( const std::string& var ) const {84 const EqvClass * TypeEnvironment::lookup( const TypeInstType::TypeEnvKey & var ) const { 82 85 for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) { 83 86 if ( i->vars.find( var ) != i->vars.end() ) return &*i; … … 105 108 } 106 109 107 void TypeEnvironment::add( const ParameterizedType::ForallList & tyDecls ) {108 for ( const TypeDecl *tyDecl : tyDecls ) {110 void TypeEnvironment::add( const FunctionType::ForallList & tyDecls ) { 111 for ( auto & tyDecl : tyDecls ) { 109 112 env.emplace_back( tyDecl ); 110 113 } … … 119 122 void TypeEnvironment::writeToSubstitution( TypeSubstitution & sub ) const { 120 123 for ( const auto & clz : env ) { 121 std::string clzRep; 124 TypeInstType::TypeEnvKey clzRep; 125 bool first = true; 122 126 for ( const auto & var : clz.vars ) { 123 127 if ( clz.bound ) { 124 128 sub.add( var, clz.bound ); 125 } else if ( clzRep.empty()) {129 } else if ( first ) { 126 130 clzRep = var; 131 first = false; 127 132 } else { 128 sub.add( var, new TypeInstType{ clzRep , clz.data.kind} );133 sub.add( var, new TypeInstType{ clzRep } ); 129 134 } 130 135 } … … 141 146 struct Occurs : public ast::WithVisitorRef<Occurs> { 142 147 bool result; 143 std:: set< std::string> vars;148 std::unordered_set< TypeInstType::TypeEnvKey > vars; 144 149 const TypeEnvironment & tenv; 145 150 146 Occurs( const std::string& var, const TypeEnvironment & env )151 Occurs( const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env ) 147 152 : result( false ), vars(), tenv( env ) { 148 153 if ( const EqvClass * clz = tenv.lookup( var ) ) { … … 154 159 155 160 void previsit( const TypeInstType * typeInst ) { 156 if ( vars.count( typeInst->name) ) {161 if ( vars.count( *typeInst ) ) { 157 162 result = true; 158 } else if ( const EqvClass * clz = tenv.lookup( typeInst->name) ) {163 } else if ( const EqvClass * clz = tenv.lookup( *typeInst ) ) { 159 164 if ( clz->bound ) { 160 165 clz->bound->accept( *visitor ); … … 165 170 166 171 /// true if `var` occurs in `ty` under `env` 167 bool occurs( const Type * ty, const std::string& var, const TypeEnvironment & env ) {172 bool occurs( const Type * ty, const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env ) { 168 173 Pass<Occurs> occur{ var, env }; 169 174 maybe_accept( ty, occur ); … … 280 285 // remove references from bound type, so that type variables can only bind to value types 281 286 ptr<Type> target = bindTo->stripReferences(); 282 auto tyvar = open.find( typeInst->name);287 auto tyvar = open.find( *typeInst ); 283 288 assert( tyvar != open.end() ); 284 289 if ( ! tyVarCompatible( tyvar->second, target ) ) return false; 285 if ( occurs( target, typeInst->name, *this ) ) return false;286 287 auto it = internal_lookup( typeInst->name);290 if ( occurs( target, *typeInst, *this ) ) return false; 291 292 auto it = internal_lookup( *typeInst ); 288 293 if ( it != env.end() ) { 289 294 if ( it->bound ) { … … 308 313 } else { 309 314 env.emplace_back( 310 typeInst->name, target, widen.first && widen.second, data );315 *typeInst, target, widen.first && widen.second, data ); 311 316 } 312 317 return true; … … 318 323 WidenMode widen, const SymbolTable & symtab 319 324 ) { 320 auto c1 = internal_lookup( var1->name);321 auto c2 = internal_lookup( var2->name);325 auto c1 = internal_lookup( *var1 ); 326 auto c2 = internal_lookup( *var2 ); 322 327 323 328 // exit early if variables already bound together … … 333 338 if ( c1 != env.end() ) { 334 339 if ( c1->bound ) { 335 if ( occurs( c1->bound, var2->name, *this ) ) return false;340 if ( occurs( c1->bound, *var2, *this ) ) return false; 336 341 type1 = c1->bound; 337 342 } … … 340 345 if ( c2 != env.end() ) { 341 346 if ( c2->bound ) { 342 if ( occurs( c2->bound, var1->name, *this ) ) return false;347 if ( occurs( c2->bound, *var1, *this ) ) return false; 343 348 type2 = c2->bound; 344 349 } … … 378 383 } else if ( c1 != env.end() ) { 379 384 // var2 unbound, add to env[c1] 380 c1->vars.emplace( var2->name);385 c1->vars.emplace( *var2 ); 381 386 c1->allowWidening = widen1; 382 387 c1->data.isComplete |= data.isComplete; 383 388 } else if ( c2 != env.end() ) { 384 389 // var1 unbound, add to env[c2] 385 c2->vars.emplace( var1->name);390 c2->vars.emplace( *var1 ); 386 391 c2->allowWidening = widen2; 387 392 c2->data.isComplete |= data.isComplete; 388 393 } else { 389 394 // neither var bound, create new class 390 env.emplace_back( var1->name, var2->name, widen1 && widen2, data );395 env.emplace_back( *var1, *var2, widen1 && widen2, data ); 391 396 } 392 397 … … 452 457 } 453 458 454 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string& var ) {459 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const TypeInstType::TypeEnvKey & var ) { 455 460 for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) { 456 461 if ( i->vars.count( var ) ) return i; -
src/AST/TypeEnvironment.hpp
rb3c8496 r53449a4 55 55 /// recorded. More investigation is needed. 56 56 struct AssertCompare { 57 bool operator()( const DeclWithType * d1, const DeclWithType* d2 ) const {58 int cmp = d1-> name.compare( d2->name );59 return cmp < 0 || ( cmp == 0 && d1-> get_type() < d2->get_type());57 bool operator()( const VariableExpr * d1, const VariableExpr * d2 ) const { 58 int cmp = d1->var->name.compare( d2->var->name ); 59 return cmp < 0 || ( cmp == 0 && d1->result < d2->result ); 60 60 } 61 61 }; … … 70 70 71 71 /// Set of assertions pending satisfaction 72 using AssertionSet = std::map< readonly<DeclWithType>, AssertionSetValue, AssertCompare >;72 using AssertionSet = std::map< const VariableExpr *, AssertionSetValue, AssertCompare >; 73 73 74 74 /// Set of open variables 75 using OpenVarSet = std::unordered_map< std::string, TypeDecl::Data >;75 using OpenVarSet = std::unordered_map< TypeInstType::TypeEnvKey, TypeDecl::Data >; 76 76 77 77 /// Merges one set of open vars into another … … 89 89 /// they bind to. 90 90 struct EqvClass { 91 std:: set< std::string> vars;91 std::unordered_set< TypeInstType::TypeEnvKey > vars; 92 92 ptr<Type> bound; 93 93 bool allowWidening; … … 101 101 102 102 /// Singleton class constructor from TypeDecl 103 EqvClass( const Type Decl * decl)104 : vars{ decl->name }, bound(), allowWidening( true ), data( decl) {}103 EqvClass( const TypeInstType * inst ) 104 : vars{ *inst }, bound(), allowWidening( true ), data( inst->base ) {} 105 105 106 106 /// Singleton class constructor from substitution 107 EqvClass( const std::string& v, const Type * b )107 EqvClass( const TypeInstType::TypeEnvKey & v, const Type * b ) 108 108 : vars{ v }, bound( b ), allowWidening( false ), data( TypeDecl::Dtype, false ) {} 109 109 110 110 /// Single-var constructor (strips qualifiers from bound type) 111 EqvClass( const std::string& v, const Type * b, bool w, const TypeDecl::Data & d )111 EqvClass( const TypeInstType::TypeEnvKey & v, const Type * b, bool w, const TypeDecl::Data & d ) 112 112 : vars{ v }, bound( b ), allowWidening( w ), data( d ) { 113 113 reset_qualifiers( bound ); … … 115 115 116 116 /// Double-var constructor 117 EqvClass( const std::string & v, const std::string& u, bool w, const TypeDecl::Data & d )117 EqvClass( const TypeInstType::TypeEnvKey & v, const TypeInstType::TypeEnvKey & u, bool w, const TypeDecl::Data & d ) 118 118 : vars{ v, u }, bound(), allowWidening( w ), data( d ) {} 119 119 … … 131 131 public: 132 132 /// Finds the equivalence class containing a variable; nullptr for none such 133 const EqvClass * lookup( const std::string& var ) const;133 const EqvClass * lookup( const TypeInstType::TypeEnvKey & var ) const; 134 134 135 135 /// Add a new equivalence class for each type variable 136 void add( const ParameterizedType::ForallList & tyDecls );136 void add( const FunctionType::ForallList & tyDecls ); 137 137 138 138 /// Add a new equivalence class for each branch of the substitution, checking for conflicts … … 207 207 208 208 /// Private lookup API; returns array index of string, or env.size() for not found 209 ClassList::iterator internal_lookup( const std::string& );209 ClassList::iterator internal_lookup( const TypeInstType::TypeEnvKey & ); 210 210 }; 211 211 -
src/AST/TypeSubstitution.cpp
rb3c8496 r53449a4 39 39 void TypeSubstitution::initialize( const TypeSubstitution &src, TypeSubstitution &dest ) { 40 40 dest.typeEnv.clear(); 41 dest.varEnv.clear();42 41 dest.add( src ); 43 42 } … … 47 46 typeEnv[ i->first ] = i->second; 48 47 } // for 49 for ( VarEnvType::const_iterator i = other.varEnv.begin(); i != other.varEnv.end(); ++i ) {50 varEnv[ i->first ] = i->second;51 } // for52 48 } 53 49 54 void TypeSubstitution::add( std::stringformalType, const Type *actualType ) {55 typeEnv[ formalType ] = actualType;50 void TypeSubstitution::add( const TypeInstType * formalType, const Type *actualType ) { 51 typeEnv[ *formalType ] = actualType; 56 52 } 57 53 58 void TypeSubstitution::add Var( std::string formalExpr, const Expr *actualExpr) {59 varEnv[ formalExpr ] = actualExpr;54 void TypeSubstitution::add( const TypeInstType::TypeEnvKey & key, const Type * actualType) { 55 typeEnv[ key ] = actualType; 60 56 } 61 57 62 void TypeSubstitution::remove( std::stringformalType ) {63 TypeEnvType::iterator i = typeEnv.find( formalType );58 void TypeSubstitution::remove( const TypeInstType * formalType ) { 59 TypeEnvType::iterator i = typeEnv.find( *formalType ); 64 60 if ( i != typeEnv.end() ) { 65 typeEnv.erase( formalType );61 typeEnv.erase( *formalType ); 66 62 } // if 67 63 } 68 64 69 const Type *TypeSubstitution::lookup( std::stringformalType ) const {70 TypeEnvType::const_iterator i = typeEnv.find( formalType );65 const Type *TypeSubstitution::lookup( const TypeInstType * formalType ) const { 66 TypeEnvType::const_iterator i = typeEnv.find( *formalType ); 71 67 72 68 // break on not in substitution set … … 75 71 // attempt to transitively follow TypeInstType links. 76 72 while ( const TypeInstType *actualType = i->second.as<TypeInstType>()) { 77 const std::string& typeName = actualType->name;78 79 73 // break cycles in the transitive follow 80 if ( formalType == typeName ) break;74 if ( *formalType == *actualType ) break; 81 75 82 76 // Look for the type this maps to, returning previous mapping if none-such 83 i = typeEnv.find( typeName );77 i = typeEnv.find( *actualType ); 84 78 if ( i == typeEnv.end() ) return actualType; 85 79 } … … 90 84 91 85 bool TypeSubstitution::empty() const { 92 return typeEnv.empty() && varEnv.empty();86 return typeEnv.empty(); 93 87 } 94 88 … … 98 92 TypeSubstitution * newEnv; 99 93 EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} 100 void previsit( TypeDecl * tyDecl) {94 void previsit( FunctionType * ftype ) { 101 95 // transfer known bindings for seen type variables 102 if ( const Type * t = env->lookup( tyDecl->name ) ) { 103 newEnv->add( tyDecl->name, t ); 96 for (auto & formal : ftype->forall) { 97 if ( const Type * t = env->lookup( formal ) ) { 98 newEnv->add( formal, t ); 99 } 104 100 } 105 101 } … … 130 126 131 127 const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) { 132 BoundVarsType::const_iterator bound = boundVars.find( inst->name);128 BoundVarsType::const_iterator bound = boundVars.find( *inst ); 133 129 if ( bound != boundVars.end() ) return inst; 134 130 135 TypeEnvType::const_iterator i = sub.typeEnv.find( inst->name);131 TypeEnvType::const_iterator i = sub.typeEnv.find( *inst ); 136 132 if ( i == sub.typeEnv.end() ) { 137 133 return inst; … … 141 137 // TODO: investigate preventing type variables from being bound to themselves in the first place. 142 138 if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) { 143 if ( inst->name == replacement->name) {139 if ( *inst == *replacement ) { 144 140 return inst; 145 141 } … … 156 152 } 157 153 158 const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) { 159 VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name ); 160 if ( i == sub.varEnv.end() ) { 161 return nameExpr; 162 } else { 163 subCount++; 164 return i->second; 165 } // if 166 } 167 168 void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) { 154 void TypeSubstitution::Substituter::previsit( const FunctionType * ptype ) { 169 155 GuardValue( boundVars ); 170 156 // bind type variables from forall-qualifiers 171 157 if ( freeOnly ) { 172 for ( const TypeDecl *tyvar : ptype->forall ) {173 boundVars.insert( tyvar->name);158 for ( auto & tyvar : ptype->forall ) { 159 boundVars.insert( *tyvar ); 174 160 } // for 175 161 } // if 176 162 } 177 163 164 /* 178 165 void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) { 179 166 GuardValue( boundVars ); 180 167 // bind type variables from forall-qualifiers 181 168 if ( freeOnly ) { 182 for ( const TypeDecl * tyvar : type->forall ) {183 boundVars.insert( tyvar->name );184 } // for185 169 // bind type variables from generic type instantiations 186 170 if ( auto decl = type->aggr() ) { 187 171 if ( ! type->params.empty() ) { 188 172 for ( const TypeDecl * tyvar : decl->params ) { 189 boundVars.insert( tyvar->name);173 boundVars.insert( *tyvar ); 190 174 } // for 191 175 } // if … … 201 185 handleAggregateType( aggregateUseType ); 202 186 } 187 */ 203 188 204 189 } // namespace ast -
src/AST/TypeSubstitution.hpp
rb3c8496 r53449a4 69 69 } 70 70 71 void add( std::string formalType, const Type *actualType ); 71 void add( const TypeInstType * formalType, const Type *actualType ); 72 void add( const TypeInstType::TypeEnvKey & key, const Type *actualType ); 72 73 void add( const TypeSubstitution &other ); 73 void remove( std::stringformalType );74 const Type *lookup( std::stringformalType ) const;74 void remove( const TypeInstType * formalType ); 75 const Type *lookup( const TypeInstType * formalType ) const; 75 76 bool empty() const; 76 77 void addVar( std::string formalExpr, const Expr *actualExpr );78 77 79 78 template< typename FormalIterator, typename ActualIterator > … … 101 100 friend class Pass; 102 101 103 typedef std::unordered_map< std::string, ptr<Type> > TypeEnvType; 104 typedef std::unordered_map< std::string, ptr<Expr> > VarEnvType; 102 typedef std::unordered_map< TypeInstType::TypeEnvKey, ptr<Type> > TypeEnvType; 105 103 TypeEnvType typeEnv; 106 VarEnvType varEnv;107 104 108 105 public: … … 113 110 auto end() const -> decltype( typeEnv. end() ) { return typeEnv. end(); } 114 111 115 auto beginVar() -> decltype( varEnv.begin() ) { return varEnv.begin(); }116 auto endVar() -> decltype( varEnv. end() ) { return varEnv. end(); }117 auto beginVar() const -> decltype( varEnv.begin() ) { return varEnv.begin(); }118 auto endVar() const -> decltype( varEnv. end() ) { return varEnv. end(); }119 112 }; 120 113 114 // this is the only place where type parameters outside a function formal may be substituted. 121 115 template< typename FormalIterator, typename ActualIterator > 122 116 void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) { … … 129 123 if ( const TypeExpr *actual = actualIt->template as<TypeExpr>() ) { 130 124 if ( formal->name != "" ) { 131 typeEnv[ formal ->name] = actual->type;125 typeEnv[ formal ] = actual->type; 132 126 } // if 133 127 } else { … … 135 129 } // if 136 130 } else { 137 // TODO: type check the formal and actual parameters 138 if ( (*formalIt)->name != "" ) { 139 varEnv[ (*formalIt)->name ] = *actualIt; 140 } // if 131 141 132 } // if 142 133 } // for 143 134 } 135 136 144 137 145 138 template< typename FormalIterator, typename ActualIterator > … … 147 140 add( formalBegin, formalEnd, actualBegin ); 148 141 } 142 149 143 150 144 } // namespace ast … … 164 158 165 159 const Type * postvisit( const TypeInstType * aggregateUseType ); 166 const Expr * postvisit( const NameExpr * nameExpr );167 160 168 161 /// Records type variable bindings from forall-statements 169 void previsit( const ParameterizedType * type );162 void previsit( const FunctionType * type ); 170 163 /// Records type variable bindings from forall-statements and instantiations of generic types 171 void handleAggregateType( const BaseInstType * type );164 // void handleAggregateType( const BaseInstType * type ); 172 165 173 void previsit( const StructInstType * aggregateUseType );174 void previsit( const UnionInstType * aggregateUseType );166 // void previsit( const StructInstType * aggregateUseType ); 167 // void previsit( const UnionInstType * aggregateUseType ); 175 168 176 169 const TypeSubstitution & sub; 177 170 int subCount = 0; 178 171 bool freeOnly; 179 typedef std::unordered_set< std::string> BoundVarsType;172 typedef std::unordered_set< TypeInstType::TypeEnvKey > BoundVarsType; 180 173 BoundVarsType boundVars; 181 174 -
src/AST/module.mk
rb3c8496 r53449a4 33 33 AST/Expr.cpp \ 34 34 AST/Expr.hpp \ 35 AST/ForallSubstitutionTable.cpp \36 AST/ForallSubstitutionTable.hpp \37 AST/ForallSubstitutor.hpp \38 35 AST/FunctionSpec.hpp \ 39 36 AST/Fwd.hpp \ -
src/Common/PassVisitor.impl.h
rb3c8496 r53449a4 835 835 { 836 836 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 837 maybeAccept_impl( node->parameters, *this );838 837 maybeAccept_impl( node->base , *this ); 839 838 } … … 858 857 { 859 858 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 860 maybeAccept_impl( node->parameters, *this );861 859 maybeAccept_impl( node->base , *this ); 862 860 } … … 880 878 { 881 879 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 882 maybeMutate_impl( node->parameters, *this );883 880 maybeMutate_impl( node->base , *this ); 884 881 } … … 904 901 { 905 902 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 906 maybeAccept_impl( node->parameters, *this );907 903 maybeAccept_impl( node->base , *this ); 908 904 } … … 921 917 { 922 918 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 923 maybeAccept_impl( node->parameters, *this );924 919 maybeAccept_impl( node->base , *this ); 925 920 } … … 938 933 { 939 934 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 940 maybeMutate_impl( node->parameters, *this );941 935 maybeMutate_impl( node->base , *this ); 942 936 } -
src/GenPoly/GenPoly.cc
rb3c8496 r53449a4 115 115 if (!env) return type; 116 116 if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) { 117 auto newType = env->lookup(typeInst ->name);117 auto newType = env->lookup(typeInst); 118 118 if (newType) return newType; 119 119 } … … 172 172 173 173 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) { 174 return tyVars.find(typeInst-> name) != tyVars.end() ? type : nullptr;174 return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr; 175 175 } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) { 176 176 return isPolyType( arrayType->base, env ); … … 552 552 } 553 553 554 void addToTyVarMap( const ast::Type Decl* tyVar, TyVarMap & tyVarMap) {555 tyVarMap.insert(tyVar-> name, convData(ast::TypeDecl::Data{tyVar}));554 void addToTyVarMap( const ast::TypeInstType * tyVar, TyVarMap & tyVarMap) { 555 tyVarMap.insert(tyVar->typeString(), convData(ast::TypeDecl::Data{tyVar->base})); 556 556 } 557 557 … … 567 567 568 568 void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap) { 569 if (auto ptype = dynamic_cast<const ast:: ParameterizedType *>(type)) {569 if (auto ptype = dynamic_cast<const ast::FunctionType *>(type)) { 570 570 for (auto & tyVar : ptype->forall) { 571 571 assert (tyVar); -
src/Parser/TypeData.cc
rb3c8496 r53449a4 900 900 ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true ); 901 901 } // if 902 buildList( td->symbolic.params, ret->get_parameters() );903 902 buildList( td->symbolic.assertions, ret->get_assertions() ); 904 903 ret->base->attributes.splice( ret->base->attributes.end(), attributes ); -
src/ResolvExpr/AdjustExprType.cc
rb3c8496 r53449a4 133 133 const ast::Type * postvisit( const ast::TypeInstType * inst ) { 134 134 // replace known function-type-variables with pointer-to-function 135 if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name) ) {135 if ( const ast::EqvClass * eqvClass = tenv.lookup( *inst ) ) { 136 136 if ( eqvClass->data.kind == ast::TypeDecl::Ftype ) { 137 137 return new ast::PointerType{ inst }; -
src/ResolvExpr/CandidateFinder.cpp
rb3c8496 r53449a4 212 212 // mark type variable and specialization cost of forall clause 213 213 convCost.incVar( function->forall.size() ); 214 for ( const ast::TypeDecl * td : function->forall ) { 215 convCost.decSpec( td->assertions.size() ); 216 } 214 convCost.decSpec( function->assertions.size() ); 217 215 218 216 return convCost; … … 220 218 221 219 void makeUnifiableVars( 222 const ast:: ParameterizedType * type, ast::OpenVarSet & unifiableVars,220 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars, 223 221 ast::AssertionSet & need 224 222 ) { 225 for ( const ast::TypeDecl *tyvar : type->forall ) {226 unifiableVars[ tyvar->name ] = ast::TypeDecl::Data{ tyvar};227 for ( const ast::DeclWithType * assn : tyvar->assertions ) {228 need[ assn ].isUsed = true;229 }223 for ( auto & tyvar : type->forall ) { 224 unifiableVars[ *tyvar ] = ast::TypeDecl::Data{ tyvar->base }; 225 } 226 for ( auto & assn : type->assertions ) { 227 need[ assn ].isUsed = true; 230 228 } 231 229 } … … 953 951 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 954 952 ) { 955 if ( const ast::EqvClass * clz = func->env.lookup( inst->name) ) {953 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) { 956 954 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 957 955 CandidateRef newFunc{ new Candidate{ *func } }; … … 1077 1075 assert( toType ); 1078 1076 toType = resolveTypeof( toType, symtab ); 1079 toType = SymTab::validateType( castExpr->location, toType, symtab );1077 // toType = SymTab::validateType( castExpr->location, toType, symtab ); 1080 1078 toType = adjustExprType( toType, tenv, symtab ); 1081 1079 … … 1162 1160 1163 1161 if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) { 1164 auto td = cand->env.lookup( insttype->name);1162 auto td = cand->env.lookup(*insttype); 1165 1163 if(!td) { continue; } 1166 1164 expr = td->bound.get(); … … 1568 1566 // calculate target type 1569 1567 const ast::Type * toType = resolveTypeof( initAlt.type, symtab ); 1570 toType = SymTab::validateType( initExpr->location, toType, symtab );1568 // toType = SymTab::validateType( initExpr->location, toType, symtab ); 1571 1569 toType = adjustExprType( toType, tenv, symtab ); 1572 1570 // The call to find must occur inside this loop, otherwise polymorphic return -
src/ResolvExpr/CastCost.cc
rb3c8496 r53449a4 165 165 } else { 166 166 ast::TypeEnvironment newEnv{ env }; 167 if ( auto wParams = pointerType->base.as< ast:: ParameterizedType >() ) {167 if ( auto wParams = pointerType->base.as< ast::FunctionType >() ) { 168 168 newEnv.add( wParams->forall ); 169 169 } … … 202 202 ) { 203 203 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 204 if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name) ) {204 if ( const ast::EqvClass * eqvClass = env.lookup( *typeInst ) ) { 205 205 // check cast cost against bound type, if present 206 206 if ( eqvClass->bound ) { -
src/ResolvExpr/CommonType.cc
rb3c8496 r53449a4 713 713 const ast::Type * base = oPtr->base; 714 714 if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) { 715 auto entry = open.find( var->name);715 auto entry = open.find( *var ); 716 716 if ( entry != open.end() ) { 717 717 ast::AssertionSet need, have; -
src/ResolvExpr/ConversionCost.cc
rb3c8496 r53449a4 498 498 ) { 499 499 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 500 if ( const ast::EqvClass * eqv = env.lookup( inst->name) ) {500 if ( const ast::EqvClass * eqv = env.lookup( *inst ) ) { 501 501 if ( eqv->bound ) { 502 502 return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env ); … … 675 675 676 676 void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) { 677 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {677 if ( const ast::EqvClass * eqv = env.lookup( *typeInstType ) ) { 678 678 cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env ); 679 679 } else if ( const ast::TypeInstType * dstAsInst = 680 680 dynamic_cast< const ast::TypeInstType * >( dst ) ) { 681 if ( typeInstType->name == dstAsInst->name) {681 if ( *typeInstType == *dstAsInst ) { 682 682 cost = Cost::zero; 683 683 } -
src/ResolvExpr/FindOpenVars.cc
rb3c8496 r53449a4 112 112 // mark open/closed variables 113 113 if ( nextIsOpen ) { 114 for ( const ast::TypeDecl *decl : type->forall ) {115 open[ decl->name ] = ast::TypeDecl::Data{ decl};116 for ( const ast::DeclWithType * assert : decl->assertions ) {117 need[ assert ].isUsed = false;118 }114 for ( auto & decl : type->forall ) { 115 open[ *decl ] = ast::TypeDecl::Data{ decl->base }; 116 } 117 for ( auto & assert : type->assertions ) { 118 need[ assert ].isUsed = false; 119 119 } 120 120 } else { 121 for ( const ast::TypeDecl *decl : type->forall ) {122 closed[ decl->name ] = ast::TypeDecl::Data{ decl };123 for ( const ast::DeclWithType * assert : decl->assertions ) {124 have[ assert ].isUsed = false;125 }121 for ( auto & decl : type->forall ) { 122 closed[ *decl ] = ast::TypeDecl::Data{ decl->base }; 123 } 124 for ( auto & assert : type->assertions ) { 125 have[ assert ].isUsed = false; 126 126 } 127 127 } -
src/ResolvExpr/PolyCost.cc
rb3c8496 r53449a4 68 68 69 69 void previsit( const ast::TypeInstType * type ) { 70 if ( const ast::EqvClass * eqv = env_.lookup( type->name ) ) /* && */ if ( eqv->bound ) {70 if ( const ast::EqvClass * eqv = env_.lookup( *type ) ) /* && */ if ( eqv->bound ) { 71 71 if ( const ast::TypeInstType * otherType = eqv->bound.as< ast::TypeInstType >() ) { 72 72 if ( symtab.lookupType( otherType->name ) ) { -
src/ResolvExpr/PtrsAssignable.cc
rb3c8496 r53449a4 134 134 } 135 135 void postvisit( const ast::TypeInstType * inst ) { 136 if ( const ast::EqvClass * eqv = typeEnv.lookup( inst->name) ) {136 if ( const ast::EqvClass * eqv = typeEnv.lookup( *inst ) ) { 137 137 if ( eqv->bound ) { 138 138 // T * = S * for any S depends on the type bound to T … … 146 146 const ast::TypeEnvironment & env ) { 147 147 if ( const ast::TypeInstType * dstAsInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 148 if ( const ast::EqvClass * eqv = env.lookup( dstAsInst->name) ) {148 if ( const ast::EqvClass * eqv = env.lookup( *dstAsInst ) ) { 149 149 return ptrsAssignable( src, eqv->bound, env ); 150 150 } -
src/ResolvExpr/PtrsCastable.cc
rb3c8496 r53449a4 180 180 } 181 181 } 182 } else if ( const ast::EqvClass * eqvClass = env.lookup( inst->name) ) {182 } else if ( const ast::EqvClass * eqvClass = env.lookup( *inst ) ) { 183 183 if ( eqvClass->data.kind == ast::TypeDecl::Ftype ) { 184 184 return -1; … … 283 283 ) { 284 284 if ( auto inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 285 if ( const ast::EqvClass * eqvClass = env.lookup( inst->name) ) {285 if ( const ast::EqvClass * eqvClass = env.lookup( *inst ) ) { 286 286 return ptrsAssignable( src, eqvClass->bound, env ); 287 287 } -
src/ResolvExpr/RenameVars.cc
rb3c8496 r53449a4 19 19 #include <utility> // for pair 20 20 21 #include "AST/ForallSubstitutionTable.hpp"22 21 #include "AST/Pass.hpp" 23 22 #include "AST/Type.hpp" … … 39 38 int level = 0; 40 39 int resetCount = 0; 40 41 int next_expr_id = 1; 42 int next_usage_id = 1; 41 43 ScopedMap< std::string, std::string > nameMap; 44 ScopedMap< std::string, ast::TypeInstType::TypeEnvKey > idMap; 42 45 public: 43 ast::ForallSubstitutionTable subs;44 45 46 void reset() { 46 47 level = 0; … … 53 54 type->name = it->second; 54 55 } 56 } 57 58 void nextUsage() { 59 ++next_usage_id; 55 60 } 56 61 … … 78 83 79 84 const ast::TypeInstType * rename( const ast::TypeInstType * type ) { 80 // re-linking of base type handled by WithForallSubstitutor81 82 85 // rename 83 auto it = nameMap.find( type->name ); 84 if ( it != nameMap.end() ) { 85 // unconditionally mutate because map will *always* have different name, 86 // if this mutates, will *always* have been mutated by ForallSubstitutor above 87 ast::TypeInstType * mut = ast::mutate( type ); 88 mut->name = it->second; 86 auto it = idMap.find( type->name ); 87 if ( it != idMap.end() ) { 88 // unconditionally mutate because map will *always* have different name 89 ast::TypeInstType * mut = ast::shallowCopy( type ); 90 // reconcile base node since some copies might have been made 91 mut->base = it->second.base; 92 mut->formal_usage = it->second.formal_usage; 93 mut->expr_id = it->second.expr_id; 89 94 type = mut; 90 95 } … … 93 98 } 94 99 95 template<typename NodeT> 96 const NodeT * openLevel( const NodeT * type ) { 100 const ast::FunctionType * openLevel( const ast::FunctionType * type, RenameMode mode ) { 97 101 if ( type->forall.empty() ) return type; 98 99 nameMap.beginScope(); 102 idMap.beginScope(); 100 103 101 104 // Load new names from this forall clause and perform renaming. 102 NodeT * mutType = ast::mutate( type ); 103 assert( type == mutType && "mutated type must be unique from ForallSubstitutor" ); 104 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) { 105 std::ostringstream output; 106 output << "_" << resetCount << "_" << level << "_" << td->name; 107 std::string newname = output.str(); 108 nameMap[ td->name ] = newname; 109 ++level; 110 111 ast::TypeDecl * mutDecl = ast::mutate( td.get() ); 112 assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" ); 113 mutDecl->name = newname; 114 // assertion above means `td = mutDecl;` is unnecessary 115 } 116 // assertion above means `type = mutType;` is unnecessary 117 118 return type; 119 } 120 121 void closeLevel( const ast::ParameterizedType * type ) { 105 auto mutType = ast::shallowCopy( type ); 106 // assert( type == mutType && "mutated type must be unique from ForallSubstitutor" ); 107 for ( auto & td : mutType->forall ) { 108 auto mut = ast::shallowCopy( td.get() ); 109 // assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" ); 110 111 if (mode == GEN_EXPR_ID) { 112 mut->expr_id = next_expr_id; 113 mut->formal_usage = -1; 114 ++next_expr_id; 115 } 116 else if (mode == GEN_USAGE) { 117 assertf(mut->expr_id, "unfilled expression id in generating candidate type"); 118 mut->formal_usage = next_usage_id; 119 } 120 else { 121 assert(false); 122 } 123 idMap[ td->name ] = ast::TypeInstType::TypeEnvKey(*mut); 124 125 td = mut; 126 } 127 128 return mutType; 129 } 130 131 void closeLevel( const ast::FunctionType * type ) { 122 132 if ( type->forall.empty() ) return; 123 124 nameMap.endScope(); 133 idMap.endScope(); 125 134 } 126 135 }; … … 142 151 }; 143 152 144 struct RenameVars_new /*: public ast::WithForallSubstitutor*/ { 145 #warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor 146 ast::ForallSubstitutionTable & subs = renaming.subs; 153 struct RenameVars_new : public ast::PureVisitor /*: public ast::WithForallSubstitutor*/ { 154 RenameMode mode; 147 155 148 156 const ast::FunctionType * previsit( const ast::FunctionType * type ) { 149 return renaming.openLevel( type ); 150 } 157 return renaming.openLevel( type, mode ); 158 } 159 160 /* 151 161 const ast::StructInstType * previsit( const ast::StructInstType * type ) { 152 162 return renaming.openLevel( type ); … … 158 168 return renaming.openLevel( type ); 159 169 } 170 */ 171 160 172 const ast::TypeInstType * previsit( const ast::TypeInstType * type ) { 161 return renaming.rename( renaming.openLevel( type ) ); 162 } 163 void postvisit( const ast::ParameterizedType * type ) { 173 if (mode == GEN_USAGE && !type->formal_usage) return type; // do not rename an actual type 174 return renaming.rename( type ); 175 } 176 void postvisit( const ast::FunctionType * type ) { 164 177 renaming.closeLevel( type ); 165 178 } … … 173 186 } 174 187 175 const ast::Type * renameTyVars( const ast::Type * t ) {176 ast::Type *tc = ast::deepCopy(t);188 const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode ) { 189 // ast::Type *tc = ast::deepCopy(t); 177 190 ast::Pass<RenameVars_new> renamer; 178 // return t->accept( renamer ); 179 return tc->accept( renamer ); 191 renamer.core.mode = mode; 192 if (mode == GEN_USAGE) { 193 renaming.nextUsage(); 194 } 195 return t->accept( renamer ); 180 196 } 181 197 -
src/ResolvExpr/RenameVars.h
rb3c8496 r53449a4 30 30 /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID 31 31 void renameTyVars( Type * ); 32 const ast::Type * renameTyVars( const ast::Type * ); 32 33 enum RenameMode { 34 GEN_USAGE, // for type in VariableExpr 35 GEN_EXPR_ID // for type in decl 36 }; 37 const ast::Type * renameTyVars( const ast::Type *, RenameMode mode = GEN_USAGE ); 33 38 34 39 /// resets internal state of renamer to avoid overflow 35 40 void resetTyVarRenaming(); 41 42 36 43 } // namespace ResolvExpr 37 44 -
src/ResolvExpr/ResolveTypeof.cc
rb3c8496 r53449a4 15 15 16 16 #include "ResolveTypeof.h" 17 #include "RenameVars.h" 17 18 18 19 #include <cassert> // for assert … … 218 219 mutDecl->mangleName = Mangle::mangle(mutDecl); // do not mangle unnamed variables 219 220 221 mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID); 220 222 mutDecl->isTypeFixed = true; 221 223 return mutDecl; -
src/ResolvExpr/Resolver.cc
rb3c8496 r53449a4 968 968 namespace { 969 969 /// Finds deleted expressions in an expression tree 970 struct DeleteFinder_new final : public ast::WithShortCircuiting {970 struct DeleteFinder_new final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder_new> { 971 971 const ast::DeletedExpr * result = nullptr; 972 972 … … 976 976 } 977 977 978 void previsit( const ast::Expr * ) {978 void previsit( const ast::Expr * expr ) { 979 979 if ( result ) { visit_children = false; } 980 if (expr->inferred.hasParams()) { 981 for (auto & imp : expr->inferred.inferParams() ) { 982 imp.second.expr->accept(*visitor); 983 } 984 } 980 985 } 981 986 }; 982 987 } // anonymous namespace 983 984 988 /// Check if this expression is or includes a deleted expression 985 989 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { … … 1370 1374 } 1371 1375 1372 // handle assertions . (seems deep)1376 // handle assertions 1373 1377 1374 1378 symtab.enterScope(); 1375 for (auto & typeParam : mutType->forall) { 1376 auto mutParam = typeParam.get_and_mutate(); 1377 symtab.addType(mutParam); 1378 for (auto & asst : mutParam->assertions) { 1379 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab); 1380 symtab.addId(asst); 1381 } 1382 typeParam = mutParam; 1379 mutType->forall.clear(); 1380 mutType->assertions.clear(); 1381 for (auto & typeParam : mutDecl->type_params) { 1382 symtab.addType(typeParam); 1383 mutType->forall.emplace_back(new ast::TypeInstType(typeParam->name, typeParam)); 1384 } 1385 for (auto & asst : mutDecl->assertions) { 1386 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab); 1387 symtab.addId(asst); 1388 mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst)); 1383 1389 } 1384 1390 … … 1402 1408 mutType->returns = std::move(returnTypes); 1403 1409 1410 auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID)); 1411 1404 1412 std::list<ast::ptr<ast::Stmt>> newStmts; 1405 1413 resolveWithExprs (mutDecl->withExprs, newStmts); … … 1413 1421 symtab.leaveScope(); 1414 1422 1423 mutDecl->type = renamedType; 1415 1424 mutDecl->mangleName = Mangle::mangle(mutDecl); 1416 1425 mutDecl->isTypeFixed = true; -
src/ResolvExpr/SatisfyAssertions.cpp
rb3c8496 r53449a4 69 69 /// Reference to a single deferred item 70 70 struct DeferRef { 71 const ast:: DeclWithType * decl;71 const ast::VariableExpr * expr; 72 72 const ast::AssertionSetValue & info; 73 73 const AssnCandidate & match; … … 77 77 /// Acts like an indexed list of DeferRef 78 78 struct DeferItem { 79 const ast:: DeclWithType * decl;79 const ast::VariableExpr * expr; 80 80 const ast::AssertionSetValue & info; 81 81 AssnCandidateList matches; 82 82 83 83 DeferItem( 84 const ast:: DeclWithType* d, const ast::AssertionSetValue & i, AssnCandidateList && ms )85 : decl( d ), info( i ), matches( std::move( ms ) ) {}84 const ast::VariableExpr * d, const ast::AssertionSetValue & i, AssnCandidateList && ms ) 85 : expr( d ), info( i ), matches( std::move( ms ) ) {} 86 86 87 87 bool empty() const { return matches.empty(); } … … 89 89 AssnCandidateList::size_type size() const { return matches.size(); } 90 90 91 DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; }91 DeferRef operator[] ( unsigned i ) const { return { expr, info, matches[i] }; } 92 92 }; 93 93 … … 138 138 void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) { 139 139 for ( auto & i : have ) { 140 if ( i.second.isUsed ) { symtab.addId( i.first ); }140 if ( i.second.isUsed ) { symtab.addId( i.first->var ); } 141 141 } 142 142 } … … 144 144 /// Binds a single assertion, updating satisfaction state 145 145 void bindAssertion( 146 const ast:: DeclWithType * decl, const ast::AssertionSetValue & info, CandidateRef & cand,146 const ast::VariableExpr * expr, const ast::AssertionSetValue & info, CandidateRef & cand, 147 147 AssnCandidate & match, InferCache & inferred 148 148 ) { … … 156 156 157 157 // place newly-inferred assertion in proper location in cache 158 inferred[ info.resnSlot ][ decl->uniqueId ] = ast::ParamEntry{159 candidate->uniqueId, candidate, match.adjType, decl->get_type(), varExpr };158 inferred[ info.resnSlot ][ expr->var->uniqueId ] = ast::ParamEntry{ 159 candidate->uniqueId, candidate, match.adjType, expr->result, varExpr }; 160 160 } 161 161 … … 169 169 170 170 std::vector<ast::SymbolTable::IdData> candidates; 171 auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first-> name);171 auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->var->name); 172 172 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { 173 173 // prefilter special decls by argument type, if already known 174 ast::ptr<ast::Type> thisArgType = strict_dynamic_cast<const ast::PointerType *>(assn.first->get_type())->base174 ast::ptr<ast::Type> thisArgType = assn.first->result.strict_as<ast::PointerType>()->base 175 175 .strict_as<ast::FunctionType>()->params[0] 176 176 .strict_as<ast::ReferenceType>()->base; … … 184 184 } 185 185 else { 186 candidates = sat.symtab.lookupId(assn.first-> name);186 candidates = sat.symtab.lookupId(assn.first->var->name); 187 187 } 188 188 for ( const ast::SymbolTable::IdData & cdata : candidates ) { … … 194 194 // if we should implement the same rule here 195 195 // (i.e. error if unique best match is deleted) 196 if (candidate->isDeleted ) continue;196 if (candidate->isDeleted && candidate->linkage == ast::Linkage::AutoGen) continue; 197 197 198 198 // build independent unification context for candidate … … 200 200 ast::TypeEnvironment newEnv{ sat.cand->env }; 201 201 ast::OpenVarSet newOpen{ sat.cand->open }; 202 ast::ptr< ast::Type > toType = assn.first-> get_type();202 ast::ptr< ast::Type > toType = assn.first->result; 203 203 ast::ptr< ast::Type > adjType = 204 204 renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ) ); … … 337 337 // compute conversion cost from satisfying decl to assertion 338 338 cost += computeConversionCost( 339 assn.match.adjType, assn. decl->get_type(), false, symtab, env );339 assn.match.adjType, assn.expr->result, false, symtab, env ); 340 340 341 341 // mark vars+specialization on function-type assertions … … 350 350 cost.incVar( func->forall.size() ); 351 351 352 for ( const ast::TypeDecl * td : func->forall ) { 353 cost.decSpec( td->assertions.size() ); 354 } 352 cost.decSpec( func->assertions.size() ); 355 353 } 356 354 } … … 451 449 ss << (tabs-1) << "Too many non-unique satisfying assignments for assertions:\n"; 452 450 for ( const auto & d : sat.deferred ) { 453 ast::print( ss, d. decl, tabs );451 ast::print( ss, d.expr, tabs ); 454 452 } 455 453 … … 469 467 ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n"; 470 468 for ( const auto& d : sat.deferred ) { 471 ast::print( ss, d. decl, tabs );469 ast::print( ss, d.expr, tabs ); 472 470 } 473 471 … … 501 499 nextNewNeed.insert( match.need.begin(), match.need.end() ); 502 500 503 bindAssertion( r. decl, r.info, nextCand, match, nextInferred );501 bindAssertion( r.expr, r.info, nextCand, match, nextInferred ); 504 502 } 505 503 -
src/ResolvExpr/Unify.cc
rb3c8496 r53449a4 773 773 774 774 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 775 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name) ) {775 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) { 776 776 // expand ttype parameter into its actual type 777 777 if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) { … … 888 888 } 889 889 890 static void markAssertionSet( ast::AssertionSet & assns, const ast:: DeclWithType* assn ) {890 static void markAssertionSet( ast::AssertionSet & assns, const ast::VariableExpr * assn ) { 891 891 auto i = assns.find( assn ); 892 892 if ( i != assns.end() ) { … … 898 898 static void markAssertions( 899 899 ast::AssertionSet & assn1, ast::AssertionSet & assn2, 900 const ast:: ParameterizedType * type900 const ast::FunctionType * type 901 901 ) { 902 for ( const auto & tyvar : type->forall ) { 903 for ( const ast::DeclWithType * assert : tyvar->assertions ) { 904 markAssertionSet( assn1, assert ); 905 markAssertionSet( assn2, assert ); 906 } 902 for ( auto & assert : type->assertions ) { 903 markAssertionSet( assn1, assert ); 904 markAssertionSet( assn2, assert ); 907 905 } 908 906 } … … 1030 1028 1031 1029 void postvisit( const ast::TypeInstType * typeInst ) { 1032 assert( open.find( typeInst->name) == open.end() );1030 assert( open.find( *typeInst ) == open.end() ); 1033 1031 handleRefType( typeInst, type2 ); 1034 1032 } … … 1171 1169 auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 ); 1172 1170 ast::OpenVarSet::const_iterator 1173 entry1 = var1 ? open.find( var1->name) : open.end(),1174 entry2 = var2 ? open.find( var2->name) : open.end();1171 entry1 = var1 ? open.find( *var1 ) : open.end(), 1172 entry2 = var2 ? open.find( *var2 ) : open.end(); 1175 1173 bool isopen1 = entry1 != open.end(); 1176 1174 bool isopen2 = entry2 != open.end(); -
src/SymTab/Mangler.cc
rb3c8496 r53449a4 666 666 // skip if not including qualifiers 667 667 if ( typeMode ) return; 668 if ( auto ptype = dynamic_cast< const ast:: ParameterizedType * >(type) ) {668 if ( auto ptype = dynamic_cast< const ast::FunctionType * >(type) ) { 669 669 if ( ! ptype->forall.empty() ) { 670 670 std::list< std::string > assertionNames; 671 671 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 672 672 mangleName += Encoding::forall; 673 for ( const ast::TypeDecl *decl : ptype->forall ) {673 for ( auto & decl : ptype->forall ) { 674 674 switch ( decl->kind ) { 675 675 case ast::TypeDecl::Kind::Dtype: … … 686 686 } // switch 687 687 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind ); 688 for ( const ast::DeclWithType * assert : decl->assertions ) {689 ast::Pass<Mangler_new> sub_mangler(690 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );691 assert->accept( sub_mangler);692 assertionNames.push_back( sub_mangler.core.get_mangleName());693 acount++;694 } // for688 } // for 689 for ( auto & assert : ptype->assertions ) { 690 ast::Pass<Mangler_new> sub_mangler( 691 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 692 assert->var->accept( sub_mangler ); 693 assertionNames.push_back( sub_mangler.core.get_mangleName() ); 694 acount++; 695 695 } // for 696 696 mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_"; -
src/SymTab/Validate.cc
rb3c8496 r53449a4 1463 1463 } 1464 1464 1465 /* 1466 1465 1467 /// Associates forward declarations of aggregates with their definitions 1466 1468 class LinkReferenceToTypes_new final … … 1793 1795 static const node_t * forallFixer( 1794 1796 const CodeLocation & loc, const node_t * node, 1795 ast:: ParameterizedType::ForallList parent_t::* forallField1797 ast::FunctionType::ForallList parent_t::* forallField 1796 1798 ) { 1797 1799 for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) { … … 1844 1846 } 1845 1847 }; 1848 */ 1846 1849 } // anonymous namespace 1847 1850 1851 /* 1848 1852 const ast::Type * validateType( 1849 1853 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) { … … 1854 1858 return type->accept( lrt )->accept( fpd ); 1855 1859 } 1860 */ 1856 1861 1857 1862 } // namespace SymTab -
src/SynTree/Declaration.h
rb3c8496 r53449a4 181 181 public: 182 182 Type * base; 183 std::list< TypeDecl * > parameters;184 183 std::list< DeclarationWithType * > assertions; 185 184 … … 190 189 Type * get_base() const { return base; } 191 190 void set_base( Type * newValue ) { base = newValue; } 192 std::list< TypeDecl* > & get_parameters() { return parameters; }193 191 std::list< DeclarationWithType * >& get_assertions() { return assertions; } 194 192 -
src/SynTree/NamedTypeDecl.cc
rb3c8496 r53449a4 29 29 NamedTypeDecl::NamedTypeDecl( const NamedTypeDecl &other ) 30 30 : Parent( other ), base( maybeClone( other.base ) ) { 31 cloneAll( other.parameters, parameters );32 31 cloneAll( other.assertions, assertions ); 33 32 } … … 35 34 NamedTypeDecl::~NamedTypeDecl() { 36 35 delete base; 37 deleteAll( parameters );38 36 deleteAll( assertions ); 39 37 } … … 56 54 base->print( os, indent+1 ); 57 55 } // if 58 if ( ! parameters.empty() ) {59 os << endl << indent << "... with parameters" << endl;60 printAll( parameters, os, indent+1 );61 } // if62 56 if ( ! assertions.empty() ) { 63 57 os << endl << indent << "... with assertions" << endl; … … 76 70 base->print( os, indent+1 ); 77 71 } // if 78 if ( ! parameters.empty() ) {79 os << endl << indent << "... with parameters" << endl;80 printAll( parameters, os, indent+1 );81 } // if82 72 } 83 73 -
src/Tuples/TupleAssignment.cc
rb3c8496 r53449a4 504 504 505 505 std::vector< ast::ptr< ast::Expr > > match() override { 506 // temporary workaround for new and old ast to coexist and avoid name collision 507 static UniqueName lhsNamer( "__massassign_Ln" ); 508 static UniqueName rhsNamer( "__massassign_Rn" ); 506 static UniqueName lhsNamer( "__massassign_L" ); 507 static UniqueName rhsNamer( "__massassign_R" ); 509 508 // empty tuple case falls into this matcher 510 509 assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 ); … … 535 534 536 535 std::vector< ast::ptr< ast::Expr > > match() override { 537 // temporary workaround for new and old ast to coexist and avoid name collision 538 static UniqueName lhsNamer( "__multassign_Ln" ); 539 static UniqueName rhsNamer( "__multassign_Rn" ); 536 static UniqueName lhsNamer( "__multassign_L" ); 537 static UniqueName rhsNamer( "__multassign_R" ); 540 538 541 539 if ( lhs.size() != rhs.size() ) return {};
Note:
See TracChangeset
for help on using the changeset viewer.