source: src/Validate/ImplementEnumFunc.cpp@ 083e637

Last change on this file since 083e637 was eb7586e, checked in by JiadaL <j82liang@…>, 17 months 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.