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