source: src/Validate/ImplementEnumFunc.cpp @ 0153dbd

Last change on this file since 0153dbd was eb7586e, checked in by JiadaL <j82liang@…>, 5 weeks ago
  1. Change return value of typed Enum in null context: they now return the position. Therefore, printf with enumeration value will no longer be supported. 2. sout now will return the enumeration value. So sout | enumValue will print what we expect. 3. Provide enum.hfa, which contains traits that related to enum. 4. Implement functions declare in enum.hfa for enum types, so enum type fulfill the traits. Known defeat: error if we use the enum traits on enum types. They work but c compiler gives an warning
  • Property mode set to 100644
File size: 20.8 KB
Line 
1#include "AST/Create.hpp"
2#include "AST/Pass.hpp"
3#include "AST/TranslationUnit.hpp"
4#include "CodeGen/OperatorTable.h"  // for isCtorDtor, isCtorDtorAssign
5#include "InitTweak/InitTweak.h"    // for isAssignment, isCopyConstructor
6namespace Validate {
7
8namespace {
9class EnumAttrFuncGenerator {
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        // Implement Bounded trait for enum
76    void genBoundedFunctions();
77        // Implement Serial trait for enum
78        void genSerialTraitFuncs();
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
86        ast::FunctionDecl* genPosnProto() const;
87        ast::FunctionDecl* genLabelProto() const;
88        ast::FunctionDecl* genValueProto() const;
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;
98        ////////////////
99
100        ast::FunctionDecl* genSuccPosProto() const;
101        ast::FunctionDecl* genPredPosProto() const;
102
103        // ---------------------------------------------------
104        // ast::FunctionDecl* genAttrCtorProto() const;
105        /// Changes the node inside a pointer so that it has the unused attribute.
106        void addUnusedAttribute(ast::ptr<ast::DeclWithType>& declPtr) {
107                ast::DeclWithType* decl = declPtr.get_and_mutate();
108                decl->attributes.push_back(new ast::Attribute("unused"));
109        }
110
111        ast::ObjectDecl* dstParam() const {
112                return new ast::ObjectDecl(getLocation(), "_dst",
113                                           new ast::ReferenceType(new ast::EnumAttrType(
114                                               ast::deepCopy(instType))));
115        }
116
117        ast::ObjectDecl* srcParam() const {
118                return new ast::ObjectDecl(
119                        getLocation(), "_src",
120                        new ast::EnumAttrType(ast::deepCopy(instType)));
121        }
122
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*
204        // ----------------------------------------------------
205
206        ast::FunctionDecl* genSuccPredFunc(bool succ);
207
208        const ast::Init* getAutoInit(const ast::Init* prev) const;
209
210        std::vector<ast::ptr<ast::Init>> genLabelInit() const;
211
212        std::vector<ast::ptr<ast::Init>> genValueInit() const;
213        ast::ObjectDecl* genAttrArrayProto(
214                const ast::EnumAttribute attr, const CodeLocation& location,
215                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);
220};
221
222std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genLabelInit() const {
223        std::vector<ast::ptr<ast::Init>> inits;
224        for (size_t i = 0; i < decl->members.size(); i++) {
225                ast::ptr<ast::Decl> mem = decl->members.at(i);
226                auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
227                assert(memAsObjectDecl);
228                inits.emplace_back(new ast::SingleInit(
229                        mem->location,
230                        ast::ConstantExpr::from_string(mem->location, mem->name)));
231        }
232        return inits;
233}
234
235std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genValueInit() const {
236        std::vector<ast::ptr<ast::Init>> inits;
237        for (size_t i = 0; i < decl->members.size(); i++) {
238                ast::ptr<ast::Decl> mem = decl->members.at(i);
239                auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
240                assert(memAsObjectDecl);
241                if (memAsObjectDecl->init) {
242                        inits.emplace_back(memAsObjectDecl->init);
243                } else {
244                        const CodeLocation& location = mem->location;
245                        if (i == 0) {
246                                inits.emplace_back(new ast::SingleInit(
247                                        location, ast::ConstantExpr::from_int(mem->location, 0)));
248                        } else {
249                                inits.emplace_back(getAutoInit(inits.at(i - 1)));
250                        }
251                }
252        }
253        return inits;
254}
255const ast::Init* EnumAttrFuncGenerator::getAutoInit(
256        const ast::Init* prev) const {
257        if (prev == nullptr) {
258                return new ast::SingleInit(
259                        getLocation(), ast::ConstantExpr::from_int(getLocation(), 0));
260        }
261        auto prevInit = dynamic_cast<const ast::SingleInit*>(prev);
262        assert(prevInit);
263        auto prevInitExpr = prevInit->value;
264        if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
265                // Assume no string literal for now
266                return new ast::SingleInit(
267                        getLocation(), ast::ConstantExpr::from_int(
268                                getLocation(), constInit->intValue() + 1));
269        } else {
270                auto untypedThisInit = new ast::UntypedExpr(
271                        getLocation(), new ast::NameExpr(getLocation(), "?++"),
272                        {prevInitExpr});
273                return new ast::SingleInit(getLocation(), untypedThisInit);
274        }
275}
276
277ast::FunctionDecl* EnumAttrFuncGenerator::genProto(
278        std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
279        std::vector<ast::ptr<ast::DeclWithType>>&& returns) const {
280        ast::FunctionDecl* decl = new ast::FunctionDecl(
281                // Auto-generated routines use the type declaration's location.
282                getLocation(), std::move(name), {}, {}, std::move(params),
283                std::move(returns),
284                // Only a prototype, no body.
285                nullptr,
286                // Use static storage if we are at the top level.
287                (0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static,
288                proto_linkage, std::vector<ast::ptr<ast::Attribute>>(),
289                // Auto-generated routines are inline to avoid conflicts.
290                ast::Function::Specs(ast::Function::Inline));
291        decl->fixUniqueId();
292        return decl;
293}
294
295void EnumAttrFuncGenerator::produceDecl(const ast::FunctionDecl* decl) {
296        assert(nullptr != decl->stmts);
297
298        definitions.push_back(decl);
299}
300
301void EnumAttrFuncGenerator::produceForwardDecl(const ast::FunctionDecl* decl) {
302        if (0 != functionNesting) return;
303        ast::FunctionDecl* fwd =
304                (decl->stmts) ? ast::asForward(decl) : ast::deepCopy(decl);
305        fwd->fixUniqueId();
306        forwards.push_back(fwd);
307}
308
309ast::FunctionDecl* EnumAttrFuncGenerator::genPosnProto() const {
310    return genProto(
311        "posE",
312        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
313        {new ast::ObjectDecl(getLocation(), "_ret",
314            new ast::BasicType(ast::BasicKind::UnsignedInt))});
315}
316
317ast::FunctionDecl* EnumAttrFuncGenerator::genLabelProto() const {
318        return genProto(
319                "labelE",
320                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
321                {new ast::ObjectDecl(
322                        getLocation(), "_ret",
323                        new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}))});
324}
325
326ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const {
327        return genProto(
328                "valueE",
329                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
330                {new ast::ObjectDecl(getLocation(), "_ret",
331                                     ast::deepCopy(decl->base))});
332}
333
334ast::FunctionDecl* EnumAttrFuncGenerator::genFromIntProto() const {
335        return genProto(
336                "fromInt",
337                {new ast::ObjectDecl(getLocation(), "_i", new ast::BasicType(ast::BasicKind::UnsignedInt))},
338                {new ast::ObjectDecl(getLocation(), "_ret", new ast::EnumInstType(decl))}
339        );
340}
341
342ast::FunctionDecl* EnumAttrFuncGenerator::genFromInstanceProto() const {
343        return genProto(
344                "fromInstance",
345                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
346                {new ast::ObjectDecl(getLocation(), "_ret", new ast::BasicType(ast::BasicKind::UnsignedInt))}
347        );
348}
349
350void EnumAttrFuncGenerator::genFromIntBody(ast::FunctionDecl* func) const {
351        auto params = func->params;
352        assert( params.size() == 1 );
353        auto param = params.front();
354        auto castExpr = new ast::CastExpr(
355                func->location,
356                new ast::VariableExpr(func->location, param),
357                new ast::EnumInstType(decl),
358                ast::GeneratedFlag::ExplicitCast
359        );
360        func->stmts = new ast::CompoundStmt(
361                func->location, {new ast::ReturnStmt(func->location, castExpr)}
362        );
363}
364
365void EnumAttrFuncGenerator::genFromInstanceBody(ast::FunctionDecl* func) const {
366        auto params = func->params;
367        assert( params.size() == 1 );
368        auto param = params.front();
369        ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
370                func->location, "posE", { new ast::VariableExpr(func->location, param) });
371        func->stmts = new ast::CompoundStmt(
372                func->location, {new ast::ReturnStmt(func->location, untyped)}
373        );
374}
375
376void EnumAttrFuncGenerator::genSerialTraitFuncs() {
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",
396                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
397                {new ast::ObjectDecl(getLocation(), "_ret",
398                                     new ast::EnumInstType(decl))});
399}
400
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", {}, {
411        new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))
412    });
413}
414
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 {
422        const CodeLocation & loc = func->location;
423        auto mem = decl->members.front();
424        // auto expr = new ast::QualifiedNameExpr( loc, decl, mem->name );
425        // expr->result = new ast::EnumInstType( decl );
426        auto expr = new ast::NameExpr( loc, mem->name );
427        func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});
428}
429
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
438void EnumAttrFuncGenerator::genBoundedFunctions() {
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);
448}
449
450inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) {
451        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        );
468}
469
470ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
471        const ast::EnumAttribute attr, const CodeLocation& location,
472        std::vector<ast::ptr<ast::Init>>& inits) const {
473        ast::ArrayType* arrT = new ast::ArrayType(
474                attr == ast::EnumAttribute::Value
475                        ? decl->base
476                        : new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}),
477                ast::ConstantExpr::from_int(decl->location, decl->members.size()),
478                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
479
480        ast::ObjectDecl* objDecl =
481                new ast::ObjectDecl(
482                        decl->location, decl->getUnmangeldArrayName( attr ),
483                        arrT, new ast::ListInit( location, std::move( inits ) ),
484                        ast::Storage::Static, ast::Linkage::AutoGen );
485
486        return objDecl;
487}
488
489void EnumAttrFuncGenerator::genValueOrLabelBody(
490        ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const {
491        ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
492                func->location, "?[?]",
493                {new ast::NameExpr(func->location, arrDecl->name),
494                new ast::CastExpr(
495                        func->location,
496                        new ast::VariableExpr( func->location, func->params.front() ),
497                        new ast::EnumAttrType( new ast::EnumInstType(decl),
498                                ast::EnumAttribute::Posn))});
499        func->stmts = new ast::CompoundStmt(
500                func->location, {new ast::ReturnStmt(func->location, untyped)});
501}
502
503void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const {
504        auto castExpr = new ast::CastExpr(
505                func->location,
506                new ast::VariableExpr(func->location, func->params.front()),
507                new ast::EnumAttrType(new ast::EnumInstType(decl),
508                                                          ast::EnumAttribute::Posn));
509        func->stmts = new ast::CompoundStmt(
510                func->location, {new ast::ReturnStmt(func->location, castExpr)});
511}
512
513void EnumAttrFuncGenerator::genAttributesDecls(const ast::EnumAttribute attr) {
514        if (attr == ast::EnumAttribute::Value ||
515                attr == ast::EnumAttribute::Label) {
516                std::vector<ast::ptr<ast::Init>> inits =
517                        attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit();
518                ast::ObjectDecl* arrayProto =
519                        genAttrArrayProto(attr, getLocation(), inits);
520                forwards.push_back(arrayProto);
521
522                ast::FunctionDecl* funcProto = ( attr == ast::EnumAttribute::Value )
523                                               ? genValueProto()
524                                               : genLabelProto();
525                produceForwardDecl(funcProto);
526                genValueOrLabelBody(funcProto, arrayProto);
527                produceDecl(funcProto);
528        } else {
529                ast::FunctionDecl* funcProto = genPosnProto();
530                produceForwardDecl(funcProto);
531                genPosnBody(funcProto);
532                produceDecl(funcProto);
533        }
534}
535
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);
590}
591
592void EnumAttrFuncGenerator::generateAndAppendFunctions(
593        std::list<ast::ptr<ast::Decl>>& decls) {
594        // Generate the functions (they go into forwards and definitions).
595        genAttrStandardFuncs();
596        genAttrFunctions();
597        genSerialTraitFuncs();
598        genSuccPredPosn();
599        // problematic
600        genBoundedFunctions();
601        // Now export the lists contents.
602        decls.splice(decls.end(), forwards);
603        decls.splice(decls.end(), definitions);
604}
605
606// ---------------------------------------------------------
607
608struct ImplementEnumFunc final :
609                public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting {
610        void previsit(const ast::EnumDecl* enumDecl);
611        void previsit(const ast::FunctionDecl* functionDecl);
612        void postvisit(const ast::FunctionDecl* functionDecl);
613
614private:
615        // Current level of nested functions.
616        unsigned int functionNesting = 0;
617};
618
619void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
620        if (!enumDecl->body) return;
621        if (!enumDecl->base) return;
622
623        ast::EnumInstType enumInst(enumDecl->name);
624        enumInst.base = enumDecl;
625
626        EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
627        gen.generateAndAppendFunctions(declsToAddAfter);
628}
629
630void ImplementEnumFunc::previsit(const ast::FunctionDecl*) {
631        functionNesting += 1;
632}
633
634void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) {
635        functionNesting -= 1;
636}
637
638} // namespace
639
640void implementEnumFunc(ast::TranslationUnit& translationUnit) {
641        ast::Pass<ImplementEnumFunc>::run(translationUnit);
642}
643
644} // namespace Validate
Note: See TracBrowser for help on using the repository browser.