1//===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Polymorphic value type.
12///
13//===----------------------------------------------------------------------===//
14
15#include "clang/ASTMatchers/Dynamic/VariantValue.h"
16#include "clang/Basic/LLVM.h"
17#include "llvm/ADT/STLExtras.h"
18
19namespace clang {
20namespace ast_matchers {
21namespace dynamic {
22
23std::string ArgKind::asString() const {
24  switch (getArgKind()) {
25  case AK_Matcher:
26    return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
27  case AK_Unsigned:
28    return "unsigned";
29  case AK_String:
30    return "string";
31  }
32  llvm_unreachable("unhandled ArgKind");
33}
34
35bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
36  if (K != To.K)
37    return false;
38  if (K != AK_Matcher) {
39    if (Specificity)
40      *Specificity = 1;
41    return true;
42  }
43  unsigned Distance;
44  if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
45    return false;
46
47  if (Specificity)
48    *Specificity = 100 - Distance;
49  return true;
50}
51
52bool
53VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
54                                             bool &IsExactMatch) const {
55  IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
56  return Matcher.canConvertTo(NodeKind);
57}
58
59llvm::Optional<DynTypedMatcher>
60VariantMatcher::MatcherOps::constructVariadicOperator(
61    DynTypedMatcher::VariadicOperator Op,
62    ArrayRef<VariantMatcher> InnerMatchers) const {
63  std::vector<DynTypedMatcher> DynMatchers;
64  for (const auto &InnerMatcher : InnerMatchers) {
65    // Abort if any of the inner matchers can't be converted to
66    // Matcher<T>.
67    if (!InnerMatcher.Value)
68      return llvm::None;
69    llvm::Optional<DynTypedMatcher> Inner =
70        InnerMatcher.Value->getTypedMatcher(*this);
71    if (!Inner)
72      return llvm::None;
73    DynMatchers.push_back(*Inner);
74  }
75  return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
76}
77
78VariantMatcher::Payload::~Payload() {}
79
80class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
81public:
82  SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
83
84  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
85    return Matcher;
86  }
87
88  std::string getTypeAsString() const override {
89    return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
90        .str();
91  }
92
93  llvm::Optional<DynTypedMatcher>
94  getTypedMatcher(const MatcherOps &Ops) const override {
95    bool Ignore;
96    if (Ops.canConstructFrom(Matcher, Ignore))
97      return Matcher;
98    return llvm::None;
99  }
100
101  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
102                       unsigned *Specificity) const override {
103    return ArgKind(Matcher.getSupportedKind())
104        .isConvertibleTo(Kind, Specificity);
105  }
106
107private:
108  const DynTypedMatcher Matcher;
109};
110
111class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
112public:
113  PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
114      : Matchers(std::move(MatchersIn)) {}
115
116  ~PolymorphicPayload() override {}
117
118  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
119    if (Matchers.size() != 1)
120      return llvm::Optional<DynTypedMatcher>();
121    return Matchers[0];
122  }
123
124  std::string getTypeAsString() const override {
125    std::string Inner;
126    for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
127      if (i != 0)
128        Inner += "|";
129      Inner += Matchers[i].getSupportedKind().asStringRef();
130    }
131    return (Twine("Matcher<") + Inner + ">").str();
132  }
133
134  llvm::Optional<DynTypedMatcher>
135  getTypedMatcher(const MatcherOps &Ops) const override {
136    bool FoundIsExact = false;
137    const DynTypedMatcher *Found = nullptr;
138    int NumFound = 0;
139    for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
140      bool IsExactMatch;
141      if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
142        if (Found) {
143          if (FoundIsExact) {
144            assert(!IsExactMatch && "We should not have two exact matches.");
145            continue;
146          }
147        }
148        Found = &Matchers[i];
149        FoundIsExact = IsExactMatch;
150        ++NumFound;
151      }
152    }
153    // We only succeed if we found exactly one, or if we found an exact match.
154    if (Found && (FoundIsExact || NumFound == 1))
155      return *Found;
156    return llvm::None;
157  }
158
159  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
160                       unsigned *Specificity) const override {
161    unsigned MaxSpecificity = 0;
162    for (const DynTypedMatcher &Matcher : Matchers) {
163      unsigned ThisSpecificity;
164      if (ArgKind(Matcher.getSupportedKind())
165              .isConvertibleTo(Kind, &ThisSpecificity)) {
166        MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
167      }
168    }
169    if (Specificity)
170      *Specificity = MaxSpecificity;
171    return MaxSpecificity > 0;
172  }
173
174  const std::vector<DynTypedMatcher> Matchers;
175};
176
177class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
178public:
179  VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
180                    std::vector<VariantMatcher> Args)
181      : Op(Op), Args(std::move(Args)) {}
182
183  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
184    return llvm::Optional<DynTypedMatcher>();
185  }
186
187  std::string getTypeAsString() const override {
188    std::string Inner;
189    for (size_t i = 0, e = Args.size(); i != e; ++i) {
190      if (i != 0)
191        Inner += "&";
192      Inner += Args[i].getTypeAsString();
193    }
194    return Inner;
195  }
196
197  llvm::Optional<DynTypedMatcher>
198  getTypedMatcher(const MatcherOps &Ops) const override {
199    return Ops.constructVariadicOperator(Op, Args);
200  }
201
202  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
203                       unsigned *Specificity) const override {
204    for (const VariantMatcher &Matcher : Args) {
205      if (!Matcher.isConvertibleTo(Kind, Specificity))
206        return false;
207    }
208    return true;
209  }
210
211private:
212  const DynTypedMatcher::VariadicOperator Op;
213  const std::vector<VariantMatcher> Args;
214};
215
216VariantMatcher::VariantMatcher() {}
217
218VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
219  return VariantMatcher(new SinglePayload(Matcher));
220}
221
222VariantMatcher
223VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
224  return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
225}
226
227VariantMatcher VariantMatcher::VariadicOperatorMatcher(
228    DynTypedMatcher::VariadicOperator Op,
229    std::vector<VariantMatcher> Args) {
230  return VariantMatcher(new VariadicOpPayload(Op, std::move(Args)));
231}
232
233llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
234  return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
235}
236
237void VariantMatcher::reset() { Value.reset(); }
238
239std::string VariantMatcher::getTypeAsString() const {
240  if (Value) return Value->getTypeAsString();
241  return "<Nothing>";
242}
243
244VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
245  *this = Other;
246}
247
248VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
249  setUnsigned(Unsigned);
250}
251
252VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
253  setString(String);
254}
255
256VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
257  setMatcher(Matcher);
258}
259
260VariantValue::~VariantValue() { reset(); }
261
262VariantValue &VariantValue::operator=(const VariantValue &Other) {
263  if (this == &Other) return *this;
264  reset();
265  switch (Other.Type) {
266  case VT_Unsigned:
267    setUnsigned(Other.getUnsigned());
268    break;
269  case VT_String:
270    setString(Other.getString());
271    break;
272  case VT_Matcher:
273    setMatcher(Other.getMatcher());
274    break;
275  case VT_Nothing:
276    Type = VT_Nothing;
277    break;
278  }
279  return *this;
280}
281
282void VariantValue::reset() {
283  switch (Type) {
284  case VT_String:
285    delete Value.String;
286    break;
287  case VT_Matcher:
288    delete Value.Matcher;
289    break;
290  // Cases that do nothing.
291  case VT_Unsigned:
292  case VT_Nothing:
293    break;
294  }
295  Type = VT_Nothing;
296}
297
298bool VariantValue::isUnsigned() const {
299  return Type == VT_Unsigned;
300}
301
302unsigned VariantValue::getUnsigned() const {
303  assert(isUnsigned());
304  return Value.Unsigned;
305}
306
307void VariantValue::setUnsigned(unsigned NewValue) {
308  reset();
309  Type = VT_Unsigned;
310  Value.Unsigned = NewValue;
311}
312
313bool VariantValue::isString() const {
314  return Type == VT_String;
315}
316
317const std::string &VariantValue::getString() const {
318  assert(isString());
319  return *Value.String;
320}
321
322void VariantValue::setString(StringRef NewValue) {
323  reset();
324  Type = VT_String;
325  Value.String = new std::string(NewValue);
326}
327
328bool VariantValue::isMatcher() const {
329  return Type == VT_Matcher;
330}
331
332const VariantMatcher &VariantValue::getMatcher() const {
333  assert(isMatcher());
334  return *Value.Matcher;
335}
336
337void VariantValue::setMatcher(const VariantMatcher &NewValue) {
338  reset();
339  Type = VT_Matcher;
340  Value.Matcher = new VariantMatcher(NewValue);
341}
342
343bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
344  switch (Kind.getArgKind()) {
345  case ArgKind::AK_Unsigned:
346    if (!isUnsigned())
347      return false;
348    *Specificity = 1;
349    return true;
350
351  case ArgKind::AK_String:
352    if (!isString())
353      return false;
354    *Specificity = 1;
355    return true;
356
357  case ArgKind::AK_Matcher:
358    if (!isMatcher())
359      return false;
360    return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
361  }
362  llvm_unreachable("Invalid Type");
363}
364
365bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
366                                   unsigned *Specificity) const {
367  unsigned MaxSpecificity = 0;
368  for (const ArgKind& Kind : Kinds) {
369    unsigned ThisSpecificity;
370    if (!isConvertibleTo(Kind, &ThisSpecificity))
371      continue;
372    MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
373  }
374  if (Specificity && MaxSpecificity > 0) {
375    *Specificity = MaxSpecificity;
376  }
377  return MaxSpecificity > 0;
378}
379
380std::string VariantValue::getTypeAsString() const {
381  switch (Type) {
382  case VT_String: return "String";
383  case VT_Matcher: return getMatcher().getTypeAsString();
384  case VT_Unsigned: return "Unsigned";
385  case VT_Nothing: return "Nothing";
386  }
387  llvm_unreachable("Invalid Type");
388}
389
390} // end namespace dynamic
391} // end namespace ast_matchers
392} // end namespace clang
393