- File:
-
- 1 edited
-
src/Validate/ImplementEnumFunc.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Validate/ImplementEnumFunc.cpp
rfc1a3e2 rcf191ac 8 8 namespace { 9 9 class 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); 201 204 }; 202 205 203 206 std::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; 214 217 } 215 218 216 219 std::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; 235 238 } 236 239 const 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 now247 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 } 256 259 } 257 260 258 261 ast::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; 274 277 } 275 278 276 279 void 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); 280 283 } 281 284 282 285 void 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); 288 291 } 289 292 290 293 ast::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))}); 296 299 } 297 300 298 301 ast::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}))}); 305 308 } 306 309 307 310 ast::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))}); 313 316 } 314 317 315 318 ast::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))}); 321 324 } 322 325 323 326 ast::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))}); 329 332 } 330 333 331 334 inline 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); 333 336 } 334 337 335 338 ast::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 ); 341 344 } 342 345 343 346 ast::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 ); 349 352 } 350 353 351 354 ast::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; 368 370 } 369 371 370 372 void 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)}); 382 384 } 383 385 384 386 void 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)}); 392 394 } 393 395 394 396 void 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 } 415 417 } 416 418 417 419 ast::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; 449 451 } 450 452 451 453 void 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 } 457 459 } 458 460 459 461 void 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 } 467 469 } 468 470 469 471 void 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 } 477 479 } 478 480 479 481 void 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(); // Posn486 // 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); 489 491 } 490 492 491 493 // --------------------------------------------------------- 492 494 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;495 struct ImplementEnumFunc final : public ast::WithDeclsToAdd<>, 496 public ast::WithShortCircuiting { 497 void previsit(const ast::EnumDecl* enumDecl); 498 void previsit(const ast::FunctionDecl* functionDecl); 499 void postvisit(const ast::FunctionDecl* functionDecl); 500 501 private: 502 // Current level of nested functions. 503 unsigned int functionNesting = 0; 502 504 }; 503 505 504 506 void 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); 513 515 } 514 516 515 517 void ImplementEnumFunc::previsit(const ast::FunctionDecl*) { 516 functionNesting += 1;518 functionNesting += 1; 517 519 } 518 520 519 521 void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) { 520 functionNesting -= 1;521 } 522 523 } // namespace522 functionNesting -= 1; 523 } 524 525 } // namespace 524 526 525 527 void 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.