Skip to content

Commit

Permalink
Dyno: Default initializers for classes that inherit (#26028)
Browse files Browse the repository at this point in the history
This PR changes the frontend to start generating uAST for default
initializers, which allows us to support default initializers on classes
that inherit.

This PR replaces the current signature-based implementation for default
initializers with uAST for a Function. This Function's body contains the
suitable statements to initialize each field, as well as a "super.init"
call if applicable. This code currently lacks suitable init-expressions
for default-initializable formals, which is left as future work.

An UntypedFnSignature is built manually so that we can force resolution
to accept non-existent default values for each formal, regardless of
whether it has an init-expression or not.

The resulting TypedFnSignature is created with `typedSignatureInitial`.
This might be overkill, but it keeps the code cleaner for the time
being.

-----

Now that default initializers have actual bodies, the frontend is
attempting to resolve various assignment operators only defined in the
internal/standard modules. This was initially a problem for the
dedicated frontend tests, which do not generally load the internal
modules in which basic assignment operators are implemented. This PR
updates the frontend to generate assignment operators for primitive
types, tuples, and classes when the standard library is not available.

[reviewed-by @mppf]
  • Loading branch information
benharsh authored Oct 2, 2024
2 parents 328bb70 + 2d2f913 commit 6086616
Show file tree
Hide file tree
Showing 14 changed files with 448 additions and 771 deletions.
9 changes: 7 additions & 2 deletions frontend/lib/framework/ID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,13 @@ ID ID::parentSymbolId(Context* context) const {
return ID();
}

// Otherwise, construct an ID for the parent symbol
return ID(parentSymPath, -1, 0);
if (this->isFabricatedId() &&
this->fabricatedIdKind() == FabricatedIdKind::Generated) {
return ID(parentSymPath, ID_GEN_START, 0);
} else {
// Otherwise, construct an ID for the parent symbol
return ID(parentSymPath, -1, 0);
}
}

UniqueString ID::symbolName(Context* context) const {
Expand Down
4 changes: 3 additions & 1 deletion frontend/lib/parsing/parsing-queries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ parseFileContainingIdToBuilderResult(Context* context,
symbolPath = id.symbolPath();
} else {
symbolPath = ID::parentSymbolPath(context, id.symbolPath());
if (symbolPath.isEmpty()) return nullptr;

// Assumption: The generated module goes only one symbol deep.
CHPL_ASSERT(ID::innermostSymbolName(context, symbolPath).startsWith("chpl__generated"));
Expand Down Expand Up @@ -1246,7 +1247,8 @@ static const AstTag& idToTagQuery(Context* context, ID id) {

AstTag result = asttags::AST_TAG_UNKNOWN;

if (!id.isFabricatedId()) {
if (!id.isFabricatedId() ||
id.fabricatedIdKind() == ID::FabricatedIdKind::Generated) {
const AstNode* ast = astForIdQuery(context, id);
if (ast != nullptr) {
result = ast->tag();
Expand Down
15 changes: 12 additions & 3 deletions frontend/lib/resolution/InitResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,8 @@ InitResolver::computeTypedSignature(const Type* newRecvType) {

formalsInstantiated.resize(ufs->numFormals());

bool needsInstantiation = false;

for (int i = 0; i < tfs->numFormals(); i++) {
if (i == 0) {
auto qt = QualifiedType(determineReceiverIntent(), newRecvType);
Expand All @@ -427,12 +429,15 @@ InitResolver::computeTypedSignature(const Type* newRecvType) {
} else {
formalTypes.push_back(tfs->formalType(i));
formalsInstantiated.setBit(i, tfs->formalIsInstantiated(i));
if (tfs->formalType(i).genericity() == Type::Genericity::GENERIC) {
needsInstantiation = true;
}
}
}

ret = TypedFnSignature::get(ctx_, ufs, formalTypes,
tfs->whereClauseResult(),
/* needsInstantiation */ false,
needsInstantiation,
tfs->instantiatedFrom(),
tfs->parentFn(),
formalsInstantiated,
Expand Down Expand Up @@ -759,8 +764,12 @@ bool InitResolver::handleAssignmentToField(const OpCall* node) {

// TODO: Anything to do if the opposite is true?
if (!isAlreadyInitialized) {
auto& reRhs = initResolver_.byPostorder.byAst(rhs);
state->qt = reRhs.type();
auto rhsType = initResolver_.byPostorder.byAst(rhs).type();

auto param = state->qt.kind() == QualifiedType::PARAM ? rhsType.param() : nullptr;
auto qt = QualifiedType(state->qt.kind(), rhsType.type(), param);
state->qt = qt;

state->initPointId = node->id();
state->isInitialized = true;

Expand Down
Loading

0 comments on commit 6086616

Please sign in to comment.