- Timestamp:
- Jun 21, 2023, 2:38:55 AM (2 years ago)
- Branches:
- master
- Children:
- 92355883
- Parents:
- 0b0a285 (diff), 2de175ce (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
r0b0a285 rc84dd61 2343 2343 old->location, 2344 2344 GET_ACCEPT_1(arg, Expr), 2345 old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast 2345 old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast, 2346 (ast::CastExpr::CastKind) old->kind 2346 2347 ) 2347 2348 ); -
src/AST/Expr.cpp
r0b0a285 rc84dd61 186 186 // --- CastExpr 187 187 188 CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )189 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}188 CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g, CastKind kind ) 189 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ), kind( kind ) {} 190 190 191 191 bool CastExpr::get_lvalue() const { -
src/AST/Expr.hpp
r0b0a285 rc84dd61 55 55 const Expr * e ) 56 56 : decl( id ), declptr( declptr ), actualType( actual ), formalType( formal ), expr( e ) {} 57 58 operator bool() {return declptr;} 57 59 }; 58 60 … … 335 337 GeneratedFlag isGenerated; 336 338 339 enum CastKind { 340 Default, // C 341 Coerce, // reinterpret cast 342 Return // overload selection 343 }; 344 345 CastKind kind = Default; 346 337 347 CastExpr( const CodeLocation & loc, const Expr * a, const Type * to, 338 GeneratedFlag g = GeneratedCast ) : Expr( loc, to ), arg( a ), isGenerated( g) {}348 GeneratedFlag g = GeneratedCast, CastKind kind = Default ) : Expr( loc, to ), arg( a ), isGenerated( g ), kind( kind ) {} 339 349 /// Cast-to-void 340 CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast );350 CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast, CastKind kind = Default ); 341 351 342 352 /// Wrap a cast expression around an existing expression (always generated) -
src/AST/SymbolTable.cpp
r0b0a285 rc84dd61 19 19 20 20 #include "Copy.hpp" 21 #include <iostream> 22 #include <algorithm> 23 21 24 #include "Decl.hpp" 22 25 #include "Expr.hpp" … … 203 206 out.push_back(decl.second); 204 207 } 208 209 // std::cerr << otypeKey << ' ' << out.size() << std::endl; 205 210 } 206 211 -
src/AST/Type.hpp
r0b0a285 rc84dd61 451 451 bool operator==(const TypeEnvKey & other) const; 452 452 bool operator<(const TypeEnvKey & other) const; 453 }; 453 operator bool() {return base;} 454 }; 455 454 456 455 457 /// tuple type e.g. `[int, char]` -
src/AST/TypeEnvironment.cpp
r0b0a285 rc84dd61 135 135 } 136 136 } 137 sub.normalize();137 // sub.normalize(); 138 138 } 139 139 -
src/AST/TypeEnvironment.hpp
r0b0a285 rc84dd61 63 63 64 64 int cmp = d1->var->name.compare( d2->var->name ); 65 return cmp <0 || ( cmp == 0 && d1->result < d2->result );65 return cmp > 0 || ( cmp == 0 && d1->result < d2->result ); 66 66 } 67 67 }; -
src/Concurrency/Actors.cpp
r0b0a285 rc84dd61 223 223 if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) { 224 224 ////////////////////////////////////////////////////////////////////// 225 // The following generates this wrapper for all receive(derived_actor &, derived_msg &) functions 226 /* base_actor and base_msg are output params 227 static inline allocation __CFA_receive_wrap( derived_actor & receiver, derived_msg & msg, actor ** base_actor, message ** base_msg ) { 228 base_actor = &receiver; 229 base_msg = &msg; 230 return receive( receiver, msg ); 231 } 232 */ 233 CompoundStmt * wrapBody = new CompoundStmt( decl->location ); 234 235 // generates: base_actor = &receiver; 236 wrapBody->push_back( new ExprStmt( decl->location, 237 UntypedExpr::createAssign( decl->location, 238 UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_actor" ) ), 239 new AddressExpr( decl->location, new NameExpr( decl->location, "receiver" ) ) 240 ) 241 )); 242 243 // generates: base_msg = &msg; 244 wrapBody->push_back( new ExprStmt( decl->location, 245 UntypedExpr::createAssign( decl->location, 246 UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_msg" ) ), 247 new AddressExpr( decl->location, new NameExpr( decl->location, "msg" ) ) 248 ) 249 )); 250 251 // generates: return receive( receiver, msg ); 252 wrapBody->push_back( new ReturnStmt( decl->location, 253 new UntypedExpr ( decl->location, 254 new NameExpr( decl->location, "receive" ), 255 { 256 new NameExpr( decl->location, "receiver" ), 257 new NameExpr( decl->location, "msg" ) 258 } 259 ) 260 )); 261 262 // create receive wrapper to extract base message and actor pointer 263 // put it all together into the complete function decl from above 264 FunctionDecl * receiveWrapper = new FunctionDecl( 265 decl->location, 266 "__CFA_receive_wrap", 267 {}, // forall 268 { 269 new ObjectDecl( 270 decl->location, 271 "receiver", 272 ast::deepCopy( derivedActorRef ) 273 ), 274 new ObjectDecl( 275 decl->location, 276 "msg", 277 ast::deepCopy( derivedMsgRef ) 278 ), 279 new ObjectDecl( 280 decl->location, 281 "base_actor", 282 new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) 283 ), 284 new ObjectDecl( 285 decl->location, 286 "base_msg", 287 new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) 288 ) 289 }, // params 290 { 291 new ObjectDecl( 292 decl->location, 293 "__CFA_receive_wrap_ret", 294 new EnumInstType( *allocationDecl ) 295 ) 296 }, 297 wrapBody, // body 298 { Storage::Static }, // storage 299 Linkage::Cforall, // linkage 300 {}, // attributes 301 { Function::Inline } 302 ); 303 304 declsToAddAfter.push_back( receiveWrapper ); 305 306 ////////////////////////////////////////////////////////////////////// 225 307 // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions 226 308 /* … … 246 328 )); 247 329 248 // Function type is: allocation (*)( derived_actor &, derived_msg & )330 // Function type is: allocation (*)( derived_actor &, derived_msg &, actor **, message ** ) 249 331 FunctionType * derivedReceive = new FunctionType(); 250 332 derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) ); 251 333 derivedReceive->params.push_back( ast::deepCopy( derivedMsgRef ) ); 334 derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) ); 335 derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) ); 252 336 derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) ); 253 337 254 // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;338 // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg &, actor **, message ** ) = receive; 255 339 sendBody->push_back( new DeclStmt( 256 340 decl->location, … … 259 343 "my_work_fn", 260 344 new PointerType( derivedReceive ), 261 new SingleInit( decl->location, new NameExpr( decl->location, " receive" ) )345 new SingleInit( decl->location, new NameExpr( decl->location, "__CFA_receive_wrap" ) ) 262 346 ) 263 347 )); … … 267 351 genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) ); 268 352 genericReceive->params.push_back( new ReferenceType( new StructInstType( *msgDecl ) ) ); 353 genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) ); 354 genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) ); 269 355 genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) ); 270 356 … … 285 371 )); 286 372 287 // Generates: new_req{ &receiver,&msg, fn };373 // Generates: new_req{ (actor *)&receiver, (message *)&msg, fn }; 288 374 sendBody->push_back( new ExprStmt( 289 375 decl->location, … … 293 379 { 294 380 new NameExpr( decl->location, "new_req" ), 295 new AddressExpr( new NameExpr( decl->location, "receiver" )),296 new AddressExpr( new NameExpr( decl->location, "msg" )),381 new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "receiver" ) ), new PointerType( new StructInstType( *actorDecl ) ), ExplicitCast ), 382 new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "msg" ) ), new PointerType( new StructInstType( *msgDecl ) ), ExplicitCast ), 297 383 new NameExpr( decl->location, "fn" ) 298 384 } … … 321 407 FunctionDecl * sendOperatorFunction = new FunctionDecl( 322 408 decl->location, 323 "? <<?",409 "?|?", 324 410 {}, // forall 325 411 { -
src/GenPoly/SpecializeNew.cpp
r0b0a285 rc84dd61 113 113 using namespace ResolvExpr; 114 114 ast::OpenVarSet openVars, closedVars; 115 ast::AssertionSet need, have; 116 findOpenVars( formalType, openVars, closedVars, need, have, FirstClosed ); 117 findOpenVars( actualType, openVars, closedVars, need, have, FirstOpen ); 115 ast::AssertionSet need, have; // unused 116 ast::TypeEnvironment env; // unused 117 // findOpenVars( formalType, openVars, closedVars, need, have, FirstClosed ); 118 findOpenVars( actualType, openVars, closedVars, need, have, env, FirstOpen ); 118 119 for ( const ast::OpenVarSet::value_type & openVar : openVars ) { 119 120 const ast::Type * boundType = subs->lookup( openVar.first ); … … 125 126 if ( closedVars.find( *inst ) == closedVars.end() ) { 126 127 return true; 128 } 129 else { 130 assertf(false, "closed: %s", inst->name.c_str()); 127 131 } 128 132 // Otherwise, the variable is bound to a concrete type. -
src/Parser/DeclarationNode.cc
r0b0a285 rc84dd61 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 12:34:05 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Thr Apr 20 11:46:00202313 // Update Count : 1 39311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jun 17 14:41:48 2023 13 // Update Count : 1405 14 14 // 15 15 … … 459 459 std::vector<ast::ptr<ast::Expr>> exprs; 460 460 buildList( expr, exprs ); 461 newnode->attributes.push_back( 462 new ast::Attribute( *name, std::move( exprs ) ) ); 461 newnode->attributes.push_back( new ast::Attribute( *name, std::move( exprs ) ) ); 463 462 delete name; 464 463 return newnode; … … 633 632 dst->basictype = src->basictype; 634 633 } else if ( src->basictype != DeclarationNode::NoBasicType ) 635 SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: " ); 634 SemanticError( yylloc, string( "multiple declaration types \"" ) + DeclarationNode::basicTypeNames[ dst->basictype ] + 635 "\" and \"" + DeclarationNode::basicTypeNames[ src->basictype ] + "\"." ); 636 636 637 637 if ( dst->complextype == DeclarationNode::NoComplexType ) { 638 638 dst->complextype = src->complextype; 639 639 } else if ( src->complextype != DeclarationNode::NoComplexType ) 640 SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: " ); 640 SemanticError( yylloc, string( "multiple declaration types \"" ) + DeclarationNode::complexTypeNames[ src->complextype ] + 641 "\" and \"" + DeclarationNode::complexTypeNames[ src->complextype ] + "\"." ); 641 642 642 643 if ( dst->signedness == DeclarationNode::NoSignedness ) { 643 644 dst->signedness = src->signedness; 644 645 } else if ( src->signedness != DeclarationNode::NoSignedness ) 645 SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: " ); 646 SemanticError( yylloc, string( "conflicting type specifier \"" ) + DeclarationNode::signednessNames[ dst->signedness ] + 647 "\" and \"" + DeclarationNode::signednessNames[ src->signedness ] + "\"." ); 646 648 647 649 if ( dst->length == DeclarationNode::NoLength ) { … … 650 652 dst->length = DeclarationNode::LongLong; 651 653 } else if ( src->length != DeclarationNode::NoLength ) 652 SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: " ); 654 SemanticError( yylloc, string( "conflicting type specifier \"" ) + DeclarationNode::lengthNames[ dst->length ] + 655 "\" and \"" + DeclarationNode::lengthNames[ src->length ] + "\"." ); 653 656 } // if 654 657 break; … … 718 721 719 722 DeclarationNode * DeclarationNode::addEnumBase( DeclarationNode * o ) { 720 if ( o && o ->type) {723 if ( o && o->type) { 721 724 type->base= o->type; 722 } 725 } // if 723 726 delete o; 724 727 return this; … … 1003 1006 } 1004 1007 1005 // If a typedef wraps an anonymous declaration, name the inner declaration 1006 // so it has a consistent name acrosstranslation units.1008 // If a typedef wraps an anonymous declaration, name the inner declaration so it has a consistent name across 1009 // translation units. 1007 1010 static void nameTypedefedDecl( 1008 1011 DeclarationNode * innerDecl, … … 1085 1088 } 1086 1089 1087 void buildList( DeclarationNode * firstNode, 1088 std::vector<ast::ptr<ast::Decl>> & outputList ) { 1090 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::Decl>> & outputList ) { 1089 1091 SemanticErrorException errors; 1090 1092 std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList ); -
src/Parser/ExpressionNode.cc
r0b0a285 rc84dd61 601 601 ast::Expr * build_cast( const CodeLocation & location, 602 602 DeclarationNode * decl_node, 603 ExpressionNode * expr_node ) { 603 ExpressionNode * expr_node, 604 ast::CastExpr::CastKind kind ) { 604 605 ast::Type * targetType = maybeMoveBuildType( decl_node ); 605 606 if ( dynamic_cast<ast::VoidType *>( targetType ) ) { … … 607 608 return new ast::CastExpr( location, 608 609 maybeMoveBuild( expr_node ), 609 ast::ExplicitCast );610 ast::ExplicitCast, kind ); 610 611 } else { 611 612 return new ast::CastExpr( location, 612 613 maybeMoveBuild( expr_node ), 613 614 targetType, 614 ast::ExplicitCast );615 ast::ExplicitCast, kind ); 615 616 } // if 616 617 } // build_cast -
src/Parser/ExpressionNode.h
r0b0a285 rc84dd61 69 69 ast::DimensionExpr * build_dimensionref( const CodeLocation &, const std::string * name ); 70 70 71 ast::Expr * build_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node );71 ast::Expr * build_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node, ast::CastExpr::CastKind kind = ast::CastExpr::Default ); 72 72 ast::Expr * build_keyword_cast( const CodeLocation &, ast::AggregateDecl::Aggregate target, ExpressionNode * expr_node ); 73 73 ast::Expr * build_virtual_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node ); -
src/Parser/parser.yy
r0b0a285 rc84dd61 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jun 7 14:32:28202313 // Update Count : 634 112 // Last Modified On : Sat Jun 17 18:53:24 2023 13 // Update Count : 6347 14 14 // 15 15 … … 931 931 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); } 932 932 | '(' RETURN type_no_function ')' cast_expression // CFA 933 { SemanticError( yylloc, "Return cast is currently unimplemented." ); $$ = nullptr; }933 { $$ = new ExpressionNode( build_cast( yylloc, $3, $5, ast::CastExpr::Return ) ); } 934 934 | '(' COERCE type_no_function ')' cast_expression // CFA 935 935 { SemanticError( yylloc, "Coerce cast is currently unimplemented." ); $$ = nullptr; } … … 1040 1040 // FIX ME: computes $1 twice 1041 1041 | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand 1042 { $$ = new ExpressionNode( build_cond( yylloc, $1, $1 , $4 ) ); }1042 { $$ = new ExpressionNode( build_cond( yylloc, $1, $1->clone(), $4 ) ); } 1043 1043 ; 1044 1044 -
src/ResolvExpr/Candidate.hpp
r0b0a285 rc84dd61 91 91 92 92 /// Holdover behaviour from old `findMinCost` -- xxx -- can maybe be eliminated? 93 /* 93 94 static inline void promoteCvtCost( CandidateList & candidates ) { 94 95 for ( CandidateRef & r : candidates ) { … … 96 97 } 97 98 } 99 */ 98 100 99 101 void print( std::ostream & os, const Candidate & cand, Indenter indent = {} ); -
src/ResolvExpr/CandidateFinder.cpp
r0b0a285 rc84dd61 38 38 #include "typeops.h" // for combos 39 39 #include "Unify.h" 40 #include "WidenMode.h" 40 41 #include "AST/Expr.hpp" 41 42 #include "AST/Node.hpp" … … 749 750 // attempt to narrow based on expected target type 750 751 const ast::Type * returnType = funcType->returns.front(); 751 if ( ! unify( 752 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen ) 753 ) { 754 // unification failed, do not pursue this candidate 755 return; 752 if ( selfFinder.strictMode ) { 753 if ( ! unifyExact( 754 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden() ) // xxx - is no widening correct? 755 ) { 756 // unification failed, do not pursue this candidate 757 return; 758 } 759 } 760 else { 761 if ( ! unify( 762 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen ) 763 ) { 764 // unification failed, do not pursue this candidate 765 return; 766 } 756 767 } 757 768 } … … 771 782 for (size_t i=0; i<nParams; ++i) { 772 783 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 773 if ( !instantiateArgument( location,784 if ( !instantiateArgument( location, 774 785 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 775 786 } … … 781 792 // matches 782 793 // no default args for indirect calls 783 if ( ! 794 if ( !instantiateArgument( location, 784 795 param, nullptr, args, results, genStart, symtab ) ) return; 785 796 } … … 874 885 875 886 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) { 876 addAggMembers( structInst, aggrExpr, *cand, Cost:: safe, "" );887 addAggMembers( structInst, aggrExpr, *cand, Cost::unsafe, "" ); 877 888 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 878 addAggMembers( unionInst, aggrExpr, *cand, Cost:: safe, "" );889 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 879 890 } 880 891 } … … 1007 1018 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) { 1008 1019 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 1020 // if (!selfFinder.allowVoid && function->returns.empty()) continue; 1009 1021 CandidateRef newFunc{ new Candidate{ *func } }; 1010 1022 newFunc->expr = … … 1018 1030 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) { 1019 1031 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 1020 CandidateRef newFunc { new Candidate{ *func } };1032 CandidateRef newFunc( new Candidate( *func ) ); 1021 1033 newFunc->expr = 1022 1034 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); … … 1060 1072 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } 1061 1073 1074 // only keep the best matching intrinsic result to match C semantics (no unexpected narrowing/widening) 1075 // TODO: keep one for each set of argument candidates? 1076 Cost intrinsicCost = Cost::infinity; 1077 CandidateList intrinsicResult; 1078 1062 1079 // Compute conversion costs 1063 1080 for ( CandidateRef & withFunc : found ) { … … 1082 1099 if ( cvtCost != Cost::infinity ) { 1083 1100 withFunc->cvtCost = cvtCost; 1084 candidates.emplace_back( std::move( withFunc ) ); 1085 } 1086 } 1101 withFunc->cost += cvtCost; 1102 auto func = withFunc->expr.strict_as<ast::ApplicationExpr>()->func.as<ast::VariableExpr>(); 1103 if (func && func->var->linkage == ast::Linkage::Intrinsic) { 1104 if (withFunc->cost < intrinsicCost) { 1105 intrinsicResult.clear(); 1106 intrinsicCost = withFunc->cost; 1107 } 1108 if (withFunc->cost == intrinsicCost) { 1109 intrinsicResult.emplace_back(std::move(withFunc)); 1110 } 1111 } 1112 else { 1113 candidates.emplace_back( std::move( withFunc ) ); 1114 } 1115 } 1116 } 1117 spliceBegin( candidates, intrinsicResult ); 1087 1118 found = std::move( candidates ); 1088 1119 1089 1120 // use a new list so that candidates are not examined by addAnonConversions twice 1090 CandidateList winners = findMinCost( found );1091 promoteCvtCost( winners );1121 // CandidateList winners = findMinCost( found ); 1122 // promoteCvtCost( winners ); 1092 1123 1093 1124 // function may return a struct/union value, in which case we need to add candidates 1094 1125 // for implicit conversions to each of the anonymous members, which must happen after 1095 1126 // `findMinCost`, since anon conversions are never the cheapest 1096 for ( const CandidateRef & c : winners) {1127 for ( const CandidateRef & c : found ) { 1097 1128 addAnonConversions( c ); 1098 1129 } 1099 spliceBegin( candidates, winners ); 1100 1101 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 1130 // would this be too slow when we don't check cost anymore? 1131 spliceBegin( candidates, found ); 1132 1133 if ( candidates.empty() && targetType && ! targetType->isVoid() && !selfFinder.strictMode ) { 1102 1134 // If resolution is unsuccessful with a target type, try again without, since it 1103 1135 // will sometimes succeed when it wouldn't with a target type binding. … … 1140 1172 1141 1173 CandidateFinder finder( context, tenv, toType ); 1174 if (toType->isVoid()) { 1175 finder.allowVoid = true; 1176 } 1177 if ( castExpr->kind == ast::CastExpr::Return ) { 1178 finder.strictMode = true; 1179 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1180 1181 // return casts are eliminated (merely selecting an overload, no actual operation) 1182 candidates = std::move(finder.candidates); 1183 } 1142 1184 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1143 1185 … … 1145 1187 1146 1188 CandidateList matches; 1189 Cost minExprCost = Cost::infinity; 1190 Cost minCastCost = Cost::infinity; 1147 1191 for ( CandidateRef & cand : finder.candidates ) { 1148 1192 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; … … 1176 1220 // count one safe conversion for each value that is thrown away 1177 1221 thisCost.incSafe( discardedValues ); 1178 CandidateRef newCand = std::make_shared<Candidate>( 1179 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1180 copy( cand->env ), std::move( open ), std::move( need ), cand->cost, 1181 cand->cost + thisCost ); 1182 inferParameters( newCand, matches ); 1183 } 1184 } 1185 1186 // select first on argument cost, then conversion cost 1187 CandidateList minArgCost = findMinCost( matches ); 1188 promoteCvtCost( minArgCost ); 1189 candidates = findMinCost( minArgCost ); 1222 // select first on argument cost, then conversion cost 1223 if ( cand->cost < minExprCost || ( cand->cost == minExprCost && thisCost < minCastCost ) ) { 1224 minExprCost = cand->cost; 1225 minCastCost = thisCost; 1226 matches.clear(); 1227 1228 1229 } 1230 // ambiguous case, still output candidates to print in error message 1231 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1232 CandidateRef newCand = std::make_shared<Candidate>( 1233 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1234 copy( cand->env ), std::move( open ), std::move( need ), cand->cost + thisCost); 1235 // currently assertions are always resolved immediately so this should have no effect. 1236 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1237 // we may need to revisit the logic. 1238 inferParameters( newCand, matches ); 1239 } 1240 // else skip, better alternatives found 1241 1242 } 1243 } 1244 candidates = std::move(matches); 1245 1246 //CandidateList minArgCost = findMinCost( matches ); 1247 //promoteCvtCost( minArgCost ); 1248 //candidates = findMinCost( minArgCost ); 1190 1249 } 1191 1250 … … 1453 1512 // candidates for true result 1454 1513 CandidateFinder finder2( context, tenv ); 1514 finder2.allowVoid = true; 1455 1515 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 1456 1516 if ( finder2.candidates.empty() ) return; … … 1458 1518 // candidates for false result 1459 1519 CandidateFinder finder3( context, tenv ); 1520 finder3.allowVoid = true; 1460 1521 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1461 1522 if ( finder3.candidates.empty() ) return; … … 1524 1585 void Finder::postvisit( const ast::ConstructorExpr * ctorExpr ) { 1525 1586 CandidateFinder finder( context, tenv ); 1587 finder.allowVoid = true; 1526 1588 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() ); 1527 1589 for ( CandidateRef & r : finder.candidates ) { … … 1640 1702 CandidateFinder finder( context, tenv, toType ); 1641 1703 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1704 1705 Cost minExprCost = Cost::infinity; 1706 Cost minCastCost = Cost::infinity; 1642 1707 for ( CandidateRef & cand : finder.candidates ) { 1643 1708 if (reason.code == NotFound) reason.code = NoMatch; … … 1677 1742 // count one safe conversion for each value that is thrown away 1678 1743 thisCost.incSafe( discardedValues ); 1679 CandidateRef newCand = std::make_shared<Candidate>( 1680 new ast::InitExpr{ 1681 initExpr->location, restructureCast( cand->expr, toType ), 1682 initAlt.designation }, 1683 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost ); 1684 inferParameters( newCand, matches ); 1744 if ( cand->cost < minExprCost || ( cand->cost == minExprCost && thisCost < minCastCost ) ) { 1745 minExprCost = cand->cost; 1746 minCastCost = thisCost; 1747 matches.clear(); 1748 } 1749 // ambiguous case, still output candidates to print in error message 1750 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1751 CandidateRef newCand = std::make_shared<Candidate>( 1752 new ast::InitExpr{ 1753 initExpr->location, 1754 restructureCast( cand->expr, toType ), 1755 initAlt.designation }, 1756 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1757 // currently assertions are always resolved immediately so this should have no effect. 1758 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1759 // we may need to revisit the logic. 1760 inferParameters( newCand, matches ); 1761 } 1685 1762 } 1686 1763 } … … 1688 1765 1689 1766 // select first on argument cost, then conversion cost 1690 CandidateList minArgCost = findMinCost( matches ); 1691 promoteCvtCost( minArgCost ); 1692 candidates = findMinCost( minArgCost ); 1767 // CandidateList minArgCost = findMinCost( matches ); 1768 // promoteCvtCost( minArgCost ); 1769 // candidates = findMinCost( minArgCost ); 1770 candidates = std::move(matches); 1693 1771 } 1694 1772 … … 1756 1834 auto found = selected.find( mangleName ); 1757 1835 if ( found != selected.end() ) { 1758 if ( newCand->cost < found->second.candidate->cost ) { 1836 // tiebreaking by picking the lower cost on CURRENT expression 1837 // NOTE: this behavior is different from C semantics. 1838 // Specific remediations are performed for C operators at postvisit(UntypedExpr). 1839 // Further investigations may take place. 1840 if ( newCand->cost < found->second.candidate->cost 1841 || (newCand->cost == found->second.candidate->cost && newCand->cvtCost < found->second.candidate->cvtCost) ) { 1759 1842 PRINT( 1760 1843 std::cerr << "cost " << newCand->cost << " beats " … … 1763 1846 1764 1847 found->second = PruneStruct{ newCand }; 1765 } else if ( newCand->cost == found->second.candidate->cost ) {1848 } else if ( newCand->cost == found->second.candidate->cost && newCand->cvtCost == found->second.candidate->cvtCost ) { 1766 1849 // if one of the candidates contains a deleted identifier, can pick the other, 1767 1850 // since deleted expressions should not be ambiguous if there is another option … … 1854 1937 */ 1855 1938 1856 if ( mode.prune ) { 1939 // optimization: don't prune for NameExpr since it never has cost 1940 if ( mode.prune && !dynamic_cast<const ast::NameExpr *>(expr) ) { 1857 1941 // trim candidates to single best one 1858 1942 PRINT( -
src/ResolvExpr/CandidateFinder.hpp
r0b0a285 rc84dd61 33 33 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 34 34 ast::ptr< ast::Type > targetType; ///< Target type for resolution 35 bool strictMode = false; ///< If set to true, requires targetType to be exact match (inside return cast) 36 bool allowVoid = false; ///< If set to true, allow void-returning function calls (only top level, cast to void and first in comma) 35 37 std::set< std::string > otypeKeys; /// different type may map to same key 36 38 -
src/ResolvExpr/CastCost.cc
r0b0a285 rc84dd61 234 234 if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) { 235 235 PRINT( std::cerr << "compatible!" << std::endl; ) 236 if (dynamic_cast<const ast::ZeroType *>(dst) || dynamic_cast<const ast::OneType *>(dst)) { 237 return Cost::spec; 238 } 236 239 return Cost::zero; 237 240 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) { -
src/ResolvExpr/CommonType.cc
r0b0a285 rc84dd61 697 697 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 698 698 #warning remove casts when `commonTypes` moved to new AST 699 700 /* 699 701 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ]; 700 702 if ( … … 706 708 result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers }; 707 709 } 710 */ 711 ast::BasicType::Kind kind; 712 if (basic->kind != basic2->kind && !widen.first && !widen.second) return; 713 else if (!widen.first) kind = basic->kind; // widen.second 714 else if (!widen.second) kind = basic2->kind; 715 else kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ]; 716 // xxx - what does qualifiers even do here?? 717 if ( (basic->qualifiers >= basic2->qualifiers || widen.first) 718 && (basic->qualifiers <= basic2->qualifiers || widen.second) ) { 719 result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers }; 720 } 721 708 722 } else if ( 709 723 dynamic_cast< const ast::ZeroType * >( type2 ) … … 712 726 #warning remove casts when `commonTypes` moved to new AST 713 727 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ]; 714 if ( 715 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 728 /* 729 if ( // xxx - what does qualifier even do here?? 730 ( ( basic->qualifiers >= type2->qualifiers ) 716 731 || widen.first ) 717 && ( (kind != basic->kind && basic->qualifiers <= type2->qualifiers )732 && ( ( /* kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 718 733 || widen.second ) 719 ) { 720 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 734 ) 735 */ 736 if (widen.second) { 737 result = new ast::BasicType{ basic->kind, basic->qualifiers | type2->qualifiers }; 721 738 } 722 739 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { … … 746 763 auto entry = open.find( *var ); 747 764 if ( entry != open.end() ) { 765 // if (tenv.lookup(*var)) { 748 766 ast::AssertionSet need, have; 749 767 if ( ! tenv.bindVar( -
src/ResolvExpr/ConversionCost.cc
r0b0a285 rc84dd61 702 702 703 703 cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env ); 704 705 // xxx - should qualifiers be considered in pass-by-value? 706 /* 704 707 if ( refType->base->qualifiers == dst->qualifiers ) { 705 708 cost.incReference(); … … 709 712 cost.incUnsafe(); 710 713 } 714 */ 715 cost.incReference(); 711 716 } 712 717 … … 792 797 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 793 798 } 799 // this has the effect of letting any expr such as x+0, x+1 to be typed 800 // the same as x, instead of at least int. are we willing to sacrifice this little 801 // bit of coherence with C? 802 // TODO: currently this does not work when no zero/one overloads exist. Find a fix for it. 803 // cost = Cost::zero; 794 804 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) { 795 805 cost = Cost::zero; 796 806 // +1 for zero_t ->, +1 for disambiguation 797 807 cost.incSafe( maxIntCost + 2 ); 808 // assuming 0p is supposed to be used for pointers? 798 809 } 799 810 } … … 804 815 cost = Cost::zero; 805 816 } else if ( const ast::BasicType * dstAsBasic = 806 dynamic_cast< const ast::BasicType * >( dst ) ) { 817 dynamic_cast< const ast::BasicType * >( dst ) ) { 807 818 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ]; 808 819 if ( -1 == tableResult ) { … … 813 824 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 814 825 } 826 827 // cost = Cost::zero; 815 828 } 816 829 } -
src/ResolvExpr/FindOpenVars.cc
r0b0a285 rc84dd61 21 21 #include "AST/Pass.hpp" 22 22 #include "AST/Type.hpp" 23 #include "AST/TypeEnvironment.hpp" 23 24 #include "Common/PassVisitor.h" 24 25 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType (ptr ... 25 26 #include "SynTree/Type.h" // for Type, Type::ForallList, ArrayType 27 28 #include <iostream> 26 29 27 30 namespace ResolvExpr { … … 102 105 ast::AssertionSet & need; 103 106 ast::AssertionSet & have; 107 ast::TypeEnvironment & env; 104 108 bool nextIsOpen; 105 109 106 110 FindOpenVars_new( 107 111 ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n, 108 ast::AssertionSet & h, FirstMode firstIsOpen )109 : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {}112 ast::AssertionSet & h, ast::TypeEnvironment & env, FirstMode firstIsOpen ) 113 : open( o ), closed( c ), need( n ), have( h ), env (env), nextIsOpen( firstIsOpen ) {} 110 114 111 115 void previsit( const ast::FunctionType * type ) { 112 116 // mark open/closed variables 113 117 if ( nextIsOpen ) { 118 // trying to remove this from resolver. 119 // occasionally used in other parts so not deleting right now. 120 121 // insert open variables unbound to environment. 122 env.add(type->forall); 123 114 124 for ( auto & decl : type->forall ) { 115 125 open[ *decl ] = ast::TypeData{ decl->base }; … … 137 147 void findOpenVars( 138 148 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 139 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {140 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen };149 ast::AssertionSet & need, ast::AssertionSet & have, ast::TypeEnvironment & env, FirstMode firstIsOpen ) { 150 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, env, firstIsOpen }; 141 151 type->accept( finder ); 152 153 if (!closed.empty()) { 154 std::cerr << "closed: "; 155 for (auto& i : closed) { 156 std::cerr << i.first.base->location << ":" << i.first.base->name << ' '; 157 } 158 std::cerr << std::endl; 159 } 142 160 } 143 161 } // namespace ResolvExpr -
src/ResolvExpr/FindOpenVars.h
r0b0a285 rc84dd61 33 33 void findOpenVars( 34 34 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 35 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen );35 ast::AssertionSet & need, ast::AssertionSet & have, ast::TypeEnvironment & env, FirstMode firstIsOpen ); 36 36 } // namespace ResolvExpr 37 37 -
src/ResolvExpr/Resolver.cc
r0b0a285 rc84dd61 1011 1011 ast::TypeEnvironment env; 1012 1012 CandidateFinder finder( context, env ); 1013 finder.allowVoid = true; 1013 1014 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 1014 1015 --recursion_level; … … 1054 1055 1055 1056 // promote candidate.cvtCost to .cost 1056 promoteCvtCost( winners );1057 // promoteCvtCost( winners ); 1057 1058 1058 1059 // produce ambiguous errors, if applicable -
src/ResolvExpr/SatisfyAssertions.cpp
r0b0a285 rc84dd61 16 16 #include "SatisfyAssertions.hpp" 17 17 18 #include <iostream> 18 19 #include <algorithm> 19 20 #include <cassert> … … 45 46 #include "SymTab/Mangler.h" 46 47 48 49 47 50 namespace ResolvExpr { 48 51 … … 65 68 ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs ) 66 69 : cdata( c ), adjType( at ), env( std::move( e ) ), have( std::move( h ) ), 67 need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {} 70 need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) { 71 if (!have.empty()) { 72 // std::cerr << c.id->location << ':' << c.id->name << std::endl; // I think this was debugging code so I commented it 73 } 74 } 68 75 }; 69 76 … … 139 146 }; 140 147 141 /// Adds a captured assertion to the symbol table 142 void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) { 143 for ( auto & i : have ) { 144 if ( i.second.isUsed ) { symtab.addId( i.first->var ); } 145 } 146 } 148 enum AssertionResult {Fail, Skip, Success} ; 147 149 148 150 /// Binds a single assertion, updating satisfaction state … … 155 157 "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 156 158 157 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->c vtCost );159 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cost ); 158 160 varExpr->result = match.adjType; 159 161 if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); } … … 165 167 166 168 /// Satisfy a single assertion 167 bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) {169 AssertionResult satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool skipUnbound = false) { 168 170 // skip unused assertions 169 if ( ! assn.second.isUsed ) return true; 171 // static unsigned int cnt = 0; // I think this was debugging code so I commented it 172 if ( ! assn.second.isUsed ) return AssertionResult::Success; 173 174 // if (assn.first->var->name[1] == '|') std::cerr << ++cnt << std::endl; // I think this was debugging code so I commented it 170 175 171 176 // find candidates that unify with the desired type 172 AssnCandidateList matches ;177 AssnCandidateList matches, inexactMatches; 173 178 174 179 std::vector<ast::SymbolTable::IdData> candidates; … … 179 184 .strict_as<ast::FunctionType>()->params[0] 180 185 .strict_as<ast::ReferenceType>()->base; 181 sat.cand->env.apply(thisArgType); 186 // sat.cand->env.apply(thisArgType); 187 188 if (auto inst = thisArgType.as<ast::TypeInstType>()) { 189 auto cls = sat.cand->env.lookup(*inst); 190 if (cls && cls->bound) thisArgType = cls->bound; 191 } 182 192 183 193 std::string otypeKey = ""; 184 194 if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer; 185 195 else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams); 186 else if (skipUnbound) return false;196 else if (skipUnbound) return AssertionResult::Skip; 187 197 188 198 candidates = sat.symtab.specialLookupId(kind, otypeKey); … … 212 222 213 223 ast::OpenVarSet closed; 214 findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed ); 215 findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen ); 216 if ( allowConversion ) { 224 // findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed ); 225 findOpenVars( adjType, newOpen, closed, newNeed, have, newEnv, FirstOpen ); 226 ast::TypeEnvironment tempNewEnv {newEnv}; 227 228 if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) { 229 // set up binding slot for recursive assertions 230 ast::UniqueId crntResnSlot = 0; 231 if ( ! newNeed.empty() ) { 232 crntResnSlot = ++globalResnSlot; 233 for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; } 234 } 235 236 matches.emplace_back( 237 cdata, adjType, std::move( tempNewEnv ), std::move( have ), std::move( newNeed ), 238 std::move( newOpen ), crntResnSlot ); 239 } 240 else if ( matches.empty() ) { 241 // restore invalidated env 242 // newEnv = sat.cand->env; 243 // newNeed.clear(); 217 244 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) { 218 245 // set up binding slot for recursive assertions … … 223 250 } 224 251 225 matches.emplace_back(252 inexactMatches.emplace_back( 226 253 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ), 227 254 std::move( newOpen ), crntResnSlot ); 228 255 } 229 256 } 230 else {231 if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {232 // set up binding slot for recursive assertions233 ast::UniqueId crntResnSlot = 0;234 if ( ! newNeed.empty() ) {235 crntResnSlot = ++globalResnSlot;236 for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }237 }238 239 matches.emplace_back(240 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),241 std::move( newOpen ), crntResnSlot );242 }243 }244 257 } 245 258 246 259 // break if no satisfying match 247 if ( matches.empty() ) return false; 260 if ( matches.empty() ) matches = std::move(inexactMatches); 261 if ( matches.empty() ) return AssertionResult::Fail; 248 262 249 263 // defer if too many satisfying matches 250 264 if ( matches.size() > 1 ) { 251 265 sat.deferred.emplace_back( assn.first, assn.second, std::move( matches ) ); 252 return true;266 return AssertionResult::Success; 253 267 } 254 268 255 269 // otherwise bind unique match in ongoing scope 256 270 AssnCandidate & match = matches.front(); 257 addToSymbolTable( match.have, sat.symtab );271 // addToSymbolTable( match.have, sat.symtab ); 258 272 sat.newNeed.insert( match.need.begin(), match.need.end() ); 259 273 sat.cand->env = std::move( match.env ); … … 261 275 262 276 bindAssertion( assn.first, assn.second, sat.cand, match, sat.inferred ); 263 return true;277 return AssertionResult::Success; 264 278 } 265 279 … … 438 452 // for each current mutually-compatible set of assertions 439 453 for ( SatState & sat : sats ) { 440 bool allowConversion = false;441 454 // stop this branch if a better option is already found 442 455 auto it = thresholds.find( pruneKey( *sat.cand ) ); … … 447 460 for (unsigned resetCount = 0; ; ++resetCount) { 448 461 ast::AssertionList next; 449 resetTyVarRenaming();450 462 // make initial pass at matching assertions 451 463 for ( auto & assn : sat.need ) { 464 resetTyVarRenaming(); 452 465 // fail early if any assertion is not satisfiable 453 if ( ! satisfyAssertion( assn, sat, allowConversion, !next.empty() ) ) { 454 next.emplace_back(assn); 455 // goto nextSat; 456 } 457 } 458 // success 459 if (next.empty()) break; 460 // fail if nothing resolves 461 else if (next.size() == sat.need.size()) { 462 if (allowConversion) { 466 auto result = satisfyAssertion( assn, sat, !next.empty() ); 467 if ( result == AssertionResult::Fail ) { 463 468 Indenter tabs{ 3 }; 464 469 std::ostringstream ss; … … 466 471 print( ss, *sat.cand, ++tabs ); 467 472 ss << (tabs-1) << "Could not satisfy assertion:\n"; 468 ast::print( ss, next[0].first, tabs );473 ast::print( ss, assn.first, tabs ); 469 474 470 475 errors.emplace_back( ss.str() ); 471 476 goto nextSat; 472 477 } 473 474 else { 475 allowConversion = true; 476 continue; 477 } 478 } 479 allowConversion = false; 478 else if ( result == AssertionResult::Skip ) { 479 next.emplace_back(assn); 480 // goto nextSat; 481 } 482 } 483 // success 484 if (next.empty()) break; 485 480 486 sat.need = std::move(next); 481 487 } … … 531 537 sat.cand->expr, std::move( compat.env ), std::move( compat.open ), 532 538 ast::AssertionSet{} /* need moved into satisfaction state */, 533 sat.cand->cost , sat.cand->cvtCost);539 sat.cand->cost ); 534 540 535 541 ast::AssertionSet nextNewNeed{ sat.newNeed }; … … 544 550 for ( DeferRef r : compat.assns ) { 545 551 AssnCandidate match = r.match; 546 addToSymbolTable( match.have, nextSymtab );552 // addToSymbolTable( match.have, nextSymtab ); 547 553 nextNewNeed.insert( match.need.begin(), match.need.end() ); 548 554 -
src/ResolvExpr/Unify.cc
r0b0a285 rc84dd61 160 160 env.apply( newSecond ); 161 161 162 findOpenVars( newFirst, open, closed, need, have, FirstClosed );163 findOpenVars( newSecond, open, closed, need, have, FirstOpen );162 // findOpenVars( newFirst, open, closed, need, have, FirstClosed ); 163 findOpenVars( newSecond, open, closed, need, have, newEnv, FirstOpen ); 164 164 165 165 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() ); … … 964 964 // check that the other type is compatible and named the same 965 965 auto otherInst = dynamic_cast< const XInstType * >( other ); 966 if (otherInst && inst->name == otherInst->name) this->result = otherInst; 966 if (otherInst && inst->name == otherInst->name) 967 this->result = otherInst; 967 968 return otherInst; 968 969 } … … 1049 1050 1050 1051 void postvisit( const ast::TypeInstType * typeInst ) { 1051 assert( open.find( *typeInst ) == open.end() ); 1052 handleRefType( typeInst, type2 ); 1052 // assert( open.find( *typeInst ) == open.end() ); 1053 auto otherInst = dynamic_cast< const ast::TypeInstType * >( type2 ); 1054 if (otherInst && typeInst->name == otherInst->name) 1055 this->result = otherInst; 1056 // return otherInst; 1053 1057 } 1054 1058 … … 1161 1165 ) { 1162 1166 ast::OpenVarSet closed; 1163 findOpenVars( type1, open, closed, need, have, FirstClosed );1164 findOpenVars( type2, open, closed, need, have, FirstOpen );1167 // findOpenVars( type1, open, closed, need, have, FirstClosed ); 1168 findOpenVars( type2, open, closed, need, have, env, FirstOpen ); 1165 1169 return unifyInexact( 1166 1170 type1, type2, env, need, have, open, WidenMode{ true, true }, common ); … … 1179 1183 entry1 = var1 ? open.find( *var1 ) : open.end(), 1180 1184 entry2 = var2 ? open.find( *var2 ) : open.end(); 1181 bool isopen1 = entry1 != open.end(); 1182 bool isopen2 = entry2 != open.end(); 1183 1185 // bool isopen1 = entry1 != open.end(); 1186 // bool isopen2 = entry2 != open.end(); 1187 bool isopen1 = var1 && env.lookup(*var1); 1188 bool isopen2 = var2 && env.lookup(*var2); 1189 1190 /* 1184 1191 if ( isopen1 && isopen2 ) { 1185 1192 if ( entry1->second.kind != entry2->second.kind ) return false; … … 1190 1197 return env.bindVar( var1, type2, entry1->second, need, have, open, widen ); 1191 1198 } else if ( isopen2 ) { 1192 return env.bindVar( var2, type1, entry2->second, need, have, open, widen ); 1193 } else { 1199 return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab ); 1200 } */ 1201 if ( isopen1 && isopen2 ) { 1202 if ( var1->base->kind != var2->base->kind ) return false; 1203 return env.bindVarToVar( 1204 var1, var2, ast::TypeData{ var1->base->kind, var1->base->sized||var2->base->sized }, need, have, 1205 open, widen ); 1206 } else if ( isopen1 ) { 1207 return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen ); 1208 } else if ( isopen2 ) { 1209 return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen ); 1210 }else { 1194 1211 return ast::Pass<Unify_new>::read( 1195 1212 type1, type2, env, need, have, open, widen ); 1196 1213 } 1214 1197 1215 } 1198 1216 -
src/SynTree/Expression.cc
r0b0a285 rc84dd61 267 267 } 268 268 269 CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {269 CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated, CastKind kind ) : arg(arg), isGenerated( isGenerated ), kind( kind ) { 270 270 set_result(toType); 271 271 } 272 272 273 CastExpr::CastExpr( Expression * arg, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {273 CastExpr::CastExpr( Expression * arg, bool isGenerated, CastKind kind ) : arg(arg), isGenerated( isGenerated ), kind( kind ) { 274 274 set_result( new VoidType( Type::Qualifiers() ) ); 275 275 } 276 276 277 CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ) {277 CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ), kind( other.kind ) { 278 278 } 279 279 -
src/SynTree/Expression.h
r0b0a285 rc84dd61 271 271 bool isGenerated = true; 272 272 273 CastExpr( Expression * arg, bool isGenerated = true ); 274 CastExpr( Expression * arg, Type * toType, bool isGenerated = true ); 273 enum CastKind { 274 Default, // C 275 Coerce, // reinterpret cast 276 Return // overload selection 277 }; 278 279 CastKind kind = Default; 280 281 CastExpr( Expression * arg, bool isGenerated = true, CastKind kind = Default ); 282 CastExpr( Expression * arg, Type * toType, bool isGenerated = true, CastKind kind = Default ); 275 283 CastExpr( Expression * arg, void * ) = delete; // prevent accidentally passing pointers for isGenerated in the first constructor 276 284 CastExpr( const CastExpr & other ); -
src/Tuples/TupleAssignment.cc
r0b0a285 rc84dd61 679 679 680 680 ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env ); 681 finder.allowVoid = true; 681 682 682 683 try { -
src/Validate/Autogen.cpp
r0b0a285 rc84dd61 321 321 void FuncGenerator::produceDecl( const ast::FunctionDecl * decl ) { 322 322 assert( nullptr != decl->stmts ); 323 assert( decl->type_params.size() == getGenericParams( type ).size() ); 323 324 324 325 definitions.push_back( decl ); … … 356 357 decl->init = nullptr; 357 358 splice( assertions, decl->assertions ); 358 oldToNew.emplace( std::make_pair( old_param, decl ));359 oldToNew.emplace( old_param, decl ); 359 360 type_params.push_back( decl ); 360 361 } … … 522 523 InitTweak::InitExpander_new srcParam( src ); 523 524 // Assign to destination. 524 ast:: Expr * dstSelect = new ast::MemberExpr(525 ast::MemberExpr * dstSelect = new ast::MemberExpr( 525 526 location, 526 527 field, … … 574 575 } 575 576 576 ast:: Expr * srcSelect = (srcParam) ? new ast::MemberExpr(577 ast::MemberExpr * srcSelect = (srcParam) ? new ast::MemberExpr( 577 578 location, field, new ast::VariableExpr( location, srcParam ) 578 579 ) : nullptr; -
src/Validate/GenericParameter.cpp
r0b0a285 rc84dd61 120 120 } 121 121 122 struct ValidateGenericParamsCore : public ast::WithCodeLocation { 122 bool isSizedPolymorphic( const ast::AggregateDecl * decl ) { 123 for ( const auto & param : decl->params ) { 124 if ( param->sized ) return true; 125 } 126 return false; 127 } 128 129 struct ValidateGenericParamsCore : 130 public ast::WithCodeLocation, public ast::WithGuards { 131 // Generic parameter filling and checks: 123 132 const ast::StructInstType * previsit( const ast::StructInstType * type ) { 124 133 assert( location ); … … 129 138 assert( location ); 130 139 return validateGeneric( *location, type ); 140 } 141 142 // Check parameter and bitfield combinations: 143 bool insideSized = false; 144 void previsit( const ast::StructDecl * decl ) { 145 if ( isSizedPolymorphic( decl ) && !insideSized ) { 146 GuardValue( insideSized ) = true; 147 } 148 } 149 150 void previsit( const ast::UnionDecl * decl ) { 151 if ( isSizedPolymorphic( decl ) && !insideSized ) { 152 GuardValue( insideSized ) = true; 153 } 154 } 155 156 void previsit( const ast::ObjectDecl * decl ) { 157 if ( insideSized && decl->bitfieldWidth ) { 158 SemanticError( decl->location, decl, 159 "Cannot have bitfields inside a sized polymorphic structure." ); 160 } 131 161 } 132 162 }; -
src/Validate/LinkReferenceToTypes.cpp
r0b0a285 rc84dd61 84 84 // Just linking in the node. 85 85 auto mut = ast::mutate( type ); 86 mut->base = const_cast<ast::EnumDecl *>( decl );86 mut->base = decl; 87 87 type = mut; 88 88 } … … 101 101 // Just linking in the node. 102 102 auto mut = ast::mutate( type ); 103 mut->base = const_cast<ast::StructDecl *>( decl );103 mut->base = decl; 104 104 type = mut; 105 105 } … … 118 118 // Just linking in the node. 119 119 auto mut = ast::mutate( type ); 120 mut->base = const_cast<ast::UnionDecl *>( decl );120 mut->base = decl; 121 121 type = mut; 122 122 } … … 141 141 142 142 // Just linking in the node. 143 mut->base = const_cast<ast::TraitDecl *>( decl );143 mut->base = decl; 144 144 145 145 // Need to carry over the 'sized' status of each decl in the instance. … … 203 203 } 204 204 205 // The following section206 207 205 ForwardEnumsType::iterator fwds = forwardEnums.find( decl->name ); 208 206 if ( fwds != forwardEnums.end() ) { -
src/Virtual/VirtualDtor.cpp
r0b0a285 rc84dd61 146 146 147 147 CompoundStmt * dtorBody = mutate( decl->stmts.get() ); 148 // Adds the following to the endof any actor/message dtor:148 // Adds the following to the start of any actor/message dtor: 149 149 // __CFA_dtor_shutdown( this ); 150 dtorBody->push_front( new ExprStmt( 151 decl->location, 152 new UntypedExpr ( 153 decl->location, 154 new NameExpr( decl->location, "__CFA_dtor_shutdown" ), 155 { 156 new NameExpr( decl->location, decl->params.at(0)->name ) 157 } 158 ) 159 )); 150 dtorBody->push_front( 151 new IfStmt( decl->location, 152 new UntypedExpr ( 153 decl->location, 154 new NameExpr( decl->location, "__CFA_dtor_shutdown" ), 155 { 156 new NameExpr( decl->location, decl->params.at(0)->name ) 157 } 158 ), 159 new ReturnStmt( decl->location, nullptr ) 160 ) 161 ); 160 162 return; 161 163 } -
src/main.cc
r0b0a285 rc84dd61 28 28 #include <list> // for list 29 29 #include <string> // for char_traits, operator<< 30 31 using namespace std;32 30 33 31 #include "AST/Convert.hpp" … … 88 86 #include "Virtual/VirtualDtor.hpp" // for implementVirtDtors 89 87 88 using namespace std; 89 90 90 static void NewPass( const char * const name ) { 91 91 Stats::Heap::newPass( name ); … … 335 335 336 336 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit ); 337 PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit ); 337 338 PASS( "Hoist Struct", Validate::hoistStruct, transUnit ); 338 PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit );339 339 PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit ); 340 340 PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit );
Note:
See TracChangeset
for help on using the changeset viewer.