Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Validate/ImplementEnumFunc.cpp

    rfc1a3e2 rcf191ac  
    88namespace {
    99class EnumAttrFuncGenerator {
    10         const ast::EnumDecl* decl;
    11         const ast::EnumInstType* instType;
    12         unsigned int functionNesting;
    13         ast::Linkage::Spec proto_linkage;
    14 
    15 public:
    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 
    63 private:
    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);
     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);
    201204};
    202205
    203206std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genLabelInit() const {
    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;
     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;
    214217}
    215218
    216219std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genValueInit() const {
    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;
     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;
    235238}
    236239const ast::Init* EnumAttrFuncGenerator::getAutoInit(
    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         }
     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    }
    256259}
    257260
    258261ast::FunctionDecl* EnumAttrFuncGenerator::genProto(
    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;
     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;
    274277}
    275278
    276279void EnumAttrFuncGenerator::produceDecl(const ast::FunctionDecl* decl) {
    277         assert(nullptr != decl->stmts);
    278 
    279         definitions.push_back(decl);
     280    assert(nullptr != decl->stmts);
     281
     282    definitions.push_back(decl);
    280283}
    281284
    282285void EnumAttrFuncGenerator::produceForwardDecl(const ast::FunctionDecl* decl) {
    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);
     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);
    288291}
    289292
    290293ast::FunctionDecl* EnumAttrFuncGenerator::genPosnProto() const {
    291         return genProto(
    292                 "posE",
    293                 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    294                 {new ast::ObjectDecl(getLocation(), "_ret",
    295                         new ast::BasicType(ast::BasicKind::UnsignedInt))});
     294    return genProto(
     295        "posE",
     296        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
     297        {new ast::ObjectDecl(getLocation(), "_ret",
     298            new ast::BasicType(ast::BasicKind::UnsignedInt))});
    296299}
    297300
    298301ast::FunctionDecl* EnumAttrFuncGenerator::genLabelProto() const {
    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}))});
     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}))});
    305308}
    306309
    307310ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const {
    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))});
     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))});
    313316}
    314317
    315318ast::FunctionDecl* EnumAttrFuncGenerator::genSuccProto() const {
    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))});
     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))});
    321324}
    322325
    323326ast::FunctionDecl* EnumAttrFuncGenerator::genPredProto() const {
    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))});
     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))});
    329332}
    330333
    331334inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) {
    332         return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
     335    return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
    333336}
    334337
    335338ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPosProto() const {
    336         return genProto(
    337                 "_successor_",
    338                 {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
    339                 {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
    340         );
     339    return genProto(
     340        "_successor_",
     341        {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
     342        {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
     343    );
    341344}
    342345
    343346ast::FunctionDecl* EnumAttrFuncGenerator::genPredPosProto() const {
    344         return genProto(
    345                 "_predessor_",
    346                 {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
    347                 {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
    348         );
     347    return genProto(
     348        "_predessor_",
     349        {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
     350        {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
     351    );
    349352}
    350353
    351354ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
    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;
     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;
    368370}
    369371
    370372void EnumAttrFuncGenerator::genValueOrLabelBody(
    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)});
     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)});
    382384}
    383385
    384386void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const {
    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)});
     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)});
    392394}
    393395
    394396void EnumAttrFuncGenerator::genAttributesDecls(const ast::EnumAttribute attr) {
    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         }
     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    }
    415417}
    416418
    417419ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPredFunc(bool succ) {
    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;
     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;
    449451}
    450452
    451453void EnumAttrFuncGenerator::genAttrFunctions() {
    452         if (decl->base) {
    453                 genAttributesDecls(ast::EnumAttribute::Value);
    454                 genAttributesDecls(ast::EnumAttribute::Label);
    455                 genAttributesDecls(ast::EnumAttribute::Posn);
    456         }
     454    if (decl->base) {
     455        genAttributesDecls(ast::EnumAttribute::Value);
     456        genAttributesDecls(ast::EnumAttribute::Label);
     457        genAttributesDecls(ast::EnumAttribute::Posn);
     458    }
    457459}
    458460
    459461void EnumAttrFuncGenerator::genSuccPredDecl() {
    460         if (decl->base) {
    461                 auto succProto = genSuccProto();
    462                 auto predProto = genPredProto();
    463 
    464                 produceForwardDecl(succProto);
    465                 produceForwardDecl(predProto);
    466         }
     462    if (decl->base) {
     463        auto succProto = genSuccProto();
     464        auto predProto = genPredProto();
     465
     466        produceForwardDecl(succProto);
     467        produceForwardDecl(predProto);
     468    }
    467469}
    468470
    469471void EnumAttrFuncGenerator::genSuccPredPosn() {
    470         if (decl->base) {
    471                 ast::FunctionDecl* succ = genSuccPredFunc(true);
    472                 ast::FunctionDecl* pred = genSuccPredFunc(false);
    473 
    474                 produceDecl(succ);
    475                 produceDecl(pred);
    476         }
     472    if (decl->base) {
     473        ast::FunctionDecl* succ = genSuccPredFunc(true);
     474        ast::FunctionDecl* pred = genSuccPredFunc(false);
     475
     476        produceDecl(succ);
     477        produceDecl(pred);
     478    }
    477479}
    478480
    479481void EnumAttrFuncGenerator::generateAndAppendFunctions(
    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);
     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);
    489491}
    490492
    491493// ---------------------------------------------------------
    492494
    493 struct 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 
    499 private:
    500         // Current level of nested functions.
    501         unsigned int functionNesting = 0;
     495struct 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;
    502504};
    503505
    504506void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
    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);
     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);
    513515}
    514516
    515517void ImplementEnumFunc::previsit(const ast::FunctionDecl*) {
    516         functionNesting += 1;
     518    functionNesting += 1;
    517519}
    518520
    519521void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) {
    520         functionNesting -= 1;
    521 }
    522 
    523 } // namespace
     522    functionNesting -= 1;
     523}
     524
     525}  // namespace
    524526
    525527void implementEnumFunc(ast::TranslationUnit& translationUnit) {
    526         ast::Pass<ImplementEnumFunc>::run(translationUnit);
    527 }
    528 
    529 } // namespace Validate
     528    ast::Pass<ImplementEnumFunc>::run(translationUnit);
     529}
     530}  // namespace Validate
Note: See TracChangeset for help on using the changeset viewer.