- Timestamp:
- Dec 16, 2020, 2:43:12 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:
- 53449a4
- Parents:
- 13fece5
- Location:
- src/AST
- Files:
-
- 3 deleted
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
r13fece5 r3e5dd913 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); … … 602 607 603 608 for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) { 604 rslt->add( src_i->first ,609 rslt->add( src_i->first.typeString(), 605 610 get<Type>().accept1(src_i->second) ); 606 }607 608 for (decltype(src->beginVar()) src_i = src->beginVar(); src_i != src->endVar(); src_i++) {609 rslt->addVar( src_i->first,610 get<Expression>().accept1(src_i->second) );611 611 } 612 612 … … 1212 1212 // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns ); 1213 1213 // ty->parameters = get<DeclarationWithType>().acceptL( node->params ); 1214 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 1215 1235 return visitType( node, ty ); 1216 1236 } … … 1299 1319 ty = new TypeInstType{ 1300 1320 cv( node ), 1301 node-> name,1321 node->typeString(), 1302 1322 get<TypeDecl>().accept1( node->base ), 1303 1323 get<Attribute>().acceptL( node->attributes ) … … 1306 1326 ty = new TypeInstType{ 1307 1327 cv( node ), 1308 node-> name,1328 node->typeString(), 1309 1329 node->kind == ast::TypeDecl::Ftype, 1310 1330 get<Attribute>().acceptL( node->attributes ) … … 1431 1451 /// at conversion stage, all created nodes are guaranteed to be unique, therefore 1432 1452 /// const_casting out of smart pointers is permitted. 1433 std::unordered_map< const BaseSyntaxNode *, ast:: ptr<ast::Node> > cache = {};1453 std::unordered_map< const BaseSyntaxNode *, ast::readonly<ast::Node> > cache = {}; 1434 1454 1435 1455 // Local Utilities: … … 1565 1585 // can function type have attributes? seems not to be the case. 1566 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 } 1567 1599 1568 1600 auto decl = new ast::FunctionDecl{ … … 1584 1616 cache.emplace( old, decl ); 1585 1617 1618 decl->assertions = std::move(assertions); 1586 1619 decl->withExprs = GET_ACCEPT_V(withExprs, Expr); 1587 1620 decl->stmts = GET_ACCEPT_1(statements, CompoundStmt); … … 2066 2099 } 2067 2100 2101 // TypeSubstitution shouldn't exist yet in old. 2068 2102 ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) { 2069 2103 2070 2104 if (!old) return nullptr; 2071 2105 if (old->empty()) return nullptr; 2106 assert(false); 2107 2108 /* 2072 2109 ast::TypeSubstitution *rslt = new ast::TypeSubstitution(); 2073 2110 … … 2077 2114 } 2078 2115 2079 for (decltype(old->beginVar()) old_i = old->beginVar(); old_i != old->endVar(); old_i++) {2080 rslt->addVar( old_i->first,2081 getAccept1<ast::Expr>(old_i->second) );2082 }2083 2084 2116 return rslt; 2117 */ 2085 2118 } 2086 2119 … … 2610 2643 ty->params.emplace_back(v->get_type()); 2611 2644 } 2612 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 } 2613 2655 visitType( old, ty ); 2614 2656 } -
src/AST/Decl.cpp
r13fece5 r3e5dd913 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
r13fece5 r3e5dd913 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, -
src/AST/Expr.cpp
r13fece5 r3e5dd913 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/Pass.hpp
r13fece5 r3e5dd913 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 … … 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
r13fece5 r3e5dd913 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 ); … … 1758 1743 1759 1744 VISIT({ 1760 guard_forall_subs forall_guard { *this, node }; 1761 mutate_forall( node ); 1745 // guard_forall_subs forall_guard { *this, node }; 1746 // mutate_forall( node ); 1747 maybe_accept( node, &FunctionType::assertions ); 1762 1748 maybe_accept( node, &FunctionType::returns ); 1763 1749 maybe_accept( node, &FunctionType::params ); … … 1981 1967 { 1982 1968 bool mutated = false; 1983 std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;1969 std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map; 1984 1970 for ( const auto & p : node->typeEnv ) { 1985 1971 guard_symtab guard { *this }; … … 1994 1980 } 1995 1981 } 1996 1997 {1998 bool mutated = false;1999 std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;2000 for ( const auto & p : node->varEnv ) {2001 guard_symtab guard { *this };2002 auto new_node = p.second->accept( *this );2003 if (new_node != p.second) mutated = true;2004 new_map.insert({ p.first, new_node });2005 }2006 if (mutated) {2007 auto new_node = __pass::mutate<core_t>( node );2008 new_node->varEnv.swap( new_map );2009 node = new_node;2010 }2011 }2012 1982 ) 2013 1983 -
src/AST/Pass.proto.hpp
r13fece5 r3e5dd913 413 413 static inline auto leave( core_t &, long, const ast::FunctionType * ) {} 414 414 415 // Get the substitution table, if present416 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; }423 424 415 // Replaces a TypeInstType's base TypeDecl according to the table 425 416 template<typename core_t> -
src/AST/Print.cpp
r13fece5 r3e5dd913 155 155 } 156 156 157 void print( const ast::FunctionType::AssertionList & assts ) { 158 if (assts.empty()) return; 159 os << "with assertions" << endl; 160 ++indent; 161 printAll(assts); 162 os << indent; 163 --indent; 164 } 165 157 166 void print( const std::vector<ptr<Attribute>> & attrs ) { 158 167 if ( attrs.empty() ) return; … … 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 … … 261 269 void preprint( const ast::FunctionType * node ) { 262 270 print( node->forall ); 271 print( node->assertions ); 263 272 print( node->qualifiers ); 264 273 } … … 1375 1384 virtual const ast::Type * visit( const ast::TypeInstType * node ) override final { 1376 1385 preprint( node ); 1377 const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node-> name;1386 const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->typeString(); 1378 1387 os << "instance of type " << _name 1379 1388 << " (" << (node->kind == ast::TypeDecl::Ftype ? "" : "not ") << "function type)"; … … 1502 1511 os << indent << "Types:" << endl; 1503 1512 for ( const auto& i : *node ) { 1504 os << indent+1 << i.first << " -> ";1513 os << indent+1 << i.first.typeString() << " -> "; 1505 1514 indent += 2; 1506 1515 safe_print( i.second ); 1507 indent -= 2;1508 os << endl;1509 }1510 os << indent << "Non-types:" << endl;1511 for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {1512 os << indent+1 << i->first << " -> ";1513 indent += 2;1514 safe_print( i->second );1515 1516 indent -= 2; 1516 1517 os << endl; -
src/AST/SymbolTable.cpp
r13fece5 r3e5dd913 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/Type.cpp
r13fece5 r3e5dd913 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 FunctionType::initWithSub(97 const FunctionType & o, Pass< ForallSubstitutor > & sub98 ) {99 forall = sub.core( o.forall );100 }101 102 93 // --- FunctionType 103 104 105 FunctionType::FunctionType( const FunctionType & o )106 : Type( 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 ) { … … 199 179 // TODO: once TypeInstType representation is updated, it should properly check 200 180 // if the context id is filled. this is a temporary hack for now 201 return isUnboundType(typeInst->name); 202 } 203 return false; 204 } 205 206 bool isUnboundType(const std::string & tname) { 207 // xxx - look for a type name produced by renameTyVars. 208 209 // TODO: once TypeInstType representation is updated, it should properly check 210 // if the context id is filled. this is a temporary hack for now 211 if (std::count(tname.begin(), tname.end(), '_') >= 3) { 212 return true; 181 return typeInst->formal_usage > 0; 213 182 } 214 183 return false; -
src/AST/Type.hpp
r13fece5 r3e5dd913 36 36 37 37 template< typename T > class Pass; 38 39 struct ForallSubstitutor;40 38 41 39 class Type : public Node { … … 272 270 /// Type of a function `[R1, R2](*)(P1, P2, P3)` 273 271 class FunctionType final : public Type { 274 protected: 275 /// initializes forall with substitutor 276 void initWithSub( const FunctionType & o, Pass< ForallSubstitutor > & sub ); 277 public: 278 using ForallList = std::vector<ptr<TypeDecl>>; 272 public: 273 using ForallList = std::vector<ptr<TypeInstType>>; 274 using AssertionList = std::vector<ptr<VariableExpr>>; 279 275 ForallList forall; 276 AssertionList assertions; 280 277 281 278 std::vector<ptr<Type>> returns; … … 292 289 : Type(q), returns(), params(), isVarArgs(va) {} 293 290 294 FunctionType( const FunctionType & o ) ;291 FunctionType( const FunctionType & o ) = default; 295 292 296 293 /// true if either the parameters or return values contain a tttype … … 397 394 public: 398 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) 399 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; } 400 418 401 419 TypeInstType( … … 409 427 TypeInstType( const TypeInstType & o ) = default; 410 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) {} 431 411 432 /// sets `base`, updating `kind` correctly 412 433 void set_base( const TypeDecl * ); … … 418 439 419 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 } 420 446 private: 421 447 TypeInstType * clone() const override { return new TypeInstType{ *this }; } … … 510 536 511 537 bool isUnboundType(const Type * type); 512 bool isUnboundType(const std::string & tname); 513 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 }; 514 552 } 515 553 -
src/AST/TypeEnvironment.cpp
r13fece5 r3e5dd913 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; … … 106 109 107 110 void TypeEnvironment::add( const FunctionType::ForallList & tyDecls ) { 108 for ( const TypeDecl *tyDecl : 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
r13fece5 r3e5dd913 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 … … 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
r13fece5 r3e5dd913 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 } // if166 }167 168 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 ); … … 184 171 if ( ! type->params.empty() ) { 185 172 for ( const TypeDecl * tyvar : decl->params ) { 186 boundVars.insert( tyvar->name);173 boundVars.insert( *tyvar ); 187 174 } // for 188 175 } // if … … 198 185 handleAggregateType( aggregateUseType ); 199 186 } 187 */ 200 188 201 189 } // namespace ast -
src/AST/TypeSubstitution.hpp
r13fece5 r3e5dd913 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 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
r13fece5 r3e5dd913 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 \
Note:
See TracChangeset
for help on using the changeset viewer.