VariantValue.cpp revision 321369
1259701Sdim//===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/ 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim/// 10259701Sdim/// \file 11259701Sdim/// \brief Polymorphic value type. 12259701Sdim/// 13259701Sdim//===----------------------------------------------------------------------===// 14259701Sdim 15259701Sdim#include "clang/ASTMatchers/Dynamic/VariantValue.h" 16259701Sdim#include "clang/Basic/LLVM.h" 17259701Sdim#include "llvm/ADT/STLExtras.h" 18259701Sdim 19259701Sdimnamespace clang { 20259701Sdimnamespace ast_matchers { 21259701Sdimnamespace dynamic { 22259701Sdim 23280031Sdimstd::string ArgKind::asString() const { 24280031Sdim switch (getArgKind()) { 25280031Sdim case AK_Matcher: 26280031Sdim return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str(); 27321369Sdim case AK_Boolean: 28321369Sdim return "boolean"; 29321369Sdim case AK_Double: 30321369Sdim return "double"; 31280031Sdim case AK_Unsigned: 32280031Sdim return "unsigned"; 33280031Sdim case AK_String: 34280031Sdim return "string"; 35280031Sdim } 36280031Sdim llvm_unreachable("unhandled ArgKind"); 37280031Sdim} 38280031Sdim 39280031Sdimbool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const { 40280031Sdim if (K != To.K) 41280031Sdim return false; 42280031Sdim if (K != AK_Matcher) { 43280031Sdim if (Specificity) 44280031Sdim *Specificity = 1; 45280031Sdim return true; 46280031Sdim } 47280031Sdim unsigned Distance; 48280031Sdim if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance)) 49280031Sdim return false; 50280031Sdim 51280031Sdim if (Specificity) 52280031Sdim *Specificity = 100 - Distance; 53280031Sdim return true; 54280031Sdim} 55280031Sdim 56280031Sdimbool 57280031SdimVariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher, 58280031Sdim bool &IsExactMatch) const { 59280031Sdim IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind); 60280031Sdim return Matcher.canConvertTo(NodeKind); 61280031Sdim} 62280031Sdim 63280031Sdimllvm::Optional<DynTypedMatcher> 64280031SdimVariantMatcher::MatcherOps::constructVariadicOperator( 65280031Sdim DynTypedMatcher::VariadicOperator Op, 66280031Sdim ArrayRef<VariantMatcher> InnerMatchers) const { 67280031Sdim std::vector<DynTypedMatcher> DynMatchers; 68280031Sdim for (const auto &InnerMatcher : InnerMatchers) { 69280031Sdim // Abort if any of the inner matchers can't be converted to 70280031Sdim // Matcher<T>. 71280031Sdim if (!InnerMatcher.Value) 72280031Sdim return llvm::None; 73280031Sdim llvm::Optional<DynTypedMatcher> Inner = 74280031Sdim InnerMatcher.Value->getTypedMatcher(*this); 75280031Sdim if (!Inner) 76280031Sdim return llvm::None; 77280031Sdim DynMatchers.push_back(*Inner); 78280031Sdim } 79296417Sdim return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers); 80280031Sdim} 81280031Sdim 82259701SdimVariantMatcher::Payload::~Payload() {} 83259701Sdim 84259701Sdimclass VariantMatcher::SinglePayload : public VariantMatcher::Payload { 85259701Sdimpublic: 86259701Sdim SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {} 87259701Sdim 88280031Sdim llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 89259701Sdim return Matcher; 90259701Sdim } 91259701Sdim 92280031Sdim std::string getTypeAsString() const override { 93259701Sdim return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">") 94259701Sdim .str(); 95259701Sdim } 96259701Sdim 97280031Sdim llvm::Optional<DynTypedMatcher> 98280031Sdim getTypedMatcher(const MatcherOps &Ops) const override { 99276479Sdim bool Ignore; 100276479Sdim if (Ops.canConstructFrom(Matcher, Ignore)) 101280031Sdim return Matcher; 102280031Sdim return llvm::None; 103259701Sdim } 104259701Sdim 105280031Sdim bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 106280031Sdim unsigned *Specificity) const override { 107280031Sdim return ArgKind(Matcher.getSupportedKind()) 108280031Sdim .isConvertibleTo(Kind, Specificity); 109280031Sdim } 110280031Sdim 111259701Sdimprivate: 112259701Sdim const DynTypedMatcher Matcher; 113259701Sdim}; 114259701Sdim 115259701Sdimclass VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { 116259701Sdimpublic: 117276479Sdim PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn) 118276479Sdim : Matchers(std::move(MatchersIn)) {} 119259701Sdim 120280031Sdim ~PolymorphicPayload() override {} 121259701Sdim 122280031Sdim llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 123259701Sdim if (Matchers.size() != 1) 124259701Sdim return llvm::Optional<DynTypedMatcher>(); 125259701Sdim return Matchers[0]; 126259701Sdim } 127259701Sdim 128280031Sdim std::string getTypeAsString() const override { 129259701Sdim std::string Inner; 130259701Sdim for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 131259701Sdim if (i != 0) 132259701Sdim Inner += "|"; 133259701Sdim Inner += Matchers[i].getSupportedKind().asStringRef(); 134259701Sdim } 135259701Sdim return (Twine("Matcher<") + Inner + ">").str(); 136259701Sdim } 137259701Sdim 138280031Sdim llvm::Optional<DynTypedMatcher> 139280031Sdim getTypedMatcher(const MatcherOps &Ops) const override { 140276479Sdim bool FoundIsExact = false; 141276479Sdim const DynTypedMatcher *Found = nullptr; 142276479Sdim int NumFound = 0; 143259701Sdim for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 144276479Sdim bool IsExactMatch; 145276479Sdim if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) { 146276479Sdim if (Found) { 147276479Sdim if (FoundIsExact) { 148276479Sdim assert(!IsExactMatch && "We should not have two exact matches."); 149276479Sdim continue; 150276479Sdim } 151276479Sdim } 152259701Sdim Found = &Matchers[i]; 153276479Sdim FoundIsExact = IsExactMatch; 154276479Sdim ++NumFound; 155259701Sdim } 156259701Sdim } 157276479Sdim // We only succeed if we found exactly one, or if we found an exact match. 158276479Sdim if (Found && (FoundIsExact || NumFound == 1)) 159280031Sdim return *Found; 160280031Sdim return llvm::None; 161259701Sdim } 162259701Sdim 163280031Sdim bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 164280031Sdim unsigned *Specificity) const override { 165280031Sdim unsigned MaxSpecificity = 0; 166280031Sdim for (const DynTypedMatcher &Matcher : Matchers) { 167280031Sdim unsigned ThisSpecificity; 168280031Sdim if (ArgKind(Matcher.getSupportedKind()) 169280031Sdim .isConvertibleTo(Kind, &ThisSpecificity)) { 170280031Sdim MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); 171280031Sdim } 172280031Sdim } 173280031Sdim if (Specificity) 174280031Sdim *Specificity = MaxSpecificity; 175280031Sdim return MaxSpecificity > 0; 176280031Sdim } 177280031Sdim 178259701Sdim const std::vector<DynTypedMatcher> Matchers; 179259701Sdim}; 180259701Sdim 181259701Sdimclass VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { 182259701Sdimpublic: 183280031Sdim VariadicOpPayload(DynTypedMatcher::VariadicOperator Op, 184276479Sdim std::vector<VariantMatcher> Args) 185280031Sdim : Op(Op), Args(std::move(Args)) {} 186259701Sdim 187280031Sdim llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 188259701Sdim return llvm::Optional<DynTypedMatcher>(); 189259701Sdim } 190259701Sdim 191280031Sdim std::string getTypeAsString() const override { 192259701Sdim std::string Inner; 193259701Sdim for (size_t i = 0, e = Args.size(); i != e; ++i) { 194259701Sdim if (i != 0) 195259701Sdim Inner += "&"; 196259701Sdim Inner += Args[i].getTypeAsString(); 197259701Sdim } 198259701Sdim return Inner; 199259701Sdim } 200259701Sdim 201280031Sdim llvm::Optional<DynTypedMatcher> 202280031Sdim getTypedMatcher(const MatcherOps &Ops) const override { 203280031Sdim return Ops.constructVariadicOperator(Op, Args); 204259701Sdim } 205259701Sdim 206280031Sdim bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 207280031Sdim unsigned *Specificity) const override { 208280031Sdim for (const VariantMatcher &Matcher : Args) { 209280031Sdim if (!Matcher.isConvertibleTo(Kind, Specificity)) 210280031Sdim return false; 211280031Sdim } 212280031Sdim return true; 213280031Sdim } 214280031Sdim 215259701Sdimprivate: 216280031Sdim const DynTypedMatcher::VariadicOperator Op; 217259701Sdim const std::vector<VariantMatcher> Args; 218259701Sdim}; 219259701Sdim 220259701SdimVariantMatcher::VariantMatcher() {} 221259701Sdim 222259701SdimVariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { 223314564Sdim return VariantMatcher(std::make_shared<SinglePayload>(Matcher)); 224259701Sdim} 225259701Sdim 226259701SdimVariantMatcher 227276479SdimVariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { 228314564Sdim return VariantMatcher( 229314564Sdim std::make_shared<PolymorphicPayload>(std::move(Matchers))); 230259701Sdim} 231259701Sdim 232259701SdimVariantMatcher VariantMatcher::VariadicOperatorMatcher( 233280031Sdim DynTypedMatcher::VariadicOperator Op, 234276479Sdim std::vector<VariantMatcher> Args) { 235314564Sdim return VariantMatcher( 236314564Sdim std::make_shared<VariadicOpPayload>(Op, std::move(Args))); 237259701Sdim} 238259701Sdim 239259701Sdimllvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { 240259701Sdim return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>(); 241259701Sdim} 242259701Sdim 243259701Sdimvoid VariantMatcher::reset() { Value.reset(); } 244259701Sdim 245259701Sdimstd::string VariantMatcher::getTypeAsString() const { 246259701Sdim if (Value) return Value->getTypeAsString(); 247259701Sdim return "<Nothing>"; 248259701Sdim} 249259701Sdim 250259701SdimVariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { 251259701Sdim *this = Other; 252259701Sdim} 253259701Sdim 254321369SdimVariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) { 255321369Sdim setBoolean(Boolean); 256321369Sdim} 257321369Sdim 258321369SdimVariantValue::VariantValue(double Double) : Type(VT_Nothing) { 259321369Sdim setDouble(Double); 260321369Sdim} 261321369Sdim 262259701SdimVariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { 263259701Sdim setUnsigned(Unsigned); 264259701Sdim} 265259701Sdim 266288943SdimVariantValue::VariantValue(StringRef String) : Type(VT_Nothing) { 267259701Sdim setString(String); 268259701Sdim} 269259701Sdim 270259701SdimVariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) { 271259701Sdim setMatcher(Matcher); 272259701Sdim} 273259701Sdim 274259701SdimVariantValue::~VariantValue() { reset(); } 275259701Sdim 276259701SdimVariantValue &VariantValue::operator=(const VariantValue &Other) { 277259701Sdim if (this == &Other) return *this; 278259701Sdim reset(); 279259701Sdim switch (Other.Type) { 280321369Sdim case VT_Boolean: 281321369Sdim setBoolean(Other.getBoolean()); 282321369Sdim break; 283321369Sdim case VT_Double: 284321369Sdim setDouble(Other.getDouble()); 285321369Sdim break; 286259701Sdim case VT_Unsigned: 287259701Sdim setUnsigned(Other.getUnsigned()); 288259701Sdim break; 289259701Sdim case VT_String: 290259701Sdim setString(Other.getString()); 291259701Sdim break; 292259701Sdim case VT_Matcher: 293259701Sdim setMatcher(Other.getMatcher()); 294259701Sdim break; 295259701Sdim case VT_Nothing: 296259701Sdim Type = VT_Nothing; 297259701Sdim break; 298259701Sdim } 299259701Sdim return *this; 300259701Sdim} 301259701Sdim 302259701Sdimvoid VariantValue::reset() { 303259701Sdim switch (Type) { 304259701Sdim case VT_String: 305259701Sdim delete Value.String; 306259701Sdim break; 307259701Sdim case VT_Matcher: 308259701Sdim delete Value.Matcher; 309259701Sdim break; 310259701Sdim // Cases that do nothing. 311321369Sdim case VT_Boolean: 312321369Sdim case VT_Double: 313259701Sdim case VT_Unsigned: 314259701Sdim case VT_Nothing: 315259701Sdim break; 316259701Sdim } 317259701Sdim Type = VT_Nothing; 318259701Sdim} 319259701Sdim 320321369Sdimbool VariantValue::isBoolean() const { 321321369Sdim return Type == VT_Boolean; 322321369Sdim} 323321369Sdim 324321369Sdimbool VariantValue::getBoolean() const { 325321369Sdim assert(isBoolean()); 326321369Sdim return Value.Boolean; 327321369Sdim} 328321369Sdim 329321369Sdimvoid VariantValue::setBoolean(bool NewValue) { 330321369Sdim reset(); 331321369Sdim Type = VT_Boolean; 332321369Sdim Value.Boolean = NewValue; 333321369Sdim} 334321369Sdim 335321369Sdimbool VariantValue::isDouble() const { 336321369Sdim return Type == VT_Double; 337321369Sdim} 338321369Sdim 339321369Sdimdouble VariantValue::getDouble() const { 340321369Sdim assert(isDouble()); 341321369Sdim return Value.Double; 342321369Sdim} 343321369Sdim 344321369Sdimvoid VariantValue::setDouble(double NewValue) { 345321369Sdim reset(); 346321369Sdim Type = VT_Double; 347321369Sdim Value.Double = NewValue; 348321369Sdim} 349321369Sdim 350259701Sdimbool VariantValue::isUnsigned() const { 351259701Sdim return Type == VT_Unsigned; 352259701Sdim} 353259701Sdim 354259701Sdimunsigned VariantValue::getUnsigned() const { 355259701Sdim assert(isUnsigned()); 356259701Sdim return Value.Unsigned; 357259701Sdim} 358259701Sdim 359259701Sdimvoid VariantValue::setUnsigned(unsigned NewValue) { 360259701Sdim reset(); 361259701Sdim Type = VT_Unsigned; 362259701Sdim Value.Unsigned = NewValue; 363259701Sdim} 364259701Sdim 365259701Sdimbool VariantValue::isString() const { 366259701Sdim return Type == VT_String; 367259701Sdim} 368259701Sdim 369259701Sdimconst std::string &VariantValue::getString() const { 370259701Sdim assert(isString()); 371259701Sdim return *Value.String; 372259701Sdim} 373259701Sdim 374288943Sdimvoid VariantValue::setString(StringRef NewValue) { 375259701Sdim reset(); 376259701Sdim Type = VT_String; 377259701Sdim Value.String = new std::string(NewValue); 378259701Sdim} 379259701Sdim 380259701Sdimbool VariantValue::isMatcher() const { 381259701Sdim return Type == VT_Matcher; 382259701Sdim} 383259701Sdim 384259701Sdimconst VariantMatcher &VariantValue::getMatcher() const { 385259701Sdim assert(isMatcher()); 386259701Sdim return *Value.Matcher; 387259701Sdim} 388259701Sdim 389259701Sdimvoid VariantValue::setMatcher(const VariantMatcher &NewValue) { 390259701Sdim reset(); 391259701Sdim Type = VT_Matcher; 392259701Sdim Value.Matcher = new VariantMatcher(NewValue); 393259701Sdim} 394259701Sdim 395280031Sdimbool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const { 396280031Sdim switch (Kind.getArgKind()) { 397321369Sdim case ArgKind::AK_Boolean: 398321369Sdim if (!isBoolean()) 399321369Sdim return false; 400321369Sdim *Specificity = 1; 401321369Sdim return true; 402321369Sdim 403321369Sdim case ArgKind::AK_Double: 404321369Sdim if (!isDouble()) 405321369Sdim return false; 406321369Sdim *Specificity = 1; 407321369Sdim return true; 408321369Sdim 409280031Sdim case ArgKind::AK_Unsigned: 410280031Sdim if (!isUnsigned()) 411280031Sdim return false; 412280031Sdim *Specificity = 1; 413280031Sdim return true; 414280031Sdim 415280031Sdim case ArgKind::AK_String: 416280031Sdim if (!isString()) 417280031Sdim return false; 418280031Sdim *Specificity = 1; 419280031Sdim return true; 420280031Sdim 421280031Sdim case ArgKind::AK_Matcher: 422280031Sdim if (!isMatcher()) 423280031Sdim return false; 424280031Sdim return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity); 425280031Sdim } 426280031Sdim llvm_unreachable("Invalid Type"); 427280031Sdim} 428280031Sdim 429280031Sdimbool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds, 430280031Sdim unsigned *Specificity) const { 431280031Sdim unsigned MaxSpecificity = 0; 432280031Sdim for (const ArgKind& Kind : Kinds) { 433280031Sdim unsigned ThisSpecificity; 434280031Sdim if (!isConvertibleTo(Kind, &ThisSpecificity)) 435280031Sdim continue; 436280031Sdim MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); 437280031Sdim } 438280031Sdim if (Specificity && MaxSpecificity > 0) { 439280031Sdim *Specificity = MaxSpecificity; 440280031Sdim } 441280031Sdim return MaxSpecificity > 0; 442280031Sdim} 443280031Sdim 444259701Sdimstd::string VariantValue::getTypeAsString() const { 445259701Sdim switch (Type) { 446259701Sdim case VT_String: return "String"; 447259701Sdim case VT_Matcher: return getMatcher().getTypeAsString(); 448321369Sdim case VT_Boolean: return "Boolean"; 449321369Sdim case VT_Double: return "Double"; 450259701Sdim case VT_Unsigned: return "Unsigned"; 451259701Sdim case VT_Nothing: return "Nothing"; 452259701Sdim } 453259701Sdim llvm_unreachable("Invalid Type"); 454259701Sdim} 455259701Sdim 456259701Sdim} // end namespace dynamic 457259701Sdim} // end namespace ast_matchers 458259701Sdim} // end namespace clang 459