VariantValue.cpp revision 1.1.1.2
1//===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8/// 9/// \file 10/// Polymorphic value type. 11/// 12//===----------------------------------------------------------------------===// 13 14#include "clang/ASTMatchers/Dynamic/VariantValue.h" 15#include "clang/Basic/LLVM.h" 16#include "llvm/ADT/STLExtras.h" 17 18namespace clang { 19namespace ast_matchers { 20namespace dynamic { 21 22std::string ArgKind::asString() const { 23 switch (getArgKind()) { 24 case AK_Matcher: 25 return (Twine("Matcher<") + NodeKind.asStringRef() + ">").str(); 26 case AK_Node: 27 return NodeKind.asStringRef().str(); 28 case AK_Boolean: 29 return "boolean"; 30 case AK_Double: 31 return "double"; 32 case AK_Unsigned: 33 return "unsigned"; 34 case AK_String: 35 return "string"; 36 } 37 llvm_unreachable("unhandled ArgKind"); 38} 39 40bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const { 41 if (K != To.K) 42 return false; 43 if (K != AK_Matcher && K != AK_Node) { 44 if (Specificity) 45 *Specificity = 1; 46 return true; 47 } 48 unsigned Distance; 49 if (!NodeKind.isBaseOf(To.NodeKind, &Distance)) 50 return false; 51 52 if (Specificity) 53 *Specificity = 100 - Distance; 54 return true; 55} 56 57bool 58VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher, 59 bool &IsExactMatch) const { 60 IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind); 61 return Matcher.canConvertTo(NodeKind); 62} 63 64DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher( 65 const DynTypedMatcher &Matcher) const { 66 return Matcher.dynCastTo(NodeKind); 67} 68 69llvm::Optional<DynTypedMatcher> 70VariantMatcher::MatcherOps::constructVariadicOperator( 71 DynTypedMatcher::VariadicOperator Op, 72 ArrayRef<VariantMatcher> InnerMatchers) const { 73 std::vector<DynTypedMatcher> DynMatchers; 74 for (const auto &InnerMatcher : InnerMatchers) { 75 // Abort if any of the inner matchers can't be converted to 76 // Matcher<T>. 77 if (!InnerMatcher.Value) 78 return llvm::None; 79 llvm::Optional<DynTypedMatcher> Inner = 80 InnerMatcher.Value->getTypedMatcher(*this); 81 if (!Inner) 82 return llvm::None; 83 DynMatchers.push_back(*Inner); 84 } 85 return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers); 86} 87 88VariantMatcher::Payload::~Payload() {} 89 90class VariantMatcher::SinglePayload : public VariantMatcher::Payload { 91public: 92 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {} 93 94 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 95 return Matcher; 96 } 97 98 std::string getTypeAsString() const override { 99 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">") 100 .str(); 101 } 102 103 llvm::Optional<DynTypedMatcher> 104 getTypedMatcher(const MatcherOps &Ops) const override { 105 bool Ignore; 106 if (Ops.canConstructFrom(Matcher, Ignore)) 107 return Matcher; 108 return llvm::None; 109 } 110 111 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { 112 return ArgKind::MakeMatcherArg(Matcher.getSupportedKind()) 113 .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), Specificity); 114 } 115 116private: 117 const DynTypedMatcher Matcher; 118}; 119 120class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { 121public: 122 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn) 123 : Matchers(std::move(MatchersIn)) {} 124 125 ~PolymorphicPayload() override {} 126 127 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 128 if (Matchers.size() != 1) 129 return llvm::Optional<DynTypedMatcher>(); 130 return Matchers[0]; 131 } 132 133 std::string getTypeAsString() const override { 134 std::string Inner; 135 for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 136 if (i != 0) 137 Inner += "|"; 138 Inner += Matchers[i].getSupportedKind().asStringRef(); 139 } 140 return (Twine("Matcher<") + Inner + ">").str(); 141 } 142 143 llvm::Optional<DynTypedMatcher> 144 getTypedMatcher(const MatcherOps &Ops) const override { 145 bool FoundIsExact = false; 146 const DynTypedMatcher *Found = nullptr; 147 int NumFound = 0; 148 for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 149 bool IsExactMatch; 150 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) { 151 if (Found) { 152 if (FoundIsExact) { 153 assert(!IsExactMatch && "We should not have two exact matches."); 154 continue; 155 } 156 } 157 Found = &Matchers[i]; 158 FoundIsExact = IsExactMatch; 159 ++NumFound; 160 } 161 } 162 // We only succeed if we found exactly one, or if we found an exact match. 163 if (Found && (FoundIsExact || NumFound == 1)) 164 return *Found; 165 return llvm::None; 166 } 167 168 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { 169 unsigned MaxSpecificity = 0; 170 for (const DynTypedMatcher &Matcher : Matchers) { 171 unsigned ThisSpecificity; 172 if (ArgKind::MakeMatcherArg(Matcher.getSupportedKind()) 173 .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), 174 &ThisSpecificity)) { 175 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); 176 } 177 } 178 if (Specificity) 179 *Specificity = MaxSpecificity; 180 return MaxSpecificity > 0; 181 } 182 183 const std::vector<DynTypedMatcher> Matchers; 184}; 185 186class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { 187public: 188 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op, 189 std::vector<VariantMatcher> Args) 190 : Op(Op), Args(std::move(Args)) {} 191 192 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 193 return llvm::Optional<DynTypedMatcher>(); 194 } 195 196 std::string getTypeAsString() const override { 197 std::string Inner; 198 for (size_t i = 0, e = Args.size(); i != e; ++i) { 199 if (i != 0) 200 Inner += "&"; 201 Inner += Args[i].getTypeAsString(); 202 } 203 return Inner; 204 } 205 206 llvm::Optional<DynTypedMatcher> 207 getTypedMatcher(const MatcherOps &Ops) const override { 208 return Ops.constructVariadicOperator(Op, Args); 209 } 210 211 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { 212 for (const VariantMatcher &Matcher : Args) { 213 if (!Matcher.isConvertibleTo(Kind, Specificity)) 214 return false; 215 } 216 return true; 217 } 218 219private: 220 const DynTypedMatcher::VariadicOperator Op; 221 const std::vector<VariantMatcher> Args; 222}; 223 224VariantMatcher::VariantMatcher() {} 225 226VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { 227 return VariantMatcher(std::make_shared<SinglePayload>(Matcher)); 228} 229 230VariantMatcher 231VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { 232 return VariantMatcher( 233 std::make_shared<PolymorphicPayload>(std::move(Matchers))); 234} 235 236VariantMatcher VariantMatcher::VariadicOperatorMatcher( 237 DynTypedMatcher::VariadicOperator Op, 238 std::vector<VariantMatcher> Args) { 239 return VariantMatcher( 240 std::make_shared<VariadicOpPayload>(Op, std::move(Args))); 241} 242 243llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { 244 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>(); 245} 246 247void VariantMatcher::reset() { Value.reset(); } 248 249std::string VariantMatcher::getTypeAsString() const { 250 if (Value) return Value->getTypeAsString(); 251 return "<Nothing>"; 252} 253 254VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { 255 *this = Other; 256} 257 258VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) { 259 setBoolean(Boolean); 260} 261 262VariantValue::VariantValue(double Double) : Type(VT_Nothing) { 263 setDouble(Double); 264} 265 266VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { 267 setUnsigned(Unsigned); 268} 269 270VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) { 271 setString(String); 272} 273 274VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) { 275 setNodeKind(NodeKind); 276} 277 278VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) { 279 setMatcher(Matcher); 280} 281 282VariantValue::~VariantValue() { reset(); } 283 284VariantValue &VariantValue::operator=(const VariantValue &Other) { 285 if (this == &Other) return *this; 286 reset(); 287 switch (Other.Type) { 288 case VT_Boolean: 289 setBoolean(Other.getBoolean()); 290 break; 291 case VT_Double: 292 setDouble(Other.getDouble()); 293 break; 294 case VT_Unsigned: 295 setUnsigned(Other.getUnsigned()); 296 break; 297 case VT_String: 298 setString(Other.getString()); 299 break; 300 case VT_NodeKind: 301 setNodeKind(Other.getNodeKind()); 302 break; 303 case VT_Matcher: 304 setMatcher(Other.getMatcher()); 305 break; 306 case VT_Nothing: 307 Type = VT_Nothing; 308 break; 309 } 310 return *this; 311} 312 313void VariantValue::reset() { 314 switch (Type) { 315 case VT_String: 316 delete Value.String; 317 break; 318 case VT_Matcher: 319 delete Value.Matcher; 320 break; 321 case VT_NodeKind: 322 delete Value.NodeKind; 323 break; 324 // Cases that do nothing. 325 case VT_Boolean: 326 case VT_Double: 327 case VT_Unsigned: 328 case VT_Nothing: 329 break; 330 } 331 Type = VT_Nothing; 332} 333 334bool VariantValue::isBoolean() const { 335 return Type == VT_Boolean; 336} 337 338bool VariantValue::getBoolean() const { 339 assert(isBoolean()); 340 return Value.Boolean; 341} 342 343void VariantValue::setBoolean(bool NewValue) { 344 reset(); 345 Type = VT_Boolean; 346 Value.Boolean = NewValue; 347} 348 349bool VariantValue::isDouble() const { 350 return Type == VT_Double; 351} 352 353double VariantValue::getDouble() const { 354 assert(isDouble()); 355 return Value.Double; 356} 357 358void VariantValue::setDouble(double NewValue) { 359 reset(); 360 Type = VT_Double; 361 Value.Double = NewValue; 362} 363 364bool VariantValue::isUnsigned() const { 365 return Type == VT_Unsigned; 366} 367 368unsigned VariantValue::getUnsigned() const { 369 assert(isUnsigned()); 370 return Value.Unsigned; 371} 372 373void VariantValue::setUnsigned(unsigned NewValue) { 374 reset(); 375 Type = VT_Unsigned; 376 Value.Unsigned = NewValue; 377} 378 379bool VariantValue::isString() const { 380 return Type == VT_String; 381} 382 383const std::string &VariantValue::getString() const { 384 assert(isString()); 385 return *Value.String; 386} 387 388void VariantValue::setString(StringRef NewValue) { 389 reset(); 390 Type = VT_String; 391 Value.String = new std::string(NewValue); 392} 393 394bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; } 395 396const ASTNodeKind &VariantValue::getNodeKind() const { 397 assert(isNodeKind()); 398 return *Value.NodeKind; 399} 400 401void VariantValue::setNodeKind(ASTNodeKind NewValue) { 402 reset(); 403 Type = VT_NodeKind; 404 Value.NodeKind = new ASTNodeKind(NewValue); 405} 406 407bool VariantValue::isMatcher() const { 408 return Type == VT_Matcher; 409} 410 411const VariantMatcher &VariantValue::getMatcher() const { 412 assert(isMatcher()); 413 return *Value.Matcher; 414} 415 416void VariantValue::setMatcher(const VariantMatcher &NewValue) { 417 reset(); 418 Type = VT_Matcher; 419 Value.Matcher = new VariantMatcher(NewValue); 420} 421 422bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const { 423 switch (Kind.getArgKind()) { 424 case ArgKind::AK_Boolean: 425 if (!isBoolean()) 426 return false; 427 *Specificity = 1; 428 return true; 429 430 case ArgKind::AK_Double: 431 if (!isDouble()) 432 return false; 433 *Specificity = 1; 434 return true; 435 436 case ArgKind::AK_Unsigned: 437 if (!isUnsigned()) 438 return false; 439 *Specificity = 1; 440 return true; 441 442 case ArgKind::AK_String: 443 if (!isString()) 444 return false; 445 *Specificity = 1; 446 return true; 447 448 case ArgKind::AK_Node: 449 if (!isNodeKind()) 450 return false; 451 return getMatcher().isConvertibleTo(Kind.getNodeKind(), Specificity); 452 453 case ArgKind::AK_Matcher: 454 if (!isMatcher()) 455 return false; 456 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity); 457 } 458 llvm_unreachable("Invalid Type"); 459} 460 461bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds, 462 unsigned *Specificity) const { 463 unsigned MaxSpecificity = 0; 464 for (const ArgKind& Kind : Kinds) { 465 unsigned ThisSpecificity; 466 if (!isConvertibleTo(Kind, &ThisSpecificity)) 467 continue; 468 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); 469 } 470 if (Specificity && MaxSpecificity > 0) { 471 *Specificity = MaxSpecificity; 472 } 473 return MaxSpecificity > 0; 474} 475 476std::string VariantValue::getTypeAsString() const { 477 switch (Type) { 478 case VT_String: return "String"; 479 case VT_Matcher: return getMatcher().getTypeAsString(); 480 case VT_Boolean: return "Boolean"; 481 case VT_Double: return "Double"; 482 case VT_Unsigned: return "Unsigned"; 483 case VT_NodeKind: 484 return getNodeKind().asStringRef().str(); 485 case VT_Nothing: return "Nothing"; 486 } 487 llvm_unreachable("Invalid Type"); 488} 489 490} // end namespace dynamic 491} // end namespace ast_matchers 492} // end namespace clang 493