@@ -414,107 +414,71 @@ class DeclAndTypePrinter::Implementation
414
414
return p1.second .tag < p2.second .tag ;
415
415
});
416
416
417
- if (elementTagMapping.empty ()) {
418
- os << " \n " ;
419
- return ;
420
- }
421
-
422
- os << " enum class cases {\n " ;
423
- for (const auto &pair : elementTagMapping) {
424
- os << " " ;
425
- syntaxPrinter.printIdentifier (pair.first ->getNameStr ());
426
- os << " ,\n " ;
427
- }
428
- os << " };\n " ; // enum class cases' closing bracket
429
-
430
- // Printing operator cases()
431
- os << " inline operator cases() const {\n " ;
432
- if (ED->isResilient ()) {
433
- os << " auto tag = _getEnumTag();\n " ;
434
- for (const auto &pair : elementTagMapping) {
435
- os << " if (tag == " << cxx_synthesis::getCxxImplNamespaceName ();
436
- os << " ::" << pair.second .globalVariableName << " ) return cases::" ;
437
- syntaxPrinter.printIdentifier (pair.first ->getNameStr ());
438
- os << " ;\n " ;
439
- }
440
- // TODO: change to Swift's fatalError when it's available in C++
441
- os << " abort();\n " ;
442
- } else { // non-resilient enum
443
- os << " switch (_getEnumTag()) {\n " ;
444
- for (const auto &pair : elementTagMapping) {
445
- os << " case " << pair.second .tag << " : return cases::" ;
446
- syntaxPrinter.printIdentifier (pair.first ->getNameStr ());
447
- os << " ;\n " ;
448
- }
449
- // TODO: change to Swift's fatalError when it's available in C++
450
- os << " default: abort();\n " ;
451
- os << " }\n " ; // switch's closing bracket
452
- }
453
- os << " }\n " ; // operator cases()'s closing bracket
454
-
417
+ os << ' \n ' ;
418
+ os << " enum class cases {" ;
419
+ llvm::interleave (
420
+ elementTagMapping, os,
421
+ [&](const auto &pair) {
422
+ os << " \n " ;
423
+ syntaxPrinter.printIdentifier (pair.first ->getNameStr ());
424
+ },
425
+ " ," );
426
+ // TODO: allow custom name for this special case
427
+ auto resilientUnknownDefaultCaseName = " unknownDefault" ;
455
428
if (ED->isResilient ()) {
456
- os << " inline bool inResilientUnknownCase() const {\n " ;
457
- os << " auto tag = _getEnumTag();\n " ;
458
- os << " return" ;
459
- llvm::interleave (
460
- elementTagMapping, os,
461
- [&](const auto &pair) {
462
- os << " \n tag != " << cxx_synthesis::getCxxImplNamespaceName ()
463
- << " ::" << pair.second .globalVariableName ;
464
- },
465
- " &&" );
466
- os << " ;\n " ;
467
- os << " }\n " ;
429
+ os << " ,\n " << resilientUnknownDefaultCaseName;
468
430
}
431
+ os << " \n };\n\n " ; // enum class cases' closing bracket
469
432
470
- // Printing case-related functions
433
+ // Printing struct, is, and get functions for each case
471
434
DeclAndTypeClangFunctionPrinter clangFuncPrinter (
472
435
os, owningPrinter.prologueOS , owningPrinter.typeMapping ,
473
436
owningPrinter.interopContext );
474
437
475
- for ( const auto &pair : elementTagMapping ) {
438
+ auto printIsFunction = [&](StringRef caseName, EnumDecl *ED ) {
476
439
os << " inline bool is" ;
477
- auto name = pair.first ->getNameStr ().str ();
440
+ std::string name;
441
+ llvm::raw_string_ostream nameStream (name);
442
+ ClangSyntaxPrinter (nameStream).printIdentifier (caseName);
478
443
name[0 ] = std::toupper (name[0 ]);
479
444
os << name << " () const {\n " ;
480
- os << " return _getEnumTag() == " ;
481
- if (ED->isResilient ()) {
482
- os << cxx_synthesis::getCxxImplNamespaceName ()
483
- << " ::" << pair.second .globalVariableName ;
484
- } else {
485
- os << pair.second .tag ;
486
- }
487
- os << " ;\n }\n " ;
488
-
489
- if (!pair.first ->hasAssociatedValues ()) {
490
- continue ;
491
- }
445
+ os << " return *this == " ;
446
+ syntaxPrinter.printBaseName (ED);
447
+ os << " ::" ;
448
+ syntaxPrinter.printIdentifier (caseName);
449
+ os << " ;\n " ;
450
+ os << " }\n " ;
451
+ };
492
452
493
- auto associatedValueList = pair.first ->getParameterList ();
453
+ auto printGetFunction = [&](EnumElementDecl *elementDecl) {
454
+ auto associatedValueList = elementDecl->getParameterList ();
494
455
// TODO: add tuple type support
495
456
if (associatedValueList->size () > 1 ) {
496
- continue ;
457
+ return ;
497
458
}
498
459
auto firstType = associatedValueList->front ()->getType ();
499
460
auto firstTypeDecl = firstType->getNominalOrBoundGenericNominal ();
500
461
OptionalTypeKind optKind;
501
462
std::tie (firstType, optKind) =
502
463
getObjectTypeAndOptionality (firstTypeDecl, firstType);
503
464
504
- // FIXME: (tongjie) may have to forward declare return type
465
+ auto name = elementDecl->getNameStr ().str ();
466
+ name[0 ] = std::toupper (name[0 ]);
467
+
468
+ // FIXME: may have to forward declare return type
505
469
os << " inline " ;
506
470
clangFuncPrinter.printClangFunctionReturnType (
507
471
firstType, optKind, firstTypeDecl->getModuleContext (),
508
472
owningPrinter.outputLang );
509
473
os << " get" << name << " () const {\n " ;
510
474
os << " if (!is" << name << " ()) abort();\n " ;
511
475
os << " alignas(" ;
512
- syntaxPrinter.printBaseName (ED );
476
+ syntaxPrinter.printBaseName (elementDecl-> getParentEnum () );
513
477
os << " ) unsigned char buffer[sizeof(" ;
514
- syntaxPrinter.printBaseName (ED );
478
+ syntaxPrinter.printBaseName (elementDecl-> getParentEnum () );
515
479
os << " )];\n " ;
516
480
os << " auto *thisCopy = new(buffer) " ;
517
- syntaxPrinter.printBaseName (ED );
481
+ syntaxPrinter.printBaseName (elementDecl-> getParentEnum () );
518
482
os << " (*this);\n " ;
519
483
os << " char * _Nonnull payloadFromDestruction = "
520
484
" thisCopy->_destructiveProjectEnumData();\n " ;
@@ -531,7 +495,8 @@ class DeclAndTypePrinter::Implementation
531
495
} else {
532
496
os << " return " ;
533
497
syntaxPrinter.printModuleNamespaceQualifiersIfNeeded (
534
- firstTypeDecl->getModuleContext (), ED->getModuleContext ());
498
+ firstTypeDecl->getModuleContext (),
499
+ elementDecl->getParentEnum ()->getModuleContext ());
535
500
os << cxx_synthesis::getCxxImplNamespaceName ();
536
501
os << " ::" ;
537
502
ClangValueTypePrinter::printCxxImplClassName (os, firstTypeDecl);
@@ -542,8 +507,77 @@ class DeclAndTypePrinter::Implementation
542
507
os << " ::initializeWithTake(result, payloadFromDestruction);\n " ;
543
508
os << " });\n " ;
544
509
}
545
- os << " }\n " ;
510
+ os << " }\n " ; // closing bracket of get function
511
+ };
512
+
513
+ auto printStruct = [&](StringRef caseName, EnumElementDecl *elementDecl) {
514
+ os << " static struct { // impl struct for case " << caseName << ' \n ' ;
515
+ os << " inline constexpr operator cases() const {\n " ;
516
+ os << " return cases::" ;
517
+ syntaxPrinter.printIdentifier (caseName);
518
+ os << " ;\n " ;
519
+ os << " }\n " ;
520
+ if (elementDecl != nullptr ) {
521
+ os << " inline " ;
522
+ syntaxPrinter.printBaseName (elementDecl->getParentEnum ());
523
+ os << " operator()(" ;
524
+ // TODO: implement parameter for associated value
525
+ os << " ) const {\n " ;
526
+ // TODO: print _make for now; need to print actual code making an enum
527
+ os << " return " ;
528
+ syntaxPrinter.printBaseName (elementDecl->getParentEnum ());
529
+ os << " ::_make();\n " ;
530
+ os << " }\n " ;
531
+ }
532
+ os << " } " ;
533
+ syntaxPrinter.printIdentifier (caseName);
534
+ os << " ;\n " ;
535
+ };
536
+
537
+ for (const auto &pair : elementTagMapping) {
538
+ // Printing struct
539
+ printStruct (pair.first ->getNameStr (), pair.first );
540
+ // Printing `is` function
541
+ printIsFunction (pair.first ->getNameStr (), ED);
542
+ if (pair.first ->hasAssociatedValues ()) {
543
+ // Printing `get` function
544
+ printGetFunction (pair.first );
545
+ }
546
+ os << ' \n ' ;
547
+ }
548
+
549
+ if (ED->isResilient ()) {
550
+ // Printing struct for unknownDefault
551
+ printStruct (resilientUnknownDefaultCaseName, /* elementDecl */ nullptr );
552
+ // Printing isUnknownDefault
553
+ printIsFunction (resilientUnknownDefaultCaseName, ED);
554
+ os << ' \n ' ;
555
+ }
556
+ os << ' \n ' ;
557
+
558
+ // Printing operator cases()
559
+ os << " inline operator cases() const {\n " ;
560
+ if (ED->isResilient ()) {
561
+ os << " auto tag = _getEnumTag();\n " ;
562
+ for (const auto &pair : elementTagMapping) {
563
+ os << " if (tag == " << cxx_synthesis::getCxxImplNamespaceName ();
564
+ os << " ::" << pair.second .globalVariableName << " ) return cases::" ;
565
+ syntaxPrinter.printIdentifier (pair.first ->getNameStr ());
566
+ os << " ;\n " ;
567
+ }
568
+ os << " return cases::" << resilientUnknownDefaultCaseName << " ;\n " ;
569
+ } else { // non-resilient enum
570
+ os << " switch (_getEnumTag()) {\n " ;
571
+ for (const auto &pair : elementTagMapping) {
572
+ os << " case " << pair.second .tag << " : return cases::" ;
573
+ syntaxPrinter.printIdentifier (pair.first ->getNameStr ());
574
+ os << " ;\n " ;
575
+ }
576
+ // TODO: change to Swift's fatalError when it's available in C++
577
+ os << " default: abort();\n " ;
578
+ os << " }\n " ; // switch's closing bracket
546
579
}
580
+ os << " }\n " ; // operator cases()'s closing bracket
547
581
os << " \n " ;
548
582
});
549
583
os << outOfLineDefinitions;
0 commit comments