Changes in / [7030dab:057298e]
- Files:
-
- 1 added
- 7 deleted
- 47 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Attribute.hpp
r7030dab r057298e 51 51 template<typename node_t> 52 52 friend node_t * mutate(const node_t * node); 53 template<typename node_t>54 friend node_t * shallowCopy(const node_t * node);55 53 }; 56 54 -
src/AST/CVQualifiers.hpp
r7030dab r057298e 27 27 Restrict = 1 << 1, 28 28 Volatile = 1 << 2, 29 Mutex = 1 << 3, 30 Atomic = 1 << 4, 31 NumQualifiers = 5 29 Lvalue = 1 << 3, 30 Mutex = 1 << 4, 31 Atomic = 1 << 5, 32 NumQualifiers = 6 32 33 }; 33 34 34 35 /// Mask for equivalence-preserving qualfiers 35 enum { EquivQualifiers = ~ Restrict};36 enum { EquivQualifiers = ~(Restrict | Lvalue) }; 36 37 37 38 /// Underlying data for qualifiers … … 43 44 bool is_restrict : 1; 44 45 bool is_volatile : 1; 46 bool is_lvalue : 1; 45 47 bool is_mutex : 1; 46 48 bool is_atomic : 1; -
src/AST/Convert.cpp
r7030dab r057298e 620 620 621 621 tgt->result = get<Type>().accept1(src->result); 622 // Unconditionally use a clone of the result type.623 // We know this will leak some objects: much of the immediate conversion result.624 // In some cases, using the conversion result directly gives unintended object sharing.625 // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.626 // But tgt->result must be fully owned privately by tgt.627 // Applying these conservative copies here means628 // - weak references point at the declaration's copy, not these expr.result copies (good)629 // - we copy more objects than really needed (bad, tolerated)630 if (tgt->result) {631 tgt->result = tgt->result->clone();632 }633 622 return visitBaseExpr_skipResultType(src, tgt); 634 623 } … … 2128 2117 old->location, 2129 2118 GET_ACCEPT_1(member, DeclWithType), 2130 GET_ACCEPT_1(aggregate, Expr), 2131 ast::MemberExpr::NoOpConstructionChosen 2119 GET_ACCEPT_1(aggregate, Expr) 2132 2120 ) 2133 2121 ); -
src/AST/Decl.cpp
r7030dab r057298e 50 50 51 51 const Type * FunctionDecl::get_type() const { return type.get(); } 52 void FunctionDecl::set_type( const Type * t ) { 53 type = strict_dynamic_cast< const FunctionType * >( t ); 54 } 52 void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); } 55 53 56 54 // --- TypeDecl -
src/AST/Decl.hpp
r7030dab r057298e 33 33 34 34 // Must be included in *all* AST classes; should be #undef'd at the end of the file 35 #define MUTATE_FRIEND \ 36 template<typename node_t> friend node_t * mutate(const node_t * node); \ 37 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 35 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 38 36 39 37 namespace ast { … … 90 88 virtual const Type * get_type() const = 0; 91 89 /// Set type of this declaration. May be verified by subclass 92 virtual void set_type( const Type *) = 0;90 virtual void set_type(Type *) = 0; 93 91 94 92 const DeclWithType * accept( Visitor & v ) const override = 0; … … 113 111 114 112 const Type* get_type() const override { return type; } 115 void set_type( constType * ty ) override { type = ty; }113 void set_type( Type * ty ) override { type = ty; } 116 114 117 115 const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); } … … 135 133 136 134 const Type * get_type() const override; 137 void set_type( const Type * t) override;135 void set_type(Type * t) override; 138 136 139 137 bool has_body() const { return stmts; } … … 152 150 std::vector<ptr<DeclWithType>> assertions; 153 151 154 NamedTypeDecl( 155 const CodeLocation & loc, const std::string & name, Storage::Classes storage, 156 const Type * b, Linkage::Spec spec = Linkage::Cforall ) 152 NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 153 Type* b, Linkage::Spec spec = Linkage::Cforall ) 157 154 : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {} 158 155 … … 189 186 }; 190 187 191 TypeDecl( 192 const CodeLocation & loc, const std::string & name, Storage::Classes storage, 193 const Type * b, TypeVar::Kind k, bool s, const Type * i = nullptr ) 194 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ), 195 init( i ) {} 188 TypeDecl( const CodeLocation & loc, const std::string & name, Storage::Classes storage, Type * b, 189 Kind k, bool s, Type * i = nullptr ) 190 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ), 191 init( i ) {} 196 192 197 193 const char * typeString() const override; -
src/AST/Expr.cpp
r7030dab r057298e 20 20 #include <vector> 21 21 22 #include "Copy.hpp" // for shallowCopy23 #include "Eval.hpp" // for call24 22 #include "GenericSubstitution.hpp" 25 #include "LinkageSpec.hpp"26 23 #include "Stmt.hpp" 27 24 #include "Type.hpp" … … 30 27 #include "Common/SemanticError.h" 31 28 #include "GenPoly/Lvalue.h" // for referencesPermissable 32 #include "InitTweak/InitTweak.h" // for get Function, getPointerBase29 #include "InitTweak/InitTweak.h" // for getPointerBase 33 30 #include "ResolvExpr/typeops.h" // for extractResultType 34 31 #include "Tuples/Tuples.h" // for makeTupleType 35 32 36 33 namespace ast { 37 38 namespace {39 std::set<std::string> const lvalueFunctionNames = {"*?", "?[?]"};40 }41 42 // --- Expr43 bool Expr::get_lvalue() const {44 return false;45 }46 34 47 35 // --- ApplicationExpr … … 58 46 } 59 47 60 bool ApplicationExpr::get_lvalue() const {61 if ( const DeclWithType * func = InitTweak::getFunction( this ) ) {62 return func->linkage == Linkage::Intrinsic && lvalueFunctionNames.count( func->name );63 }64 return false;65 }66 67 48 // --- UntypedExpr 68 49 … … 70 51 assert( arg ); 71 52 72 UntypedExpr * ret = call( loc, "*?", arg ); 53 UntypedExpr * ret = new UntypedExpr{ 54 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } } 55 }; 73 56 if ( const Type * ty = arg->result ) { 74 57 const Type * base = InitTweak::getPointerBase( ty ); … … 82 65 // base type 83 66 ret->result = base; 67 add_qualifiers( ret->result, CV::Lvalue ); 84 68 } 85 69 } 86 70 return ret; 87 }88 89 bool UntypedExpr::get_lvalue() const {90 std::string fname = InitTweak::getFunctionName( this );91 return lvalueFunctionNames.count( fname );92 71 } 93 72 … … 95 74 assert( lhs && rhs ); 96 75 97 UntypedExpr * ret = call( loc, "?=?", lhs, rhs ); 76 UntypedExpr * ret = new UntypedExpr{ 77 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } } 78 }; 98 79 if ( lhs->result && rhs->result ) { 99 80 // if both expressions are typed, assumes that this assignment is a C bitwise assignment, … … 127 108 AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) { 128 109 if ( arg->result ) { 129 if ( arg-> get_lvalue() ) {110 if ( arg->result->is_lvalue() ) { 130 111 // lvalue, retains all levels of reference, and gains a pointer inside the references 131 112 Type * res = addrType( arg->result ); 113 res->set_lvalue( false ); // result of & is never an lvalue 132 114 result = res; 133 115 } else { … … 136 118 dynamic_cast< const ReferenceType * >( arg->result.get() ) ) { 137 119 Type * res = addrType( refType->base ); 120 res->set_lvalue( false ); // result of & is never an lvalue 138 121 result = res; 139 122 } else { … … 156 139 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {} 157 140 158 bool CastExpr::get_lvalue() const {159 // This is actually wrong by C, but it works with our current set-up.160 return arg->get_lvalue();161 }162 163 141 // --- KeywordCastExpr 164 142 165 143 const char * KeywordCastExpr::targetString() const { 166 144 return AggregateDecl::aggrString( target ); 167 }168 169 // --- UntypedMemberExpr170 171 bool UntypedMemberExpr::get_lvalue() const {172 return aggregate->get_lvalue();173 145 } 174 146 … … 181 153 assert( aggregate->result ); 182 154 183 // Deep copy on result type avoids mutation on transitively multiply referenced object. 184 // 185 // Example, adapted from parts of builtins and bootloader: 186 // 187 // forall(dtype T) 188 // struct __Destructor { 189 // T * object; 190 // void (*dtor)(T *); 191 // }; 192 // 193 // forall(dtype S) 194 // void foo(__Destructor(S) &d) { 195 // if (d.dtor) { // here 196 // } 197 // } 198 // 199 // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve. Let d be the 200 // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level 201 // declaration of __Destructor. Consider the types e.result and d.type. In the old AST, one 202 // is a clone of the other. Ordinary new-AST use would set them up as a multiply-referenced 203 // object. 204 // 205 // e.result: PointerType 206 // .base: FunctionType 207 // .params.front(): ObjectDecl, the anonymous parameter of type T* 208 // .type: PointerType 209 // .base: TypeInstType 210 // let x = that 211 // let y = similar, except start from d.type 212 // 213 // Consider two code lines down, genericSubstitution(...).apply(result). 214 // 215 // Applying this chosen-candidate's type substitution means modifying x, substituting 216 // S for T. This mutation should affect x and not y. 217 218 result = deepCopy(mem->get_type()); 219 155 // take ownership of member type 156 result = mem->get_type(); 220 157 // substitute aggregate generic parameters into member type 221 158 genericSubstitution( aggregate->result ).apply( result ); 222 // ensure appropriate restrictions from aggregate type 223 add_qualifiers( result, aggregate->result->qualifiers ); 224 } 225 226 MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg, 227 MemberExpr::NoOpConstruction overloadSelector ) 228 : Expr( loc ), member( mem ), aggregate( agg ) { 229 assert( member ); 230 assert( aggregate ); 231 assert( aggregate->result ); 232 (void) overloadSelector; 233 } 234 235 bool MemberExpr::get_lvalue() const { 236 // This is actually wrong by C, but it works with our current set-up. 237 return true; 159 // ensure lvalue and appropriate restrictions from aggregate type 160 add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue ); 238 161 } 239 162 … … 247 170 assert( var ); 248 171 assert( var->get_type() ); 249 result = shallowCopy( var->get_type() ); 250 } 251 252 bool VariableExpr::get_lvalue() const { 253 // It isn't always an lvalue, but it is never an rvalue. 254 return true; 172 result = var->get_type(); 173 add_qualifiers( result, CV::Lvalue ); 255 174 } 256 175 … … 338 257 const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia ) 339 258 : Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {} 340 341 // --- CommaExpr342 bool CommaExpr::get_lvalue() const {343 // This is wrong by C, but the current implementation uses it.344 // (ex: Specialize, Lvalue and Box)345 return arg2->get_lvalue();346 }347 259 348 260 // --- ConstructorExpr … … 364 276 assert( t && i ); 365 277 result = t; 366 } 367 368 bool CompoundLiteralExpr::get_lvalue() const { 369 return true; 278 add_qualifiers( result, CV::Lvalue ); 370 279 } 371 280 … … 384 293 // like MemberExpr, TupleIndexExpr is always an lvalue 385 294 result = type->types[ index ]; 386 } 387 388 bool TupleIndexExpr::get_lvalue() const { 389 return tuple->get_lvalue(); 295 add_qualifiers( result, CV::Lvalue ); 390 296 } 391 297 -
src/AST/Expr.hpp
r7030dab r057298e 31 31 32 32 // Must be included in *all* AST classes; should be #undef'd at the end of the file 33 #define MUTATE_FRIEND \ 34 template<typename node_t> friend node_t * mutate(const node_t * node); \ 35 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 36 33 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 37 34 38 35 class ConverterOldToNew; … … 188 185 189 186 Expr * set_extension( bool ex ) { extension = ex; return this; } 190 virtual bool get_lvalue() const;191 187 192 188 virtual const Expr * accept( Visitor & v ) const override = 0; … … 205 201 ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ); 206 202 207 bool get_lvalue() const final;208 209 203 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 210 204 private: … … 221 215 UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ) 222 216 : Expr( loc ), func( f ), args( std::move(as) ) {} 223 224 bool get_lvalue() const final;225 217 226 218 /// Creates a new dereference expression … … 299 291 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {} 300 292 301 bool get_lvalue() const final;302 303 293 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 304 294 private: … … 348 338 : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); } 349 339 350 bool get_lvalue() const final;351 352 340 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 353 341 private: … … 364 352 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg ); 365 353 366 bool get_lvalue() const final;367 368 354 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 369 355 private: 370 356 MemberExpr * clone() const override { return new MemberExpr{ *this }; } 371 357 MUTATE_FRIEND 372 373 // Custructor overload meant only for AST conversion374 enum NoOpConstruction { NoOpConstructionChosen };375 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,376 NoOpConstruction overloadSelector );377 friend class ::ConverterOldToNew;378 friend class ::ConverterNewToOld;379 358 }; 380 359 … … 386 365 VariableExpr( const CodeLocation & loc ); 387 366 VariableExpr( const CodeLocation & loc, const DeclWithType * v ); 388 389 bool get_lvalue() const final;390 367 391 368 /// generates a function pointer for a given function … … 555 532 556 533 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 557 : Expr( loc ), arg1( a1 ), arg2( a2 ) { 558 this->result = a2->result; 559 } 560 561 bool get_lvalue() const final; 534 : Expr( loc ), arg1( a1 ), arg2( a2 ) {} 562 535 563 536 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 632 605 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i ); 633 606 634 bool get_lvalue() const final;635 636 607 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 637 608 private: … … 689 660 690 661 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i ); 691 692 bool get_lvalue() const final;693 662 694 663 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } -
src/AST/Init.hpp
r7030dab r057298e 25 25 26 26 // Must be included in *all* AST classes; should be #undef'd at the end of the file 27 #define MUTATE_FRIEND \ 28 template<typename node_t> friend node_t * mutate(const node_t * node); \ 29 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 27 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 30 28 31 29 namespace ast { -
src/AST/Node.cpp
r7030dab r057298e 17 17 #include "Fwd.hpp" 18 18 19 #include <csignal> // MEMORY DEBUG -- for raise20 19 #include <iostream> 21 20 … … 30 29 #include "Print.hpp" 31 30 32 /// MEMORY DEBUG -- allows breaking on ref-count changes of dynamically chosen object. 33 /// Process to use in GDB: 34 /// break ast::Node::_trap() 35 /// run 36 /// set variable MEM_TRAP_OBJ = <target> 37 /// disable <first breakpoint> 38 /// continue 39 void * MEM_TRAP_OBJ = nullptr; 40 41 void _trap( const void * node ) { 42 if ( node == MEM_TRAP_OBJ ) std::raise(SIGTRAP); 43 } 44 45 template< typename node_t, enum ast::Node::ref_type ref_t > 46 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { 47 node->increment(ref_t); 48 _trap( node ); 49 } 50 51 template< typename node_t, enum ast::Node::ref_type ref_t > 52 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node, bool do_delete ) { 53 _trap( node ); 54 node->decrement(ref_t, do_delete ); 55 } 56 57 template< typename node_t, enum ast::Node::ref_type ref_t > 58 void ast::ptr_base<node_t, ref_t>::_check() const { 59 // if(node) assert(node->was_ever_strong == false || node->strong_count > 0); 60 } 31 template< typename node_t, enum ast::Node::ref_type ref_t > 32 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); } 33 34 template< typename node_t, enum ast::Node::ref_type ref_t > 35 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); } 36 37 template< typename node_t, enum ast::Node::ref_type ref_t > 38 void ast::ptr_base<node_t, ref_t>::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); } 61 39 62 40 template< typename node_t, enum ast::Node::ref_type ref_t > -
src/AST/Node.hpp
r7030dab r057298e 38 38 Node& operator= (const Node&) = delete; 39 39 Node& operator= (Node&&) = delete; 40 virtual ~Node() {}40 virtual ~Node() = default; 41 41 42 42 virtual const Node * accept( Visitor & v ) const = 0; … … 57 57 template<typename node_t> 58 58 friend node_t * mutate(const node_t * node); 59 template<typename node_t>60 friend node_t * shallowCopy(const node_t * node);61 59 62 60 mutable size_t strong_count = 0; … … 71 69 } 72 70 73 void decrement(ast::Node::ref_type ref , bool do_delete = true) const {71 void decrement(ast::Node::ref_type ref) const { 74 72 switch (ref) { 75 73 case ref_type::strong: strong_count--; break; … … 77 75 } 78 76 79 if( do_delete &&!strong_count && !weak_count) {77 if(!strong_count && !weak_count) { 80 78 delete this; 81 79 } … … 96 94 assertf( 97 95 node->weak_count == 0, 98 "Error: mutating node with weak references to it will invalid atesome references"96 "Error: mutating node with weak references to it will invalided some references" 99 97 ); 100 98 return node->clone(); … … 106 104 // skip mutate if equivalent 107 105 if ( node->*field == val ) return node; 108 106 109 107 // mutate and return 110 108 node_t * ret = mutate( node ); … … 125 123 (ret->*field)[i] = std::forward< field_t >( val ); 126 124 return ret; 127 }128 129 /// Mutate an entire indexed collection by cloning to accepted value130 template<typename node_t, typename parent_t, typename coll_t>131 const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {132 for ( unsigned i = 0; i < (node->*field).size(); ++i ) {133 node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) );134 }135 return node;136 125 } 137 126 … … 230 219 operator const node_t * () const { _check(); return node; } 231 220 232 const node_t * release() {233 const node_t * ret = node;234 if ( node ) {235 _dec(node, false);236 node = nullptr;237 }238 return ret;239 }240 241 221 /// wrapper for convenient access to dynamic_cast 242 222 template<typename o_node_t> … … 264 244 265 245 void _inc( const node_t * other ); 266 void _dec( const node_t * other , bool do_delete = true);246 void _dec( const node_t * other ); 267 247 void _check() const; 268 248 -
src/AST/Pass.hpp
r7030dab r057298e 35 35 #include "AST/SymbolTable.hpp" 36 36 37 #include "AST/ForallSubstitutionTable.hpp"38 39 37 // Private prelude header, needed for some of the magic tricks this class pulls off 40 38 #include "AST/Pass.proto.hpp" … … 48 46 // 49 47 // Several additional features are available through inheritance 50 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the 51 // current expression 52 // | WithStmtsToAdd - provides the ability to insert statements before or after the current 53 // statement by adding new statements into stmtsToAddBefore or 54 // stmtsToAddAfter respectively. 55 // | WithDeclsToAdd - provides the ability to insert declarations before or after the 56 // current declarations by adding new DeclStmt into declsToAddBefore or 57 // declsToAddAfter respectively. 58 // | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children 59 // to false in pre{visit,visit} to skip visiting children 60 // | WithGuards - provides the ability to save/restore data like a LIFO stack; to save, 61 // call GuardValue with the variable to save, the variable will 62 // automatically be restored to its previous value after the 63 // corresponding postvisit/postmutate teminates. 64 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 65 // | WithSymbolTable - provides symbol table functionality 66 // | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation 48 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the 49 // current expression 50 // | WithStmtsToAdd - provides the ability to insert statements before or after the current 51 // statement by adding new statements into stmtsToAddBefore or 52 // stmtsToAddAfter respectively. 53 // | WithDeclsToAdd - provides the ability to insert declarations before or after the current 54 // declarations by adding new DeclStmt into declsToAddBefore or 55 // declsToAddAfter respectively. 56 // | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children 57 // to false in pre{visit,visit} to skip visiting children 58 // | WithGuards - provides the ability to save/restore data like a LIFO stack; to save, 59 // call GuardValue with the variable to save, the variable will 60 // automatically be restored to its previous value after the corresponding 61 // postvisit/postmutate teminates. 62 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 63 // | WithSymbolTable - provides symbol table functionality 67 64 //------------------------------------------------------------------------------------------------- 68 65 template< typename pass_t > … … 205 202 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 206 203 207 /// Mutate forall-list, accounting for presence of type substitution map208 template<typename node_t>209 void mutate_forall( const node_t *& );210 211 204 public: 212 205 /// Logic to call the accept and mutate the parent if needed, delegates call to accept … … 217 210 /// Internal RAII guard for symbol table features 218 211 struct guard_symtab { 219 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass .pass, 0); }220 ~guard_symtab() { __pass::symtab::leave(pass .pass, 0); }212 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); } 213 ~guard_symtab() { __pass::symtab::leave(pass, 0); } 221 214 Pass<pass_t> & pass; 222 215 }; … … 224 217 /// Internal RAII guard for scope features 225 218 struct guard_scope { 226 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass .pass, 0); }227 ~guard_scope() { __pass::scope::leave(pass .pass, 0); }219 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); } 220 ~guard_scope() { __pass::scope::leave(pass, 0); } 228 221 Pass<pass_t> & pass; 229 };230 231 /// Internal RAII guard for forall substitutions232 struct guard_forall_subs {233 guard_forall_subs( Pass<pass_t> & pass, const ParameterizedType * type )234 : pass( pass ), type( type ) { __pass::forall::enter(pass.pass, 0, type ); }235 ~guard_forall_subs() { __pass::forall::leave(pass.pass, 0, type ); }236 Pass<pass_t> & pass;237 const ParameterizedType * type;238 222 }; 239 223 … … 330 314 SymbolTable symtab; 331 315 }; 332 333 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl334 struct WithForallSubstitutor {335 ForallSubstitutionTable subs;336 };337 338 316 } 339 317 -
src/AST/Pass.impl.hpp
r7030dab r057298e 127 127 , decltype( node->accept(*this) ) 128 128 >::type 129 129 130 { 130 131 __pedantic_pass_assert( __visit_children() ); 131 __pedantic_pass_assert( node);132 __pedantic_pass_assert( expr ); 132 133 133 134 static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR"); … … 322 323 } 323 324 324 325 template< typename pass_t >326 template< typename node_t >327 void ast::Pass< pass_t >::mutate_forall( const node_t *& node ) {328 if ( auto subs = __pass::forall::subs( pass, 0 ) ) {329 // tracking TypeDecl substitution, full clone330 if ( node->forall.empty() ) return;331 332 node_t * mut = mutate( node );333 mut->forall = subs->clone( node->forall, *this );334 node = mut;335 } else {336 // not tracking TypeDecl substitution, just mutate337 maybe_accept( node, &node_t::forall );338 }339 }340 325 } 341 326 … … 444 429 guard_symtab guard { *this }; 445 430 // implicit add __func__ identifier as specified in the C manual 6.4.2.2 446 static ast:: ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{447 CodeLocation{}, "__func__",448 new ast::ArrayType {449 new ast::BasicType { ast::BasicType::Char, ast::CV::Const },431 static ast::ObjectDecl func( 432 node->location, "__func__", 433 new ast::ArrayType( 434 new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ), 450 435 nullptr, VariableLen, DynamicDim 451 }452 } };453 __pass::symtab::addId( pass, 0, func );436 ) 437 ); 438 __pass::symtab::addId( pass, 0, &func ); 454 439 VISIT( 455 440 maybe_accept( node, &FunctionDecl::type ); … … 625 610 VISIT({ 626 611 // do not enter a new scope if inFunction is true - needs to check old state before the assignment 627 auto guard1 = makeFuncGuard( [this, inFunction Cpy= this->inFunction]() {628 if ( ! inFunction Cpy) __pass::symtab::enter(pass, 0);629 }, [this, inFunction Cpy= this->inFunction]() {630 if ( ! inFunction Cpy) __pass::symtab::leave(pass, 0);612 auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() { 613 if ( ! inFunction ) __pass::symtab::enter(pass, 0); 614 }, [this, inFunction = this->inFunction]() { 615 if ( ! inFunction ) __pass::symtab::leave(pass, 0); 631 616 }); 632 617 ValueGuard< bool > guard2( inFunction ); … … 966 951 // For now this isn't visited, it is unclear if this causes problem 967 952 // if all tests are known to pass, remove this code 968 VISIT(969 maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );970 )953 // VISIT( 954 // maybe_accept( node, &ImplicitCtorDtorStmt::callStmt ); 955 // ) 971 956 972 957 VISIT_END( Stmt, node ); … … 1694 1679 VISIT_START( node ); 1695 1680 1696 VISIT({ 1697 guard_forall_subs forall_guard { *this, node }; 1698 mutate_forall( node ); 1681 VISIT( 1682 maybe_accept( node, &FunctionType::forall ); 1699 1683 maybe_accept( node, &FunctionType::returns ); 1700 1684 maybe_accept( node, &FunctionType::params ); 1701 })1685 ) 1702 1686 1703 1687 VISIT_END( Type, node ); … … 1714 1698 VISIT({ 1715 1699 guard_symtab guard { *this }; 1716 guard_forall_subs forall_guard { *this, node }; 1717 mutate_forall( node ); 1700 maybe_accept( node, &StructInstType::forall ); 1718 1701 maybe_accept( node, &StructInstType::params ); 1719 1702 }) … … 1728 1711 VISIT_START( node ); 1729 1712 1730 __pass::symtab::add Union( pass, 0, node->name );1731 1732 VISIT({1713 __pass::symtab::addStruct( pass, 0, node->name ); 1714 1715 { 1733 1716 guard_symtab guard { *this }; 1734 guard_forall_subs forall_guard { *this, node }; 1735 mutate_forall( node ); 1717 maybe_accept( node, &UnionInstType::forall ); 1736 1718 maybe_accept( node, &UnionInstType::params ); 1737 } )1719 } 1738 1720 1739 1721 VISIT_END( Type, node ); … … 1746 1728 VISIT_START( node ); 1747 1729 1748 VISIT({ 1749 guard_forall_subs forall_guard { *this, node }; 1750 mutate_forall( node ); 1730 VISIT( 1731 maybe_accept( node, &EnumInstType::forall ); 1751 1732 maybe_accept( node, &EnumInstType::params ); 1752 })1733 ) 1753 1734 1754 1735 VISIT_END( Type, node ); … … 1761 1742 VISIT_START( node ); 1762 1743 1763 VISIT({ 1764 guard_forall_subs forall_guard { *this, node }; 1765 mutate_forall( node ); 1744 VISIT( 1745 maybe_accept( node, &TraitInstType::forall ); 1766 1746 maybe_accept( node, &TraitInstType::params ); 1767 })1747 ) 1768 1748 1769 1749 VISIT_END( Type, node ); … … 1777 1757 1778 1758 VISIT( 1779 { 1780 guard_forall_subs forall_guard { *this, node }; 1781 mutate_forall( node ); 1782 maybe_accept( node, &TypeInstType::params ); 1783 } 1784 // ensure that base re-bound if doing substitution 1785 __pass::forall::replace( pass, 0, node ); 1759 maybe_accept( node, &TypeInstType::forall ); 1760 maybe_accept( node, &TypeInstType::params ); 1786 1761 ) 1787 1762 … … 1932 1907 guard_symtab guard { *this }; 1933 1908 auto new_node = p.second->accept( *this ); 1934 if (new_node != p.second) mutated = true;1909 if (new_node != p.second) mutated = false; 1935 1910 new_map.insert({ p.first, new_node }); 1936 1911 } … … 1948 1923 guard_symtab guard { *this }; 1949 1924 auto new_node = p.second->accept( *this ); 1950 if (new_node != p.second) mutated = true;1925 if (new_node != p.second) mutated = false; 1951 1926 new_map.insert({ p.first, new_node }); 1952 1927 } -
src/AST/Pass.proto.hpp
r7030dab r057298e 263 263 template<typename pass_t> 264 264 static inline void leave( pass_t &, long ) {} 265 } // namespace scope266 267 // Certain passes desire an up to date symbol table automatically265 }; 266 267 // Finally certain pass desire an up to date symbol table automatically 268 268 // detect the presence of a member name `symtab` and call all the members appropriately 269 269 namespace symtab { 270 270 // Some simple scoping rules 271 271 template<typename pass_t> 272 static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab , void() ) {272 static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) { 273 273 pass.symtab.enterScope(); 274 274 } … … 278 278 279 279 template<typename pass_t> 280 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab , void() ) {280 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) { 281 281 pass.symtab.leaveScope(); 282 282 } … … 311 311 SYMTAB_FUNC1( addUnion , const UnionDecl * ); 312 312 SYMTAB_FUNC1( addTrait , const TraitDecl * ); 313 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Decl* );313 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Node * ); 314 314 315 315 // A few extra functions have more complicated behaviour, they are hand written … … 356 356 #undef SYMTAB_FUNC1 357 357 #undef SYMTAB_FUNC2 358 } // namespace symtab 359 360 // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType. 361 // Detect the presence of a member name `subs` and call all members appropriately 362 namespace forall { 363 // Some simple scoping rules 364 template<typename pass_t> 365 static inline auto enter( pass_t & pass, int, const ast::ParameterizedType * type ) 366 -> decltype( pass.subs, void() ) { 367 if ( ! type->forall.empty() ) pass.subs.beginScope(); 368 } 369 370 template<typename pass_t> 371 static inline auto enter( pass_t &, long, const ast::ParameterizedType * ) {} 372 373 template<typename pass_t> 374 static inline auto leave( pass_t & pass, int, const ast::ParameterizedType * type ) 375 -> decltype( pass.subs, void() ) { 376 if ( ! type->forall.empty() ) { pass.subs.endScope(); } 377 } 378 379 template<typename pass_t> 380 static inline auto leave( pass_t &, long, const ast::ParameterizedType * ) {} 381 382 // Get the substitution table, if present 383 template<typename pass_t> 384 static inline auto subs( pass_t & pass, int ) -> decltype( &pass.subs ) { 385 return &pass.subs; 386 } 387 388 template<typename pass_t> 389 static inline ast::ForallSubstitutionTable * subs( pass_t &, long ) { return nullptr; } 390 391 // Replaces a TypeInstType's base TypeDecl according to the table 392 template<typename pass_t> 393 static inline auto replace( pass_t & pass, int, const ast::TypeInstType *& inst ) 394 -> decltype( pass.subs, void() ) { 395 inst = ast::mutate_field( 396 inst, &ast::TypeInstType::base, pass.subs.replace( inst->base ) ); 397 } 398 399 template<typename pass_t> 400 static inline auto replace( pass_t &, long, const ast::TypeInstType *& ) {} 401 402 } // namespace forall 403 } // namespace __pass 404 } // namespace ast 358 }; 359 }; 360 }; -
src/AST/Stmt.hpp
r7030dab r057298e 27 27 28 28 // Must be included in *all* AST classes; should be #undef'd at the end of the file 29 #define MUTATE_FRIEND \ 30 template<typename node_t> friend node_t * mutate(const node_t * node); \ 31 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 29 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 32 30 33 31 namespace ast { … … 414 412 class ImplicitCtorDtorStmt final : public Stmt { 415 413 public: 416 ptr<Stmt> callStmt;414 readonly<Stmt> callStmt; 417 415 418 416 ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt, -
src/AST/Type.cpp
r7030dab r057298e 21 21 22 22 #include "Decl.hpp" 23 #include "ForallSubstitutor.hpp" // for substituteForall24 23 #include "Init.hpp" 25 #include "Common/utility.h" // for copy, move26 24 #include "InitTweak/InitTweak.h" // for getPointerBase 27 25 #include "Tuples/Tuples.h" // for isTtype … … 92 90 // GENERATED END 93 91 94 // --- ParameterizedType95 96 void ParameterizedType::initWithSub(97 const ParameterizedType & o, Pass< ForallSubstitutor > & sub98 ) {99 forall = sub.pass( o.forall );100 }101 102 92 // --- FunctionType 103 104 FunctionType::FunctionType( const FunctionType & o )105 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),106 isVarArgs( o.isVarArgs ) {107 Pass< ForallSubstitutor > sub;108 initWithSub( o, sub ); // initialize substitution map109 returns = sub.pass( o.returns ); // apply to return and parameter types110 params = sub.pass( o.params );111 }112 93 113 94 namespace { … … 125 106 126 107 // --- ReferenceToType 127 128 void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {129 ParameterizedType::initWithSub( o, sub ); // initialize substitution130 params = sub.pass( o.params ); // apply to parameters131 }132 133 ReferenceToType::ReferenceToType( const ReferenceToType & o )134 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),135 hoistType( o.hoistType ) {136 Pass< ForallSubstitutor > sub;137 initWithSub( o, sub );138 }139 140 108 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const { 141 109 assertf( aggr(), "Must have aggregate to perform lookup" ); … … 150 118 // --- StructInstType 151 119 152 StructInstType::StructInstType( 153 const StructDecl * b, CV::Qualifiers q,std::vector<ptr<Attribute>>&& as )154 : ReferenceToType( b->name, q, move(as) ), base( b ) {}120 StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q, 121 std::vector<ptr<Attribute>>&& as ) 122 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {} 155 123 156 124 bool StructInstType::isComplete() const { return base ? base->body : false; } … … 158 126 // --- UnionInstType 159 127 160 UnionInstType::UnionInstType( 161 const UnionDecl * b, CV::Qualifiers q,std::vector<ptr<Attribute>>&& as )162 : ReferenceToType( b->name, q, move(as) ), base( b ) {}128 UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q, 129 std::vector<ptr<Attribute>>&& as ) 130 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {} 163 131 164 132 bool UnionInstType::isComplete() const { return base ? base->body : false; } … … 166 134 // --- EnumInstType 167 135 168 EnumInstType::EnumInstType( 169 const EnumDecl * b, CV::Qualifiers q,std::vector<ptr<Attribute>>&& as )170 : ReferenceToType( b->name, q, move(as) ), base( b ) {}136 EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q, 137 std::vector<ptr<Attribute>>&& as ) 138 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {} 171 139 172 140 bool EnumInstType::isComplete() const { return base ? base->body : false; } … … 174 142 // --- TraitInstType 175 143 176 TraitInstType::TraitInstType( 177 const TraitDecl * b, CV::Qualifiers q,std::vector<ptr<Attribute>>&& as )178 : ReferenceToType( b->name, q, move(as) ), base( b ) {}144 TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q, 145 std::vector<ptr<Attribute>>&& as ) 146 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {} 179 147 180 148 // --- TypeInstType 181 182 TypeInstType::TypeInstType( const TypeInstType & o )183 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {184 Pass< ForallSubstitutor > sub;185 initWithSub( o, sub ); // initialize substitution186 base = sub.pass( o.base ); // apply to base type187 }188 149 189 150 void TypeInstType::set_base( const TypeDecl * b ) { … … 197 158 198 159 TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q ) 199 : Type( q ), types( move(ts) ), members() {160 : Type( q ), types( std::move(ts) ), members() { 200 161 // This constructor is awkward. `TupleType` needs to contain objects so that members can be 201 162 // named, but members without initializer nodes end up getting constructors, which breaks -
src/AST/Type.hpp
r7030dab r057298e 29 29 30 30 // Must be included in *all* AST classes; should be #undef'd at the end of the file 31 #define MUTATE_FRIEND \ 32 template<typename node_t> friend node_t * mutate(const node_t * node); \ 33 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 31 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 34 32 35 33 namespace ast { 36 37 template< typename T > class Pass;38 39 struct ForallSubstitutor;40 34 41 35 class Type : public Node { … … 50 44 bool is_volatile() const { return qualifiers.is_volatile; } 51 45 bool is_restrict() const { return qualifiers.is_restrict; } 46 bool is_lvalue() const { return qualifiers.is_lvalue; } 52 47 bool is_mutex() const { return qualifiers.is_mutex; } 53 48 bool is_atomic() const { return qualifiers.is_atomic; } … … 56 51 Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; } 57 52 Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; } 53 Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; } 58 54 Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; } 59 55 Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; } … … 167 163 static const char *typeNames[]; 168 164 169 BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 165 BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 170 166 : Type(q, std::move(as)), kind(k) {} 171 167 … … 269 265 /// Base type for potentially forall-qualified types 270 266 class ParameterizedType : public Type { 271 protected:272 /// initializes forall with substitutor273 void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );274 267 public: 275 268 using ForallList = std::vector<ptr<TypeDecl>>; … … 283 276 ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} ) 284 277 : 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 278 293 279 private: … … 315 301 : ParameterizedType(q), returns(), params(), isVarArgs(va) {} 316 302 317 FunctionType( const FunctionType & o );318 319 303 /// true if either the parameters or return values contain a tttype 320 304 bool isTtype() const; … … 330 314 /// base class for types that refer to types declared elsewhere (aggregates and typedefs) 331 315 class ReferenceToType : public ParameterizedType { 332 protected:333 /// Initializes forall and parameters based on substitutor334 void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );335 316 public: 336 317 std::vector<ptr<Expr>> params; … … 338 319 bool hoistType = false; 339 320 340 ReferenceToType( 341 const std::string& n, CV::Qualifiers q = {},std::vector<ptr<Attribute>> && as = {} )321 ReferenceToType( const std::string& n, CV::Qualifiers q = {}, 322 std::vector<ptr<Attribute>> && as = {} ) 342 323 : ParameterizedType(q, std::move(as)), params(), name(n) {} 343 344 ReferenceToType( const ReferenceToType & o );345 324 346 325 /// Gets aggregate declaration this type refers to … … 359 338 readonly<StructDecl> base; 360 339 361 StructInstType( 362 const std::string& n, CV::Qualifiers q = {},std::vector<ptr<Attribute>> && as = {} )340 StructInstType( const std::string& n, CV::Qualifiers q = {}, 341 std::vector<ptr<Attribute>> && as = {} ) 363 342 : ReferenceToType( n, q, std::move(as) ), base() {} 364 365 StructInstType( 366 const StructDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ); 343 StructInstType( const StructDecl * b, CV::Qualifiers q = {}, 344 std::vector<ptr<Attribute>> && as = {} ); 367 345 368 346 bool isComplete() const override; … … 381 359 readonly<UnionDecl> base; 382 360 383 UnionInstType( 384 const std::string& n, CV::Qualifiers q = {},std::vector<ptr<Attribute>> && as = {} )361 UnionInstType( const std::string& n, CV::Qualifiers q = {}, 362 std::vector<ptr<Attribute>> && as = {} ) 385 363 : ReferenceToType( n, q, std::move(as) ), base() {} 386 387 UnionInstType( 388 const UnionDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ); 364 UnionInstType( const UnionDecl * b, CV::Qualifiers q = {}, 365 std::vector<ptr<Attribute>> && as = {} ); 389 366 390 367 bool isComplete() const override; … … 403 380 readonly<EnumDecl> base; 404 381 405 EnumInstType( 406 const std::string& n, CV::Qualifiers q = {},std::vector<ptr<Attribute>> && as = {} )382 EnumInstType( const std::string& n, CV::Qualifiers q = {}, 383 std::vector<ptr<Attribute>> && as = {} ) 407 384 : ReferenceToType( n, q, std::move(as) ), base() {} 408 409 EnumInstType( 410 const EnumDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ); 385 EnumInstType( const EnumDecl * b, CV::Qualifiers q = {}, 386 std::vector<ptr<Attribute>> && as = {} ); 411 387 412 388 bool isComplete() const override; … … 425 401 readonly<TraitDecl> base; 426 402 427 TraitInstType( 428 const std::string& n, CV::Qualifiers q = {},std::vector<ptr<Attribute>> && as = {} )403 TraitInstType( const std::string& n, CV::Qualifiers q = {}, 404 std::vector<ptr<Attribute>> && as = {} ) 429 405 : ReferenceToType( n, q, std::move(as) ), base() {} 430 431 TraitInstType( 432 const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ); 406 TraitInstType( const TraitDecl * b, CV::Qualifiers q = {}, 407 std::vector<ptr<Attribute>> && as = {} ); 433 408 434 409 // not meaningful for TraitInstType … … 449 424 TypeDecl::Kind kind; 450 425 451 TypeInstType( 452 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 426 TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 453 427 std::vector<ptr<Attribute>> && as = {} ) 454 428 : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {} … … 456 430 std::vector<ptr<Attribute>> && as = {} ) 457 431 : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {} 458 459 TypeInstType( const TypeInstType & o );460 432 461 433 /// sets `base`, updating `kind` correctly -
src/AST/TypeEnvironment.hpp
r7030dab r057298e 37 37 /// Adding this comparison operator significantly improves assertion satisfaction run time for 38 38 /// some cases. The current satisfaction algorithm's speed partially depends on the order of 39 /// assertions. Assertions which have fewer possible matches should appear before assertions 40 /// which have more possible matches. This seems to imply that this could be further improved 41 /// by providing an indexer as an additional argument and ordering based on the number of 39 /// assertions. Assertions which have fewer possible matches should appear before assertions 40 /// which have more possible matches. This seems to imply that this could be further improved 41 /// by providing an indexer as an additional argument and ordering based on the number of 42 42 /// matches of the same kind (object, function) for the names of the declarations. 43 43 /// 44 /// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 44 /// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 45 45 /// comparator. 46 46 /// 47 /// Note: since this compares pointers for position, minor changes in the source file that 48 /// affect memory layout can alter compilation time in unpredictable ways. For example, the 49 /// placement of a line directive can reorder type pointers with respect to each other so that 50 /// assertions are seen in different orders, causing a potentially different number of 51 /// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27 52 /// seconds by reordering line directives alone, so it would be nice to fix this comparison so 53 /// that assertions compare more consistently. I've tried to modify this to compare on mangle 54 /// name instead of type as the second comparator, but this causes some assertions to never be 47 /// Note: since this compares pointers for position, minor changes in the source file that 48 /// affect memory layout can alter compilation time in unpredictable ways. For example, the 49 /// placement of a line directive can reorder type pointers with respect to each other so that 50 /// assertions are seen in different orders, causing a potentially different number of 51 /// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27 52 /// seconds by reordering line directives alone, so it would be nice to fix this comparison so 53 /// that assertions compare more consistently. I've tried to modify this to compare on mangle 54 /// name instead of type as the second comparator, but this causes some assertions to never be 55 55 /// recorded. More investigation is needed. 56 56 struct AssertCompare { … … 86 86 void print( std::ostream &, const OpenVarSet &, Indenter indent = {} ); 87 87 88 /// Represents an equivalence class of bound type variables, optionally with the concrete type 88 /// Represents an equivalence class of bound type variables, optionally with the concrete type 89 89 /// they bind to. 90 90 struct EqvClass { … … 95 95 96 96 EqvClass() : vars(), bound(), allowWidening( true ), data() {} 97 97 98 98 /// Copy-with-bound constructor 99 EqvClass( const EqvClass & o, const Type * b ) 99 EqvClass( const EqvClass & o, const Type * b ) 100 100 : vars( o.vars ), bound( b ), allowWidening( o.allowWidening ), data( o.data ) {} 101 101 … … 142 142 void writeToSubstitution( TypeSubstitution & sub ) const; 143 143 144 template< typename node_t >145 auto apply( node_t && type ) const {144 template< typename node_t, enum Node::ref_type ref_t > 145 int apply( ptr_base< node_t, ref_t > & type ) const { 146 146 TypeSubstitution sub; 147 147 writeToSubstitution( sub ); 148 return sub.apply( std::forward<node_t>(type));149 } 150 151 template< typename node_t >152 auto applyFree( node_t && type ) const {148 return sub.apply( type ); 149 } 150 151 template< typename node_t, enum Node::ref_type ref_t > 152 int applyFree( ptr_base< node_t, ref_t > & type ) const { 153 153 TypeSubstitution sub; 154 154 writeToSubstitution( sub ); 155 return sub.applyFree( std::forward<node_t>(type));155 return sub.applyFree( type ); 156 156 } 157 157 … … 172 172 void addActual( const TypeEnvironment & actualEnv, OpenVarSet & openVars ); 173 173 174 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if 174 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if 175 175 /// needed. Returns false on failure. 176 bool bindVar( 177 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 178 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 176 bool bindVar( 177 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 178 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 179 179 ResolvExpr::WidenMode widen, const SymbolTable & symtab ); 180 181 /// Binds the type classes represented by `var1` and `var2` together; will add one or both 180 181 /// Binds the type classes represented by `var1` and `var2` together; will add one or both 182 182 /// classes if needed. Returns false on failure. 183 bool bindVarToVar( 184 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 185 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 183 bool bindVarToVar( 184 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 185 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 186 186 ResolvExpr::WidenMode widen, const SymbolTable & symtab ); 187 187 … … 198 198 199 199 /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails 200 bool mergeBound( 200 bool mergeBound( 201 201 EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab ); 202 202 203 203 /// Merges two type classes from local environment, returning false if fails 204 bool mergeClasses( 205 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 204 bool mergeClasses( 205 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 206 206 const SymbolTable & symtab ); 207 207 -
src/AST/TypeSubstitution.cpp
r7030dab r057298e 92 92 namespace { 93 93 struct EnvTrimmer { 94 const TypeSubstitution *env;94 ptr<TypeSubstitution> env; 95 95 TypeSubstitution * newEnv; 96 96 EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} … … 108 108 if ( env ) { 109 109 TypeSubstitution * newEnv = new TypeSubstitution(); 110 #if TIME_TO_CONVERT_PASSES 110 111 Pass<EnvTrimmer> trimmer( env, newEnv ); 111 112 expr->accept( trimmer ); 113 #else 114 (void)expr; 115 (void)env; 116 #endif 112 117 return newEnv; 113 118 } … … 116 121 117 122 void TypeSubstitution::normalize() { 118 Pass<Substituter> sub( *this, true ); 123 #if TIME_TO_CONVERT_PASSES 124 PassVisitor<Substituter> sub( *this, true ); 119 125 do { 120 126 sub.pass.subCount = 0; 121 127 sub.pass.freeOnly = true; 122 128 for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) { 123 i->second = i->second->accept ( sub );129 i->second = i->second->acceptMutator( sub ); 124 130 } 125 131 } while ( sub.pass.subCount ); 126 } 127 128 const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) { 132 #endif 133 } 134 135 #if TIME_TO_CONVERT_PASSES 136 137 Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) { 129 138 BoundVarsType::const_iterator bound = boundVars.find( inst->name ); 130 139 if ( bound != boundVars.end() ) return inst; … … 137 146 // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here. 138 147 // TODO: investigate preventing type variables from being bound to themselves in the first place. 139 if ( constTypeInstType * replacement = i->second.as<TypeInstType>() ) {148 if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) { 140 149 if ( inst->name == replacement->name ) { 141 150 return inst; … … 144 153 // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl; 145 154 subCount++; 146 ptr<Type> newType = i->second; // force clone if needed 147 add_qualifiers( newType, inst->qualifiers ); 148 // Note: need to recursively apply substitution to the new type because normalize does not 149 // substitute bound vars, but bound vars must be substituted when not in freeOnly mode. 150 newType = newType->accept( *visitor ); 151 return newType.release(); 152 } // if 153 } 154 155 const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) { 155 Type * newtype = i->second->clone(); 156 newtype->get_qualifiers() |= inst->get_qualifiers(); 157 delete inst; 158 // Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode. 159 return newtype->acceptMutator( *visitor ); 160 } // if 161 } 162 163 Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) { 156 164 VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name ); 157 165 if ( i == sub.varEnv.end() ) { … … 159 167 } else { 160 168 subCount++; 161 return i->second; 162 } // if 163 } 164 165 void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) { 169 delete nameExpr; 170 return i->second->clone(); 171 } // if 172 } 173 174 void TypeSubstitution::Substituter::premutate( Type * type ) { 166 175 GuardValue( boundVars ); 167 176 // bind type variables from forall-qualifiers 168 177 if ( freeOnly ) { 169 for ( const TypeDecl * tyvar : ptype->forall) {170 boundVars.insert( tyvar->name );178 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) { 179 boundVars.insert( (*tyvar)->name ); 171 180 } // for 172 181 } // if 173 182 } 174 183 175 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) { 184 template< typename TypeClass > 185 void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) { 176 186 GuardValue( boundVars ); 177 187 // bind type variables from forall-qualifiers 178 188 if ( freeOnly ) { 179 for ( const TypeDecl * tyvar : type->forall) {180 boundVars.insert( tyvar->name );189 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) { 190 boundVars.insert( (*tyvar)->name ); 181 191 } // for 182 192 // bind type variables from generic type instantiations 183 if ( auto decl = type->aggr() ) { 184 if ( ! type->params.empty() ) { 185 for ( const TypeDecl * tyvar : decl->params ) { 186 boundVars.insert( tyvar->name ); 187 } // for 188 } // if 189 } 190 } // if 191 } 192 193 void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) { 193 std::list< TypeDecl* > *baseParameters = type->get_baseParameters(); 194 if ( baseParameters && ! type->parameters.empty() ) { 195 for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) { 196 boundVars.insert( (*tyvar)->name ); 197 } // for 198 } // if 199 } // if 200 } 201 202 void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) { 194 203 handleAggregateType( aggregateUseType ); 195 204 } 196 205 197 void TypeSubstitution::Substituter::pre visit( constUnionInstType *aggregateUseType ) {206 void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) { 198 207 handleAggregateType( aggregateUseType ); 199 208 } 209 210 #endif 200 211 201 212 } // namespace ast -
src/AST/TypeSubstitution.hpp
r7030dab r057298e 44 44 TypeSubstitution &operator=( const TypeSubstitution &other ); 45 45 46 template< typename SynTreeClass > 47 struct ApplyResult { 48 const SynTreeClass * node; 49 int count; 50 }; 51 52 template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const; 53 template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const; 46 template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const; 47 template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const; 54 48 55 49 template< typename node_t, enum Node::ref_type ref_t > 56 50 int apply( ptr_base< node_t, ref_t > & input ) const { 57 51 const node_t * p = input.get(); 58 autoret = apply(p);59 input = ret.node;60 return ret .count;52 int ret = apply(p); 53 input = p; 54 return ret; 61 55 } 62 56 … … 64 58 int applyFree( ptr_base< node_t, ref_t > & input ) const { 65 59 const node_t * p = input.get(); 66 autoret = applyFree(p);67 input = ret.node;68 return ret .count;60 int ret = applyFree(p); 61 input = p; 62 return ret; 69 63 } 70 64 … … 161 155 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {} 162 156 163 const Type * postvisit( const TypeInstType * aggregateUseType ); 164 const Expr * postvisit( const NameExpr * nameExpr ); 157 #if TIME_TO_CONVERT_PASSES 158 159 Type * postmutate( TypeInstType * aggregateUseType ); 160 Expression * postmutate( NameExpr * nameExpr ); 165 161 166 162 /// Records type variable bindings from forall-statements 167 void pre visit( const ParameterizedType * type );163 void premutate( Type * type ); 168 164 /// Records type variable bindings from forall-statements and instantiations of generic types 169 void handleAggregateType( const ReferenceToType * type ); 170 171 void previsit( const StructInstType * aggregateUseType ); 172 void previsit( const UnionInstType * aggregateUseType ); 165 template< typename TypeClass > void handleAggregateType( TypeClass * type ); 166 167 void premutate( StructInstType * aggregateUseType ); 168 void premutate( UnionInstType * aggregateUseType ); 169 170 #endif 173 171 174 172 const TypeSubstitution & sub; … … 181 179 182 180 template< typename SynTreeClass > 183 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass *input ) const {181 int TypeSubstitution::apply( const SynTreeClass *& input ) const { 184 182 assert( input ); 185 183 Pass<Substituter> sub( *this, false ); 186 184 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) ); 187 return { input, sub.pass.subCount }; 185 /// std::cerr << "substitution result is: "; 186 /// newType->print( std::cerr ); 187 /// std::cerr << std::endl; 188 return sub.pass.subCount; 188 189 } 189 190 190 191 template< typename SynTreeClass > 191 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass *input ) const {192 int TypeSubstitution::applyFree( const SynTreeClass *& input ) const { 192 193 assert( input ); 193 194 Pass<Substituter> sub( *this, true ); 194 195 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) ); 195 return { input, sub.pass.subCount }; 196 /// std::cerr << "substitution result is: "; 197 /// newType->print( std::cerr ); 198 /// std::cerr << std::endl; 199 return sub.pass.subCount; 196 200 } 197 201 -
src/AST/module.mk
r7030dab r057298e 22 22 AST/DeclReplacer.cpp \ 23 23 AST/Expr.cpp \ 24 AST/ForallSubstitutionTable.cpp \25 24 AST/GenericSubstitution.cpp \ 26 25 AST/Init.cpp \ -
src/Common/ScopedMap.h
r7030dab r057298e 249 249 250 250 /// Gets the note at the given scope 251 Note& getNote() { return scopes.back().note; }252 const Note& getNote() const { return scopes.back().note; }253 251 Note& getNote( size_type i ) { return scopes[i].note; } 254 252 const Note& getNote( size_type i ) const { return scopes[i].note; } -
src/Makefile.in
r7030dab r057298e 169 169 AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \ 170 170 AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \ 171 AST/ForallSubstitutionTable.$(OBJEXT) \172 171 AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \ 173 172 AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \ … … 590 589 AST/DeclReplacer.cpp \ 591 590 AST/Expr.cpp \ 592 AST/ForallSubstitutionTable.cpp \593 591 AST/GenericSubstitution.cpp \ 594 592 AST/Init.cpp \ … … 767 765 AST/$(DEPDIR)/$(am__dirstamp) 768 766 AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp) 769 AST/ForallSubstitutionTable.$(OBJEXT): AST/$(am__dirstamp) \770 AST/$(DEPDIR)/$(am__dirstamp)771 767 AST/GenericSubstitution.$(OBJEXT): AST/$(am__dirstamp) \ 772 768 AST/$(DEPDIR)/$(am__dirstamp) … … 1222 1218 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/DeclReplacer.Po@am__quote@ 1223 1219 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Expr.Po@am__quote@ 1224 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/ForallSubstitutionTable.Po@am__quote@1225 1220 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/GenericSubstitution.Po@am__quote@ 1226 1221 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Init.Po@am__quote@ -
src/ResolvExpr/AdjustExprType.cc
r7030dab r057298e 100 100 101 101 namespace { 102 class AdjustExprType_new final : public ast::WithShortCircuiting { 102 struct AdjustExprType_new final : public ast::WithShortCircuiting { 103 const ast::TypeEnvironment & tenv; 103 104 const ast::SymbolTable & symtab; 104 public:105 const ast::TypeEnvironment & tenv;106 105 107 106 AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms ) 108 : symtab( syms ), tenv( e) {}107 : tenv( e ), symtab( syms ) {} 109 108 110 void pre visit( const ast::VoidType * ) { visit_children = false; }111 void pre visit( const ast::BasicType * ) { visit_children = false; }112 void pre visit( const ast::PointerType * ) { visit_children = false; }113 void pre visit( const ast::ArrayType * ) { visit_children = false; }114 void pre visit( const ast::FunctionType * ) { visit_children = false; }115 void pre visit( const ast::StructInstType * ) { visit_children = false; }116 void pre visit( const ast::UnionInstType * ) { visit_children = false; }117 void pre visit( const ast::EnumInstType * ) { visit_children = false; }118 void pre visit( const ast::TraitInstType * ) { visit_children = false; }119 void pre visit( const ast::TypeInstType * ) { visit_children = false; }120 void pre visit( const ast::TupleType * ) { visit_children = false; }121 void pre visit( const ast::VarArgsType * ) { visit_children = false; }122 void pre visit( const ast::ZeroType * ) { visit_children = false; }123 void pre visit( const ast::OneType * ) { visit_children = false; }109 void premutate( const ast::VoidType * ) { visit_children = false; } 110 void premutate( const ast::BasicType * ) { visit_children = false; } 111 void premutate( const ast::PointerType * ) { visit_children = false; } 112 void premutate( const ast::ArrayType * ) { visit_children = false; } 113 void premutate( const ast::FunctionType * ) { visit_children = false; } 114 void premutate( const ast::StructInstType * ) { visit_children = false; } 115 void premutate( const ast::UnionInstType * ) { visit_children = false; } 116 void premutate( const ast::EnumInstType * ) { visit_children = false; } 117 void premutate( const ast::TraitInstType * ) { visit_children = false; } 118 void premutate( const ast::TypeInstType * ) { visit_children = false; } 119 void premutate( const ast::TupleType * ) { visit_children = false; } 120 void premutate( const ast::VarArgsType * ) { visit_children = false; } 121 void premutate( const ast::ZeroType * ) { visit_children = false; } 122 void premutate( const ast::OneType * ) { visit_children = false; } 124 123 125 const ast::Type * post visit( const ast::ArrayType * at ) {124 const ast::Type * postmutate( const ast::ArrayType * at ) { 126 125 return new ast::PointerType{ at->base, at->qualifiers }; 127 126 } 128 127 129 const ast::Type * post visit( const ast::FunctionType * ft ) {128 const ast::Type * postmutate( const ast::FunctionType * ft ) { 130 129 return new ast::PointerType{ ft }; 131 130 } 132 131 133 const ast::Type * post visit( const ast::TypeInstType * inst ) {132 const ast::Type * postmutate( const ast::TypeInstType * inst ) { 134 133 // replace known function-type-variables with pointer-to-function 135 134 if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) { -
src/ResolvExpr/Candidate.hpp
r7030dab r057298e 51 51 52 52 Candidate( const ast::Expr * x, const ast::TypeEnvironment & e ) 53 : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() { 54 assert(x->result); 55 } 53 : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {} 56 54 57 55 Candidate( const Candidate & o, const ast::Expr * x, const Cost & addedCost = Cost::zero ) 58 56 : expr( x ), cost( o.cost + addedCost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ), 59 need( o.need ) { 60 assert(x->result); 61 } 57 need( o.need ) {} 62 58 63 59 Candidate( 64 const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 60 const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 65 61 const ast::AssertionSet & n, const Cost & c, const Cost & cvt = Cost::zero ) 66 : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) { 67 assert(x->result); 68 } 62 : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {} 69 63 70 64 Candidate( … … 72 66 ast::AssertionSet && n, const Cost & c, const Cost & cvt = Cost::zero ) 73 67 : expr( x ), cost( c ), cvtCost( cvt ), env( std::move( e ) ), open( std::move( o ) ), 74 need( n.begin(), n.end() ) { 75 assert(x->result); 76 } 68 need( n.begin(), n.end() ) {} 77 69 }; 78 70 -
src/ResolvExpr/CandidateFinder.cpp
r7030dab r057298e 9 9 // Author : Aaron B. Moss 10 10 // Created On : Wed Jun 5 14:30:00 2019 11 // Last Modified By : A ndrew Beach12 // Last Modified On : Tue Oct 1 14:55:00 201913 // Update Count : 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Wed Jun 5 14:30:00 2019 13 // Update Count : 1 14 14 // 15 15 … … 54 54 return new ast::CastExpr{ expr, expr->result->stripReferences() }; 55 55 } 56 56 57 57 return expr; 58 58 } … … 61 61 UniqueId globalResnSlot = 0; 62 62 63 Cost computeConversionCost( 64 const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,65 const ast:: SymbolTable & symtab, const ast::TypeEnvironment & env63 Cost computeConversionCost( 64 const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab, 65 const ast::TypeEnvironment & env 66 66 ) { 67 67 PRINT( … … 74 74 std::cerr << std::endl; 75 75 ) 76 Cost convCost = conversionCost( argType, paramType, argIsLvalue,symtab, env );76 Cost convCost = conversionCost( argType, paramType, symtab, env ); 77 77 PRINT( 78 78 std::cerr << std::endl << "cost is " << convCost << std::endl; … … 107 107 108 108 /// Computes conversion cost for a given expression to a given type 109 const ast::Expr * computeExpressionConversionCost( 110 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 109 const ast::Expr * computeExpressionConversionCost( 110 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 111 111 ) { 112 Cost convCost = computeConversionCost( 113 arg->result, paramType, arg->get_lvalue(), symtab, env ); 112 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env ); 114 113 outCost += convCost; 115 114 116 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 117 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 115 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 116 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 118 117 // infer parameters and this does not currently work for the reason stated below 119 118 Cost tmpCost = convCost; … … 124 123 return new ast::CastExpr{ arg, newType }; 125 124 126 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 127 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 125 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 126 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 128 127 // once this is fixed it should be possible to resolve the cast. 129 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 130 // but it shouldn't be because this makes the conversion from DT* to DT* since 128 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 129 // but it shouldn't be because this makes the conversion from DT* to DT* since 131 130 // commontype(zero_t, DT*) is DT*, rather than nothing 132 131 133 132 // CandidateFinder finder{ symtab, env }; 134 133 // finder.find( arg, ResolvMode::withAdjustment() ); 135 // assertf( finder.candidates.size() > 0, 134 // assertf( finder.candidates.size() > 0, 136 135 // "Somehow castable expression failed to find alternatives." ); 137 // assertf( finder.candidates.size() == 1, 136 // assertf( finder.candidates.size() == 1, 138 137 // "Somehow got multiple alternatives for known cast expression." ); 139 138 // return finder.candidates.front()->expr; … … 144 143 145 144 /// Computes conversion cost for a given candidate 146 Cost computeApplicationConversionCost( 147 CandidateRef cand, const ast::SymbolTable & symtab 145 Cost computeApplicationConversionCost( 146 CandidateRef cand, const ast::SymbolTable & symtab 148 147 ) { 149 148 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >(); … … 168 167 if ( function->isVarArgs ) { 169 168 convCost.incUnsafe(); 170 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 169 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 171 170 << convCost << std::endl; ; ) 172 171 // convert reference-typed expressions into value-typed expressions 173 cand->expr = ast::mutate_field_index( 174 appExpr, &ast::ApplicationExpr::args, i, 172 cand->expr = ast::mutate_field_index( 173 appExpr, &ast::ApplicationExpr::args, i, 175 174 referenceToRvalueConversion( args[i], convCost ) ); 176 175 continue; … … 181 180 // Default arguments should be free - don't include conversion cost. 182 181 // Unwrap them here because they are not relevant to the rest of the system 183 cand->expr = ast::mutate_field_index( 182 cand->expr = ast::mutate_field_index( 184 183 appExpr, &ast::ApplicationExpr::args, i, def->expr ); 185 184 ++param; … … 189 188 // mark conversion cost and also specialization cost of param type 190 189 const ast::Type * paramType = (*param)->get_type(); 191 cand->expr = ast::mutate_field_index( 192 appExpr, &ast::ApplicationExpr::args, i, 193 computeExpressionConversionCost( 190 cand->expr = ast::mutate_field_index( 191 appExpr, &ast::ApplicationExpr::args, i, 192 computeExpressionConversionCost( 194 193 args[i], paramType, symtab, cand->env, convCost ) ); 195 194 convCost.decSpec( specCost( paramType ) ); … … 199 198 if ( param != params.end() ) return Cost::infinity; 200 199 201 // specialization cost of return types can't be accounted for directly, it disables 200 // specialization cost of return types can't be accounted for directly, it disables 202 201 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 203 202 // … … 216 215 } 217 216 218 void makeUnifiableVars( 219 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 220 ast::AssertionSet & need 217 void makeUnifiableVars( 218 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 219 ast::AssertionSet & need 221 220 ) { 222 221 for ( const ast::TypeDecl * tyvar : type->forall ) { … … 255 254 256 255 ArgPack() 257 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 256 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 258 257 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 259 258 259 ArgPack( 260 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 261 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 262 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 263 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 264 260 265 ArgPack( 261 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 262 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 263 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 264 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 265 266 ArgPack( 267 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 268 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 269 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 266 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 267 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 268 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 270 269 unsigned nextExpl = 0, unsigned explAlt = 0 ) 271 270 : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ), 272 271 have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ), 273 272 nextExpl( nextExpl ), explAlt( explAlt ) {} 274 273 275 274 ArgPack( 276 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 275 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 277 276 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added ) 278 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 279 need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 277 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 278 need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 280 279 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {} 281 280 282 281 /// true if this pack is in the middle of an exploded argument 283 282 bool hasExpl() const { return nextExpl > 0; } … … 287 286 return args[ nextArg-1 ][ explAlt ]; 288 287 } 289 288 290 289 /// Ends a tuple expression, consolidating the appropriate args 291 290 void endTuple( const std::vector< ArgPack > & packs ) { … … 308 307 309 308 /// Instantiates an argument to match a parameter, returns false if no matching results left 310 bool instantiateArgument( 311 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 312 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 313 unsigned nTuples = 0 309 bool instantiateArgument( 310 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 311 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 312 unsigned nTuples = 0 314 313 ) { 315 314 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) { … … 319 318 // xxx - dropping initializer changes behaviour from previous, but seems correct 320 319 // ^^^ need to handle the case where a tuple has a default argument 321 if ( ! instantiateArgument( 320 if ( ! instantiateArgument( 322 321 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 323 322 nTuples = 0; … … 330 329 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) { 331 330 // paramType is a ttype, consumes all remaining arguments 332 331 333 332 // completed tuples; will be spliced to end of results to finish 334 333 std::vector< ArgPack > finalResults{}; … … 343 342 for ( std::size_t i = genStart; i < genEnd; ++i ) { 344 343 unsigned nextArg = results[i].nextArg; 345 344 346 345 // use next element of exploded tuple if present 347 346 if ( results[i].hasExpl() ) { … … 353 352 results.emplace_back( 354 353 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 355 copy( results[i].need ), copy( results[i].have ), 354 copy( results[i].need ), copy( results[i].have ), 356 355 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl, 357 356 results[i].explAlt ); … … 371 370 // push empty tuple expression 372 371 newResult.parent = i; 373 newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} }; 372 std::vector< ast::ptr< ast::Expr > > emptyList; 373 newResult.expr = 374 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) }; 374 375 argType = newResult.expr->result; 375 376 } else { … … 399 400 400 401 // check unification for ttype before adding to final 401 if ( 402 unify( 402 if ( 403 unify( 403 404 ttype, argType, newResult.env, newResult.need, newResult.have, 404 newResult.open, symtab ) 405 newResult.open, symtab ) 405 406 ) { 406 407 finalResults.emplace_back( move( newResult ) ); … … 423 424 if ( expl.exprs.empty() ) { 424 425 results.emplace_back( 425 results[i], move( env ), copy( results[i].need ), 426 results[i], move( env ), copy( results[i].need ), 426 427 copy( results[i].have ), move( open ), nextArg + 1, expl.cost ); 427 428 428 429 continue; 429 430 } … … 431 432 // add new result 432 433 results.emplace_back( 433 i, expl.exprs.front(), move( env ), copy( results[i].need ), 434 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 434 i, expl.exprs.front(), move( env ), copy( results[i].need ), 435 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 435 436 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 436 437 } … … 478 479 479 480 results.emplace_back( 480 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 481 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 481 482 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 482 483 } … … 494 495 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) { 495 496 results.emplace_back( 496 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 497 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 497 498 move( need ), move( have ), move( open ), nextArg, nTuples ); 498 499 } … … 516 517 if ( expl.exprs.empty() ) { 517 518 results.emplace_back( 518 results[i], move( env ), move( need ), move( have ), move( open ), 519 results[i], move( env ), move( need ), move( have ), move( open ), 519 520 nextArg + 1, expl.cost ); 520 521 521 522 continue; 522 523 } … … 538 539 // add new result 539 540 results.emplace_back( 540 i, expr, move( env ), move( need ), move( have ), move( open ), 541 i, expr, move( env ), move( need ), move( have ), move( open ), 541 542 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 542 543 } … … 547 548 genStart = genEnd; 548 549 549 return genEnd != results.size(); // were any new results added?550 return genEnd != results.size(); 550 551 } 551 552 552 553 /// Generate a cast expression from `arg` to `toType` 553 const ast::Expr * restructureCast( 554 const ast::Expr * restructureCast( 554 555 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast 555 556 ) { 556 if ( 557 arg->result->size() > 1 558 && ! toType->isVoid() 559 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 557 if ( 558 arg->result->size() > 1 559 && ! toType->isVoid() 560 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 560 561 ) { 561 // Argument is a tuple and the target type is neither void nor a reference. Cast each 562 // member of the tuple to its corresponding target type, producing the tuple of those 563 // cast expressions. If there are more components of the tuple than components in the 564 // target type, then excess components do not come out in the result expression (but 562 // Argument is a tuple and the target type is neither void nor a reference. Cast each 563 // member of the tuple to its corresponding target type, producing the tuple of those 564 // cast expressions. If there are more components of the tuple than components in the 565 // target type, then excess components do not come out in the result expression (but 565 566 // UniqueExpr ensures that the side effects will still be produced) 566 567 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 567 // expressions which may contain side effects require a single unique instance of 568 // expressions which may contain side effects require a single unique instance of 568 569 // the expression 569 570 arg = new ast::UniqueExpr{ arg->location, arg }; … … 573 574 // cast each component 574 575 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i }; 575 components.emplace_back( 576 components.emplace_back( 576 577 restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 577 578 } … … 593 594 594 595 /// Actually visits expressions to find their candidate interpretations 595 class Finder final : public ast::WithShortCircuiting { 596 struct Finder final : public ast::WithShortCircuiting { 597 CandidateFinder & selfFinder; 596 598 const ast::SymbolTable & symtab; 597 public:598 CandidateFinder & selfFinder;599 599 CandidateList & candidates; 600 600 const ast::TypeEnvironment & tenv; 601 601 ast::ptr< ast::Type > & targetType; 602 602 603 enum Errors {604 NotFound,605 NoMatch,606 ArgsToFew,607 ArgsToMany,608 RetsToFew,609 RetsToMany,610 NoReason611 };612 613 struct {614 Errors code = NotFound;615 } reason;616 617 603 Finder( CandidateFinder & f ) 618 : s ymtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),604 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ), 619 605 targetType( f.targetType ) {} 620 606 621 607 void previsit( const ast::Node * ) { visit_children = false; } 622 608 … … 625 611 void addCandidate( Args &&... args ) { 626 612 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } ); 627 reason.code = NoReason;628 613 } 629 614 … … 654 639 655 640 /// Completes a function candidate with arguments located 656 void validateFunctionCandidate( 657 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 658 CandidateList & out 641 void validateFunctionCandidate( 642 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 643 CandidateList & out 659 644 ) { 660 ast::ApplicationExpr * appExpr = 645 ast::ApplicationExpr * appExpr = 661 646 new ast::ApplicationExpr{ func->expr->location, func->expr }; 662 647 // sum cost and accumulate arguments … … 672 657 appExpr->args = move( vargs ); 673 658 // build and validate new candidate 674 auto newCand = 659 auto newCand = 675 660 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost ); 676 661 PRINT( … … 684 669 /// Builds a list of candidates for a function, storing them in out 685 670 void makeFunctionCandidates( 686 const CandidateRef & func, const ast::FunctionType * funcType, 671 const CandidateRef & func, const ast::FunctionType * funcType, 687 672 const ExplodedArgs_new & args, CandidateList & out 688 673 ) { … … 691 676 ast::TypeEnvironment funcEnv{ func->env }; 692 677 makeUnifiableVars( funcType, funcOpen, funcNeed ); 693 // add all type variables as open variables now so that those not used in the 694 // parameterlist are still considered open678 // add all type variables as open variables now so that those not used in the parameter 679 // list are still considered open 695 680 funcEnv.add( funcType->forall ); 696 681 … … 698 683 // attempt to narrow based on expected target type 699 684 const ast::Type * returnType = funcType->returns.front()->get_type(); 700 if ( ! unify( 701 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 685 if ( ! unify( 686 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 702 687 ) { 703 688 // unification failed, do not pursue this candidate … … 713 698 for ( const ast::DeclWithType * param : funcType->params ) { 714 699 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param ); 715 // Try adding the arguments corresponding to the current parameter to the existing 700 // Try adding the arguments corresponding to the current parameter to the existing 716 701 // matches 717 if ( ! instantiateArgument( 702 if ( ! instantiateArgument( 718 703 obj->type, obj->init, args, results, genStart, symtab ) ) return; 719 704 } … … 765 750 if ( expl.exprs.empty() ) { 766 751 results.emplace_back( 767 results[i], move( env ), copy( results[i].need ), 768 copy( results[i].have ), move( open ), nextArg + 1, 752 results[i], move( env ), copy( results[i].need ), 753 copy( results[i].have ), move( open ), nextArg + 1, 769 754 expl.cost ); 770 755 … … 775 760 results.emplace_back( 776 761 i, expl.exprs.front(), move( env ), copy( results[i].need ), 777 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 762 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 778 763 expl.exprs.size() == 1 ? 0 : 1, j ); 779 764 } … … 795 780 /// Adds implicit struct-conversions to the alternative list 796 781 void addAnonConversions( const CandidateRef & cand ) { 797 // adds anonymous member interpretations whenever an aggregate value type is seen. 798 // it's okay for the aggregate expression to have reference type -- cast it to the 782 // adds anonymous member interpretations whenever an aggregate value type is seen. 783 // it's okay for the aggregate expression to have reference type -- cast it to the 799 784 // base type to treat the aggregate as the referenced value 800 785 ast::ptr< ast::Expr > aggrExpr( cand->expr ); 801 786 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result; 802 787 cand->env.apply( aggrType ); 803 788 804 789 if ( aggrType.as< ast::ReferenceType >() ) { 805 790 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; … … 814 799 815 800 /// Adds aggregate member interpretations 816 void addAggMembers( 817 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 818 const Candidate & cand, const Cost & addedCost, const std::string & name 801 void addAggMembers( 802 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 803 const Candidate & cand, const Cost & addedCost, const std::string & name 819 804 ) { 820 805 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 821 806 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 822 CandidateRef newCand = std::make_shared<Candidate>( 807 CandidateRef newCand = std::make_shared<Candidate>( 823 808 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 824 // add anonymous member interpretations whenever an aggregate value type is seen 809 // add anonymous member interpretations whenever an aggregate value type is seen 825 810 // as a member expression 826 811 addAnonConversions( newCand ); … … 830 815 831 816 /// Adds tuple member interpretations 832 void addTupleMembers( 833 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 834 const Cost & addedCost, const ast::Expr * member 817 void addTupleMembers( 818 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 819 const Cost & addedCost, const ast::Expr * member 835 820 ) { 836 821 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) { 837 // get the value of the constant expression as an int, must be between 0 and the 822 // get the value of the constant expression as an int, must be between 0 and the 838 823 // length of the tuple to have meaning 839 824 long long val = constantExpr->intValue(); 840 825 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 841 826 addCandidate( 842 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 827 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 843 828 addedCost ); 844 829 } … … 852 837 if ( funcFinder.candidates.empty() ) return; 853 838 854 reason.code = NoMatch; 855 856 std::vector< CandidateFinder > argCandidates = 839 std::vector< CandidateFinder > argCandidates = 857 840 selfFinder.findSubExprs( untypedExpr->args ); 858 841 859 842 // take care of possible tuple assignments 860 843 // if not tuple assignment, handled as normal function call … … 894 877 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 895 878 CandidateRef newFunc{ new Candidate{ *func } }; 896 newFunc->expr = 879 newFunc->expr = 897 880 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 898 881 makeFunctionCandidates( newFunc, function, argExpansions, found ); 899 882 } 900 } else if ( 901 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 883 } else if ( 884 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 902 885 ) { 903 886 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) { 904 887 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 905 888 CandidateRef newFunc{ new Candidate{ *func } }; 906 newFunc->expr = 889 newFunc->expr = 907 890 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 908 891 makeFunctionCandidates( newFunc, function, argExpansions, found ); … … 918 901 std::vector< ExplodedArg > funcE; 919 902 funcE.reserve( funcFinder.candidates.size() ); 920 for ( const CandidateRef & func : funcFinder ) { 903 for ( const CandidateRef & func : funcFinder ) { 921 904 funcE.emplace_back( *func, symtab ); 922 905 } … … 930 913 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 931 914 CandidateRef newOp{ new Candidate{ *op} }; 932 newOp->expr = 915 newOp->expr = 933 916 referenceToRvalueConversion( newOp->expr, newOp->cost ); 934 917 makeFunctionCandidates( newOp, function, argExpansions, found ); … … 939 922 } 940 923 941 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 924 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 942 925 // candidates 943 926 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } … … 951 934 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 952 935 auto function = pointer->base.strict_as< ast::FunctionType >(); 953 936 954 937 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 955 938 std::cerr << "parameters are:" << std::endl; … … 974 957 promoteCvtCost( winners ); 975 958 976 // function may return a struct/union value, in which case we need to add candidates 977 // for implicit conversions to each of the anonymous members, which must happen after 959 // function may return a struct/union value, in which case we need to add candidates 960 // for implicit conversions to each of the anonymous members, which must happen after 978 961 // `findMinCost`, since anon conversions are never the cheapest 979 962 for ( const CandidateRef & c : winners ) { … … 983 966 984 967 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 985 // If resolution is unsuccessful with a target type, try again without, since it 968 // If resolution is unsuccessful with a target type, try again without, since it 986 969 // will sometimes succeed when it wouldn't with a target type binding. 987 970 // For example: … … 1000 983 /// true if expression is an lvalue 1001 984 static bool isLvalue( const ast::Expr * x ) { 1002 return x->result && ( x-> get_lvalue() || x->result.as< ast::ReferenceType >() );985 return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() ); 1003 986 } 1004 987 … … 1006 989 CandidateFinder finder{ symtab, tenv }; 1007 990 finder.find( addressExpr->arg ); 1008 1009 if( finder.candidates.empty() ) return;1010 1011 reason.code = NoMatch;1012 1013 991 for ( CandidateRef & r : finder.candidates ) { 1014 992 if ( ! isLvalue( r->expr ) ) continue; … … 1031 1009 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1032 1010 1033 if( !finder.candidates.empty() ) reason.code = NoMatch;1034 1035 1011 CandidateList matches; 1036 1012 for ( CandidateRef & cand : finder.candidates ) { … … 1040 1016 cand->env.extractOpenVars( open ); 1041 1017 1042 // It is possible that a cast can throw away some values in a multiply-valued 1043 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1044 // subexpression results that are cast directly. The candidate is invalid if it 1018 // It is possible that a cast can throw away some values in a multiply-valued 1019 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1020 // subexpression results that are cast directly. The candidate is invalid if it 1045 1021 // has fewer results than there are types to cast to. 1046 1022 int discardedValues = cand->expr->result->size() - toType->size(); … … 1049 1025 // unification run for side-effects 1050 1026 unify( toType, cand->expr->result, cand->env, need, have, open, symtab ); 1051 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1052 symtab, cand->env ); 1027 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env ); 1053 1028 PRINT( 1054 1029 std::cerr << "working on cast with result: " << toType << std::endl; … … 1062 1037 // count one safe conversion for each value that is thrown away 1063 1038 thisCost.incSafe( discardedValues ); 1064 CandidateRef newCand = std::make_shared<Candidate>( 1065 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1066 copy( cand->env ), move( open ), move( need ), cand->cost, 1039 CandidateRef newCand = std::make_shared<Candidate>( 1040 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1041 copy( cand->env ), move( open ), move( need ), cand->cost, 1067 1042 cand->cost + thisCost ); 1068 1043 inferParameters( newCand, matches ); … … 1082 1057 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 1083 1058 for ( CandidateRef & r : finder.candidates ) { 1084 addCandidate( 1085 *r, 1059 addCandidate( 1060 *r, 1086 1061 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 1087 1062 } … … 1092 1067 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1093 1068 for ( CandidateRef & agg : aggFinder.candidates ) { 1094 // it's okay for the aggregate expression to have reference type -- cast it to the 1069 // it's okay for the aggregate expression to have reference type -- cast it to the 1095 1070 // base type to treat the aggregate as the referenced value 1096 1071 Cost addedCost = Cost::zero; … … 1099 1074 // find member of the given type 1100 1075 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1101 addAggMembers( 1076 addAggMembers( 1102 1077 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1103 1078 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1104 addAggMembers( 1079 addAggMembers( 1105 1080 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1106 1081 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { … … 1117 1092 std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name ); 1118 1093 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1119 if( declList.empty() ) return;1120 1121 reason.code = NoMatch;1122 1123 1094 for ( auto & data : declList ) { 1124 1095 Cost cost = Cost::zero; … … 1126 1097 1127 1098 CandidateRef newCand = std::make_shared<Candidate>( 1128 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1099 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1129 1100 cost ); 1130 1101 PRINT( … … 1136 1107 std::cerr << std::endl; 1137 1108 ) 1138 newCand->expr = ast::mutate_field( 1139 newCand->expr.get(), &ast::Expr::result, 1109 newCand->expr = ast::mutate_field( 1110 newCand->expr.get(), &ast::Expr::result, 1140 1111 renameTyVars( newCand->expr->result ) ); 1141 // add anonymous member interpretations whenever an aggregate value type is seen 1112 // add anonymous member interpretations whenever an aggregate value type is seen 1142 1113 // as a name expression 1143 1114 addAnonConversions( newCand ); … … 1149 1120 // not sufficient to just pass `variableExpr` here, type might have changed since 1150 1121 // creation 1151 addCandidate( 1122 addCandidate( 1152 1123 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 1153 1124 } … … 1159 1130 void postvisit( const ast::SizeofExpr * sizeofExpr ) { 1160 1131 if ( sizeofExpr->type ) { 1161 addCandidate( 1162 new ast::SizeofExpr{ 1163 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1132 addCandidate( 1133 new ast::SizeofExpr{ 1134 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1164 1135 tenv ); 1165 1136 } else { … … 1170 1141 CandidateList winners = findMinCost( finder.candidates ); 1171 1142 if ( winners.size() != 1 ) { 1172 SemanticError( 1143 SemanticError( 1173 1144 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1174 1145 } … … 1183 1154 void postvisit( const ast::AlignofExpr * alignofExpr ) { 1184 1155 if ( alignofExpr->type ) { 1185 addCandidate( 1186 new ast::AlignofExpr{ 1187 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1156 addCandidate( 1157 new ast::AlignofExpr{ 1158 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1188 1159 tenv ); 1189 1160 } else { … … 1194 1165 CandidateList winners = findMinCost( finder.candidates ); 1195 1166 if ( winners.size() != 1 ) { 1196 SemanticError( 1167 SemanticError( 1197 1168 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1198 1169 } … … 1201 1172 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1202 1173 choice->cost = Cost::zero; 1203 addCandidate( 1174 addCandidate( 1204 1175 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1205 1176 } … … 1214 1185 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1215 1186 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1216 addCandidate( 1187 addCandidate( 1217 1188 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1218 1189 } … … 1235 1206 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 1236 1207 if ( finder2.candidates.empty() ) return; 1237 1238 reason.code = NoMatch;1239 1208 1240 1209 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1249 1218 1250 1219 addCandidate( 1251 new ast::LogicalExpr{ 1220 new ast::LogicalExpr{ 1252 1221 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1253 1222 move( env ), move( open ), move( need ), r1->cost + r2->cost ); … … 1271 1240 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1272 1241 if ( finder3.candidates.empty() ) return; 1273 1274 reason.code = NoMatch;1275 1242 1276 1243 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1289 1256 ast::AssertionSet have; 1290 1257 1291 // unify true and false results, then infer parameters to produce new 1258 // unify true and false results, then infer parameters to produce new 1292 1259 // candidates 1293 1260 ast::ptr< ast::Type > common; 1294 if ( 1295 unify( 1296 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1297 common ) 1261 if ( 1262 unify( 1263 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1264 common ) 1298 1265 ) { 1299 1266 // generate typed expression 1300 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1267 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1301 1268 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1302 1269 newExpr->result = common ? common : r2->expr->result; 1303 1270 // convert both options to result type 1304 1271 Cost cost = r1->cost + r2->cost + r3->cost; 1305 newExpr->arg2 = computeExpressionConversionCost( 1272 newExpr->arg2 = computeExpressionConversionCost( 1306 1273 newExpr->arg2, newExpr->result, symtab, env, cost ); 1307 1274 newExpr->arg3 = computeExpressionConversionCost( … … 1320 1287 ast::TypeEnvironment env{ tenv }; 1321 1288 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env ); 1322 1289 1323 1290 CandidateFinder finder2{ symtab, env }; 1324 1291 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); … … 1350 1317 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 1351 1318 if ( finder2.candidates.empty() ) return; 1352 1353 reason.code = NoMatch;1354 1319 1355 1320 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1365 1330 1366 1331 ast::ptr< ast::Type > common; 1367 if ( 1368 unify( 1369 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1370 common ) 1332 if ( 1333 unify( 1334 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1335 common ) 1371 1336 ) { 1372 1337 // generate new expression 1373 ast::RangeExpr * newExpr = 1338 ast::RangeExpr * newExpr = 1374 1339 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1375 1340 newExpr->result = common ? common : r1->expr->result; 1376 1341 // add candidate 1377 1342 CandidateRef newCand = std::make_shared<Candidate>( 1378 newExpr, move( env ), move( open ), move( need ), 1343 newExpr, move( env ), move( open ), move( need ), 1379 1344 r1->cost + r2->cost ); 1380 1345 inferParameters( newCand, candidates ); … … 1385 1350 1386 1351 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 1387 std::vector< CandidateFinder > subCandidates = 1352 std::vector< CandidateFinder > subCandidates = 1388 1353 selfFinder.findSubExprs( tupleExpr->exprs ); 1389 1354 std::vector< CandidateList > possibilities; … … 1405 1370 1406 1371 addCandidate( 1407 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1372 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1408 1373 move( env ), move( open ), move( need ), sumCost( subs ) ); 1409 1374 } … … 1447 1412 toType = SymTab::validateType( initExpr->location, toType, symtab ); 1448 1413 toType = adjustExprType( toType, tenv, symtab ); 1449 // The call to find must occur inside this loop, otherwise polymorphic return 1450 // types are not bound to the initialization type, since return type variables are 1451 // only open for the duration of resolving the UntypedExpr. 1414 // The call to find must occur inside this loop, otherwise polymorphic return 1415 // types are not bound to the initialization type, since return type variables are 1416 // only open for the duration of resolving the UntypedExpr. 1452 1417 CandidateFinder finder{ symtab, tenv, toType }; 1453 1418 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1454 1419 for ( CandidateRef & cand : finder.candidates ) { 1455 if(reason.code == NotFound) reason.code = NoMatch;1456 1457 1420 ast::TypeEnvironment env{ cand->env }; 1458 1421 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; … … 1463 1426 ) 1464 1427 1465 // It is possible that a cast can throw away some values in a multiply-valued 1466 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1467 // the subexpression results that are cast directly. The candidate is invalid 1428 // It is possible that a cast can throw away some values in a multiply-valued 1429 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1430 // the subexpression results that are cast directly. The candidate is invalid 1468 1431 // if it has fewer results than there are types to cast to. 1469 1432 int discardedValues = cand->expr->result->size() - toType->size(); … … 1472 1435 // unification run for side-effects 1473 1436 unify( toType, cand->expr->result, env, need, have, open, symtab ); 1474 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1475 symtab, env ); 1476 1437 Cost thisCost = castCost( cand->expr->result, toType, symtab, env ); 1438 1477 1439 if ( thisCost != Cost::infinity ) { 1478 1440 // count one safe conversion for each value that is thrown away 1479 1441 thisCost.incSafe( discardedValues ); 1480 CandidateRef newCand = std::make_shared<Candidate>( 1481 new ast::InitExpr{ 1482 initExpr->location, restructureCast( cand->expr, toType ), 1483 initAlt.designation }, 1442 CandidateRef newCand = std::make_shared<Candidate>( 1443 new ast::InitExpr{ 1444 initExpr->location, restructureCast( cand->expr, toType ), 1445 initAlt.designation }, 1484 1446 copy( cand->env ), move( open ), move( need ), cand->cost, thisCost ); 1485 1447 inferParameters( newCand, matches ); … … 1507 1469 }; 1508 1470 1509 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1471 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1510 1472 /// return type. Skips ambiguous candidates. 1511 1473 CandidateList pruneCandidates( CandidateList & candidates ) { … … 1524 1486 { 1525 1487 ast::ptr< ast::Type > newType = candidate->expr->result; 1526 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());1527 1488 candidate->env.apply( newType ); 1528 1489 mangleName = Mangle::mangle( newType ); … … 1533 1494 if ( candidate->cost < found->second.candidate->cost ) { 1534 1495 PRINT( 1535 std::cerr << "cost " << candidate->cost << " beats " 1496 std::cerr << "cost " << candidate->cost << " beats " 1536 1497 << found->second.candidate->cost << std::endl; 1537 1498 ) … … 1539 1500 found->second = PruneStruct{ candidate }; 1540 1501 } else if ( candidate->cost == found->second.candidate->cost ) { 1541 // if one of the candidates contains a deleted identifier, can pick the other, 1542 // since deleted expressions should not be ambiguous if there is another option 1502 // if one of the candidates contains a deleted identifier, can pick the other, 1503 // since deleted expressions should not be ambiguous if there is another option 1543 1504 // that is at least as good 1544 1505 if ( findDeletedExpr( candidate->expr ) ) { … … 1554 1515 } else { 1555 1516 PRINT( 1556 std::cerr << "cost " << candidate->cost << " loses to " 1517 std::cerr << "cost " << candidate->cost << " loses to " 1557 1518 << found->second.candidate->cost << std::endl; 1558 1519 ) … … 1569 1530 1570 1531 CandidateRef cand = target.second.candidate; 1571 1532 1572 1533 ast::ptr< ast::Type > newResult = cand->expr->result; 1573 1534 cand->env.applyFree( newResult ); 1574 1535 cand->expr = ast::mutate_field( 1575 1536 cand->expr.get(), &ast::Expr::result, move( newResult ) ); 1576 1537 1577 1538 out.emplace_back( cand ); 1578 1539 } … … 1588 1549 1589 1550 if ( mode.failFast && candidates.empty() ) { 1590 switch(finder.pass.reason.code) { 1591 case Finder::NotFound: 1592 { SemanticError( expr, "No alternatives for expression " ); break; } 1593 case Finder::NoMatch: 1594 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; } 1595 case Finder::ArgsToFew: 1596 case Finder::ArgsToMany: 1597 case Finder::RetsToFew: 1598 case Finder::RetsToMany: 1599 case Finder::NoReason: 1600 default: 1601 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); } 1602 } 1551 SemanticError( expr, "No reasonable alternatives for expression " ); 1603 1552 } 1604 1553 … … 1609 1558 std::vector< std::string > errors; 1610 1559 for ( CandidateRef & candidate : candidates ) { 1611 satisfyAssertions( candidate, localSyms, satisfied, errors );1560 satisfyAssertions( candidate, symtab, satisfied, errors ); 1612 1561 } 1613 1562 … … 1634 1583 1635 1584 CandidateList pruned = pruneCandidates( candidates ); 1636 1585 1637 1586 if ( mode.failFast && pruned.empty() ) { 1638 1587 std::ostringstream stream; … … 1653 1602 ) 1654 1603 PRINT( 1655 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1604 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1656 1605 << std::endl; 1657 1606 ) 1658 1607 } 1659 1608 1660 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1609 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1661 1610 // adjusted 1662 1611 if ( mode.adjust ) { 1663 1612 for ( CandidateRef & r : candidates ) { 1664 r->expr = ast::mutate_field( 1665 r->expr.get(), &ast::Expr::result, 1666 adjustExprType( r->expr->result, r->env, localSyms) );1613 r->expr = ast::mutate_field( 1614 r->expr.get(), &ast::Expr::result, 1615 adjustExprType( r->expr->result, r->env, symtab ) ); 1667 1616 } 1668 1617 } … … 1676 1625 } 1677 1626 1678 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1679 const std::vector< ast::ptr< ast::Expr > > & xs 1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1628 const std::vector< ast::ptr< ast::Expr > > & xs 1680 1629 ) { 1681 1630 std::vector< CandidateFinder > out; 1682 1631 1683 1632 for ( const auto & x : xs ) { 1684 out.emplace_back( localSyms, env );1633 out.emplace_back( symtab, env ); 1685 1634 out.back().find( x, ResolvMode::withAdjustment() ); 1686 1635 1687 1636 PRINT( 1688 1637 std::cerr << "findSubExprs" << std::endl; -
src/ResolvExpr/CandidateFinder.hpp
r7030dab r057298e 9 9 // Author : Aaron B. Moss 10 10 // Created On : Wed Jun 5 14:30:00 2019 11 // Last Modified By : A ndrew Beach12 // Last Modified On : Tue Oct 1 9:51:00 201913 // Update Count : 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Wed Jun 5 14:30:00 2019 13 // Update Count : 1 14 14 // 15 15 … … 28 28 struct CandidateFinder { 29 29 CandidateList candidates; ///< List of candidate resolutions 30 const ast::SymbolTable & localSyms; ///< Symbol table to lookup candidates30 const ast::SymbolTable & symtab; ///< Symbol table to lookup candidates 31 31 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 32 32 ast::ptr< ast::Type > targetType; ///< Target type for resolution 33 33 34 CandidateFinder( 35 const ast::SymbolTable & sym s, const ast::TypeEnvironment & env,34 CandidateFinder( 35 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 36 36 const ast::Type * tt = nullptr ) 37 : candidates(), localSyms( syms), env( env ), targetType( tt ) {}37 : candidates(), symtab( symtab ), env( env ), targetType( tt ) {} 38 38 39 39 /// Fill candidates with feasible resolutions for `expr` … … 49 49 iterator begin() { return candidates.begin(); } 50 50 const_iterator begin() const { return candidates.begin(); } 51 51 52 52 iterator end() { return candidates.end(); } 53 53 const_iterator end() const { return candidates.end(); } … … 55 55 56 56 /// Computes conversion cost between two types 57 Cost computeConversionCost( 58 const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,59 const ast:: SymbolTable & symtab, const ast::TypeEnvironment & env );57 Cost computeConversionCost( 58 const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab, 59 const ast::TypeEnvironment & env ); 60 60 61 61 } // namespace ResolvExpr -
src/ResolvExpr/CastCost.cc
r7030dab r057298e 10 10 // Created On : Sun May 17 06:57:43 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T ue Oct 4 15:00:00 201913 // Update Count : 912 // Last Modified On : Thu Aug 8 16:12:00 2019 13 // Update Count : 8 14 14 // 15 15 … … 142 142 143 143 CastCost_new( 144 const ast::Type * dst, bool srcIsLvalue,const ast::SymbolTable & symtab,144 const ast::Type * dst, const ast::SymbolTable & symtab, 145 145 const ast::TypeEnvironment & env, CostCalculation costFunc ) 146 : ConversionCost_new( dst, s rcIsLvalue, symtab, env, costFunc ) {}146 : ConversionCost_new( dst, symtab, env, costFunc ) {} 147 147 148 148 void postvisit( const ast::BasicType * basicType ) { … … 152 152 cost = Cost::unsafe; 153 153 } else { 154 cost = conversionCost( basicType, dst, s rcIsLvalue, symtab, env );154 cost = conversionCost( basicType, dst, symtab, env ); 155 155 } 156 156 } … … 183 183 } 184 184 }; 185 186 #warning For overload resolution between the two versions.187 int localPtrsCastable(const ast::Type * t1, const ast::Type * t2,188 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) {189 return ptrsCastable( t1, t2, symtab, env );190 }191 Cost localCastCost(192 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,193 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env194 ) { return castCost( src, dst, srcIsLvalue, symtab, env ); }195 185 } // anonymous namespace 196 186 197 198 199 187 Cost castCost( 200 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,201 const ast:: SymbolTable & symtab, const ast::TypeEnvironment & env188 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 189 const ast::TypeEnvironment & env 202 190 ) { 203 191 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { … … 205 193 // check cast cost against bound type, if present 206 194 if ( eqvClass->bound ) { 207 return castCost( src, eqvClass->bound, s rcIsLvalue, symtab, env );195 return castCost( src, eqvClass->bound, symtab, env ); 208 196 } else { 209 197 return Cost::infinity; … … 213 201 auto type = strict_dynamic_cast< const ast::TypeDecl * >( named ); 214 202 if ( type->base ) { 215 return castCost( src, type->base, s rcIsLvalue, symtab, env ) + Cost::safe;203 return castCost( src, type->base, symtab, env ) + Cost::safe; 216 204 } 217 205 } … … 236 224 #warning cast on ptrsCastable artifact of having two functions, remove when port done 237 225 return convertToReferenceCost( 238 src, refType, srcIsLvalue, symtab, env, localPtrsCastable ); 226 src, refType, symtab, env, 227 ( int (*)( 228 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 229 const ast::TypeEnvironment & ) 230 ) ptrsCastable ); 239 231 } else { 240 232 #warning cast on castCost artifact of having two functions, remove when port done 241 ast::Pass< CastCost_new > converter( 242 dst, srcIsLvalue, symtab, env, localCastCost ); 233 ast::Pass< CastCost_new > converter{ 234 dst, symtab, env, 235 ( Cost (*)( 236 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 237 const ast::TypeEnvironment & ) 238 ) castCost }; 243 239 src->accept( converter ); 244 240 return converter.pass.cost; -
src/ResolvExpr/CommonType.cc
r7030dab r057298e 939 939 ast::ptr< ast::Type > result; 940 940 const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >(); 941 const ast::ReferenceType * ref2 = type 2.as< ast::ReferenceType >();941 const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >(); 942 942 943 943 if ( depth1 > depth2 ) { -
src/ResolvExpr/ConversionCost.cc
r7030dab r057298e 10 10 // Created On : Sun May 17 07:06:19 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Oct 4 14:45:00 201913 // Update Count : 2 812 // Last Modified On : Mon Aug 12 10:21:00 2019 13 // Update Count : 27 14 14 // 15 15 … … 497 497 } 498 498 499 namespace { 500 # warning For overload resolution between the two versions.501 int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,502 const ast::SymbolTable &, const ast::TypeEnvironment & env ) { 503 return ptrsAssignable( t1, t2, env ); 504 } 505 Cost localConversionCost( 506 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 507 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env508 ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }509 }499 static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2, 500 const ast::SymbolTable &, const ast::TypeEnvironment & env ) { 501 return ptrsAssignable( t1, t2, env ); 502 } 503 504 // TODO: This is used for overload resolution. It might be able to be dropped once the old system 505 // is removed. 506 static Cost localConversionCost( 507 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 508 const ast::TypeEnvironment & env 509 ) { return conversionCost( src, dst, symtab, env ); } 510 510 511 511 Cost conversionCost( 512 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,513 const ast:: SymbolTable & symtab, const ast::TypeEnvironment & env512 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 513 const ast::TypeEnvironment & env 514 514 ) { 515 515 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 516 516 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) { 517 517 if ( eqv->bound ) { 518 return conversionCost(src, eqv->bound, s rcIsLvalue, symtab, env );518 return conversionCost(src, eqv->bound, symtab, env ); 519 519 } else { 520 520 return Cost::infinity; … … 524 524 assertf( type, "Unexpected typedef." ); 525 525 if ( type->base ) { 526 return conversionCost( src, type->base, s rcIsLvalue, symtab, env ) + Cost::safe;526 return conversionCost( src, type->base, symtab, env ) + Cost::safe; 527 527 } 528 528 } … … 534 534 } else if ( const ast::ReferenceType * refType = 535 535 dynamic_cast< const ast::ReferenceType * >( dst ) ) { 536 return convertToReferenceCost( src, refType, s rcIsLvalue, symtab, env, localPtrsAssignable );536 return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable ); 537 537 } else { 538 ast::Pass<ConversionCost_new> converter( dst, s rcIsLvalue, symtab, env, localConversionCost );538 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost ); 539 539 src->accept( converter ); 540 540 return converter.pass.cost; … … 542 542 } 543 543 544 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,544 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, 545 545 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 546 PtrsCalculation func ) {546 NumCostCalculation func ) { 547 547 if ( 0 < diff ) { 548 548 Cost cost = convertToReferenceCost( 549 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,550 srcIsLvalue, (diff - 1), symtab, env, func );549 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, 550 dst, (diff - 1), symtab, env, func ); 551 551 cost.incReference(); 552 552 return cost; … … 554 554 Cost cost = convertToReferenceCost( 555 555 src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base, 556 srcIsLvalue,(diff + 1), symtab, env, func );556 (diff + 1), symtab, env, func ); 557 557 cost.incReference(); 558 558 return cost; … … 579 579 } 580 580 } else { 581 ast::Pass<ConversionCost_new> converter( dst, s rcIsLvalue, symtab, env, localConversionCost );581 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost ); 582 582 src->accept( converter ); 583 583 return converter.pass.cost; … … 588 588 assert( dstAsRef ); 589 589 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) { 590 if ( src IsLvalue) {590 if ( src->is_lvalue() ) { 591 591 if ( src->qualifiers == dstAsRef->base->qualifiers ) { 592 592 return Cost::reference; … … 607 607 608 608 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst, 609 bool srcIsLvalue,const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,610 PtrsCalculation func ) {609 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 610 NumCostCalculation func ) { 611 611 int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth(); 612 return convertToReferenceCost( src, dst, s rcIsLvalue, sdepth - ddepth, symtab, env, func );612 return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func ); 613 613 } 614 614 … … 667 667 assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) ); 668 668 669 cost = costCalc( refType->base, dst, s rcIsLvalue, symtab, env );669 cost = costCalc( refType->base, dst, symtab, env ); 670 670 if ( refType->base->qualifiers == dst->qualifiers ) { 671 671 cost.incReference(); … … 701 701 void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) { 702 702 (void)enumInstType; 703 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };704 cost = costCalc( integer, dst, srcIsLvalue, symtab, env );703 static const ast::BasicType integer( ast::BasicType::SignedInt ); 704 cost = costCalc( &integer, dst, symtab, env ); 705 705 if ( cost < Cost::unsafe ) { 706 706 cost.incSafe(); … … 714 714 void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) { 715 715 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) { 716 cost = costCalc( eqv->bound, dst, s rcIsLvalue, symtab, env );716 cost = costCalc( eqv->bound, dst, symtab, env ); 717 717 } else if ( const ast::TypeInstType * dstAsInst = 718 718 dynamic_cast< const ast::TypeInstType * >( dst ) ) { … … 724 724 assertf( type, "Unexpected typedef."); 725 725 if ( type->base ) { 726 cost = costCalc( type->base, dst, s rcIsLvalue, symtab, env ) + Cost::safe;726 cost = costCalc( type->base, dst, symtab, env ) + Cost::safe; 727 727 } 728 728 } … … 737 737 auto dstEnd = dstAsTuple->types.end(); 738 738 while ( srcIt != srcEnd && dstIt != dstEnd ) { 739 Cost newCost = costCalc( * srcIt++, * dstIt++, s rcIsLvalue, symtab, env );739 Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env ); 740 740 if ( newCost == Cost::infinity ) { 741 741 return; … … 772 772 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 773 773 } 774 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {775 cost = Cost::zero;776 // +1 for zero_t ->, +1 for disambiguation777 cost.incSafe( maxIntCost + 2 );778 774 } 779 775 } … … 793 789 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 794 790 } 791 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) { 792 cost = Cost::zero; 793 cost.incSafe( maxIntCost + 2 ); 795 794 } 796 795 } -
src/ResolvExpr/ConversionCost.h
r7030dab r057298e 10 10 // Created On : Sun May 17 09:37:28 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T ue Oct 4 14:59:00 201913 // Update Count : 712 // Last Modified On : Thu Aug 8 16:13:00 2019 13 // Update Count : 6 14 14 // 15 15 … … 74 74 75 75 // Some function pointer types, differ in return type. 76 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool,76 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, 77 77 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 78 using PtrsCalculation = std::function<int(const ast::Type *, const ast::Type *,78 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *, 79 79 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 80 80 … … 83 83 protected: 84 84 const ast::Type * dst; 85 bool srcIsLvalue;86 85 const ast::SymbolTable & symtab; 87 86 const ast::TypeEnvironment & env; … … 90 89 Cost cost; 91 90 92 ConversionCost_new( const ast::Type * dst, bool srcIsLvalue,const ast::SymbolTable & symtab,91 ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab, 93 92 const ast::TypeEnvironment & env, CostCalculation costCalc ) : 94 dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ), 95 costCalc( costCalc ), cost( Cost::infinity ) 93 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity ) 96 94 {} 97 95 … … 116 114 117 115 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest, 118 bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, 119 PtrsCalculation func ); 116 const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func ); 120 117 121 118 } // namespace ResolvExpr -
src/ResolvExpr/CurrentObject.cc
r7030dab r057298e 21 21 #include <string> // for string, operator<<, allocator 22 22 23 #include "AST/Copy.hpp" // for shallowCopy24 23 #include "AST/Expr.hpp" // for InitAlternative 25 24 #include "AST/GenericSubstitution.hpp" // for genericSubstitution 26 25 #include "AST/Init.hpp" // for Designation 27 26 #include "AST/Node.hpp" // for readonly 28 #include "AST/Print.hpp" // for readonly29 27 #include "AST/Type.hpp" 30 28 #include "Common/Indenter.h" // for Indenter, operator<< … … 598 596 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {} 599 597 600 void setPosition( 601 std::deque< ptr< Expr > >::const_iterator begin, 598 void setPosition( 599 std::deque< ptr< Expr > >::const_iterator begin, 602 600 std::deque< ptr< Expr > >::const_iterator end 603 601 ) override { … … 639 637 auto res = eval(expr); 640 638 if ( ! res.second ) { 641 SemanticError( location, 639 SemanticError( location, 642 640 toString("Array designator must be a constant expression: ", expr ) ); 643 641 } … … 646 644 647 645 public: 648 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 646 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 649 647 : location( loc ), array( at ), base( at->base ) { 650 648 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) … … 657 655 658 656 void setPosition( const Expr * expr ) { 659 // need to permit integer-constant-expressions, including: integer constants, 660 // enumeration constants, character constants, sizeof expressions, alignof expressions, 657 // need to permit integer-constant-expressions, including: integer constants, 658 // enumeration constants, character constants, sizeof expressions, alignof expressions, 661 659 // cast expressions 662 660 if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { … … 664 662 index = constExpr->intValue(); 665 663 } catch ( SemanticErrorException & ) { 666 SemanticError( expr, 664 SemanticError( expr, 667 665 "Constant expression of non-integral type in array designator: " ); 668 666 } 669 667 } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) { 670 668 setPosition( castExpr->arg ); 671 } else if ( 672 dynamic_cast< const SizeofExpr * >( expr ) 673 || dynamic_cast< const AlignofExpr * >( expr ) 669 } else if ( 670 dynamic_cast< const SizeofExpr * >( expr ) 671 || dynamic_cast< const AlignofExpr * >( expr ) 674 672 ) { 675 673 index = 0; 676 674 } else { 677 assertf( false, 675 assertf( false, 678 676 "bad designator given to ArrayIterator: %s", toString( expr ).c_str() ); 679 677 } 680 678 } 681 679 682 void setPosition( 683 std::deque< ptr< Expr > >::const_iterator begin, 680 void setPosition( 681 std::deque< ptr< Expr > >::const_iterator begin, 684 682 std::deque< ptr< Expr > >::const_iterator end 685 683 ) override { … … 760 758 } 761 759 762 AggregateIterator( 763 const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 760 AggregateIterator( 761 const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 764 762 const MemberList & ms ) 765 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 763 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 766 764 sub( genericSubstitution( i ) ) { 767 765 PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; ) … … 770 768 771 769 public: 772 void setPosition( 773 std::deque< ptr< Expr > >::const_iterator begin, 770 void setPosition( 771 std::deque< ptr< Expr > >::const_iterator begin, 774 772 std::deque< ptr< Expr > >::const_iterator end 775 773 ) final { … … 788 786 return; 789 787 } 790 assertf( false, 788 assertf( false, 791 789 "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() ); 792 790 } else { 793 assertf( false, 791 assertf( false, 794 792 "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() ); 795 793 } … … 805 803 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } ); 806 804 // need to substitute for generic types so that casts are to concrete types 807 alt.type = shallowCopy(alt.type.get());808 805 PRINT( std::cerr << " type is: " << alt.type; ) 809 806 sub.apply( alt.type ); // also apply to designation?? … … 845 842 for ( InitAlternative & alt : ret ) { 846 843 PRINT( std::cerr << "iterating and adding designators" << std::endl; ) 847 alt.designation.get_and_mutate()->designators.emplace_front( 844 alt.designation.get_and_mutate()->designators.emplace_front( 848 845 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } ); 849 846 } … … 900 897 class TupleIterator final : public AggregateIterator { 901 898 public: 902 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 903 : AggregateIterator( 904 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 899 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 900 : AggregateIterator( 901 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 905 902 ) {} 906 903 … … 929 926 return new UnionIterator{ loc, uit }; 930 927 } else { 931 assertf( 932 dynamic_cast< const EnumInstType * >( type )933 || dynamic_cast< const TypeInstType * >( type ),928 assertf( 929 dynamic_cast< const EnumInstType * >( aggr ) 930 || dynamic_cast< const TypeInstType * >( aggr ), 934 931 "Encountered unhandled ReferenceToType in createMemberIterator: %s", 935 932 toString( type ).c_str() ); … … 952 949 using DesignatorChain = std::deque< ptr< Expr > >; 953 950 PRINT( std::cerr << "___findNext" << std::endl; ) 954 951 955 952 // find all the d's 956 953 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts; … … 1016 1013 // set new designators 1017 1014 assertf( ! objStack.empty(), "empty object stack when setting designation" ); 1018 Designation * actualDesignation = 1015 Designation * actualDesignation = 1019 1016 new Designation{ designation->location, DesignatorChain{d} }; 1020 1017 objStack.back()->setPosition( d ); // destroys d -
src/ResolvExpr/PolyCost.cc
r7030dab r057298e 58 58 59 59 // TODO: When the old PolyCost is torn out get rid of the _new suffix. 60 class PolyCost_new { 60 struct PolyCost_new { 61 int result; 61 62 const ast::SymbolTable &symtab; 62 public:63 int result;64 63 const ast::TypeEnvironment &env_; 65 64 66 PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) 67 : symtab( symtab ), result( 0), env_( env ) {}65 PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) : 66 result( 0 ), symtab( symtab ), env_( env ) {} 68 67 69 68 void previsit( const ast::TypeInstType * type ) { -
src/ResolvExpr/RenameVars.cc
r7030dab r057298e 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" … … 31 30 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 32 31 33 #include "AST/Copy.hpp"34 35 32 namespace ResolvExpr { 36 33 … … 40 37 int resetCount = 0; 41 38 ScopedMap< std::string, std::string > nameMap; 39 42 40 public: 43 ast::ForallSubstitutionTable subs;44 45 41 void reset() { 46 42 level = 0; … … 48 44 } 49 45 46 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator; 47 50 48 void rename( TypeInstType * type ) { 51 autoit = nameMap.find( type->name );49 mapConstIterator it = nameMap.find( type->name ); 52 50 if ( it != nameMap.end() ) { 53 51 type->name = it->second; … … 67 65 // ditto for assertion names, the next level in 68 66 level++; 69 } 70 } 67 // acceptAll( td->assertions, *this ); 68 } // for 69 } // if 71 70 } 72 71 … … 78 77 79 78 const ast::TypeInstType * rename( const ast::TypeInstType * type ) { 80 // re-linking of base type handled by WithForallSubstitutor 81 82 // rename 83 auto it = nameMap.find( type->name ); 79 mapConstIterator it = nameMap.find( type->name ); 84 80 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; 89 type = mut; 81 ast::TypeInstType * mutType = ast::mutate( type ); 82 mutType->name = it->second; 83 type = mutType; 90 84 } 91 92 85 return type; 93 86 } … … 95 88 template<typename NodeT> 96 89 const NodeT * openLevel( const NodeT * type ) { 97 if ( type->forall.empty() ) return type; 90 if ( !type->forall.empty() ) { 91 nameMap.beginScope(); 92 // Load new names from this forall clause and perform renaming. 93 NodeT * mutType = ast::mutate( type ); 94 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) { 95 std::ostringstream output; 96 output << "_" << resetCount << "_" << level << "_" << td->name; 97 std::string newname( output.str() ); 98 nameMap[ td->name ] = newname; 99 ++level; 98 100 99 nameMap.beginScope(); 100 101 // 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 101 ast::TypeDecl * decl = ast::mutate( td.get() ); 102 decl->name = newname; 103 td = decl; 104 } 115 105 } 116 // assertion above means `type = mutType;` is unnecessary117 118 106 return type; 119 107 } 120 108 121 void closeLevel( const ast::ParameterizedType * type ) { 122 if ( type->forall.empty() ) return; 123 124 nameMap.endScope(); 109 template<typename NodeT> 110 const NodeT * closeLevel( const NodeT * type ) { 111 if ( !type->forall.empty() ) { 112 nameMap.endScope(); 113 } 114 return type; 125 115 } 126 116 }; … … 129 119 RenamingData renaming; 130 120 131 struct RenameVars _old{121 struct RenameVars { 132 122 void previsit( TypeInstType * instType ) { 133 123 renaming.openLevel( (Type*)instType ); … … 140 130 renaming.closeLevel( type ); 141 131 } 142 };143 144 struct RenameVars_new /*: public ast::WithForallSubstitutor*/ {145 #warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor146 ast::ForallSubstitutionTable & subs = renaming.subs;147 132 148 133 const ast::FunctionType * previsit( const ast::FunctionType * type ) { … … 161 146 return renaming.rename( renaming.openLevel( type ) ); 162 147 } 163 voidpostvisit( const ast::ParameterizedType * type ) {164 re naming.closeLevel( type );148 const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) { 149 return renaming.closeLevel( type ); 165 150 } 166 151 }; … … 169 154 170 155 void renameTyVars( Type * t ) { 171 PassVisitor<RenameVars _old> renamer;156 PassVisitor<RenameVars> renamer; 172 157 t->accept( renamer ); 173 158 } 174 159 175 160 const ast::Type * renameTyVars( const ast::Type * t ) { 176 ast::Type *tc = ast::deepCopy(t); 177 ast::Pass<RenameVars_new> renamer; 178 // return t->accept( renamer ); 179 return tc->accept( renamer ); 161 ast::Pass<RenameVars> renamer; 162 return t->accept( renamer ); 180 163 } 181 164 -
src/ResolvExpr/ResolveTypeof.cc
r7030dab r057298e 99 99 // replace basetypeof(<enum>) by int 100 100 if ( dynamic_cast<EnumInstType*>(newType) ) { 101 Type* newerType = 102 new BasicType{ newType->get_qualifiers(), BasicType::SignedInt, 101 Type* newerType = 102 new BasicType{ newType->get_qualifiers(), BasicType::SignedInt, 103 103 newType->attributes }; 104 104 delete newType; 105 105 newType = newerType; 106 106 } 107 newType->get_qualifiers().val 107 newType->get_qualifiers().val 108 108 = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals; 109 109 } else { 110 110 newType->get_qualifiers().val |= oldQuals; 111 111 } 112 112 113 113 return newType; 114 114 } … … 120 120 ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {} 121 121 122 void pre visit( const ast::TypeofType * ) { visit_children = false; }122 void premutate( const ast::TypeofType * ) { visit_children = false; } 123 123 124 const ast::Type * post visit( const ast::TypeofType * typeofType ) {124 const ast::Type * postmutate( const ast::TypeofType * typeofType ) { 125 125 // pass on null expression 126 126 if ( ! typeofType->expr ) return typeofType; … … 133 133 // typeof wrapping expression 134 134 ast::TypeEnvironment dummy; 135 ast::ptr< ast::Expr > newExpr = 135 ast::ptr< ast::Expr > newExpr = 136 136 resolveInVoidContext( typeofType->expr, localSymtab, dummy ); 137 137 assert( newExpr->result && ! newExpr->result->isVoid() ); … … 143 143 // replace basetypeof(<enum>) by int 144 144 if ( newType.as< ast::EnumInstType >() ) { 145 newType = new ast::BasicType{ 145 newType = new ast::BasicType{ 146 146 ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) }; 147 147 } 148 reset_qualifiers( 149 newType, 148 reset_qualifiers( 149 newType, 150 150 ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers ); 151 151 } else { … … 153 153 } 154 154 155 return newType .release();155 return newType; 156 156 } 157 157 }; -
src/ResolvExpr/Resolver.cc
r7030dab r057298e 1074 1074 const ast::Expr * postmutate( const ast::CastExpr * castExpr ) { 1075 1075 if ( 1076 castExpr->isGenerated == ast::GeneratedCast1076 castExpr->isGenerated 1077 1077 && typesCompatible( castExpr->arg->result, castExpr->result ) 1078 1078 ) { … … 1128 1128 1129 1129 // set up and resolve expression cast to void 1130 ast:: ptr< ast::CastExpr >untyped = new ast::CastExpr{ expr };1130 ast::CastExpr * untyped = new ast::CastExpr{ expr }; 1131 1131 CandidateRef choice = findUnfinishedKindExpression( 1132 1132 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); … … 1267 1267 }; 1268 1268 1269 void resolve( std::list< ast::ptr< ast::Decl> >& translationUnit ) {1269 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) { 1270 1270 ast::Pass< Resolver_new > resolver; 1271 1271 accept_all( translationUnit, resolver ); … … 1301 1301 ast::ptr< ast::FunctionDecl > ret = functionDecl; 1302 1302 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) { 1303 const ast::ptr< ast::DeclWithType> & d = functionDecl->type->params[i];1303 const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i]; 1304 1304 1305 1305 if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) { … … 1318 1318 } 1319 1319 } 1320 return ret. release();1320 return ret.get(); 1321 1321 } 1322 1322 … … 1341 1341 // in case we decide to allow nested enums 1342 1342 GuardValue( inEnumDecl ); 1343 inEnumDecl = true;1343 inEnumDecl = false; 1344 1344 } 1345 1345 -
src/ResolvExpr/SatisfyAssertions.cpp
r7030dab r057298e 9 9 // Author : Aaron B. Moss 10 10 // Created On : Mon Jun 10 17:45:00 2019 11 // Last Modified By : A ndrew Beach12 // Last Modified On : Tue Oct 1 13:56:00 201913 // Update Count : 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 10 17:45:00 2019 13 // Update Count : 1 14 14 // 15 15 … … 299 299 Cost cost; 300 300 301 OutType( 302 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 301 OutType( 302 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 303 303 const std::vector< DeferRef > & as, const ast::SymbolTable & symtab ) 304 304 : env( e ), open( o ), assns( as ), cost( Cost::zero ) { … … 306 306 for ( const DeferRef & assn : assns ) { 307 307 // compute conversion cost from satisfying decl to assertion 308 cost += computeConversionCost( 309 assn.match.adjType, assn.decl->get_type(), false,symtab, env );310 308 cost += computeConversionCost( 309 assn.match.adjType, assn.decl->get_type(), symtab, env ); 310 311 311 // mark vars+specialization on function-type assertions 312 const ast::FunctionType * func = 312 const ast::FunctionType * func = 313 313 GenPoly::getFunctionType( assn.match.cdata.id->get_type() ); 314 314 if ( ! func ) continue; … … 317 317 cost.decSpec( specCost( param->get_type() ) ); 318 318 } 319 319 320 320 cost.incVar( func->forall.size() ); 321 321 322 322 for ( const ast::TypeDecl * td : func->forall ) { 323 323 cost.decSpec( td->assertions.size() ); … … 329 329 }; 330 330 331 CandidateEnvMerger( 332 const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 331 CandidateEnvMerger( 332 const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 333 333 const ast::SymbolTable & syms ) 334 334 : crnt(), envs{ env }, opens{ open }, symtab( syms ) {} -
src/ResolvExpr/SatisfyAssertions.hpp
r7030dab r057298e 28 28 29 29 /// Recursively satisfies all assertions provided in a candidate; returns true if succeeds 30 void satisfyAssertions( 31 CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out, 30 void satisfyAssertions( 31 CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out, 32 32 std::vector<std::string> & errors ); 33 33 -
src/ResolvExpr/SpecCost.cc
r7030dab r057298e 10 10 // Created On : Tue Oct 02 15:50:00 2018 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jul 3 11:07:00 2019 13 // Update Count : 3 14 // 15 16 #include <cassert> 12 // Last Modified On : Wed Jun 19 10:43:00 2019 13 // Update Count : 2 14 // 15 17 16 #include <limits> 18 17 #include <list> … … 130 129 typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type; 131 130 132 #warning Should use a standard maybe_accept133 void maybe_accept( ast::Type const * type ) {134 if ( type ) {135 auto node = type->accept( *visitor );136 assert( node == nullptr || node == type );137 }138 }139 140 131 // Update the minimum to the new lowest non-none value. 141 132 template<typename T> … … 143 134 for ( const auto & node : list ) { 144 135 count = -1; 145 ma ybe_accept( mapper( node ));136 mapper( node )->accept( *visitor ); 146 137 if ( count != -1 && count < minimum ) minimum = count; 147 138 } -
src/ResolvExpr/Unify.cc
r7030dab r057298e 25 25 #include <vector> 26 26 27 #include "AST/Copy.hpp"28 27 #include "AST/Decl.hpp" 29 28 #include "AST/Node.hpp" 30 29 #include "AST/Pass.hpp" 31 #include "AST/Print.hpp"32 30 #include "AST/Type.hpp" 33 31 #include "AST/TypeEnvironment.hpp" … … 137 135 findOpenVars( newSecond, open, closed, need, have, FirstOpen ); 138 136 139 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 140 139 } 141 140 … … 149 148 newFirst->get_qualifiers() = Type::Qualifiers(); 150 149 newSecond->get_qualifiers() = Type::Qualifiers(); 151 150 /// std::cerr << "first is "; 151 /// first->print( std::cerr ); 152 /// std::cerr << std::endl << "second is "; 153 /// second->print( std::cerr ); 154 /// std::cerr << std::endl << "newFirst is "; 155 /// newFirst->print( std::cerr ); 156 /// std::cerr << std::endl << "newSecond is "; 157 /// newSecond->print( std::cerr ); 158 /// std::cerr << std::endl; 152 159 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 153 160 delete newFirst; … … 163 170 ast::AssertionSet need, have; 164 171 165 ast::Type * newFirst = shallowCopy( first ); 166 ast::Type * newSecond = shallowCopy( second ); 167 newFirst ->qualifiers = {}; 168 newSecond->qualifiers = {}; 169 ast::ptr< ast::Type > t1_(newFirst ); 170 ast::ptr< ast::Type > t2_(newSecond); 172 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 173 env.apply( newFirst ); 174 env.apply( newSecond ); 175 reset_qualifiers( newFirst ); 176 reset_qualifiers( newSecond ); 171 177 172 178 return unifyExact( 173 env.apply( newFirst ).node, 174 env.apply( newSecond ).node, 175 newEnv, need, have, open, noWiden(), symtab ); 179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 176 180 } 177 181 … … 322 326 323 327 void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) { 328 /// std::cerr << "assertion set is" << std::endl; 329 /// printAssertionSet( assertions, std::cerr, 8 ); 330 /// std::cerr << "looking for "; 331 /// assert->print( std::cerr ); 332 /// std::cerr << std::endl; 324 333 AssertionSet::iterator i = assertions.find( assert ); 325 334 if ( i != assertions.end() ) { 335 /// std::cerr << "found it!" << std::endl; 326 336 i->second.isUsed = true; 327 337 } // if … … 933 943 934 944 private: 935 // Returns: other, cast as XInstType 936 // Assigns this->result: whether types are compatible (up to generic parameters) 937 template< typename XInstType > 938 const XInstType * handleRefType( const XInstType * inst, const ast::Type * other ) { 945 template< typename RefType > 946 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) { 939 947 // check that the other type is compatible and named the same 940 auto otherInst = dynamic_cast< const XInstType * >( other );941 this->result = otherInst && inst->name == otherInst->name;948 auto otherInst = dynamic_cast< const RefType * >( other ); 949 result = otherInst && inst->name == otherInst->name; 942 950 return otherInst; 943 951 } … … 960 968 } 961 969 962 template< typename XInstType >963 void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {970 template< typename RefType > 971 void handleGenericRefType( const RefType * inst, const ast::Type * other ) { 964 972 // check that other type is compatible and named the same 965 const XInstType * otherInst= handleRefType( inst, other );966 if ( ! this->result) return;973 const RefType * inst2 = handleRefType( inst, other ); 974 if ( ! inst2 ) return; 967 975 968 976 // check that parameters of types unify, if any 969 977 const std::vector< ast::ptr< ast::Expr > > & params = inst->params; 970 const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;978 const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params; 971 979 972 980 auto it = params.begin(); … … 1194 1202 // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and 1195 1203 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1196 ast::Type * t1 = shallowCopy(type1.get()); 1197 ast::Type * t2 = shallowCopy(type2.get()); 1198 t1->qualifiers = {}; 1199 t2->qualifiers = {}; 1200 ast::ptr< ast::Type > t1_(t1); 1201 ast::ptr< ast::Type > t2_(t2); 1204 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1205 reset_qualifiers( t1 ); 1206 reset_qualifiers( t2 ); 1202 1207 1203 1208 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { 1209 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1210 1204 1211 // if exact unification on unqualified types, try to merge qualifiers 1205 1212 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { 1206 t1->qualifiers = q1 | q2;1207 common = t1;1213 common = type1; 1214 reset_qualifiers( common, q1 | q2 ); 1208 1215 return true; 1209 1216 } else { … … 1212 1219 1213 1220 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) { 1221 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1222 1214 1223 // no exact unification, but common type 1215 auto c = shallowCopy(common.get()); 1216 c->qualifiers = q1 | q2; 1217 common = c; 1224 reset_qualifiers( common, q1 | q2 ); 1218 1225 return true; 1219 1226 } else { -
src/ResolvExpr/typeops.h
r7030dab r057298e 10 10 // Created On : Sun May 17 07:28:22 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T ue Oct 1 09:45:00 201913 // Update Count : 612 // Last Modified On : Thu Aug 8 16:36:00 2019 13 // Update Count : 5 14 14 // 15 15 … … 83 83 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 84 84 Cost castCost( 85 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,86 const ast:: SymbolTable & symtab, const ast::TypeEnvironment & env );85 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 86 const ast::TypeEnvironment & env ); 87 87 88 88 // in ConversionCost.cc … … 90 90 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 91 91 Cost conversionCost( 92 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,93 const ast:: SymbolTable & symtab, const ast::TypeEnvironment & env );92 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 93 const ast::TypeEnvironment & env ); 94 94 95 95 // in AlternativeFinder.cc -
src/SymTab/Autogen.h
r7030dab r057298e 21 21 22 22 #include "AST/Decl.hpp" 23 #include "AST/Eval.hpp"24 23 #include "AST/Expr.hpp" 25 24 #include "AST/Init.hpp" … … 266 265 } 267 266 268 ast::ptr< ast::Expr > begin, end; 269 std::string cmp, update; 267 ast::ptr< ast::Expr > begin, end, cmp, update; 270 268 271 269 if ( forward ) { … … 273 271 begin = ast::ConstantExpr::from_int( loc, 0 ); 274 272 end = array->dimension; 275 cmp = "?<?";276 update = "++?";273 cmp = new ast::NameExpr{ loc, "?<?" }; 274 update = new ast::NameExpr{ loc, "++?" }; 277 275 } else { 278 276 // generate: for ( int i = N-1; i >= 0; --i ) 279 begin = ast::call( 280 loc, "?-?", array->dimension, ast::ConstantExpr::from_int( loc, 1 ) ); 277 begin = new ast::UntypedExpr{ 278 loc, new ast::NameExpr{ loc, "?-?" }, 279 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } }; 281 280 end = ast::ConstantExpr::from_int( loc, 0 ); 282 cmp = "?>=?";283 update = "--?";281 cmp = new ast::NameExpr{ loc, "?>=?" }; 282 update = new ast::NameExpr{ loc, "--?" }; 284 283 } 285 284 … … 287 286 loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt }, 288 287 new ast::SingleInit{ loc, begin } }; 289 ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index }; 290 291 ast::ptr< ast::Expr > cond = ast::call( loc, cmp, indexVar, end ); 292 293 ast::ptr< ast::Expr > inc = ast::call( loc, update, indexVar ); 294 295 ast::ptr< ast::Expr > dstIndex = ast::call( loc, "?[?]", dstParam, indexVar ); 288 289 ast::ptr< ast::Expr > cond = new ast::UntypedExpr{ 290 loc, cmp, { new ast::VariableExpr{ loc, index }, end } }; 291 292 ast::ptr< ast::Expr > inc = new ast::UntypedExpr{ 293 loc, update, { new ast::VariableExpr{ loc, index } } }; 294 295 ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{ 296 loc, new ast::NameExpr{ loc, "?[?]" }, 297 { dstParam, new ast::VariableExpr{ loc, index } } }; 296 298 297 299 // srcParam must keep track of the array indices to build the source parameter and/or 298 300 // array list initializer 299 srcParam.addArrayIndex( indexVar, array->dimension );301 srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension ); 300 302 301 303 // for stmt's body, eventually containing call … … 383 385 if ( isUnnamedBitfield( obj ) ) return {}; 384 386 385 ast::ptr< ast::Type > addCast ;387 ast::ptr< ast::Type > addCast = nullptr; 386 388 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) { 387 389 assert( dstParam->result ); -
src/SynTree/Statement.h
r7030dab r057298e 518 518 class ImplicitCtorDtorStmt : public Statement { 519 519 public: 520 // the constructor/destructor call statement; owned here for a while, eventually transferred elsewhere520 // Non-owned pointer to the constructor/destructor statement 521 521 Statement * callStmt; 522 522 -
src/Tuples/Explode.cc
r7030dab r057298e 129 129 for ( const ast::Expr * expr : tupleExpr->exprs ) { 130 130 exprs.emplace_back( applyCast( expr, false ) ); 131 //exprs.emplace_back( ast::ptr< ast::Expr >( applyCast( expr, false ) ) ); 131 132 } 132 133 if ( first ) { -
src/Tuples/Explode.h
r7030dab r057298e 210 210 } 211 211 // Cast a reference away to a value-type to allow further explosion. 212 if ( local->result.as< ast::ReferenceType >() ) {212 if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) { 213 213 local = new ast::CastExpr{ local, tupleType }; 214 214 } … … 220 220 // delete idx; 221 221 } 222 // delete local; 222 223 } 223 224 } else { -
src/Tuples/TupleAssignment.cc
r7030dab r057298e 465 465 // resolve ctor/dtor for the new object 466 466 ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 467 InitTweak::genCtorInit( location, ret ), spotter.crntFinder. localSyms);467 InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab ); 468 468 // remove environments from subexpressions of stmtExpr 469 469 ast::Pass< EnvRemover > rm{ env }; … … 560 560 // resolve the cast expression so that rhsCand return type is bound by the cast 561 561 // type as needed, and transfer the resulting environment 562 ResolvExpr::CandidateFinder finder{ spotter.crntFinder. localSyms, env };562 ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env }; 563 563 finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() ); 564 564 assert( finder.candidates.size() == 1 ); … … 609 609 // explode the LHS so that each field of a tuple-valued expr is assigned 610 610 ResolvExpr::CandidateList lhs; 611 explode( *lhsCand, crntFinder. localSyms, back_inserter(lhs), true );611 explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true ); 612 612 for ( ResolvExpr::CandidateRef & cand : lhs ) { 613 613 // each LHS value must be a reference - some come in with a cast, if not … … 629 629 if ( isTuple( rhsCand->expr ) ) { 630 630 // multiple assignment 631 explode( *rhsCand, crntFinder. localSyms, back_inserter(rhs), true );631 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 632 632 matcher.reset( 633 633 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); … … 648 648 // multiple assignment 649 649 ResolvExpr::CandidateList rhs; 650 explode( rhsCand, crntFinder. localSyms, back_inserter(rhs), true );650 explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 651 651 matcher.reset( 652 652 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); … … 678 678 ) 679 679 680 ResolvExpr::CandidateFinder finder{ crntFinder. localSyms, matcher->env };680 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env }; 681 681 682 682 try { -
src/Tuples/TupleExpansion.cc
r7030dab r057298e 323 323 std::vector<ast::ptr<ast::Type>> types; 324 324 ast::CV::Qualifiers quals{ 325 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | 325 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Lvalue | 326 326 ast::CV::Atomic | ast::CV::Mutex }; 327 327 -
src/main.cc
r7030dab r057298e 31 31 using namespace std; 32 32 33 #include "AST/Convert.hpp" 33 34 34 #include "CompilationState.h" 35 35 #include "../config.h" // for CFA_LIBDIR … … 339 339 } // if 340 340 341 // PASS( "Resolve", ResolvExpr::resolve( translationUnit ) ); 342 { 343 auto transUnit = convert( move( translationUnit ) ); 344 PASS( "Resolve", ResolvExpr::resolve( transUnit ) ); 345 translationUnit = convert( move( transUnit ) ); 346 } 347 341 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) ); 348 342 if ( exprp ) { 349 343 dump( translationUnit );
Note:
See TracChangeset
for help on using the changeset viewer.