Skip to content

Commit

Permalink
Dyno: Add support for file-related reflection routines (#26635)
Browse files Browse the repository at this point in the history
This PR adds support for the following reflection routines to dyno:
- ``getLineNumber``
- ``getFileName``
- ``getRoutineName``
- ``getModuleName``

[reviewed-by @DanilaFe]
  • Loading branch information
benharsh authored Jan 31, 2025
2 parents 2261e5e + 19be3b2 commit a269f17
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 2 deletions.
57 changes: 55 additions & 2 deletions frontend/lib/resolution/resolution-queries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5097,6 +5097,49 @@ resolutionResultFromMostSpecificCandidate(ResolutionContext* rc,
exprType, yieldedType, poiInfo);
}

static bool handleReflectionFunction(ResolutionContext* rc,
const TypedFnSignature* sig,
const Call* call,
QualifiedType& result) {
if (sig->isCompilerGenerated()) return false;

auto context = rc->context();
auto fn = parsing::idToAst(context, sig->id())->toFunction();
if (fn && fn->attributeGroup()) {
auto attr = fn->attributeGroup();
if (attr->hasPragma(pragmatags::PRAGMA_GET_LINE_NUMBER)) {
auto loc = parsing::locateId(context, call->id());
result = QualifiedType::makeParamInt(context, loc.firstLine());
return true;
} else if (attr->hasPragma(pragmatags::PRAGMA_GET_FILE_NAME)) {
auto loc = parsing::locateId(context, call->id());
result = QualifiedType::makeParamString(context, loc.path());
return true;
} else if (attr->hasPragma(pragmatags::PRAGMA_GET_FUNCTION_NAME)) {
auto func = parsing::idToParentFunctionId(context, call->id());
if (!func.isEmpty()) {
auto name = func.symbolName(context);
result = QualifiedType::makeParamString(context, name);
} else {
// For compatibility with production
// TODO: What *should* happen here?
auto mod = parsing::idToParentModule(context, call->id());
auto name = mod.symbolName(context);
auto initFn = UniqueString::get(context, "chpl__init_" + name.str());
result = QualifiedType::makeParamString(context, initFn);
}
return true;
} else if (attr->hasPragma(pragmatags::PRAGMA_GET_MODULE_NAME)) {
auto mod = parsing::idToParentModule(context, call->id());
auto name = mod.symbolName(context);
result = QualifiedType::makeParamString(context, name);
return true;
}
}

return false;
}

// call can be nullptr. in that event ci.name() will be used to find
// what is called.
static CallResolutionResult
Expand Down Expand Up @@ -5171,8 +5214,18 @@ resolveFnCall(ResolutionContext* rc,
for (const MostSpecificCandidate& candidate : mostSpecific) {
if (candidate.fn() != nullptr) {
bool isIterator = candidate.fn()->isIterator();
QualifiedType rt = returnType(rc, candidate.fn(),
instantiationPoiScope);

QualifiedType rt;
// TODO: Ideally we'd refactor things such that we instantiate some kind
// of hidden argument to these functions that is then returned. Alas, we
// still need this stuff to work with production, so we create this hack.
if (handleReflectionFunction(rc, candidate.fn(), call, rt)) {
CHPL_ASSERT(rt.isParam() && rt.hasParamPtr());
} else {
rt = returnType(rc, candidate.fn(),
instantiationPoiScope);
}

QualifiedType yt;

if (!candidate.promotedFormals().empty()) {
Expand Down
31 changes: 31 additions & 0 deletions frontend/test/resolution/testReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,36 @@ static void test9() {
ensureParamBool(variables.at("r7"), false);
}

static void test10() {
auto context = buildStdContext();
ErrorGuard guard(context);

auto variables = resolveTypesOfVariables(context,
R"""(
module M {
use Reflection;
param lineno = getLineNumber();
param toplevelFn = getRoutineName();
proc bar() param {
return getRoutineName();
}
param fn = bar();
param filename = getFileName();
param modname = getModuleName();
}
)""", {"lineno", "filename", "toplevelFn", "fn", "modname"});
ensureParamInt(variables["lineno"], 5);
ensureParamString(variables["filename"], "input.chpl");
ensureParamString(variables["toplevelFn"], "chpl__init_M");
ensureParamString(variables["fn"], "bar");
ensureParamString(variables["modname"], "M");
}

int main() {
test1();
test2();
Expand All @@ -322,5 +352,6 @@ int main() {
test7();
test8();
test9();
test10();
return 0;
}

0 comments on commit a269f17

Please sign in to comment.