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 
17 #include "clang/Basic/LLVM.h"
18 #include "llvm/ADT/STLExtras.h"
19 
20 namespace clang {
21 namespace ast_matchers {
22 namespace dynamic {
23 
24 VariantMatcher::MatcherOps::~MatcherOps() {}
25 VariantMatcher::Payload::~Payload() {}
26 
27 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
28 public:
29   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher.clone()) {}
30 
31   virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
32     Out = Matcher.get();
33     return true;
34   }
35 
36   virtual std::string getTypeAsString() const {
37     return (Twine("Matcher<") + Matcher->getSupportedKind().asStringRef() + ">")
38         .str();
39   }
40 
41   virtual void makeTypedMatcher(MatcherOps &Ops) const {
42     if (Ops.canConstructFrom(*Matcher))
43       Ops.constructFrom(*Matcher);
44   }
45 
46 private:
47   OwningPtr<const DynTypedMatcher> Matcher;
48 };
49 
50 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
51 public:
52   PolymorphicPayload(ArrayRef<const DynTypedMatcher *> MatchersIn) {
53     for (size_t i = 0, e = MatchersIn.size(); i != e; ++i) {
54       Matchers.push_back(MatchersIn[i]->clone());
55     }
56   }
57 
58   virtual ~PolymorphicPayload() {
59     llvm::DeleteContainerPointers(Matchers);
60   }
61 
62   virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
63     if (Matchers.size() != 1)
64       return false;
65     Out = Matchers[0];
66     return true;
67   }
68 
69   virtual std::string getTypeAsString() const {
70     std::string Inner;
71     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
72       if (i != 0)
73         Inner += "|";
74       Inner += Matchers[i]->getSupportedKind().asStringRef();
75     }
76     return (Twine("Matcher<") + Inner + ">").str();
77   }
78 
79   virtual void makeTypedMatcher(MatcherOps &Ops) const {
80     const DynTypedMatcher *Found = NULL;
81     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
82       if (Ops.canConstructFrom(*Matchers[i])) {
83         if (Found)
84           return;
85         Found = Matchers[i];
86       }
87     }
88     if (Found)
89       Ops.constructFrom(*Found);
90   }
91 
92   std::vector<const DynTypedMatcher *> Matchers;
93 };
94 
95 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
96 public:
97   VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
98                     ArrayRef<VariantMatcher> Args)
99       : Func(Func), Args(Args) {}
100 
101   virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
102     return false;
103   }
104 
105   virtual std::string getTypeAsString() const {
106     std::string Inner;
107     for (size_t i = 0, e = Args.size(); i != e; ++i) {
108       if (i != 0)
109         Inner += "&";
110       Inner += Args[i].getTypeAsString();
111     }
112     return Inner;
113   }
114 
115   virtual void makeTypedMatcher(MatcherOps &Ops) const {
116     Ops.constructVariadicOperator(Func, Args);
117   }
118 
119 private:
120   const ast_matchers::internal::VariadicOperatorFunction Func;
121   const std::vector<VariantMatcher> Args;
122 };
123 
124 VariantMatcher::VariantMatcher() {}
125 
126 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
127   return VariantMatcher(new SinglePayload(Matcher));
128 }
129 
130 VariantMatcher
131 VariantMatcher::PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers) {
132   return VariantMatcher(new PolymorphicPayload(Matchers));
133 }
134 
135 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
136     ast_matchers::internal::VariadicOperatorFunction Func,
137     ArrayRef<VariantMatcher> Args) {
138   return VariantMatcher(new VariadicOpPayload(Func, Args));
139 }
140 
141 bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const {
142   if (Value) return Value->getSingleMatcher(Out);
143   return false;
144 }
145 
146 void VariantMatcher::reset() { Value.reset(); }
147 
148 std::string VariantMatcher::getTypeAsString() const {
149   if (Value) return Value->getTypeAsString();
150   return "<Nothing>";
151 }
152 
153 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
154   *this = Other;
155 }
156 
157 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
158   setUnsigned(Unsigned);
159 }
160 
161 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
162   setString(String);
163 }
164 
165 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
166   setMatcher(Matcher);
167 }
168 
169 VariantValue::~VariantValue() { reset(); }
170 
171 VariantValue &VariantValue::operator=(const VariantValue &Other) {
172   if (this == &Other) return *this;
173   reset();
174   switch (Other.Type) {
175   case VT_Unsigned:
176     setUnsigned(Other.getUnsigned());
177     break;
178   case VT_String:
179     setString(Other.getString());
180     break;
181   case VT_Matcher:
182     setMatcher(Other.getMatcher());
183     break;
184   case VT_Nothing:
185     Type = VT_Nothing;
186     break;
187   }
188   return *this;
189 }
190 
191 void VariantValue::reset() {
192   switch (Type) {
193   case VT_String:
194     delete Value.String;
195     break;
196   case VT_Matcher:
197     delete Value.Matcher;
198     break;
199   // Cases that do nothing.
200   case VT_Unsigned:
201   case VT_Nothing:
202     break;
203   }
204   Type = VT_Nothing;
205 }
206 
207 bool VariantValue::isUnsigned() const {
208   return Type == VT_Unsigned;
209 }
210 
211 unsigned VariantValue::getUnsigned() const {
212   assert(isUnsigned());
213   return Value.Unsigned;
214 }
215 
216 void VariantValue::setUnsigned(unsigned NewValue) {
217   reset();
218   Type = VT_Unsigned;
219   Value.Unsigned = NewValue;
220 }
221 
222 bool VariantValue::isString() const {
223   return Type == VT_String;
224 }
225 
226 const std::string &VariantValue::getString() const {
227   assert(isString());
228   return *Value.String;
229 }
230 
231 void VariantValue::setString(const std::string &NewValue) {
232   reset();
233   Type = VT_String;
234   Value.String = new std::string(NewValue);
235 }
236 
237 bool VariantValue::isMatcher() const {
238   return Type == VT_Matcher;
239 }
240 
241 const VariantMatcher &VariantValue::getMatcher() const {
242   assert(isMatcher());
243   return *Value.Matcher;
244 }
245 
246 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
247   reset();
248   Type = VT_Matcher;
249   Value.Matcher = new VariantMatcher(NewValue);
250 }
251 
252 std::string VariantValue::getTypeAsString() const {
253   switch (Type) {
254   case VT_String: return "String";
255   case VT_Matcher: return getMatcher().getTypeAsString();
256   case VT_Unsigned: return "Unsigned";
257   case VT_Nothing: return "Nothing";
258   }
259   llvm_unreachable("Invalid Type");
260 }
261 
262 } // end namespace dynamic
263 } // end namespace ast_matchers
264 } // end namespace clang
265