- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Validate/ImplementEnumFunc.cpp
rc333ed2 reb7586e 28 28 proto_linkage{ast::Linkage::Cforall} {} 29 29 30 void genAttrFunctions(); 31 void genSuccPredPosn(); 32 // void genSuccPredDecl(); 33 34 void appendReturnThis(ast::FunctionDecl* decl) { 35 assert(1 <= decl->params.size()); 36 assert(1 == decl->returns.size()); 37 assert(decl->stmts); 38 39 const CodeLocation& location = (decl->stmts->kids.empty()) 40 ? decl->stmts->location 41 : decl->stmts->kids.back()->location; 42 const ast::DeclWithType* thisParam = decl->params.front(); 43 decl->stmts.get_and_mutate()->push_back(new ast::ReturnStmt( 44 location, new ast::VariableExpr(location, thisParam))); 45 } 46 void genAttrStandardFuncs() { 47 ast::FunctionDecl* (EnumAttrFuncGenerator::*standardProtos[4])() 48 const = {&EnumAttrFuncGenerator::genCtorProto, 49 &EnumAttrFuncGenerator::genCopyProto, 50 &EnumAttrFuncGenerator::genDtorProto, 51 &EnumAttrFuncGenerator::genAssignProto}; 52 for (auto& generator : standardProtos) { 53 ast::FunctionDecl* decl = (this->*generator)(); 54 produceForwardDecl(decl); 55 genFuncBody(decl); 56 if (CodeGen::isAssignment(decl->name)) { 57 appendReturnThis(decl); 58 } 59 produceDecl(decl); 60 } 61 } 62 30 63 private: 31 64 const CodeLocation& getLocation() const { return decl->location; } … … 40 73 const ast::Decl* getDecl() const { return decl; } 41 74 42 // Implement Bounded trait 43 void genBoundedFunctions(); 44 ast::FunctionDecl* genBoundedProto(const char *) const; 45 void genBoundedBody(ast::FunctionDecl* func) const; 46 47 // Implement Serial trait 75 // Implement Bounded trait for enum 76 void genBoundedFunctions(); 77 // Implement Serial trait for enum 48 78 void genSerialTraitFuncs(); 49 ast::FunctionDecl* genFromIntProto() const; 50 ast::FunctionDecl* genFromInstanceProto() const; 51 ast::FunctionDecl* genInstToInstFuncProto(const char* func) const; 52 void genFromIntBody(ast::FunctionDecl *) const; 53 void genFromInstanceBody(ast::FunctionDecl *) const; 54 void genSuccPredBody(ast::FunctionDecl *, const char *) const; 55 56 // Implement TypedEnum trait 57 void genTypedEnumFuncs(); 58 void genTypedEnumFunction(const ast::EnumAttribute attr); 79 80 // Bounded trait 81 ast::FunctionDecl* genLowerBoundProto() const; 82 ast::FunctionDecl* genUpperBoundProto() const; 83 void genLowerBoundBody(ast::FunctionDecl* func) const; 84 void genUpperBoundBody(ast::FunctionDecl* func) const; 85 59 86 ast::FunctionDecl* genPosnProto() const; 60 87 ast::FunctionDecl* genLabelProto() const; 61 88 ast::FunctionDecl* genValueProto() const; 62 void genValueOrLabelBody( 63 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const; 64 void genPosnBody(ast::FunctionDecl* func) const; 65 89 90 // Serial trait 91 ast::FunctionDecl* genFromIntProto() const; 92 ast::FunctionDecl* genFromInstanceProto() const; 93 ast::FunctionDecl* genSuccProto() const; 94 ast::FunctionDecl* genPredProto() const; 95 96 void genFromIntBody(ast::FunctionDecl *) const; 97 void genFromInstanceBody(ast::FunctionDecl *) const; 66 98 //////////////// 99 100 ast::FunctionDecl* genSuccPosProto() const; 101 ast::FunctionDecl* genPredPosProto() const; 67 102 68 103 // --------------------------------------------------- … … 86 121 } 87 122 123 /// E = EnumAttrType<T>` 124 /// `void ?{}(E & _dst)`. 125 ast::FunctionDecl* genCtorProto() const { 126 return genProto("?{}", {dstParam()}, {}); 127 } 128 129 /// void ?{}(E & _dst, E _src)`. 130 ast::FunctionDecl* genCopyProto() const { 131 return genProto("?{}", {dstParam(), srcParam()}, {}); 132 } 133 134 ///`void ^?{}(E & _dst)`. 135 ast::FunctionDecl* genDtorProto() const { 136 // The destructor must be mutex on a concurrent type. 137 return genProto("^?{}", {dstParam()}, {}); 138 } 139 140 /// `E ?{}(E & _dst, E _src)`. 141 ast::FunctionDecl* genAssignProto() const { 142 // Only the name is different, so just reuse the generation function. 143 auto retval = srcParam(); 144 retval->name = "_ret"; 145 return genProto("?=?", {dstParam(), srcParam()}, {retval}); 146 } 147 148 void genFuncBody(ast::FunctionDecl* func) { 149 const CodeLocation& location = func->location; 150 auto& params = func->params; 151 if (InitTweak::isCopyConstructor(func) || 152 InitTweak::isAssignment(func)) { 153 assert(2 == params.size()); 154 auto dstParam = params.front().strict_as<ast::ObjectDecl>(); 155 auto srcParam = params.back().strict_as<ast::ObjectDecl>(); 156 func->stmts = genCopyBody(location, dstParam, srcParam); 157 } else { 158 assert(1 == params.size()); 159 // Default constructor and destructor is empty. 160 func->stmts = new ast::CompoundStmt(location); 161 // Add unused attribute to parameter to silence warnings. 162 addUnusedAttribute(params.front()); 163 164 // Just an extra step to make the forward and declaration match. 165 if (forwards.empty()) return; 166 ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>( 167 forwards.back().get_and_mutate()); 168 addUnusedAttribute(fwd->params.front()); 169 } 170 } 171 172 const ast::CompoundStmt* genCopyBody( const CodeLocation& location, 173 const ast::ObjectDecl* dstParam, const ast::ObjectDecl* srcParam) { 174 return new ast::CompoundStmt( 175 location, 176 {new ast::ExprStmt( 177 location, 178 new ast::UntypedExpr( 179 location, new ast::NameExpr(location, "__builtin_memcpy"), 180 { 181 new ast::AddressExpr( location, 182 new ast::VariableExpr( location, dstParam ) ), 183 new ast::AddressExpr( location, 184 new ast::VariableExpr( location, srcParam ) ), 185 new ast::SizeofExpr( location, srcParam->type ), 186 }))}); 187 } 188 189 void genDtorBody(ast::FunctionDecl* func) { 190 const CodeLocation& location = func->location; 191 auto& params = func->params; 192 assert(1 == params.size()); 193 func->stmts = new ast::CompoundStmt(location); 194 addUnusedAttribute(params.front()); 195 196 // Just an extra step to make the forward and declaration match. 197 if (forwards.empty()) return; 198 ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>( 199 forwards.back().get_and_mutate()); 200 addUnusedAttribute(fwd->params.front()); 201 } 202 203 // ast::FunctionDecl* 88 204 // ---------------------------------------------------- 205 206 ast::FunctionDecl* genSuccPredFunc(bool succ); 89 207 90 208 const ast::Init* getAutoInit(const ast::Init* prev) const; … … 96 214 const ast::EnumAttribute attr, const CodeLocation& location, 97 215 std::vector<ast::ptr<ast::Init>>& inits) const; 216 void genValueOrLabelBody( 217 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const; 218 void genPosnBody(ast::FunctionDecl* func) const; 219 void genAttributesDecls(const ast::EnumAttribute attr); 98 220 }; 99 221 … … 252 374 } 253 375 254 void EnumAttrFuncGenerator::genSuccPredBody(ast::FunctionDecl * func, const char* opt) const {255 auto params = func->params;256 assert( params.size() == 1 );257 auto param = params.front();258 auto enumToInt = new ast::CastExpr(259 func->location,260 new ast::VariableExpr(func->location, param),261 new ast::BasicType(ast::BasicKind::UnsignedInt),262 ast::GeneratedFlag::ExplicitCast263 );264 ast::UntypedExpr* addOneExpr = ast::UntypedExpr::createCall( func->location,265 opt,266 {enumToInt,267 ast::ConstantExpr::from_int(func->location, 1)}268 );269 auto intToEnum = new ast::CastExpr(270 func->location,271 addOneExpr,272 new ast::EnumInstType( decl ),273 ast::GeneratedFlag::ExplicitCast274 );275 func->stmts = new ast::CompoundStmt(276 func->location, {277 new ast::ReturnStmt(278 func->location,279 intToEnum280 )281 }282 );283 }284 285 286 376 void EnumAttrFuncGenerator::genSerialTraitFuncs() { 287 ast::FunctionDecl * protos[4] = { 288 genFromIntProto(), 289 genFromInstanceProto(), 290 genInstToInstFuncProto("succ"), 291 genInstToInstFuncProto("pred") 292 }; 293 for (auto& proto: protos) produceForwardDecl(proto); 294 genFromIntBody(protos[0]); 295 genFromInstanceBody(protos[1]); 296 genSuccPredBody(protos[2], "?+?"); 297 genSuccPredBody(protos[3], "?-?"); 298 } 299 300 ast::FunctionDecl* EnumAttrFuncGenerator::genInstToInstFuncProto(const char * func) const { 301 return genProto( 302 func, 377 auto fromIntProto = genFromIntProto(); 378 produceForwardDecl(fromIntProto); 379 genFromIntBody(fromIntProto); 380 produceDecl(fromIntProto); 381 382 auto fromInstanceProto = genFromInstanceProto(); 383 produceForwardDecl(fromInstanceProto); 384 genFromInstanceBody(fromInstanceProto); 385 produceDecl(fromInstanceProto); 386 387 auto succProto = genSuccProto(); 388 auto predProto = genPredProto(); 389 produceForwardDecl(succProto); 390 produceForwardDecl(predProto); 391 } 392 393 ast::FunctionDecl* EnumAttrFuncGenerator::genSuccProto() const { 394 return genProto( 395 "succ", 303 396 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 304 397 {new ast::ObjectDecl(getLocation(), "_ret", … … 306 399 } 307 400 308 ast::FunctionDecl* EnumAttrFuncGenerator::genBoundedProto(const char * func) const { 309 return genProto(func, {}, { 401 ast::FunctionDecl* EnumAttrFuncGenerator::genPredProto() const { 402 return genProto( 403 "pred", 404 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 405 {new ast::ObjectDecl(getLocation(), "_ret", 406 new ast::EnumInstType(decl))}); 407 } 408 409 ast::FunctionDecl* EnumAttrFuncGenerator::genLowerBoundProto() const { 410 return genProto("lowerBound", {}, { 310 411 new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl)) 311 412 }); 312 413 } 313 414 314 void EnumAttrFuncGenerator::genBoundedBody(ast::FunctionDecl* func) const { 415 ast::FunctionDecl* EnumAttrFuncGenerator::genUpperBoundProto() const { 416 return genProto("upperBound", {}, { 417 new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl)) 418 }); 419 } 420 421 void EnumAttrFuncGenerator::genLowerBoundBody(ast::FunctionDecl* func) const { 315 422 const CodeLocation & loc = func->location; 316 auto mem = func->name=="lowerBound"? decl->members.front() : decl->members.back(); 423 auto mem = decl->members.front(); 424 // auto expr = new ast::QualifiedNameExpr( loc, decl, mem->name ); 425 // expr->result = new ast::EnumInstType( decl ); 317 426 auto expr = new ast::NameExpr( loc, mem->name ); 318 427 func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)}); 319 428 } 320 429 430 void EnumAttrFuncGenerator::genUpperBoundBody(ast::FunctionDecl* func) const { 431 const CodeLocation & loc = func->location; 432 auto mem = decl->members.back(); 433 auto expr = new ast::NameExpr( loc, mem->name ); 434 // expr->result = new ast::EnumInstType( decl ); 435 func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)}); 436 } 437 321 438 void EnumAttrFuncGenerator::genBoundedFunctions() { 322 ast::FunctionDecl * boundedProtos[2] = {genBoundedProto("upperBound"), genBoundedProto("lowerBound")}; 323 for (auto & protos: boundedProtos) { 324 produceForwardDecl(protos); 325 genBoundedBody(protos); 326 produceDecl(protos); 327 } 439 ast::FunctionDecl * upperDecl = genUpperBoundProto(); 440 produceForwardDecl(upperDecl); 441 genUpperBoundBody(upperDecl); 442 produceDecl(upperDecl); 443 444 ast::FunctionDecl * lowerDecl = genLowerBoundProto(); 445 produceForwardDecl(lowerDecl); 446 genLowerBoundBody(lowerDecl); 447 produceDecl(lowerDecl); 328 448 } 329 449 330 450 inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) { 331 451 return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn); 452 } 453 454 ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPosProto() const { 455 return genProto( 456 "_successor_", 457 {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))}, 458 {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))} 459 ); 460 } 461 462 ast::FunctionDecl* EnumAttrFuncGenerator::genPredPosProto() const { 463 return genProto( 464 "_predessor_", 465 {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))}, 466 {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))} 467 ); 332 468 } 333 469 … … 375 511 } 376 512 377 void EnumAttrFuncGenerator::gen TypedEnumFunction(const ast::EnumAttribute attr) {513 void EnumAttrFuncGenerator::genAttributesDecls(const ast::EnumAttribute attr) { 378 514 if (attr == ast::EnumAttribute::Value || 379 515 attr == ast::EnumAttribute::Label) { 380 // TypedEnum's backing arrays381 516 std::vector<ast::ptr<ast::Init>> inits = 382 517 attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit(); … … 399 534 } 400 535 401 void EnumAttrFuncGenerator::genTypedEnumFuncs() { 402 if (decl->base) genTypedEnumFunction(ast::EnumAttribute::Value); 403 genTypedEnumFunction(ast::EnumAttribute::Label); 404 genTypedEnumFunction(ast::EnumAttribute::Posn); 536 ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPredFunc(bool succ) { 537 ast::FunctionDecl* funcDecl = succ ? genSuccPosProto() : genPredPosProto(); 538 produceForwardDecl(funcDecl); 539 540 const CodeLocation& location = getLocation(); 541 542 auto& params = funcDecl->params; 543 assert(params.size() == 1); 544 auto param = params.front().strict_as<ast::ObjectDecl>(); 545 546 547 auto rets = funcDecl->returns; 548 assert(params.size() == 1); 549 auto ret = rets.front().strict_as<ast::ObjectDecl>(); 550 auto retType = ret->type.strict_as<ast::EnumAttrType>(); 551 552 auto addOneExpr = ast::UntypedExpr::createCall( location, 553 succ? "?+?": "?-?", 554 {new ast::VariableExpr(location, param), 555 ast::ConstantExpr::from_int(location, 1)} 556 ); 557 558 funcDecl->stmts = new ast::CompoundStmt( 559 location, { 560 new ast::ReturnStmt( 561 location, 562 new ast::CastExpr(location, addOneExpr, retType) 563 ) 564 } 565 ); 566 567 return funcDecl; 568 } 569 570 void EnumAttrFuncGenerator::genAttrFunctions() { 571 genAttributesDecls(ast::EnumAttribute::Value); 572 genAttributesDecls(ast::EnumAttribute::Label); 573 genAttributesDecls(ast::EnumAttribute::Posn); 574 } 575 576 // void EnumAttrFuncGenerator::genSuccPredDecl() { 577 // auto succProto = genSuccProto(); 578 // auto predProto = genPredProto(); 579 580 // produceForwardDecl(succProto); 581 // produceForwardDecl(predProto); 582 // } 583 584 void EnumAttrFuncGenerator::genSuccPredPosn() { 585 ast::FunctionDecl* succ = genSuccPredFunc(true); 586 ast::FunctionDecl* pred = genSuccPredFunc(false); 587 588 produceDecl(succ); 589 produceDecl(pred); 405 590 } 406 591 … … 408 593 std::list<ast::ptr<ast::Decl>>& decls) { 409 594 // Generate the functions (they go into forwards and definitions). 410 genTypedEnumFuncs(); 595 genAttrStandardFuncs(); 596 genAttrFunctions(); 411 597 genSerialTraitFuncs(); 598 genSuccPredPosn(); 599 // problematic 412 600 genBoundedFunctions(); 413 601 // Now export the lists contents. … … 430 618 431 619 void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) { 432 if (!enumDecl->body || !enumDecl->isTyped) return; 620 if (!enumDecl->body) return; 621 if (!enumDecl->base) return; 622 433 623 ast::EnumInstType enumInst(enumDecl->name); 434 624 enumInst.base = enumDecl; 625 435 626 EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting); 436 627 gen.generateAndAppendFunctions(declsToAddAfter);
Note: See TracChangeset
for help on using the changeset viewer.