Skip to content

Commit 9e1b9d7

Browse files
support template instantiation using integral values (#137)
* support template instantiation using integral values * add fixme comment on "should we support template instantiation using string?"
1 parent 4ad9658 commit 9e1b9d7

File tree

1 file changed

+88
-9
lines changed

1 file changed

+88
-9
lines changed

clingwrapper/src/clingwrapper.cxx

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <string.h>
2929
#include <typeinfo>
3030
#include <iostream>
31+
#include <vector>
3132

3233

3334
// temp
@@ -163,6 +164,15 @@ void push_tokens_from_string(char *s, std::vector <const char*> &tokens) {
163164
}
164165
}
165166

167+
static inline
168+
bool is_integral(std::string& s)
169+
{
170+
if (s == "false") { s = "0"; return true; }
171+
else if (s == "true") { s = "1"; return true; }
172+
return !s.empty() && std::find_if(s.begin(),
173+
s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
174+
}
175+
166176
class ApplicationStarter {
167177
Cpp::TInterp_t Interp;
168178
public:
@@ -473,19 +483,66 @@ bool Cppyy::IsFunctionPointerType(TCppType_t type) {
473483
return Cpp::IsFunctionPointerType(type);
474484
}
475485

486+
std::string trim(const std::string& line)
487+
{
488+
if (line.empty()) return "";
489+
const char* WhiteSpace = " \t\v\r\n";
490+
std::size_t start = line.find_first_not_of(WhiteSpace);
491+
std::size_t end = line.find_last_not_of(WhiteSpace);
492+
return line.substr(start, end - start + 1);
493+
}
494+
495+
// returns false of angular brackets dont match, else true
496+
bool split_comma_saparated_types(const std::string& name,
497+
std::vector<std::string>& types) {
498+
std::string trimed_name = trim(name);
499+
size_t start_pos = 0;
500+
size_t end_pos = 0;
501+
size_t appended_count = 0;
502+
int matching_angular_brackets = 0;
503+
while (end_pos < trimed_name.size()) {
504+
switch (trimed_name[end_pos]) {
505+
case ',': {
506+
if (!matching_angular_brackets) {
507+
types.push_back(
508+
trim(trimed_name.substr(start_pos, end_pos - start_pos)));
509+
start_pos = end_pos + 1;
510+
}
511+
break;
512+
}
513+
case '<': {
514+
matching_angular_brackets++;
515+
break;
516+
}
517+
case '>': {
518+
if (matching_angular_brackets == 1) {
519+
types.push_back(
520+
trim(trimed_name.substr(start_pos, end_pos - start_pos + 1)));
521+
start_pos = end_pos + 1;
522+
} else if (matching_angular_brackets < 1) {
523+
types.clear();
524+
return false;
525+
}
526+
matching_angular_brackets--;
527+
break;
528+
}
529+
}
530+
end_pos++;
531+
}
532+
if (start_pos < trimed_name.size())
533+
types.push_back(trim(trimed_name.substr(start_pos, end_pos - start_pos)));
534+
return true;
535+
}
536+
476537
// returns true if no new type was added.
477-
bool Cppyy::AppendTypesSlow(const std::string &name,
538+
bool Cppyy::AppendTypesSlow(const std::string& name,
478539
std::vector<Cpp::TemplateArgInfo>& types) {
479540

480541
// Add no new type if string is empty
481-
if (name.empty()) return true;
542+
if (name.empty())
543+
return true;
482544

483-
// Try going via Cppyy::GetType first.
484-
if (Cppyy::TCppType_t type = GetType(name, /*enable_slow_lookup=*/true)) {
485-
types.push_back(type);
486-
return false;
487-
}
488-
// Else, we might have an entire expression such as int, double.
545+
// We might have an entire expression such as int, double.
489546
static unsigned long long struct_count = 0;
490547
std::string code = "template<typename ...T> struct __Cppyy_AppendTypesSlow {};\n";
491548
if (!struct_count)
@@ -500,7 +557,29 @@ bool Cppyy::AppendTypesSlow(const std::string &name,
500557
Cpp::GetClassTemplateInstantiationArgs(instance_class, types);
501558
return oldSize == types.size();
502559
}
503-
return true;
560+
561+
// We split each individual types based on , and resolve it
562+
// FIXME: see discussion on should we support template instantiation with string:
563+
// https://github.com/compiler-research/cppyy-backend/pull/137#discussion_r2079357491
564+
// We should consider eliminating the `split_comma_saparated_types` and `is_integral`
565+
// string parsing.
566+
std::vector<std::string> individual_types;
567+
if (!split_comma_saparated_types(name, individual_types))
568+
return true;
569+
570+
for (std::string& i : individual_types) {
571+
// Try going via Cppyy::GetType first.
572+
if (Cppyy::TCppType_t type = GetType(i, /*enable_slow_lookup=*/true)) {
573+
const char* integral_value = nullptr;
574+
if (is_integral(i))
575+
integral_value = strdup(i.c_str());
576+
types.emplace_back(type, integral_value);
577+
} else {
578+
types.clear();
579+
return true;
580+
}
581+
}
582+
return false;
504583
}
505584

506585
Cppyy::TCppType_t Cppyy::GetType(const std::string &name, bool enable_slow_lookup /* = false */) {

0 commit comments

Comments
 (0)