Ignore:
Timestamp:
Apr 25, 2024, 3:48:17 PM (2 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
eb7586e
Parents:
cf191ac (diff), 55c97e4 (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.
Message:

resolve conflict

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Validate/ImplementEnumFunc.cpp

    rcf191ac r7042c60  
    88namespace {
    99class EnumAttrFuncGenerator {
    10     const ast::EnumDecl* decl;
    11     const ast::EnumInstType* instType;
    12     // const ast::EnumAttrType* attrType;
    13     unsigned int functionNesting;
    14     ast::Linkage::Spec proto_linkage;
    15 
    16    public:
    17     std::list<ast::ptr<ast::Decl>> forwards;
    18     std::list<ast::ptr<ast::Decl>> definitions;
    19 
    20     void generateAndAppendFunctions(std::list<ast::ptr<ast::Decl>>&);
    21 
    22     EnumAttrFuncGenerator(const ast::EnumDecl* decl,
    23                           const ast::EnumInstType* instType,
    24                           // const ast::EnumAttrType* enumAttrType,
    25                           unsigned int functionNesting)
    26         : decl(decl),
    27           instType{instType},
    28           // attrType{enumAttrType},
    29           functionNesting{functionNesting},
    30           proto_linkage{ast::Linkage::Cforall} {}
    31 
    32     void genAttrFunctions();
    33     void genSuccPredPosn();
    34     void genSuccPredDecl();
    35 
    36     void appendReturnThis(ast::FunctionDecl* decl) {
    37         assert(1 <= decl->params.size());
    38         assert(1 == decl->returns.size());
    39         assert(decl->stmts);
    40 
    41         const CodeLocation& location = (decl->stmts->kids.empty())
    42                                            ? decl->stmts->location
    43                                            : decl->stmts->kids.back()->location;
    44         const ast::DeclWithType* thisParam = decl->params.front();
    45         decl->stmts.get_and_mutate()->push_back(new ast::ReturnStmt(
    46             location, new ast::VariableExpr(location, thisParam)));
    47     }
    48     void genAttrStandardFuncs() {
    49         ast::FunctionDecl* (EnumAttrFuncGenerator::*standardProtos[4])()
    50             const = {&EnumAttrFuncGenerator::genCtorProto,
    51                      &EnumAttrFuncGenerator::genCopyProto,
    52                      &EnumAttrFuncGenerator::genDtorProto,
    53                      &EnumAttrFuncGenerator::genAssignProto};
    54         for (auto& generator : standardProtos) {
    55             ast::FunctionDecl* decl = (this->*generator)();
    56             produceForwardDecl(decl);
    57             genFuncBody(decl);
    58             if (CodeGen::isAssignment(decl->name)) {
    59                 appendReturnThis(decl);
    60             }
    61             produceDecl(decl);
    62         }
    63     }
    64 
    65    private:
    66     const CodeLocation& getLocation() const { return decl->location; }
    67 
    68     ast::FunctionDecl* genProto(
    69         std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
    70         std::vector<ast::ptr<ast::DeclWithType>>&& returns) const;
    71 
    72     void produceDecl(const ast::FunctionDecl* decl);
    73     void produceForwardDecl(const ast::FunctionDecl* decl);
    74 
    75     const ast::Decl* getDecl() const { return decl; }
    76 
    77     ast::FunctionDecl* genPosnProto() const;
    78     ast::FunctionDecl* genLabelProto() const;
    79     ast::FunctionDecl* genValueProto() const;
    80     ast::FunctionDecl* genSuccProto() const;
    81     ast::FunctionDecl* genPredProto() const;
    82 
    83     ast::FunctionDecl* genSuccPosProto() const;
    84     ast::FunctionDecl* genPredPosProto() const;
    85 
    86     // ---------------------------------------------------
    87     // ast::FunctionDecl* genAttrCtorProto() const;
    88     /// Changes the node inside a pointer so that it has the unused attribute.
    89     void addUnusedAttribute(ast::ptr<ast::DeclWithType>& declPtr) {
    90         ast::DeclWithType* decl = declPtr.get_and_mutate();
    91         decl->attributes.push_back(new ast::Attribute("unused"));
    92     }
    93 
    94     ast::ObjectDecl* dstParam() const {
    95         return new ast::ObjectDecl(getLocation(), "_dst",
    96                                    new ast::ReferenceType(new ast::EnumAttrType(
    97                                        ast::deepCopy(instType))));
    98     }
    99 
    100     ast::ObjectDecl* srcParam() const {
    101         return new ast::ObjectDecl(
    102             getLocation(), "_src",
    103             new ast::EnumAttrType(ast::deepCopy(instType)));
    104     }
    105 
    106     /// E = EnumAttrType<T>`
    107     /// `void ?{}(E & _dst)`.
    108     ast::FunctionDecl* genCtorProto() const {
    109         return genProto("?{}", {dstParam()}, {});
    110     }
    111 
    112     /// void ?{}(E & _dst, E _src)`.
    113     ast::FunctionDecl* genCopyProto() const {
    114         return genProto("?{}", {dstParam(), srcParam()}, {});
    115     }
    116 
    117     ///`void ^?{}(E & _dst)`.
    118     ast::FunctionDecl* genDtorProto() const {
    119         // The destructor must be mutex on a concurrent type.
    120         return genProto("^?{}", {dstParam()}, {});
    121     }
    122 
    123     /// `E ?{}(E & _dst, E _src)`.
    124     ast::FunctionDecl* genAssignProto() const {
    125         // Only the name is different, so just reuse the generation function.
    126         auto retval = srcParam();
    127         retval->name = "_ret";
    128         return genProto("?=?", {dstParam(), srcParam()}, {retval});
    129     }
    130 
    131     void genFuncBody(ast::FunctionDecl* func) {
    132         const CodeLocation& location = func->location;
    133         auto& params = func->params;
    134         if (InitTweak::isCopyConstructor(func) ||
    135             InitTweak::isAssignment(func)) {
    136             assert(2 == params.size());
    137             auto dstParam = params.front().strict_as<ast::ObjectDecl>();
    138             auto srcParam = params.back().strict_as<ast::ObjectDecl>();
    139             func->stmts = genCopyBody(location, dstParam, srcParam);
    140         } else {
    141             assert(1 == params.size());
    142             // Default constructor and destructor is empty.
    143             func->stmts = new ast::CompoundStmt(location);
    144             // Add unused attribute to parameter to silence warnings.
    145             addUnusedAttribute(params.front());
    146 
    147             // Just an extra step to make the forward and declaration match.
    148             if (forwards.empty()) return;
    149             ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
    150                 forwards.back().get_and_mutate());
    151             addUnusedAttribute(fwd->params.front());
    152         }
    153     }
    154 
    155     const ast::CompoundStmt* genCopyBody(const CodeLocation& location,
    156                                          const ast::ObjectDecl* dstParam,
    157                                          const ast::ObjectDecl* srcParam) {
    158         return new ast::CompoundStmt(
    159             location,
    160             {new ast::ExprStmt(
    161                 location,
    162                 new ast::UntypedExpr(
    163                     location, new ast::NameExpr(location, "__builtin_memcpy"),
    164                     {
    165                         new ast::AddressExpr(location, new ast::VariableExpr(
    166                                                            location, dstParam)),
    167                         new ast::AddressExpr(location, new ast::VariableExpr(
    168                                                            location, srcParam)),
    169                         new ast::SizeofExpr(location, srcParam->type),
    170                     }))});
    171     }
    172 
    173     void genDtorBody(ast::FunctionDecl* func) {
    174         const CodeLocation& location = func->location;
    175         auto& params = func->params;
    176         assert(1 == params.size());
    177         func->stmts = new ast::CompoundStmt(location);
    178         addUnusedAttribute(params.front());
    179 
    180         // Just an extra step to make the forward and declaration match.
    181         if (forwards.empty()) return;
    182         ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
    183             forwards.back().get_and_mutate());
    184         addUnusedAttribute(fwd->params.front());
    185     }
    186 
    187     // ast::FunctionDecl*
    188     // ----------------------------------------------------
    189 
    190     ast::FunctionDecl* genSuccPredFunc(bool succ);
    191 
    192     const ast::Init* getAutoInit(const ast::Init* prev) const;
    193 
    194     std::vector<ast::ptr<ast::Init>> genLabelInit() const;
    195 
    196     std::vector<ast::ptr<ast::Init>> genValueInit() const;
    197     ast::ObjectDecl* genAttrArrayProto(
    198         const ast::EnumAttribute attr, const CodeLocation& location,
    199         std::vector<ast::ptr<ast::Init>>& inits) const;
    200     void genValueOrLabelBody(ast::FunctionDecl* func,
    201                              ast::ObjectDecl* arrDecl) const;
    202     void genPosnBody(ast::FunctionDecl* func) const;
    203     void genAttributesDecls(const ast::EnumAttribute attr);
     10        const ast::EnumDecl* decl;
     11        const ast::EnumInstType* instType;
     12        unsigned int functionNesting;
     13        ast::Linkage::Spec proto_linkage;
     14
     15public:
     16        std::list<ast::ptr<ast::Decl>> forwards;
     17        std::list<ast::ptr<ast::Decl>> definitions;
     18
     19        void generateAndAppendFunctions(std::list<ast::ptr<ast::Decl>>&);
     20
     21        EnumAttrFuncGenerator(
     22                        const ast::EnumDecl* decl,
     23                        const ast::EnumInstType* instType,
     24                        unsigned int functionNesting )
     25                : decl(decl),
     26                  instType{instType},
     27                  functionNesting{functionNesting},
     28                  proto_linkage{ast::Linkage::Cforall} {}
     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
     63private:
     64        const CodeLocation& getLocation() const { return decl->location; }
     65
     66        ast::FunctionDecl* genProto(
     67                std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
     68                std::vector<ast::ptr<ast::DeclWithType>>&& returns) const;
     69
     70        void produceDecl(const ast::FunctionDecl* decl);
     71        void produceForwardDecl(const ast::FunctionDecl* decl);
     72
     73        const ast::Decl* getDecl() const { return decl; }
     74
     75        ast::FunctionDecl* genPosnProto() const;
     76        ast::FunctionDecl* genLabelProto() const;
     77        ast::FunctionDecl* genValueProto() const;
     78        ast::FunctionDecl* genSuccProto() const;
     79        ast::FunctionDecl* genPredProto() const;
     80
     81        ast::FunctionDecl* genSuccPosProto() const;
     82        ast::FunctionDecl* genPredPosProto() const;
     83
     84        // ---------------------------------------------------
     85        // ast::FunctionDecl* genAttrCtorProto() const;
     86        /// Changes the node inside a pointer so that it has the unused attribute.
     87        void addUnusedAttribute(ast::ptr<ast::DeclWithType>& declPtr) {
     88                ast::DeclWithType* decl = declPtr.get_and_mutate();
     89                decl->attributes.push_back(new ast::Attribute("unused"));
     90        }
     91
     92        ast::ObjectDecl* dstParam() const {
     93                return new ast::ObjectDecl(getLocation(), "_dst",
     94                                           new ast::ReferenceType(new ast::EnumAttrType(
     95                                               ast::deepCopy(instType))));
     96        }
     97
     98        ast::ObjectDecl* srcParam() const {
     99                return new ast::ObjectDecl(
     100                        getLocation(), "_src",
     101                        new ast::EnumAttrType(ast::deepCopy(instType)));
     102        }
     103
     104        /// E = EnumAttrType<T>`
     105        /// `void ?{}(E & _dst)`.
     106        ast::FunctionDecl* genCtorProto() const {
     107                return genProto("?{}", {dstParam()}, {});
     108        }
     109
     110        /// void ?{}(E & _dst, E _src)`.
     111        ast::FunctionDecl* genCopyProto() const {
     112                return genProto("?{}", {dstParam(), srcParam()}, {});
     113        }
     114
     115        ///`void ^?{}(E & _dst)`.
     116        ast::FunctionDecl* genDtorProto() const {
     117                // The destructor must be mutex on a concurrent type.
     118                return genProto("^?{}", {dstParam()}, {});
     119        }
     120
     121        /// `E ?{}(E & _dst, E _src)`.
     122        ast::FunctionDecl* genAssignProto() const {
     123                // Only the name is different, so just reuse the generation function.
     124                auto retval = srcParam();
     125                retval->name = "_ret";
     126                return genProto("?=?", {dstParam(), srcParam()}, {retval});
     127        }
     128
     129        void genFuncBody(ast::FunctionDecl* func) {
     130                const CodeLocation& location = func->location;
     131                auto& params = func->params;
     132                if (InitTweak::isCopyConstructor(func) ||
     133                        InitTweak::isAssignment(func)) {
     134                        assert(2 == params.size());
     135                        auto dstParam = params.front().strict_as<ast::ObjectDecl>();
     136                        auto srcParam = params.back().strict_as<ast::ObjectDecl>();
     137                        func->stmts = genCopyBody(location, dstParam, srcParam);
     138                } else {
     139                        assert(1 == params.size());
     140                        // Default constructor and destructor is empty.
     141                        func->stmts = new ast::CompoundStmt(location);
     142                        // Add unused attribute to parameter to silence warnings.
     143                        addUnusedAttribute(params.front());
     144
     145                        // Just an extra step to make the forward and declaration match.
     146                        if (forwards.empty()) return;
     147                        ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
     148                                forwards.back().get_and_mutate());
     149                        addUnusedAttribute(fwd->params.front());
     150                }
     151        }
     152
     153        const ast::CompoundStmt* genCopyBody( const CodeLocation& location,
     154                        const ast::ObjectDecl* dstParam, const ast::ObjectDecl* srcParam) {
     155                return new ast::CompoundStmt(
     156                        location,
     157                        {new ast::ExprStmt(
     158                                location,
     159                                new ast::UntypedExpr(
     160                                        location, new ast::NameExpr(location, "__builtin_memcpy"),
     161                                        {
     162                                                new ast::AddressExpr( location,
     163                                                        new ast::VariableExpr( location, dstParam ) ),
     164                                                new ast::AddressExpr( location,
     165                                                        new ast::VariableExpr( location, srcParam ) ),
     166                                                new ast::SizeofExpr( location, srcParam->type ),
     167                                        }))});
     168        }
     169
     170        void genDtorBody(ast::FunctionDecl* func) {
     171                const CodeLocation& location = func->location;
     172                auto& params = func->params;
     173                assert(1 == params.size());
     174                func->stmts = new ast::CompoundStmt(location);
     175                addUnusedAttribute(params.front());
     176
     177                // Just an extra step to make the forward and declaration match.
     178                if (forwards.empty()) return;
     179                ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
     180                        forwards.back().get_and_mutate());
     181                addUnusedAttribute(fwd->params.front());
     182        }
     183
     184        // ast::FunctionDecl*
     185        // ----------------------------------------------------
     186
     187        ast::FunctionDecl* genSuccPredFunc(bool succ);
     188
     189        const ast::Init* getAutoInit(const ast::Init* prev) const;
     190
     191        std::vector<ast::ptr<ast::Init>> genLabelInit() const;
     192
     193        std::vector<ast::ptr<ast::Init>> genValueInit() const;
     194        ast::ObjectDecl* genAttrArrayProto(
     195                const ast::EnumAttribute attr, const CodeLocation& location,
     196                std::vector<ast::ptr<ast::Init>>& inits) const;
     197        void genValueOrLabelBody(
     198                ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const;
     199        void genPosnBody(ast::FunctionDecl* func) const;
     200        void genAttributesDecls(const ast::EnumAttribute attr);
    204201};
    205202
    206203std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genLabelInit() const {
    207     std::vector<ast::ptr<ast::Init>> inits;
    208     for (size_t i = 0; i < decl->members.size(); i++) {
    209         ast::ptr<ast::Decl> mem = decl->members.at(i);
    210         auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
    211         assert(memAsObjectDecl);
    212         inits.emplace_back(new ast::SingleInit(
    213             mem->location,
    214             ast::ConstantExpr::from_string(mem->location, mem->name)));
    215     }
    216     return inits;
     204        std::vector<ast::ptr<ast::Init>> inits;
     205        for (size_t i = 0; i < decl->members.size(); i++) {
     206                ast::ptr<ast::Decl> mem = decl->members.at(i);
     207                auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
     208                assert(memAsObjectDecl);
     209                inits.emplace_back(new ast::SingleInit(
     210                        mem->location,
     211                        ast::ConstantExpr::from_string(mem->location, mem->name)));
     212        }
     213        return inits;
    217214}
    218215
    219216std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genValueInit() const {
    220     std::vector<ast::ptr<ast::Init>> inits;
    221     for (size_t i = 0; i < decl->members.size(); i++) {
    222         ast::ptr<ast::Decl> mem = decl->members.at(i);
    223         auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
    224         assert(memAsObjectDecl);
    225         if (memAsObjectDecl->init) {
    226             inits.emplace_back(memAsObjectDecl->init);
    227         } else {
    228             const CodeLocation& location = mem->location;
    229             if (i == 0) {
    230                 inits.emplace_back(new ast::SingleInit(
    231                     location, ast::ConstantExpr::from_int(mem->location, 0)));
    232             } else {
    233                 inits.emplace_back(getAutoInit(inits.at(i - 1)));
    234             }
    235         }
    236     }
    237     return inits;
     217        std::vector<ast::ptr<ast::Init>> inits;
     218        for (size_t i = 0; i < decl->members.size(); i++) {
     219                ast::ptr<ast::Decl> mem = decl->members.at(i);
     220                auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
     221                assert(memAsObjectDecl);
     222                if (memAsObjectDecl->init) {
     223                        inits.emplace_back(memAsObjectDecl->init);
     224                } else {
     225                        const CodeLocation& location = mem->location;
     226                        if (i == 0) {
     227                                inits.emplace_back(new ast::SingleInit(
     228                                        location, ast::ConstantExpr::from_int(mem->location, 0)));
     229                        } else {
     230                                inits.emplace_back(getAutoInit(inits.at(i - 1)));
     231                        }
     232                }
     233        }
     234        return inits;
    238235}
    239236const ast::Init* EnumAttrFuncGenerator::getAutoInit(
    240     const ast::Init* prev) const {
    241     if (prev == nullptr) {
    242         return new ast::SingleInit(
    243             getLocation(), ast::ConstantExpr::from_int(getLocation(), 0));
    244     }
    245     auto prevInit = dynamic_cast<const ast::SingleInit*>(prev);
    246     assert(prevInit);
    247     auto prevInitExpr = prevInit->value;
    248     if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
    249         // Assume no string literal for now
    250         return new ast::SingleInit(
    251             getLocation(), ast::ConstantExpr::from_int(
    252                                getLocation(), constInit->intValue() + 1));
    253     } else {
    254         auto untypedThisInit = new ast::UntypedExpr(
    255             getLocation(), new ast::NameExpr(getLocation(), "?++"),
    256             {prevInitExpr});
    257         return new ast::SingleInit(getLocation(), untypedThisInit);
    258     }
     237        const ast::Init* prev) const {
     238        if (prev == nullptr) {
     239                return new ast::SingleInit(
     240                        getLocation(), ast::ConstantExpr::from_int(getLocation(), 0));
     241        }
     242        auto prevInit = dynamic_cast<const ast::SingleInit*>(prev);
     243        assert(prevInit);
     244        auto prevInitExpr = prevInit->value;
     245        if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
     246                // Assume no string literal for now
     247                return new ast::SingleInit(
     248                        getLocation(), ast::ConstantExpr::from_int(
     249                                getLocation(), constInit->intValue() + 1));
     250        } else {
     251                auto untypedThisInit = new ast::UntypedExpr(
     252                        getLocation(), new ast::NameExpr(getLocation(), "?++"),
     253                        {prevInitExpr});
     254                return new ast::SingleInit(getLocation(), untypedThisInit);
     255        }
    259256}
    260257
    261258ast::FunctionDecl* EnumAttrFuncGenerator::genProto(
    262     std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
    263     std::vector<ast::ptr<ast::DeclWithType>>&& returns) const {
    264     ast::FunctionDecl* decl = new ast::FunctionDecl(
    265         // Auto-generated routines use the type declaration's location.
    266         getLocation(), std::move(name), {}, {}, std::move(params),
    267         std::move(returns),
    268         // Only a prototype, no body.
    269         nullptr,
    270         // Use static storage if we are at the top level.
    271         (0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static,
    272         proto_linkage, std::vector<ast::ptr<ast::Attribute>>(),
    273         // Auto-generated routines are inline to avoid conflicts.
    274         ast::Function::Specs(ast::Function::Inline));
    275     decl->fixUniqueId();
    276     return decl;
     259        std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
     260        std::vector<ast::ptr<ast::DeclWithType>>&& returns) const {
     261        ast::FunctionDecl* decl = new ast::FunctionDecl(
     262                // Auto-generated routines use the type declaration's location.
     263                getLocation(), std::move(name), {}, {}, std::move(params),
     264                std::move(returns),
     265                // Only a prototype, no body.
     266                nullptr,
     267                // Use static storage if we are at the top level.
     268                (0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static,
     269                proto_linkage, std::vector<ast::ptr<ast::Attribute>>(),
     270                // Auto-generated routines are inline to avoid conflicts.
     271                ast::Function::Specs(ast::Function::Inline));
     272        decl->fixUniqueId();
     273        return decl;
    277274}
    278275
    279276void EnumAttrFuncGenerator::produceDecl(const ast::FunctionDecl* decl) {
    280     assert(nullptr != decl->stmts);
    281 
    282     definitions.push_back(decl);
     277        assert(nullptr != decl->stmts);
     278
     279        definitions.push_back(decl);
    283280}
    284281
    285282void EnumAttrFuncGenerator::produceForwardDecl(const ast::FunctionDecl* decl) {
    286     if (0 != functionNesting) return;
    287     ast::FunctionDecl* fwd =
    288         (decl->stmts) ? ast::asForward(decl) : ast::deepCopy(decl);
    289     fwd->fixUniqueId();
    290     forwards.push_back(fwd);
     283        if (0 != functionNesting) return;
     284        ast::FunctionDecl* fwd =
     285                (decl->stmts) ? ast::asForward(decl) : ast::deepCopy(decl);
     286        fwd->fixUniqueId();
     287        forwards.push_back(fwd);
    291288}
    292289
     
    300297
    301298ast::FunctionDecl* EnumAttrFuncGenerator::genLabelProto() const {
    302     return genProto(
    303         "labelE",
    304         {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    305         {new ast::ObjectDecl(
    306             getLocation(), "_ret",
    307             new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}))});
     299        return genProto(
     300                "labelE",
     301                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
     302                {new ast::ObjectDecl(
     303                        getLocation(), "_ret",
     304                        new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}))});
    308305}
    309306
    310307ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const {
    311     return genProto(
    312         "valueE",
    313         {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    314         {new ast::ObjectDecl(getLocation(), "_ret",
    315                              ast::deepCopy(decl->base))});
     308        return genProto(
     309                "valueE",
     310                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
     311                {new ast::ObjectDecl(getLocation(), "_ret",
     312                                     ast::deepCopy(decl->base))});
    316313}
    317314
    318315ast::FunctionDecl* EnumAttrFuncGenerator::genSuccProto() const {
    319     return genProto(
    320         "succ",
    321         {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    322         {new ast::ObjectDecl(getLocation(), "_ret",
    323                              new ast::EnumInstType(decl))});
     316        return genProto(
     317                "succ",
     318                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
     319                {new ast::ObjectDecl(getLocation(), "_ret",
     320                                     new ast::EnumInstType(decl))});
    324321}
    325322
    326323ast::FunctionDecl* EnumAttrFuncGenerator::genPredProto() const {
    327     return genProto(
    328         "pred",
    329         {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    330         {new ast::ObjectDecl(getLocation(), "_ret",
    331                              new ast::EnumInstType(decl))});
     324        return genProto(
     325                "pred",
     326                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
     327                {new ast::ObjectDecl(getLocation(), "_ret",
     328                                     new ast::EnumInstType(decl))});
    332329}
    333330
    334331inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) {
    335     return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
     332        return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
    336333}
    337334
    338335ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPosProto() const {
    339     return genProto(
    340         "_successor_",
    341         {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
    342         {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
    343     );
     336        return genProto(
     337                "_successor_",
     338                {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
     339                {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
     340        );
    344341}
    345342
    346343ast::FunctionDecl* EnumAttrFuncGenerator::genPredPosProto() const {
    347     return genProto(
    348         "_predessor_",
    349         {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
    350         {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
    351     );
     344        return genProto(
     345                "_predessor_",
     346                {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
     347                {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
     348        );
    352349}
    353350
    354351ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
    355     const ast::EnumAttribute attr, const CodeLocation& location,
    356     std::vector<ast::ptr<ast::Init>>& inits) const {
    357     ast::ArrayType* arrT = new ast::ArrayType(
    358         attr == ast::EnumAttribute::Value
    359             ? decl->base
    360             : new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}),
    361         ast::ConstantExpr::from_int(decl->location, decl->members.size()),
    362         ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
    363 
    364     ast::ObjectDecl* objDecl =
    365         new ast::ObjectDecl(decl->location, decl->getUnmangeldArrayName(attr),
    366                             arrT, new ast::ListInit(location, std::move(inits)),
    367                             ast::Storage::Static, ast::Linkage::AutoGen);
    368 
    369     return objDecl;
     352        const ast::EnumAttribute attr, const CodeLocation& location,
     353        std::vector<ast::ptr<ast::Init>>& inits) const {
     354        ast::ArrayType* arrT = new ast::ArrayType(
     355                attr == ast::EnumAttribute::Value
     356                        ? decl->base
     357                        : new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}),
     358                ast::ConstantExpr::from_int(decl->location, decl->members.size()),
     359                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
     360
     361        ast::ObjectDecl* objDecl =
     362                new ast::ObjectDecl(
     363                        decl->location, decl->getUnmangeldArrayName( attr ),
     364                        arrT, new ast::ListInit( location, std::move( inits ) ),
     365                        ast::Storage::Static, ast::Linkage::AutoGen );
     366
     367        return objDecl;
    370368}
    371369
    372370void EnumAttrFuncGenerator::genValueOrLabelBody(
    373     ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const {
    374     ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
    375         func->location, "?[?]",
    376         {new ast::NameExpr(func->location, arrDecl->name),
    377          new ast::CastExpr(
    378              func->location,
    379              new ast::VariableExpr(func->location, func->params.front()),
    380              new ast::EnumAttrType(new ast::EnumInstType(decl),
    381                                    ast::EnumAttribute::Posn))});
    382     func->stmts = new ast::CompoundStmt(
    383         func->location, {new ast::ReturnStmt(func->location, untyped)});
     371        ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const {
     372        ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
     373                func->location, "?[?]",
     374                {new ast::NameExpr(func->location, arrDecl->name),
     375                        new ast::CastExpr(
     376                                func->location,
     377                                new ast::VariableExpr( func->location, func->params.front() ),
     378                                new ast::EnumAttrType( new ast::EnumInstType(decl),
     379                                        ast::EnumAttribute::Posn))});
     380        func->stmts = new ast::CompoundStmt(
     381                func->location, {new ast::ReturnStmt(func->location, untyped)});
    384382}
    385383
    386384void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const {
    387     auto castExpr = new ast::CastExpr(
    388         func->location,
    389         new ast::VariableExpr(func->location, func->params.front()),
    390         new ast::EnumAttrType(new ast::EnumInstType(decl),
    391                               ast::EnumAttribute::Posn));
    392     func->stmts = new ast::CompoundStmt(
    393         func->location, {new ast::ReturnStmt(func->location, castExpr)});
     385        auto castExpr = new ast::CastExpr(
     386                func->location,
     387                new ast::VariableExpr(func->location, func->params.front()),
     388                new ast::EnumAttrType(new ast::EnumInstType(decl),
     389                                                          ast::EnumAttribute::Posn));
     390        func->stmts = new ast::CompoundStmt(
     391                func->location, {new ast::ReturnStmt(func->location, castExpr)});
    394392}
    395393
    396394void EnumAttrFuncGenerator::genAttributesDecls(const ast::EnumAttribute attr) {
    397     if (attr == ast::EnumAttribute::Value ||
    398         attr == ast::EnumAttribute::Label) {
    399         std::vector<ast::ptr<ast::Init>> inits =
    400             attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit();
    401         ast::ObjectDecl* arrayProto =
    402             genAttrArrayProto(attr, getLocation(), inits);
    403         forwards.push_back(arrayProto);
    404 
    405         ast::FunctionDecl* funcProto = attr == ast::EnumAttribute::Value
    406                                            ? genValueProto()
    407                                            : genLabelProto();
    408         produceForwardDecl(funcProto);
    409         genValueOrLabelBody(funcProto, arrayProto);
    410         produceDecl(funcProto);
    411     } else {
    412         ast::FunctionDecl* funcProto = genPosnProto();
    413         produceForwardDecl(funcProto);
    414         genPosnBody(funcProto);
    415         produceDecl(funcProto);
    416     }
     395        if (attr == ast::EnumAttribute::Value ||
     396                attr == ast::EnumAttribute::Label) {
     397                std::vector<ast::ptr<ast::Init>> inits =
     398                        attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit();
     399                ast::ObjectDecl* arrayProto =
     400                        genAttrArrayProto(attr, getLocation(), inits);
     401                forwards.push_back(arrayProto);
     402
     403                ast::FunctionDecl* funcProto = ( attr == ast::EnumAttribute::Value )
     404                                               ? genValueProto()
     405                                               : genLabelProto();
     406                produceForwardDecl(funcProto);
     407                genValueOrLabelBody(funcProto, arrayProto);
     408                produceDecl(funcProto);
     409        } else {
     410                ast::FunctionDecl* funcProto = genPosnProto();
     411                produceForwardDecl(funcProto);
     412                genPosnBody(funcProto);
     413                produceDecl(funcProto);
     414        }
    417415}
    418416
    419417ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPredFunc(bool succ) {
    420     ast::FunctionDecl* funcDecl = succ ? genSuccPosProto() : genPredPosProto();
    421     produceForwardDecl(funcDecl);
    422 
    423     const CodeLocation& location = getLocation();
    424 
    425     auto& params = funcDecl->params;
    426     assert(params.size() == 1);
    427     auto param = params.front().strict_as<ast::ObjectDecl>();
    428 
    429 
    430     auto rets = funcDecl->returns;
    431     assert(params.size() == 1);
    432     auto ret = rets.front().strict_as<ast::ObjectDecl>();
    433     auto retType = ret->type.strict_as<ast::EnumAttrType>();
    434 
    435     auto addOneExpr = ast::UntypedExpr::createCall( location,
    436         succ? "?+?": "?-?",
    437         {new ast::VariableExpr(location, param),
    438         ast::ConstantExpr::from_int(location, 1)}
    439     );
    440 
    441     funcDecl->stmts = new ast::CompoundStmt(
    442         location, {
    443             new ast::ReturnStmt(
    444                 location,
    445                 new ast::CastExpr(location, addOneExpr, retType)
    446             )
    447         }
    448     );
    449 
    450     return funcDecl;
     418        ast::FunctionDecl* funcDecl = succ ? genSuccPosProto() : genPredPosProto();
     419        produceForwardDecl(funcDecl);
     420
     421        const CodeLocation& location = getLocation();
     422
     423        auto& params = funcDecl->params;
     424        assert(params.size() == 1);
     425        auto param = params.front().strict_as<ast::ObjectDecl>();
     426
     427
     428        auto rets = funcDecl->returns;
     429        assert(params.size() == 1);
     430        auto ret = rets.front().strict_as<ast::ObjectDecl>();
     431        auto retType = ret->type.strict_as<ast::EnumAttrType>();
     432
     433        auto addOneExpr = ast::UntypedExpr::createCall( location,
     434                succ? "?+?": "?-?",
     435                {new ast::VariableExpr(location, param),
     436                ast::ConstantExpr::from_int(location, 1)}
     437        );
     438
     439        funcDecl->stmts = new ast::CompoundStmt(
     440                location, {
     441                        new ast::ReturnStmt(
     442                                location,
     443                                new ast::CastExpr(location, addOneExpr, retType)
     444                        )
     445                }
     446        );
     447
     448        return funcDecl;
    451449}
    452450
    453451void EnumAttrFuncGenerator::genAttrFunctions() {
    454     if (decl->base) {
    455         genAttributesDecls(ast::EnumAttribute::Value);
    456         genAttributesDecls(ast::EnumAttribute::Label);
    457         genAttributesDecls(ast::EnumAttribute::Posn);
    458     }
     452        if (decl->base) {
     453                genAttributesDecls(ast::EnumAttribute::Value);
     454                genAttributesDecls(ast::EnumAttribute::Label);
     455                genAttributesDecls(ast::EnumAttribute::Posn);
     456        }
    459457}
    460458
    461459void EnumAttrFuncGenerator::genSuccPredDecl() {
    462     if (decl->base) {
    463         auto succProto = genSuccProto();
    464         auto predProto = genPredProto();
    465 
    466         produceForwardDecl(succProto);
    467         produceForwardDecl(predProto);
    468     }
     460        if (decl->base) {
     461                auto succProto = genSuccProto();
     462                auto predProto = genPredProto();
     463
     464                produceForwardDecl(succProto);
     465                produceForwardDecl(predProto);
     466        }
    469467}
    470468
    471469void EnumAttrFuncGenerator::genSuccPredPosn() {
    472     if (decl->base) {
    473         ast::FunctionDecl* succ = genSuccPredFunc(true);
    474         ast::FunctionDecl* pred = genSuccPredFunc(false);
    475 
    476         produceDecl(succ);
    477         produceDecl(pred);
    478     }
     470        if (decl->base) {
     471                ast::FunctionDecl* succ = genSuccPredFunc(true);
     472                ast::FunctionDecl* pred = genSuccPredFunc(false);
     473
     474                produceDecl(succ);
     475                produceDecl(pred);
     476        }
    479477}
    480478
    481479void EnumAttrFuncGenerator::generateAndAppendFunctions(
    482     std::list<ast::ptr<ast::Decl>>& decls) {
    483     // Generate the functions (they go into forwards and definitions).
    484     genAttrStandardFuncs();
    485     genAttrFunctions();
    486     genSuccPredDecl();
    487     genSuccPredPosn(); // Posn
    488     // Now export the lists contents.
    489     decls.splice(decls.end(), forwards);
    490     decls.splice(decls.end(), definitions);
     480        std::list<ast::ptr<ast::Decl>>& decls) {
     481        // Generate the functions (they go into forwards and definitions).
     482        genAttrStandardFuncs();
     483        genAttrFunctions();
     484        genSuccPredDecl();
     485        genSuccPredPosn(); // Posn
     486        // Now export the lists contents.
     487        decls.splice(decls.end(), forwards);
     488        decls.splice(decls.end(), definitions);
    491489}
    492490
    493491// ---------------------------------------------------------
    494492
    495 struct ImplementEnumFunc final : public ast::WithDeclsToAdd<>,
    496                                 public ast::WithShortCircuiting {
    497     void previsit(const ast::EnumDecl* enumDecl);
    498     void previsit(const ast::FunctionDecl* functionDecl);
    499     void postvisit(const ast::FunctionDecl* functionDecl);
    500 
    501    private:
    502     // Current level of nested functions.
    503     unsigned int functionNesting = 0;
     493struct ImplementEnumFunc final :
     494                public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting {
     495        void previsit(const ast::EnumDecl* enumDecl);
     496        void previsit(const ast::FunctionDecl* functionDecl);
     497        void postvisit(const ast::FunctionDecl* functionDecl);
     498
     499private:
     500        // Current level of nested functions.
     501        unsigned int functionNesting = 0;
    504502};
    505503
    506504void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
    507     if (!enumDecl->body) return;
    508     if (!enumDecl->base) return;
    509 
    510     ast::EnumInstType enumInst(enumDecl->name);
    511     enumInst.base = enumDecl;
    512 
    513     EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
    514     gen.generateAndAppendFunctions(declsToAddAfter);
     505        if (!enumDecl->body) return;
     506        if (!enumDecl->base) return;
     507
     508        ast::EnumInstType enumInst(enumDecl->name);
     509        enumInst.base = enumDecl;
     510
     511        EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
     512        gen.generateAndAppendFunctions(declsToAddAfter);
    515513}
    516514
    517515void ImplementEnumFunc::previsit(const ast::FunctionDecl*) {
    518     functionNesting += 1;
     516        functionNesting += 1;
    519517}
    520518
    521519void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) {
    522     functionNesting -= 1;
    523 }
    524 
    525 }  // namespace
     520        functionNesting -= 1;
     521}
     522
     523} // namespace
    526524
    527525void implementEnumFunc(ast::TranslationUnit& translationUnit) {
    528     ast::Pass<ImplementEnumFunc>::run(translationUnit);
    529 }
    530 }  // namespace Validate
     526        ast::Pass<ImplementEnumFunc>::run(translationUnit);
     527}
     528
     529} // namespace Validate
Note: See TracChangeset for help on using the changeset viewer.