Cling: Dynamic Scopes
The ProblemPermalink
The objects from the current directory (gDirectory) are injected into a magic scope that is available to CINT:
Important constrain: To not break old code we need to continue to support this. Of course the code is invalid C++ and thus cannot be parsed by clang. Upon clang’s Sema complaining about undeclared identifiers we need to convert it into proper C++.
Use CasesPermalink
1. Simple use case:Permalink
void macro() {
TFile::Open("f.root");
hpx->Draw();
}
2. ParametersPermalink
void macro() {
TFile::Open("f.root");
int i = 12;
obj->Func(i);
}
3. Function OverloadingPermalink
An additional complication is function overload resolution required in this example:
void Klass::Func(TTree*);
void NameSpace::Func(TH1*);
void Func(TObject*);
using namespace NameSpace;
void Klass::Call() {
TFile::Open("f.root");
int i = 12;
Func(obj);
}
N. Can we have smth else?Permalink
SolutionsPermalink
Escaping to Late EvaluationPermalink
In use case 1: the code can be converted to:
void macro() {
TFile::Open("f.root");
Cling::Interpreter().Eval("hpx->Draw()");
}
This is now valid C++; the code hpx->Draw()
will be evaluated during runtime, when we
know all the necessary information. In this case we have:
In use case number 2: we need to pass the variable to the interpreter as well. We need to introduce a Context
void macro() {
TFile::Open("f.root");
int i = 12;
{
Cling::InterpreterContext ctx;
ctx.add("i", &i);
Cling::Interpreter().Eval("obj->Func(i);", ctx);
}
}
In use case number 3: we don’t know the type of obj at compile time, we don’t know which
overload of Func()
to use.
Here we have several options:
- Let Cling decide which overload to use - We could pass the list of candidates that Sema found during overload resolution to the escaped interpreter, probably including a copy of the identifier table. This would require changes in Sema, because the escaped Sema needs to take an external identifier table and the candidates into account;
- Assume void* - One could argue that this is a rare case. We know that unknown identifiers
have to be pointers; we could simply select the void* overload of
Func()
, i.e. claim that obj is avoid*
; - Refuse the overloads - If we have problems determining the proper overload. By refusing to accept multiple overloads we can simplify the situation;
- Discontinue Support - We could detect the case of multiple overload candidates and issue an error. This should be in case no other options are possible.
The page is based on ClingDynamicScope at tWiki