Changes in / [fb0ae06:dab09ad]
- Files:
-
- 6 deleted
- 68 edited
-
configure.ac (modified) (1 diff)
-
libcfa/src/Makefile.am (modified) (1 diff)
-
libcfa/src/concurrency/ready_queue.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/ready_subqueue.hfa (modified) (4 diffs)
-
src/AST/Attribute.hpp (modified) (1 diff)
-
src/AST/CVQualifiers.hpp (modified) (2 diffs)
-
src/AST/Convert.cpp (modified) (7 diffs)
-
src/AST/Copy.hpp (deleted)
-
src/AST/Decl.cpp (modified) (1 diff)
-
src/AST/Decl.hpp (modified) (6 diffs)
-
src/AST/Eval.hpp (deleted)
-
src/AST/Expr.cpp (modified) (14 diffs)
-
src/AST/Expr.hpp (modified) (18 diffs)
-
src/AST/ForallSubstitutionTable.cpp (deleted)
-
src/AST/ForallSubstitutionTable.hpp (deleted)
-
src/AST/ForallSubstitutor.hpp (deleted)
-
src/AST/Fwd.hpp (modified) (2 diffs)
-
src/AST/GenericSubstitution.cpp (modified) (1 diff)
-
src/AST/Init.hpp (modified) (1 diff)
-
src/AST/Node.cpp (modified) (3 diffs)
-
src/AST/Node.hpp (modified) (10 diffs)
-
src/AST/Pass.hpp (modified) (12 diffs)
-
src/AST/Pass.impl.hpp (modified) (116 diffs)
-
src/AST/Pass.proto.hpp (modified) (13 diffs)
-
src/AST/Print.cpp (modified) (4 diffs)
-
src/AST/Stmt.hpp (modified) (2 diffs)
-
src/AST/Type.cpp (modified) (6 diffs)
-
src/AST/Type.hpp (modified) (13 diffs)
-
src/AST/TypeEnvironment.cpp (modified) (11 diffs)
-
src/AST/TypeEnvironment.hpp (modified) (6 diffs)
-
src/AST/TypeSubstitution.cpp (modified) (7 diffs)
-
src/AST/TypeSubstitution.hpp (modified) (6 diffs)
-
src/AST/module.mk (modified) (1 diff)
-
src/AST/porting.md (modified) (1 diff)
-
src/Common/Eval.cc (modified) (1 diff)
-
src/Common/ScopedMap.h (modified) (1 diff)
-
src/Common/Stats/Heap.cc (modified) (6 diffs)
-
src/Common/Stats/Heap.h (modified) (1 diff)
-
src/CompilationState.cc (modified) (2 diffs)
-
src/CompilationState.h (modified) (1 diff)
-
src/InitTweak/InitTweak.cc (modified) (2 diffs)
-
src/ResolvExpr/AdjustExprType.cc (modified) (1 diff)
-
src/ResolvExpr/Candidate.hpp (modified) (2 diffs)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (92 diffs)
-
src/ResolvExpr/CandidateFinder.hpp (modified) (4 diffs)
-
src/ResolvExpr/CastCost.cc (modified) (7 diffs)
-
src/ResolvExpr/CommonType.cc (modified) (4 diffs)
-
src/ResolvExpr/ConversionCost.cc (modified) (14 diffs)
-
src/ResolvExpr/ConversionCost.h (modified) (3 diffs)
-
src/ResolvExpr/CurrentObject.cc (modified) (15 diffs)
-
src/ResolvExpr/PolyCost.cc (modified) (2 diffs)
-
src/ResolvExpr/PtrsAssignable.cc (modified) (1 diff)
-
src/ResolvExpr/PtrsCastable.cc (modified) (1 diff)
-
src/ResolvExpr/RenameVars.cc (modified) (11 diffs)
-
src/ResolvExpr/ResolveTypeof.cc (modified) (5 diffs)
-
src/ResolvExpr/Resolver.cc (modified) (7 diffs)
-
src/ResolvExpr/SatisfyAssertions.cpp (modified) (9 diffs)
-
src/ResolvExpr/SatisfyAssertions.hpp (modified) (1 diff)
-
src/ResolvExpr/SpecCost.cc (modified) (4 diffs)
-
src/ResolvExpr/Unify.cc (modified) (12 diffs)
-
src/ResolvExpr/typeops.h (modified) (3 diffs)
-
src/SymTab/Autogen.h (modified) (5 diffs)
-
src/SymTab/FixFunction.cc (modified) (4 diffs)
-
src/SymTab/Mangler.cc (modified) (2 diffs)
-
src/SynTree/ApplicationExpr.cc (modified) (1 diff)
-
src/SynTree/Statement.h (modified) (1 diff)
-
src/Tuples/Explode.cc (modified) (4 diffs)
-
src/Tuples/Explode.h (modified) (2 diffs)
-
src/Tuples/TupleAssignment.cc (modified) (8 diffs)
-
src/Tuples/TupleExpansion.cc (modified) (1 diff)
-
src/Tuples/Tuples.cc (modified) (2 diffs)
-
src/config.h.in (modified) (1 diff)
-
src/main.cc (modified) (5 diffs)
-
tests/resolutionErrors.cfa (deleted)
Legend:
- Unmodified
- Added
- Removed
-
configure.ac
rfb0ae06 rdab09ad 24 24 #Trasforming cc1 will break compilation 25 25 M4CFA_PROGRAM_NAME 26 27 #==============================================================================28 # New AST toggling support29 AH_TEMPLATE([CFA_USE_NEW_AST],[Sets whether or not to use the new-ast, this is adefault value and can be overrided by --old-ast and --new-ast])30 AC_ARG_ENABLE(new-ast,31 [ --enable-new-ast whether or not to use new ast as the default AST algorithm],32 [case "${enableval}" in33 yes) newast=true ;;34 no) newast=false ;;35 *) AC_MSG_ERROR([bad value ${enableval} for --enable-new-ast]) ;;36 esac],[newast=false])37 AC_DEFINE_UNQUOTED([CFA_USE_NEW_AST], $newast)38 26 39 27 #============================================================================== -
libcfa/src/Makefile.am
rfb0ae06 rdab09ad 44 44 45 45 headers = common.hfa fstream.hfa heap.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa \ 46 time.hfa stdlib.hfa parseargs.hfa \46 time.hfa stdlib.hfa memory.hfa parseargs.hfa \ 47 47 containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa 48 48 -
libcfa/src/concurrency/ready_queue.cfa
rfb0ae06 rdab09ad 419 419 // Actually pop the list 420 420 struct $thread * thrd; 421 thrd = pop(lane); 421 bool emptied; 422 [thrd, emptied] = pop(lane); 422 423 423 424 /* paranoid */ verify(thrd); … … 456 457 if(head(lane)->link.next == thrd) { 457 458 $thread * pthrd; 458 pthrd = pop(lane); 459 bool emptied; 460 [pthrd, emptied] = pop(lane); 459 461 460 462 /* paranoid */ verify( pthrd == thrd ); … … 606 608 while(!is_empty(lanes.data[idx])) { 607 609 struct $thread * thrd; 608 thrd = pop(lanes.data[idx]); 610 __attribute__((unused)) bool _; 611 [thrd, _] = pop(lanes.data[idx]); 609 612 610 613 push(cltr, thrd); -
libcfa/src/concurrency/ready_subqueue.hfa
rfb0ae06 rdab09ad 144 144 // returns popped 145 145 // returns true of lane was empty before push, false otherwise 146 $thread *pop(__intrusive_lane_t & this) {146 [$thread *, bool] pop(__intrusive_lane_t & this) { 147 147 /* paranoid */ verify(this.lock); 148 148 /* paranoid */ verify(this.before.link.ts != 0ul); … … 162 162 head->link.next = next; 163 163 next->link.prev = head; 164 node->link.next = 0p; 165 node->link.prev = 0p; 164 node->link.[next, prev] = 0p; 166 165 167 166 // Update head time stamp … … 181 180 /* paranoid */ verify(tail(this)->link.prev == head(this)); 182 181 /* paranoid */ verify(head(this)->link.next == tail(this)); 183 return node;182 return [node, true]; 184 183 } 185 184 else { … … 188 187 /* paranoid */ verify(head(this)->link.next != tail(this)); 189 188 /* paranoid */ verify(this.before.link.ts != 0); 190 return node;189 return [node, false]; 191 190 } 192 191 } -
src/AST/Attribute.hpp
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 20 20 21 21 #include "AST/Attribute.hpp" 22 #include "AST/Copy.hpp"23 22 #include "AST/Decl.hpp" 24 23 #include "AST/Expr.hpp" … … 588 587 assert( tgtResnSlots.empty() ); 589 588 590 if ( srcInferred. data.inferParams ) {589 if ( srcInferred.mode == ast::Expr::InferUnion::Params ) { 591 590 const ast::InferredParams &srcParams = srcInferred.inferParams(); 592 591 for (auto & srcParam : srcParams) { … … 594 593 srcParam.second.decl, 595 594 get<Declaration>().accept1(srcParam.second.declptr), 596 get<Type>().accept1(srcParam.second.actualType) ->clone(),597 get<Type>().accept1(srcParam.second.formalType) ->clone(),598 get<Expression>().accept1(srcParam.second.expr) ->clone()595 get<Type>().accept1(srcParam.second.actualType), 596 get<Type>().accept1(srcParam.second.formalType), 597 get<Expression>().accept1(srcParam.second.expr) 599 598 )); 600 599 assert(res.second); 601 600 } 602 } 603 if ( srcInferred.data.resnSlots ) { 601 } else if ( srcInferred.mode == ast::Expr::InferUnion::Slots ) { 604 602 const ast::ResnSlots &srcSlots = srcInferred.resnSlots(); 605 603 for (auto srcSlot : srcSlots) { … … 622 620 623 621 tgt->result = get<Type>().accept1(src->result); 624 // Unconditionally use a clone of the result type.625 // We know this will leak some objects: much of the immediate conversion result.626 // In some cases, using the conversion result directly gives unintended object sharing.627 // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.628 // But tgt->result must be fully owned privately by tgt.629 // Applying these conservative copies here means630 // - weak references point at the declaration's copy, not these expr.result copies (good)631 // - we copy more objects than really needed (bad, tolerated)632 if (tgt->result) {633 tgt->result = tgt->result->clone();634 }635 622 return visitBaseExpr_skipResultType(src, tgt); 636 623 } … … 992 979 993 980 const ast::Expr * visit( const ast::StmtExpr * node ) override final { 994 auto stmts = node->stmts;995 // disable sharing between multiple StmtExprs explicitly.996 if (inCache(stmts)) {997 stmts = ast::deepCopy(stmts.get());998 }999 981 auto rslt = new StmtExpr( 1000 get<CompoundStmt>().accept1( stmts)982 get<CompoundStmt>().accept1(node->stmts) 1001 983 ); 1002 984 … … 2004 1986 2005 1987 assert( oldInferParams.empty() || oldResnSlots.empty() ); 2006 //assert( newInferred.mode == ast::Expr::InferUnion::Empty );1988 assert( newInferred.mode == ast::Expr::InferUnion::Empty ); 2007 1989 2008 1990 if ( !oldInferParams.empty() ) { … … 2135 2117 old->location, 2136 2118 GET_ACCEPT_1(member, DeclWithType), 2137 GET_ACCEPT_1(aggregate, Expr), 2138 ast::MemberExpr::NoOpConstructionChosen 2119 GET_ACCEPT_1(aggregate, Expr) 2139 2120 ) 2140 2121 ); -
src/AST/Decl.cpp
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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, TypeDecl::Kind k, bool s, const Type * i = nullptr ) 194 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeDecl::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
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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; … … 45 42 struct ParamEntry { 46 43 UniqueId decl; 47 readonly<Decl> declptr;44 ptr<Decl> declptr; 48 45 ptr<Type> actualType; 49 46 ptr<Type> formalType; … … 65 62 class Expr : public ParseNode { 66 63 public: 67 /* 68 * NOTE: the union approach is incorrect until the case of 69 * partial resolution in InferMatcher is eliminated. 70 * it is reverted to allow unresolved and resolved parameters 71 * to coexist in an expression node. 72 */ 64 /// Saves space (~16 bytes) by combining ResnSlots and InferredParams 73 65 struct InferUnion { 74 // mode is now unused75 66 enum { Empty, Slots, Params } mode; 76 struct data_t { 77 // char def; 78 ResnSlots * resnSlots; 79 InferredParams * inferParams; 80 81 data_t(): resnSlots(nullptr), inferParams(nullptr) {} 82 data_t(const data_t &other) = delete; 83 ~data_t() { 84 delete resnSlots; 85 delete inferParams; 86 } 67 union data_t { 68 char def; 69 ResnSlots resnSlots; 70 InferredParams inferParams; 71 72 data_t() : def('\0') {} 73 ~data_t() {} 87 74 } data; 88 75 89 76 /// initializes from other InferUnion 90 77 void init_from( const InferUnion& o ) { 91 if (o.data.resnSlots) { 92 data.resnSlots = new ResnSlots(*o.data.resnSlots); 93 } 94 if (o.data.inferParams) { 95 data.inferParams = new InferredParams(*o.data.inferParams); 78 switch ( o.mode ) { 79 case Empty: return; 80 case Slots: new(&data.resnSlots) ResnSlots{ o.data.resnSlots }; return; 81 case Params: new(&data.inferParams) InferredParams{ o.data.inferParams }; return; 96 82 } 97 83 } … … 99 85 /// initializes from other InferUnion (move semantics) 100 86 void init_from( InferUnion&& o ) { 101 data.resnSlots = o.data.resnSlots; 102 data.inferParams = o.data.inferParams; 103 o.data.resnSlots = nullptr; 104 o.data.inferParams = nullptr; 87 switch ( o.mode ) { 88 case Empty: return; 89 case Slots: new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return; 90 case Params: 91 new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return; 92 } 93 } 94 95 /// clears variant fields 96 void reset() { 97 switch( mode ) { 98 case Empty: return; 99 case Slots: data.resnSlots.~ResnSlots(); return; 100 case Params: data.inferParams.~InferredParams(); return; 101 } 105 102 } 106 103 … … 110 107 InferUnion& operator= ( const InferUnion& ) = delete; 111 108 InferUnion& operator= ( InferUnion&& ) = delete; 112 113 bool hasSlots() const { return data.resnSlots; } 109 ~InferUnion() { reset(); } 114 110 115 111 ResnSlots& resnSlots() { 116 if (!data.resnSlots) { 117 data.resnSlots = new ResnSlots(); 112 switch (mode) { 113 case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; // fallthrough 114 case Slots: return data.resnSlots; 115 case Params: assertf(false, "Cannot return to resnSlots from Params"); abort(); 118 116 } 119 return *data.resnSlots;117 assertf(false, "unreachable"); 120 118 } 121 119 122 120 const ResnSlots& resnSlots() const { 123 if ( data.resnSlots) {124 return *data.resnSlots;121 if (mode == Slots) { 122 return data.resnSlots; 125 123 } 126 124 assertf(false, "Mode was not already resnSlots"); … … 129 127 130 128 InferredParams& inferParams() { 131 if (!data.inferParams) { 132 data.inferParams = new InferredParams(); 129 switch (mode) { 130 case Slots: data.resnSlots.~ResnSlots(); // fallthrough 131 case Empty: new(&data.inferParams) InferredParams{}; mode = Params; // fallthrough 132 case Params: return data.inferParams; 133 133 } 134 return *data.inferParams;134 assertf(false, "unreachable"); 135 135 } 136 136 137 137 const InferredParams& inferParams() const { 138 if ( data.inferParams) {139 return *data.inferParams;138 if (mode == Params) { 139 return data.inferParams; 140 140 } 141 141 assertf(false, "Mode was not already Params"); … … 143 143 } 144 144 145 void set_inferParams( InferredParams * ps ) { 146 delete data.resnSlots; 147 data.resnSlots = nullptr; 148 delete data.inferParams; 149 data.inferParams = ps; 145 void set_inferParams( InferredParams && ps ) { 146 switch(mode) { 147 case Slots: 148 data.resnSlots.~ResnSlots(); 149 // fallthrough 150 case Empty: 151 new(&data.inferParams) InferredParams{ std::move( ps ) }; 152 mode = Params; 153 break; 154 case Params: 155 data.inferParams = std::move( ps ); 156 break; 157 } 150 158 } 151 159 … … 153 161 /// and the other is in `Params`. 154 162 void splice( InferUnion && o ) { 155 if (o.data.resnSlots) { 156 if (data.resnSlots) { 157 data.resnSlots->insert( 158 data.resnSlots->end(), o.data.resnSlots->begin(), o.data.resnSlots->end() ); 159 delete o.data.resnSlots; 163 if ( o.mode == Empty ) return; 164 if ( mode == Empty ) { init_from( o ); return; } 165 assert( mode == o.mode && "attempt to splice incompatible InferUnion" ); 166 167 if ( mode == Slots ){ 168 data.resnSlots.insert( 169 data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() ); 170 } else if ( mode == Params ) { 171 for ( const auto & p : o.data.inferParams ) { 172 data.inferParams[p.first] = std::move(p.second); 160 173 } 161 else { 162 data.resnSlots = o.data.resnSlots; 163 } 164 o.data.resnSlots = nullptr; 165 } 166 167 if (o.data.inferParams) { 168 if (data.inferParams) { 169 for ( const auto & p : *o.data.inferParams ) { 170 (*data.inferParams)[p.first] = std::move(p.second); 171 } 172 delete o.data.inferParams; 173 } 174 else { 175 data.inferParams = o.data.inferParams; 176 } 177 o.data.inferParams = nullptr; 178 } 174 } else assertf(false, "invalid mode"); 179 175 } 180 176 }; … … 189 185 190 186 Expr * set_extension( bool ex ) { extension = ex; return this; } 191 virtual bool get_lvalue() const;192 187 193 188 virtual const Expr * accept( Visitor & v ) const override = 0; … … 206 201 ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ); 207 202 208 bool get_lvalue() const final;209 210 203 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 211 204 private: … … 222 215 UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ) 223 216 : Expr( loc ), func( f ), args( std::move(as) ) {} 224 225 bool get_lvalue() const final;226 217 227 218 /// Creates a new dereference expression … … 300 291 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {} 301 292 302 bool get_lvalue() const final;303 304 293 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 305 294 private: … … 349 338 : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); } 350 339 351 bool get_lvalue() const final;352 353 340 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 354 341 private: … … 365 352 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg ); 366 353 367 bool get_lvalue() const final;368 369 354 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 370 355 private: 371 356 MemberExpr * clone() const override { return new MemberExpr{ *this }; } 372 357 MUTATE_FRIEND 373 374 // Custructor overload meant only for AST conversion375 enum NoOpConstruction { NoOpConstructionChosen };376 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,377 NoOpConstruction overloadSelector );378 friend class ::ConverterOldToNew;379 friend class ::ConverterNewToOld;380 358 }; 381 359 … … 387 365 VariableExpr( const CodeLocation & loc ); 388 366 VariableExpr( const CodeLocation & loc, const DeclWithType * v ); 389 390 bool get_lvalue() const final;391 367 392 368 /// generates a function pointer for a given function … … 556 532 557 533 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 558 : Expr( loc ), arg1( a1 ), arg2( a2 ) { 559 this->result = a2->result; 560 } 561 562 bool get_lvalue() const final; 534 : Expr( loc ), arg1( a1 ), arg2( a2 ) {} 563 535 564 536 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 633 605 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i ); 634 606 635 bool get_lvalue() const final;636 637 607 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 638 608 private: … … 690 660 691 661 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i ); 692 693 bool get_lvalue() const final;694 662 695 663 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } -
src/AST/Fwd.hpp
rfb0ae06 rdab09ad 10 10 // Created On : Wed May 8 16:05:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Jul 23 14:15:00 202013 // Update Count : 212 // Last Modified On : Mon Jun 24 09:48:00 2019 13 // Update Count : 1 14 14 // 15 15 … … 108 108 class FunctionType; 109 109 class ReferenceToType; 110 template<typename decl_t> class SueInstType; 111 using StructInstType = SueInstType<StructDecl>; 112 using UnionInstType = SueInstType<UnionDecl>; 113 using EnumInstType = SueInstType<EnumDecl>; 110 class StructInstType; 111 class UnionInstType; 112 class EnumInstType; 114 113 class TraitInstType; 115 114 class TypeInstType; -
src/AST/GenericSubstitution.cpp
rfb0ae06 rdab09ad 62 62 Pass<GenericSubstitutionBuilder> builder; 63 63 maybe_accept( ty, builder ); 64 return std::move(builder. core.sub);64 return std::move(builder.pass.sub); 65 65 } 66 66 -
src/AST/Init.hpp
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 9 9 // Author : Thierry Delisle 10 10 // Created On : Thu May 16 14:16:00 2019 11 // Last Modified By : Andrew Beach12 // Last Modified On : Fri Jun 5 10:21:00 202013 // Update Count : 111 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 14 // 15 15 … … 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 [[noreturn]] static inline void strict_fail(const ast::Node * node) { 46 assertf(node, "strict_as had nullptr input."); 47 const ast::ParseNode * parse = dynamic_cast<const ast::ParseNode *>( node ); 48 if ( nullptr == parse ) { 49 assertf(nullptr, "%s (no location)", toString(node).c_str()); 50 } else if ( parse->location.isUnset() ) { 51 assertf(nullptr, "%s (unset location)", toString(node).c_str()); 52 } else { 53 assertf(nullptr, "%s (at %s:%d)", toString(node).c_str(), 54 parse->location.filename.c_str(), parse->location.first_line); 55 } 56 } 57 58 template< typename node_t, enum ast::Node::ref_type ref_t > 59 void ast::ptr_base<node_t, ref_t>::_strict_fail() const { 60 strict_fail(node); 61 } 62 63 template< typename node_t, enum ast::Node::ref_type ref_t > 64 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { 65 node->increment(ref_t); 66 _trap( node ); 67 } 68 69 template< typename node_t, enum ast::Node::ref_type ref_t > 70 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node, bool do_delete ) { 71 _trap( node ); 72 node->decrement( ref_t, do_delete ); 73 } 74 75 template< typename node_t, enum ast::Node::ref_type ref_t > 76 void ast::ptr_base<node_t, ref_t>::_check() const { 77 // if(node) assert(node->was_ever_strong == false || node->strong_count > 0); 78 } 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); } 79 39 80 40 template< typename node_t, enum ast::Node::ref_type ref_t > -
src/AST/Node.hpp
rfb0ae06 rdab09ad 10 10 // Created On : Wed May 8 10:27:04 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jun 5 9:47:00 202013 // Update Count : 612 // Last Modified On : Mon Jun 3 13:26:00 2019 13 // Update Count : 5 14 14 // 15 15 … … 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> 243 223 const o_node_t * as() const { _check(); return dynamic_cast<const o_node_t *>(node); } 244 224 245 /// Wrapper that makes sure dynamic_cast returns non-null.225 /// wrapper for convenient access to strict_dynamic_cast 246 226 template<typename o_node_t> 247 const o_node_t * strict_as() const { 248 if (const o_node_t * ret = as<o_node_t>()) return ret; 249 _strict_fail(); 250 } 251 252 /// Wrapper that makes sure dynamic_cast does not fail. 253 template<typename o_node_t, decltype(nullptr) null> 254 const o_node_t * strict_as() const { return node ? strict_as<o_node_t>() : nullptr; } 227 const o_node_t * strict_as() const { _check(); return strict_dynamic_cast<const o_node_t *>(node); } 255 228 256 229 /// Returns a mutable version of the pointer in this node. … … 271 244 272 245 void _inc( const node_t * other ); 273 void _dec( const node_t * other , bool do_delete = true);246 void _dec( const node_t * other ); 274 247 void _check() const; 275 void _strict_fail() const __attribute__((noreturn));276 248 277 249 const node_t * node; -
src/AST/Pass.hpp
rfb0ae06 rdab09ad 8 8 // 9 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15: 37:05 201910 // Created On : Thu May 09 15::37::05 2019 11 11 // Last Modified By : 12 12 // Last Modified On : … … 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 template< typename core_t >65 template< typename pass_t > 69 66 class Pass final : public ast::Visitor { 70 67 public: 71 using core_type = core_t;72 using type = Pass<core_t>;73 74 68 /// Forward any arguments to the pass constructor 75 69 /// Propagate 'this' if necessary 76 70 template< typename... Args > 77 71 Pass( Args &&... args) 78 : core( std::forward<Args>( args )... )72 : pass( std::forward<Args>( args )... ) 79 73 { 80 74 // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor 81 type * const * visitor = __pass::visitor(core, 0); 75 typedef Pass<pass_t> this_t; 76 this_t * const * visitor = __pass::visitor(pass, 0); 82 77 if(visitor) { 83 *const_cast<t ype**>( visitor ) = this;78 *const_cast<this_t **>( visitor ) = this; 84 79 } 85 80 } … … 87 82 virtual ~Pass() = default; 88 83 89 /// Construct and run a pass on a translation unit.90 template< typename... Args >91 static void run( std::list< ptr<Decl> > & decls, Args &&... args ) {92 Pass<core_t> visitor( std::forward<Args>( args )... );93 accept_all( decls, visitor );94 }95 96 84 /// Storage for the actual pass 97 core_t core;85 pass_t pass; 98 86 99 87 /// Visit function declarations … … 191 179 const ast::TypeSubstitution * visit( const ast::TypeSubstitution * ) override final; 192 180 193 template<typename core_type>194 friend void accept_all( std::list< ptr<Decl> > & decls, Pass< core_type>& visitor );181 template<typename pass_type> 182 friend void accept_all( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor ); 195 183 private: 196 184 197 bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children( core, 0); return ptr ? *ptr : true; }185 bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(pass, 0); return ptr ? *ptr : true; } 198 186 199 187 private: … … 214 202 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 215 203 216 /// Mutate forall-list, accounting for presence of type substitution map217 template<typename node_t>218 void mutate_forall( const node_t *& );219 220 204 public: 221 205 /// Logic to call the accept and mutate the parent if needed, delegates call to accept … … 226 210 /// Internal RAII guard for symbol table features 227 211 struct guard_symtab { 228 guard_symtab( Pass< core_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.core, 0); }229 ~guard_symtab() { __pass::symtab::leave(pass .core, 0); }230 Pass< core_t> & pass;212 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); } 213 ~guard_symtab() { __pass::symtab::leave(pass, 0); } 214 Pass<pass_t> & pass; 231 215 }; 232 216 233 217 /// Internal RAII guard for scope features 234 218 struct guard_scope { 235 guard_scope( Pass<core_t> & pass ): pass( pass ) { __pass::scope::enter(pass.core, 0); } 236 ~guard_scope() { __pass::scope::leave(pass.core, 0); } 237 Pass<core_t> & pass; 238 }; 239 240 /// Internal RAII guard for forall substitutions 241 struct guard_forall_subs { 242 guard_forall_subs( Pass<core_t> & pass, const ParameterizedType * type ) 243 : pass( pass ), type( type ) { __pass::forall::enter(pass.core, 0, type ); } 244 ~guard_forall_subs() { __pass::forall::leave(pass.core, 0, type ); } 245 Pass<core_t> & pass; 246 const ParameterizedType * type; 219 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); } 220 ~guard_scope() { __pass::scope::leave(pass, 0); } 221 Pass<pass_t> & pass; 247 222 }; 248 223 … … 252 227 253 228 /// Apply a pass to an entire translation unit 254 template<typename core_t>255 void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass< core_t> & visitor );229 template<typename pass_t> 230 void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<pass_t> & visitor ); 256 231 257 232 //------------------------------------------------------------------------------------------------- … … 293 268 }; 294 269 295 template< typename core_t>296 friend auto __pass::at_cleanup( core_t & core, int ) -> decltype( &core.at_cleanup );270 template< typename pass_t> 271 friend auto __pass::at_cleanup( pass_t & pass, int ) -> decltype( &pass.at_cleanup ); 297 272 public: 298 273 … … 330 305 331 306 /// Used to get a pointer to the pass with its wrapped type 332 template<typename core_t>307 template<typename pass_t> 333 308 struct WithVisitorRef { 334 Pass< core_t> * const visitor = nullptr;309 Pass<pass_t> * const visitor = nullptr; 335 310 }; 336 311 … … 339 314 SymbolTable symtab; 340 315 }; 341 342 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl343 struct WithForallSubstitutor {344 ForallSubstitutionTable subs;345 };346 347 316 } 348 317 … … 352 321 extern struct PassVisitorStats { 353 322 size_t depth = 0; 354 Stats::Counters::MaxCounter<double> * max ;355 Stats::Counters::AverageCounter<double> * avg ;323 Stats::Counters::MaxCounter<double> * max = nullptr; 324 Stats::Counters::AverageCounter<double> * avg = nullptr; 356 325 } pass_visitor_stats; 357 326 } -
src/AST/Pass.impl.hpp
rfb0ae06 rdab09ad 25 25 using namespace ast; \ 26 26 /* back-up the visit children */ \ 27 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children( core, 0) ); \27 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \ 28 28 /* setup the scope for passes that want to run code at exit */ \ 29 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup (core, 0) ); \ 30 /* begin tracing memory allocation if requested by this pass */ \ 31 __pass::beginTrace( core, 0 ); \ 29 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup (pass, 0) ); \ 32 30 /* call the implementation of the previsit of this pass */ \ 33 __pass::previsit( core, node, 0 );31 __pass::previsit( pass, node, 0 ); 34 32 35 33 #define VISIT( code... ) \ … … 42 40 #define VISIT_END( type, node ) \ 43 41 /* call the implementation of the postvisit of this pass */ \ 44 auto __return = __pass::postvisit( core, node, 0 ); \42 auto __return = __pass::postvisit( pass, node, 0 ); \ 45 43 assertf(__return, "post visit should never return null"); \ 46 /* end tracing memory allocation if requested by this pass */ \47 __pass::endTrace( core, 0 ); \48 44 return __return; 49 45 … … 123 119 } 124 120 125 template< typename core_t >121 template< typename pass_t > 126 122 template< typename node_t > 127 auto ast::Pass< core_t >::call_accept( const node_t * node )123 auto ast::Pass< pass_t >::call_accept( const node_t * node ) 128 124 -> typename std::enable_if< 129 125 !std::is_base_of<ast::Expr, node_t>::value && … … 131 127 , decltype( node->accept(*this) ) 132 128 >::type 129 133 130 { 134 131 __pedantic_pass_assert( __visit_children() ); 135 __pedantic_pass_assert( node);132 __pedantic_pass_assert( expr ); 136 133 137 134 static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR"); … … 141 138 } 142 139 143 template< typename core_t >144 const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {140 template< typename pass_t > 141 const ast::Expr * ast::Pass< pass_t >::call_accept( const ast::Expr * expr ) { 145 142 __pedantic_pass_assert( __visit_children() ); 146 143 __pedantic_pass_assert( expr ); 147 144 148 const ast::TypeSubstitution ** env_ptr = __pass::env( core, 0);145 const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0); 149 146 if ( env_ptr && expr->env ) { 150 147 *env_ptr = expr->env; … … 154 151 } 155 152 156 template< typename core_t >157 const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {153 template< typename pass_t > 154 const ast::Stmt * ast::Pass< pass_t >::call_accept( const ast::Stmt * stmt ) { 158 155 __pedantic_pass_assert( __visit_children() ); 159 156 __pedantic_pass_assert( stmt ); … … 163 160 164 161 // get the stmts/decls that will need to be spliced in 165 auto stmts_before = __pass::stmtsToAddBefore( core, 0);166 auto stmts_after = __pass::stmtsToAddAfter ( core, 0);167 auto decls_before = __pass::declsToAddBefore( core, 0);168 auto decls_after = __pass::declsToAddAfter ( core, 0);162 auto stmts_before = __pass::stmtsToAddBefore( pass, 0); 163 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0); 164 auto decls_before = __pass::declsToAddBefore( pass, 0); 165 auto decls_after = __pass::declsToAddAfter ( pass, 0); 169 166 170 167 // These may be modified by subnode but most be restored once we exit this statemnet. 171 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( core, 0) );168 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( pass, 0) ); 172 169 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 173 170 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); … … 205 202 } 206 203 207 template< typename core_t >204 template< typename pass_t > 208 205 template< template <class...> class container_t > 209 container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {206 container_t< ptr<Stmt> > ast::Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 210 207 __pedantic_pass_assert( __visit_children() ); 211 208 if( statements.empty() ) return {}; … … 218 215 219 216 // get the stmts/decls that will need to be spliced in 220 auto stmts_before = __pass::stmtsToAddBefore( core, 0);221 auto stmts_after = __pass::stmtsToAddAfter ( core, 0);222 auto decls_before = __pass::declsToAddBefore( core, 0);223 auto decls_after = __pass::declsToAddAfter ( core, 0);217 auto stmts_before = __pass::stmtsToAddBefore( pass, 0); 218 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0); 219 auto decls_before = __pass::declsToAddBefore( pass, 0); 220 auto decls_after = __pass::declsToAddAfter ( pass, 0); 224 221 225 222 // These may be modified by subnode but most be restored once we exit this statemnet. … … 271 268 } 272 269 273 template< typename core_t >270 template< typename pass_t > 274 271 template< template <class...> class container_t, typename node_t > 275 container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {272 container_t< ast::ptr<node_t> > ast::Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 276 273 __pedantic_pass_assert( __visit_children() ); 277 274 if( container.empty() ) return {}; … … 302 299 } 303 300 304 template< typename core_t >301 template< typename pass_t > 305 302 template<typename node_t, typename parent_t, typename child_t> 306 void ast::Pass< core_t >::maybe_accept(303 void ast::Pass< pass_t >::maybe_accept( 307 304 const node_t * & parent, 308 305 child_t parent_t::*child … … 326 323 } 327 324 328 329 template< typename core_t >330 template< typename node_t >331 void ast::Pass< core_t >::mutate_forall( const node_t *& node ) {332 if ( auto subs = __pass::forall::subs( core, 0 ) ) {333 // tracking TypeDecl substitution, full clone334 if ( node->forall.empty() ) return;335 336 node_t * mut = mutate( node );337 mut->forall = subs->clone( node->forall, *this );338 node = mut;339 } else {340 // not tracking TypeDecl substitution, just mutate341 maybe_accept( node, &node_t::forall );342 }343 }344 325 } 345 326 … … 352 333 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 353 334 354 template< typename core_t >355 inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< core_t > & visitor ) {335 template< typename pass_t > 336 inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) { 356 337 // We are going to aggregate errors for all these statements 357 338 SemanticErrorException errors; … … 361 342 362 343 // get the stmts/decls that will need to be spliced in 363 auto decls_before = __pass::declsToAddBefore( visitor. core, 0);364 auto decls_after = __pass::declsToAddAfter ( visitor. core, 0);344 auto decls_before = __pass::declsToAddBefore( visitor.pass, 0); 345 auto decls_after = __pass::declsToAddAfter ( visitor.pass, 0); 365 346 366 347 // update pass statitistics … … 411 392 //-------------------------------------------------------------------------- 412 393 // ObjectDecl 413 template< typename core_t >414 const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::ObjectDecl * node ) {394 template< typename pass_t > 395 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) { 415 396 VISIT_START( node ); 416 397 … … 425 406 ) 426 407 427 __pass::symtab::addId( core, 0, node );408 __pass::symtab::addId( pass, 0, node ); 428 409 429 410 VISIT_END( DeclWithType, node ); … … 432 413 //-------------------------------------------------------------------------- 433 414 // FunctionDecl 434 template< typename core_t >435 const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::FunctionDecl * node ) {436 VISIT_START( node ); 437 438 __pass::symtab::addId( core, 0, node );415 template< typename pass_t > 416 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::FunctionDecl * node ) { 417 VISIT_START( node ); 418 419 __pass::symtab::addId( pass, 0, node ); 439 420 440 421 VISIT(maybe_accept( node, &FunctionDecl::withExprs );) … … 444 425 // shadow with exprs and not the other way around. 445 426 guard_symtab guard { *this }; 446 __pass::symtab::addWith( core, 0, node->withExprs, node );427 __pass::symtab::addWith( pass, 0, node->withExprs, node ); 447 428 { 448 429 guard_symtab guard { *this }; 449 430 // implicit add __func__ identifier as specified in the C manual 6.4.2.2 450 static ast:: ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{451 CodeLocation{}, "__func__",452 new ast::ArrayType {453 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 ) ), 454 435 nullptr, VariableLen, DynamicDim 455 }456 } };457 __pass::symtab::addId( core, 0,func );436 ) 437 ); 438 __pass::symtab::addId( pass, 0, &func ); 458 439 VISIT( 459 440 maybe_accept( node, &FunctionDecl::type ); … … 473 454 //-------------------------------------------------------------------------- 474 455 // StructDecl 475 template< typename core_t >476 const ast::Decl * ast::Pass< core_t >::visit( const ast::StructDecl * node ) {456 template< typename pass_t > 457 const ast::Decl * ast::Pass< pass_t >::visit( const ast::StructDecl * node ) { 477 458 VISIT_START( node ); 478 459 479 460 // make up a forward declaration and add it before processing the members 480 461 // needs to be on the heap because addStruct saves the pointer 481 __pass::symtab::addStructFwd( core, 0, node );462 __pass::symtab::addStructFwd( pass, 0, node ); 482 463 483 464 VISIT({ … … 488 469 489 470 // this addition replaces the forward declaration 490 __pass::symtab::addStruct( core, 0, node );471 __pass::symtab::addStruct( pass, 0, node ); 491 472 492 473 VISIT_END( Decl, node ); … … 495 476 //-------------------------------------------------------------------------- 496 477 // UnionDecl 497 template< typename core_t >498 const ast::Decl * ast::Pass< core_t >::visit( const ast::UnionDecl * node ) {478 template< typename pass_t > 479 const ast::Decl * ast::Pass< pass_t >::visit( const ast::UnionDecl * node ) { 499 480 VISIT_START( node ); 500 481 501 482 // make up a forward declaration and add it before processing the members 502 __pass::symtab::addUnionFwd( core, 0, node );483 __pass::symtab::addUnionFwd( pass, 0, node ); 503 484 504 485 VISIT({ … … 508 489 }) 509 490 510 __pass::symtab::addUnion( core, 0, node );491 __pass::symtab::addUnion( pass, 0, node ); 511 492 512 493 VISIT_END( Decl, node ); … … 515 496 //-------------------------------------------------------------------------- 516 497 // EnumDecl 517 template< typename core_t >518 const ast::Decl * ast::Pass< core_t >::visit( const ast::EnumDecl * node ) {519 VISIT_START( node ); 520 521 __pass::symtab::addEnum( core, 0, node );498 template< typename pass_t > 499 const ast::Decl * ast::Pass< pass_t >::visit( const ast::EnumDecl * node ) { 500 VISIT_START( node ); 501 502 __pass::symtab::addEnum( pass, 0, node ); 522 503 523 504 VISIT( … … 532 513 //-------------------------------------------------------------------------- 533 514 // TraitDecl 534 template< typename core_t >535 const ast::Decl * ast::Pass< core_t >::visit( const ast::TraitDecl * node ) {515 template< typename pass_t > 516 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TraitDecl * node ) { 536 517 VISIT_START( node ); 537 518 … … 542 523 }) 543 524 544 __pass::symtab::addTrait( core, 0, node );525 __pass::symtab::addTrait( pass, 0, node ); 545 526 546 527 VISIT_END( Decl, node ); … … 549 530 //-------------------------------------------------------------------------- 550 531 // TypeDecl 551 template< typename core_t >552 const ast::Decl * ast::Pass< core_t >::visit( const ast::TypeDecl * node ) {532 template< typename pass_t > 533 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypeDecl * node ) { 553 534 VISIT_START( node ); 554 535 … … 562 543 // note that assertions come after the type is added to the symtab, since they are not part of the type proper 563 544 // and may depend on the type itself 564 __pass::symtab::addType( core, 0, node );545 __pass::symtab::addType( pass, 0, node ); 565 546 566 547 VISIT( … … 578 559 //-------------------------------------------------------------------------- 579 560 // TypedefDecl 580 template< typename core_t >581 const ast::Decl * ast::Pass< core_t >::visit( const ast::TypedefDecl * node ) {561 template< typename pass_t > 562 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypedefDecl * node ) { 582 563 VISIT_START( node ); 583 564 … … 588 569 }) 589 570 590 __pass::symtab::addType( core, 0, node );571 __pass::symtab::addType( pass, 0, node ); 591 572 592 573 VISIT( maybe_accept( node, &TypedefDecl::assertions ); ) … … 597 578 //-------------------------------------------------------------------------- 598 579 // AsmDecl 599 template< typename core_t >600 const ast::AsmDecl * ast::Pass< core_t >::visit( const ast::AsmDecl * node ) {580 template< typename pass_t > 581 const ast::AsmDecl * ast::Pass< pass_t >::visit( const ast::AsmDecl * node ) { 601 582 VISIT_START( node ); 602 583 … … 610 591 //-------------------------------------------------------------------------- 611 592 // StaticAssertDecl 612 template< typename core_t >613 const ast::StaticAssertDecl * ast::Pass< core_t >::visit( const ast::StaticAssertDecl * node ) {593 template< typename pass_t > 594 const ast::StaticAssertDecl * ast::Pass< pass_t >::visit( const ast::StaticAssertDecl * node ) { 614 595 VISIT_START( node ); 615 596 … … 624 605 //-------------------------------------------------------------------------- 625 606 // CompoundStmt 626 template< typename core_t >627 const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {607 template< typename pass_t > 608 const ast::CompoundStmt * ast::Pass< pass_t >::visit( const ast::CompoundStmt * node ) { 628 609 VISIT_START( node ); 629 610 VISIT({ 630 611 // do not enter a new scope if inFunction is true - needs to check old state before the assignment 631 auto guard1 = makeFuncGuard( [this, inFunction Cpy= this->inFunction]() {632 if ( ! inFunction Cpy ) __pass::symtab::enter(core, 0);633 }, [this, inFunction Cpy= this->inFunction]() {634 if ( ! inFunction Cpy ) __pass::symtab::leave(core, 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); 635 616 }); 636 617 ValueGuard< bool > guard2( inFunction ); … … 644 625 //-------------------------------------------------------------------------- 645 626 // ExprStmt 646 template< typename core_t >647 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ExprStmt * node ) {627 template< typename pass_t > 628 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ExprStmt * node ) { 648 629 VISIT_START( node ); 649 630 … … 657 638 //-------------------------------------------------------------------------- 658 639 // AsmStmt 659 template< typename core_t >660 const ast::Stmt * ast::Pass< core_t >::visit( const ast::AsmStmt * node ) {640 template< typename pass_t > 641 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::AsmStmt * node ) { 661 642 VISIT_START( node ) 662 643 … … 673 654 //-------------------------------------------------------------------------- 674 655 // DirectiveStmt 675 template< typename core_t >676 const ast::Stmt * ast::Pass< core_t >::visit( const ast::DirectiveStmt * node ) {656 template< typename pass_t > 657 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DirectiveStmt * node ) { 677 658 VISIT_START( node ) 678 659 … … 682 663 //-------------------------------------------------------------------------- 683 664 // IfStmt 684 template< typename core_t >685 const ast::Stmt * ast::Pass< core_t >::visit( const ast::IfStmt * node ) {665 template< typename pass_t > 666 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::IfStmt * node ) { 686 667 VISIT_START( node ); 687 668 … … 700 681 //-------------------------------------------------------------------------- 701 682 // WhileStmt 702 template< typename core_t >703 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileStmt * node ) {683 template< typename pass_t > 684 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WhileStmt * node ) { 704 685 VISIT_START( node ); 705 686 … … 717 698 //-------------------------------------------------------------------------- 718 699 // ForStmt 719 template< typename core_t >720 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ForStmt * node ) {700 template< typename pass_t > 701 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ForStmt * node ) { 721 702 VISIT_START( node ); 722 703 … … 735 716 //-------------------------------------------------------------------------- 736 717 // SwitchStmt 737 template< typename core_t >738 const ast::Stmt * ast::Pass< core_t >::visit( const ast::SwitchStmt * node ) {718 template< typename pass_t > 719 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SwitchStmt * node ) { 739 720 VISIT_START( node ); 740 721 … … 749 730 //-------------------------------------------------------------------------- 750 731 // CaseStmt 751 template< typename core_t >752 const ast::Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt * node ) {732 template< typename pass_t > 733 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CaseStmt * node ) { 753 734 VISIT_START( node ); 754 735 … … 763 744 //-------------------------------------------------------------------------- 764 745 // BranchStmt 765 template< typename core_t >766 const ast::Stmt * ast::Pass< core_t >::visit( const ast::BranchStmt * node ) {746 template< typename pass_t > 747 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::BranchStmt * node ) { 767 748 VISIT_START( node ); 768 749 VISIT_END( Stmt, node ); … … 771 752 //-------------------------------------------------------------------------- 772 753 // ReturnStmt 773 template< typename core_t >774 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ReturnStmt * node ) {754 template< typename pass_t > 755 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ReturnStmt * node ) { 775 756 VISIT_START( node ); 776 757 … … 784 765 //-------------------------------------------------------------------------- 785 766 // ThrowStmt 786 template< typename core_t >787 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ThrowStmt * node ) {767 template< typename pass_t > 768 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ThrowStmt * node ) { 788 769 VISIT_START( node ); 789 770 … … 798 779 //-------------------------------------------------------------------------- 799 780 // TryStmt 800 template< typename core_t >801 const ast::Stmt * ast::Pass< core_t >::visit( const ast::TryStmt * node ) {781 template< typename pass_t > 782 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::TryStmt * node ) { 802 783 VISIT_START( node ); 803 784 … … 813 794 //-------------------------------------------------------------------------- 814 795 // CatchStmt 815 template< typename core_t >816 const ast::Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt * node ) {796 template< typename pass_t > 797 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CatchStmt * node ) { 817 798 VISIT_START( node ); 818 799 … … 830 811 //-------------------------------------------------------------------------- 831 812 // FinallyStmt 832 template< typename core_t >833 const ast::Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt * node ) {813 template< typename pass_t > 814 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::FinallyStmt * node ) { 834 815 VISIT_START( node ); 835 816 … … 843 824 //-------------------------------------------------------------------------- 844 825 // FinallyStmt 845 template< typename core_t >846 const ast::Stmt * ast::Pass< core_t >::visit( const ast::SuspendStmt * node ) {826 template< typename pass_t > 827 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SuspendStmt * node ) { 847 828 VISIT_START( node ); 848 829 … … 856 837 //-------------------------------------------------------------------------- 857 838 // WaitForStmt 858 template< typename core_t >859 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitForStmt * node ) {839 template< typename pass_t > 840 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WaitForStmt * node ) { 860 841 VISIT_START( node ); 861 842 // for( auto & clause : node->clauses ) { … … 925 906 //-------------------------------------------------------------------------- 926 907 // WithStmt 927 template< typename core_t >928 const ast::Decl * ast::Pass< core_t >::visit( const ast::WithStmt * node ) {908 template< typename pass_t > 909 const ast::Decl * ast::Pass< pass_t >::visit( const ast::WithStmt * node ) { 929 910 VISIT_START( node ); 930 911 … … 934 915 // catch statements introduce a level of scope (for the caught exception) 935 916 guard_symtab guard { *this }; 936 __pass::symtab::addWith( core, 0, node->exprs, node );917 __pass::symtab::addWith( pass, 0, node->exprs, node ); 937 918 maybe_accept( node, &WithStmt::stmt ); 938 919 } … … 943 924 //-------------------------------------------------------------------------- 944 925 // NullStmt 945 template< typename core_t >946 const ast::NullStmt * ast::Pass< core_t >::visit( const ast::NullStmt * node ) {926 template< typename pass_t > 927 const ast::NullStmt * ast::Pass< pass_t >::visit( const ast::NullStmt * node ) { 947 928 VISIT_START( node ); 948 929 VISIT_END( NullStmt, node ); … … 951 932 //-------------------------------------------------------------------------- 952 933 // DeclStmt 953 template< typename core_t >954 const ast::Stmt * ast::Pass< core_t >::visit( const ast::DeclStmt * node ) {934 template< typename pass_t > 935 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DeclStmt * node ) { 955 936 VISIT_START( node ); 956 937 … … 964 945 //-------------------------------------------------------------------------- 965 946 // ImplicitCtorDtorStmt 966 template< typename core_t >967 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {947 template< typename pass_t > 948 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ImplicitCtorDtorStmt * node ) { 968 949 VISIT_START( node ); 969 950 970 951 // For now this isn't visited, it is unclear if this causes problem 971 952 // if all tests are known to pass, remove this code 972 VISIT(973 maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );974 )953 // VISIT( 954 // maybe_accept( node, &ImplicitCtorDtorStmt::callStmt ); 955 // ) 975 956 976 957 VISIT_END( Stmt, node ); … … 979 960 //-------------------------------------------------------------------------- 980 961 // ApplicationExpr 981 template< typename core_t >982 const ast::Expr * ast::Pass< core_t >::visit( const ast::ApplicationExpr * node ) {962 template< typename pass_t > 963 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ApplicationExpr * node ) { 983 964 VISIT_START( node ); 984 965 … … 997 978 //-------------------------------------------------------------------------- 998 979 // UntypedExpr 999 template< typename core_t >1000 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedExpr * node ) {980 template< typename pass_t > 981 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedExpr * node ) { 1001 982 VISIT_START( node ); 1002 983 … … 1015 996 //-------------------------------------------------------------------------- 1016 997 // NameExpr 1017 template< typename core_t >1018 const ast::Expr * ast::Pass< core_t >::visit( const ast::NameExpr * node ) {998 template< typename pass_t > 999 const ast::Expr * ast::Pass< pass_t >::visit( const ast::NameExpr * node ) { 1019 1000 VISIT_START( node ); 1020 1001 … … 1029 1010 //-------------------------------------------------------------------------- 1030 1011 // CastExpr 1031 template< typename core_t >1032 const ast::Expr * ast::Pass< core_t >::visit( const ast::CastExpr * node ) {1012 template< typename pass_t > 1013 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CastExpr * node ) { 1033 1014 VISIT_START( node ); 1034 1015 … … 1045 1026 //-------------------------------------------------------------------------- 1046 1027 // KeywordCastExpr 1047 template< typename core_t >1048 const ast::Expr * ast::Pass< core_t >::visit( const ast::KeywordCastExpr * node ) {1028 template< typename pass_t > 1029 const ast::Expr * ast::Pass< pass_t >::visit( const ast::KeywordCastExpr * node ) { 1049 1030 VISIT_START( node ); 1050 1031 … … 1061 1042 //-------------------------------------------------------------------------- 1062 1043 // VirtualCastExpr 1063 template< typename core_t >1064 const ast::Expr * ast::Pass< core_t >::visit( const ast::VirtualCastExpr * node ) {1044 template< typename pass_t > 1045 const ast::Expr * ast::Pass< pass_t >::visit( const ast::VirtualCastExpr * node ) { 1065 1046 VISIT_START( node ); 1066 1047 … … 1077 1058 //-------------------------------------------------------------------------- 1078 1059 // AddressExpr 1079 template< typename core_t >1080 const ast::Expr * ast::Pass< core_t >::visit( const ast::AddressExpr * node ) {1060 template< typename pass_t > 1061 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AddressExpr * node ) { 1081 1062 VISIT_START( node ); 1082 1063 … … 1093 1074 //-------------------------------------------------------------------------- 1094 1075 // LabelAddressExpr 1095 template< typename core_t >1096 const ast::Expr * ast::Pass< core_t >::visit( const ast::LabelAddressExpr * node ) {1076 template< typename pass_t > 1077 const ast::Expr * ast::Pass< pass_t >::visit( const ast::LabelAddressExpr * node ) { 1097 1078 VISIT_START( node ); 1098 1079 … … 1107 1088 //-------------------------------------------------------------------------- 1108 1089 // UntypedMemberExpr 1109 template< typename core_t >1110 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedMemberExpr * node ) {1090 template< typename pass_t > 1091 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedMemberExpr * node ) { 1111 1092 VISIT_START( node ); 1112 1093 … … 1124 1105 //-------------------------------------------------------------------------- 1125 1106 // MemberExpr 1126 template< typename core_t >1127 const ast::Expr * ast::Pass< core_t >::visit( const ast::MemberExpr * node ) {1107 template< typename pass_t > 1108 const ast::Expr * ast::Pass< pass_t >::visit( const ast::MemberExpr * node ) { 1128 1109 VISIT_START( node ); 1129 1110 … … 1140 1121 //-------------------------------------------------------------------------- 1141 1122 // VariableExpr 1142 template< typename core_t >1143 const ast::Expr * ast::Pass< core_t >::visit( const ast::VariableExpr * node ) {1123 template< typename pass_t > 1124 const ast::Expr * ast::Pass< pass_t >::visit( const ast::VariableExpr * node ) { 1144 1125 VISIT_START( node ); 1145 1126 … … 1154 1135 //-------------------------------------------------------------------------- 1155 1136 // ConstantExpr 1156 template< typename core_t >1157 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstantExpr * node ) {1137 template< typename pass_t > 1138 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstantExpr * node ) { 1158 1139 VISIT_START( node ); 1159 1140 … … 1168 1149 //-------------------------------------------------------------------------- 1169 1150 // SizeofExpr 1170 template< typename core_t >1171 const ast::Expr * ast::Pass< core_t >::visit( const ast::SizeofExpr * node ) {1151 template< typename pass_t > 1152 const ast::Expr * ast::Pass< pass_t >::visit( const ast::SizeofExpr * node ) { 1172 1153 VISIT_START( node ); 1173 1154 … … 1188 1169 //-------------------------------------------------------------------------- 1189 1170 // AlignofExpr 1190 template< typename core_t >1191 const ast::Expr * ast::Pass< core_t >::visit( const ast::AlignofExpr * node ) {1171 template< typename pass_t > 1172 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AlignofExpr * node ) { 1192 1173 VISIT_START( node ); 1193 1174 … … 1208 1189 //-------------------------------------------------------------------------- 1209 1190 // UntypedOffsetofExpr 1210 template< typename core_t >1211 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedOffsetofExpr * node ) {1191 template< typename pass_t > 1192 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedOffsetofExpr * node ) { 1212 1193 VISIT_START( node ); 1213 1194 … … 1224 1205 //-------------------------------------------------------------------------- 1225 1206 // OffsetofExpr 1226 template< typename core_t >1227 const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetofExpr * node ) {1207 template< typename pass_t > 1208 const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetofExpr * node ) { 1228 1209 VISIT_START( node ); 1229 1210 … … 1240 1221 //-------------------------------------------------------------------------- 1241 1222 // OffsetPackExpr 1242 template< typename core_t >1243 const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetPackExpr * node ) {1223 template< typename pass_t > 1224 const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetPackExpr * node ) { 1244 1225 VISIT_START( node ); 1245 1226 … … 1256 1237 //-------------------------------------------------------------------------- 1257 1238 // LogicalExpr 1258 template< typename core_t >1259 const ast::Expr * ast::Pass< core_t >::visit( const ast::LogicalExpr * node ) {1239 template< typename pass_t > 1240 const ast::Expr * ast::Pass< pass_t >::visit( const ast::LogicalExpr * node ) { 1260 1241 VISIT_START( node ); 1261 1242 … … 1273 1254 //-------------------------------------------------------------------------- 1274 1255 // ConditionalExpr 1275 template< typename core_t >1276 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConditionalExpr * node ) {1256 template< typename pass_t > 1257 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConditionalExpr * node ) { 1277 1258 VISIT_START( node ); 1278 1259 … … 1291 1272 //-------------------------------------------------------------------------- 1292 1273 // CommaExpr 1293 template< typename core_t >1294 const ast::Expr * ast::Pass< core_t >::visit( const ast::CommaExpr * node ) {1274 template< typename pass_t > 1275 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CommaExpr * node ) { 1295 1276 VISIT_START( node ); 1296 1277 … … 1308 1289 //-------------------------------------------------------------------------- 1309 1290 // TypeExpr 1310 template< typename core_t >1311 const ast::Expr * ast::Pass< core_t >::visit( const ast::TypeExpr * node ) {1291 template< typename pass_t > 1292 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TypeExpr * node ) { 1312 1293 VISIT_START( node ); 1313 1294 … … 1324 1305 //-------------------------------------------------------------------------- 1325 1306 // AsmExpr 1326 template< typename core_t >1327 const ast::Expr * ast::Pass< core_t >::visit( const ast::AsmExpr * node ) {1307 template< typename pass_t > 1308 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AsmExpr * node ) { 1328 1309 VISIT_START( node ); 1329 1310 … … 1341 1322 //-------------------------------------------------------------------------- 1342 1323 // ImplicitCopyCtorExpr 1343 template< typename core_t >1344 const ast::Expr * ast::Pass< core_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {1324 template< typename pass_t > 1325 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ImplicitCopyCtorExpr * node ) { 1345 1326 VISIT_START( node ); 1346 1327 … … 1357 1338 //-------------------------------------------------------------------------- 1358 1339 // ConstructorExpr 1359 template< typename core_t >1360 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstructorExpr * node ) {1340 template< typename pass_t > 1341 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstructorExpr * node ) { 1361 1342 VISIT_START( node ); 1362 1343 … … 1373 1354 //-------------------------------------------------------------------------- 1374 1355 // CompoundLiteralExpr 1375 template< typename core_t >1376 const ast::Expr * ast::Pass< core_t >::visit( const ast::CompoundLiteralExpr * node ) {1356 template< typename pass_t > 1357 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CompoundLiteralExpr * node ) { 1377 1358 VISIT_START( node ); 1378 1359 … … 1389 1370 //-------------------------------------------------------------------------- 1390 1371 // RangeExpr 1391 template< typename core_t >1392 const ast::Expr * ast::Pass< core_t >::visit( const ast::RangeExpr * node ) {1372 template< typename pass_t > 1373 const ast::Expr * ast::Pass< pass_t >::visit( const ast::RangeExpr * node ) { 1393 1374 VISIT_START( node ); 1394 1375 … … 1406 1387 //-------------------------------------------------------------------------- 1407 1388 // UntypedTupleExpr 1408 template< typename core_t >1409 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedTupleExpr * node ) {1389 template< typename pass_t > 1390 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedTupleExpr * node ) { 1410 1391 VISIT_START( node ); 1411 1392 … … 1422 1403 //-------------------------------------------------------------------------- 1423 1404 // TupleExpr 1424 template< typename core_t >1425 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleExpr * node ) {1405 template< typename pass_t > 1406 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleExpr * node ) { 1426 1407 VISIT_START( node ); 1427 1408 … … 1438 1419 //-------------------------------------------------------------------------- 1439 1420 // TupleIndexExpr 1440 template< typename core_t >1441 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleIndexExpr * node ) {1421 template< typename pass_t > 1422 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleIndexExpr * node ) { 1442 1423 VISIT_START( node ); 1443 1424 … … 1454 1435 //-------------------------------------------------------------------------- 1455 1436 // TupleAssignExpr 1456 template< typename core_t >1457 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleAssignExpr * node ) {1437 template< typename pass_t > 1438 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleAssignExpr * node ) { 1458 1439 VISIT_START( node ); 1459 1440 … … 1470 1451 //-------------------------------------------------------------------------- 1471 1452 // StmtExpr 1472 template< typename core_t >1473 const ast::Expr * ast::Pass< core_t >::visit( const ast::StmtExpr * node ) {1453 template< typename pass_t > 1454 const ast::Expr * ast::Pass< pass_t >::visit( const ast::StmtExpr * node ) { 1474 1455 VISIT_START( node ); 1475 1456 1476 1457 VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr 1477 1458 // get the stmts that will need to be spliced in 1478 auto stmts_before = __pass::stmtsToAddBefore( core, 0);1479 auto stmts_after = __pass::stmtsToAddAfter ( core, 0);1459 auto stmts_before = __pass::stmtsToAddBefore( pass, 0); 1460 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0); 1480 1461 1481 1462 // These may be modified by subnode but most be restored once we exit this statemnet. 1482 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( core, 0) );1463 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( pass, 0) ); 1483 1464 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 1484 1465 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); … … 1498 1479 //-------------------------------------------------------------------------- 1499 1480 // UniqueExpr 1500 template< typename core_t >1501 const ast::Expr * ast::Pass< core_t >::visit( const ast::UniqueExpr * node ) {1481 template< typename pass_t > 1482 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UniqueExpr * node ) { 1502 1483 VISIT_START( node ); 1503 1484 … … 1514 1495 //-------------------------------------------------------------------------- 1515 1496 // UntypedInitExpr 1516 template< typename core_t >1517 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedInitExpr * node ) {1497 template< typename pass_t > 1498 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedInitExpr * node ) { 1518 1499 VISIT_START( node ); 1519 1500 … … 1531 1512 //-------------------------------------------------------------------------- 1532 1513 // InitExpr 1533 template< typename core_t >1534 const ast::Expr * ast::Pass< core_t >::visit( const ast::InitExpr * node ) {1514 template< typename pass_t > 1515 const ast::Expr * ast::Pass< pass_t >::visit( const ast::InitExpr * node ) { 1535 1516 VISIT_START( node ); 1536 1517 … … 1548 1529 //-------------------------------------------------------------------------- 1549 1530 // DeletedExpr 1550 template< typename core_t >1551 const ast::Expr * ast::Pass< core_t >::visit( const ast::DeletedExpr * node ) {1531 template< typename pass_t > 1532 const ast::Expr * ast::Pass< pass_t >::visit( const ast::DeletedExpr * node ) { 1552 1533 VISIT_START( node ); 1553 1534 … … 1565 1546 //-------------------------------------------------------------------------- 1566 1547 // DefaultArgExpr 1567 template< typename core_t >1568 const ast::Expr * ast::Pass< core_t >::visit( const ast::DefaultArgExpr * node ) {1548 template< typename pass_t > 1549 const ast::Expr * ast::Pass< pass_t >::visit( const ast::DefaultArgExpr * node ) { 1569 1550 VISIT_START( node ); 1570 1551 … … 1581 1562 //-------------------------------------------------------------------------- 1582 1563 // GenericExpr 1583 template< typename core_t >1584 const ast::Expr * ast::Pass< core_t >::visit( const ast::GenericExpr * node ) {1564 template< typename pass_t > 1565 const ast::Expr * ast::Pass< pass_t >::visit( const ast::GenericExpr * node ) { 1585 1566 VISIT_START( node ); 1586 1567 … … 1621 1602 //-------------------------------------------------------------------------- 1622 1603 // VoidType 1623 template< typename core_t >1624 const ast::Type * ast::Pass< core_t >::visit( const ast::VoidType * node ) {1604 template< typename pass_t > 1605 const ast::Type * ast::Pass< pass_t >::visit( const ast::VoidType * node ) { 1625 1606 VISIT_START( node ); 1626 1607 … … 1630 1611 //-------------------------------------------------------------------------- 1631 1612 // BasicType 1632 template< typename core_t >1633 const ast::Type * ast::Pass< core_t >::visit( const ast::BasicType * node ) {1613 template< typename pass_t > 1614 const ast::Type * ast::Pass< pass_t >::visit( const ast::BasicType * node ) { 1634 1615 VISIT_START( node ); 1635 1616 … … 1639 1620 //-------------------------------------------------------------------------- 1640 1621 // PointerType 1641 template< typename core_t >1642 const ast::Type * ast::Pass< core_t >::visit( const ast::PointerType * node ) {1622 template< typename pass_t > 1623 const ast::Type * ast::Pass< pass_t >::visit( const ast::PointerType * node ) { 1643 1624 VISIT_START( node ); 1644 1625 … … 1653 1634 //-------------------------------------------------------------------------- 1654 1635 // ArrayType 1655 template< typename core_t >1656 const ast::Type * ast::Pass< core_t >::visit( const ast::ArrayType * node ) {1636 template< typename pass_t > 1637 const ast::Type * ast::Pass< pass_t >::visit( const ast::ArrayType * node ) { 1657 1638 VISIT_START( node ); 1658 1639 … … 1667 1648 //-------------------------------------------------------------------------- 1668 1649 // ReferenceType 1669 template< typename core_t >1670 const ast::Type * ast::Pass< core_t >::visit( const ast::ReferenceType * node ) {1650 template< typename pass_t > 1651 const ast::Type * ast::Pass< pass_t >::visit( const ast::ReferenceType * node ) { 1671 1652 VISIT_START( node ); 1672 1653 … … 1680 1661 //-------------------------------------------------------------------------- 1681 1662 // QualifiedType 1682 template< typename core_t >1683 const ast::Type * ast::Pass< core_t >::visit( const ast::QualifiedType * node ) {1663 template< typename pass_t > 1664 const ast::Type * ast::Pass< pass_t >::visit( const ast::QualifiedType * node ) { 1684 1665 VISIT_START( node ); 1685 1666 … … 1694 1675 //-------------------------------------------------------------------------- 1695 1676 // FunctionType 1696 template< typename core_t > 1697 const ast::Type * ast::Pass< core_t >::visit( const ast::FunctionType * node ) { 1698 VISIT_START( node ); 1699 1700 VISIT({ 1701 guard_forall_subs forall_guard { *this, node }; 1702 mutate_forall( node ); 1677 template< typename pass_t > 1678 const ast::Type * ast::Pass< pass_t >::visit( const ast::FunctionType * node ) { 1679 VISIT_START( node ); 1680 1681 VISIT( 1682 maybe_accept( node, &FunctionType::forall ); 1703 1683 maybe_accept( node, &FunctionType::returns ); 1704 1684 maybe_accept( node, &FunctionType::params ); 1705 })1685 ) 1706 1686 1707 1687 VISIT_END( Type, node ); … … 1710 1690 //-------------------------------------------------------------------------- 1711 1691 // StructInstType 1712 template< typename core_t >1713 const ast::Type * ast::Pass< core_t >::visit( const ast::StructInstType * node ) {1714 VISIT_START( node ); 1715 1716 __pass::symtab::addStruct( core, 0, node->name );1692 template< typename pass_t > 1693 const ast::Type * ast::Pass< pass_t >::visit( const ast::StructInstType * node ) { 1694 VISIT_START( node ); 1695 1696 __pass::symtab::addStruct( pass, 0, node->name ); 1717 1697 1718 1698 VISIT({ 1719 1699 guard_symtab guard { *this }; 1720 guard_forall_subs forall_guard { *this, node }; 1721 mutate_forall( node ); 1700 maybe_accept( node, &StructInstType::forall ); 1722 1701 maybe_accept( node, &StructInstType::params ); 1723 1702 }) … … 1728 1707 //-------------------------------------------------------------------------- 1729 1708 // UnionInstType 1730 template< typename core_t >1731 const ast::Type * ast::Pass< core_t >::visit( const ast::UnionInstType * node ) {1732 VISIT_START( node ); 1733 1734 __pass::symtab::add Union( core, 0, node->name );1735 1736 VISIT({1709 template< typename pass_t > 1710 const ast::Type * ast::Pass< pass_t >::visit( const ast::UnionInstType * node ) { 1711 VISIT_START( node ); 1712 1713 __pass::symtab::addStruct( pass, 0, node->name ); 1714 1715 { 1737 1716 guard_symtab guard { *this }; 1738 guard_forall_subs forall_guard { *this, node }; 1739 mutate_forall( node ); 1717 maybe_accept( node, &UnionInstType::forall ); 1740 1718 maybe_accept( node, &UnionInstType::params ); 1741 } )1719 } 1742 1720 1743 1721 VISIT_END( Type, node ); … … 1746 1724 //-------------------------------------------------------------------------- 1747 1725 // EnumInstType 1748 template< typename core_t > 1749 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumInstType * node ) { 1750 VISIT_START( node ); 1751 1752 VISIT({ 1753 guard_forall_subs forall_guard { *this, node }; 1754 mutate_forall( node ); 1726 template< typename pass_t > 1727 const ast::Type * ast::Pass< pass_t >::visit( const ast::EnumInstType * node ) { 1728 VISIT_START( node ); 1729 1730 VISIT( 1731 maybe_accept( node, &EnumInstType::forall ); 1755 1732 maybe_accept( node, &EnumInstType::params ); 1756 })1733 ) 1757 1734 1758 1735 VISIT_END( Type, node ); … … 1761 1738 //-------------------------------------------------------------------------- 1762 1739 // TraitInstType 1763 template< typename core_t > 1764 const ast::Type * ast::Pass< core_t >::visit( const ast::TraitInstType * node ) { 1765 VISIT_START( node ); 1766 1767 VISIT({ 1768 guard_forall_subs forall_guard { *this, node }; 1769 mutate_forall( node ); 1740 template< typename pass_t > 1741 const ast::Type * ast::Pass< pass_t >::visit( const ast::TraitInstType * node ) { 1742 VISIT_START( node ); 1743 1744 VISIT( 1745 maybe_accept( node, &TraitInstType::forall ); 1770 1746 maybe_accept( node, &TraitInstType::params ); 1771 })1747 ) 1772 1748 1773 1749 VISIT_END( Type, node ); … … 1776 1752 //-------------------------------------------------------------------------- 1777 1753 // TypeInstType 1778 template< typename core_t > 1779 const ast::Type * ast::Pass< core_t >::visit( const ast::TypeInstType * node ) { 1780 VISIT_START( node ); 1781 1782 VISIT( 1783 { 1784 guard_forall_subs forall_guard { *this, node }; 1785 mutate_forall( node ); 1786 maybe_accept( node, &TypeInstType::params ); 1787 } 1788 // ensure that base re-bound if doing substitution 1789 __pass::forall::replace( core, 0, node ); 1754 template< typename pass_t > 1755 const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeInstType * node ) { 1756 VISIT_START( node ); 1757 1758 VISIT( 1759 maybe_accept( node, &TypeInstType::forall ); 1760 maybe_accept( node, &TypeInstType::params ); 1790 1761 ) 1791 1762 … … 1795 1766 //-------------------------------------------------------------------------- 1796 1767 // TupleType 1797 template< typename core_t >1798 const ast::Type * ast::Pass< core_t >::visit( const ast::TupleType * node ) {1768 template< typename pass_t > 1769 const ast::Type * ast::Pass< pass_t >::visit( const ast::TupleType * node ) { 1799 1770 VISIT_START( node ); 1800 1771 … … 1809 1780 //-------------------------------------------------------------------------- 1810 1781 // TypeofType 1811 template< typename core_t >1812 const ast::Type * ast::Pass< core_t >::visit( const ast::TypeofType * node ) {1782 template< typename pass_t > 1783 const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeofType * node ) { 1813 1784 VISIT_START( node ); 1814 1785 … … 1822 1793 //-------------------------------------------------------------------------- 1823 1794 // VarArgsType 1824 template< typename core_t >1825 const ast::Type * ast::Pass< core_t >::visit( const ast::VarArgsType * node ) {1795 template< typename pass_t > 1796 const ast::Type * ast::Pass< pass_t >::visit( const ast::VarArgsType * node ) { 1826 1797 VISIT_START( node ); 1827 1798 … … 1831 1802 //-------------------------------------------------------------------------- 1832 1803 // ZeroType 1833 template< typename core_t >1834 const ast::Type * ast::Pass< core_t >::visit( const ast::ZeroType * node ) {1804 template< typename pass_t > 1805 const ast::Type * ast::Pass< pass_t >::visit( const ast::ZeroType * node ) { 1835 1806 VISIT_START( node ); 1836 1807 … … 1840 1811 //-------------------------------------------------------------------------- 1841 1812 // OneType 1842 template< typename core_t >1843 const ast::Type * ast::Pass< core_t >::visit( const ast::OneType * node ) {1813 template< typename pass_t > 1814 const ast::Type * ast::Pass< pass_t >::visit( const ast::OneType * node ) { 1844 1815 VISIT_START( node ); 1845 1816 … … 1849 1820 //-------------------------------------------------------------------------- 1850 1821 // GlobalScopeType 1851 template< typename core_t >1852 const ast::Type * ast::Pass< core_t >::visit( const ast::GlobalScopeType * node ) {1822 template< typename pass_t > 1823 const ast::Type * ast::Pass< pass_t >::visit( const ast::GlobalScopeType * node ) { 1853 1824 VISIT_START( node ); 1854 1825 … … 1859 1830 //-------------------------------------------------------------------------- 1860 1831 // Designation 1861 template< typename core_t >1862 const ast::Designation * ast::Pass< core_t >::visit( const ast::Designation * node ) {1832 template< typename pass_t > 1833 const ast::Designation * ast::Pass< pass_t >::visit( const ast::Designation * node ) { 1863 1834 VISIT_START( node ); 1864 1835 … … 1870 1841 //-------------------------------------------------------------------------- 1871 1842 // SingleInit 1872 template< typename core_t >1873 const ast::Init * ast::Pass< core_t >::visit( const ast::SingleInit * node ) {1843 template< typename pass_t > 1844 const ast::Init * ast::Pass< pass_t >::visit( const ast::SingleInit * node ) { 1874 1845 VISIT_START( node ); 1875 1846 … … 1883 1854 //-------------------------------------------------------------------------- 1884 1855 // ListInit 1885 template< typename core_t >1886 const ast::Init * ast::Pass< core_t >::visit( const ast::ListInit * node ) {1856 template< typename pass_t > 1857 const ast::Init * ast::Pass< pass_t >::visit( const ast::ListInit * node ) { 1887 1858 VISIT_START( node ); 1888 1859 … … 1897 1868 //-------------------------------------------------------------------------- 1898 1869 // ConstructorInit 1899 template< typename core_t >1900 const ast::Init * ast::Pass< core_t >::visit( const ast::ConstructorInit * node ) {1870 template< typename pass_t > 1871 const ast::Init * ast::Pass< pass_t >::visit( const ast::ConstructorInit * node ) { 1901 1872 VISIT_START( node ); 1902 1873 … … 1912 1883 //-------------------------------------------------------------------------- 1913 1884 // Attribute 1914 template< typename core_t >1915 const ast::Attribute * ast::Pass< core_t >::visit( const ast::Attribute * node ) {1885 template< typename pass_t > 1886 const ast::Attribute * ast::Pass< pass_t >::visit( const ast::Attribute * node ) { 1916 1887 VISIT_START( node ); 1917 1888 … … 1925 1896 //-------------------------------------------------------------------------- 1926 1897 // TypeSubstitution 1927 template< typename core_t >1928 const ast::TypeSubstitution * ast::Pass< core_t >::visit( const ast::TypeSubstitution * node ) {1898 template< typename pass_t > 1899 const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) { 1929 1900 VISIT_START( node ); 1930 1901 … … 1936 1907 guard_symtab guard { *this }; 1937 1908 auto new_node = p.second->accept( *this ); 1938 if (new_node != p.second) mutated = true;1909 if (new_node != p.second) mutated = false; 1939 1910 new_map.insert({ p.first, new_node }); 1940 1911 } … … 1952 1923 guard_symtab guard { *this }; 1953 1924 auto new_node = p.second->accept( *this ); 1954 if (new_node != p.second) mutated = true;1925 if (new_node != p.second) mutated = false; 1955 1926 new_map.insert({ p.first, new_node }); 1956 1927 } -
src/AST/Pass.proto.hpp
rfb0ae06 rdab09ad 17 17 // IWYU pragma: private, include "Pass.hpp" 18 18 19 #include "Common/Stats/Heap.h"20 21 19 namespace ast { 22 template<typename core_t>20 template<typename pass_type> 23 21 class Pass; 24 22 … … 84 82 }; 85 83 86 std::stack< cleanup_t , std::vector<cleanup_t>> cleanups;84 std::stack< cleanup_t > cleanups; 87 85 }; 88 86 … … 113 111 /// "Short hand" to check if this is a valid previsit function 114 112 /// Mostly used to make the static_assert look (and print) prettier 115 template<typename core_t, typename node_t>113 template<typename pass_t, typename node_t> 116 114 struct is_valid_previsit { 117 using ret_t = decltype( (( core_t*)nullptr)->previsit( (const node_t *)nullptr ) );115 using ret_t = decltype( ((pass_t*)nullptr)->previsit( (const node_t *)nullptr ) ); 118 116 119 117 static constexpr bool value = std::is_void< ret_t >::value || … … 129 127 template<> 130 128 struct __assign<true> { 131 template<typename core_t, typename node_t>132 static inline void result( core_t & core, const node_t * & node ) {133 core.previsit( node );129 template<typename pass_t, typename node_t> 130 static inline void result( pass_t & pass, const node_t * & node ) { 131 pass.previsit( node ); 134 132 } 135 133 }; … … 137 135 template<> 138 136 struct __assign<false> { 139 template<typename core_t, typename node_t>140 static inline void result( core_t & core, const node_t * & node ) {141 node = core.previsit( node );137 template<typename pass_t, typename node_t> 138 static inline void result( pass_t & pass, const node_t * & node ) { 139 node = pass.previsit( node ); 142 140 assertf(node, "Previsit must not return NULL"); 143 141 } … … 152 150 template<> 153 151 struct __return<true> { 154 template<typename core_t, typename node_t>155 static inline const node_t * result( core_t & core, const node_t * & node ) {156 core.postvisit( node );152 template<typename pass_t, typename node_t> 153 static inline const node_t * result( pass_t & pass, const node_t * & node ) { 154 pass.postvisit( node ); 157 155 return node; 158 156 } … … 161 159 template<> 162 160 struct __return<false> { 163 template<typename core_t, typename node_t>164 static inline auto result( core_t & core, const node_t * & node ) {165 return core.postvisit( node );161 template<typename pass_t, typename node_t> 162 static inline auto result( pass_t & pass, const node_t * & node ) { 163 return pass.postvisit( node ); 166 164 } 167 165 }; … … 182 180 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 183 181 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 184 template<typename core_t, typename node_t>185 static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) {182 template<typename pass_t, typename node_t> 183 static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) { 186 184 static_assert( 187 is_valid_previsit< core_t, node_t>::value,185 is_valid_previsit<pass_t, node_t>::value, 188 186 "Previsit may not change the type of the node. It must return its paremeter or void." 189 187 ); … … 191 189 __assign< 192 190 std::is_void< 193 decltype( core.previsit( node ) )191 decltype( pass.previsit( node ) ) 194 192 >::value 195 >::result( core, node );193 >::result( pass, node ); 196 194 } 197 195 198 template<typename core_t, typename node_t>199 static inline auto previsit( core_t &, const node_t *, long ) {}196 template<typename pass_t, typename node_t> 197 static inline auto previsit( pass_t &, const node_t *, long ) {} 200 198 201 199 // PostVisit : never mutates the passed pointer but may return a different node 202 template<typename core_t, typename node_t>203 static inline auto postvisit( core_t & core, const node_t * node, int ) ->204 decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) )200 template<typename pass_t, typename node_t> 201 static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> 202 decltype( pass.postvisit( node ), node->accept( *(Visitor*)nullptr ) ) 205 203 { 206 204 return __return< 207 205 std::is_void< 208 decltype( core.postvisit( node ) )206 decltype( pass.postvisit( node ) ) 209 207 >::value 210 >::result( core, node );208 >::result( pass, node ); 211 209 } 212 210 213 template<typename core_t, typename node_t>214 static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; }211 template<typename pass_t, typename node_t> 212 static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; } 215 213 216 214 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- … … 227 225 // The type is not strictly enforced but does match the accessory 228 226 #define FIELD_PTR( name, default_type ) \ 229 template< typename core_t > \230 static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \227 template< typename pass_t > \ 228 static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \ 231 229 \ 232 template< typename core_t > \233 static inline default_type * name( core_t &, long ) { return nullptr; }230 template< typename pass_t > \ 231 static inline default_type * name( pass_t &, long ) { return nullptr; } 234 232 235 233 // List of fields and their expected types … … 241 239 FIELD_PTR( visit_children, __pass::bool_ref ) 242 240 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 243 FIELD_PTR( visitor, ast::Pass< core_t> * const )241 FIELD_PTR( visitor, ast::Pass<pass_t> * const ) 244 242 245 243 // Remove the macro to make sure we don't clash 246 244 #undef FIELD_PTR 247 248 template< typename core_t >249 static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {250 // Stats::Heap::stacktrace_push(core_t::traceId);251 }252 253 template< typename core_t >254 static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {255 // Stats::Heap::stacktrace_pop();256 }257 258 template< typename core_t >259 static void beginTrace(core_t &, long) {}260 261 template< typename core_t >262 static void endTrace(core_t &, long) {}263 245 264 246 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. … … 266 248 // detect it using the same strategy 267 249 namespace scope { 268 template<typename core_t>269 static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) {270 core.beginScope();271 } 272 273 template<typename core_t>274 static inline void enter( core_t &, long ) {}275 276 template<typename core_t>277 static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) {278 core.endScope();279 } 280 281 template<typename core_t>282 static inline void leave( core_t &, long ) {}283 } // namespace scope284 285 // Certain passes desire an up to date symbol table automatically250 template<typename pass_t> 251 static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) { 252 pass.beginScope(); 253 } 254 255 template<typename pass_t> 256 static inline void enter( pass_t &, long ) {} 257 258 template<typename pass_t> 259 static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) { 260 pass.endScope(); 261 } 262 263 template<typename pass_t> 264 static inline void leave( pass_t &, long ) {} 265 }; 266 267 // Finally certain pass desire an up to date symbol table automatically 286 268 // detect the presence of a member name `symtab` and call all the members appropriately 287 269 namespace symtab { 288 270 // Some simple scoping rules 289 template<typename core_t>290 static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) {291 core.symtab.enterScope();292 } 293 294 template<typename core_t>295 static inline auto enter( core_t &, long ) {}296 297 template<typename core_t>298 static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) {299 core.symtab.leaveScope();300 } 301 302 template<typename core_t>303 static inline auto leave( core_t &, long ) {}271 template<typename pass_t> 272 static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) { 273 pass.symtab.enterScope(); 274 } 275 276 template<typename pass_t> 277 static inline auto enter( pass_t &, long ) {} 278 279 template<typename pass_t> 280 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) { 281 pass.symtab.leaveScope(); 282 } 283 284 template<typename pass_t> 285 static inline auto leave( pass_t &, long ) {} 304 286 305 287 // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments 306 288 // Create macro to condense these common patterns 307 289 #define SYMTAB_FUNC1( func, type ) \ 308 template<typename core_t> \309 static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\310 core.symtab.func( arg ); \290 template<typename pass_t> \ 291 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.symtab.func( arg ), void() ) {\ 292 pass.symtab.func( arg ); \ 311 293 } \ 312 294 \ 313 template<typename core_t> \314 static inline void func( core_t &, long, type ) {}295 template<typename pass_t> \ 296 static inline void func( pass_t &, long, type ) {} 315 297 316 298 #define SYMTAB_FUNC2( func, type1, type2 ) \ 317 template<typename core_t> \318 static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\319 core.symtab.func( arg1, arg2 ); \299 template<typename pass_t> \ 300 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.symtab.func( arg1, arg2 ), void () ) {\ 301 pass.symtab.func( arg1, arg2 ); \ 320 302 } \ 321 303 \ 322 template<typename core_t> \323 static inline void func( core_t &, long, type1, type2 ) {}304 template<typename pass_t> \ 305 static inline void func( pass_t &, long, type1, type2 ) {} 324 306 325 307 SYMTAB_FUNC1( addId , const DeclWithType * ); … … 329 311 SYMTAB_FUNC1( addUnion , const UnionDecl * ); 330 312 SYMTAB_FUNC1( addTrait , const TraitDecl * ); 331 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Decl* );313 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Node * ); 332 314 333 315 // A few extra functions have more complicated behaviour, they are hand written 334 template<typename core_t>335 static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) {316 template<typename pass_t> 317 static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.symtab.addStruct( decl ), void() ) { 336 318 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 337 319 fwd->params = decl->params; 338 core.symtab.addStruct( fwd );339 } 340 341 template<typename core_t>342 static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {}343 344 template<typename core_t>345 static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) {320 pass.symtab.addStruct( fwd ); 321 } 322 323 template<typename pass_t> 324 static inline void addStructFwd( pass_t &, long, const ast::StructDecl * ) {} 325 326 template<typename pass_t> 327 static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.symtab.addUnion( decl ), void() ) { 346 328 UnionDecl * fwd = new UnionDecl( decl->location, decl->name ); 347 329 fwd->params = decl->params; 348 core.symtab.addUnion( fwd );349 } 350 351 template<typename core_t>352 static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {}353 354 template<typename core_t>355 static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) {356 if ( ! core.symtab.lookupStruct( str ) ) {357 core.symtab.addStruct( str );358 } 359 } 360 361 template<typename core_t>362 static inline void addStruct( core_t &, long, const std::string & ) {}363 364 template<typename core_t>365 static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) {366 if ( ! core.symtab.lookupUnion( str ) ) {367 core.symtab.addUnion( str );368 } 369 } 370 371 template<typename core_t>372 static inline void addUnion( core_t &, long, const std::string & ) {}330 pass.symtab.addUnion( fwd ); 331 } 332 333 template<typename pass_t> 334 static inline void addUnionFwd( pass_t &, long, const ast::UnionDecl * ) {} 335 336 template<typename pass_t> 337 static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addStruct( str ), void() ) { 338 if ( ! pass.symtab.lookupStruct( str ) ) { 339 pass.symtab.addStruct( str ); 340 } 341 } 342 343 template<typename pass_t> 344 static inline void addStruct( pass_t &, long, const std::string & ) {} 345 346 template<typename pass_t> 347 static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addUnion( str ), void() ) { 348 if ( ! pass.symtab.lookupUnion( str ) ) { 349 pass.symtab.addUnion( str ); 350 } 351 } 352 353 template<typename pass_t> 354 static inline void addUnion( pass_t &, long, const std::string & ) {} 373 355 374 356 #undef SYMTAB_FUNC1 375 357 #undef SYMTAB_FUNC2 376 } // namespace symtab 377 378 // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType. 379 // Detect the presence of a member name `subs` and call all members appropriately 380 namespace forall { 381 // Some simple scoping rules 382 template<typename core_t> 383 static inline auto enter( core_t & core, int, const ast::ParameterizedType * type ) 384 -> decltype( core.subs, void() ) { 385 if ( ! type->forall.empty() ) core.subs.beginScope(); 386 } 387 388 template<typename core_t> 389 static inline auto enter( core_t &, long, const ast::ParameterizedType * ) {} 390 391 template<typename core_t> 392 static inline auto leave( core_t & core, int, const ast::ParameterizedType * type ) 393 -> decltype( core.subs, void() ) { 394 if ( ! type->forall.empty() ) { core.subs.endScope(); } 395 } 396 397 template<typename core_t> 398 static inline auto leave( core_t &, long, const ast::ParameterizedType * ) {} 399 400 // Get the substitution table, if present 401 template<typename core_t> 402 static inline auto subs( core_t & core, int ) -> decltype( &core.subs ) { 403 return &core.subs; 404 } 405 406 template<typename core_t> 407 static inline ast::ForallSubstitutionTable * subs( core_t &, long ) { return nullptr; } 408 409 // Replaces a TypeInstType's base TypeDecl according to the table 410 template<typename core_t> 411 static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst ) 412 -> decltype( core.subs, void() ) { 413 inst = ast::mutate_field( 414 inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) ); 415 } 416 417 template<typename core_t> 418 static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {} 419 420 } // namespace forall 421 } // namespace __pass 422 } // namespace ast 358 }; 359 }; 360 }; -
src/AST/Print.cpp
rfb0ae06 rdab09ad 29 29 30 30 template <typename C, typename... T> 31 constexpr array<C,sizeof...(T)> make_array(T&&... values) 31 constexpr auto make_array(T&&... values) -> 32 array<C,sizeof...(T)> 32 33 { 33 34 return array<C,sizeof...(T)>{ … … 128 129 129 130 void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) { 130 if (inferred.data.resnSlots && !inferred.data.resnSlots->empty()) { 131 os << indent << "with " << inferred.data.resnSlots->size() 131 switch ( inferred.mode ) { 132 case ast::Expr::InferUnion::Empty: return; 133 case ast::Expr::InferUnion::Slots: { 134 os << indent << "with " << inferred.data.resnSlots.size() 132 135 << " pending inference slots" << endl; 133 } 134 if (inferred.data.inferParams && !inferred.data.inferParams->empty()) { 136 return; 137 } 138 case ast::Expr::InferUnion::Params: { 135 139 os << indent << "with inferred parameters " << level << ":" << endl; 136 140 ++indent; 137 for ( const auto & i : *inferred.data.inferParams ) {141 for ( const auto & i : inferred.data.inferParams ) { 138 142 os << indent; 139 short_print( i.second.declptr);143 short_print( Decl::fromId( i.second.decl ) ); 140 144 os << endl; 141 145 print( i.second.expr->inferred, level+1 ); 142 146 } 143 147 --indent; 148 return; 149 } 144 150 } 145 151 } … … 227 233 } 228 234 229 if ( ! node->assertions.empty() ) {235 if ( ! short_mode && ! node->assertions.empty() ) { 230 236 os << endl << indent << "... with assertions" << endl; 231 237 ++indent; … … 836 842 virtual const ast::Expr * visit( const ast::CastExpr * node ) override final { 837 843 ++indent; 838 os << (node->isGenerated ? "Generated" : "Explicit") << " Cast of:" << endl << indent;844 os << (node->isGenerated ? "Generated" : "Explicit") << " cast of:" << endl << indent; 839 845 safe_print( node->arg ); 840 846 os << endl << indent-1 << "... to:"; -
src/AST/Stmt.hpp
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 9 9 // Author : Aaron B. Moss 10 10 // Created On : Mon May 13 15:00:00 2019 11 // Last Modified By : Andrew Beach12 // Last Modified On : Thu Jul 23 14:16:00 202013 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Dec 15 16:56:28 2019 13 // Update Count : 4 14 14 // 15 15 … … 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.core( 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.core( o.returns ); // apply to return and parameter types110 params = sub.core( 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.core( 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" ); … … 148 116 } 149 117 150 // --- S ueInstType (StructInstType, UnionInstType, EnumInstType)118 // --- StructInstType 151 119 152 template<typename decl_t> 153 SueInstType<decl_t>::SueInstType( 154 const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as ) 155 : 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 ) {} 156 123 157 template<typename decl_t> 158 bool SueInstType<decl_t>::isComplete() const { 159 return base ? base->body : false; 160 } 124 bool StructInstType::isComplete() const { return base ? base->body : false; } 161 125 162 template class SueInstType<StructDecl>; 163 template class SueInstType<UnionDecl>; 164 template class SueInstType<EnumDecl>; 126 // --- UnionInstType 127 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 ) {} 131 132 bool UnionInstType::isComplete() const { return base ? base->body : false; } 133 134 // --- EnumInstType 135 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 ) {} 139 140 bool EnumInstType::isComplete() const { return base ? base->body : false; } 165 141 166 142 // --- TraitInstType 167 143 168 TraitInstType::TraitInstType( 169 const TraitDecl * b, CV::Qualifiers q,std::vector<ptr<Attribute>>&& as )170 : 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 ) {} 171 147 172 148 // --- TypeInstType 173 174 TypeInstType::TypeInstType( const TypeInstType & o )175 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {176 Pass< ForallSubstitutor > sub;177 initWithSub( o, sub ); // initialize substitution178 base = sub.core( o.base ); // apply to base type179 }180 149 181 150 void TypeInstType::set_base( const TypeDecl * b ) { … … 189 158 190 159 TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q ) 191 : Type( q ), types( move(ts) ), members() {160 : Type( q ), types( std::move(ts) ), members() { 192 161 // This constructor is awkward. `TupleType` needs to contain objects so that members can be 193 162 // named, but members without initializer nodes end up getting constructors, which breaks -
src/AST/Type.hpp
rfb0ae06 rdab09ad 9 9 // Author : Aaron B. Moss 10 10 // Created On : Thu May 9 10:00:00 2019 11 // Last Modified By : Andrew Beach12 // Last Modified On : Thu Jul 23 14:15:00 202013 // Update Count : 611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Dec 11 21:56:46 2019 13 // Update Count : 5 14 14 // 15 15 … … 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 … … 354 333 }; 355 334 356 // Common implementation for the SUE instance types. Not to be used directly. 357 template<typename decl_t> 358 class SueInstType final : public ReferenceToType { 359 public: 360 using base_type = decl_t; 361 readonly<decl_t> base; 362 363 SueInstType( 364 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 335 /// instance of struct type 336 class StructInstType final : public ReferenceToType { 337 public: 338 readonly<StructDecl> base; 339 340 StructInstType( const std::string& n, CV::Qualifiers q = {}, 341 std::vector<ptr<Attribute>> && as = {} ) 365 342 : ReferenceToType( n, q, std::move(as) ), base() {} 366 367 SueInstType( 368 const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ); 343 StructInstType( const StructDecl * b, CV::Qualifiers q = {}, 344 std::vector<ptr<Attribute>> && as = {} ); 369 345 370 346 bool isComplete() const override; 371 347 372 const decl_t * aggr() const override { return base; } 373 374 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 375 private: 376 SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; } 377 MUTATE_FRIEND 378 }; 379 380 /// An instance of a struct type. 381 using StructInstType = SueInstType<StructDecl>; 382 383 /// An instance of a union type. 384 using UnionInstType = SueInstType<UnionDecl>; 385 386 /// An instance of an enum type. 387 using EnumInstType = SueInstType<EnumDecl>; 388 389 /// An instance of a trait type. 348 const StructDecl * aggr() const override { return base; } 349 350 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 351 private: 352 StructInstType * clone() const override { return new StructInstType{ *this }; } 353 MUTATE_FRIEND 354 }; 355 356 /// instance of union type 357 class UnionInstType final : public ReferenceToType { 358 public: 359 readonly<UnionDecl> base; 360 361 UnionInstType( const std::string& n, CV::Qualifiers q = {}, 362 std::vector<ptr<Attribute>> && as = {} ) 363 : ReferenceToType( n, q, std::move(as) ), base() {} 364 UnionInstType( const UnionDecl * b, CV::Qualifiers q = {}, 365 std::vector<ptr<Attribute>> && as = {} ); 366 367 bool isComplete() const override; 368 369 const UnionDecl * aggr() const override { return base; } 370 371 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 372 private: 373 UnionInstType * clone() const override { return new UnionInstType{ *this }; } 374 MUTATE_FRIEND 375 }; 376 377 /// instance of enum type 378 class EnumInstType final : public ReferenceToType { 379 public: 380 readonly<EnumDecl> base; 381 382 EnumInstType( const std::string& n, CV::Qualifiers q = {}, 383 std::vector<ptr<Attribute>> && as = {} ) 384 : ReferenceToType( n, q, std::move(as) ), base() {} 385 EnumInstType( const EnumDecl * b, CV::Qualifiers q = {}, 386 std::vector<ptr<Attribute>> && as = {} ); 387 388 bool isComplete() const override; 389 390 const EnumDecl * aggr() const override { return base; } 391 392 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 393 private: 394 EnumInstType * clone() const override { return new EnumInstType{ *this }; } 395 MUTATE_FRIEND 396 }; 397 398 /// instance of trait type 390 399 class TraitInstType final : public ReferenceToType { 391 400 public: 392 401 readonly<TraitDecl> base; 393 402 394 TraitInstType( 395 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 = {} ) 396 405 : ReferenceToType( n, q, std::move(as) ), base() {} 397 398 TraitInstType( 399 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 = {} ); 400 408 401 409 // not meaningful for TraitInstType … … 416 424 TypeDecl::Kind kind; 417 425 418 TypeInstType( 419 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 426 TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 420 427 std::vector<ptr<Attribute>> && as = {} ) 421 428 : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {} … … 423 430 std::vector<ptr<Attribute>> && as = {} ) 424 431 : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {} 425 426 TypeInstType( const TypeInstType & o );427 432 428 433 /// sets `base`, updating `kind` correctly -
src/AST/TypeEnvironment.cpp
rfb0ae06 rdab09ad 59 59 std::copy( clz.vars.begin(), clz.vars.end(), std::ostream_iterator< std::string >( out, " " ) ); 60 60 out << ")"; 61 61 62 62 if ( clz.bound ) { 63 63 out << " -> "; … … 92 92 } 93 93 } 94 94 95 95 i = next; // go to next node even if this removed 96 96 } … … 161 161 Pass<Occurs> occur{ var, env }; 162 162 maybe_accept( ty, occur ); 163 return occur. core.result;164 } 165 } 166 167 bool TypeEnvironment::combine( 163 return occur.pass.result; 164 } 165 } 166 167 bool TypeEnvironment::combine( 168 168 const TypeEnvironment & o, OpenVarSet & open, const SymbolTable & symtab ) { 169 169 // short-circuit easy cases … … 199 199 auto st = internal_lookup( *vt ); 200 200 if ( st == env.end() ) { 201 // unbound, safe to add if occurs 201 // unbound, safe to add if occurs 202 202 if ( r.bound && occurs( r.bound, *vt, *this ) ) return false; 203 203 r.vars.emplace( *vt ); … … 266 266 } 267 267 268 bool TypeEnvironment::bindVar( 269 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 270 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 271 const SymbolTable & symtab 268 bool TypeEnvironment::bindVar( 269 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 270 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 271 const SymbolTable & symtab 272 272 ) { 273 273 // remove references from bound type, so that type variables can only bind to value types … … 286 286 ptr<Type> newType = it->bound; 287 287 reset_qualifiers( newType, typeInst->qualifiers ); 288 if ( unifyInexact( 289 newType, target, *this, need, have, open, 288 if ( unifyInexact( 289 newType, target, *this, need, have, open, 290 290 widen & WidenMode{ it->allowWidening, true }, symtab, common ) ) { 291 291 if ( common ) { … … 300 300 } 301 301 } else { 302 env.emplace_back( 302 env.emplace_back( 303 303 typeInst->name, target, widen.first && widen.second, data ); 304 304 } … … 306 306 } 307 307 308 bool TypeEnvironment::bindVarToVar( 309 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 310 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 311 WidenMode widen, const SymbolTable & symtab 308 bool TypeEnvironment::bindVarToVar( 309 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 310 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 311 WidenMode widen, const SymbolTable & symtab 312 312 ) { 313 313 auto c1 = internal_lookup( var1->name ); 314 314 auto c2 = internal_lookup( var2->name ); 315 315 316 316 // exit early if variables already bound together 317 317 if ( c1 != env.end() && c1 == c2 ) { … … 396 396 } 397 397 398 bool TypeEnvironment::mergeBound( 398 bool TypeEnvironment::mergeBound( 399 399 EqvClass & to, const EqvClass & from, OpenVarSet & open, const SymbolTable & symtab ) { 400 400 if ( from.bound ) { … … 406 406 AssertionSet need, have; 407 407 408 if ( unifyInexact( 408 if ( unifyInexact( 409 409 toType, fromType, *this, need, have, open, widen, symtab, common ) ) { 410 410 // unifies, set common type if necessary … … 424 424 } 425 425 426 bool TypeEnvironment::mergeClasses( 426 bool TypeEnvironment::mergeClasses( 427 427 ClassList::iterator to, ClassList::iterator from, OpenVarSet & open, const SymbolTable & symtab 428 428 ) { -
src/AST/TypeEnvironment.hpp
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 18 18 19 19 namespace ast { 20 21 22 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");23 20 24 21 TypeSubstitution::TypeSubstitution() { … … 95 92 namespace { 96 93 struct EnvTrimmer { 97 const TypeSubstitution *env;94 ptr<TypeSubstitution> env; 98 95 TypeSubstitution * newEnv; 99 96 EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} … … 111 108 if ( env ) { 112 109 TypeSubstitution * newEnv = new TypeSubstitution(); 110 #if TIME_TO_CONVERT_PASSES 113 111 Pass<EnvTrimmer> trimmer( env, newEnv ); 114 112 expr->accept( trimmer ); 113 #else 114 (void)expr; 115 (void)env; 116 #endif 115 117 return newEnv; 116 118 } … … 119 121 120 122 void TypeSubstitution::normalize() { 121 Pass<Substituter> sub( *this, true ); 123 #if TIME_TO_CONVERT_PASSES 124 PassVisitor<Substituter> sub( *this, true ); 122 125 do { 123 sub. core.subCount = 0;124 sub. core.freeOnly = true;126 sub.pass.subCount = 0; 127 sub.pass.freeOnly = true; 125 128 for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) { 126 i->second = i->second->accept ( sub );129 i->second = i->second->acceptMutator( sub ); 127 130 } 128 } while ( sub.core.subCount ); 129 } 130 131 const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) { 131 } while ( sub.pass.subCount ); 132 #endif 133 } 134 135 #if TIME_TO_CONVERT_PASSES 136 137 Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) { 132 138 BoundVarsType::const_iterator bound = boundVars.find( inst->name ); 133 139 if ( bound != boundVars.end() ) return inst; … … 140 146 // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here. 141 147 // TODO: investigate preventing type variables from being bound to themselves in the first place. 142 if ( constTypeInstType * replacement = i->second.as<TypeInstType>() ) {148 if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) { 143 149 if ( inst->name == replacement->name ) { 144 150 return inst; … … 147 153 // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl; 148 154 subCount++; 149 ptr<Type> newType = i->second; // force clone if needed 150 add_qualifiers( newType, inst->qualifiers ); 151 // Note: need to recursively apply substitution to the new type because normalize does not 152 // substitute bound vars, but bound vars must be substituted when not in freeOnly mode. 153 newType = newType->accept( *visitor ); 154 return newType.release(); 155 } // if 156 } 157 158 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 ) { 159 164 VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name ); 160 165 if ( i == sub.varEnv.end() ) { … … 162 167 } else { 163 168 subCount++; 164 return i->second; 165 } // if 166 } 167 168 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 ) { 169 175 GuardValue( boundVars ); 170 176 // bind type variables from forall-qualifiers 171 177 if ( freeOnly ) { 172 for ( const TypeDecl * tyvar : ptype->forall) {173 boundVars.insert( tyvar->name );178 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) { 179 boundVars.insert( (*tyvar)->name ); 174 180 } // for 175 181 } // if 176 182 } 177 183 178 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) { 184 template< typename TypeClass > 185 void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) { 179 186 GuardValue( boundVars ); 180 187 // bind type variables from forall-qualifiers 181 188 if ( freeOnly ) { 182 for ( const TypeDecl * tyvar : type->forall) {183 boundVars.insert( tyvar->name );189 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) { 190 boundVars.insert( (*tyvar)->name ); 184 191 } // for 185 192 // bind type variables from generic type instantiations 186 if ( auto decl = type->aggr() ) { 187 if ( ! type->params.empty() ) { 188 for ( const TypeDecl * tyvar : decl->params ) { 189 boundVars.insert( tyvar->name ); 190 } // for 191 } // if 192 } 193 } // if 194 } 195 196 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 ) { 197 203 handleAggregateType( aggregateUseType ); 198 204 } 199 205 200 void TypeSubstitution::Substituter::pre visit( constUnionInstType *aggregateUseType ) {206 void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) { 201 207 handleAggregateType( aggregateUseType ); 202 208 } 209 210 #endif 203 211 204 212 } // namespace ast -
src/AST/TypeSubstitution.hpp
rfb0ae06 rdab09ad 44 44 TypeSubstitution &operator=( const TypeSubstitution &other ); 45 45 46 template< typename SynTreeClass > 47 struct ApplyResult { 48 // const SynTreeClass * node; 49 ast::ptr<SynTreeClass> node; 50 int count; 51 }; 52 53 template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const; 54 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; 55 48 56 49 template< typename node_t, enum Node::ref_type ref_t > 57 50 int apply( ptr_base< node_t, ref_t > & input ) const { 58 51 const node_t * p = input.get(); 59 autoret = apply(p);60 input = ret.node;61 return ret .count;52 int ret = apply(p); 53 input = p; 54 return ret; 62 55 } 63 56 … … 65 58 int applyFree( ptr_base< node_t, ref_t > & input ) const { 66 59 const node_t * p = input.get(); 67 autoret = applyFree(p);68 input = ret.node;69 return ret .count;60 int ret = applyFree(p); 61 input = p; 62 return ret; 70 63 } 71 64 … … 99 92 void initialize( const TypeSubstitution &src, TypeSubstitution &dest ); 100 93 101 template<typename core_t>94 template<typename pass_type> 102 95 friend class Pass; 103 96 … … 154 147 // PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals. 155 148 #include "Pass.hpp" 156 #include "Copy.hpp"157 149 158 150 namespace ast { … … 160 152 // definitition must happen after PassVisitor is included so that WithGuards can be used 161 153 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> { 162 static size_t traceId;163 154 164 155 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {} 165 156 166 const Type * postvisit( const TypeInstType * aggregateUseType ); 167 const Expr * postvisit( const NameExpr * nameExpr ); 157 #if TIME_TO_CONVERT_PASSES 158 159 Type * postmutate( TypeInstType * aggregateUseType ); 160 Expression * postmutate( NameExpr * nameExpr ); 168 161 169 162 /// Records type variable bindings from forall-statements 170 void pre visit( const ParameterizedType * type );163 void premutate( Type * type ); 171 164 /// Records type variable bindings from forall-statements and instantiations of generic types 172 void handleAggregateType( const ReferenceToType * type ); 173 174 void previsit( const StructInstType * aggregateUseType ); 175 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 176 171 177 172 const TypeSubstitution & sub; … … 184 179 185 180 template< typename SynTreeClass > 186 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass *input ) const {181 int TypeSubstitution::apply( const SynTreeClass *& input ) const { 187 182 assert( input ); 188 183 Pass<Substituter> sub( *this, false ); 189 input = strict_dynamic_cast< const SynTreeClass * >( deepCopy(input)->accept( sub ) ); 190 return { input, sub.core.subCount }; 184 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) ); 185 /// std::cerr << "substitution result is: "; 186 /// newType->print( std::cerr ); 187 /// std::cerr << std::endl; 188 return sub.pass.subCount; 191 189 } 192 190 193 191 template< typename SynTreeClass > 194 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass *input ) const {192 int TypeSubstitution::applyFree( const SynTreeClass *& input ) const { 195 193 assert( input ); 196 194 Pass<Substituter> sub( *this, true ); 197 195 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) ); 198 return { input, sub.core.subCount }; 196 /// std::cerr << "substitution result is: "; 197 /// newType->print( std::cerr ); 198 /// std::cerr << std::endl; 199 return sub.pass.subCount; 199 200 } 200 201 -
src/AST/module.mk
rfb0ae06 rdab09ad 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/AST/porting.md
rfb0ae06 rdab09ad 47 47 template<typename node_t> 48 48 friend node_t * mutate(const node_t * node); 49 template<typename node_t>50 friend node_t * shallowCopy(const node_t * node);51 or equilant.52 * You should use the `mutate` function where possible as it avoids extra copies.53 * If you must copy use `shallowCopy` or `deepCopy` as required.54 49 55 50 All leaves of the `Node` inheritance tree are now declared `final` -
src/Common/Eval.cc
rfb0ae06 rdab09ad 168 168 if (expr) { 169 169 expr->accept(ev); 170 return std::make_pair(ev. core.value, ev.core.valid);170 return std::make_pair(ev.pass.value, ev.pass.valid); 171 171 } else { 172 172 return std::make_pair(0, false); -
src/Common/ScopedMap.h
rfb0ae06 rdab09ad 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/Common/Stats/Heap.cc
rfb0ae06 rdab09ad 53 53 const size_t passes_size = sizeof(passes) / sizeof(passes[0]); 54 54 size_t passes_cnt = 1; 55 56 StatBlock stacktrace_stats[100];57 size_t stacktrace_stats_count = 0;58 bool stacktrace_stats_enabled = true;59 60 size_t trace[1000];61 const size_t stacktrace_max_depth = sizeof(trace) / sizeof(size_t);62 size_t stacktrace_depth;63 64 size_t new_stacktrace_id(const char * const name) {65 stacktrace_stats[stacktrace_stats_count].name = name;66 return stacktrace_stats_count++;67 }68 69 void stacktrace_push(size_t id) {70 ++stacktrace_depth;71 assertf(stacktrace_depth < stacktrace_max_depth, "Stack trace too deep: increase size of array in Heap.cc");72 trace[stacktrace_depth] = id;73 }74 75 void stacktrace_pop() {76 assertf(stacktrace_depth > 0, "Invalid stack tracing operation: trace is empty");77 --stacktrace_depth;78 }79 55 80 56 void newPass( const char * const name ) { … … 140 116 for(size_t i = 0; i < passes_cnt; i++) { 141 117 print(passes[i], nc, total_mallocs, total_frees, overall_peak); 142 }143 144 print('-', nct);145 std::cerr << std::setw(nc) << "Trace";146 std::cerr << " | Malloc Count | Free Count | Peak Allocs |" << std::endl;147 148 print('-', nct);149 for (size_t i = 0; i < stacktrace_stats_count; i++) {150 print(stacktrace_stats[i], nc, total_mallocs, total_frees, overall_peak);151 118 } 152 119 print('-', nct); … … 221 188 = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs); 222 189 } 223 224 if ( stacktrace_stats_enabled && stacktrace_depth > 0) {225 stacktrace_stats[trace[stacktrace_depth]].mallocs++;226 }227 190 return __malloc( size ); 228 191 } … … 233 196 passes[passes_cnt - 1].frees++; 234 197 passes[passes_cnt - 1].n_allocs--; 235 }236 if ( stacktrace_stats_enabled && stacktrace_depth > 0) {237 stacktrace_stats[trace[stacktrace_depth]].frees++;238 198 } 239 199 return __free( ptr ); … … 248 208 = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs); 249 209 } 250 if ( stacktrace_stats_enabled && stacktrace_depth > 0) {251 stacktrace_stats[trace[stacktrace_depth]].mallocs++;252 }253 210 return __calloc( nelem, size ); 254 211 } … … 261 218 passes[passes_cnt - 1].frees++; 262 219 } // if 263 if ( stacktrace_stats_enabled && stacktrace_depth > 0) {264 stacktrace_stats[trace[stacktrace_depth]].mallocs++;265 stacktrace_stats[trace[stacktrace_depth]].frees++;266 }267 220 return s; 268 221 } -
src/Common/Stats/Heap.h
rfb0ae06 rdab09ad 20 20 void newPass( const char * const name ); 21 21 void print(); 22 23 size_t new_stacktrace_id(const char * const name);24 void stacktrace_push(size_t id);25 void stacktrace_pop();26 22 } 27 23 } -
src/CompilationState.cc
rfb0ae06 rdab09ad 14 14 // 15 15 16 #include "config.h"17 18 16 int 19 17 astp = false, … … 30 28 genproto = false, 31 29 deterministic_output = false, 32 useNewAST = CFA_USE_NEW_AST,33 30 nomainp = false, 34 31 parsep = false, -
src/CompilationState.h
rfb0ae06 rdab09ad 29 29 genproto, 30 30 deterministic_output, 31 useNewAST,32 31 nomainp, 33 32 parsep, -
src/InitTweak/InitTweak.cc
rfb0ae06 rdab09ad 127 127 ast::Pass< InitFlattener_new > flattener; 128 128 maybe_accept( init, flattener ); 129 return std::move( flattener. core.argList );129 return std::move( flattener.pass.argList ); 130 130 } 131 131 … … 561 561 ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } }; 562 562 maybe_accept( stmt, finder ); 563 return std::move( finder. core.matches );563 return std::move( finder.pass.matches ); 564 564 } 565 565 -
src/ResolvExpr/AdjustExprType.cc
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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 static size_t traceId;599 CandidateFinder & selfFinder;600 599 CandidateList & candidates; 601 600 const ast::TypeEnvironment & tenv; 602 601 ast::ptr< ast::Type > & targetType; 603 602 604 enum Errors {605 NotFound,606 NoMatch,607 ArgsToFew,608 ArgsToMany,609 RetsToFew,610 RetsToMany,611 NoReason612 };613 614 struct {615 Errors code = NotFound;616 } reason;617 618 603 Finder( CandidateFinder & f ) 619 : s ymtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),604 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ), 620 605 targetType( f.targetType ) {} 621 606 622 607 void previsit( const ast::Node * ) { visit_children = false; } 623 608 … … 626 611 void addCandidate( Args &&... args ) { 627 612 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } ); 628 reason.code = NoReason;629 613 } 630 614 … … 655 639 656 640 /// Completes a function candidate with arguments located 657 void validateFunctionCandidate( 658 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 659 CandidateList & out 641 void validateFunctionCandidate( 642 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 643 CandidateList & out 660 644 ) { 661 ast::ApplicationExpr * appExpr = 645 ast::ApplicationExpr * appExpr = 662 646 new ast::ApplicationExpr{ func->expr->location, func->expr }; 663 647 // sum cost and accumulate arguments … … 673 657 appExpr->args = move( vargs ); 674 658 // build and validate new candidate 675 auto newCand = 659 auto newCand = 676 660 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost ); 677 661 PRINT( … … 685 669 /// Builds a list of candidates for a function, storing them in out 686 670 void makeFunctionCandidates( 687 const CandidateRef & func, const ast::FunctionType * funcType, 671 const CandidateRef & func, const ast::FunctionType * funcType, 688 672 const ExplodedArgs_new & args, CandidateList & out 689 673 ) { … … 692 676 ast::TypeEnvironment funcEnv{ func->env }; 693 677 makeUnifiableVars( funcType, funcOpen, funcNeed ); 694 // add all type variables as open variables now so that those not used in the 695 // 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 696 680 funcEnv.add( funcType->forall ); 697 681 … … 699 683 // attempt to narrow based on expected target type 700 684 const ast::Type * returnType = funcType->returns.front()->get_type(); 701 if ( ! unify( 702 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 685 if ( ! unify( 686 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 703 687 ) { 704 688 // unification failed, do not pursue this candidate … … 714 698 for ( const ast::DeclWithType * param : funcType->params ) { 715 699 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param ); 716 // 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 717 701 // matches 718 if ( ! instantiateArgument( 702 if ( ! instantiateArgument( 719 703 obj->type, obj->init, args, results, genStart, symtab ) ) return; 720 704 } … … 766 750 if ( expl.exprs.empty() ) { 767 751 results.emplace_back( 768 results[i], move( env ), copy( results[i].need ), 769 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, 770 754 expl.cost ); 771 755 … … 776 760 results.emplace_back( 777 761 i, expl.exprs.front(), move( env ), copy( results[i].need ), 778 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 762 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 779 763 expl.exprs.size() == 1 ? 0 : 1, j ); 780 764 } … … 796 780 /// Adds implicit struct-conversions to the alternative list 797 781 void addAnonConversions( const CandidateRef & cand ) { 798 // adds anonymous member interpretations whenever an aggregate value type is seen. 799 // 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 800 784 // base type to treat the aggregate as the referenced value 801 785 ast::ptr< ast::Expr > aggrExpr( cand->expr ); 802 786 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result; 803 787 cand->env.apply( aggrType ); 804 788 805 789 if ( aggrType.as< ast::ReferenceType >() ) { 806 790 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; … … 815 799 816 800 /// Adds aggregate member interpretations 817 void addAggMembers( 818 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 819 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 820 804 ) { 821 805 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 822 806 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 823 CandidateRef newCand = std::make_shared<Candidate>( 807 CandidateRef newCand = std::make_shared<Candidate>( 824 808 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 825 // add anonymous member interpretations whenever an aggregate value type is seen 809 // add anonymous member interpretations whenever an aggregate value type is seen 826 810 // as a member expression 827 811 addAnonConversions( newCand ); … … 831 815 832 816 /// Adds tuple member interpretations 833 void addTupleMembers( 834 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 835 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 836 820 ) { 837 821 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) { 838 // 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 839 823 // length of the tuple to have meaning 840 824 long long val = constantExpr->intValue(); 841 825 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 842 826 addCandidate( 843 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 827 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 844 828 addedCost ); 845 829 } … … 853 837 if ( funcFinder.candidates.empty() ) return; 854 838 855 reason.code = NoMatch; 856 857 std::vector< CandidateFinder > argCandidates = 839 std::vector< CandidateFinder > argCandidates = 858 840 selfFinder.findSubExprs( untypedExpr->args ); 859 841 860 842 // take care of possible tuple assignments 861 843 // if not tuple assignment, handled as normal function call … … 895 877 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 896 878 CandidateRef newFunc{ new Candidate{ *func } }; 897 newFunc->expr = 879 newFunc->expr = 898 880 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 899 881 makeFunctionCandidates( newFunc, function, argExpansions, found ); 900 882 } 901 } else if ( 902 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 883 } else if ( 884 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 903 885 ) { 904 886 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) { 905 887 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 906 888 CandidateRef newFunc{ new Candidate{ *func } }; 907 newFunc->expr = 889 newFunc->expr = 908 890 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 909 891 makeFunctionCandidates( newFunc, function, argExpansions, found ); … … 919 901 std::vector< ExplodedArg > funcE; 920 902 funcE.reserve( funcFinder.candidates.size() ); 921 for ( const CandidateRef & func : funcFinder ) { 903 for ( const CandidateRef & func : funcFinder ) { 922 904 funcE.emplace_back( *func, symtab ); 923 905 } … … 931 913 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 932 914 CandidateRef newOp{ new Candidate{ *op} }; 933 newOp->expr = 915 newOp->expr = 934 916 referenceToRvalueConversion( newOp->expr, newOp->cost ); 935 917 makeFunctionCandidates( newOp, function, argExpansions, found ); … … 940 922 } 941 923 942 // 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 943 925 // candidates 944 926 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } … … 952 934 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 953 935 auto function = pointer->base.strict_as< ast::FunctionType >(); 954 936 955 937 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 956 938 std::cerr << "parameters are:" << std::endl; … … 975 957 promoteCvtCost( winners ); 976 958 977 // function may return a struct/union value, in which case we need to add candidates 978 // 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 979 961 // `findMinCost`, since anon conversions are never the cheapest 980 962 for ( const CandidateRef & c : winners ) { … … 984 966 985 967 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 986 // 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 987 969 // will sometimes succeed when it wouldn't with a target type binding. 988 970 // For example: … … 1001 983 /// true if expression is an lvalue 1002 984 static bool isLvalue( const ast::Expr * x ) { 1003 return x->result && ( x-> get_lvalue() || x->result.as< ast::ReferenceType >() );985 return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() ); 1004 986 } 1005 987 … … 1007 989 CandidateFinder finder{ symtab, tenv }; 1008 990 finder.find( addressExpr->arg ); 1009 1010 if( finder.candidates.empty() ) return;1011 1012 reason.code = NoMatch;1013 1014 991 for ( CandidateRef & r : finder.candidates ) { 1015 992 if ( ! isLvalue( r->expr ) ) continue; … … 1032 1009 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1033 1010 1034 if( !finder.candidates.empty() ) reason.code = NoMatch;1035 1036 1011 CandidateList matches; 1037 1012 for ( CandidateRef & cand : finder.candidates ) { … … 1041 1016 cand->env.extractOpenVars( open ); 1042 1017 1043 // It is possible that a cast can throw away some values in a multiply-valued 1044 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1045 // 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 1046 1021 // has fewer results than there are types to cast to. 1047 1022 int discardedValues = cand->expr->result->size() - toType->size(); … … 1050 1025 // unification run for side-effects 1051 1026 unify( toType, cand->expr->result, cand->env, need, have, open, symtab ); 1052 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1053 symtab, cand->env ); 1027 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env ); 1054 1028 PRINT( 1055 1029 std::cerr << "working on cast with result: " << toType << std::endl; … … 1063 1037 // count one safe conversion for each value that is thrown away 1064 1038 thisCost.incSafe( discardedValues ); 1065 CandidateRef newCand = std::make_shared<Candidate>( 1066 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1067 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, 1068 1042 cand->cost + thisCost ); 1069 1043 inferParameters( newCand, matches ); … … 1083 1057 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 1084 1058 for ( CandidateRef & r : finder.candidates ) { 1085 addCandidate( 1086 *r, 1059 addCandidate( 1060 *r, 1087 1061 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 1088 1062 } … … 1093 1067 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1094 1068 for ( CandidateRef & agg : aggFinder.candidates ) { 1095 // 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 1096 1070 // base type to treat the aggregate as the referenced value 1097 1071 Cost addedCost = Cost::zero; … … 1100 1074 // find member of the given type 1101 1075 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1102 addAggMembers( 1076 addAggMembers( 1103 1077 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1104 1078 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1105 addAggMembers( 1079 addAggMembers( 1106 1080 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1107 1081 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { … … 1118 1092 std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name ); 1119 1093 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1120 if( declList.empty() ) return;1121 1122 reason.code = NoMatch;1123 1124 1094 for ( auto & data : declList ) { 1125 1095 Cost cost = Cost::zero; … … 1127 1097 1128 1098 CandidateRef newCand = std::make_shared<Candidate>( 1129 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1099 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1130 1100 cost ); 1131 1101 PRINT( … … 1137 1107 std::cerr << std::endl; 1138 1108 ) 1139 newCand->expr = ast::mutate_field( 1140 newCand->expr.get(), &ast::Expr::result, 1109 newCand->expr = ast::mutate_field( 1110 newCand->expr.get(), &ast::Expr::result, 1141 1111 renameTyVars( newCand->expr->result ) ); 1142 // add anonymous member interpretations whenever an aggregate value type is seen 1112 // add anonymous member interpretations whenever an aggregate value type is seen 1143 1113 // as a name expression 1144 1114 addAnonConversions( newCand ); … … 1150 1120 // not sufficient to just pass `variableExpr` here, type might have changed since 1151 1121 // creation 1152 addCandidate( 1122 addCandidate( 1153 1123 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 1154 1124 } … … 1160 1130 void postvisit( const ast::SizeofExpr * sizeofExpr ) { 1161 1131 if ( sizeofExpr->type ) { 1162 addCandidate( 1163 new ast::SizeofExpr{ 1164 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1132 addCandidate( 1133 new ast::SizeofExpr{ 1134 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1165 1135 tenv ); 1166 1136 } else { … … 1171 1141 CandidateList winners = findMinCost( finder.candidates ); 1172 1142 if ( winners.size() != 1 ) { 1173 SemanticError( 1143 SemanticError( 1174 1144 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1175 1145 } … … 1184 1154 void postvisit( const ast::AlignofExpr * alignofExpr ) { 1185 1155 if ( alignofExpr->type ) { 1186 addCandidate( 1187 new ast::AlignofExpr{ 1188 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1156 addCandidate( 1157 new ast::AlignofExpr{ 1158 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1189 1159 tenv ); 1190 1160 } else { … … 1195 1165 CandidateList winners = findMinCost( finder.candidates ); 1196 1166 if ( winners.size() != 1 ) { 1197 SemanticError( 1167 SemanticError( 1198 1168 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1199 1169 } … … 1202 1172 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1203 1173 choice->cost = Cost::zero; 1204 addCandidate( 1174 addCandidate( 1205 1175 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1206 1176 } … … 1215 1185 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1216 1186 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1217 addCandidate( 1187 addCandidate( 1218 1188 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1219 1189 } … … 1236 1206 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 1237 1207 if ( finder2.candidates.empty() ) return; 1238 1239 reason.code = NoMatch;1240 1208 1241 1209 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1250 1218 1251 1219 addCandidate( 1252 new ast::LogicalExpr{ 1220 new ast::LogicalExpr{ 1253 1221 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1254 1222 move( env ), move( open ), move( need ), r1->cost + r2->cost ); … … 1272 1240 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1273 1241 if ( finder3.candidates.empty() ) return; 1274 1275 reason.code = NoMatch;1276 1242 1277 1243 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1290 1256 ast::AssertionSet have; 1291 1257 1292 // unify true and false results, then infer parameters to produce new 1258 // unify true and false results, then infer parameters to produce new 1293 1259 // candidates 1294 1260 ast::ptr< ast::Type > common; 1295 if ( 1296 unify( 1297 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1298 common ) 1261 if ( 1262 unify( 1263 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1264 common ) 1299 1265 ) { 1300 1266 // generate typed expression 1301 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1267 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1302 1268 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1303 1269 newExpr->result = common ? common : r2->expr->result; 1304 1270 // convert both options to result type 1305 1271 Cost cost = r1->cost + r2->cost + r3->cost; 1306 newExpr->arg2 = computeExpressionConversionCost( 1272 newExpr->arg2 = computeExpressionConversionCost( 1307 1273 newExpr->arg2, newExpr->result, symtab, env, cost ); 1308 1274 newExpr->arg3 = computeExpressionConversionCost( … … 1321 1287 ast::TypeEnvironment env{ tenv }; 1322 1288 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env ); 1323 1289 1324 1290 CandidateFinder finder2{ symtab, env }; 1325 1291 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); … … 1351 1317 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 1352 1318 if ( finder2.candidates.empty() ) return; 1353 1354 reason.code = NoMatch;1355 1319 1356 1320 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1366 1330 1367 1331 ast::ptr< ast::Type > common; 1368 if ( 1369 unify( 1370 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1371 common ) 1332 if ( 1333 unify( 1334 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1335 common ) 1372 1336 ) { 1373 1337 // generate new expression 1374 ast::RangeExpr * newExpr = 1338 ast::RangeExpr * newExpr = 1375 1339 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1376 1340 newExpr->result = common ? common : r1->expr->result; 1377 1341 // add candidate 1378 1342 CandidateRef newCand = std::make_shared<Candidate>( 1379 newExpr, move( env ), move( open ), move( need ), 1343 newExpr, move( env ), move( open ), move( need ), 1380 1344 r1->cost + r2->cost ); 1381 1345 inferParameters( newCand, candidates ); … … 1386 1350 1387 1351 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 1388 std::vector< CandidateFinder > subCandidates = 1352 std::vector< CandidateFinder > subCandidates = 1389 1353 selfFinder.findSubExprs( tupleExpr->exprs ); 1390 1354 std::vector< CandidateList > possibilities; … … 1406 1370 1407 1371 addCandidate( 1408 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1372 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1409 1373 move( env ), move( open ), move( need ), sumCost( subs ) ); 1410 1374 } … … 1448 1412 toType = SymTab::validateType( initExpr->location, toType, symtab ); 1449 1413 toType = adjustExprType( toType, tenv, symtab ); 1450 // The call to find must occur inside this loop, otherwise polymorphic return 1451 // types are not bound to the initialization type, since return type variables are 1452 // 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. 1453 1417 CandidateFinder finder{ symtab, tenv, toType }; 1454 1418 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1455 1419 for ( CandidateRef & cand : finder.candidates ) { 1456 if(reason.code == NotFound) reason.code = NoMatch;1457 1458 1420 ast::TypeEnvironment env{ cand->env }; 1459 1421 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; … … 1464 1426 ) 1465 1427 1466 // It is possible that a cast can throw away some values in a multiply-valued 1467 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1468 // 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 1469 1431 // if it has fewer results than there are types to cast to. 1470 1432 int discardedValues = cand->expr->result->size() - toType->size(); … … 1473 1435 // unification run for side-effects 1474 1436 unify( toType, cand->expr->result, env, need, have, open, symtab ); 1475 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1476 symtab, env ); 1477 1437 Cost thisCost = castCost( cand->expr->result, toType, symtab, env ); 1438 1478 1439 if ( thisCost != Cost::infinity ) { 1479 1440 // count one safe conversion for each value that is thrown away 1480 1441 thisCost.incSafe( discardedValues ); 1481 CandidateRef newCand = std::make_shared<Candidate>( 1482 new ast::InitExpr{ 1483 initExpr->location, restructureCast( cand->expr, toType ), 1484 initAlt.designation }, 1442 CandidateRef newCand = std::make_shared<Candidate>( 1443 new ast::InitExpr{ 1444 initExpr->location, restructureCast( cand->expr, toType ), 1445 initAlt.designation }, 1485 1446 copy( cand->env ), move( open ), move( need ), cand->cost, thisCost ); 1486 1447 inferParameters( newCand, matches ); … … 1508 1469 }; 1509 1470 1510 // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder"); 1511 /// 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 1512 1472 /// return type. Skips ambiguous candidates. 1513 1473 CandidateList pruneCandidates( CandidateList & candidates ) { … … 1526 1486 { 1527 1487 ast::ptr< ast::Type > newType = candidate->expr->result; 1528 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());1529 1488 candidate->env.apply( newType ); 1530 1489 mangleName = Mangle::mangle( newType ); … … 1535 1494 if ( candidate->cost < found->second.candidate->cost ) { 1536 1495 PRINT( 1537 std::cerr << "cost " << candidate->cost << " beats " 1496 std::cerr << "cost " << candidate->cost << " beats " 1538 1497 << found->second.candidate->cost << std::endl; 1539 1498 ) … … 1541 1500 found->second = PruneStruct{ candidate }; 1542 1501 } else if ( candidate->cost == found->second.candidate->cost ) { 1543 // if one of the candidates contains a deleted identifier, can pick the other, 1544 // 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 1545 1504 // that is at least as good 1546 1505 if ( findDeletedExpr( candidate->expr ) ) { … … 1556 1515 } else { 1557 1516 PRINT( 1558 std::cerr << "cost " << candidate->cost << " loses to " 1517 std::cerr << "cost " << candidate->cost << " loses to " 1559 1518 << found->second.candidate->cost << std::endl; 1560 1519 ) … … 1571 1530 1572 1531 CandidateRef cand = target.second.candidate; 1573 1532 1574 1533 ast::ptr< ast::Type > newResult = cand->expr->result; 1575 1534 cand->env.applyFree( newResult ); 1576 1535 cand->expr = ast::mutate_field( 1577 1536 cand->expr.get(), &ast::Expr::result, move( newResult ) ); 1578 1537 1579 1538 out.emplace_back( cand ); 1580 1539 } … … 1590 1549 1591 1550 if ( mode.failFast && candidates.empty() ) { 1592 switch(finder.core.reason.code) { 1593 case Finder::NotFound: 1594 { SemanticError( expr, "No alternatives for expression " ); break; } 1595 case Finder::NoMatch: 1596 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; } 1597 case Finder::ArgsToFew: 1598 case Finder::ArgsToMany: 1599 case Finder::RetsToFew: 1600 case Finder::RetsToMany: 1601 case Finder::NoReason: 1602 default: 1603 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); } 1604 } 1551 SemanticError( expr, "No reasonable alternatives for expression " ); 1605 1552 } 1606 1553 … … 1611 1558 std::vector< std::string > errors; 1612 1559 for ( CandidateRef & candidate : candidates ) { 1613 satisfyAssertions( candidate, localSyms, satisfied, errors );1560 satisfyAssertions( candidate, symtab, satisfied, errors ); 1614 1561 } 1615 1562 … … 1636 1583 1637 1584 CandidateList pruned = pruneCandidates( candidates ); 1638 1585 1639 1586 if ( mode.failFast && pruned.empty() ) { 1640 1587 std::ostringstream stream; … … 1655 1602 ) 1656 1603 PRINT( 1657 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1604 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1658 1605 << std::endl; 1659 1606 ) 1660 1607 } 1661 1608 1662 // 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 1663 1610 // adjusted 1664 1611 if ( mode.adjust ) { 1665 1612 for ( CandidateRef & r : candidates ) { 1666 r->expr = ast::mutate_field( 1667 r->expr.get(), &ast::Expr::result, 1668 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 ) ); 1669 1616 } 1670 1617 } … … 1678 1625 } 1679 1626 1680 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1681 const std::vector< ast::ptr< ast::Expr > > & xs 1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1628 const std::vector< ast::ptr< ast::Expr > > & xs 1682 1629 ) { 1683 1630 std::vector< CandidateFinder > out; 1684 1631 1685 1632 for ( const auto & x : xs ) { 1686 out.emplace_back( localSyms, env );1633 out.emplace_back( symtab, env ); 1687 1634 out.back().find( x, ResolvMode::withAdjustment() ); 1688 1635 1689 1636 PRINT( 1690 1637 std::cerr << "findSubExprs" << std::endl; -
src/ResolvExpr/CandidateFinder.hpp
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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 return converter. core.cost;240 return converter.pass.cost; 245 241 } 246 242 } -
src/ResolvExpr/CommonType.cc
rfb0ae06 rdab09ad 666 666 const ast::OpenVarSet & open; 667 667 public: 668 static size_t traceId;669 668 ast::ptr< ast::Type > result; 670 669 … … 894 893 }; 895 894 896 // size_t CommonType_new::traceId = Stats::Heap::new_stacktrace_id("CommonType_new");897 895 namespace { 898 896 ast::ptr< ast::Type > handleReference( … … 941 939 ast::ptr< ast::Type > result; 942 940 const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >(); 943 const ast::ReferenceType * ref2 = type 2.as< ast::ReferenceType >();941 const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >(); 944 942 945 943 if ( depth1 > depth2 ) { … … 968 966 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open }; 969 967 type1->accept( visitor ); 970 ast::ptr< ast::Type > result = visitor. core.result;968 ast::ptr< ast::Type > result = visitor.pass.result; 971 969 972 970 // handling for opaque type declarations (?) -
src/ResolvExpr/ConversionCost.cc
rfb0ae06 rdab09ad 481 481 } 482 482 483 namespace { 484 # warning For overload resolution between the two versions.485 int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,486 const ast::SymbolTable &, const ast::TypeEnvironment & env ) { 487 return ptrsAssignable( t1, t2, env ); 488 } 489 Cost localConversionCost( 490 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 491 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env492 ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }493 }483 static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2, 484 const ast::SymbolTable &, const ast::TypeEnvironment & env ) { 485 return ptrsAssignable( t1, t2, env ); 486 } 487 488 // TODO: This is used for overload resolution. It might be able to be dropped once the old system 489 // is removed. 490 static Cost localConversionCost( 491 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 492 const ast::TypeEnvironment & env 493 ) { return conversionCost( src, dst, symtab, env ); } 494 494 495 495 Cost conversionCost( 496 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,497 const ast:: SymbolTable & symtab, const ast::TypeEnvironment & env496 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 497 const ast::TypeEnvironment & env 498 498 ) { 499 499 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 500 500 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) { 501 501 if ( eqv->bound ) { 502 return conversionCost(src, eqv->bound, s rcIsLvalue, symtab, env );502 return conversionCost(src, eqv->bound, symtab, env ); 503 503 } else { 504 504 return Cost::infinity; … … 508 508 assertf( type, "Unexpected typedef." ); 509 509 if ( type->base ) { 510 return conversionCost( src, type->base, s rcIsLvalue, symtab, env ) + Cost::safe;510 return conversionCost( src, type->base, symtab, env ) + Cost::safe; 511 511 } 512 512 } … … 518 518 } else if ( const ast::ReferenceType * refType = 519 519 dynamic_cast< const ast::ReferenceType * >( dst ) ) { 520 return convertToReferenceCost( src, refType, s rcIsLvalue, symtab, env, localPtrsAssignable );520 return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable ); 521 521 } else { 522 ast::Pass<ConversionCost_new> converter( dst, s rcIsLvalue, symtab, env, localConversionCost );522 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost ); 523 523 src->accept( converter ); 524 return converter. core.cost;525 } 526 } 527 528 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,524 return converter.pass.cost; 525 } 526 } 527 528 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, 529 529 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 530 PtrsCalculation func ) {530 NumCostCalculation func ) { 531 531 if ( 0 < diff ) { 532 532 Cost cost = convertToReferenceCost( 533 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,534 srcIsLvalue, (diff - 1), symtab, env, func );533 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, 534 dst, (diff - 1), symtab, env, func ); 535 535 cost.incReference(); 536 536 return cost; … … 538 538 Cost cost = convertToReferenceCost( 539 539 src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base, 540 srcIsLvalue,(diff + 1), symtab, env, func );540 (diff + 1), symtab, env, func ); 541 541 cost.incReference(); 542 542 return cost; … … 563 563 } 564 564 } else { 565 ast::Pass<ConversionCost_new> converter( dst, s rcIsLvalue, symtab, env, localConversionCost );565 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost ); 566 566 src->accept( converter ); 567 return converter. core.cost;567 return converter.pass.cost; 568 568 } 569 569 } else { … … 572 572 assert( dstAsRef ); 573 573 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) { 574 if ( src IsLvalue) {574 if ( src->is_lvalue() ) { 575 575 if ( src->qualifiers == dstAsRef->base->qualifiers ) { 576 576 return Cost::reference; … … 591 591 592 592 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst, 593 bool srcIsLvalue,const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,594 PtrsCalculation func ) {593 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 594 NumCostCalculation func ) { 595 595 int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth(); 596 return convertToReferenceCost( src, dst, s rcIsLvalue, sdepth - ddepth, symtab, env, func );596 return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func ); 597 597 } 598 598 … … 651 651 assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) ); 652 652 653 cost = costCalc( refType->base, dst, s rcIsLvalue, symtab, env );653 cost = costCalc( refType->base, dst, symtab, env ); 654 654 if ( refType->base->qualifiers == dst->qualifiers ) { 655 655 cost.incReference(); … … 667 667 void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) { 668 668 (void)enumInstType; 669 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };670 cost = costCalc( integer, dst, srcIsLvalue, symtab, env );669 static const ast::BasicType integer( ast::BasicType::SignedInt ); 670 cost = costCalc( &integer, dst, symtab, env ); 671 671 if ( cost < Cost::unsafe ) { 672 672 cost.incSafe(); … … 680 680 void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) { 681 681 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) { 682 cost = costCalc( eqv->bound, dst, s rcIsLvalue, symtab, env );682 cost = costCalc( eqv->bound, dst, symtab, env ); 683 683 } else if ( const ast::TypeInstType * dstAsInst = 684 684 dynamic_cast< const ast::TypeInstType * >( dst ) ) { … … 690 690 assertf( type, "Unexpected typedef."); 691 691 if ( type->base ) { 692 cost = costCalc( type->base, dst, s rcIsLvalue, symtab, env ) + Cost::safe;692 cost = costCalc( type->base, dst, symtab, env ) + Cost::safe; 693 693 } 694 694 } … … 703 703 auto dstEnd = dstAsTuple->types.end(); 704 704 while ( srcIt != srcEnd && dstIt != dstEnd ) { 705 Cost newCost = costCalc( * srcIt++, * dstIt++, s rcIsLvalue, symtab, env );705 Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env ); 706 706 if ( newCost == Cost::infinity ) { 707 707 return; … … 738 738 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 739 739 } 740 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {741 cost = Cost::zero;742 // +1 for zero_t ->, +1 for disambiguation743 cost.incSafe( maxIntCost + 2 );744 740 } 745 741 } … … 759 755 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 760 756 } 761 } 762 } 763 // size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost"); 757 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) { 758 cost = Cost::zero; 759 cost.incSafe( maxIntCost + 2 ); 760 } 761 } 762 764 763 765 764 } // namespace ResolvExpr -
src/ResolvExpr/ConversionCost.h
rfb0ae06 rdab09ad 72 72 73 73 // Some function pointer types, differ in return type. 74 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool,74 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, 75 75 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 76 using PtrsCalculation = std::function<int(const ast::Type *, const ast::Type *,76 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *, 77 77 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 78 78 … … 81 81 protected: 82 82 const ast::Type * dst; 83 bool srcIsLvalue;84 83 const ast::SymbolTable & symtab; 85 84 const ast::TypeEnvironment & env; 86 85 CostCalculation costCalc; 87 86 public: 88 static size_t traceId;89 87 Cost cost; 90 88 91 ConversionCost_new( const ast::Type * dst, bool srcIsLvalue,const ast::SymbolTable & symtab,89 ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab, 92 90 const ast::TypeEnvironment & env, CostCalculation costCalc ) : 93 dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ), 94 costCalc( costCalc ), cost( Cost::infinity ) 91 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity ) 95 92 {} 96 93 … … 113 110 114 111 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest, 115 bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, 116 PtrsCalculation func ); 112 const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func ); 117 113 118 114 } // namespace ResolvExpr -
src/ResolvExpr/CurrentObject.cc
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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 ) { … … 87 86 ast::Pass<PolyCost_new> costing( symtab, env ); 88 87 type->accept( costing ); 89 return costing. core.result;88 return costing.pass.result; 90 89 } 91 90 -
src/ResolvExpr/PtrsAssignable.cc
rfb0ae06 rdab09ad 155 155 ast::Pass<PtrsAssignable_new> visitor( dst, env ); 156 156 src->accept( visitor ); 157 return visitor. core.result;157 return visitor.pass.result; 158 158 } 159 159 -
src/ResolvExpr/PtrsCastable.cc
rfb0ae06 rdab09ad 293 293 ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab }; 294 294 src->accept( ptrs ); 295 return ptrs. core.result;295 return ptrs.pass.result; 296 296 } 297 297 } -
src/ResolvExpr/RenameVars.cc
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 982 982 ast::Pass<DeleteFinder_new> finder; 983 983 expr->accept( finder ); 984 return finder. core.delExpr;984 return finder.pass.delExpr; 985 985 } 986 986 … … 1072 1072 /// Strips extraneous casts out of an expression 1073 1073 struct StripCasts_new final { 1074 const ast::Expr * post visit( const ast::CastExpr * castExpr ) {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() ); … … 1236 1236 1237 1237 public: 1238 static size_t traceId;1239 1238 Resolver_new() = default; 1240 1239 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } … … 1267 1266 const ast::ConstructorInit * previsit( const ast::ConstructorInit * ); 1268 1267 }; 1269 // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver"); 1270 1271 void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {1272 a st::Pass< Resolver_new >::run( translationUnit);1268 1269 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) { 1270 ast::Pass< Resolver_new > resolver; 1271 accept_all( translationUnit, resolver ); 1273 1272 } 1274 1273 … … 1300 1299 // default value expressions have an environment which shouldn't be there and trips up 1301 1300 // later passes. 1302 as sert( functionDecl->unique() );1303 ast::FunctionType * mutType = mutate( functionDecl->type.get() );1304 1305 for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) { 1306 if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) {1301 ast::ptr< ast::FunctionDecl > ret = functionDecl; 1302 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) { 1303 const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i]; 1304 1305 if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) { 1307 1306 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) { 1308 1307 if ( init->value->env == nullptr ) continue; 1309 1308 // clone initializer minus the initializer environment 1310 auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() ); 1311 auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() ); 1312 auto mutValue = mutate( mutInit->value.get() ); 1313 1314 mutValue->env = nullptr; 1315 mutInit->value = mutValue; 1316 mutParam->init = mutInit; 1317 mutType->params[i] = mutParam; 1318 1319 assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env); 1309 ast::chain_mutate( ret ) 1310 ( &ast::FunctionDecl::type ) 1311 ( &ast::FunctionType::params )[i] 1312 ( &ast::ObjectDecl::init ) 1313 ( &ast::SingleInit::value )->env = nullptr; 1314 1315 assert( functionDecl != ret.get() || functionDecl->unique() ); 1316 assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env ); 1320 1317 } 1321 1318 } 1322 1319 } 1323 mutate_field(functionDecl, &ast::FunctionDecl::type, mutType); 1324 return functionDecl; 1320 return ret.get(); 1325 1321 } 1326 1322 … … 1345 1341 // in case we decide to allow nested enums 1346 1342 GuardValue( inEnumDecl ); 1347 inEnumDecl = true;1343 inEnumDecl = false; 1348 1344 } 1349 1345 -
src/ResolvExpr/SatisfyAssertions.cpp
rfb0ae06 rdab09ad 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 … … 188 188 189 189 matches.emplace_back( 190 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),190 cdata, adjType, std::move( newEnv ), std::move( newNeed ), std::move( have ), 191 191 std::move( newOpen ), crntResnSlot ); 192 192 } … … 229 229 InferMatcher( InferCache & inferred ) : inferred( inferred ) {} 230 230 231 const ast::Expr * post visit( const ast::Expr * expr ) {231 const ast::Expr * postmutate( const ast::Expr * expr ) { 232 232 // Skip if no slots to find 233 if ( !expr->inferred.hasSlots() ) return expr; 234 // if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr; 235 std::vector<UniqueId> missingSlots; 233 if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr; 234 236 235 // find inferred parameters for resolution slots 237 ast::InferredParams * newInferred = new ast::InferredParams();236 ast::InferredParams newInferred; 238 237 for ( UniqueId slot : expr->inferred.resnSlots() ) { 239 238 // fail if no matching assertions found 240 239 auto it = inferred.find( slot ); 241 240 if ( it == inferred.end() ) { 242 std::cerr << "missing assertion " << slot << std::endl; 243 missingSlots.push_back(slot); 244 continue; 241 assert(!"missing assertion"); 245 242 } 246 243 … … 248 245 for ( auto & entry : it->second ) { 249 246 // recurse on inferParams of resolved expressions 250 entry.second.expr = post visit( entry.second.expr );251 auto res = newInferred ->emplace( entry );247 entry.second.expr = postmutate( entry.second.expr ); 248 auto res = newInferred.emplace( entry ); 252 249 assert( res.second && "all assertions newly placed" ); 253 250 } … … 255 252 256 253 ast::Expr * ret = mutate( expr ); 257 ret->inferred.set_inferParams( newInferred ); 258 if (!missingSlots.empty()) ret->inferred.resnSlots() = missingSlots; 254 ret->inferred.set_inferParams( std::move( newInferred ) ); 259 255 return ret; 260 256 } … … 303 299 Cost cost; 304 300 305 OutType( 306 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 301 OutType( 302 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 307 303 const std::vector< DeferRef > & as, const ast::SymbolTable & symtab ) 308 304 : env( e ), open( o ), assns( as ), cost( Cost::zero ) { … … 310 306 for ( const DeferRef & assn : assns ) { 311 307 // compute conversion cost from satisfying decl to assertion 312 cost += computeConversionCost( 313 assn.match.adjType, assn.decl->get_type(), false,symtab, env );314 308 cost += computeConversionCost( 309 assn.match.adjType, assn.decl->get_type(), symtab, env ); 310 315 311 // mark vars+specialization on function-type assertions 316 const ast::FunctionType * func = 312 const ast::FunctionType * func = 317 313 GenPoly::getFunctionType( assn.match.cdata.id->get_type() ); 318 314 if ( ! func ) continue; … … 321 317 cost.decSpec( specCost( param->get_type() ) ); 322 318 } 323 319 324 320 cost.incVar( func->forall.size() ); 325 321 326 322 for ( const ast::TypeDecl * td : func->forall ) { 327 323 cost.decSpec( td->assertions.size() ); … … 333 329 }; 334 330 335 CandidateEnvMerger( 336 const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 331 CandidateEnvMerger( 332 const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 337 333 const ast::SymbolTable & syms ) 338 334 : crnt(), envs{ env }, opens{ open }, symtab( syms ) {} -
src/ResolvExpr/SatisfyAssertions.hpp
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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 } … … 217 208 } 218 209 ast::Pass<SpecCounter> counter; 219 type->accept( counter );220 return counter. core.get_count();210 type->accept( *counter.pass.visitor ); 211 return counter.pass.get_count(); 221 212 } 222 213 -
src/ResolvExpr/Unify.cc
rfb0ae06 rdab09ad 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); 171 172 ast::ptr< ast::Type > subFirst = env.apply(newFirst).node; 173 ast::ptr< ast::Type > subSecond = env.apply(newSecond).node; 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 ); 174 177 175 178 return unifyExact( 176 subFirst, 177 subSecond, 178 newEnv, need, have, open, noWiden(), symtab ); 179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 179 180 } 180 181 … … 325 326 326 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; 327 333 AssertionSet::iterator i = assertions.find( assert ); 328 334 if ( i != assertions.end() ) { 335 /// std::cerr << "found it!" << std::endl; 329 336 i->second.isUsed = true; 330 337 } // if … … 702 709 const ast::SymbolTable & symtab; 703 710 public: 704 static size_t traceId;705 711 bool result; 706 712 … … 937 943 938 944 private: 939 // Returns: other, cast as XInstType 940 // Assigns this->result: whether types are compatible (up to generic parameters) 941 template< typename XInstType > 942 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 ) { 943 947 // check that the other type is compatible and named the same 944 auto otherInst = dynamic_cast< const XInstType * >( other );945 this->result = otherInst && inst->name == otherInst->name;948 auto otherInst = dynamic_cast< const RefType * >( other ); 949 result = otherInst && inst->name == otherInst->name; 946 950 return otherInst; 947 951 } … … 964 968 } 965 969 966 template< typename XInstType >967 void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {970 template< typename RefType > 971 void handleGenericRefType( const RefType * inst, const ast::Type * other ) { 968 972 // check that other type is compatible and named the same 969 const XInstType * otherInst= handleRefType( inst, other );970 if ( ! this->result) return;973 const RefType * inst2 = handleRefType( inst, other ); 974 if ( ! inst2 ) return; 971 975 972 976 // check that parameters of types unify, if any 973 977 const std::vector< ast::ptr< ast::Expr > > & params = inst->params; 974 const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;978 const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params; 975 979 976 980 auto it = params.begin(); … … 1136 1140 }; 1137 1141 1138 // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");1139 1142 bool unify( 1140 1143 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, … … 1185 1188 ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab }; 1186 1189 type1->accept( comparator ); 1187 return comparator. core.result;1190 return comparator.pass.result; 1188 1191 } 1189 1192 } … … 1199 1202 // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and 1200 1203 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1201 ast::Type * t1 = shallowCopy(type1.get()); 1202 ast::Type * t2 = shallowCopy(type2.get()); 1203 t1->qualifiers = {}; 1204 t2->qualifiers = {}; 1205 ast::ptr< ast::Type > t1_(t1); 1206 ast::ptr< ast::Type > t2_(t2); 1204 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1205 reset_qualifiers( t1 ); 1206 reset_qualifiers( t2 ); 1207 1207 1208 1208 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { 1209 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1210 1209 1211 // if exact unification on unqualified types, try to merge qualifiers 1210 1212 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { 1211 t1->qualifiers = q1 | q2;1212 common = t1;1213 common = type1; 1214 reset_qualifiers( common, q1 | q2 ); 1213 1215 return true; 1214 1216 } else { … … 1217 1219 1218 1220 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) { 1221 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1222 1219 1223 // no exact unification, but common type 1220 auto c = shallowCopy(common.get()); 1221 c->qualifiers = q1 | q2; 1222 common = c; 1224 reset_qualifiers( common, q1 | q2 ); 1223 1225 return true; 1224 1226 } else { -
src/ResolvExpr/typeops.h
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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/SymTab/FixFunction.cc
rfb0ae06 rdab09ad 106 106 bool isVoid = false; 107 107 108 void pre visit( const ast::FunctionDecl * ) { visit_children = false; }108 void premutate( const ast::FunctionDecl * ) { visit_children = false; } 109 109 110 const ast::DeclWithType * post visit( const ast::FunctionDecl * func ) {110 const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) { 111 111 return new ast::ObjectDecl{ 112 112 func->location, func->name, new ast::PointerType{ func->type }, nullptr, … … 114 114 } 115 115 116 void pre visit( const ast::ArrayType * ) { visit_children = false; }116 void premutate( const ast::ArrayType * ) { visit_children = false; } 117 117 118 const ast::Type * post visit( const ast::ArrayType * array ) {118 const ast::Type * postmutate( const ast::ArrayType * array ) { 119 119 return new ast::PointerType{ 120 120 array->base, array->dimension, array->isVarLen, array->isStatic, … … 122 122 } 123 123 124 void pre visit( const ast::VoidType * ) { isVoid = true; }124 void premutate( const ast::VoidType * ) { isVoid = true; } 125 125 126 void pre visit( const ast::BasicType * ) { visit_children = false; }127 void pre visit( const ast::PointerType * ) { visit_children = false; }128 void pre visit( const ast::StructInstType * ) { visit_children = false; }129 void pre visit( const ast::UnionInstType * ) { visit_children = false; }130 void pre visit( const ast::EnumInstType * ) { visit_children = false; }131 void pre visit( const ast::TraitInstType * ) { visit_children = false; }132 void pre visit( const ast::TypeInstType * ) { visit_children = false; }133 void pre visit( const ast::TupleType * ) { visit_children = false; }134 void pre visit( const ast::VarArgsType * ) { visit_children = false; }135 void pre visit( const ast::ZeroType * ) { visit_children = false; }136 void pre visit( const ast::OneType * ) { visit_children = false; }126 void premutate( const ast::BasicType * ) { visit_children = false; } 127 void premutate( const ast::PointerType * ) { visit_children = false; } 128 void premutate( const ast::StructInstType * ) { visit_children = false; } 129 void premutate( const ast::UnionInstType * ) { visit_children = false; } 130 void premutate( const ast::EnumInstType * ) { visit_children = false; } 131 void premutate( const ast::TraitInstType * ) { visit_children = false; } 132 void premutate( const ast::TypeInstType * ) { visit_children = false; } 133 void premutate( const ast::TupleType * ) { visit_children = false; } 134 void premutate( const ast::VarArgsType * ) { visit_children = false; } 135 void premutate( const ast::ZeroType * ) { visit_children = false; } 136 void premutate( const ast::OneType * ) { visit_children = false; } 137 137 }; 138 138 } // anonymous namespace … … 141 141 ast::Pass< FixFunction_new > fixer; 142 142 dwt = dwt->accept( fixer ); 143 isVoid |= fixer. core.isVoid;143 isVoid |= fixer.pass.isVoid; 144 144 return dwt; 145 145 } -
src/SymTab/Mangler.cc
rfb0ae06 rdab09ad 447 447 ast::Pass<Mangler_new> mangler( mode ); 448 448 maybeAccept( decl, mangler ); 449 return mangler. core.get_mangleName();449 return mangler.pass.get_mangleName(); 450 450 } 451 451 … … 691 691 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 692 692 assert->accept( sub_mangler ); 693 assertionNames.push_back( sub_mangler. core.get_mangleName() );693 assertionNames.push_back( sub_mangler.pass.get_mangleName() ); 694 694 acount++; 695 695 } // for -
src/SynTree/ApplicationExpr.cc
rfb0ae06 rdab09ad 34 34 35 35 ParamEntry::ParamEntry( const ParamEntry &other ) : 36 decl( other.decl ), declptr( other.declptr), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) {36 decl( other.decl ), declptr( maybeClone( other.declptr ) ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) { 37 37 } 38 38 39 39 ParamEntry::~ParamEntry() { 40 //delete declptr;40 delete declptr; 41 41 delete actualType; 42 42 delete formalType; -
src/SynTree/Statement.h
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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 ) { … … 147 148 } 148 149 149 const ast::Expr * post visit( const ast::UniqueExpr * node ) {150 const ast::Expr * postmutate( const ast::UniqueExpr * node ) { 150 151 // move cast into unique expr so that the unique expr has type T& rather than 151 152 // type T. In particular, this transformation helps with generating the … … 166 167 } 167 168 168 const ast::Expr * post visit( const ast::TupleIndexExpr * tupleExpr ) {169 const ast::Expr * postmutate( const ast::TupleIndexExpr * tupleExpr ) { 169 170 // tuple index expr needs to be rebuilt to ensure that the type of the 170 171 // field is consistent with the type of the tuple expr, since the field … … 179 180 ast::Pass<CastExploderCore> exploder; 180 181 expr = expr->accept( exploder ); 181 if ( ! exploder. core.foundUniqueExpr ) {182 if ( ! exploder.pass.foundUniqueExpr ) { 182 183 expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } }; 183 184 } -
src/Tuples/Explode.h
rfb0ae06 rdab09ad 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
rfb0ae06 rdab09ad 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 }; … … 504 504 505 505 std::vector< ast::ptr< ast::Expr > > match() override { 506 // temporary workaround for new and old ast to coexist and avoid name collision 507 static UniqueName lhsNamer( "__massassign_Ln" ); 508 static UniqueName rhsNamer( "__massassign_Rn" ); 506 static UniqueName lhsNamer( "__massassign_L" ); 507 static UniqueName rhsNamer( "__massassign_R" ); 509 508 // empty tuple case falls into this matcher 510 509 assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 ); … … 535 534 536 535 std::vector< ast::ptr< ast::Expr > > match() override { 537 // temporary workaround for new and old ast to coexist and avoid name collision 538 static UniqueName lhsNamer( "__multassign_Ln" ); 539 static UniqueName rhsNamer( "__multassign_Rn" ); 536 static UniqueName lhsNamer( "__multassign_L" ); 537 static UniqueName rhsNamer( "__multassign_R" ); 540 538 541 539 if ( lhs.size() != rhs.size() ) return {}; … … 562 560 // resolve the cast expression so that rhsCand return type is bound by the cast 563 561 // type as needed, and transfer the resulting environment 564 ResolvExpr::CandidateFinder finder{ spotter.crntFinder. localSyms, env };562 ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env }; 565 563 finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() ); 566 564 assert( finder.candidates.size() == 1 ); … … 611 609 // explode the LHS so that each field of a tuple-valued expr is assigned 612 610 ResolvExpr::CandidateList lhs; 613 explode( *lhsCand, crntFinder. localSyms, back_inserter(lhs), true );611 explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true ); 614 612 for ( ResolvExpr::CandidateRef & cand : lhs ) { 615 613 // each LHS value must be a reference - some come in with a cast, if not … … 631 629 if ( isTuple( rhsCand->expr ) ) { 632 630 // multiple assignment 633 explode( *rhsCand, crntFinder. localSyms, back_inserter(rhs), true );631 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 634 632 matcher.reset( 635 633 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); … … 650 648 // multiple assignment 651 649 ResolvExpr::CandidateList rhs; 652 explode( rhsCand, crntFinder. localSyms, back_inserter(rhs), true );650 explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 653 651 matcher.reset( 654 652 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); … … 680 678 ) 681 679 682 ResolvExpr::CandidateFinder finder{ crntFinder. localSyms, matcher->env };680 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env }; 683 681 684 682 try { -
src/Tuples/TupleExpansion.cc
rfb0ae06 rdab09ad 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/Tuples/Tuples.cc
rfb0ae06 rdab09ad 43 43 }; 44 44 struct ImpurityDetectorIgnoreUnique : public ImpurityDetector { 45 using ImpurityDetector::previsit;46 45 void previsit( ast::UniqueExpr const * ) { 47 46 visit_children = false; … … 53 52 ast::Pass<Detector> detector; 54 53 expr->accept( detector ); 55 return detector. core.maybeImpure;54 return detector.pass.maybeImpure; 56 55 } 57 56 } // namespace -
src/config.h.in
rfb0ae06 rdab09ad 27 27 /* Location of cfa install. */ 28 28 #undef CFA_PREFIX 29 30 /* Sets whether or not to use the new-ast, this is adefault value and can be31 overrided by --old-ast and --new-ast */32 #undef CFA_USE_NEW_AST33 29 34 30 /* Major.Minor */ -
src/main.cc
rfb0ae06 rdab09ad 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 … … 340 340 } // if 341 341 342 if( useNewAST) { 343 auto transUnit = convert( move( translationUnit ) ); 344 PASS( "Resolve", ResolvExpr::resolve( transUnit ) ); 345 translationUnit = convert( move( transUnit ) ); 346 } else { 347 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) ); 348 } 349 342 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) ); 350 343 if ( exprp ) { 351 344 dump( translationUnit ); … … 465 458 { "prototypes", no_argument, nullptr, 'p' }, 466 459 { "deterministic-out", no_argument, nullptr, 'd' }, 467 { "old-ast", no_argument, nullptr, 'O'},468 { "new-ast", no_argument, nullptr, 'A'},469 460 { "print", required_argument, nullptr, 'P' }, 470 461 { "prelude-dir", required_argument, nullptr, PreludeDir }, … … 488 479 "generate prototypes for prelude functions", // -p 489 480 "don't print output that isn't deterministic", // -d 490 "Use the old-ast", // -O491 "Use the new-ast", // -A492 481 "print", // -P 493 482 "<directory> prelude directory for debug/nodebug", // no flag … … 595 584 break; 596 585 case 'd': // don't print non-deterministic output 597 deterministic_output = true; 598 break; 599 case 'O': // don't print non-deterministic output 600 useNewAST = false; 601 break; 602 case 'A': // don't print non-deterministic output 603 useNewAST = true; 586 deterministic_output = true; 604 587 break; 605 588 case 'P': // print options
Note:
See TracChangeset
for help on using the changeset viewer.