Skip to content

Commit

Permalink
Resolve associative domain type expr module code in Dyno (#26077)
Browse files Browse the repository at this point in the history
Get associative domain type expressions resolving using their module code in Dyno, and re-enable testing for them.

This PR itself contains little work and mostly just drove Dyno work needed to support the module code.

Contributes to Cray/chapel-private#6729.

Also includes:
- adding a dyno test for _rectangular_ domain literals
- allowing `helpResolveFunction` to run on generic type constructors, per bug fix suggestion from Ben
- adjusting the handling of `param == ?` comparisons which was introduced in #26219, so that it gets specially handled rather than trying to resolve a defined `==` operator
- skipping recursing into `TupleDecl`s in `VarScopeVisitor` to delay [implementing call-init-deinit support for them](Cray/chapel-private#7021) for now
- an out-of-scope fix in `CallInitDeinit::handleDeclarations` where we clearly meant to reference type expr, but used init expr
- moving `makeParam[Int,String,Bool]` helpers in `prims.cpp` onto `QualifiedType` and use everywhere

Future work:
- resolve associative domain literals (#26534)
- implement call-init-deinit for tuple splitting declarations/assignments (Cray/chapel-private#7021)

[reviewed by @DanilaFe , thanks!]

Testing:
- [x] dyno tests
- [x] paratest
  • Loading branch information
riftEmber authored Jan 16, 2025
2 parents c50fbda + 4cb1dcb commit e6a8b27
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 264 deletions.
4 changes: 1 addition & 3 deletions compiler/passes/convert-typed-uast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1098,9 +1098,7 @@ void TConverter::createMainFunctions() {

// TODO: add converter or QualifiedType methods to more
// easily construct a QualifiedType for common values like param false.
auto falseQt = types::QualifiedType(types::QualifiedType::PARAM,
types::BoolType::get(context),
types::BoolParam::get(context, false));
auto falseQt = types::QualifiedType::makeParamBool(context, false);
auto ci = resolution::CallInfo(UniqueString::get(context, "_endCountAlloc"),
/* calledType */ types::QualifiedType(),
/* isMethodCall */ false,
Expand Down
1 change: 1 addition & 0 deletions frontend/include/chpl/types/DomainType.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class DomainType final : public CompositeType {

/** Return an associative domain type */
static const DomainType* getAssociativeType(Context* context,
const QualifiedType& instance,
const QualifiedType& idxType,
const QualifiedType& parSafe);

Expand Down
6 changes: 6 additions & 0 deletions frontend/include/chpl/types/QualifiedType.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ class QualifiedType final {

static const char* kindToString(Kind k);

// Convenience functions to construct param types
static QualifiedType makeParamBool(Context* context, bool b);
static QualifiedType makeParamInt(Context* context, int64_t i);
static QualifiedType makeParamString(Context* context, UniqueString s);
static QualifiedType makeParamString(Context* context, std::string s);

private:
Kind kind_ = UNKNOWN;
const Type* type_ = nullptr;
Expand Down
2 changes: 0 additions & 2 deletions frontend/include/chpl/uast/prim-ops-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ PRIMITIVE_R(QUERY, "query")
PRIMITIVE_R(QUERY_PARAM_FIELD, "query param field")
PRIMITIVE_R(QUERY_TYPE_FIELD, "query type field")

PRIMITIVE_R(STATIC_DOMAIN_TYPE, "static domain type")

PRIMITIVE_R(STATIC_FUNCTION_VAR, "static function var")
PRIMITIVE_R(STATIC_FUNCTION_VAR_VALIDATE_TYPE, "static function validate type")
PRIMITIVE_R(STATIC_FUNCTION_VAR_WRAPPER, "static function var wrapper")
Expand Down
23 changes: 20 additions & 3 deletions frontend/lib/resolution/InitResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,9 @@ static const DomainType* domainTypeFromSubsHelper(
if (auto instanceBct = instanceCt->basicClassType()) {
// Get BaseRectangularDom parent subs for rectangular domain info
if (auto baseDom = instanceBct->parentClassType()) {
auto& rf = fieldsForTypeDecl(context, baseDom,
DefaultsPolicy::IGNORE_DEFAULTS);
if (baseDom->id().symbolPath() == "ChapelDistribution.BaseRectangularDom") {
auto& rf = fieldsForTypeDecl(context, baseDom,
DefaultsPolicy::IGNORE_DEFAULTS);
CHPL_ASSERT(rf.numFields() == 3);
QualifiedType rank;
QualifiedType idxType;
Expand All @@ -315,7 +315,24 @@ static const DomainType* domainTypeFromSubsHelper(
return DomainType::getRectangularType(context, instanceQt, rank,
idxType, strides);
} else if (baseDom->id().symbolPath() == "ChapelDistribution.BaseAssociativeDom") {
// TODO: support associative domains
// Currently the relevant associative domain fields are defined
// on all the children of BaseAssociativeDom, so get information
// from there.
auto& rf = fieldsForTypeDecl(context, instanceBct,
DefaultsPolicy::IGNORE_DEFAULTS);
CHPL_ASSERT(rf.numFields() >= 2);
QualifiedType idxType;
QualifiedType parSafe;
for (int i = 0; i < rf.numFields(); i++) {
if (rf.fieldName(i) == "idxType") {
idxType = rf.fieldType(i);
} else if (rf.fieldName(i) == "parSafe") {
parSafe = rf.fieldType(i);
}
}

return DomainType::getAssociativeType(context, instanceQt, idxType,
parSafe);
} else if (baseDom->id().symbolPath() == "ChapelDistribution.BaseSparseDom") {
// TODO: support sparse domains
} else {
Expand Down
25 changes: 7 additions & 18 deletions frontend/lib/resolution/Resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,9 +1056,7 @@ void Resolver::resolveTypeQueries(const AstNode* formalTypeExpr,
if (isNonStarVarArg) {
varArgTypeQueryError(context, call->actual(0), resolvedWidth);
} else {
auto p = IntParam::get(context, pt->bitwidth());
auto it = IntType::get(context, 0);
auto qt = QualifiedType(QualifiedType::PARAM, it, p);
auto qt = QualifiedType::makeParamInt(context, pt->bitwidth());
resolvedWidth.setType(qt);
}
}
Expand Down Expand Up @@ -1218,10 +1216,8 @@ void Resolver::resolveTypeQueriesFromFormalType(const VarLikeDecl* formal,

// args...?n
if (auto countQuery = varargs->count()) {
auto intType = IntType::get(context, 0);
auto val = IntParam::get(context, tuple->numElements());
ResolvedExpression& result = byPostorder.byAst(countQuery);
result.setType(QualifiedType(QualifiedType::PARAM, intType, val));
result.setType(QualifiedType::makeParamInt(context, tuple->numElements()));
}

if (auto typeExpr = formal->typeExpression()) {
Expand Down Expand Up @@ -2453,8 +2449,7 @@ bool Resolver::resolveSpecialPrimitiveCall(const Call* call) {
resultBool = false;
}

result = QualifiedType(QualifiedType::PARAM, BoolType::get(context),
BoolParam::get(context, resultBool));
result = QualifiedType::makeParamBool(context, resultBool);
}

byPostorder.byAst(primCall).setType(result);
Expand Down Expand Up @@ -2748,9 +2743,7 @@ QualifiedType Resolver::typeForId(const ID& id, bool localGenericToUnknown) {
if (field && field->name() == USTR("size")) {
// Tuples don't store a 'size' in their substitutions map, so
// manually take care of things here.
auto intType = IntType::get(context, 0);
auto val = IntParam::get(context, tup->numElements());
return QualifiedType(QualifiedType::PARAM, intType, val);
return QualifiedType::makeParamInt(context, tup->numElements());
}
}

Expand Down Expand Up @@ -4174,10 +4167,8 @@ void Resolver::exit(const uast::Domain* decl) {

// Add definedConst actual if appropriate
if (decl->usedCurlyBraces()) {
actuals.emplace_back(
QualifiedType(QualifiedType::PARAM, BoolType::get(context),
BoolParam::get(context, true)),
UniqueString());
actuals.emplace_back(QualifiedType::makeParamBool(context, true)),
UniqueString();
}

auto ci = CallInfo(/* name */ UniqueString::get(context, domainBuilderProc),
Expand Down Expand Up @@ -4235,9 +4226,7 @@ types::QualifiedType Resolver::typeForBooleanOp(const uast::OpCall* op) {
// preserve param-ness
// this case is only hit when the result is false (for &&)
// or when the result is true (for ||), so return !isAnd.
return QualifiedType(QualifiedType::PARAM,
BoolType::get(context),
BoolParam::get(context, !isAnd));
return QualifiedType::makeParamBool(context, !isAnd);
} else {
// otherwise just return a Bool value
return QualifiedType(QualifiedType::CONST_VAR,
Expand Down
14 changes: 14 additions & 0 deletions frontend/lib/resolution/VarScopeVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,20 @@ void VarScopeVisitor::exitAst(const uast::AstNode* ast) {
inAstStack.pop_back();
}

bool VarScopeVisitor::enter(const TupleDecl* ast, RV& rv) {
enterAst(ast);
enterScope(ast, rv);

// TODO: handle tuple decls
return false;
}
void VarScopeVisitor::exit(const TupleDecl* ast, RV& rv) {
exitScope(ast, rv);
exitAst(ast);

return;
}

bool VarScopeVisitor::enter(const NamedDecl* ast, RV& rv) {

if (ast->id().isSymbolDefiningScope()) {
Expand Down
3 changes: 3 additions & 0 deletions frontend/lib/resolution/VarScopeVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ class VarScopeVisitor {
bool enter(const NamedDecl* ast, RV& rv);
void exit(const NamedDecl* ast, RV& rv);

bool enter(const TupleDecl* ast, RV& rv);
void exit(const TupleDecl* ast, RV& rv);

bool enter(const OpCall* ast, RV& rv);
void exit(const OpCall* ast, RV& rv);

Expand Down
4 changes: 2 additions & 2 deletions frontend/lib/resolution/call-init-deinit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -788,8 +788,8 @@ void CallInitDeinit::handleDeclaration(const VarLikeDecl* ast, RV& rv) {
VarFrame* frame = currentFrame();

// check for use of deinited variables in type or init exprs
if (auto init = ast->initExpression()) {
processMentions(init, rv);
if (auto type = ast->typeExpression()) {
processMentions(type, rv);
}
if (auto init = ast->initExpression()) {
processMentions(init, rv);
Expand Down
Loading

0 comments on commit e6a8b27

Please sign in to comment.