brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.5 KiB · 2309c8a Raw
493 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// Polymorphic value type.11///12//===----------------------------------------------------------------------===//13 14#include "clang/ASTMatchers/Dynamic/VariantValue.h"15#include "clang/Basic/LLVM.h"16#include <optional>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 57bool58VariantMatcher::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 69std::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 to76    // Matcher<T>.77    if (!InnerMatcher.Value)78      return std::nullopt;79    std::optional<DynTypedMatcher> Inner =80        InnerMatcher.Value->getTypedMatcher(*this);81    if (!Inner)82      return std::nullopt;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  std::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  std::optional<DynTypedMatcher>104  getTypedMatcher(const MatcherOps &Ops) const override {105    bool Ignore;106    if (Ops.canConstructFrom(Matcher, Ignore))107      return Matcher;108    return std::nullopt;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  std::optional<DynTypedMatcher> getSingleMatcher() const override {128    if (Matchers.size() != 1)129      return std::nullopt;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  std::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 std::nullopt;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  std::optional<DynTypedMatcher> getSingleMatcher() const override {193    return std::nullopt;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  std::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 230VariantMatcher231VariantMatcher::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 243std::optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {244  return Value ? Value->getSingleMatcher() : std::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 dynamic491} // end namespace ast_matchers492} // end namespace clang493