Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Validate/ImplementEnumFunc.cpp

    rc333ed2 reb7586e  
    2828                  proto_linkage{ast::Linkage::Cforall} {}
    2929
     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
    3063private:
    3164        const CodeLocation& getLocation() const { return decl->location; }
     
    4073        const ast::Decl* getDecl() const { return decl; }
    4174
    42         // Implement Bounded trait
    43         void genBoundedFunctions();
    44         ast::FunctionDecl* genBoundedProto(const char *) const;
    45         void genBoundedBody(ast::FunctionDecl* func) const;
    46 
    47         // Implement Serial trait
     75        // Implement Bounded trait for enum
     76    void genBoundedFunctions();
     77        // Implement Serial trait for enum
    4878        void genSerialTraitFuncs();
    49         ast::FunctionDecl* genFromIntProto() const;
    50         ast::FunctionDecl* genFromInstanceProto() const;
    51         ast::FunctionDecl* genInstToInstFuncProto(const char* func) const;
    52         void genFromIntBody(ast::FunctionDecl *) const;
    53         void genFromInstanceBody(ast::FunctionDecl *) const;
    54         void genSuccPredBody(ast::FunctionDecl *, const char *) const;
    55 
    56         // Implement TypedEnum trait
    57         void genTypedEnumFuncs();
    58         void genTypedEnumFunction(const ast::EnumAttribute attr);
     79
     80        // Bounded trait
     81        ast::FunctionDecl* genLowerBoundProto() const;
     82        ast::FunctionDecl* genUpperBoundProto() const;
     83        void genLowerBoundBody(ast::FunctionDecl* func) const;
     84        void genUpperBoundBody(ast::FunctionDecl* func) const;
     85
    5986        ast::FunctionDecl* genPosnProto() const;
    6087        ast::FunctionDecl* genLabelProto() const;
    6188        ast::FunctionDecl* genValueProto() const;
    62         void genValueOrLabelBody(
    63                 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const;
    64         void genPosnBody(ast::FunctionDecl* func) const;
    65 
     89
     90        // Serial trait
     91        ast::FunctionDecl* genFromIntProto() const;
     92        ast::FunctionDecl* genFromInstanceProto() const;
     93        ast::FunctionDecl* genSuccProto() const;
     94        ast::FunctionDecl* genPredProto() const;
     95
     96        void genFromIntBody(ast::FunctionDecl *) const;
     97        void genFromInstanceBody(ast::FunctionDecl *) const;
    6698        ////////////////
     99
     100        ast::FunctionDecl* genSuccPosProto() const;
     101        ast::FunctionDecl* genPredPosProto() const;
    67102
    68103        // ---------------------------------------------------
     
    86121        }
    87122
     123        /// E = EnumAttrType<T>`
     124        /// `void ?{}(E & _dst)`.
     125        ast::FunctionDecl* genCtorProto() const {
     126                return genProto("?{}", {dstParam()}, {});
     127        }
     128
     129        /// void ?{}(E & _dst, E _src)`.
     130        ast::FunctionDecl* genCopyProto() const {
     131                return genProto("?{}", {dstParam(), srcParam()}, {});
     132        }
     133
     134        ///`void ^?{}(E & _dst)`.
     135        ast::FunctionDecl* genDtorProto() const {
     136                // The destructor must be mutex on a concurrent type.
     137                return genProto("^?{}", {dstParam()}, {});
     138        }
     139
     140        /// `E ?{}(E & _dst, E _src)`.
     141        ast::FunctionDecl* genAssignProto() const {
     142                // Only the name is different, so just reuse the generation function.
     143                auto retval = srcParam();
     144                retval->name = "_ret";
     145                return genProto("?=?", {dstParam(), srcParam()}, {retval});
     146        }
     147
     148        void genFuncBody(ast::FunctionDecl* func) {
     149                const CodeLocation& location = func->location;
     150                auto& params = func->params;
     151                if (InitTweak::isCopyConstructor(func) ||
     152                        InitTweak::isAssignment(func)) {
     153                        assert(2 == params.size());
     154                        auto dstParam = params.front().strict_as<ast::ObjectDecl>();
     155                        auto srcParam = params.back().strict_as<ast::ObjectDecl>();
     156                        func->stmts = genCopyBody(location, dstParam, srcParam);
     157                } else {
     158                        assert(1 == params.size());
     159                        // Default constructor and destructor is empty.
     160                        func->stmts = new ast::CompoundStmt(location);
     161                        // Add unused attribute to parameter to silence warnings.
     162                        addUnusedAttribute(params.front());
     163
     164                        // Just an extra step to make the forward and declaration match.
     165                        if (forwards.empty()) return;
     166                        ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
     167                                forwards.back().get_and_mutate());
     168                        addUnusedAttribute(fwd->params.front());
     169                }
     170        }
     171
     172        const ast::CompoundStmt* genCopyBody( const CodeLocation& location,
     173                        const ast::ObjectDecl* dstParam, const ast::ObjectDecl* srcParam) {
     174                return new ast::CompoundStmt(
     175                        location,
     176                        {new ast::ExprStmt(
     177                                location,
     178                                new ast::UntypedExpr(
     179                                        location, new ast::NameExpr(location, "__builtin_memcpy"),
     180                                        {
     181                                                new ast::AddressExpr( location,
     182                                                        new ast::VariableExpr( location, dstParam ) ),
     183                                                new ast::AddressExpr( location,
     184                                                        new ast::VariableExpr( location, srcParam ) ),
     185                                                new ast::SizeofExpr( location, srcParam->type ),
     186                                        }))});
     187        }
     188
     189        void genDtorBody(ast::FunctionDecl* func) {
     190                const CodeLocation& location = func->location;
     191                auto& params = func->params;
     192                assert(1 == params.size());
     193                func->stmts = new ast::CompoundStmt(location);
     194                addUnusedAttribute(params.front());
     195
     196                // Just an extra step to make the forward and declaration match.
     197                if (forwards.empty()) return;
     198                ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
     199                        forwards.back().get_and_mutate());
     200                addUnusedAttribute(fwd->params.front());
     201        }
     202
     203        // ast::FunctionDecl*
    88204        // ----------------------------------------------------
     205
     206        ast::FunctionDecl* genSuccPredFunc(bool succ);
    89207
    90208        const ast::Init* getAutoInit(const ast::Init* prev) const;
     
    96214                const ast::EnumAttribute attr, const CodeLocation& location,
    97215                std::vector<ast::ptr<ast::Init>>& inits) const;
     216        void genValueOrLabelBody(
     217                ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const;
     218        void genPosnBody(ast::FunctionDecl* func) const;
     219        void genAttributesDecls(const ast::EnumAttribute attr);
    98220};
    99221
     
    252374}
    253375
    254 void EnumAttrFuncGenerator::genSuccPredBody(ast::FunctionDecl * func, const char* opt) const {
    255         auto params = func->params;
    256         assert( params.size() == 1 );
    257         auto param = params.front();
    258         auto enumToInt = new ast::CastExpr(
    259                 func->location,
    260                 new ast::VariableExpr(func->location, param),
    261                 new ast::BasicType(ast::BasicKind::UnsignedInt),
    262                 ast::GeneratedFlag::ExplicitCast
    263         );
    264         ast::UntypedExpr* addOneExpr = ast::UntypedExpr::createCall( func->location,
    265                 opt,
    266                 {enumToInt,
    267                 ast::ConstantExpr::from_int(func->location, 1)}
    268         );
    269         auto intToEnum = new ast::CastExpr(
    270                 func->location,
    271                 addOneExpr,
    272                 new ast::EnumInstType( decl ),
    273                 ast::GeneratedFlag::ExplicitCast
    274         );
    275         func->stmts = new ast::CompoundStmt(
    276                 func->location, {
    277                         new ast::ReturnStmt(
    278                                 func->location,
    279                                 intToEnum
    280                         )
    281                 }
    282         );
    283 }
    284 
    285 
    286376void EnumAttrFuncGenerator::genSerialTraitFuncs() {
    287         ast::FunctionDecl * protos[4] = {
    288                 genFromIntProto(),
    289                 genFromInstanceProto(),
    290                 genInstToInstFuncProto("succ"),
    291                 genInstToInstFuncProto("pred")
    292         };
    293         for (auto& proto: protos) produceForwardDecl(proto);
    294         genFromIntBody(protos[0]);
    295         genFromInstanceBody(protos[1]);
    296         genSuccPredBody(protos[2], "?+?");
    297         genSuccPredBody(protos[3], "?-?");
    298 }
    299 
    300 ast::FunctionDecl* EnumAttrFuncGenerator::genInstToInstFuncProto(const char * func) const {
    301         return genProto(
    302                 func,
     377        auto fromIntProto = genFromIntProto();
     378        produceForwardDecl(fromIntProto);
     379        genFromIntBody(fromIntProto);
     380        produceDecl(fromIntProto);
     381
     382        auto fromInstanceProto = genFromInstanceProto();
     383        produceForwardDecl(fromInstanceProto);
     384        genFromInstanceBody(fromInstanceProto);
     385        produceDecl(fromInstanceProto);
     386
     387        auto succProto = genSuccProto();
     388        auto predProto = genPredProto();
     389        produceForwardDecl(succProto);
     390        produceForwardDecl(predProto);
     391}
     392
     393ast::FunctionDecl* EnumAttrFuncGenerator::genSuccProto() const {
     394        return genProto(
     395                "succ",
    303396                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    304397                {new ast::ObjectDecl(getLocation(), "_ret",
     
    306399}
    307400
    308 ast::FunctionDecl* EnumAttrFuncGenerator::genBoundedProto(const char * func) const {
    309     return genProto(func, {}, {
     401ast::FunctionDecl* EnumAttrFuncGenerator::genPredProto() const {
     402        return genProto(
     403                "pred",
     404                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
     405                {new ast::ObjectDecl(getLocation(), "_ret",
     406                                     new ast::EnumInstType(decl))});
     407}
     408
     409ast::FunctionDecl* EnumAttrFuncGenerator::genLowerBoundProto() const {
     410    return genProto("lowerBound", {}, {
    310411        new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))
    311412    });
    312413}
    313414
    314 void EnumAttrFuncGenerator::genBoundedBody(ast::FunctionDecl* func) const {
     415ast::FunctionDecl* EnumAttrFuncGenerator::genUpperBoundProto() const {
     416    return genProto("upperBound", {}, {
     417        new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))
     418    });
     419}
     420
     421void EnumAttrFuncGenerator::genLowerBoundBody(ast::FunctionDecl* func) const {
    315422        const CodeLocation & loc = func->location;
    316         auto mem = func->name=="lowerBound"?  decl->members.front() : decl->members.back();
     423        auto mem = decl->members.front();
     424        // auto expr = new ast::QualifiedNameExpr( loc, decl, mem->name );
     425        // expr->result = new ast::EnumInstType( decl );
    317426        auto expr = new ast::NameExpr( loc, mem->name );
    318427        func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});
    319428}
    320429
     430void EnumAttrFuncGenerator::genUpperBoundBody(ast::FunctionDecl* func) const {
     431        const CodeLocation & loc = func->location;
     432        auto mem = decl->members.back();
     433        auto expr = new ast::NameExpr( loc, mem->name );
     434        // expr->result = new ast::EnumInstType( decl );
     435        func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});   
     436}
     437
    321438void EnumAttrFuncGenerator::genBoundedFunctions() {
    322         ast::FunctionDecl * boundedProtos[2] = {genBoundedProto("upperBound"), genBoundedProto("lowerBound")};
    323         for (auto & protos: boundedProtos) {
    324                 produceForwardDecl(protos);
    325                 genBoundedBody(protos);
    326                 produceDecl(protos);
    327         }
     439        ast::FunctionDecl * upperDecl = genUpperBoundProto();
     440        produceForwardDecl(upperDecl);
     441        genUpperBoundBody(upperDecl);
     442        produceDecl(upperDecl);
     443
     444        ast::FunctionDecl * lowerDecl = genLowerBoundProto();
     445        produceForwardDecl(lowerDecl);
     446        genLowerBoundBody(lowerDecl);
     447        produceDecl(lowerDecl);
    328448}
    329449
    330450inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) {
    331451        return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
     452}
     453
     454ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPosProto() const {
     455        return genProto(
     456                "_successor_",
     457                {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
     458                {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
     459        );
     460}
     461
     462ast::FunctionDecl* EnumAttrFuncGenerator::genPredPosProto() const {
     463        return genProto(
     464                "_predessor_",
     465                {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
     466                {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
     467        );
    332468}
    333469
     
    375511}
    376512
    377 void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) {
     513void EnumAttrFuncGenerator::genAttributesDecls(const ast::EnumAttribute attr) {
    378514        if (attr == ast::EnumAttribute::Value ||
    379515                attr == ast::EnumAttribute::Label) {
    380                 // TypedEnum's backing arrays
    381516                std::vector<ast::ptr<ast::Init>> inits =
    382517                        attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit();
     
    399534}
    400535
    401 void EnumAttrFuncGenerator::genTypedEnumFuncs() {
    402         if (decl->base) genTypedEnumFunction(ast::EnumAttribute::Value);
    403         genTypedEnumFunction(ast::EnumAttribute::Label);
    404         genTypedEnumFunction(ast::EnumAttribute::Posn);
     536ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPredFunc(bool succ) {
     537        ast::FunctionDecl* funcDecl = succ ? genSuccPosProto() : genPredPosProto();
     538        produceForwardDecl(funcDecl);
     539
     540        const CodeLocation& location = getLocation();
     541
     542        auto& params = funcDecl->params;
     543        assert(params.size() == 1);
     544        auto param = params.front().strict_as<ast::ObjectDecl>();
     545
     546
     547        auto rets = funcDecl->returns;
     548        assert(params.size() == 1);
     549        auto ret = rets.front().strict_as<ast::ObjectDecl>();
     550        auto retType = ret->type.strict_as<ast::EnumAttrType>();
     551
     552        auto addOneExpr = ast::UntypedExpr::createCall( location,
     553                succ? "?+?": "?-?",
     554                {new ast::VariableExpr(location, param),
     555                ast::ConstantExpr::from_int(location, 1)}
     556        );
     557
     558        funcDecl->stmts = new ast::CompoundStmt(
     559                location, {
     560                        new ast::ReturnStmt(
     561                                location,
     562                                new ast::CastExpr(location, addOneExpr, retType)
     563                        )
     564                }
     565        );
     566
     567        return funcDecl;
     568}
     569
     570void EnumAttrFuncGenerator::genAttrFunctions() {
     571        genAttributesDecls(ast::EnumAttribute::Value);
     572        genAttributesDecls(ast::EnumAttribute::Label);
     573        genAttributesDecls(ast::EnumAttribute::Posn);   
     574}
     575
     576// void EnumAttrFuncGenerator::genSuccPredDecl() {
     577//      auto succProto = genSuccProto();
     578//      auto predProto = genPredProto();
     579
     580//      produceForwardDecl(succProto);
     581//      produceForwardDecl(predProto);
     582// }
     583
     584void EnumAttrFuncGenerator::genSuccPredPosn() {
     585        ast::FunctionDecl* succ = genSuccPredFunc(true);
     586        ast::FunctionDecl* pred = genSuccPredFunc(false);
     587
     588        produceDecl(succ);
     589        produceDecl(pred);
    405590}
    406591
     
    408593        std::list<ast::ptr<ast::Decl>>& decls) {
    409594        // Generate the functions (they go into forwards and definitions).
    410         genTypedEnumFuncs();
     595        genAttrStandardFuncs();
     596        genAttrFunctions();
    411597        genSerialTraitFuncs();
     598        genSuccPredPosn();
     599        // problematic
    412600        genBoundedFunctions();
    413601        // Now export the lists contents.
     
    430618
    431619void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
    432         if (!enumDecl->body || !enumDecl->isTyped) return;
     620        if (!enumDecl->body) return;
     621        if (!enumDecl->base) return;
     622
    433623        ast::EnumInstType enumInst(enumDecl->name);
    434624        enumInst.base = enumDecl;
     625
    435626        EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
    436627        gen.generateAndAppendFunctions(declsToAddAfter);
Note: See TracChangeset for help on using the changeset viewer.