1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
#include "CommonTools/Utils/interface/parser/MethodSetter.h"
#include "CommonTools/Utils/interface/parser/Exception.h"
#include "CommonTools/Utils/src/ErrorCodes.h"
#include "CommonTools/Utils/interface/parser/MethodInvoker.h"
#include "CommonTools/Utils/src/findDataMember.h"
#include "CommonTools/Utils/src/findMethod.h"
#include "CommonTools/Utils/interface/returnType.h"
#include <string>
using namespace reco::parser;
using namespace std;
void MethodSetter::operator()(const char* begin, const char* end) const {
string name(begin, end);
string::size_type parenthesis = name.find_first_of('(');
if ((*begin == '[') || (*begin == '(')) {
name.insert(0, "operator.."); // operator..[arg];
parenthesis = 10; // ^--- idx = 10
name[8] = *begin; // operator[.[arg];
name[9] = name[name.size() - 1]; // operator[][arg];
name[10] = '('; // operator[](arg];
name[name.size() - 1] = ')'; // operator[](arg);
// we don't actually need the last two, but just for extra care
//std::cout << "Transformed {" << string(begin,end) << "} into
// {"<< name <<"}" << std::endl;
}
std::vector<AnyMethodArgument> args;
if (parenthesis != string::npos) {
name.erase(parenthesis, name.size());
if (intStack_.empty()) {
throw Exception(begin) << "expected method argument, but non given.";
}
for (vector<AnyMethodArgument>::const_iterator i = intStack_.begin(); i != intStack_.end(); ++i) {
args.push_back(*i);
}
intStack_.clear();
}
string::size_type endOfExpr = name.find_last_of(' ');
if (endOfExpr != string::npos) {
name.erase(endOfExpr, name.size());
}
//std::cerr << "Pushing [" << name << "] with " << args.size()
// << " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl;
if (lazy_) {
// for lazy parsing we just push method name and arguments
lazyMethStack_.push_back(LazyInvoker(name, args));
} else {
// otherwise we really have to resolve the method
push(name, args, begin);
}
//std::cerr << "Pushed [" << name << "] with " << args.size() <<
// " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl;
}
bool MethodSetter::push(const string& name, const vector<AnyMethodArgument>& args, const char* begin, bool deep) const {
edm::TypeWithDict type = typeStack_.back();
vector<AnyMethodArgument> fixups;
int error = 0;
pair<edm::FunctionWithDict, bool> mem = reco::findMethod(type, name, args, fixups, begin, error);
if (bool(mem.first)) {
// We found the method.
edm::TypeWithDict retType = reco::returnType(mem.first);
if (!bool(retType)) {
// Invalid return type, fatal error, throw.
throw Exception(begin) << "member \"" << mem.first.name() << "\" return type is invalid:\n"
<< " return type: \"" << mem.first.typeName() << "\"\n";
}
typeStack_.push_back(retType);
// check for edm::Ref, edm::RefToBase, edm::Ptr
if (mem.second) {
// Without fixups.
//std::cout << "Mem.second, so book " << mem.first.name() <<
// " without fixups." << std::endl;
methStack_.push_back(MethodInvoker(mem.first));
if (!deep) {
return false;
}
// note: we have not found the method, so we have not
// fixupped the arguments
push(name, args, begin);
} else {
// With fixups.
//std::cout << "Not mem.second, so book " << mem.first.name()
// << " with #args = " << fixups.size() << std::endl;
methStack_.push_back(MethodInvoker(mem.first, fixups));
}
return true;
}
if (error != reco::parser::kNameDoesNotExist) {
// Fatal error, throw.
switch (error) {
case reco::parser::kIsNotPublic:
throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name()
<< "\" is not publically accessible.";
break;
case reco::parser::kIsStatic:
throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name() << "\" is static.";
break;
case reco::parser::kIsNotConst:
throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name() << "\" is not const.";
break;
case reco::parser::kWrongNumberOfArguments:
throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name()
<< "\" was passed the wrong number of arguments.";
break;
case reco::parser::kWrongArgumentType:
throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name()
<< "\" was passed the wrong types of arguments.";
break;
default:
throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name()
<< "\" is not usable in this context.";
}
}
// Not a method, check for a data member.
error = 0;
edm::MemberWithDict member(reco::findDataMember(type, name, error));
if (!bool(member)) {
// Not a data member either, fatal error, throw.
switch (error) {
case reco::parser::kNameDoesNotExist: {
Exception ex(begin);
ex << "no method or data member named \"" << name << "\" found for type \"" << type.name() << "\"\n";
// The following information is for temporary debugging only, intended to be removed later
ex << "It has the following methods\n";
edm::TypeFunctionMembers functions(type);
for (auto const& f : functions) {
ex << " " << f->GetName() << "\n";
}
ex << "and the following data members\n";
edm::TypeDataMembers members(type);
for (auto const& m : members) {
ex << " " << m->GetName() << "\n";
}
throw ex;
} break;
case reco::parser::kIsNotPublic:
throw Exception(begin) << "data member named \"" << name << "\" for type \"" << type.name()
<< "\" is not publically accessible.";
break;
default:
throw Exception(begin) << "data member named \"" << name << "\" for type \"" << type.name()
<< "\" is not usable in this context.";
break;
}
}
// Ok, it was a data member.
typeStack_.push_back(member.typeOf());
methStack_.push_back(MethodInvoker(member));
return true;
}
|