blob: c350d78aa14bf5aab1d6e6fd6536969647192ade [file] [log] [blame]
Manuel Klimekf7f295f2013-05-14 09:13:00 +00001//===--- 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
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000017#include "clang/Basic/LLVM.h"
Samuel Benzaquen9d028072013-08-13 14:54:51 +000018#include "llvm/ADT/STLExtras.h"
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000019
Manuel Klimekf7f295f2013-05-14 09:13:00 +000020namespace clang {
21namespace ast_matchers {
22namespace dynamic {
23
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000024VariantMatcher::MatcherOps::~MatcherOps() {}
25VariantMatcher::Payload::~Payload() {}
Samuel Benzaquenef7eb022013-06-21 15:51:31 +000026
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000027class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
28public:
Reid Klecknerc30bf452013-10-21 22:26:36 +000029 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher.clone()) {}
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000030
Reid Klecknerc30bf452013-10-21 22:26:36 +000031 virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
32 Out = Matcher.get();
33 return true;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000034 }
35
36 virtual std::string getTypeAsString() const {
Reid Klecknerc30bf452013-10-21 22:26:36 +000037 return (Twine("Matcher<") + Matcher->getSupportedKind().asStringRef() + ">")
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000038 .str();
39 }
40
Samuel Benzaquena7350902013-08-28 18:42:04 +000041 virtual void makeTypedMatcher(MatcherOps &Ops) const {
Reid Klecknerc30bf452013-10-21 22:26:36 +000042 if (Ops.canConstructFrom(*Matcher))
43 Ops.constructFrom(*Matcher);
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000044 }
45
46private:
Reid Klecknerc30bf452013-10-21 22:26:36 +000047 OwningPtr<const DynTypedMatcher> Matcher;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000048};
49
50class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
51public:
Reid Klecknerc30bf452013-10-21 22:26:36 +000052 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 }
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000057
Reid Klecknerc30bf452013-10-21 22:26:36 +000058 virtual ~PolymorphicPayload() {
59 llvm::DeleteContainerPointers(Matchers);
60 }
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000061
Reid Klecknerc30bf452013-10-21 22:26:36 +000062 virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000063 if (Matchers.size() != 1)
Reid Klecknerc30bf452013-10-21 22:26:36 +000064 return false;
65 Out = Matchers[0];
66 return true;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000067 }
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 += "|";
Reid Klecknerc30bf452013-10-21 22:26:36 +000074 Inner += Matchers[i]->getSupportedKind().asStringRef();
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000075 }
76 return (Twine("Matcher<") + Inner + ">").str();
77 }
78
Samuel Benzaquena7350902013-08-28 18:42:04 +000079 virtual void makeTypedMatcher(MatcherOps &Ops) const {
80 const DynTypedMatcher *Found = NULL;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000081 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
Reid Klecknerc30bf452013-10-21 22:26:36 +000082 if (Ops.canConstructFrom(*Matchers[i])) {
Samuel Benzaquena7350902013-08-28 18:42:04 +000083 if (Found)
84 return;
Reid Klecknerc30bf452013-10-21 22:26:36 +000085 Found = Matchers[i];
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000086 }
87 }
Samuel Benzaquena7350902013-08-28 18:42:04 +000088 if (Found)
89 Ops.constructFrom(*Found);
90 }
91
Reid Klecknerc30bf452013-10-21 22:26:36 +000092 std::vector<const DynTypedMatcher *> Matchers;
Samuel Benzaquena7350902013-08-28 18:42:04 +000093};
94
95class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
96public:
97 VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
98 ArrayRef<VariantMatcher> Args)
99 : Func(Func), Args(Args) {}
100
Reid Klecknerc30bf452013-10-21 22:26:36 +0000101 virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
102 return false;
Samuel Benzaquena7350902013-08-28 18:42:04 +0000103 }
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);
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000117 }
118
119private:
Samuel Benzaquena7350902013-08-28 18:42:04 +0000120 const ast_matchers::internal::VariadicOperatorFunction Func;
121 const std::vector<VariantMatcher> Args;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000122};
123
124VariantMatcher::VariantMatcher() {}
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000125
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000126VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000127 return VariantMatcher(new SinglePayload(Matcher));
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000128}
129
130VariantMatcher
Reid Klecknerc30bf452013-10-21 22:26:36 +0000131VariantMatcher::PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers) {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000132 return VariantMatcher(new PolymorphicPayload(Matchers));
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000133}
134
Samuel Benzaquena7350902013-08-28 18:42:04 +0000135VariantMatcher VariantMatcher::VariadicOperatorMatcher(
136 ast_matchers::internal::VariadicOperatorFunction Func,
137 ArrayRef<VariantMatcher> Args) {
138 return VariantMatcher(new VariadicOpPayload(Func, Args));
139}
140
Reid Klecknerc30bf452013-10-21 22:26:36 +0000141bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const {
142 if (Value) return Value->getSingleMatcher(Out);
143 return false;
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000144}
145
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000146void VariantMatcher::reset() { Value.reset(); }
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000147
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000148std::string VariantMatcher::getTypeAsString() const {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000149 if (Value) return Value->getTypeAsString();
150 return "<Nothing>";
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000151}
152
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000153VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
154 *this = Other;
155}
156
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000157VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
158 setUnsigned(Unsigned);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000159}
160
161VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
162 setString(String);
163}
164
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000165VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
166 setMatcher(Matcher);
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000167}
168
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000169VariantValue::~VariantValue() { reset(); }
170
171VariantValue &VariantValue::operator=(const VariantValue &Other) {
172 if (this == &Other) return *this;
173 reset();
174 switch (Other.Type) {
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000175 case VT_Unsigned:
176 setUnsigned(Other.getUnsigned());
177 break;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000178 case VT_String:
179 setString(Other.getString());
180 break;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000181 case VT_Matcher:
182 setMatcher(Other.getMatcher());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000183 break;
184 case VT_Nothing:
185 Type = VT_Nothing;
186 break;
187 }
188 return *this;
189}
190
191void VariantValue::reset() {
192 switch (Type) {
193 case VT_String:
194 delete Value.String;
195 break;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000196 case VT_Matcher:
197 delete Value.Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000198 break;
199 // Cases that do nothing.
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000200 case VT_Unsigned:
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000201 case VT_Nothing:
202 break;
203 }
204 Type = VT_Nothing;
205}
206
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000207bool VariantValue::isUnsigned() const {
208 return Type == VT_Unsigned;
209}
210
211unsigned VariantValue::getUnsigned() const {
212 assert(isUnsigned());
213 return Value.Unsigned;
214}
215
216void VariantValue::setUnsigned(unsigned NewValue) {
217 reset();
218 Type = VT_Unsigned;
219 Value.Unsigned = NewValue;
220}
221
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000222bool VariantValue::isString() const {
223 return Type == VT_String;
224}
225
226const std::string &VariantValue::getString() const {
227 assert(isString());
228 return *Value.String;
229}
230
231void VariantValue::setString(const std::string &NewValue) {
232 reset();
233 Type = VT_String;
234 Value.String = new std::string(NewValue);
235}
236
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000237bool VariantValue::isMatcher() const {
238 return Type == VT_Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000239}
240
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000241const VariantMatcher &VariantValue::getMatcher() const {
242 assert(isMatcher());
243 return *Value.Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000244}
245
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000246void VariantValue::setMatcher(const VariantMatcher &NewValue) {
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000247 reset();
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000248 Type = VT_Matcher;
249 Value.Matcher = new VariantMatcher(NewValue);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000250}
251
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000252std::string VariantValue::getTypeAsString() const {
253 switch (Type) {
254 case VT_String: return "String";
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000255 case VT_Matcher: return getMatcher().getTypeAsString();
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000256 case VT_Unsigned: return "Unsigned";
257 case VT_Nothing: return "Nothing";
258 }
259 llvm_unreachable("Invalid Type");
260}
261
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000262} // end namespace dynamic
263} // end namespace ast_matchers
264} // end namespace clang