From 5021a655e21eacebd756874b572e27304da58f4e Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 1 Aug 2024 10:37:52 -0700 Subject: [PATCH 01/65] Move 'init' call comment closer to where it's created Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index af907dda7731..f9dd5205b4eb 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2166,9 +2166,6 @@ bool Resolver::resolveSpecialNewCall(const Call* call) { CHPL_ASSERT(initReceiverType); } - // The 'new' will produce an 'init' call as a side effect. - UniqueString name = USTR("init"); - /* auto cls = qtNewExpr.type()->toClassType(); CHPL_ASSERT(cls); @@ -2191,7 +2188,8 @@ bool Resolver::resolveSpecialNewCall(const Call* call) { CHPL_ASSERT(!questionArg); } - auto ci = CallInfo(name, calledType, isMethodCall, + // The 'new' will produce an 'init' call as a side effect. + auto ci = CallInfo(USTR("init"), calledType, isMethodCall, /* hasQuestionArg */ questionArg != nullptr, /* isParenless */ false, std::move(actuals)); From d70cc1d475146e1e70d88d46c9206ab7a8c4f490 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 1 Aug 2024 11:58:01 -0700 Subject: [PATCH 02/65] Rewrite 'new dmap' to 'new _distribution' Signed-off-by: Anna Rift --- frontend/include/chpl/types/CompositeType.h | 3 +++ frontend/lib/resolution/Resolver.cpp | 10 ++++++++++ frontend/lib/types/CompositeType.cpp | 10 ++++++++++ 3 files changed, 23 insertions(+) diff --git a/frontend/include/chpl/types/CompositeType.h b/frontend/include/chpl/types/CompositeType.h index 0ef8fedec5f0..62c96a590c69 100644 --- a/frontend/include/chpl/types/CompositeType.h +++ b/frontend/include/chpl/types/CompositeType.h @@ -225,6 +225,9 @@ class CompositeType : public Type { /** Get the chpl_localeID_t type */ static const RecordType* getLocaleIDType(Context* context); + /** Get the _distribution type */ + static const RecordType* getDistributionType(Context* context); + /** Get the record _owned implementing owned */ static const RecordType* getOwnedRecordType(Context* context, const BasicClassType* bct); diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index f9dd5205b4eb..e0406da1d742 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2147,6 +2147,16 @@ bool Resolver::resolveSpecialNewCall(const Call* call) { auto newExpr = call->calledExpression()->toNew(); auto& re = byPostorder.byAst(call); auto& reNewExpr = byPostorder.byAst(newExpr); + + // Rewrite 'new dmap' to 'new _distribution' + if (auto rt = reNewExpr.type().type()->toRecordType()) { + if (rt->id().symbolPath() == "ChapelArray.dmap") { + reNewExpr.setType(QualifiedType( + reNewExpr.type().kind(), CompositeType::getDistributionType(context), + reNewExpr.type().param())); + } + } + auto qtNewExpr = reNewExpr.type(); diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index ecd4e73e1e19..9863d0189c3e 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -186,6 +186,15 @@ const RecordType* CompositeType::getLocaleIDType(Context* context) { SubstitutionsMap()); } +const RecordType* CompositeType::getDistributionType(Context* context) { + auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelDistribution", + "_distribution"); + // gdbShouldBreakHere(); + auto name = id.symbolName(context); + return RecordType::get(context, id, name, + /* instantiatedFrom */ nullptr, SubstitutionsMap()); +} + static const RecordType* tryCreateManagerRecord(Context* context, const char* moduleName, const char* recordName, @@ -246,6 +255,7 @@ bool CompositeType::isMissingBundledRecordType(Context* context, ID id) { path == "ChapelRange._range" || path == "ChapelTuple._tuple" || path == "Bytes._bytes" || + path == "ChapelDistribution._distribution" || path == "OwnedObject._owned" || path == "SharedObject._shared"; } From 8edb2bffaacdbb0413cf8d32c2959562be35575a Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 31 Jul 2024 10:27:31 -0700 Subject: [PATCH 03/65] Add 'new' resolution for domains Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index e0406da1d742..501b80ac2577 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -4391,6 +4391,18 @@ static void resolveNewForRecord(Resolver& rv, const New* node, } } +static void resolveNewForDomain(Resolver& rv, const New* node, + const DomainType* domainType) { + ResolvedExpression& re = rv.byPostorder.byAst(node); + + if (node->management() != New::DEFAULT_MANAGEMENT) { + CHPL_REPORT(rv.context, MemManagementNonClass, node, domainType); + } else { + auto qt = QualifiedType(QualifiedType::INIT_RECEIVER, domainType); + re.setType(qt); + } +} + static void resolveNewForUnion(Resolver& rv, const New* node, const UnionType* unionType) { ResolvedExpression& re = rv.byPostorder.byAst(node); @@ -4438,6 +4450,9 @@ void Resolver::exit(const New* node) { } else if (auto recordType = qtTypeExpr.type()->toRecordType()) { resolveNewForRecord(*this, node, recordType); + } else if (auto domainType = qtTypeExpr.type()->toDomainType()) { + resolveNewForDomain(*this, node, domainType); + } else if (auto unionType = qtTypeExpr.type()->toUnionType()) { resolveNewForUnion(*this, node, unionType); From 6f4ad162d7eacc108e58264e3c1a4b052c275aca Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 31 Jul 2024 10:38:56 -0700 Subject: [PATCH 04/65] Replace hardcoded IDs of special records in return-type-inference Signed-off-by: Anna Rift --- frontend/lib/resolution/return-type-inference.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/lib/resolution/return-type-inference.cpp b/frontend/lib/resolution/return-type-inference.cpp index b9f38d680b12..46a94096f614 100644 --- a/frontend/lib/resolution/return-type-inference.cpp +++ b/frontend/lib/resolution/return-type-inference.cpp @@ -161,12 +161,11 @@ const CompositeType* helpGetTypeForDecl(Context* context, insnFromBct, std::move(filteredSubs)); } else if (auto r = ad->toRecord()) { - if (r->id().symbolPath() == "ChapelDomain._domain") { + if (r->id() == DomainType::getGenericDomainType(context)->id()) { ret = DomainType::getGenericDomainType(context); - // TODO: update this to call a method on ArrayType to get the id or path - } else if (r->id().symbolPath() == "ChapelArray._array") { + } else if (r->id() == ArrayType::getGenericArrayType(context)->id()) { ret = ArrayType::getGenericArrayType(context); - } else if (r->id().symbolPath() == "ChapelLocale._locale") { + } else if (r->id() == CompositeType::getLocaleType(context)->id()) { ret = CompositeType::getLocaleType(context); } else { const RecordType* insnFromRec = nullptr; From 1c7008f235dbd7bd58ec00720bdd1d4ee175342d Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 31 Jul 2024 10:58:07 -0700 Subject: [PATCH 05/65] Remove more redundant hardcoded symbol names of special types Signed-off-by: Anna Rift --- frontend/lib/types/ArrayType.cpp | 4 ++-- frontend/lib/types/BasicClassType.cpp | 2 +- frontend/lib/types/CompositeType.cpp | 31 +++++++++++++-------------- frontend/lib/types/DomainType.cpp | 2 +- frontend/lib/types/TupleType.cpp | 2 +- 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/frontend/lib/types/ArrayType.cpp b/frontend/lib/types/ArrayType.cpp index 24d836a60da9..25df89a9d84b 100644 --- a/frontend/lib/types/ArrayType.cpp +++ b/frontend/lib/types/ArrayType.cpp @@ -61,8 +61,8 @@ ArrayType::getArrayTypeQuery(Context* context, ID id, UniqueString name, const ArrayType* ArrayType::getGenericArrayType(Context* context) { - auto name = UniqueString::get(context, "_array"); auto id = getArrayID(context); + auto name = id.symbolName(context); SubstitutionsMap subs; const ArrayType* instantiatedFrom = nullptr; return getArrayTypeQuery(context, id, name, instantiatedFrom, subs).get(); @@ -75,8 +75,8 @@ ArrayType::getArrayType(Context* context, SubstitutionsMap subs; subs.emplace(ArrayType::domainId, domainType); subs.emplace(ArrayType::eltTypeId, eltType); - auto name = UniqueString::get(context, "_array"); auto id = getArrayID(context); + auto name = id.symbolName(context); auto instantiatedFrom = getGenericArrayType(context); return getArrayTypeQuery(context, id, name, instantiatedFrom, subs).get(); } diff --git a/frontend/lib/types/BasicClassType.cpp b/frontend/lib/types/BasicClassType.cpp index 0abbe356fd79..6a3c509ba4b7 100644 --- a/frontend/lib/types/BasicClassType.cpp +++ b/frontend/lib/types/BasicClassType.cpp @@ -65,8 +65,8 @@ BasicClassType::getRootClassType(Context* context) { const BasicClassType* BasicClassType::getReduceScanOpType(Context* context) { - auto name = UniqueString::get(context, "ReduceScanOp"); auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelReduce", "ReduceScanOp"); + auto name = id.symbolName(context); auto objectType = getRootClassType(context); return getBasicClassType(context, id, name, diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index 9863d0189c3e..62986e705add 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -147,40 +147,40 @@ void CompositeType::stringify(std::ostream& ss, } const RecordType* CompositeType::getStringType(Context* context) { - auto name = UniqueString::get(context, "string"); auto id = parsing::getSymbolFromTopLevelModule(context, "String", "_string"); + auto name = UniqueString::get(context, "string"); return RecordType::get(context, id, name, /* instantiatedFrom */ nullptr, SubstitutionsMap()); } const RecordType* CompositeType::getRangeType(Context* context) { - auto name = UniqueString::get(context, "_range"); auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelRange", "_range"); + auto name = id.symbolName(context); return RecordType::get(context, id, name, /* instantiatedFrom */ nullptr, SubstitutionsMap()); } const RecordType* CompositeType::getBytesType(Context* context) { - auto name = UniqueString::get(context, "bytes"); auto id = parsing::getSymbolFromTopLevelModule(context, "Bytes", "_bytes"); + auto name = UniqueString::get(context, "bytes"); return RecordType::get(context, id, name, /* instantiatedFrom */ nullptr, SubstitutionsMap()); } const RecordType* CompositeType::getLocaleType(Context* context) { - auto name = UniqueString::get(context, "locale"); auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelLocale", "_locale"); + auto name = UniqueString::get(context, "locale"); return RecordType::get(context, id, name, /* instantiatedFrom */ nullptr, SubstitutionsMap()); } const RecordType* CompositeType::getLocaleIDType(Context* context) { - auto name = UniqueString::get(context, "chpl_localeID_t"); auto id = ID(); + auto name = UniqueString::get(context, "chpl_localeID_t"); return RecordType::get(context, id, name, /* instantiatedFrom */ nullptr, SubstitutionsMap()); @@ -251,11 +251,11 @@ bool CompositeType::isMissingBundledRecordType(Context* context, ID id) { bool noLibrary = parsing::bundledModulePath(context).isEmpty(); if (noLibrary) { auto path = id.symbolPath(); - return path == "String._string" || - path == "ChapelRange._range" || - path == "ChapelTuple._tuple" || - path == "Bytes._bytes" || - path == "ChapelDistribution._distribution" || + return id == CompositeType::getStringType(context)->id() || + id == CompositeType::getRangeType(context)->id() || + id == TupleType::getGenericTupleType(context)->id() || + id == CompositeType::getBytesType(context)->id() || + id == CompositeType::getDistributionType(context)->id() || path == "OwnedObject._owned" || path == "SharedObject._shared"; } @@ -266,19 +266,18 @@ bool CompositeType::isMissingBundledRecordType(Context* context, ID id) { bool CompositeType::isMissingBundledClassType(Context* context, ID id) { bool noLibrary = parsing::bundledModulePath(context).isEmpty(); if (noLibrary) { - auto path = id.symbolPath(); - return path == "ChapelReduce.ReduceScanOp" || - path == "Errors.Error" || - path == "CTypes.c_ptr" || - path == "CTypes.c_ptrConst"; + return id == BasicClassType::getReduceScanOpType(context)->id() || + id == CompositeType::getErrorType(context)->basicClassType()->id() || + id == CPtrType::getId(context) || + id == CPtrType::getConstId(context); } return false; } const ClassType* CompositeType::getErrorType(Context* context) { - auto name = UniqueString::get(context, "Error"); auto id = parsing::getSymbolFromTopLevelModule(context, "Errors", "Error"); + auto name = id.symbolName(context); auto dec = ClassTypeDecorator(ClassTypeDecorator::GENERIC_NONNIL); auto bct = BasicClassType::get(context, id, name, diff --git a/frontend/lib/types/DomainType.cpp b/frontend/lib/types/DomainType.cpp index e536f0f9f831..b5c72b672ebe 100644 --- a/frontend/lib/types/DomainType.cpp +++ b/frontend/lib/types/DomainType.cpp @@ -69,8 +69,8 @@ DomainType::getDomainType(Context* context, ID id, UniqueString name, const DomainType* DomainType::getGenericDomainType(Context* context) { - auto name = UniqueString::get(context, "_domain"); auto id = getDomainID(context); + auto name = id.symbolName(context); SubstitutionsMap subs; const DomainType* instantiatedFrom = nullptr; return getDomainType(context, id, name, instantiatedFrom, subs).get(); diff --git a/frontend/lib/types/TupleType.cpp b/frontend/lib/types/TupleType.cpp index 73ed247e3716..0bd206bc9331 100644 --- a/frontend/lib/types/TupleType.cpp +++ b/frontend/lib/types/TupleType.cpp @@ -100,8 +100,8 @@ TupleType::getTupleType(Context* context, const TupleType* instantiatedFrom, QUERY_BEGIN(getTupleType, context, instantiatedFrom, subs, isVarArgTuple); - auto name = UniqueString::get(context, "_tuple"); auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelTuple", "_tuple"); + auto name = id.symbolName(context); auto result = toOwned(new TupleType(id, name, instantiatedFrom, std::move(subs), isVarArgTuple)); From cf2b217e0c0458b3fcf8c499c11a7310f0a5568b Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 2 Aug 2024 09:42:17 -0700 Subject: [PATCH 06/65] Assert domain is domain type in testDomains Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 14dd1fc1a6a9..2299b2f07f6f 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -91,6 +91,7 @@ module M { const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); QualifiedType dType = findVarType(m, rr, "d"); + assert(dType.type()->isDomainType()); QualifiedType fullIndexType = findVarType(m, rr, "fullIndex"); @@ -190,6 +191,7 @@ module M { const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); QualifiedType dType = findVarType(m, rr, "d"); + assert(dType.type()->isDomainType()); auto fullIndexType = findVarType(m, rr, "i"); assert(findVarType(m, rr, "ig") == fullIndexType); From 87ec0d226a1226d71dfa0e85c73b19bd492e52ef Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 5 Aug 2024 12:49:41 -0700 Subject: [PATCH 07/65] Rewrite resolveSpecialCall if/else as a short-circuiting disjunction Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 501b80ac2577..085a5cd9136c 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2345,17 +2345,10 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { } bool Resolver::resolveSpecialCall(const Call* call) { - if (resolveSpecialOpCall(call)) { - return true; - } else if (resolveSpecialPrimitiveCall(call)) { - return true; - } else if (resolveSpecialNewCall(call)) { - return true; - } else if (resolveSpecialKeywordCall(call)) { - return true; - } - - return false; + return resolveSpecialOpCall(call) || + resolveSpecialPrimitiveCall(call) || + resolveSpecialNewCall(call) || + resolveSpecialKeywordCall(call); } static QualifiedType From 4c7740b662187a6bd50b579803f76650d6ffb599 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 6 Aug 2024 09:52:56 -0700 Subject: [PATCH 08/65] Add 'domain' case to resolveSpecialKeywordCall Signed-off-by: Anna Rift --- .../resolution-error-classes-list.h | 1 + frontend/lib/resolution/Resolver.cpp | 21 +++++++++++++++++++ frontend/lib/resolution/Resolver.h | 2 +- .../resolution-error-classes-list.cpp | 8 +++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/frontend/include/chpl/resolution/resolution-error-classes-list.h b/frontend/include/chpl/resolution/resolution-error-classes-list.h index 6cf7b7d2d3b8..2c518e2b8871 100644 --- a/frontend/include/chpl/resolution/resolution-error-classes-list.h +++ b/frontend/include/chpl/resolution/resolution-error-classes-list.h @@ -54,6 +54,7 @@ ERROR_CLASS(IncompatibleKinds, types::QualifiedType::Kind, const uast::AstNode*, ERROR_CLASS(IncompatibleRangeBounds, const uast::Range*, types::QualifiedType, types::QualifiedType) ERROR_CLASS(IncompatibleTypeAndInit, const uast::AstNode*, const uast::AstNode*, const uast::AstNode*, const types::Type*, const types::Type*) ERROR_CLASS(InvalidClassCast, const uast::PrimCall*, types::QualifiedType) +ERROR_CLASS(InvalidDomainCall, const uast::FnCall*) ERROR_CLASS(InvalidIndexCall, const uast::FnCall*, types::QualifiedType) ERROR_CLASS(InvalidNewTarget, const uast::New*, types::QualifiedType) ERROR_CLASS(InvalidParamCast, const uast::AstNode*, types::QualifiedType, types::QualifiedType) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 085a5cd9136c..41cfc8192a36 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2339,6 +2339,27 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { CHPL_REPORT(context, InvalidIndexCall, fnCall, firstActual); } return true; + } else if (fnName == "domain") { + auto runResult = context->runAndTrackErrors([&](Context* ctx) { + // TODO: modify call to be correct (pass implicit dist actual) + auto ci = CallInfo::create(context, call, byPostorder, + /* raiseErrors */ true, + /* actualAsts */ nullptr, + /* moduleScopeId */ nullptr, + /* rename */ UniqueString::get(context, "chpl__buildDomainRuntimeType")); + auto scope = scopeStack.back(); + auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); + auto result = resolveGeneratedCall(context, call, ci, inScopes); + + auto& r = byPostorder.byAst(call); + handleResolvedCall(r, call, ci, result); + return result; + }); + + if (!runResult.ranWithoutErrors()) { + CHPL_REPORT(context, InvalidDomainCall, fnCall); + } + return true; } return false; diff --git a/frontend/lib/resolution/Resolver.h b/frontend/lib/resolution/Resolver.h index 67a2295e1ac0..6825419aee6d 100644 --- a/frontend/lib/resolution/Resolver.h +++ b/frontend/lib/resolution/Resolver.h @@ -512,7 +512,7 @@ struct Resolver { // own logic for traversing actuals etc. bool resolveSpecialPrimitiveCall(const uast::Call* call); - // resolve a keyword call like index(D) + // resolve a keyword call like index(D) or domain(1) bool resolveSpecialKeywordCall(const uast::Call* call); // Resolve a || or && operation. diff --git a/frontend/lib/resolution/resolution-error-classes-list.cpp b/frontend/lib/resolution/resolution-error-classes-list.cpp index 636687101093..ea149b123ad0 100644 --- a/frontend/lib/resolution/resolution-error-classes-list.cpp +++ b/frontend/lib/resolution/resolution-error-classes-list.cpp @@ -615,6 +615,14 @@ void ErrorInvalidClassCast::write(ErrorWriterBase& wr) const { } } +void ErrorInvalidDomainCall::write(ErrorWriterBase& wr) const { + auto fnCall = std::get(info_); + + wr.heading(kind_, type_, fnCall, "invalid use of the 'domain' keyword."); + wr.codeForLocation(fnCall); + // TODO: flesh out +} + void ErrorInvalidIndexCall::write(ErrorWriterBase& wr) const { auto fnCall = std::get(info_); auto& type = std::get(info_); From 6b7b8b7a8652c0ff98d234922423a331f9e44a5d Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 6 Aug 2024 10:53:36 -0700 Subject: [PATCH 09/65] Resolve 'domain(?)' as 'domain' Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 47 ++++++++++++++++++---------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 41cfc8192a36..9f2bae0ccef8 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2314,6 +2314,8 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { auto fnCall = call->toFnCall(); if (!fnCall->calledExpression()->isIdentifier()) return false; + auto& r = byPostorder.byAst(call); + auto fnName = fnCall->calledExpression()->toIdentifier()->name(); if (fnName == "index") { auto runResult = context->runAndTrackErrors([&](Context* ctx) { @@ -2326,7 +2328,6 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); auto result = resolveGeneratedCall(context, call, ci, inScopes); - auto& r = byPostorder.byAst(call); handleResolvedCall(r, call, ci, result); return result; }); @@ -2340,24 +2341,36 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { } return true; } else if (fnName == "domain") { - auto runResult = context->runAndTrackErrors([&](Context* ctx) { - // TODO: modify call to be correct (pass implicit dist actual) - auto ci = CallInfo::create(context, call, byPostorder, - /* raiseErrors */ true, - /* actualAsts */ nullptr, - /* moduleScopeId */ nullptr, - /* rename */ UniqueString::get(context, "chpl__buildDomainRuntimeType")); - auto scope = scopeStack.back(); - auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); - auto result = resolveGeneratedCall(context, call, ci, inScopes); + // Try resolving 'domain(?)' as a special case. + if (call->numActuals() == 1 && call->actual(0)->isIdentifier() && + call->actual(0)->toIdentifier()->name() == "?") { + // 'domain(?)' is equivalent to just 'domain', the generic domain + // type. + // Copy the result of resolving 'domain' as the called identifier. + auto& rCalledExp = byPostorder.byAst(fnCall->calledExpression()); + CHPL_ASSERT(rCalledExp.type().hasTypePtr()); + r.setType(rCalledExp.type()); + } else { + auto runResult = context->runAndTrackErrors([&](Context* ctx) { + // TODO: modify call to be correct (pass implicit dist actual) + auto ci = CallInfo::create( + context, call, byPostorder, + /* raiseErrors */ true, + /* actualAsts */ nullptr, + /* moduleScopeId */ nullptr, + /* rename */ + UniqueString::get(context, "chpl__buildDomainRuntimeType")); + auto scope = scopeStack.back(); + auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); + auto result = resolveGeneratedCall(context, call, ci, inScopes); - auto& r = byPostorder.byAst(call); - handleResolvedCall(r, call, ci, result); - return result; - }); + handleResolvedCall(r, call, ci, result); + return result; + }); - if (!runResult.ranWithoutErrors()) { - CHPL_REPORT(context, InvalidDomainCall, fnCall); + if (!runResult.ranWithoutErrors()) { + CHPL_REPORT(context, InvalidDomainCall, fnCall); + } } return true; } From b9146f684234de7a8025cd9b8c2e4ca586064057 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 6 Aug 2024 12:11:56 -0700 Subject: [PATCH 10/65] Pass 'dist' arg with placeholder type Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 36 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 9f2bae0ccef8..134658614aed 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2193,10 +2193,8 @@ bool Resolver::resolveSpecialNewCall(const Call* call) { actuals.push_back(std::move(receiverInfo)); // Remaining actuals. - if (call->numActuals()) { - prepareCallInfoActuals(call, actuals, questionArg); - CHPL_ASSERT(!questionArg); - } + prepareCallInfoActuals(call, actuals, questionArg); + CHPL_ASSERT(!questionArg); // The 'new' will produce an 'init' call as a side effect. auto ci = CallInfo(USTR("init"), calledType, isMethodCall, @@ -2341,25 +2339,35 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { } return true; } else if (fnName == "domain") { + auto& rCalledExp = byPostorder.byAst(fnCall->calledExpression()); + CHPL_ASSERT(rCalledExp.type().hasTypePtr()); // Try resolving 'domain(?)' as a special case. if (call->numActuals() == 1 && call->actual(0)->isIdentifier() && call->actual(0)->toIdentifier()->name() == "?") { // 'domain(?)' is equivalent to just 'domain', the generic domain // type. // Copy the result of resolving 'domain' as the called identifier. - auto& rCalledExp = byPostorder.byAst(fnCall->calledExpression()); - CHPL_ASSERT(rCalledExp.type().hasTypePtr()); r.setType(rCalledExp.type()); } else { auto runResult = context->runAndTrackErrors([&](Context* ctx) { - // TODO: modify call to be correct (pass implicit dist actual) - auto ci = CallInfo::create( - context, call, byPostorder, - /* raiseErrors */ true, - /* actualAsts */ nullptr, - /* moduleScopeId */ nullptr, - /* rename */ - UniqueString::get(context, "chpl__buildDomainRuntimeType")); + const AstNode* questionArg = nullptr; + std::vector actuals; + // Set up 'dist' arg + // TODO: get and use real type of defaultDist here + auto defaultDistArg = + CallInfoActual(QualifiedType(), UniqueString::get(context, "dist")); + actuals.push_back(std::move(defaultDistArg)); + // Remaining given args from domain() call as written + prepareCallInfoActuals(call, actuals, questionArg); + CHPL_ASSERT(!questionArg); + auto ci = + CallInfo(UniqueString::get(context, "chpl__buildDomainRuntimeType"), + rCalledExp.type(), + /* isMethodCall */ false, + /* hasQuestionArg */ false, + /* isParenless */ false, + actuals); + auto scope = scopeStack.back(); auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); auto result = resolveGeneratedCall(context, call, ci, inScopes); From 9324e5785f516ee649b43e56d3f693fdac53f663 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 6 Aug 2024 12:40:01 -0700 Subject: [PATCH 11/65] Resolve and use real 'defaultDist' type Signed-off-by: Anna Rift --- frontend/include/chpl/types/DomainType.h | 3 +++ frontend/lib/resolution/Resolver.cpp | 7 ++++--- frontend/lib/types/CompositeType.cpp | 1 + frontend/lib/types/DomainType.cpp | 10 ++++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/frontend/include/chpl/types/DomainType.h b/frontend/include/chpl/types/DomainType.h index 4cffbee6175f..f92ebcebd4b6 100644 --- a/frontend/include/chpl/types/DomainType.h +++ b/frontend/include/chpl/types/DomainType.h @@ -100,6 +100,9 @@ class DomainType final : public CompositeType { const QualifiedType& idxType, const QualifiedType& parSafe); + /** Get the default distribution type */ + static const RecordType* getDefaultDistType(Context* context); + Kind kind() const { return kind_; } diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 134658614aed..c2cd3870bec0 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2353,9 +2353,10 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { const AstNode* questionArg = nullptr; std::vector actuals; // Set up 'dist' arg - // TODO: get and use real type of defaultDist here - auto defaultDistArg = - CallInfoActual(QualifiedType(), UniqueString::get(context, "dist")); + auto defaultDistArg = CallInfoActual( + QualifiedType(QualifiedType::CONST_REF, + DomainType::getDefaultDistType(context)), + UniqueString::get(context, "dist")); actuals.push_back(std::move(defaultDistArg)); // Remaining given args from domain() call as written prepareCallInfoActuals(call, actuals, questionArg); diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index 62986e705add..3462bb581a37 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -256,6 +256,7 @@ bool CompositeType::isMissingBundledRecordType(Context* context, ID id) { id == TupleType::getGenericTupleType(context)->id() || id == CompositeType::getBytesType(context)->id() || id == CompositeType::getDistributionType(context)->id() || + id == DomainType::getDefaultDistType(context)->id() || path == "OwnedObject._owned" || path == "SharedObject._shared"; } diff --git a/frontend/lib/types/DomainType.cpp b/frontend/lib/types/DomainType.cpp index b5c72b672ebe..6308c1412961 100644 --- a/frontend/lib/types/DomainType.cpp +++ b/frontend/lib/types/DomainType.cpp @@ -106,6 +106,16 @@ DomainType::getAssociativeType(Context* context, DomainType::Kind::Associative).get(); } +const RecordType* DomainType::getDefaultDistType(Context* context) { + auto id = parsing::getSymbolFromTopLevelModule(context, "DefaultRectangular", + "defaultDist"); + auto name = id.symbolName(context); + + return RecordType::get(context, id, name, + /* instantiatedFrom */ nullptr, + /* subs */ SubstitutionsMap()); +} + int DomainType::rankInt() const { if (kind_ == Kind::Rectangular) { return rank().param()->toIntParam()->value(); From 8882ea2a03ed7239f05fdb63ed1fd94d0ff2bf3b Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 21 Aug 2024 13:26:11 -0700 Subject: [PATCH 12/65] Move instead of copy actuals Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index c2cd3870bec0..b09fb3b506ba 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2367,7 +2367,7 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { /* isMethodCall */ false, /* hasQuestionArg */ false, /* isParenless */ false, - actuals); + std::move(actuals)); auto scope = scopeStack.back(); auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); From 3e34e1506987b4fa1cf1d48ed74fd9d583e8454d Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 21 Aug 2024 13:28:30 -0700 Subject: [PATCH 13/65] Switch domain resolve from chpl__buildDomainRuntimeType to new _domain Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index b09fb3b506ba..f059f19fdf5f 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2352,6 +2352,9 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { auto runResult = context->runAndTrackErrors([&](Context* ctx) { const AstNode* questionArg = nullptr; std::vector actuals; + // Set up receiver + auto receiverArg = CallInfoActual(rCalledExp.type(), USTR("this")); + actuals.push_back(std::move(receiverArg)); // Set up 'dist' arg auto defaultDistArg = CallInfoActual( QualifiedType(QualifiedType::CONST_REF, @@ -2362,7 +2365,7 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { prepareCallInfoActuals(call, actuals, questionArg); CHPL_ASSERT(!questionArg); auto ci = - CallInfo(UniqueString::get(context, "chpl__buildDomainRuntimeType"), + CallInfo(USTR("init"), rCalledExp.type(), /* isMethodCall */ false, /* hasQuestionArg */ false, From 2b56b7fd46cc8c0fa23a8bac5d12d4346d4a03fc Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 21 Aug 2024 13:51:08 -0700 Subject: [PATCH 14/65] More work on getting new _domain working Most significantly including proper lookup of the type of defaultDist Signed-off-by: Anna Rift --- frontend/include/chpl/types/DomainType.h | 2 +- frontend/lib/resolution/Resolver.cpp | 29 ++++++++------- .../lib/resolution/resolution-queries.cpp | 35 ++++++++++--------- frontend/lib/types/CompositeType.cpp | 3 +- frontend/lib/types/DomainType.cpp | 22 +++++++++--- frontend/lib/types/Type.cpp | 1 + 6 files changed, 57 insertions(+), 35 deletions(-) diff --git a/frontend/include/chpl/types/DomainType.h b/frontend/include/chpl/types/DomainType.h index f92ebcebd4b6..f821977bd543 100644 --- a/frontend/include/chpl/types/DomainType.h +++ b/frontend/include/chpl/types/DomainType.h @@ -101,7 +101,7 @@ class DomainType final : public CompositeType { const QualifiedType& parSafe); /** Get the default distribution type */ - static const RecordType* getDefaultDistType(Context* context); + static const QualifiedType& getDefaultDistType(Context* context); Kind kind() const { return kind_; diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index f059f19fdf5f..2ee96efe33aa 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2349,25 +2349,28 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { // Copy the result of resolving 'domain' as the called identifier. r.setType(rCalledExp.type()); } else { - auto runResult = context->runAndTrackErrors([&](Context* ctx) { + // Get type by resolving the type of corresponding '_domain' init call + // TODO: prohibit associative domain with idxType 'domain' + // auto runResult = context->runAndTrackErrors([&](Context* ctx) { const AstNode* questionArg = nullptr; std::vector actuals; // Set up receiver - auto receiverArg = CallInfoActual(rCalledExp.type(), USTR("this")); + auto receiverType = + QualifiedType(QualifiedType::VAR, rCalledExp.type().type()); + auto receiverArg = CallInfoActual(receiverType, USTR("this")); actuals.push_back(std::move(receiverArg)); - // Set up 'dist' arg + // Set up distribution arg auto defaultDistArg = CallInfoActual( - QualifiedType(QualifiedType::CONST_REF, - DomainType::getDefaultDistType(context)), - UniqueString::get(context, "dist")); + DomainType::getDefaultDistType(context), UniqueString()); actuals.push_back(std::move(defaultDistArg)); // Remaining given args from domain() call as written prepareCallInfoActuals(call, actuals, questionArg); CHPL_ASSERT(!questionArg); + auto ci = CallInfo(USTR("init"), - rCalledExp.type(), - /* isMethodCall */ false, + /* calledType */ receiverType, + /* isMethodCall */ true, /* hasQuestionArg */ false, /* isParenless */ false, std::move(actuals)); @@ -2377,12 +2380,12 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { auto result = resolveGeneratedCall(context, call, ci, inScopes); handleResolvedCall(r, call, ci, result); - return result; - }); + // return result; + // }); - if (!runResult.ranWithoutErrors()) { - CHPL_REPORT(context, InvalidDomainCall, fnCall); - } + // if (!runResult.ranWithoutErrors()) { + // CHPL_REPORT(context, InvalidDomainCall, fnCall); + // } } return true; } diff --git a/frontend/lib/resolution/resolution-queries.cpp b/frontend/lib/resolution/resolution-queries.cpp index 8e8b237b802a..96e6804afab4 100644 --- a/frontend/lib/resolution/resolution-queries.cpp +++ b/frontend/lib/resolution/resolution-queries.cpp @@ -1634,6 +1634,8 @@ typeConstructorInitialQuery(Context* context, const Type* t) idTag = uast::asttags::Class; } else if (t->isRecordType()) { idTag = uast::asttags::Record; + } else if (t->isDomainType()) { + idTag = uast::asttags::Record; } else if (t->isUnionType()) { idTag = uast::asttags::Union; } @@ -3972,22 +3974,22 @@ static bool resolveFnCallSpecialType(Context* context, // // TODO: sync, single if (ci.name() == "domain") { - // TODO: a compiler-generated type constructor would be simpler, but we - // don't support default values on compiler-generated methods because the - // default values require existing AST. - - // Note: 'dmapped' is treated like a binary operator at the moment, so - // we don't need to worry about distribution type for 'domain(...)' exprs. - - // Transform domain type expressions like `domain(arg1, ...)` into: - // _domain.static_type(arg1, ...) - auto genericDom = DomainType::getGenericDomainType(context); - auto recv = QualifiedType(QualifiedType::TYPE, genericDom); - auto typeCtorName = UniqueString::get(context, "static_type"); - auto ctorCall = CallInfo::createWithReceiver(ci, recv, typeCtorName); - - result = resolveCall(rc, call, ctorCall, inScopes); - return true; + // // TODO: a compiler-generated type constructor would be simpler, but we + // // don't support default values on compiler-generated methods because the + // // default values require existing AST. + + // // Note: 'dmapped' is treated like a binary operator at the moment, so + // // we don't need to worry about distribution type for 'domain(...)' exprs. + + // // Transform domain type expressions like `domain(arg1, ...)` into: + // // _domain.static_type(arg1, ...) + // auto genericDom = DomainType::getGenericDomainType(context); + // auto recv = QualifiedType(QualifiedType::TYPE, genericDom); + // auto typeCtorName = UniqueString::get(context, "static_type"); + // auto ctorCall = CallInfo::createWithReceiver(ci, recv, typeCtorName); + + // result = resolveCall(rc, call, ctorCall, inScopes); + // return true; } else if (ci.name() == "atomic") { auto newName = UniqueString::get(context, "chpl__atomicType"); auto ctorCall = CallInfo::copyAndRename(ci, newName); @@ -4817,6 +4819,7 @@ resolveFnCall(ResolutionContext* rc, ci.isMethodCall() == false) { // handle invocation of a type constructor from a type // (note that we might have the type through a type alias) + if (ci.name() == "domain" || ci.name() == "_domain") gdbShouldBreakHere(); mostSpecific = resolveFnCallForTypeCtor(context, ci, inScopes.callScope(), inScopes.poiScope(), diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index 3462bb581a37..fc0a318dc711 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -26,7 +26,9 @@ #include "chpl/types/BasicClassType.h" #include "chpl/types/ClassType.h" #include "chpl/types/ClassTypeDecorator.h" +#include "chpl/types/CPtrType.h" #include "chpl/types/RecordType.h" +#include "chpl/types/TupleType.h" #include "chpl/uast/Decl.h" #include "chpl/uast/NamedDecl.h" @@ -256,7 +258,6 @@ bool CompositeType::isMissingBundledRecordType(Context* context, ID id) { id == TupleType::getGenericTupleType(context)->id() || id == CompositeType::getBytesType(context)->id() || id == CompositeType::getDistributionType(context)->id() || - id == DomainType::getDefaultDistType(context)->id() || path == "OwnedObject._owned" || path == "SharedObject._shared"; } diff --git a/frontend/lib/types/DomainType.cpp b/frontend/lib/types/DomainType.cpp index 6308c1412961..ff689c58a21a 100644 --- a/frontend/lib/types/DomainType.cpp +++ b/frontend/lib/types/DomainType.cpp @@ -21,6 +21,7 @@ #include "chpl/framework/query-impl.h" #include "chpl/parsing/parsing-queries.h" +#include "chpl/resolution/resolution-queries.h" #include "chpl/resolution/intents.h" #include "chpl/types/Param.h" #include "chpl/types/TupleType.h" @@ -106,14 +107,27 @@ DomainType::getAssociativeType(Context* context, DomainType::Kind::Associative).get(); } -const RecordType* DomainType::getDefaultDistType(Context* context) { +const QualifiedType& DomainType::getDefaultDistType(Context* context) { + QUERY_BEGIN(getDefaultDistType, context); + + QualifiedType result; + auto id = parsing::getSymbolFromTopLevelModule(context, "DefaultRectangular", "defaultDist"); auto name = id.symbolName(context); + auto modName = ID::parentSymbolPath(context, id.symbolPath()); - return RecordType::get(context, id, name, - /* instantiatedFrom */ nullptr, - /* subs */ SubstitutionsMap()); + if (auto mod = parsing::getToplevelModule(context, modName)) { + for (auto stmt : mod->children()) { + auto decl = stmt->toNamedDecl(); + if (decl && decl->name() == name) { + auto res = resolution::resolveModuleStmt(context, stmt->id()); + result = res.byId(stmt->id()).type(); + } + } + } + + return QUERY_END(result); } int DomainType::rankInt() const { diff --git a/frontend/lib/types/Type.cpp b/frontend/lib/types/Type.cpp index 6d13e0fbba2b..ea474bdad5c5 100644 --- a/frontend/lib/types/Type.cpp +++ b/frontend/lib/types/Type.cpp @@ -128,6 +128,7 @@ void Type::gatherBuiltins(Context* context, gatherType(context, map, "Error", CompositeType::getErrorType(context)); gatherType(context, map, "domain", DomainType::getGenericDomainType(context)); + gatherType(context, map, "_domain", DomainType::getGenericDomainType(context)); gatherType(context, map, "class", AnyClassType::get(context)); auto genericBorrowed = ClassType::get(context, AnyClassType::get(context), nullptr, ClassTypeDecorator(ClassTypeDecorator::BORROWED)); From f4d7694df99a17ace8cd5097a3951e3d70492211 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 23 Aug 2024 13:30:35 -0700 Subject: [PATCH 15/65] Add TODO to put runAndTrackErrors back Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 2ee96efe33aa..b710beb8cf5e 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2351,6 +2351,7 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { } else { // Get type by resolving the type of corresponding '_domain' init call // TODO: prohibit associative domain with idxType 'domain' + // TODO: put runAndTrackErrors back after resolving perf issues with it // auto runResult = context->runAndTrackErrors([&](Context* ctx) { const AstNode* questionArg = nullptr; std::vector actuals; From 983353fd0dab6dd928b98449c283f7f0def850c9 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 23 Aug 2024 09:17:55 -0700 Subject: [PATCH 16/65] Remove leftover breakpoints Signed-off-by: Anna Rift --- frontend/lib/resolution/resolution-queries.cpp | 1 - frontend/lib/types/CompositeType.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/frontend/lib/resolution/resolution-queries.cpp b/frontend/lib/resolution/resolution-queries.cpp index 96e6804afab4..8421bf106950 100644 --- a/frontend/lib/resolution/resolution-queries.cpp +++ b/frontend/lib/resolution/resolution-queries.cpp @@ -4819,7 +4819,6 @@ resolveFnCall(ResolutionContext* rc, ci.isMethodCall() == false) { // handle invocation of a type constructor from a type // (note that we might have the type through a type alias) - if (ci.name() == "domain" || ci.name() == "_domain") gdbShouldBreakHere(); mostSpecific = resolveFnCallForTypeCtor(context, ci, inScopes.callScope(), inScopes.poiScope(), diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index fc0a318dc711..fd8b8b5d22fb 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -191,7 +191,6 @@ const RecordType* CompositeType::getLocaleIDType(Context* context) { const RecordType* CompositeType::getDistributionType(Context* context) { auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelDistribution", "_distribution"); - // gdbShouldBreakHere(); auto name = id.symbolName(context); return RecordType::get(context, id, name, /* instantiatedFrom */ nullptr, SubstitutionsMap()); From 882b31c6924d42d52437f055a1c5d09db44a69ee Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 23 Aug 2024 09:24:37 -0700 Subject: [PATCH 17/65] Use init call as type rather than value Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index b710beb8cf5e..f9c7568e4400 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2381,6 +2381,8 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { auto result = resolveGeneratedCall(context, call, ci, inScopes); handleResolvedCall(r, call, ci, result); + // Use the init call type as a TYPE value + r.setType(QualifiedType(QualifiedType::TYPE, r.type().type())); // return result; // }); From 8830b083ecc83cb032dd74bed9bd7f73c808f162 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 23 Aug 2024 13:00:20 -0700 Subject: [PATCH 18/65] Add domain literal type resolution Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 43 +++++++++++++++++++++++++++- frontend/lib/types/CompositeType.cpp | 1 + 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index f9c7568e4400..eead8cc70e41 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -3799,10 +3799,51 @@ bool Resolver::enter(const uast::Domain* decl) { } void Resolver::exit(const uast::Domain* decl) { + const DomainType* genericDomainType = DomainType::getGenericDomainType(context); + if (CompositeType::isMissingBundledRecordType(context, genericDomainType->id())) { + // If we don't have the standard library code backing the Domain type, leave + // it unresolved. + return; + } + if (decl->numExprs() == 0) { + // Generic domain, as in a generic-domain array auto& re = byPostorder.byAst(decl); - auto dt = QualifiedType(QualifiedType::CONST_VAR, DomainType::getGenericDomainType(context)); + auto dt = QualifiedType(QualifiedType::CONST_VAR, genericDomainType); re.setType(dt); + } else { + // Call appropriate domain builder proc. Use ensureDomainExpr when the + // domain is declared without curly braces (within an array type). + const char* domainBuilderProc = decl->usedCurlyBraces() + ? "chpl__buildDomainExpr" + : "chpl__ensureDomainExpr"; + + // Add key or range actuals + std::vector actuals; + for (auto expr : decl->exprs()) { + actuals.emplace_back(byPostorder.byAst(expr).type(), UniqueString()); + } + + // Add definedConst actual if appropriate + if (decl->usedCurlyBraces()) { + actuals.emplace_back( + QualifiedType(QualifiedType::PARAM, BoolType::get(context), + BoolParam::get(context, true)), + UniqueString()); + } + + auto ci = CallInfo(/* name */ UniqueString::get(context, domainBuilderProc), + /* calledType */ QualifiedType(), + /* isMethodCall */ false, + /* hasQuestionArg */ false, + /* isParenless */ false, + actuals); + auto scope = scopeStack.back(); + auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); + auto c = resolveGeneratedCall(context, decl, ci, inScopes); + + ResolvedExpression& r = byPostorder.byAst(decl); + handleResolvedCall(r, decl, ci, c); } } diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index fd8b8b5d22fb..5b364a39fbe7 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -257,6 +257,7 @@ bool CompositeType::isMissingBundledRecordType(Context* context, ID id) { id == TupleType::getGenericTupleType(context)->id() || id == CompositeType::getBytesType(context)->id() || id == CompositeType::getDistributionType(context)->id() || + id == DomainType::getGenericDomainType(context)->id() || path == "OwnedObject._owned" || path == "SharedObject._shared"; } From e879d16cbef13e607381756c5b78456af1a33e78 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 4 Sep 2024 10:07:42 -0700 Subject: [PATCH 19/65] Fix comment about object -> RootClass Signed-off-by: Anna Rift --- frontend/lib/types/BasicClassType.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/lib/types/BasicClassType.cpp b/frontend/lib/types/BasicClassType.cpp index 6a3c509ba4b7..82f4269bb25c 100644 --- a/frontend/lib/types/BasicClassType.cpp +++ b/frontend/lib/types/BasicClassType.cpp @@ -44,7 +44,7 @@ BasicClassType::get(Context* context, ID id, UniqueString name, const BasicClassType* parentType, const BasicClassType* instantiatedFrom, SubstitutionsMap subs) { - // getObjectType should be used to construct object + // getRootClassType should be used to construct RootClass // everything else should have a parent type. CHPL_ASSERT(parentType != nullptr); return getBasicClassType(context, id, name, From 8791772ee6b56cc3509ebfd6971001397b817b33 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 4 Sep 2024 11:38:54 -0700 Subject: [PATCH 20/65] Set up ctFromSubs for _domain Signed-off-by: Anna Rift --- frontend/lib/resolution/InitResolver.cpp | 34 ++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index a95db6ea8b7a..832cd420be1b 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -313,6 +313,33 @@ static const Type* ctFromSubs(Context* context, auto manager = AnyOwnedType::get(context); auto dec = ClassTypeDecorator(ClassTypeDecorator::BORROWED_NONNIL); ret = ClassType::get(context, basic, manager, dec); + } else if (auto dt = receiverType->toDomainType()) { + // Extract domain information from _instance substitution + // TODO: also support associative domains here; currently assumes rectangular + QualifiedType rank; + QualifiedType idxType; + QualifiedType stridable; + + CHPL_ASSERT(subs.size() == 1); + if (auto instance = subs.begin()->second.type()) { + auto instanceCt = instance->toClassType(); + CHPL_ASSERT(instanceCt); + auto instanceBct = instanceCt->basicClassType(); + CHPL_ASSERT(instanceBct); + + // Get BaseRectangularDom parent subs for rectangular domain info + auto baseRect = instanceBct->parentClassType(); + CHPL_ASSERT(baseRect->name() == "BaseRectangularDom"); + + auto innerSubs = baseRect->sortedSubstitutions(); + CHPL_ASSERT(innerSubs.size() == 3); + + rank = innerSubs[0].second; + idxType = innerSubs[1].second; + stridable = innerSubs[2].second; + } + + ret = DomainType::getRectangularType(context, rank, idxType, stridable); } else { CHPL_ASSERT(false && "Not handled!"); } @@ -400,9 +427,12 @@ const Type* InitResolver::computeReceiverTypeConsideringState(void) { QualifiedType::Kind InitResolver::determineReceiverIntent(void) { if (initialRecvType_->isClassType()) { return QualifiedType::CONST_IN; - } else { - CHPL_ASSERT(initialRecvType_->isRecordType()); + } else if (initialRecvType_->isRecordType() || + initialRecvType_->isDomainType()) { return QualifiedType::REF; + } else { + CHPL_ASSERT(false && "Not handled"); + return QualifiedType::UNKNOWN; } } From 118ce04afee1aba78a5ead806e5cecce90ff1fee Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Wed, 4 Sep 2024 12:43:07 -0700 Subject: [PATCH 21/65] Set INIT_RECEIVER kind for generated _domain.init call Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index eead8cc70e41..f570a744da52 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2357,7 +2357,7 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { std::vector actuals; // Set up receiver auto receiverType = - QualifiedType(QualifiedType::VAR, rCalledExp.type().type()); + QualifiedType(QualifiedType::INIT_RECEIVER, rCalledExp.type().type()); auto receiverArg = CallInfoActual(receiverType, USTR("this")); actuals.push_back(std::move(receiverArg)); // Set up distribution arg From 8b1c6f103b2de2c1f037b42ff3d0c8047093c33e Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 9 Sep 2024 13:12:35 -0700 Subject: [PATCH 22/65] Include _instance in DomainType subsittutions to fix init issue Signed-off-by: Anna Rift --- .../chpl/framework/all-global-strings.h | 1 + frontend/include/chpl/types/DomainType.h | 1 + frontend/lib/resolution/InitResolver.cpp | 39 ++++++++++--------- frontend/lib/resolution/prims.cpp | 1 + frontend/lib/types/DomainType.cpp | 26 +++++++++++-- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/frontend/include/chpl/framework/all-global-strings.h b/frontend/include/chpl/framework/all-global-strings.h index 58da82ea563a..2fe83685cf2b 100644 --- a/frontend/include/chpl/framework/all-global-strings.h +++ b/frontend/include/chpl/framework/all-global-strings.h @@ -66,6 +66,7 @@ X(index , "index") X(init , "init") X(initequals , "init=") X(int_ , "int") +X(instance_ , "_instance") X(isCoercible , "isCoercible") X(leader , "leader") X(locale , "locale") diff --git a/frontend/include/chpl/types/DomainType.h b/frontend/include/chpl/types/DomainType.h index f821977bd543..707a357ab5ab 100644 --- a/frontend/include/chpl/types/DomainType.h +++ b/frontend/include/chpl/types/DomainType.h @@ -91,6 +91,7 @@ class DomainType final : public CompositeType { /** Return a rectangular domain type */ static const DomainType* getRectangularType(Context* context, + const QualifiedType& instance, const QualifiedType& rank, const QualifiedType& idxType, const QualifiedType& stridable); diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index 832cd420be1b..d104edab3548 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -321,25 +321,28 @@ static const Type* ctFromSubs(Context* context, QualifiedType stridable; CHPL_ASSERT(subs.size() == 1); - if (auto instance = subs.begin()->second.type()) { - auto instanceCt = instance->toClassType(); - CHPL_ASSERT(instanceCt); - auto instanceBct = instanceCt->basicClassType(); - CHPL_ASSERT(instanceBct); - - // Get BaseRectangularDom parent subs for rectangular domain info - auto baseRect = instanceBct->parentClassType(); - CHPL_ASSERT(baseRect->name() == "BaseRectangularDom"); - - auto innerSubs = baseRect->sortedSubstitutions(); - CHPL_ASSERT(innerSubs.size() == 3); - - rank = innerSubs[0].second; - idxType = innerSubs[1].second; - stridable = innerSubs[2].second; - } + auto instanceQt = subs.begin()->second; + auto instance = subs.begin()->second.type(); + CHPL_ASSERT(instance); + + auto instanceCt = instance->toClassType(); + CHPL_ASSERT(instanceCt); + auto instanceBct = instanceCt->basicClassType(); + CHPL_ASSERT(instanceBct); + + // Get BaseRectangularDom parent subs for rectangular domain info + auto baseRect = instanceBct->parentClassType(); + CHPL_ASSERT(baseRect->name() == "BaseRectangularDom"); + + auto innerSubs = baseRect->sortedSubstitutions(); + CHPL_ASSERT(innerSubs.size() == 3); + + rank = innerSubs[0].second; + idxType = innerSubs[1].second; + stridable = innerSubs[2].second; - ret = DomainType::getRectangularType(context, rank, idxType, stridable); + ret = DomainType::getRectangularType(context, instanceQt, rank, idxType, + stridable); } else { CHPL_ASSERT(false && "Not handled!"); } diff --git a/frontend/lib/resolution/prims.cpp b/frontend/lib/resolution/prims.cpp index 72b59f5df1a6..56b9b81df526 100644 --- a/frontend/lib/resolution/prims.cpp +++ b/frontend/lib/resolution/prims.cpp @@ -286,6 +286,7 @@ static QualifiedType primCallResolves(ResolutionContext* rc, static QualifiedType computeDomainType(Context* context, const CallInfo& ci) { if (ci.numActuals() == 3) { auto type = DomainType::getRectangularType(context, + QualifiedType(), ci.actual(0).type(), ci.actual(1).type(), ci.actual(2).type()); diff --git a/frontend/lib/types/DomainType.cpp b/frontend/lib/types/DomainType.cpp index ff689c58a21a..e4a5d2d2dc7e 100644 --- a/frontend/lib/types/DomainType.cpp +++ b/frontend/lib/types/DomainType.cpp @@ -79,18 +79,38 @@ DomainType::getGenericDomainType(Context* context) { const DomainType* DomainType::getRectangularType(Context* context, + const QualifiedType& instance, const QualifiedType& rank, const QualifiedType& idxType, const QualifiedType& stridable) { + auto genericDomain = getGenericDomainType(context); + SubstitutionsMap subs; subs.emplace(ID(UniqueString(), 0, 0), rank); subs.emplace(ID(UniqueString(), 1, 0), idxType); subs.emplace(ID(UniqueString(), 2, 0), stridable); + + // Add substitution for _instance field + auto& rf = fieldsForTypeDecl(context, genericDomain, + resolution::DefaultsPolicy::IGNORE_DEFAULTS, + /* syntaxOnly */ true); + ID instanceFieldId; + for (int i = 0; i < rf.numFields(); i++) { + if (rf.fieldName(i) == USTR("_instance")) { + instanceFieldId = rf.fieldDeclId(i); + break; + } + } + if (instanceFieldId.isEmpty()) { + CHPL_ASSERT(isMissingBundledRecordType(context, genericDomain->id())); + instanceFieldId = ID(USTR("_instance"), 0, 0); + } + subs.emplace(instanceFieldId, instance); + auto name = UniqueString::get(context, "_domain"); auto id = getDomainID(context); - auto instantiatedFrom = getGenericDomainType(context); - return getDomainType(context, id, name, instantiatedFrom, subs, - DomainType::Kind::Rectangular).get(); + return getDomainType(context, id, name, /* instantiatedFrom*/ genericDomain, + subs, DomainType::Kind::Rectangular).get(); } const DomainType* From d87d10ffd71aed28f24b56a1b91dbbe1510ed295 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 9 Sep 2024 14:01:58 -0700 Subject: [PATCH 23/65] Fix resolving domain type expressions via resolved init receiver Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index f570a744da52..376edee8862f 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2380,9 +2380,18 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); auto result = resolveGeneratedCall(context, call, ci, inScopes); + // TODO: appropriate AssociatedAction? handleResolvedCall(r, call, ci, result); - // Use the init call type as a TYPE value - r.setType(QualifiedType(QualifiedType::TYPE, r.type().type())); + + // Use the init call's receiver type as the resulting TYPE + const Type* receiverTy; + if (auto initMsc = result.mostSpecific().only()) { + receiverTy = initMsc.fn()->formalType(0).type(); + assert(receiverTy); + } else { + receiverTy = ErroneousType::get(context); + } + r.setType(QualifiedType(QualifiedType::TYPE, receiverTy)); // return result; // }); From d5c55e4a82ded452c8a1152b0ddc069603329f1c Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 9 Sep 2024 14:11:10 -0700 Subject: [PATCH 24/65] Restore use of runAndTrackErrors Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 85 ++++++++++++++-------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 376edee8862f..a6adea47f18d 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2351,53 +2351,50 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { } else { // Get type by resolving the type of corresponding '_domain' init call // TODO: prohibit associative domain with idxType 'domain' - // TODO: put runAndTrackErrors back after resolving perf issues with it - // auto runResult = context->runAndTrackErrors([&](Context* ctx) { - const AstNode* questionArg = nullptr; - std::vector actuals; - // Set up receiver - auto receiverType = - QualifiedType(QualifiedType::INIT_RECEIVER, rCalledExp.type().type()); - auto receiverArg = CallInfoActual(receiverType, USTR("this")); - actuals.push_back(std::move(receiverArg)); - // Set up distribution arg - auto defaultDistArg = CallInfoActual( - DomainType::getDefaultDistType(context), UniqueString()); - actuals.push_back(std::move(defaultDistArg)); - // Remaining given args from domain() call as written - prepareCallInfoActuals(call, actuals, questionArg); - CHPL_ASSERT(!questionArg); - - auto ci = - CallInfo(USTR("init"), - /* calledType */ receiverType, - /* isMethodCall */ true, - /* hasQuestionArg */ false, - /* isParenless */ false, - std::move(actuals)); - - auto scope = scopeStack.back(); - auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); - auto result = resolveGeneratedCall(context, call, ci, inScopes); + const AstNode* questionArg = nullptr; + std::vector actuals; + // Set up receiver + auto receiverType = + QualifiedType(QualifiedType::INIT_RECEIVER, rCalledExp.type().type()); + auto receiverArg = CallInfoActual(receiverType, USTR("this")); + actuals.push_back(std::move(receiverArg)); + // Set up distribution arg + auto defaultDistArg = CallInfoActual( + DomainType::getDefaultDistType(context), UniqueString()); + actuals.push_back(std::move(defaultDistArg)); + // Remaining given args from domain() call as written + prepareCallInfoActuals(call, actuals, questionArg); + CHPL_ASSERT(!questionArg); + + auto ci = + CallInfo(USTR("init"), + /* calledType */ receiverType, + /* isMethodCall */ true, + /* hasQuestionArg */ false, + /* isParenless */ false, + std::move(actuals)); + auto scope = scopeStack.back(); + auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); + auto runResult = context->runAndTrackErrors([&](Context* ctx) { + auto res = resolveGeneratedCall(context, call, ci, inScopes); // TODO: appropriate AssociatedAction? - handleResolvedCall(r, call, ci, result); - - // Use the init call's receiver type as the resulting TYPE - const Type* receiverTy; - if (auto initMsc = result.mostSpecific().only()) { - receiverTy = initMsc.fn()->formalType(0).type(); - assert(receiverTy); - } else { - receiverTy = ErroneousType::get(context); - } - r.setType(QualifiedType(QualifiedType::TYPE, receiverTy)); - // return result; - // }); + handleResolvedCall(r, call, ci, res); + return res; + }); - // if (!runResult.ranWithoutErrors()) { - // CHPL_REPORT(context, InvalidDomainCall, fnCall); - // } + // Use the init call's receiver type as the resulting TYPE + const Type* receiverTy; + if (runResult.ranWithoutErrors()) { + auto initMsc = runResult.result().mostSpecific().only(); + CHPL_ASSERT(initMsc); + receiverTy = initMsc.fn()->formalType(0).type(); + assert(receiverTy); + } else { + receiverTy = ErroneousType::get(context); + CHPL_REPORT(context, InvalidDomainCall, fnCall); + } + r.setType(QualifiedType(QualifiedType::TYPE, receiverTy)); } return true; } From ac32f9ad4268ddfd244ad1558199fb7f63dfea9a Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 9 Sep 2024 14:22:37 -0700 Subject: [PATCH 25/65] Get basic testing with standard domain module Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 391 ++++++++++++----------- 1 file changed, 198 insertions(+), 193 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 2299b2f07f6f..2d459e5d25f7 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -18,7 +18,6 @@ */ #include "test-resolution.h" -#include "test-minimal-modules.h" #include "chpl/parsing/parsing-queries.h" #include "chpl/resolution/resolution-queries.h" @@ -41,11 +40,14 @@ static void testRectangular(std::string domainType, int rank, std::string idxType, bool stridable) { - Context ctx; + Context::Configuration config; + config.chplHome = getenv("CHPL_HOME"); + Context ctx(config); Context* context = &ctx; + setupModuleSearchPaths(context, false, false, {}, {}); ErrorGuard guard(context); - std::string program = DomainModule + + std::string program = R"""( module M { use ChapelDomain; @@ -55,30 +57,30 @@ module M { type ig = )""" + idxType + R"""(; type fullIndex = if rg == 1 then ig else rg*ig; - param r = d.rank; - type i = d.idxType; - param s = d.stridable; - param rk = d.isRectangular(); - param ak = d.isAssociative(); + // param r = d.rank; + // type i = d.idxType; + // param s = d.stridable; + // param rk = d.isRectangular(); + // param ak = d.isAssociative(); - var p = d.pid(); + // var p = d.pid(); - for loopI in d { - var z = loopI; - } + // for loopI in d { + // var z = loopI; + // } - proc generic(arg: domain) { - type GT = arg.type; - return 42; - } + // proc generic(arg: domain) { + // type GT = arg.type; + // return 42; + // } - proc concrete(arg: )""" + domainType + R"""() { - type CT = arg.type; - return 42; - } + // proc concrete(arg: )""" + domainType + R"""() { + // type CT = arg.type; + // return 42; + // } - var g_ret = generic(d); - var c_ret = concrete(d); + // var g_ret = generic(d); + // var c_ret = concrete(d); } )"""; @@ -86,231 +88,231 @@ module M { setFileText(context, path, std::move(program)); const ModuleVec& vec = parseToplevel(context, path); - const Module* m = vec[1]; + const Module* m = vec[0]; const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); QualifiedType dType = findVarType(m, rr, "d"); assert(dType.type()->isDomainType()); - QualifiedType fullIndexType = findVarType(m, rr, "fullIndex"); + // QualifiedType fullIndexType = findVarType(m, rr, "fullIndex"); - assert(findVarType(m, rr, "r").param()->toIntParam()->value() == rank); + // assert(findVarType(m, rr, "r").param()->toIntParam()->value() == rank); - assert(findVarType(m, rr, "ig") == findVarType(m, rr, "i")); + // assert(findVarType(m, rr, "ig") == findVarType(m, rr, "i")); - assert(findVarType(m, rr, "s").param()->toBoolParam()->value() == stridable); + // assert(findVarType(m, rr, "s").param()->toBoolParam()->value() == stridable); - assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == true); + // assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == true); - assert(findVarType(m, rr, "ak").param()->toBoolParam()->value() == false); + // assert(findVarType(m, rr, "ak").param()->toBoolParam()->value() == false); - assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); + // assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); - assert(findVarType(m, rr, "z").type() == fullIndexType.type()); + // assert(findVarType(m, rr, "z").type() == fullIndexType.type()); - { - const Variable* g_ret = findOnlyNamed(m, "g_ret")->toVariable(); - auto res = rr.byAst(g_ret); - assert(res.type().type()->isIntType()); + // { + // const Variable* g_ret = findOnlyNamed(m, "g_ret")->toVariable(); + // auto res = rr.byAst(g_ret); + // assert(res.type().type()->isIntType()); - auto call = resolveOnlyCandidate(context, rr.byAst(g_ret->initExpression())); - // Generic function, should have been instantiated - assert(call->signature()->instantiatedFrom() != nullptr); + // auto call = resolveOnlyCandidate(context, rr.byAst(g_ret->initExpression())); + // // Generic function, should have been instantiated + // assert(call->signature()->instantiatedFrom() != nullptr); - const Variable* GT = findOnlyNamed(m, "GT")->toVariable(); - assert(call->byAst(GT).type().type() == dType.type()); - } + // const Variable* GT = findOnlyNamed(m, "GT")->toVariable(); + // assert(call->byAst(GT).type().type() == dType.type()); + // } - { - const Variable* c_ret = findOnlyNamed(m, "c_ret")->toVariable(); - auto res = rr.byAst(c_ret); - assert(res.type().type()->isIntType()); + // { + // const Variable* c_ret = findOnlyNamed(m, "c_ret")->toVariable(); + // auto res = rr.byAst(c_ret); + // assert(res.type().type()->isIntType()); - auto call = resolveOnlyCandidate(context, rr.byAst(c_ret->initExpression())); - // Concrete function, should not be instantiated - assert(call->signature()->instantiatedFrom() == nullptr); + // auto call = resolveOnlyCandidate(context, rr.byAst(c_ret->initExpression())); + // // Concrete function, should not be instantiated + // assert(call->signature()->instantiatedFrom() == nullptr); - const Variable* CT = findOnlyNamed(m, "CT")->toVariable(); - assert(call->byAst(CT).type().type() == dType.type()); - } + // const Variable* CT = findOnlyNamed(m, "CT")->toVariable(); + // assert(call->byAst(CT).type().type() == dType.type()); + // } assert(guard.errors().size() == 0); printf("Success: %s\n", domainType.c_str()); } -static void testAssociative(std::string domainType, - std::string idxType, - bool parSafe) { - Context ctx; - Context* context = &ctx; - ErrorGuard guard(context); - - std::string program = DomainModule + -R"""( -module M { - use ChapelDomain; +// static void testAssociative(std::string domainType, +// std::string idxType, +// bool parSafe) { +// Context ctx; +// Context* context = &ctx; +// ErrorGuard guard(context); + +// std::string program = DomainModule + +// R"""( +// module M { +// use ChapelDomain; - var d : )""" + domainType + R"""(; - type ig = )""" + idxType + R"""(; +// var d : )""" + domainType + R"""(; +// type ig = )""" + idxType + R"""(; - type i = d.idxType; - param s = d.parSafe; - param rk = d.isRectangular(); - param ak = d.isAssociative(); +// type i = d.idxType; +// param s = d.parSafe; +// param rk = d.isRectangular(); +// param ak = d.isAssociative(); - var p = d.pid(); +// var p = d.pid(); - for loopI in d { - var z = loopI; - } +// for loopI in d { +// var z = loopI; +// } - proc generic(arg: domain) { - type GT = arg.type; - return 42; - } +// proc generic(arg: domain) { +// type GT = arg.type; +// return 42; +// } - proc concrete(arg: )""" + domainType + R"""() { - type CT = arg.type; - return 42; - } +// proc concrete(arg: )""" + domainType + R"""() { +// type CT = arg.type; +// return 42; +// } - var g_ret = generic(d); - var c_ret = concrete(d); -} -)"""; - // TODO: generic checks +// var g_ret = generic(d); +// var c_ret = concrete(d); +// } +// )"""; +// // TODO: generic checks - auto path = UniqueString::get(context, "input.chpl"); - setFileText(context, path, std::move(program)); +// auto path = UniqueString::get(context, "input.chpl"); +// setFileText(context, path, std::move(program)); - const ModuleVec& vec = parseToplevel(context, path); - const Module* m = vec[1]; +// const ModuleVec& vec = parseToplevel(context, path); +// const Module* m = vec[1]; - const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); +// const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); - QualifiedType dType = findVarType(m, rr, "d"); - assert(dType.type()->isDomainType()); +// QualifiedType dType = findVarType(m, rr, "d"); +// assert(dType.type()->isDomainType()); - auto fullIndexType = findVarType(m, rr, "i"); - assert(findVarType(m, rr, "ig") == fullIndexType); +// auto fullIndexType = findVarType(m, rr, "i"); +// assert(findVarType(m, rr, "ig") == fullIndexType); - assert(findVarType(m, rr, "s").param()->toBoolParam()->value() == parSafe); +// assert(findVarType(m, rr, "s").param()->toBoolParam()->value() == parSafe); - assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == false); +// assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == false); - assert(findVarType(m, rr, "ak").param()->toBoolParam()->value() == true); +// assert(findVarType(m, rr, "ak").param()->toBoolParam()->value() == true); - assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); +// assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); - assert(findVarType(m, rr, "z").type() == fullIndexType.type()); +// assert(findVarType(m, rr, "z").type() == fullIndexType.type()); - { - const Variable* g_ret = findOnlyNamed(m, "g_ret")->toVariable(); - auto res = rr.byAst(g_ret); - assert(res.type().type()->isIntType()); +// { +// const Variable* g_ret = findOnlyNamed(m, "g_ret")->toVariable(); +// auto res = rr.byAst(g_ret); +// assert(res.type().type()->isIntType()); - auto call = resolveOnlyCandidate(context, rr.byAst(g_ret->initExpression())); - // Generic function, should have been instantiated - assert(call->signature()->instantiatedFrom() != nullptr); +// auto call = resolveOnlyCandidate(context, rr.byAst(g_ret->initExpression())); +// // Generic function, should have been instantiated +// assert(call->signature()->instantiatedFrom() != nullptr); - const Variable* GT = findOnlyNamed(m, "GT")->toVariable(); - assert(call->byAst(GT).type().type() == dType.type()); - } +// const Variable* GT = findOnlyNamed(m, "GT")->toVariable(); +// assert(call->byAst(GT).type().type() == dType.type()); +// } - { - const Variable* c_ret = findOnlyNamed(m, "c_ret")->toVariable(); - auto res = rr.byAst(c_ret); - assert(res.type().type()->isIntType()); +// { +// const Variable* c_ret = findOnlyNamed(m, "c_ret")->toVariable(); +// auto res = rr.byAst(c_ret); +// assert(res.type().type()->isIntType()); - auto call = resolveOnlyCandidate(context, rr.byAst(c_ret->initExpression())); - // Concrete function, should not be instantiated - assert(call->signature()->instantiatedFrom() == nullptr); +// auto call = resolveOnlyCandidate(context, rr.byAst(c_ret->initExpression())); +// // Concrete function, should not be instantiated +// assert(call->signature()->instantiatedFrom() == nullptr); - const Variable* CT = findOnlyNamed(m, "CT")->toVariable(); - assert(call->byAst(CT).type().type() == dType.type()); - } +// const Variable* CT = findOnlyNamed(m, "CT")->toVariable(); +// assert(call->byAst(CT).type().type() == dType.type()); +// } - assert(guard.errors().size() == 0); +// assert(guard.errors().size() == 0); - printf("Success: %s\n", domainType.c_str()); -} +// printf("Success: %s\n", domainType.c_str()); +// } -static void testBadPass(std::string argType, std::string actualType) { - // Ensure that we can't, e.g., pass a domain(1) to a domain(2) - Context ctx; - Context* context = &ctx; - ErrorGuard guard(context); +// static void testBadPass(std::string argType, std::string actualType) { +// // Ensure that we can't, e.g., pass a domain(1) to a domain(2) +// Context ctx; +// Context* context = &ctx; +// ErrorGuard guard(context); - std::string program = DomainModule + -R"""( -module M { - use ChapelDomain; +// std::string program = DomainModule + +// R"""( +// module M { +// use ChapelDomain; - proc foo(arg: )""" + argType + R"""() { - return 42; - } +// proc foo(arg: )""" + argType + R"""() { +// return 42; +// } - var d : )""" + actualType + R"""(; - var c_ret = foo(d); -} -)"""; - // TODO: generic checks +// var d : )""" + actualType + R"""(; +// var c_ret = foo(d); +// } +// )"""; +// // TODO: generic checks - auto path = UniqueString::get(context, "input.chpl"); - setFileText(context, path, std::move(program)); +// auto path = UniqueString::get(context, "input.chpl"); +// setFileText(context, path, std::move(program)); - const ModuleVec& vec = parseToplevel(context, path); - const Module* m = vec[1]; +// const ModuleVec& vec = parseToplevel(context, path); +// const Module* m = vec[1]; - const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); +// const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); - auto c_ret = findOnlyNamed(m, "c_ret")->toVariable(); - assert(rr.byAst(c_ret).type().isErroneousType()); - assert(guard.errors().size() == 1); - auto& e = guard.errors()[0]; - assert(e->type() == chpl::NoMatchingCandidates); +// auto c_ret = findOnlyNamed(m, "c_ret")->toVariable(); +// assert(rr.byAst(c_ret).type().isErroneousType()); +// assert(guard.errors().size() == 1); +// auto& e = guard.errors()[0]; +// assert(e->type() == chpl::NoMatchingCandidates); - printf("Success: cannot pass %s to %s\n", actualType.c_str(), argType.c_str()); +// printf("Success: cannot pass %s to %s\n", actualType.c_str(), argType.c_str()); - // 'clear' rather than 'realize' to simplify test output - guard.clearErrors(); -} +// // 'clear' rather than 'realize' to simplify test output +// guard.clearErrors(); +// } -static void testIndex(std::string domainType, - std::string expectedType) { - Context ctx; - Context* context = &ctx; - ErrorGuard guard(context); +// static void testIndex(std::string domainType, +// std::string expectedType) { +// Context ctx; +// Context* context = &ctx; +// ErrorGuard guard(context); - std::string program = DomainModule + ArrayModule + -R"""( -module M { - use ChapelDomain; - use ChapelArray; +// std::string program = DomainModule + ArrayModule + +// R"""( +// module M { +// use ChapelDomain; +// use ChapelArray; - var d : )""" + domainType + R"""(; - type t = )""" + expectedType + R"""(; - type i = index(d); +// var d : )""" + domainType + R"""(; +// type t = )""" + expectedType + R"""(; +// type i = index(d); - param equal = i == t; -} -)"""; +// param equal = i == t; +// } +// )"""; - auto path = UniqueString::get(context, "input.chpl"); - setFileText(context, path, std::move(program)); +// auto path = UniqueString::get(context, "input.chpl"); +// setFileText(context, path, std::move(program)); - const ModuleVec& vec = parseToplevel(context, path); - const Module* m = vec[2]; +// const ModuleVec& vec = parseToplevel(context, path); +// const Module* m = vec[2]; - const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); - findVarType(m, rr, "d").dump(); - findVarType(m, rr, "t").dump(); - findVarType(m, rr, "i").dump(); +// const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); +// findVarType(m, rr, "d").dump(); +// findVarType(m, rr, "t").dump(); +// findVarType(m, rr, "i").dump(); - assert(findVarType(m, rr, "equal").isParamTrue()); -} +// assert(findVarType(m, rr, "equal").isParamTrue()); +// } int main() { testRectangular("domain(1)", 1, "int", false); @@ -320,20 +322,23 @@ int main() { testRectangular("domain(3, int(16), true)", 3, "int(16)", true); testRectangular("domain(stridable=false, idxType=int, rank=1)", 1, "int", false); - testAssociative("domain(int)", "int", true); - testAssociative("domain(int, false)", "int", false); - testAssociative("domain(string)", "string", true); - - testBadPass("domain(1)", "domain(2)"); - testBadPass("domain(int)", "domain(string)"); - testBadPass("domain(1)", "domain(int)"); - - testIndex("domain(1)", "int"); - testIndex("domain(2)", "2*int"); - testIndex("domain(1, bool)", "bool"); - testIndex("domain(2, bool)", "2*bool"); - testIndex("domain(int)", "int"); - testIndex("domain(string)", "string"); + // TODO: re-enable associative + // testAssociative("domain(int)", "int", true); + // testAssociative("domain(int, false)", "int", false); + // testAssociative("domain(string)", "string", true); + + // TODO: re-enable + // testBadPass("domain(1)", "domain(2)"); + // testBadPass("domain(int)", "domain(string)"); + // testBadPass("domain(1)", "domain(int)"); + + // TODO: re-enable indexes + // testIndex("domain(1)", "int"); + // testIndex("domain(2)", "2*int"); + // testIndex("domain(1, bool)", "bool"); + // testIndex("domain(2, bool)", "2*bool"); + // testIndex("domain(int)", "int"); + // testIndex("domain(string)", "string"); return 0; } From 95750d7665d7a2ba2daa81ea38006ed2be4993fb Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 9 Sep 2024 14:39:56 -0700 Subject: [PATCH 26/65] Update testing from stridable -> strides Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 2d459e5d25f7..565388521747 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -39,7 +39,7 @@ static QualifiedType findVarType(const Module* m, static void testRectangular(std::string domainType, int rank, std::string idxType, - bool stridable) { + std::string strides) { Context::Configuration config; config.chplHome = getenv("CHPL_HOME"); Context ctx(config); @@ -59,7 +59,7 @@ module M { // param r = d.rank; // type i = d.idxType; - // param s = d.stridable; + // param s = d.strides; // param rk = d.isRectangular(); // param ak = d.isAssociative(); @@ -101,7 +101,7 @@ module M { // assert(findVarType(m, rr, "ig") == findVarType(m, rr, "i")); - // assert(findVarType(m, rr, "s").param()->toBoolParam()->value() == stridable); + // assert(findVarType(m, rr, "s").param()->toBoolParam()->value() == strides); // assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == true); @@ -315,12 +315,12 @@ module M { // } int main() { - testRectangular("domain(1)", 1, "int", false); - testRectangular("domain(2)", 2, "int", false); - testRectangular("domain(1, stridable=true)", 1, "int", true); - testRectangular("domain(2, int(8))", 2, "int(8)", false); - testRectangular("domain(3, int(16), true)", 3, "int(16)", true); - testRectangular("domain(stridable=false, idxType=int, rank=1)", 1, "int", false); + testRectangular("domain(1)", 1, "int", "strideKind.one"); + testRectangular("domain(2)", 2, "int", "strideKind.one"); + testRectangular("domain(1, strides=strideKind.one)", 1, "int", "strideKind.one"); + testRectangular("domain(2, int(8))", 2, "int(8)", "strideKind.one"); + testRectangular("domain(3, int(16), strideKind.negOne)", 3, "int(16)", "strideKind.negOne"); + testRectangular("domain(strides=strideKind.negative, idxType=int, rank=1)", 1, "int", "strideKind.negative"); // TODO: re-enable associative // testAssociative("domain(int)", "int", true); From 7b0b72cb9618548f2e21c3986ca61927dc9e6164 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 10 Sep 2024 10:26:27 -0700 Subject: [PATCH 27/65] Add and use RUNTIME_TYPE AssociatedAction for domain type expressions Signed-off-by: Anna Rift --- .../include/chpl/resolution/resolution-types.h | 1 + frontend/lib/resolution/Resolver.cpp | 12 +++++++----- frontend/lib/resolution/resolution-types.cpp | 2 ++ frontend/test/resolution/testDomains.cpp | 18 ++++++++++++++---- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/frontend/include/chpl/resolution/resolution-types.h b/frontend/include/chpl/resolution/resolution-types.h index 0a064d06f3c7..f535508db341 100644 --- a/frontend/include/chpl/resolution/resolution-types.h +++ b/frontend/include/chpl/resolution/resolution-types.h @@ -1960,6 +1960,7 @@ class AssociatedAction { REDUCE_SCAN, // resolution of "generate" for a reduce/scan operation. INFER_TYPE, COMPARE, // == , e.g., for select-statements + RUNTIME_TYPE, // create runtime type }; private: diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index a6adea47f18d..b022b5f4e3d3 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2377,17 +2377,19 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { auto scope = scopeStack.back(); auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); auto runResult = context->runAndTrackErrors([&](Context* ctx) { - auto res = resolveGeneratedCall(context, call, ci, inScopes); - // TODO: appropriate AssociatedAction? - handleResolvedCall(r, call, ci, res); - return res; + return resolveGeneratedCall(context, call, ci, inScopes); }); // Use the init call's receiver type as the resulting TYPE const Type* receiverTy; if (runResult.ranWithoutErrors()) { - auto initMsc = runResult.result().mostSpecific().only(); + auto result = runResult.result(); + auto initMsc = result.mostSpecific().only(); CHPL_ASSERT(initMsc); + + handleResolvedCall(r, call, ci, result, + {{AssociatedAction::RUNTIME_TYPE, fnCall->id()}}); + receiverTy = initMsc.fn()->formalType(0).type(); assert(receiverTy); } else { diff --git a/frontend/lib/resolution/resolution-types.cpp b/frontend/lib/resolution/resolution-types.cpp index 9cd0d7e1887b..6864cd020167 100644 --- a/frontend/lib/resolution/resolution-types.cpp +++ b/frontend/lib/resolution/resolution-types.cpp @@ -1156,6 +1156,8 @@ const char* AssociatedAction::kindToString(Action a) { return "infer-type"; case COMPARE: return "compare"; + case RUNTIME_TYPE: + return "runtime-type"; // no default to get a warning if new Actions are added } diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 565388521747..b49861229b9c 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -50,8 +50,6 @@ static void testRectangular(std::string domainType, std::string program = R"""( module M { - use ChapelDomain; - var d : )""" + domainType + R"""(; param rg = )""" + std::to_string(rank) + R"""(; type ig = )""" + idxType + R"""(; @@ -92,10 +90,22 @@ module M { const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); - QualifiedType dType = findVarType(m, rr, "d"); + const Variable* d = m->stmt(0)->toVariable(); + assert(d); + assert(d->name() == "d"); + + QualifiedType dType = rr.byAst(d).type(); assert(dType.type()->isDomainType()); - // QualifiedType fullIndexType = findVarType(m, rr, "fullIndex"); + auto dTypeExpr = d->typeExpression(); + assert(dTypeExpr); + auto typeRe = rr.byAst(dTypeExpr); + auto& aa = typeRe.associatedActions()[0]; + assert(!aa.id().isEmpty()); + assert(aa.action() == AssociatedAction::RUNTIME_TYPE); + + QualifiedType fullIndexType = findVarType(m, rr, "fullIndex"); + (void)fullIndexType; // assert(findVarType(m, rr, "r").param()->toIntParam()->value() == rank); From b65005d4df27ed685d8200de61ed3c4501ee064f Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 10 Sep 2024 13:06:40 -0700 Subject: [PATCH 28/65] Remove compiler-generated domain methods Signed-off-by: Anna Rift --- frontend/lib/resolution/default-functions.cpp | 63 +------------------ frontend/lib/types/CompositeType.cpp | 1 + 2 files changed, 2 insertions(+), 62 deletions(-) diff --git a/frontend/lib/resolution/default-functions.cpp b/frontend/lib/resolution/default-functions.cpp index 303419d36b68..7bab0ede4ebc 100644 --- a/frontend/lib/resolution/default-functions.cpp +++ b/frontend/lib/resolution/default-functions.cpp @@ -141,25 +141,7 @@ needCompilerGeneratedMethod(Context* context, const Type* type, } } - // Some basic getter methods for domain properties - // - // TODO: We can eventually replace these for calls on a domain *value* by - // looking at the property from the _instance implementation. But that won't - // work if we want to support these methods on a domain type-expression. - // - // TODO: calling these within a method doesn't work - if (type->isDomainType()) { - if (parenless) { - if (name == "idxType" || name == "rank" || name == "stridable" || - name == "parSafe") { - return true; - } - } else { - if (name == "isRectangular" || name == "isAssociative") { - return true; - } - } - } else if (type->isArrayType()) { + if (type->isArrayType()) { if (name == "domain" || name == "eltType") { return true; } @@ -489,47 +471,6 @@ generateDeSerialize(Context* context, const CompositeType* compType, return ret; } -static const TypedFnSignature* -generateDomainMethod(Context* context, - const DomainType* dt, - UniqueString name) { - // Build a basic function signature for methods querying some aspect of - // a domain's type. - // TODO: we should really have a way to just set the return type here - const TypedFnSignature* result = nullptr; - std::vector formals; - std::vector formalTypes; - - formals.push_back( - UntypedFnSignature::FormalDetail(USTR("this"), - UntypedFnSignature::DK_NO_DEFAULT, - nullptr)); - formalTypes.push_back(QualifiedType(QualifiedType::CONST_REF, dt)); - - auto ufs = UntypedFnSignature::get(context, - /*id*/ dt->id(), - /*name*/ name, - /*isMethod*/ true, - /*isTypeConstructor*/ false, - /*isCompilerGenerated*/ true, - /*throws*/ false, - /*idTag*/ parsing::idToTag(context, dt->id()), - /*kind*/ uast::Function::Kind::PROC, - /*formals*/ std::move(formals), - /*whereClause*/ nullptr); - - // now build the other pieces of the typed signature - result = TypedFnSignature::get(context, ufs, std::move(formalTypes), - TypedFnSignature::WHERE_NONE, - /* needsInstantiation */ false, - /* instantiatedFrom */ nullptr, - /* parentFn */ nullptr, - /* formalsInstantiated */ Bitmap(), - /* outerVariables */ {}); - - return result; -} - static const TypedFnSignature* generateArrayMethod(Context* context, const ArrayType* at, @@ -920,8 +861,6 @@ getCompilerGeneratedMethodQuery(Context* context, QualifiedType receiverType, result = generateDeSerialize(context, compType, name, "writer", "serializer"); } else if (name == USTR("deserialize")) { result = generateDeSerialize(context, compType, name, "reader", "deserializer"); - } else if (auto domainType = type->toDomainType()) { - result = generateDomainMethod(context, domainType, name); } else if (auto arrayType = type->toArrayType()) { result = generateArrayMethod(context, arrayType, name); } else if (auto tupleType = type->toTupleType()) { diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index 5b364a39fbe7..392fb54ccdb8 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -27,6 +27,7 @@ #include "chpl/types/ClassType.h" #include "chpl/types/ClassTypeDecorator.h" #include "chpl/types/CPtrType.h" +#include "chpl/types/DomainType.h" #include "chpl/types/RecordType.h" #include "chpl/types/TupleType.h" #include "chpl/uast/Decl.h" From 2a64008c94c5c1063aaa4ab6561e98034e4cda52 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 10 Sep 2024 13:10:01 -0700 Subject: [PATCH 29/65] Re-enable testing for some basic domain methods Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 34 +++++++++++++----------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index b49861229b9c..f0ab00aaca5a 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -55,11 +55,11 @@ module M { type ig = )""" + idxType + R"""(; type fullIndex = if rg == 1 then ig else rg*ig; - // param r = d.rank; - // type i = d.idxType; - // param s = d.strides; - // param rk = d.isRectangular(); - // param ak = d.isAssociative(); + param r = d.rank; + type i = d.idxType; + param s = d.strides; + param rk = d.isRectangular(); + param ak = d.isAssociative(); // var p = d.pid(); @@ -107,15 +107,17 @@ module M { QualifiedType fullIndexType = findVarType(m, rr, "fullIndex"); (void)fullIndexType; - // assert(findVarType(m, rr, "r").param()->toIntParam()->value() == rank); + assert(findVarType(m, rr, "r").param()->toIntParam()->value() == rank); - // assert(findVarType(m, rr, "ig") == findVarType(m, rr, "i")); + assert(findVarType(m, rr, "ig") == findVarType(m, rr, "i")); - // assert(findVarType(m, rr, "s").param()->toBoolParam()->value() == strides); + assert(findVarType(m, rr, "s").param()->toEnumParam()->value().str == strides); - // assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == true); + assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == true); - // assert(findVarType(m, rr, "ak").param()->toBoolParam()->value() == false); + assert(findVarType(m, rr, "ak").param()->toBoolParam()->value() == false); + + // TODO: uncommented and fix remaining testing // assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); @@ -325,12 +327,12 @@ module M { // } int main() { - testRectangular("domain(1)", 1, "int", "strideKind.one"); - testRectangular("domain(2)", 2, "int", "strideKind.one"); - testRectangular("domain(1, strides=strideKind.one)", 1, "int", "strideKind.one"); - testRectangular("domain(2, int(8))", 2, "int(8)", "strideKind.one"); - testRectangular("domain(3, int(16), strideKind.negOne)", 3, "int(16)", "strideKind.negOne"); - testRectangular("domain(strides=strideKind.negative, idxType=int, rank=1)", 1, "int", "strideKind.negative"); + testRectangular("domain(1)", 1, "int", "one"); + testRectangular("domain(2)", 2, "int", "one"); + testRectangular("domain(1, strides=strideKind.one)", 1, "int", "one"); + testRectangular("domain(2, int(8))", 2, "int(8)", "one"); + testRectangular("domain(3, int(16), strideKind.negOne)", 3, "int(16)", "negOne"); + testRectangular("domain(strides=strideKind.negative, idxType=int, rank=1)", 1, "int", "negative"); // TODO: re-enable associative // testAssociative("domain(int)", "int", true); From 58a7cbb68d4aa87a7e0beedd8378542b06ac1564 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 10 Sep 2024 16:23:20 -0700 Subject: [PATCH 30/65] Re-enable testDomains .type testing Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 68 ++++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index f0ab00aaca5a..d69902845f8a 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -67,18 +67,18 @@ module M { // var z = loopI; // } - // proc generic(arg: domain) { - // type GT = arg.type; - // return 42; - // } - - // proc concrete(arg: )""" + domainType + R"""() { - // type CT = arg.type; - // return 42; - // } - - // var g_ret = generic(d); - // var c_ret = concrete(d); + proc generic(arg: domain) { + type GT = arg.type; + return 42; + } + + proc concrete(arg: )""" + domainType + R"""() { + type CT = arg.type; + return 42; + } + + var g_ret = generic(d); + var c_ret = concrete(d); } )"""; @@ -117,37 +117,37 @@ module M { assert(findVarType(m, rr, "ak").param()->toBoolParam()->value() == false); - // TODO: uncommented and fix remaining testing - + // TODO: fix and test .pid // assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); + // TODO: fix and test iteration // assert(findVarType(m, rr, "z").type() == fullIndexType.type()); - // { - // const Variable* g_ret = findOnlyNamed(m, "g_ret")->toVariable(); - // auto res = rr.byAst(g_ret); - // assert(res.type().type()->isIntType()); + { + const Variable* g_ret = findOnlyNamed(m, "g_ret")->toVariable(); + auto res = rr.byAst(g_ret); + assert(res.type().type()->isIntType()); - // auto call = resolveOnlyCandidate(context, rr.byAst(g_ret->initExpression())); - // // Generic function, should have been instantiated - // assert(call->signature()->instantiatedFrom() != nullptr); + auto call = resolveOnlyCandidate(context, rr.byAst(g_ret->initExpression())); + // Generic function, should have been instantiated + assert(call->signature()->instantiatedFrom() != nullptr); - // const Variable* GT = findOnlyNamed(m, "GT")->toVariable(); - // assert(call->byAst(GT).type().type() == dType.type()); - // } + const Variable* GT = findOnlyNamed(m, "GT")->toVariable(); + assert(call->byAst(GT).type().type() == dType.type()); + } - // { - // const Variable* c_ret = findOnlyNamed(m, "c_ret")->toVariable(); - // auto res = rr.byAst(c_ret); - // assert(res.type().type()->isIntType()); + { + const Variable* c_ret = findOnlyNamed(m, "c_ret")->toVariable(); + auto res = rr.byAst(c_ret); + assert(res.type().type()->isIntType()); - // auto call = resolveOnlyCandidate(context, rr.byAst(c_ret->initExpression())); - // // Concrete function, should not be instantiated - // assert(call->signature()->instantiatedFrom() == nullptr); + auto call = resolveOnlyCandidate(context, rr.byAst(c_ret->initExpression())); + // Concrete function, should not be instantiated + assert(call->signature()->instantiatedFrom() == nullptr); - // const Variable* CT = findOnlyNamed(m, "CT")->toVariable(); - // assert(call->byAst(CT).type().type() == dType.type()); - // } + const Variable* CT = findOnlyNamed(m, "CT")->toVariable(); + assert(call->byAst(CT).type().type() == dType.type()); + } assert(guard.errors().size() == 0); From c5c90a37f30a7baf96de51983c68ed4e16077c60 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 13 Sep 2024 14:16:56 -0700 Subject: [PATCH 31/65] Enable forwarding on DomainTypes Signed-off-by: Anna Rift --- frontend/lib/resolution/resolution-queries.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/lib/resolution/resolution-queries.cpp b/frontend/lib/resolution/resolution-queries.cpp index 8421bf106950..27fd7d34b3b9 100644 --- a/frontend/lib/resolution/resolution-queries.cpp +++ b/frontend/lib/resolution/resolution-queries.cpp @@ -1002,7 +1002,8 @@ const ResolvedFields& resolveForwardingExprs(Context* context, static bool typeUsesForwarding(Context* context, const Type* receiverType) { if (auto ct = receiverType->getCompositeType()) { - if (ct->isBasicClassType() || ct->isRecordType() || ct->isUnionType()) { + if (ct->isBasicClassType() || ct->isRecordType() || ct->isDomainType() || + ct->isUnionType()) { ID ctId = ct->id(); if (!ctId.isEmpty()) { return parsing::aggregateUsesForwarding(context, ctId); From 049bcbba589f85ba93201d813df8dd27465b2ebf Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 13 Sep 2024 14:18:01 -0700 Subject: [PATCH 32/65] Adjust and re-enable _domain.pid testing Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index d69902845f8a..9b0df98e83f7 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -61,7 +61,7 @@ module M { param rk = d.isRectangular(); param ak = d.isAssociative(); - // var p = d.pid(); + var p = d.pid; // for loopI in d { // var z = loopI; @@ -117,8 +117,7 @@ module M { assert(findVarType(m, rr, "ak").param()->toBoolParam()->value() == false); - // TODO: fix and test .pid - // assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); + assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); // TODO: fix and test iteration // assert(findVarType(m, rr, "z").type() == fullIndexType.type()); From 5ec7563956e41660cc58fbe6c8f69e9032399e9f Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 13 Sep 2024 15:31:48 -0700 Subject: [PATCH 33/65] Re-enable domain iteration testing Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 9b0df98e83f7..a71b9624120c 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -63,9 +63,9 @@ module M { var p = d.pid; - // for loopI in d { - // var z = loopI; - // } + for loopI in d { + var z = loopI; + } proc generic(arg: domain) { type GT = arg.type; @@ -119,8 +119,7 @@ module M { assert(findVarType(m, rr, "p").type() == IntType::get(context, 0)); - // TODO: fix and test iteration - // assert(findVarType(m, rr, "z").type() == fullIndexType.type()); + assert(findVarType(m, rr, "z").type() == fullIndexType.type()); { const Variable* g_ret = findOnlyNamed(m, "g_ret")->toVariable(); From 15e4ec3a3ba191d7c1135ef34aa0d8641a267922 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 16 Sep 2024 12:52:29 -0700 Subject: [PATCH 34/65] Remove unused variable Signed-off-by: Anna Rift --- frontend/lib/resolution/InitResolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index d104edab3548..45b6dba67080 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -313,7 +313,7 @@ static const Type* ctFromSubs(Context* context, auto manager = AnyOwnedType::get(context); auto dec = ClassTypeDecorator(ClassTypeDecorator::BORROWED_NONNIL); ret = ClassType::get(context, basic, manager, dec); - } else if (auto dt = receiverType->toDomainType()) { + } else if (receiverType->isDomainType()) { // Extract domain information from _instance substitution // TODO: also support associative domains here; currently assumes rectangular QualifiedType rank; From 2ec8b66d40adebc15e56c209f8d577e8df289e02 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 16 Sep 2024 10:45:53 -0700 Subject: [PATCH 35/65] Remove use of minimal ChapelArray in testArrays Also remove test-minimal-modules.h as now empty and unused Signed-off-by: Anna Rift --- frontend/test/resolution/testArrays.cpp | 12 +-- frontend/test/resolution/testCPtr.cpp | 1 - frontend/test/test-minimal-modules.h | 104 ------------------------ 3 files changed, 6 insertions(+), 111 deletions(-) delete mode 100644 frontend/test/test-minimal-modules.h diff --git a/frontend/test/resolution/testArrays.cpp b/frontend/test/resolution/testArrays.cpp index c1b81d02ceee..8bb5d9112927 100644 --- a/frontend/test/resolution/testArrays.cpp +++ b/frontend/test/resolution/testArrays.cpp @@ -18,7 +18,6 @@ */ #include "test-resolution.h" -#include "test-minimal-modules.h" #include "chpl/parsing/parsing-queries.h" #include "chpl/resolution/resolution-queries.h" @@ -43,8 +42,11 @@ static QualifiedType findVarType(const Module* m, static void testArray(std::string domainType, std::string eltType) { - Context ctx; + Context::Configuration config; + config.chplHome = getenv("CHPL_HOME"); + Context ctx(config); Context* context = &ctx; + setupModuleSearchPaths(context, false, false, {}, {}); ErrorGuard guard(context); // a different element type from the one we were given @@ -53,11 +55,9 @@ static void testArray(std::string domainType, altElt = "string"; } - std::string program = DomainModule + ArrayModule + + std::string program = R"""( module M { - use ChapelArray; - var d : )""" + domainType + R"""(; type eltType = )""" + eltType + R"""(; @@ -94,7 +94,7 @@ module M { setFileText(context, path, std::move(program)); const ModuleVec& vec = parseToplevel(context, path); - const Module* m = vec[2]; + const Module* m = vec[0]; const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); diff --git a/frontend/test/resolution/testCPtr.cpp b/frontend/test/resolution/testCPtr.cpp index 91392ffdc760..7c25e2c0165f 100644 --- a/frontend/test/resolution/testCPtr.cpp +++ b/frontend/test/resolution/testCPtr.cpp @@ -19,7 +19,6 @@ #include "test-resolution.h" -#include "test-minimal-modules.h" #include "chpl/parsing/parsing-queries.h" #include "chpl/resolution/resolution-queries.h" diff --git a/frontend/test/test-minimal-modules.h b/frontend/test/test-minimal-modules.h deleted file mode 100644 index 1518222c9ea5..000000000000 --- a/frontend/test/test-minimal-modules.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2021-2024 Hewlett Packard Enterprise Development LP - * Other additional copyright holders may be indicated within. - * - * The entirety of this work is licensed under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TEST_MINIMAL_MODULES_H -#define TEST_MINIMAL_MODULES_H - -#include - -static std::string DomainModule = -R"""( -module ChapelDomain { - record _domain { - var _pid: int; - var _instance; - var _unowned:bool; - } - - proc type _domain.static_type(param rank : int, type idxType=int, param stridable: bool = false) type { - return __primitive("static domain type", rank, idxType, stridable); - } - - proc type _domain.static_type(type idxType, param parSafe: bool = true) type { - return __primitive("static domain type", idxType, parSafe); - } - - proc computeIndexType(arg: domain) type { - if arg.isRectangular() { - if arg.rank == 1 then return arg.idxType; - else return arg.rank*arg.idxType; - } else { - return arg.idxType; - } - } - - iter _domain.these() { - var ret : computeIndexType(this); - yield ret; - } - - // Prove that fields and methods on '_domain' work - proc _domain.pid() { - return _pid; - } -} -)"""; - - -static std::string ArrayModule = -R"""( -module ChapelArray { - public use ChapelDomain; - - record _array { - var _pid:int; - var _instance; - var _unowned:bool; - } - - iter _array.these() : this.eltType { - var i : this.eltType; - yield i; - } - - proc _array.size : int { - var i : int; - return i; - } - - // TODO: 'this' accessor can't work because accessing 'this.domain' in the - // formal's type-expr is resolved as an ErroneousType - - proc chpl__buildIndexType(param rank: int, type idxType) type where rank == 1 { - return idxType; - } - - proc chpl__buildIndexType(param rank: int, type idxType) type where __primitive(">", rank, 1) { - return rank*idxType; - } - - proc chpl__buildIndexType(param rank: int) type do - return chpl__buildIndexType(rank, int); - - proc chpl__buildIndexType(d: domain) type do - return chpl__buildIndexType(d.rank, d.idxType); -} -)"""; - -#endif From ba91b1f4da09423d511907590883cd58981a8898 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 16 Sep 2024 10:47:34 -0700 Subject: [PATCH 36/65] Revert "Remove use of minimal ChapelArray in testArrays" This reverts commit a953fb39d32dd26fb817c7350f6b66290c260c6d. Signed-off-by: Anna Rift --- frontend/test/resolution/testArrays.cpp | 12 +-- frontend/test/resolution/testCPtr.cpp | 1 + frontend/test/test-minimal-modules.h | 104 ++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 frontend/test/test-minimal-modules.h diff --git a/frontend/test/resolution/testArrays.cpp b/frontend/test/resolution/testArrays.cpp index 8bb5d9112927..c1b81d02ceee 100644 --- a/frontend/test/resolution/testArrays.cpp +++ b/frontend/test/resolution/testArrays.cpp @@ -18,6 +18,7 @@ */ #include "test-resolution.h" +#include "test-minimal-modules.h" #include "chpl/parsing/parsing-queries.h" #include "chpl/resolution/resolution-queries.h" @@ -42,11 +43,8 @@ static QualifiedType findVarType(const Module* m, static void testArray(std::string domainType, std::string eltType) { - Context::Configuration config; - config.chplHome = getenv("CHPL_HOME"); - Context ctx(config); + Context ctx; Context* context = &ctx; - setupModuleSearchPaths(context, false, false, {}, {}); ErrorGuard guard(context); // a different element type from the one we were given @@ -55,9 +53,11 @@ static void testArray(std::string domainType, altElt = "string"; } - std::string program = + std::string program = DomainModule + ArrayModule + R"""( module M { + use ChapelArray; + var d : )""" + domainType + R"""(; type eltType = )""" + eltType + R"""(; @@ -94,7 +94,7 @@ module M { setFileText(context, path, std::move(program)); const ModuleVec& vec = parseToplevel(context, path); - const Module* m = vec[0]; + const Module* m = vec[2]; const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); diff --git a/frontend/test/resolution/testCPtr.cpp b/frontend/test/resolution/testCPtr.cpp index 7c25e2c0165f..91392ffdc760 100644 --- a/frontend/test/resolution/testCPtr.cpp +++ b/frontend/test/resolution/testCPtr.cpp @@ -19,6 +19,7 @@ #include "test-resolution.h" +#include "test-minimal-modules.h" #include "chpl/parsing/parsing-queries.h" #include "chpl/resolution/resolution-queries.h" diff --git a/frontend/test/test-minimal-modules.h b/frontend/test/test-minimal-modules.h new file mode 100644 index 000000000000..1518222c9ea5 --- /dev/null +++ b/frontend/test/test-minimal-modules.h @@ -0,0 +1,104 @@ +/* + * Copyright 2021-2024 Hewlett Packard Enterprise Development LP + * Other additional copyright holders may be indicated within. + * + * The entirety of this work is licensed under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_MINIMAL_MODULES_H +#define TEST_MINIMAL_MODULES_H + +#include + +static std::string DomainModule = +R"""( +module ChapelDomain { + record _domain { + var _pid: int; + var _instance; + var _unowned:bool; + } + + proc type _domain.static_type(param rank : int, type idxType=int, param stridable: bool = false) type { + return __primitive("static domain type", rank, idxType, stridable); + } + + proc type _domain.static_type(type idxType, param parSafe: bool = true) type { + return __primitive("static domain type", idxType, parSafe); + } + + proc computeIndexType(arg: domain) type { + if arg.isRectangular() { + if arg.rank == 1 then return arg.idxType; + else return arg.rank*arg.idxType; + } else { + return arg.idxType; + } + } + + iter _domain.these() { + var ret : computeIndexType(this); + yield ret; + } + + // Prove that fields and methods on '_domain' work + proc _domain.pid() { + return _pid; + } +} +)"""; + + +static std::string ArrayModule = +R"""( +module ChapelArray { + public use ChapelDomain; + + record _array { + var _pid:int; + var _instance; + var _unowned:bool; + } + + iter _array.these() : this.eltType { + var i : this.eltType; + yield i; + } + + proc _array.size : int { + var i : int; + return i; + } + + // TODO: 'this' accessor can't work because accessing 'this.domain' in the + // formal's type-expr is resolved as an ErroneousType + + proc chpl__buildIndexType(param rank: int, type idxType) type where rank == 1 { + return idxType; + } + + proc chpl__buildIndexType(param rank: int, type idxType) type where __primitive(">", rank, 1) { + return rank*idxType; + } + + proc chpl__buildIndexType(param rank: int) type do + return chpl__buildIndexType(rank, int); + + proc chpl__buildIndexType(d: domain) type do + return chpl__buildIndexType(d.rank, d.idxType); +} +)"""; + +#endif From 72b1bb6a40201b1ed1c73b89e7f74ab7f097edb3 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 16 Sep 2024 12:35:20 -0700 Subject: [PATCH 37/65] Use real ChapelDomain in testArrays, with module code errors ignored Also disable associative array testing until associative domains are fixed Signed-off-by: Anna Rift --- frontend/test/resolution/testArrays.cpp | 19 ++++++++++++++----- frontend/test/test-minimal-modules.h | 5 +++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/frontend/test/resolution/testArrays.cpp b/frontend/test/resolution/testArrays.cpp index c1b81d02ceee..43fdd28514f4 100644 --- a/frontend/test/resolution/testArrays.cpp +++ b/frontend/test/resolution/testArrays.cpp @@ -43,8 +43,11 @@ static QualifiedType findVarType(const Module* m, static void testArray(std::string domainType, std::string eltType) { - Context ctx; + Context::Configuration config; + config.chplHome = getenv("CHPL_HOME"); + Context ctx(config); Context* context = &ctx; + setupModuleSearchPaths(context, false, false, {}, {}); ErrorGuard guard(context); // a different element type from the one we were given @@ -53,7 +56,7 @@ static void testArray(std::string domainType, altElt = "string"; } - std::string program = DomainModule + ArrayModule + + std::string program = ArrayModule + R"""( module M { use ChapelArray; @@ -94,7 +97,7 @@ module M { setFileText(context, path, std::move(program)); const ModuleVec& vec = parseToplevel(context, path); - const Module* m = vec[2]; + const Module* m = vec[1]; const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); @@ -137,7 +140,11 @@ module M { assert(call->byAst(ETGood).type().type() == AType.type()); } - assert(guard.errors().size() == 0); + // TODO: Re-enable error checking once we get more module code resolving + // successfully. Currently enough resolves to do this test, but we get errors + // along the way. + // assert(guard.errors().size() == 0); + guard.realizeErrors(context); std::string arrayText; arrayText += "[" + domainType + "] " + eltType; @@ -148,7 +155,9 @@ int main() { testArray("domain(1)", "int"); testArray("domain(1)", "string"); testArray("domain(2)", "int"); - testArray("domain(int)", "int"); + + // TODO: re-enable once associative domains are working + // testArray("domain(int)", "int"); return 0; } diff --git a/frontend/test/test-minimal-modules.h b/frontend/test/test-minimal-modules.h index 1518222c9ea5..b416843e66f8 100644 --- a/frontend/test/test-minimal-modules.h +++ b/frontend/test/test-minimal-modules.h @@ -98,6 +98,11 @@ module ChapelArray { proc chpl__buildIndexType(d: domain) type do return chpl__buildIndexType(d.rank, d.idxType); + + // Module code needed to avoid fatal errors in resolution + param nullPid = -1; + proc _isPrivatized(value) param do return false; + record dmap { } } )"""; From 1de785f6ca2db62d4a1f387bc3fb8a50fbab4959 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 26 Sep 2024 12:41:16 -0700 Subject: [PATCH 38/65] Add getGenericType branch for DomainType Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index b022b5f4e3d3..be9f8c22746e 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -3966,6 +3966,8 @@ static const Type* getGenericType(Context* context, const Type* recv) { auto m = getGenericType(context, cur->manageableType()); gen = ClassType::get(context, m->toManageableType(), cur->manager(), cur->decorator()); + } else if (recv->isDomainType()) { + gen = DomainType::getGenericDomainType(context); } return gen; } From f2ac562fb2212746a251ddf90a7c75fcca2deb00 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 30 Sep 2024 09:44:30 -0700 Subject: [PATCH 39/65] Skip type resolving domain literals for scopeResolveOnly Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index be9f8c22746e..1ab87935db4d 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -3807,6 +3807,10 @@ bool Resolver::enter(const uast::Domain* decl) { } void Resolver::exit(const uast::Domain* decl) { + if (scopeResolveOnly) { + return; + } + const DomainType* genericDomainType = DomainType::getGenericDomainType(context); if (CompositeType::isMissingBundledRecordType(context, genericDomainType->id())) { // If we don't have the standard library code backing the Domain type, leave From 8e820a7cad21257bce9a2c7b4cee8ba650f8f86f Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 30 Sep 2024 11:33:23 -0700 Subject: [PATCH 40/65] Use helper for owned/shared record IDs Signed-off-by: Anna Rift --- frontend/lib/types/CompositeType.cpp | 29 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index 392fb54ccdb8..bca5a9439574 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -197,16 +197,23 @@ const RecordType* CompositeType::getDistributionType(Context* context) { /* instantiatedFrom */ nullptr, SubstitutionsMap()); } +static const ID getOwnedRecordId(Context* context) { + return parsing::getSymbolFromTopLevelModule(context, "OwnedObject", "_owned"); +} + +static const ID getSharedRecordId(Context* context) { + return parsing::getSymbolFromTopLevelModule(context, "SharedObject", + "_shared"); +} + static const RecordType* tryCreateManagerRecord(Context* context, - const char* moduleName, - const char* recordName, + const ID& recordId, const BasicClassType* bct) { const RecordType* instantiatedFrom = nullptr; SubstitutionsMap subs; if (bct != nullptr) { instantiatedFrom = tryCreateManagerRecord(context, - moduleName, - recordName, + recordId, /*bct*/ nullptr); auto fields = fieldsForTypeDecl(context, @@ -227,21 +234,20 @@ static const RecordType* tryCreateManagerRecord(Context* context, } } - auto name = UniqueString::get(context, recordName); - auto id = parsing::getSymbolFromTopLevelModule(context, moduleName, recordName); - return RecordType::get(context, id, name, + auto name = recordId.symbolName(context); + return RecordType::get(context, recordId, name, instantiatedFrom, std::move(subs)); } const RecordType* CompositeType::getOwnedRecordType(Context* context, const BasicClassType* bct) { - return tryCreateManagerRecord(context, "OwnedObject", "_owned", bct); + return tryCreateManagerRecord(context, getOwnedRecordId(context), bct); } const RecordType* CompositeType::getSharedRecordType(Context* context, const BasicClassType* bct) { - return tryCreateManagerRecord(context, "SharedObject", "_shared", bct); + return tryCreateManagerRecord(context, getSharedRecordId(context), bct); } bool CompositeType::isMissingBundledType(Context* context, ID id) { @@ -252,15 +258,14 @@ bool CompositeType::isMissingBundledType(Context* context, ID id) { bool CompositeType::isMissingBundledRecordType(Context* context, ID id) { bool noLibrary = parsing::bundledModulePath(context).isEmpty(); if (noLibrary) { - auto path = id.symbolPath(); return id == CompositeType::getStringType(context)->id() || id == CompositeType::getRangeType(context)->id() || id == TupleType::getGenericTupleType(context)->id() || id == CompositeType::getBytesType(context)->id() || id == CompositeType::getDistributionType(context)->id() || id == DomainType::getGenericDomainType(context)->id() || - path == "OwnedObject._owned" || - path == "SharedObject._shared"; + id == getOwnedRecordId(context) || + id == getSharedRecordId(context); } return false; From 054155d3c1024667866c5bff9025d449f30c5eac Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 1 Oct 2024 11:32:49 -0700 Subject: [PATCH 41/65] Remove previous, commented domain resolution code Signed-off-by: Anna Rift --- .../lib/resolution/resolution-queries.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/frontend/lib/resolution/resolution-queries.cpp b/frontend/lib/resolution/resolution-queries.cpp index 27fd7d34b3b9..bdf777dcc845 100644 --- a/frontend/lib/resolution/resolution-queries.cpp +++ b/frontend/lib/resolution/resolution-queries.cpp @@ -3974,24 +3974,7 @@ static bool resolveFnCallSpecialType(Context* context, // the type. // // TODO: sync, single - if (ci.name() == "domain") { - // // TODO: a compiler-generated type constructor would be simpler, but we - // // don't support default values on compiler-generated methods because the - // // default values require existing AST. - - // // Note: 'dmapped' is treated like a binary operator at the moment, so - // // we don't need to worry about distribution type for 'domain(...)' exprs. - - // // Transform domain type expressions like `domain(arg1, ...)` into: - // // _domain.static_type(arg1, ...) - // auto genericDom = DomainType::getGenericDomainType(context); - // auto recv = QualifiedType(QualifiedType::TYPE, genericDom); - // auto typeCtorName = UniqueString::get(context, "static_type"); - // auto ctorCall = CallInfo::createWithReceiver(ci, recv, typeCtorName); - - // result = resolveCall(rc, call, ctorCall, inScopes); - // return true; - } else if (ci.name() == "atomic") { + if (ci.name() == "atomic") { auto newName = UniqueString::get(context, "chpl__atomicType"); auto ctorCall = CallInfo::copyAndRename(ci, newName); result = resolveCall(rc, call, ctorCall, inScopes); From 28dbe5fc4949fba4f05ec9429d6238e36afc2539 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 1 Oct 2024 12:59:42 -0700 Subject: [PATCH 42/65] Refactor and test to gracefully error, even with no modules Includes adding error message printing for many incorrect 'domain' calls. Signed-off-by: Anna Rift --- .../resolution-error-classes-list.h | 2 +- frontend/lib/resolution/InitResolver.cpp | 44 +++++++++--------- frontend/lib/resolution/Resolver.cpp | 26 ++++++----- frontend/lib/resolution/default-functions.cpp | 2 + .../resolution-error-classes-list.cpp | 42 ++++++++++++++++- frontend/test/resolution/testDomains.cpp | 45 +++++++++++++++++++ 6 files changed, 126 insertions(+), 35 deletions(-) diff --git a/frontend/include/chpl/resolution/resolution-error-classes-list.h b/frontend/include/chpl/resolution/resolution-error-classes-list.h index 2c518e2b8871..224636d7b04e 100644 --- a/frontend/include/chpl/resolution/resolution-error-classes-list.h +++ b/frontend/include/chpl/resolution/resolution-error-classes-list.h @@ -54,7 +54,7 @@ ERROR_CLASS(IncompatibleKinds, types::QualifiedType::Kind, const uast::AstNode*, ERROR_CLASS(IncompatibleRangeBounds, const uast::Range*, types::QualifiedType, types::QualifiedType) ERROR_CLASS(IncompatibleTypeAndInit, const uast::AstNode*, const uast::AstNode*, const uast::AstNode*, const types::Type*, const types::Type*) ERROR_CLASS(InvalidClassCast, const uast::PrimCall*, types::QualifiedType) -ERROR_CLASS(InvalidDomainCall, const uast::FnCall*) +ERROR_CLASS(InvalidDomainCall, const uast::FnCall*, std::vector) ERROR_CLASS(InvalidIndexCall, const uast::FnCall*, types::QualifiedType) ERROR_CLASS(InvalidNewTarget, const uast::New*, types::QualifiedType) ERROR_CLASS(InvalidParamCast, const uast::AstNode*, types::QualifiedType, types::QualifiedType) diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index 45b6dba67080..3d46d2c6ca7b 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -315,31 +315,33 @@ static const Type* ctFromSubs(Context* context, ret = ClassType::get(context, basic, manager, dec); } else if (receiverType->isDomainType()) { // Extract domain information from _instance substitution - // TODO: also support associative domains here; currently assumes rectangular + // TODO: also support associative domains here + + QualifiedType instanceQt; QualifiedType rank; QualifiedType idxType; QualifiedType stridable; - CHPL_ASSERT(subs.size() == 1); - auto instanceQt = subs.begin()->second; - auto instance = subs.begin()->second.type(); - CHPL_ASSERT(instance); - - auto instanceCt = instance->toClassType(); - CHPL_ASSERT(instanceCt); - auto instanceBct = instanceCt->basicClassType(); - CHPL_ASSERT(instanceBct); - - // Get BaseRectangularDom parent subs for rectangular domain info - auto baseRect = instanceBct->parentClassType(); - CHPL_ASSERT(baseRect->name() == "BaseRectangularDom"); - - auto innerSubs = baseRect->sortedSubstitutions(); - CHPL_ASSERT(innerSubs.size() == 3); - - rank = innerSubs[0].second; - idxType = innerSubs[1].second; - stridable = innerSubs[2].second; + if (subs.size() == 1) { + instanceQt = subs.begin()->second; + if (auto instance = instanceQt.type()) { + if (auto instanceCt = instance->toClassType()) { + if (auto instanceBct = instanceCt->basicClassType()) { + // Get BaseRectangularDom parent subs for rectangular domain info + if (auto baseRect = instanceBct->parentClassType()) { + if (baseRect->name() == "BaseRectangularDom") { + auto innerSubs = baseRect->sortedSubstitutions(); + CHPL_ASSERT(innerSubs.size() == 3); + + rank = innerSubs[0].second; + idxType = innerSubs[1].second; + stridable = innerSubs[2].second; + } + } + } + } + } + } ret = DomainType::getRectangularType(context, instanceQt, rank, idxType, stridable); diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 1ab87935db4d..8b1776a7f55b 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2372,7 +2372,7 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { /* isMethodCall */ true, /* hasQuestionArg */ false, /* isParenless */ false, - std::move(actuals)); + actuals); auto scope = scopeStack.back(); auto inScopes = CallScopeInfo::forNormalCall(scope, poiScope); @@ -2381,20 +2381,22 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { }); // Use the init call's receiver type as the resulting TYPE - const Type* receiverTy; + const Type* receiverTy = nullptr; if (runResult.ranWithoutErrors()) { auto result = runResult.result(); - auto initMsc = result.mostSpecific().only(); - CHPL_ASSERT(initMsc); - - handleResolvedCall(r, call, ci, result, - {{AssociatedAction::RUNTIME_TYPE, fnCall->id()}}); - - receiverTy = initMsc.fn()->formalType(0).type(); - assert(receiverTy); - } else { + if (auto initMsc = result.mostSpecific().only()) { + handleResolvedCall(r, call, ci, result, + {{AssociatedAction::RUNTIME_TYPE, fnCall->id()}}); + receiverTy = initMsc.fn()->formalType(0).type(); + } + } + if (!receiverTy) { receiverTy = ErroneousType::get(context); - CHPL_REPORT(context, InvalidDomainCall, fnCall); + std::vector actualTypesForErr; + for (auto it = actuals.begin() + 2; it != actuals.end(); ++it) { + actualTypesForErr.push_back(it->type()); + } + CHPL_REPORT(context, InvalidDomainCall, fnCall, actualTypesForErr); } r.setType(QualifiedType(QualifiedType::TYPE, receiverTy)); } diff --git a/frontend/lib/resolution/default-functions.cpp b/frontend/lib/resolution/default-functions.cpp index 7bab0ede4ebc..3eab8c40b186 100644 --- a/frontend/lib/resolution/default-functions.cpp +++ b/frontend/lib/resolution/default-functions.cpp @@ -200,6 +200,8 @@ generateInitParts(Context* context, CHPL_ASSERT(receiverType); qtReceiver = QualifiedType(QualifiedType::CONST_IN, receiverType); + } else if (CompositeType::isMissingBundledType(context, compType->id())) { + // ignore } else { CHPL_ASSERT(false && "Not possible!"); } diff --git a/frontend/lib/resolution/resolution-error-classes-list.cpp b/frontend/lib/resolution/resolution-error-classes-list.cpp index ea149b123ad0..80183a6562db 100644 --- a/frontend/lib/resolution/resolution-error-classes-list.cpp +++ b/frontend/lib/resolution/resolution-error-classes-list.cpp @@ -25,6 +25,7 @@ #include "chpl/uast/VisibilityClause.h" #include "chpl/uast/AstTag.h" #include "chpl/types/all-types.h" +#include #include #include @@ -617,10 +618,49 @@ void ErrorInvalidClassCast::write(ErrorWriterBase& wr) const { void ErrorInvalidDomainCall::write(ErrorWriterBase& wr) const { auto fnCall = std::get(info_); + auto actualTypes = std::get>(info_); wr.heading(kind_, type_, fnCall, "invalid use of the 'domain' keyword."); wr.codeForLocation(fnCall); - // TODO: flesh out + wr.message( + "The 'domain' keyword should be used with a valid domain type " + "expression."); + + if (fnCall->numActuals() == 0) { + wr.message("However, 'domain' here did not have any actuals."); + } else if (fnCall->numActuals() == 1) { + // Could be rectangular or associative. Error if we have an actual type + // that's wrong for both. + auto qt = actualTypes[0]; + if (!qt.isType() && !(qt.type() && qt.type()->isIntType())) { + wr.message( + "However, the first actual was ", decayToValue(qt), + " rather than an int (for rectangular) or a type (for associative)."); + wr.code(fnCall, {fnCall->actual(0)}); + } + } else if (fnCall->numActuals() <= 3) { + // Should be rectangular, must have one or more actual type(s) wrong after + // the first. + wr.message( + "This 'domain' call is structured like a rectangular domain type."); + if (fnCall->numActuals() >= 2) { + auto idxTypeQt = actualTypes[1]; + if (!idxTypeQt.isType()) { + wr.message("However, the second actual (idxType) was ", + decayToValue(idxTypeQt), " rather than a type as required."); + wr.code(fnCall, {fnCall->actual(1)}); + } + } + if (fnCall->numActuals() == 3) { + auto stridesQt = actualTypes[2]; + wr.message("However, the third actual (strides) was ", + decayToValue(stridesQt), + " rather than a strideKind as required."); + wr.code(fnCall, {fnCall->actual(2)}); + } + } else { + wr.message("However, 'domain' here had too many actuals."); + } } void ErrorInvalidIndexCall::write(ErrorWriterBase& wr) const { diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index a71b9624120c..824d106648cf 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -324,6 +324,44 @@ module M { // assert(findVarType(m, rr, "equal").isParamTrue()); // } + +static void testBadDomain(std::string domainType) { + // Ensure we gracefully error for bad domain type expressions. + Context ctx; + Context* context = &ctx; + ErrorGuard guard(context); + + std::string program = +R"""( +module M { + var d : )""" + domainType + R"""(; +} +)"""; + + auto path = UniqueString::get(context, "input.chpl"); + setFileText(context, path, std::move(program)); + + const ModuleVec& vec = parseToplevel(context, path); + const Module* m = vec[0]; + + const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); + + const Variable* d = m->stmt(0)->toVariable(); + assert(d); + assert(d->name() == "d"); + QualifiedType dType = rr.byAst(d).type(); + assert(dType.type()->isErroneousType()); + + assert(guard.errors().size() == 1); + auto& e = guard.errors()[0]; + assert(e->type() == chpl::InvalidDomainCall); + + printf("Success: cannot resolve incorrect domain type expression %s\n", + domainType.c_str()); + + guard.clearErrors(); +} + int main() { testRectangular("domain(1)", 1, "int", "one"); testRectangular("domain(2)", 2, "int", "one"); @@ -350,5 +388,12 @@ int main() { // testIndex("domain(int)", "int"); // testIndex("domain(string)", "string"); + testBadDomain("domain()"); + testBadDomain("domain(1, 2, 3, 4)"); + testBadDomain("domain(\"asdf\")"); + testBadDomain("domain(\"asdf\", \"asdf2\")"); + testBadDomain("domain(1, \"asdf\")"); + testBadDomain("domain(1, int, \"asdf\")"); + return 0; } From 115496936760b60ca7cf75581f763d421250bef6 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 1 Oct 2024 13:13:29 -0700 Subject: [PATCH 43/65] Also test proper errors with standard modules Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 34 +++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 824d106648cf..b2320901c46e 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -324,13 +324,8 @@ module M { // assert(findVarType(m, rr, "equal").isParamTrue()); // } - -static void testBadDomain(std::string domainType) { - // Ensure we gracefully error for bad domain type expressions. - Context ctx; - Context* context = &ctx; - ErrorGuard guard(context); - +static void testBadDomainHelper(std::string domainType, Context* context, + ErrorGuard& guard) { std::string program = R"""( module M { @@ -362,6 +357,31 @@ module M { guard.clearErrors(); } +// Ensure we gracefully error for bad domain type expressions, with or without +// the standard modules available. +static void testBadDomain(std::string domainType) { + // Without standard modules + { + Context ctx; + Context* context = &ctx; + ErrorGuard guard(context); + + testBadDomainHelper(domainType, context, guard); + } + + // With standard modules + { + Context::Configuration config; + config.chplHome = getenv("CHPL_HOME"); + Context ctx(config); + Context* context = &ctx; + setupModuleSearchPaths(context, false, false, {}, {}); + ErrorGuard guard(context); + + testBadDomainHelper(domainType, context, guard); + } +} + int main() { testRectangular("domain(1)", 1, "int", "one"); testRectangular("domain(2)", 2, "int", "one"); From 340b548ec6723d4cde1c94a63b3fb27bd2401803 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Tue, 1 Oct 2024 13:02:01 -0700 Subject: [PATCH 44/65] Re-enable error checking in testArrays Signed-off-by: Anna Rift --- frontend/test/resolution/testArrays.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/test/resolution/testArrays.cpp b/frontend/test/resolution/testArrays.cpp index 43fdd28514f4..b4db39ec1a31 100644 --- a/frontend/test/resolution/testArrays.cpp +++ b/frontend/test/resolution/testArrays.cpp @@ -140,10 +140,7 @@ module M { assert(call->byAst(ETGood).type().type() == AType.type()); } - // TODO: Re-enable error checking once we get more module code resolving - // successfully. Currently enough resolves to do this test, but we get errors - // along the way. - // assert(guard.errors().size() == 0); + assert(guard.errors().size() == 0); guard.realizeErrors(context); std::string arrayText; From cc74c7298dfb9bd3e9581dd4b0f0192ee882c2a0 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 3 Oct 2024 13:58:40 -0700 Subject: [PATCH 45/65] Refactor domain ctFromSubs branch into helper Signed-off-by: Anna Rift --- frontend/lib/resolution/InitResolver.cpp | 69 +++++++++++++----------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index 3d46d2c6ca7b..ba98ef9dfea3 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -280,6 +280,43 @@ bool InitResolver::isFinalReceiverStateValid(void) { return ret; } +// Extract domain information from _instance substitution +// TODO: also support associative domains here +static const DomainType* domainTypeFromSubsHelper( + Context* context, const CompositeType::SubstitutionsMap& subs) { + // Expect one substitution for _instance + if (subs.size() != 1) { + return DomainType::getGenericDomainType(context); + } + + QualifiedType instanceQt = subs.begin()->second; + + QualifiedType rank; + QualifiedType idxType; + QualifiedType stridable; + + if (auto instance = instanceQt.type()) { + if (auto instanceCt = instance->toClassType()) { + if (auto instanceBct = instanceCt->basicClassType()) { + // Get BaseRectangularDom parent subs for rectangular domain info + if (auto baseRect = instanceBct->parentClassType()) { + if (baseRect->name() == "BaseRectangularDom") { + auto innerSubs = baseRect->sortedSubstitutions(); + CHPL_ASSERT(innerSubs.size() == 3); + + rank = innerSubs[0].second; + idxType = innerSubs[1].second; + stridable = innerSubs[2].second; + } + } + } + } + } + + return DomainType::getRectangularType(context, instanceQt, rank, idxType, + stridable); +} + static const Type* ctFromSubs(Context* context, const Type* receiverType, const BasicClassType* superType, @@ -314,37 +351,7 @@ static const Type* ctFromSubs(Context* context, auto dec = ClassTypeDecorator(ClassTypeDecorator::BORROWED_NONNIL); ret = ClassType::get(context, basic, manager, dec); } else if (receiverType->isDomainType()) { - // Extract domain information from _instance substitution - // TODO: also support associative domains here - - QualifiedType instanceQt; - QualifiedType rank; - QualifiedType idxType; - QualifiedType stridable; - - if (subs.size() == 1) { - instanceQt = subs.begin()->second; - if (auto instance = instanceQt.type()) { - if (auto instanceCt = instance->toClassType()) { - if (auto instanceBct = instanceCt->basicClassType()) { - // Get BaseRectangularDom parent subs for rectangular domain info - if (auto baseRect = instanceBct->parentClassType()) { - if (baseRect->name() == "BaseRectangularDom") { - auto innerSubs = baseRect->sortedSubstitutions(); - CHPL_ASSERT(innerSubs.size() == 3); - - rank = innerSubs[0].second; - idxType = innerSubs[1].second; - stridable = innerSubs[2].second; - } - } - } - } - } - } - - ret = DomainType::getRectangularType(context, instanceQt, rank, idxType, - stridable); + ret = domainTypeFromSubsHelper(context, subs); } else { CHPL_ASSERT(false && "Not handled!"); } From 2b1230cc8ee4f7bc0374ef0a93395a70165e5981 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 3 Oct 2024 14:40:22 -0700 Subject: [PATCH 46/65] Use fieldsForTypeDecl for domain subs, validate types Includes: - testing of DomainType's substitution types - assertions that substitution types are correct when creating DomainType - minor refactors in domainTypeFromSubsHelper for clarity Signed-off-by: Anna Rift --- frontend/lib/resolution/InitResolver.cpp | 51 ++++++++++++++---------- frontend/lib/types/DomainType.cpp | 7 ++++ frontend/test/resolution/testDomains.cpp | 22 ++++++---- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index ba98ef9dfea3..24e593b337e6 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -280,41 +280,52 @@ bool InitResolver::isFinalReceiverStateValid(void) { return ret; } -// Extract domain information from _instance substitution -// TODO: also support associative domains here +// Extract domain type information from _instance substitution static const DomainType* domainTypeFromSubsHelper( Context* context, const CompositeType::SubstitutionsMap& subs) { - // Expect one substitution for _instance - if (subs.size() != 1) { - return DomainType::getGenericDomainType(context); - } + auto genericDomain = DomainType::getGenericDomainType(context); - QualifiedType instanceQt = subs.begin()->second; + // Expect one substitution for _instance + if (subs.size() != 1) return genericDomain; - QualifiedType rank; - QualifiedType idxType; - QualifiedType stridable; + const QualifiedType instanceQt = subs.begin()->second; if (auto instance = instanceQt.type()) { if (auto instanceCt = instance->toClassType()) { if (auto instanceBct = instanceCt->basicClassType()) { // Get BaseRectangularDom parent subs for rectangular domain info - if (auto baseRect = instanceBct->parentClassType()) { - if (baseRect->name() == "BaseRectangularDom") { - auto innerSubs = baseRect->sortedSubstitutions(); - CHPL_ASSERT(innerSubs.size() == 3); - - rank = innerSubs[0].second; - idxType = innerSubs[1].second; - stridable = innerSubs[2].second; + if (auto baseDom = instanceBct->parentClassType()) { + auto& rf = fieldsForTypeDecl(context, baseDom, + DefaultsPolicy::IGNORE_DEFAULTS); + if (baseDom->name() == "BaseRectangularDom") { + CHPL_ASSERT(rf.numFields() == 3); + QualifiedType rank; + QualifiedType idxType; + QualifiedType stridable; + for (int i = 0; i < rf.numFields(); i++) { + if (rf.fieldName(i) == "rank") { + rank = rf.fieldType(i); + } else if (rf.fieldName(i) == "idxType") { + idxType = rf.fieldType(i); + } else if (rf.fieldName(i) == "strides") { + stridable = rf.fieldType(i); + } + } + + return DomainType::getRectangularType(context, instanceQt, rank, + idxType, stridable); + } else if (baseDom->name() == "BaseAssociativeDom") { + // TODO: support associative domains + } else { + CHPL_ASSERT(false && "Not handled!"); } } } } } - return DomainType::getRectangularType(context, instanceQt, rank, idxType, - stridable); + // If we reach here, we weren't able to resolve the domain type + return genericDomain; } static const Type* ctFromSubs(Context* context, diff --git a/frontend/lib/types/DomainType.cpp b/frontend/lib/types/DomainType.cpp index e4a5d2d2dc7e..d8c9e8af053c 100644 --- a/frontend/lib/types/DomainType.cpp +++ b/frontend/lib/types/DomainType.cpp @@ -86,10 +86,16 @@ DomainType::getRectangularType(Context* context, auto genericDomain = getGenericDomainType(context); SubstitutionsMap subs; + CHPL_ASSERT(rank.isParam() && rank.param()->isIntParam()); subs.emplace(ID(UniqueString(), 0, 0), rank); + CHPL_ASSERT(idxType.isType()); subs.emplace(ID(UniqueString(), 1, 0), idxType); + CHPL_ASSERT(stridable.isParam() && stridable.param()->isEnumParam() && + stridable.param()->toEnumParam()->value().id.symbolPath() == + "ChapelRange.strideKind"); subs.emplace(ID(UniqueString(), 2, 0), stridable); + // Add substitution for _instance field auto& rf = fieldsForTypeDecl(context, genericDomain, resolution::DefaultsPolicy::IGNORE_DEFAULTS, @@ -118,6 +124,7 @@ DomainType::getAssociativeType(Context* context, const QualifiedType& idxType, const QualifiedType& parSafe) { SubstitutionsMap subs; + // TODO: assert validity of sub types subs.emplace(ID(UniqueString(), 0, 0), idxType); subs.emplace(ID(UniqueString(), 1, 0), parSafe); auto name = UniqueString::get(context, "_domain"); diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index b2320901c46e..1e255c37ab9e 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -94,8 +94,10 @@ module M { assert(d); assert(d->name() == "d"); - QualifiedType dType = rr.byAst(d).type(); - assert(dType.type()->isDomainType()); + QualifiedType dQt = rr.byAst(d).type(); + assert(dQt.type()); + auto dType = dQt.type()->toDomainType(); + assert(dType); auto dTypeExpr = d->typeExpression(); assert(dTypeExpr); @@ -107,11 +109,17 @@ module M { QualifiedType fullIndexType = findVarType(m, rr, "fullIndex"); (void)fullIndexType; - assert(findVarType(m, rr, "r").param()->toIntParam()->value() == rank); + auto rankVarTy = findVarType(m, rr, "r"); + assert(rankVarTy == dType->rank()); + assert(rankVarTy.param()->toIntParam()->value() == rank); - assert(findVarType(m, rr, "ig") == findVarType(m, rr, "i")); + auto idxTypeVarTy = findVarType(m, rr, "i"); + assert(idxTypeVarTy == dType->idxType()); + assert(findVarType(m, rr, "ig") == idxTypeVarTy); - assert(findVarType(m, rr, "s").param()->toEnumParam()->value().str == strides); + auto stridesVarTy = findVarType(m, rr, "s"); + assert(stridesVarTy == dType->stridable()); + assert(stridesVarTy.param()->toEnumParam()->value().str == strides); assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == true); @@ -131,7 +139,7 @@ module M { assert(call->signature()->instantiatedFrom() != nullptr); const Variable* GT = findOnlyNamed(m, "GT")->toVariable(); - assert(call->byAst(GT).type().type() == dType.type()); + assert(call->byAst(GT).type().type() == dType); } { @@ -144,7 +152,7 @@ module M { assert(call->signature()->instantiatedFrom() == nullptr); const Variable* CT = findOnlyNamed(m, "CT")->toVariable(); - assert(call->byAst(CT).type().type() == dType.type()); + assert(call->byAst(CT).type().type() == dType); } assert(guard.errors().size() == 0); From 08be9049056a8a63eb2ad45967d04872e3622e0f Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 3 Oct 2024 14:43:44 -0700 Subject: [PATCH 47/65] Rename DomainType stridable->strides Signed-off-by: Anna Rift --- frontend/include/chpl/types/DomainType.h | 6 +++--- frontend/lib/resolution/InitResolver.cpp | 6 +++--- frontend/lib/resolution/return-type-inference.cpp | 4 ++-- frontend/lib/types/DomainType.cpp | 10 +++++----- frontend/test/resolution/testDomains.cpp | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/include/chpl/types/DomainType.h b/frontend/include/chpl/types/DomainType.h index 707a357ab5ab..aeda1ae87492 100644 --- a/frontend/include/chpl/types/DomainType.h +++ b/frontend/include/chpl/types/DomainType.h @@ -56,7 +56,7 @@ class DomainType final : public CompositeType { // TODO: distributions Kind kind_; - // Will compute idxType, rank, and stridable from 'subs' + // Will compute idxType, rank, and strides from 'subs' DomainType(ID id, UniqueString name, const DomainType* instantiatedFrom, SubstitutionsMap subs, @@ -94,7 +94,7 @@ class DomainType final : public CompositeType { const QualifiedType& instance, const QualifiedType& rank, const QualifiedType& idxType, - const QualifiedType& stridable); + const QualifiedType& strides); /** Return an associative domain type */ static const DomainType* getAssociativeType(Context* context, @@ -127,7 +127,7 @@ class DomainType final : public CompositeType { } } - const QualifiedType& stridable() const { + const QualifiedType& strides() const { CHPL_ASSERT(kind_ == Kind::Rectangular); return subs_.at(ID(UniqueString(), 2, 0)); } diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index 24e593b337e6..03a19b38dd64 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -301,19 +301,19 @@ static const DomainType* domainTypeFromSubsHelper( CHPL_ASSERT(rf.numFields() == 3); QualifiedType rank; QualifiedType idxType; - QualifiedType stridable; + QualifiedType strides; for (int i = 0; i < rf.numFields(); i++) { if (rf.fieldName(i) == "rank") { rank = rf.fieldType(i); } else if (rf.fieldName(i) == "idxType") { idxType = rf.fieldType(i); } else if (rf.fieldName(i) == "strides") { - stridable = rf.fieldType(i); + strides = rf.fieldType(i); } } return DomainType::getRectangularType(context, instanceQt, rank, - idxType, stridable); + idxType, strides); } else if (baseDom->name() == "BaseAssociativeDom") { // TODO: support associative domains } else { diff --git a/frontend/lib/resolution/return-type-inference.cpp b/frontend/lib/resolution/return-type-inference.cpp index 46a94096f614..a7adda7df4a4 100644 --- a/frontend/lib/resolution/return-type-inference.cpp +++ b/frontend/lib/resolution/return-type-inference.cpp @@ -985,8 +985,8 @@ static bool helpComputeCompilerGeneratedReturnType(Context* context, result = QualifiedType(QualifiedType::PARAM, IntType::get(context, 64), IntParam::get(context, dt->rankInt())); - } else if (untyped->name() == "stridable") { - result = dt->stridable(); + } else if (untyped->name() == "strides") { + result = dt->strides(); } else if (untyped->name() == "parSafe") { result = dt->parSafe(); } else if (untyped->name() == "isRectangular") { diff --git a/frontend/lib/types/DomainType.cpp b/frontend/lib/types/DomainType.cpp index d8c9e8af053c..c58a146cb0f5 100644 --- a/frontend/lib/types/DomainType.cpp +++ b/frontend/lib/types/DomainType.cpp @@ -38,7 +38,7 @@ void DomainType::stringify(std::ostream& ss, ss << ","; idxType().type()->stringify(ss, stringKind); ss << ","; - stridable().param()->stringify(ss, stringKind); + strides().param()->stringify(ss, stringKind); ss << ")"; } else if (kind_ == Kind::Associative) { ss << "domain("; @@ -82,7 +82,7 @@ DomainType::getRectangularType(Context* context, const QualifiedType& instance, const QualifiedType& rank, const QualifiedType& idxType, - const QualifiedType& stridable) { + const QualifiedType& strides) { auto genericDomain = getGenericDomainType(context); SubstitutionsMap subs; @@ -90,10 +90,10 @@ DomainType::getRectangularType(Context* context, subs.emplace(ID(UniqueString(), 0, 0), rank); CHPL_ASSERT(idxType.isType()); subs.emplace(ID(UniqueString(), 1, 0), idxType); - CHPL_ASSERT(stridable.isParam() && stridable.param()->isEnumParam() && - stridable.param()->toEnumParam()->value().id.symbolPath() == + CHPL_ASSERT(strides.isParam() && strides.param()->isEnumParam() && + strides.param()->toEnumParam()->value().id.symbolPath() == "ChapelRange.strideKind"); - subs.emplace(ID(UniqueString(), 2, 0), stridable); + subs.emplace(ID(UniqueString(), 2, 0), strides); // Add substitution for _instance field diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 1e255c37ab9e..2fd7dcb26f7d 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -118,7 +118,7 @@ module M { assert(findVarType(m, rr, "ig") == idxTypeVarTy); auto stridesVarTy = findVarType(m, rr, "s"); - assert(stridesVarTy == dType->stridable()); + assert(stridesVarTy == dType->strides()); assert(stridesVarTy.param()->toEnumParam()->value().str == strides); assert(findVarType(m, rr, "rk").param()->toBoolParam()->value() == true); From 73fa2590dfdf8fac859b2d2964754bafd8f2dcee Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 3 Oct 2024 14:45:29 -0700 Subject: [PATCH 48/65] Remove return-type-inference for (non-existent) compiler-generated domain methods Signed-off-by: Anna Rift --- .../lib/resolution/return-type-inference.cpp | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/frontend/lib/resolution/return-type-inference.cpp b/frontend/lib/resolution/return-type-inference.cpp index a7adda7df4a4..2781c698b4d9 100644 --- a/frontend/lib/resolution/return-type-inference.cpp +++ b/frontend/lib/resolution/return-type-inference.cpp @@ -974,34 +974,6 @@ static bool helpComputeCompilerGeneratedReturnType(Context* context, result = QualifiedType(QualifiedType::REF, ft.type()); } return true; - } else if (untyped->isMethod() && sig->formalType(0).type()->isDomainType()) { - auto dt = sig->formalType(0).type()->toDomainType(); - - if (untyped->name() == "idxType") { - result = dt->idxType(); - } else if (untyped->name() == "rank") { - // Can't use `RankType::rank` because `D.rank` is defined for associative - // domains, even though they don't have a matching substitution. - result = QualifiedType(QualifiedType::PARAM, - IntType::get(context, 64), - IntParam::get(context, dt->rankInt())); - } else if (untyped->name() == "strides") { - result = dt->strides(); - } else if (untyped->name() == "parSafe") { - result = dt->parSafe(); - } else if (untyped->name() == "isRectangular") { - auto val = BoolParam::get(context, dt->kind() == DomainType::Kind::Rectangular); - auto type = BoolType::get(context); - result = QualifiedType(QualifiedType::PARAM, type, val); - } else if (untyped->name() == "isAssociative") { - auto val = BoolParam::get(context, dt->kind() == DomainType::Kind::Associative); - auto type = BoolType::get(context); - result = QualifiedType(QualifiedType::PARAM, type, val); - } else { - CHPL_ASSERT(false && "unhandled compiler-generated domain method"); - return true; - } - return true; } else if (untyped->isMethod() && sig->formalType(0).type()->isArrayType()) { auto at = sig->formalType(0).type()->toArrayType(); From ec55c8dd9b80bf17b3dc265e3274a7978018d5b8 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 3 Oct 2024 15:07:02 -0700 Subject: [PATCH 49/65] Use CHPL_TYPE_ERROR macro Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 8b1776a7f55b..3bf8b227979c 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2381,24 +2381,24 @@ bool Resolver::resolveSpecialKeywordCall(const Call* call) { }); // Use the init call's receiver type as the resulting TYPE - const Type* receiverTy = nullptr; + QualifiedType receiverTy; if (runResult.ranWithoutErrors()) { auto result = runResult.result(); if (auto initMsc = result.mostSpecific().only()) { handleResolvedCall(r, call, ci, result, {{AssociatedAction::RUNTIME_TYPE, fnCall->id()}}); - receiverTy = initMsc.fn()->formalType(0).type(); + receiverTy = initMsc.fn()->formalType(0); } } - if (!receiverTy) { - receiverTy = ErroneousType::get(context); + if (!receiverTy.type()) { std::vector actualTypesForErr; for (auto it = actuals.begin() + 2; it != actuals.end(); ++it) { actualTypesForErr.push_back(it->type()); } - CHPL_REPORT(context, InvalidDomainCall, fnCall, actualTypesForErr); + receiverTy = CHPL_TYPE_ERROR(context, InvalidDomainCall, fnCall, + actualTypesForErr); } - r.setType(QualifiedType(QualifiedType::TYPE, receiverTy)); + r.setType(QualifiedType(QualifiedType::TYPE, receiverTy.type())); } return true; } From 1848c41e2ebfe37bea335ed663097da39da17742 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 3 Oct 2024 15:19:27 -0700 Subject: [PATCH 50/65] Merge resolveNewFor{Record,Domain,Union}->RecordLike Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 53 +++++++--------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 3bf8b227979c..a817f907b35b 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -4481,38 +4481,18 @@ static void resolveNewForClass(Resolver& rv, const New* node, re.setType(qt); } -static void resolveNewForRecord(Resolver& rv, const New* node, - const RecordType* recordType) { - ResolvedExpression& re = rv.byPostorder.byAst(node); - - if (node->management() != New::DEFAULT_MANAGEMENT) { - CHPL_REPORT(rv.context, MemManagementNonClass, node, recordType); - } else { - auto qt = QualifiedType(QualifiedType::INIT_RECEIVER, recordType); - re.setType(qt); - } -} - -static void resolveNewForDomain(Resolver& rv, const New* node, - const DomainType* domainType) { - ResolvedExpression& re = rv.byPostorder.byAst(node); - - if (node->management() != New::DEFAULT_MANAGEMENT) { - CHPL_REPORT(rv.context, MemManagementNonClass, node, domainType); - } else { - auto qt = QualifiedType(QualifiedType::INIT_RECEIVER, domainType); - re.setType(qt); - } -} +static void resolveNewForRecordLike(Resolver& rv, const New* node, + const CompositeType* recordLikeType) { + CHPL_ASSERT(recordLikeType->isRecordType() || + recordLikeType->isDomainType() || + recordLikeType->isUnionType()); -static void resolveNewForUnion(Resolver& rv, const New* node, - const UnionType* unionType) { ResolvedExpression& re = rv.byPostorder.byAst(node); if (node->management() != New::DEFAULT_MANAGEMENT) { - CHPL_REPORT(rv.context, MemManagementNonClass, node, unionType); + CHPL_REPORT(rv.context, MemManagementNonClass, node, recordLikeType); } else { - auto qt = QualifiedType(QualifiedType::INIT_RECEIVER, unionType); + auto qt = QualifiedType(QualifiedType::INIT_RECEIVER, recordLikeType); re.setType(qt); } } @@ -4543,21 +4523,14 @@ void Resolver::exit(const New* node) { return; } - if (qtTypeExpr.type()->isBasicClassType()) { + auto type = qtTypeExpr.type(); + if (type->isBasicClassType()) { CHPL_ASSERT(false && "Expected fully decorated class type"); - - } else if (auto classType = qtTypeExpr.type()->toClassType()) { + } else if (auto classType = type->toClassType()) { resolveNewForClass(*this, node, classType); - - } else if (auto recordType = qtTypeExpr.type()->toRecordType()) { - resolveNewForRecord(*this, node, recordType); - - } else if (auto domainType = qtTypeExpr.type()->toDomainType()) { - resolveNewForDomain(*this, node, domainType); - - } else if (auto unionType = qtTypeExpr.type()->toUnionType()) { - resolveNewForUnion(*this, node, unionType); - + } else if (type->isRecordType() || type->isDomainType() || + type->isUnionType()) { + resolveNewForRecordLike(*this, node, type->toCompositeType()); } else { if (node->management() != New::DEFAULT_MANAGEMENT) { CHPL_REPORT(context, MemManagementNonClass, node, qtTypeExpr.type()); From 8300a0ca187421f68c5bc4e0565a66aa3508eaf8 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Thu, 3 Oct 2024 15:26:59 -0700 Subject: [PATCH 51/65] Fix repeated "however" in error message Signed-off-by: Anna Rift --- .../resolution/resolution-error-classes-list.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/frontend/lib/resolution/resolution-error-classes-list.cpp b/frontend/lib/resolution/resolution-error-classes-list.cpp index 80183a6562db..13f37b53297a 100644 --- a/frontend/lib/resolution/resolution-error-classes-list.cpp +++ b/frontend/lib/resolution/resolution-error-classes-list.cpp @@ -633,9 +633,9 @@ void ErrorInvalidDomainCall::write(ErrorWriterBase& wr) const { // that's wrong for both. auto qt = actualTypes[0]; if (!qt.isType() && !(qt.type() && qt.type()->isIntType())) { - wr.message( - "However, the first actual was ", decayToValue(qt), - " rather than an int (for rectangular) or a type (for associative)."); + wr.message("However, the first actual was ", decayToValue(qt), + " rather than an 'int' (for rectangular) or a type (for " + "associative)."); wr.code(fnCall, {fnCall->actual(0)}); } } else if (fnCall->numActuals() <= 3) { @@ -643,19 +643,21 @@ void ErrorInvalidDomainCall::write(ErrorWriterBase& wr) const { // the first. wr.message( "This 'domain' call is structured like a rectangular domain type."); + bool erroredForIdxType = false; if (fnCall->numActuals() >= 2) { auto idxTypeQt = actualTypes[1]; if (!idxTypeQt.isType()) { - wr.message("However, the second actual (idxType) was ", + erroredForIdxType = true; + wr.message("However, the second actual ('idxType') was ", decayToValue(idxTypeQt), " rather than a type as required."); wr.code(fnCall, {fnCall->actual(1)}); } } if (fnCall->numActuals() == 3) { auto stridesQt = actualTypes[2]; - wr.message("However, the third actual (strides) was ", - decayToValue(stridesQt), - " rather than a strideKind as required."); + wr.message((erroredForIdxType ? "Additionally" : "However"), + ", the third actual ('strides') was ", decayToValue(stridesQt), + " rather than a 'strideKind' as required."); wr.code(fnCall, {fnCall->actual(2)}); } } else { From 2494c9301e46e0423bf044873e3c7264168f7225 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 10:52:00 -0700 Subject: [PATCH 52/65] Make getSymbolFromTopLevelModule also return sym name Returned via a new struct containing ID and name. A new helper, getSymbolId... is introduced with the previous behavior, to preserve performance in cases where only ID is needed. Signed-off-by: Anna Rift --- .../include/chpl/parsing/parsing-queries.h | 28 +++++++++---- frontend/lib/parsing/parsing-queries.cpp | 13 ++++-- frontend/lib/types/ArrayType.cpp | 3 +- frontend/lib/types/BasicClassType.cpp | 4 +- frontend/lib/types/CPtrType.cpp | 6 ++- frontend/lib/types/CompositeType.cpp | 40 ++++++++++--------- frontend/lib/types/DomainType.cpp | 8 ++-- frontend/lib/types/EnumType.cpp | 6 +-- frontend/lib/types/TupleType.cpp | 4 +- 9 files changed, 68 insertions(+), 44 deletions(-) diff --git a/frontend/include/chpl/parsing/parsing-queries.h b/frontend/include/chpl/parsing/parsing-queries.h index 75be77d154b5..fc86c312b086 100644 --- a/frontend/include/chpl/parsing/parsing-queries.h +++ b/frontend/include/chpl/parsing/parsing-queries.h @@ -454,15 +454,29 @@ std::string getExistingFileInModuleSearchPath(Context* context, */ const uast::Module* getToplevelModule(Context* context, UniqueString name); +struct IdAndName { + ID id; + UniqueString name; +}; + + +/** + Given a particular (presumably standard) module, return the ID of a + symbol with the given name in that module. Beyond creating the ID, this also + ensures that the standard module is parsed, and thus, that 'idToAst' on the + returned ID will return a non-null value. + */ +ID getSymbolIdFromTopLevelModule(Context* context, + const char* modName, + const char* symName); + /** - Given a particular (presumably standard) module, return the ID of a symbol - with the given name in that module. Beyond creating the ID, this also ensures - that the standard module is parsed, and thus, that 'idToAst' on the returned - ID will return a non-null value. + Like getSymbolId..., but return also contains the name of the given symbol for + convenience. */ -ID getSymbolFromTopLevelModule(Context* context, - const char* modName, - const char* symName); +IdAndName getSymbolFromTopLevelModule(Context* context, + const char* modName, + const char* symName); /** This query parses a submodule for 'include submodule'. diff --git a/frontend/lib/parsing/parsing-queries.cpp b/frontend/lib/parsing/parsing-queries.cpp index 3ed5fef434fc..dfd623c03f74 100644 --- a/frontend/lib/parsing/parsing-queries.cpp +++ b/frontend/lib/parsing/parsing-queries.cpp @@ -1108,9 +1108,9 @@ const Module* getToplevelModule(Context* context, UniqueString name) { return getToplevelModuleQuery(context, name); } -ID getSymbolFromTopLevelModule(Context* context, - const char* modName, - const char* symName) { +ID getSymbolIdFromTopLevelModule(Context* context, + const char* modName, + const char* symName) { std::ignore = getToplevelModule(context, UniqueString::get(context, modName)); // Performance: this has to concatenate the two strings at runtime. @@ -1126,6 +1126,13 @@ ID getSymbolFromTopLevelModule(Context* context, return ID(UniqueString::get(context, fullPath)); } +IdAndName getSymbolFromTopLevelModule(Context* context, + const char* modName, + const char* symName) { + return {getSymbolIdFromTopLevelModule(context, modName, symName), + UniqueString::get(context, symName)}; +} + static const Module* const& getIncludedSubmoduleQuery(Context* context, ID includeModuleId) { QUERY_BEGIN(getIncludedSubmoduleQuery, context, includeModuleId); diff --git a/frontend/lib/types/ArrayType.cpp b/frontend/lib/types/ArrayType.cpp index 25df89a9d84b..9b66b0d96000 100644 --- a/frontend/lib/types/ArrayType.cpp +++ b/frontend/lib/types/ArrayType.cpp @@ -46,7 +46,8 @@ void ArrayType::stringify(std::ostream& ss, } static ID getArrayID(Context* context) { - return parsing::getSymbolFromTopLevelModule(context, "ChapelArray", "_array"); + return parsing::getSymbolIdFromTopLevelModule(context, "ChapelArray", + "_array"); } const owned& diff --git a/frontend/lib/types/BasicClassType.cpp b/frontend/lib/types/BasicClassType.cpp index 82f4269bb25c..0c5d9ce0fe96 100644 --- a/frontend/lib/types/BasicClassType.cpp +++ b/frontend/lib/types/BasicClassType.cpp @@ -65,8 +65,8 @@ BasicClassType::getRootClassType(Context* context) { const BasicClassType* BasicClassType::getReduceScanOpType(Context* context) { - auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelReduce", "ReduceScanOp"); - auto name = id.symbolName(context); + auto [id, name] = parsing::getSymbolFromTopLevelModule( + context, "ChapelReduce", "ReduceScanOp"); auto objectType = getRootClassType(context); return getBasicClassType(context, id, name, diff --git a/frontend/lib/types/CPtrType.cpp b/frontend/lib/types/CPtrType.cpp index d1e6116a029b..f510086be5d0 100644 --- a/frontend/lib/types/CPtrType.cpp +++ b/frontend/lib/types/CPtrType.cpp @@ -82,7 +82,8 @@ const CPtrType* CPtrType::getCVoidPtrType(Context* context) { const ID& CPtrType::getId(Context* context) { QUERY_BEGIN(getId, context); - ID result = parsing::getSymbolFromTopLevelModule(context, "CTypes", "c_ptr"); + ID result = + parsing::getSymbolIdFromTopLevelModule(context, "CTypes", "c_ptr"); return QUERY_END(result); } @@ -97,7 +98,8 @@ const CPtrType* CPtrType::withoutConst(Context* context) const { const ID& CPtrType::getConstId(Context* context) { QUERY_BEGIN(getConstId, context); - ID result = parsing::getSymbolFromTopLevelModule(context, "CTypes", "c_ptrConst"); + ID result = + parsing::getSymbolIdFromTopLevelModule(context, "CTypes", "c_ptrConst"); return QUERY_END(result); } diff --git a/frontend/lib/types/CompositeType.cpp b/frontend/lib/types/CompositeType.cpp index bca5a9439574..69d5c7deaa96 100644 --- a/frontend/lib/types/CompositeType.cpp +++ b/frontend/lib/types/CompositeType.cpp @@ -150,31 +150,33 @@ void CompositeType::stringify(std::ostream& ss, } const RecordType* CompositeType::getStringType(Context* context) { - auto id = parsing::getSymbolFromTopLevelModule(context, "String", "_string"); + auto id = + parsing::getSymbolIdFromTopLevelModule(context, "String", "_string"); + // note no underscoe prefix auto name = UniqueString::get(context, "string"); return RecordType::get(context, id, name, - /* instantiatedFrom */ nullptr, - SubstitutionsMap()); + /* instantiatedFrom */ nullptr, SubstitutionsMap()); } const RecordType* CompositeType::getRangeType(Context* context) { - auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelRange", "_range"); - auto name = id.symbolName(context); + auto [id, name] = + parsing::getSymbolFromTopLevelModule(context, "ChapelRange", "_range"); return RecordType::get(context, id, name, - /* instantiatedFrom */ nullptr, - SubstitutionsMap()); + /* instantiatedFrom */ nullptr, SubstitutionsMap()); } const RecordType* CompositeType::getBytesType(Context* context) { - auto id = parsing::getSymbolFromTopLevelModule(context, "Bytes", "_bytes"); + auto id = parsing::getSymbolIdFromTopLevelModule(context, "Bytes", "_bytes"); + // note no underscoe prefix auto name = UniqueString::get(context, "bytes"); return RecordType::get(context, id, name, - /* instantiatedFrom */ nullptr, - SubstitutionsMap()); + /* instantiatedFrom */ nullptr, SubstitutionsMap()); } const RecordType* CompositeType::getLocaleType(Context* context) { - auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelLocale", "_locale"); + auto id = parsing::getSymbolIdFromTopLevelModule(context, "ChapelLocale", + "_locale"); + // note no underscoe prefix auto name = UniqueString::get(context, "locale"); return RecordType::get(context, id, name, /* instantiatedFrom */ nullptr, @@ -190,20 +192,20 @@ const RecordType* CompositeType::getLocaleIDType(Context* context) { } const RecordType* CompositeType::getDistributionType(Context* context) { - auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelDistribution", - "_distribution"); - auto name = id.symbolName(context); + auto [id, name] = parsing::getSymbolFromTopLevelModule( + context, "ChapelDistribution", "_distribution"); return RecordType::get(context, id, name, /* instantiatedFrom */ nullptr, SubstitutionsMap()); } static const ID getOwnedRecordId(Context* context) { - return parsing::getSymbolFromTopLevelModule(context, "OwnedObject", "_owned"); + return parsing::getSymbolIdFromTopLevelModule(context, "OwnedObject", + "_owned"); } static const ID getSharedRecordId(Context* context) { - return parsing::getSymbolFromTopLevelModule(context, "SharedObject", - "_shared"); + return parsing::getSymbolIdFromTopLevelModule(context, "SharedObject", + "_shared"); } static const RecordType* tryCreateManagerRecord(Context* context, @@ -284,8 +286,8 @@ bool CompositeType::isMissingBundledClassType(Context* context, ID id) { } const ClassType* CompositeType::getErrorType(Context* context) { - auto id = parsing::getSymbolFromTopLevelModule(context, "Errors", "Error"); - auto name = id.symbolName(context); + auto [id, name] = + parsing::getSymbolFromTopLevelModule(context, "Errors", "Error"); auto dec = ClassTypeDecorator(ClassTypeDecorator::GENERIC_NONNIL); auto bct = BasicClassType::get(context, id, name, diff --git a/frontend/lib/types/DomainType.cpp b/frontend/lib/types/DomainType.cpp index c58a146cb0f5..5b8ff774a1bb 100644 --- a/frontend/lib/types/DomainType.cpp +++ b/frontend/lib/types/DomainType.cpp @@ -54,7 +54,8 @@ void DomainType::stringify(std::ostream& ss, } static ID getDomainID(Context* context) { - return parsing::getSymbolFromTopLevelModule(context, "ChapelDomain", "_domain"); + return parsing::getSymbolIdFromTopLevelModule(context, "ChapelDomain", + "_domain"); } const owned& @@ -139,9 +140,8 @@ const QualifiedType& DomainType::getDefaultDistType(Context* context) { QualifiedType result; - auto id = parsing::getSymbolFromTopLevelModule(context, "DefaultRectangular", - "defaultDist"); - auto name = id.symbolName(context); + auto [id, name] = parsing::getSymbolFromTopLevelModule( + context, "DefaultRectangular", "defaultDist"); auto modName = ID::parentSymbolPath(context, id.symbolPath()); if (auto mod = parsing::getToplevelModule(context, modName)) { diff --git a/frontend/lib/types/EnumType.cpp b/frontend/lib/types/EnumType.cpp index 52cd457f43c6..7a4eb12e98b0 100644 --- a/frontend/lib/types/EnumType.cpp +++ b/frontend/lib/types/EnumType.cpp @@ -61,14 +61,12 @@ const EnumType* EnumType::get(Context* context, ID id, UniqueString name) { } const EnumType* EnumType::getBoundKindType(Context* context) { - auto name = UniqueString::get(context, "boundKind"); - auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelRange", "boundKind"); + auto [id, name] = parsing::getSymbolFromTopLevelModule(context, "ChapelRange", "boundKind"); return EnumType::get(context, id, name); } const EnumType* EnumType::getIterKindType(Context* context) { - auto name = UniqueString::get(context, "iterKind"); - auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelBase", "iterKind"); + auto [id, name] = parsing::getSymbolFromTopLevelModule(context, "ChapelBase", "iterKind"); return EnumType::get(context, id, name); } diff --git a/frontend/lib/types/TupleType.cpp b/frontend/lib/types/TupleType.cpp index 0bd206bc9331..5e3fa7f865cf 100644 --- a/frontend/lib/types/TupleType.cpp +++ b/frontend/lib/types/TupleType.cpp @@ -100,8 +100,8 @@ TupleType::getTupleType(Context* context, const TupleType* instantiatedFrom, QUERY_BEGIN(getTupleType, context, instantiatedFrom, subs, isVarArgTuple); - auto id = parsing::getSymbolFromTopLevelModule(context, "ChapelTuple", "_tuple"); - auto name = id.symbolName(context); + auto [id, name] = + parsing::getSymbolFromTopLevelModule(context, "ChapelTuple", "_tuple"); auto result = toOwned(new TupleType(id, name, instantiatedFrom, std::move(subs), isVarArgTuple)); From f47c9721ced0a2cb8701a9167f7b33a83b1ae5d4 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 10:54:49 -0700 Subject: [PATCH 53/65] Remove _domain type alias Signed-off-by: Anna Rift --- frontend/lib/types/Type.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/lib/types/Type.cpp b/frontend/lib/types/Type.cpp index ea474bdad5c5..6d13e0fbba2b 100644 --- a/frontend/lib/types/Type.cpp +++ b/frontend/lib/types/Type.cpp @@ -128,7 +128,6 @@ void Type::gatherBuiltins(Context* context, gatherType(context, map, "Error", CompositeType::getErrorType(context)); gatherType(context, map, "domain", DomainType::getGenericDomainType(context)); - gatherType(context, map, "_domain", DomainType::getGenericDomainType(context)); gatherType(context, map, "class", AnyClassType::get(context)); auto genericBorrowed = ClassType::get(context, AnyClassType::get(context), nullptr, ClassTypeDecorator(ClassTypeDecorator::BORROWED)); From f7241a7a9496d6e3f5fefcab0bd84884dc8ac1f5 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 11:33:20 -0700 Subject: [PATCH 54/65] Use buildStdContext helper in domain tests Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 2fd7dcb26f7d..1e2d35d4d8fa 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -40,11 +40,8 @@ static void testRectangular(std::string domainType, int rank, std::string idxType, std::string strides) { - Context::Configuration config; - config.chplHome = getenv("CHPL_HOME"); - Context ctx(config); - Context* context = &ctx; - setupModuleSearchPaths(context, false, false, {}, {}); + auto ctx = buildStdContext(); + auto context = ctx.get(); ErrorGuard guard(context); std::string program = @@ -379,11 +376,8 @@ static void testBadDomain(std::string domainType) { // With standard modules { - Context::Configuration config; - config.chplHome = getenv("CHPL_HOME"); - Context ctx(config); - Context* context = &ctx; - setupModuleSearchPaths(context, false, false, {}, {}); + auto ctx = buildStdContext(); + auto context = ctx.get(); ErrorGuard guard(context); testBadDomainHelper(domainType, context, guard); From 4c87aea273ff356e7464be4d08eab6ed07a8fc48 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 11:36:46 -0700 Subject: [PATCH 55/65] Use realizeErrors properly in array/domain tests Signed-off-by: Anna Rift --- frontend/test/resolution/testArrays.cpp | 3 +-- frontend/test/resolution/testDomains.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/test/resolution/testArrays.cpp b/frontend/test/resolution/testArrays.cpp index b4db39ec1a31..32630f8e5e90 100644 --- a/frontend/test/resolution/testArrays.cpp +++ b/frontend/test/resolution/testArrays.cpp @@ -140,8 +140,7 @@ module M { assert(call->byAst(ETGood).type().type() == AType.type()); } - assert(guard.errors().size() == 0); - guard.realizeErrors(context); + assert(guard.realizeErrors() == 0); std::string arrayText; arrayText += "[" + domainType + "] " + eltType; diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 1e2d35d4d8fa..088ad3bfbbac 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -152,7 +152,7 @@ module M { assert(call->byAst(CT).type().type() == dType); } - assert(guard.errors().size() == 0); + assert(guard.realizeErrors() == 0); printf("Success: %s\n", domainType.c_str()); } From 255847480fdcc26113af86e795fbee2dc8192d91 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 11:48:45 -0700 Subject: [PATCH 56/65] Re-enable rectangular domain canpass and index(D) tests They now use the standard ChapelDomain rather than minimal version. Associative cases are still disabled. Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 138 ++++++++++++----------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 088ad3bfbbac..2926685fd73e 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -254,80 +254,79 @@ module M { // printf("Success: %s\n", domainType.c_str()); // } -// static void testBadPass(std::string argType, std::string actualType) { -// // Ensure that we can't, e.g., pass a domain(1) to a domain(2) -// Context ctx; -// Context* context = &ctx; -// ErrorGuard guard(context); +static void testBadPass(std::string argType, std::string actualType) { + // Ensure that we can't, e.g., pass a domain(1) to a domain(2) + auto ctx = buildStdContext(); + auto context = ctx.get(); + ErrorGuard guard(context); -// std::string program = DomainModule + -// R"""( -// module M { -// use ChapelDomain; - -// proc foo(arg: )""" + argType + R"""() { -// return 42; -// } + std::string program = +R"""( +module M { + proc foo(arg: )""" + argType + R"""() { + return 42; + } -// var d : )""" + actualType + R"""(; -// var c_ret = foo(d); -// } -// )"""; -// // TODO: generic checks + var d : )""" + actualType + R"""(; + var c_ret = foo(d); +} +)"""; + // TODO: generic checks -// auto path = UniqueString::get(context, "input.chpl"); -// setFileText(context, path, std::move(program)); + auto path = UniqueString::get(context, "input.chpl"); + setFileText(context, path, std::move(program)); -// const ModuleVec& vec = parseToplevel(context, path); -// const Module* m = vec[1]; + const ModuleVec& vec = parseToplevel(context, path); + const Module* m = vec[0]; -// const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); + const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); -// auto c_ret = findOnlyNamed(m, "c_ret")->toVariable(); -// assert(rr.byAst(c_ret).type().isErroneousType()); -// assert(guard.errors().size() == 1); -// auto& e = guard.errors()[0]; -// assert(e->type() == chpl::NoMatchingCandidates); + auto c_ret = findOnlyNamed(m, "c_ret")->toVariable(); + assert(rr.byAst(c_ret).type().isErroneousType()); + assert(guard.errors().size() == 1); + auto& e = guard.errors()[0]; + assert(e->type() == chpl::NoMatchingCandidates); -// printf("Success: cannot pass %s to %s\n", actualType.c_str(), argType.c_str()); + printf("Success: cannot pass %s to %s\n", actualType.c_str(), argType.c_str()); -// // 'clear' rather than 'realize' to simplify test output -// guard.clearErrors(); -// } + // 'clear' rather than 'realize' to simplify test output + guard.clearErrors(); +} -// static void testIndex(std::string domainType, -// std::string expectedType) { -// Context ctx; -// Context* context = &ctx; -// ErrorGuard guard(context); +static void testIndex(std::string domainType, + std::string expectedType) { + auto ctx = buildStdContext(); + auto context = ctx.get(); + ErrorGuard guard(context); -// std::string program = DomainModule + ArrayModule + -// R"""( -// module M { -// use ChapelDomain; -// use ChapelArray; + std::string program = +R"""( +module M { + var d : )""" + domainType + R"""(; + type t = )""" + expectedType + R"""(; + type i = index(d); -// var d : )""" + domainType + R"""(; -// type t = )""" + expectedType + R"""(; -// type i = index(d); + param equal = i == t; +} +)"""; -// param equal = i == t; -// } -// )"""; + auto path = UniqueString::get(context, "input.chpl"); + setFileText(context, path, std::move(program)); -// auto path = UniqueString::get(context, "input.chpl"); -// setFileText(context, path, std::move(program)); + const ModuleVec& vec = parseToplevel(context, path); + const Module* m = vec[0]; -// const ModuleVec& vec = parseToplevel(context, path); -// const Module* m = vec[2]; + const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); -// const ResolutionResultByPostorderID& rr = resolveModule(context, m->id()); -// findVarType(m, rr, "d").dump(); -// findVarType(m, rr, "t").dump(); -// findVarType(m, rr, "i").dump(); + assert(!findVarType(m, rr, "d").isUnknownOrErroneous()); + assert(!findVarType(m, rr, "t").isUnknownOrErroneous()); + assert(!findVarType(m, rr, "i").isUnknownOrErroneous()); -// assert(findVarType(m, rr, "equal").isParamTrue()); -// } + assert(findVarType(m, rr, "equal").isParamTrue()); + + printf("Success: index(%s) == %s\n", domainType.c_str(), + expectedType.c_str()); +} static void testBadDomainHelper(std::string domainType, Context* context, ErrorGuard& guard) { @@ -356,9 +355,6 @@ module M { auto& e = guard.errors()[0]; assert(e->type() == chpl::InvalidDomainCall); - printf("Success: cannot resolve incorrect domain type expression %s\n", - domainType.c_str()); - guard.clearErrors(); } @@ -382,6 +378,9 @@ static void testBadDomain(std::string domainType) { testBadDomainHelper(domainType, context, guard); } + + printf("Success: cannot resolve %s\n", + domainType.c_str()); } int main() { @@ -397,16 +396,19 @@ int main() { // testAssociative("domain(int, false)", "int", false); // testAssociative("domain(string)", "string", true); - // TODO: re-enable - // testBadPass("domain(1)", "domain(2)"); + testBadPass("domain(1)", "domain(2)"); + testBadPass("domain(1, int(16))", "domain(1, int(8))"); + testBadPass("domain(1, int(8))", "domain(1, int(16))"); + testBadPass("domain(1, strides=strideKind.negOne)", "domain(1, strides=strideKind.one)"); + // TODO: re-enable associative badPass // testBadPass("domain(int)", "domain(string)"); // testBadPass("domain(1)", "domain(int)"); - // TODO: re-enable indexes - // testIndex("domain(1)", "int"); - // testIndex("domain(2)", "2*int"); - // testIndex("domain(1, bool)", "bool"); - // testIndex("domain(2, bool)", "2*bool"); + testIndex("domain(1)", "int"); + testIndex("domain(2)", "2*int"); + testIndex("domain(1, bool)", "bool"); + testIndex("domain(2, bool)", "2*bool"); + // TODO: re-enable associative indexes // testIndex("domain(int)", "int"); // testIndex("domain(string)", "string"); From 42391202b927a44f27637e6eaab265871e27c6e9 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 11:52:35 -0700 Subject: [PATCH 57/65] Remove unused minimal testing version of ChapelDomain Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 4 +-- frontend/test/test-minimal-modules.h | 39 ------------------------ 2 files changed, 1 insertion(+), 42 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index 2926685fd73e..c355601dc1de 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -164,11 +164,9 @@ module M { // Context* context = &ctx; // ErrorGuard guard(context); -// std::string program = DomainModule + +// std::string program = // R"""( // module M { -// use ChapelDomain; - // var d : )""" + domainType + R"""(; // type ig = )""" + idxType + R"""(; diff --git a/frontend/test/test-minimal-modules.h b/frontend/test/test-minimal-modules.h index b416843e66f8..1510abdf165d 100644 --- a/frontend/test/test-minimal-modules.h +++ b/frontend/test/test-minimal-modules.h @@ -22,45 +22,6 @@ #include -static std::string DomainModule = -R"""( -module ChapelDomain { - record _domain { - var _pid: int; - var _instance; - var _unowned:bool; - } - - proc type _domain.static_type(param rank : int, type idxType=int, param stridable: bool = false) type { - return __primitive("static domain type", rank, idxType, stridable); - } - - proc type _domain.static_type(type idxType, param parSafe: bool = true) type { - return __primitive("static domain type", idxType, parSafe); - } - - proc computeIndexType(arg: domain) type { - if arg.isRectangular() { - if arg.rank == 1 then return arg.idxType; - else return arg.rank*arg.idxType; - } else { - return arg.idxType; - } - } - - iter _domain.these() { - var ret : computeIndexType(this); - yield ret; - } - - // Prove that fields and methods on '_domain' work - proc _domain.pid() { - return _pid; - } -} -)"""; - - static std::string ArrayModule = R"""( module ChapelArray { From f9c1d7b348bac5d8168661e4e40eb468225b0699 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 12:42:51 -0700 Subject: [PATCH 58/65] Reuse context in testDomains for performance Signed-off-by: Anna Rift --- frontend/test/resolution/testDomains.cpp | 109 +++++++++++++---------- 1 file changed, 62 insertions(+), 47 deletions(-) diff --git a/frontend/test/resolution/testDomains.cpp b/frontend/test/resolution/testDomains.cpp index c355601dc1de..28c9b5b17fce 100644 --- a/frontend/test/resolution/testDomains.cpp +++ b/frontend/test/resolution/testDomains.cpp @@ -36,12 +36,13 @@ static QualifiedType findVarType(const Module* m, return rr.byAst(var).type(); } -static void testRectangular(std::string domainType, +static void testRectangular(Context* context, + std::string domainType, int rank, std::string idxType, std::string strides) { - auto ctx = buildStdContext(); - auto context = ctx.get(); + context->advanceToNextRevision(false); + setupModuleSearchPaths(context, false, false, {}, {}); ErrorGuard guard(context); std::string program = @@ -157,11 +158,12 @@ module M { printf("Success: %s\n", domainType.c_str()); } -// static void testAssociative(std::string domainType, +// static void testAssociative(Context* context, +// std::string domainType, // std::string idxType, // bool parSafe) { -// Context ctx; -// Context* context = &ctx; +// context->advanceToNextRevision(false); +// setupModuleSearchPaths(context, false, false, {}, {}); // ErrorGuard guard(context); // std::string program = @@ -252,10 +254,11 @@ module M { // printf("Success: %s\n", domainType.c_str()); // } -static void testBadPass(std::string argType, std::string actualType) { +static void testBadPass(Context* context, std::string argType, + std::string actualType) { // Ensure that we can't, e.g., pass a domain(1) to a domain(2) - auto ctx = buildStdContext(); - auto context = ctx.get(); + context->advanceToNextRevision(false); + setupModuleSearchPaths(context, false, false, {}, {}); ErrorGuard guard(context); std::string program = @@ -291,10 +294,11 @@ module M { guard.clearErrors(); } -static void testIndex(std::string domainType, +static void testIndex(Context* context, + std::string domainType, std::string expectedType) { - auto ctx = buildStdContext(); - auto context = ctx.get(); + context->advanceToNextRevision(false); + setupModuleSearchPaths(context, false, false, {}, {}); ErrorGuard guard(context); std::string program = @@ -322,6 +326,8 @@ module M { assert(findVarType(m, rr, "equal").isParamTrue()); + // assert(guard.realizeErrors() == 0); + printf("Success: index(%s) == %s\n", domainType.c_str(), expectedType.c_str()); } @@ -358,7 +364,7 @@ module M { // Ensure we gracefully error for bad domain type expressions, with or without // the standard modules available. -static void testBadDomain(std::string domainType) { +static void testBadDomain(Context* contextWithStd, std::string domainType) { // Without standard modules { Context ctx; @@ -370,11 +376,11 @@ static void testBadDomain(std::string domainType) { // With standard modules { - auto ctx = buildStdContext(); - auto context = ctx.get(); - ErrorGuard guard(context); + contextWithStd->advanceToNextRevision(false); + setupModuleSearchPaths(contextWithStd, false, false, {}, {}); + ErrorGuard guard(contextWithStd); - testBadDomainHelper(domainType, context, guard); + testBadDomainHelper(domainType, contextWithStd, guard); } printf("Success: cannot resolve %s\n", @@ -382,40 +388,49 @@ static void testBadDomain(std::string domainType) { } int main() { - testRectangular("domain(1)", 1, "int", "one"); - testRectangular("domain(2)", 2, "int", "one"); - testRectangular("domain(1, strides=strideKind.one)", 1, "int", "one"); - testRectangular("domain(2, int(8))", 2, "int(8)", "one"); - testRectangular("domain(3, int(16), strideKind.negOne)", 3, "int(16)", "negOne"); - testRectangular("domain(strides=strideKind.negative, idxType=int, rank=1)", 1, "int", "negative"); + // Set up context with standard modules, re-used between tests for + // performance. + auto ctx = buildStdContext(); + auto context = ctx.get(); + + testRectangular(context, "domain(1)", 1, "int", "one"); + testRectangular(context, "domain(2)", 2, "int", "one"); + testRectangular(context, "domain(1, strides=strideKind.one)", 1, "int", "one"); + testRectangular(context, "domain(2, int(8))", 2, "int(8)", "one"); + testRectangular(context, "domain(3, int(16), strideKind.negOne)", 3, "int(16)", "negOne"); + testRectangular(context, "domain(strides=strideKind.negative, idxType=int, rank=1)", 1, "int", "negative"); + context->collectGarbage(); // TODO: re-enable associative - // testAssociative("domain(int)", "int", true); - // testAssociative("domain(int, false)", "int", false); - // testAssociative("domain(string)", "string", true); - - testBadPass("domain(1)", "domain(2)"); - testBadPass("domain(1, int(16))", "domain(1, int(8))"); - testBadPass("domain(1, int(8))", "domain(1, int(16))"); - testBadPass("domain(1, strides=strideKind.negOne)", "domain(1, strides=strideKind.one)"); + // testAssociative(context, "domain(int)", "int", true); + // testAssociative(context, "domain(int, false)", "int", false); + // testAssociative(context, "domain(string)", "string", true); + // context->collectGarbage(); + + testBadPass(context, "domain(1)", "domain(2)"); + testBadPass(context, "domain(1, int(16))", "domain(1, int(8))"); + testBadPass(context, "domain(1, int(8))", "domain(1, int(16))"); + testBadPass(context, "domain(1, strides=strideKind.negOne)", "domain(1, strides=strideKind.one)"); // TODO: re-enable associative badPass - // testBadPass("domain(int)", "domain(string)"); - // testBadPass("domain(1)", "domain(int)"); - - testIndex("domain(1)", "int"); - testIndex("domain(2)", "2*int"); - testIndex("domain(1, bool)", "bool"); - testIndex("domain(2, bool)", "2*bool"); + // testBadPass(context, "domain(int)", "domain(string)"); + // testBadPass(context, "domain(1)", "domain(int)"); + context->collectGarbage(); + + testIndex(context, "domain(1)", "int"); + testIndex(context, "domain(2)", "2*int"); + testIndex(context, "domain(1, bool)", "bool"); + testIndex(context, "domain(2, bool)", "2*bool"); // TODO: re-enable associative indexes - // testIndex("domain(int)", "int"); - // testIndex("domain(string)", "string"); - - testBadDomain("domain()"); - testBadDomain("domain(1, 2, 3, 4)"); - testBadDomain("domain(\"asdf\")"); - testBadDomain("domain(\"asdf\", \"asdf2\")"); - testBadDomain("domain(1, \"asdf\")"); - testBadDomain("domain(1, int, \"asdf\")"); + // testIndex(context, "domain(int)", "int"); + // testIndex(context, "domain(string)", "string"); + context->collectGarbage(); + + testBadDomain(context, "domain()"); + testBadDomain(context, "domain(1, 2, 3, 4)"); + testBadDomain(context, "domain(\"asdf\")"); + testBadDomain(context, "domain(\"asdf\", \"asdf2\")"); + testBadDomain(context, "domain(1, \"asdf\")"); + testBadDomain(context, "domain(1, int, \"asdf\")"); return 0; } From d6c25fc2897f5bc9f8662a32fb564e9cbd6f7768 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 12:59:03 -0700 Subject: [PATCH 59/65] Refactor getDefaultDistType to not create meaningless ID Signed-off-by: Anna Rift --- frontend/include/chpl/framework/all-global-strings.h | 1 + frontend/lib/types/DomainType.cpp | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/frontend/include/chpl/framework/all-global-strings.h b/frontend/include/chpl/framework/all-global-strings.h index 2fe83685cf2b..cd32baa7ab9f 100644 --- a/frontend/include/chpl/framework/all-global-strings.h +++ b/frontend/include/chpl/framework/all-global-strings.h @@ -43,6 +43,7 @@ X(c_ptr , "c_ptr") X(c_ptrConst , "c_ptrConst") X(c_char , "c_char") X(class_ , "class") +X(defaultDist , "defaultDist") X(deinit , "deinit") X(deserialize , "deserialize") X(dmapped , "dmapped") diff --git a/frontend/lib/types/DomainType.cpp b/frontend/lib/types/DomainType.cpp index 5b8ff774a1bb..f51adb8e5e7f 100644 --- a/frontend/lib/types/DomainType.cpp +++ b/frontend/lib/types/DomainType.cpp @@ -140,14 +140,11 @@ const QualifiedType& DomainType::getDefaultDistType(Context* context) { QualifiedType result; - auto [id, name] = parsing::getSymbolFromTopLevelModule( - context, "DefaultRectangular", "defaultDist"); - auto modName = ID::parentSymbolPath(context, id.symbolPath()); - - if (auto mod = parsing::getToplevelModule(context, modName)) { + if (auto mod = parsing::getToplevelModule( + context, UniqueString::get(context, "DefaultRectangular"))) { for (auto stmt : mod->children()) { auto decl = stmt->toNamedDecl(); - if (decl && decl->name() == name) { + if (decl && decl->name() == USTR("defaultDist")) { auto res = resolution::resolveModuleStmt(context, stmt->id()); result = res.byId(stmt->id()).type(); } From aebf86faa9ef10790c4e1185aa567b350b33de43 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Fri, 4 Oct 2024 13:02:05 -0700 Subject: [PATCH 60/65] Remove misleading comment in minimal ChapelArray Signed-off-by: Anna Rift --- frontend/test/test-minimal-modules.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/test/test-minimal-modules.h b/frontend/test/test-minimal-modules.h index 1510abdf165d..98c9c0a59e94 100644 --- a/frontend/test/test-minimal-modules.h +++ b/frontend/test/test-minimal-modules.h @@ -60,9 +60,10 @@ module ChapelArray { proc chpl__buildIndexType(d: domain) type do return chpl__buildIndexType(d.rank, d.idxType); - // Module code needed to avoid fatal errors in resolution param nullPid = -1; + proc _isPrivatized(value) param do return false; + record dmap { } } )"""; From 5451a8c95cc827c6f9d9f779ffa7f17bc1a8274e Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 7 Oct 2024 13:09:36 -0700 Subject: [PATCH 61/65] Fix weird indentation Signed-off-by: Anna Rift --- frontend/lib/parsing/parsing-queries.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/lib/parsing/parsing-queries.cpp b/frontend/lib/parsing/parsing-queries.cpp index 74cdfd7909d4..2c1e665a7e14 100644 --- a/frontend/lib/parsing/parsing-queries.cpp +++ b/frontend/lib/parsing/parsing-queries.cpp @@ -1110,8 +1110,8 @@ const Module* getToplevelModule(Context* context, UniqueString name) { } ID getSymbolIdFromTopLevelModule(Context* context, - const char* modName, - const char* symName) { + const char* modName, + const char* symName) { std::ignore = getToplevelModule(context, UniqueString::get(context, modName)); // Performance: this has to concatenate the two strings at runtime. From 50f3e0788a758014dde01a5b3b75b8fb23b93789 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 7 Oct 2024 13:13:24 -0700 Subject: [PATCH 62/65] Add BaseSparseDom in BaseDom subclasses list Signed-off-by: Anna Rift --- frontend/lib/resolution/InitResolver.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index 24066c3ae13d..c827b1f69b56 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -316,8 +316,10 @@ static const DomainType* domainTypeFromSubsHelper( idxType, strides); } else if (baseDom->name() == "BaseAssociativeDom") { // TODO: support associative domains + } else if (baseDom->name() == "BaseSparseDom") { + // TODO: support sparse domains } else { - CHPL_ASSERT(false && "Not handled!"); + CHPL_ASSERT(false && "unexpected type of domain"); } } } From 5390fffdf03cdb16f36f3cc616bf1bba451b43cb Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 7 Oct 2024 13:26:06 -0700 Subject: [PATCH 63/65] Check domain class IDs rather than names Signed-off-by: Anna Rift --- frontend/lib/resolution/InitResolver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index c827b1f69b56..6bb0eb251e38 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -297,7 +297,7 @@ static const DomainType* domainTypeFromSubsHelper( if (auto baseDom = instanceBct->parentClassType()) { auto& rf = fieldsForTypeDecl(context, baseDom, DefaultsPolicy::IGNORE_DEFAULTS); - if (baseDom->name() == "BaseRectangularDom") { + if (baseDom->id().symbolPath() == "ChapelDistribution.BaseRectangularDom") { CHPL_ASSERT(rf.numFields() == 3); QualifiedType rank; QualifiedType idxType; @@ -314,9 +314,9 @@ static const DomainType* domainTypeFromSubsHelper( return DomainType::getRectangularType(context, instanceQt, rank, idxType, strides); - } else if (baseDom->name() == "BaseAssociativeDom") { + } else if (baseDom->id().symbolPath() == "ChapelDistribution.BaseAssociativeDom") { // TODO: support associative domains - } else if (baseDom->name() == "BaseSparseDom") { + } else if (baseDom->id().symbolPath() == "ChapelDistribution.BaseSparseDom") { // TODO: support sparse domains } else { CHPL_ASSERT(false && "unexpected type of domain"); From 6770f17baab62f265827f6efff0ac10c0692d3b5 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 7 Oct 2024 13:35:35 -0700 Subject: [PATCH 64/65] Move dmap->_distribution closer to other adjustments Signed-off-by: Anna Rift --- frontend/lib/resolution/Resolver.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 10aa9321933b..bd9c7f9d8d26 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -2147,16 +2147,6 @@ bool Resolver::resolveSpecialNewCall(const Call* call) { auto newExpr = call->calledExpression()->toNew(); auto& re = byPostorder.byAst(call); auto& reNewExpr = byPostorder.byAst(newExpr); - - // Rewrite 'new dmap' to 'new _distribution' - if (auto rt = reNewExpr.type().type()->toRecordType()) { - if (rt->id().symbolPath() == "ChapelArray.dmap") { - reNewExpr.setType(QualifiedType( - reNewExpr.type().kind(), CompositeType::getDistributionType(context), - reNewExpr.type().param())); - } - } - auto qtNewExpr = reNewExpr.type(); @@ -2165,16 +2155,23 @@ bool Resolver::resolveSpecialNewCall(const Call* call) { return true; } - // Remove nilability from e.g., 'new C?()' for the init call (or else it - // will not resolve because the receiver formal is 'nonnil borrowed'). const Type* initReceiverType = qtNewExpr.type(); + if (auto clsType = qtNewExpr.type()->toClassType()) { + // Remove nilability from e.g., 'new C?()' for the init call (or else it + // will not resolve because the receiver formal is 'nonnil borrowed'). + // always set the receiver to be borrowed non-nil b/c we don't want to // call initializers for '_owned' when the receiver is 'owned(MyClass)' auto newDecor = ClassTypeDecorator(ClassTypeDecorator::BORROWED_NONNIL); initReceiverType = clsType->withDecorator(context, newDecor); - CHPL_ASSERT(initReceiverType); + } else if (auto recordType = qtNewExpr.type()->toRecordType()) { + // Rewrite 'new dmap' to 'new _distribution' + if (recordType->id().symbolPath() == "ChapelArray.dmap") { + initReceiverType = CompositeType::getDistributionType(context); + } } + CHPL_ASSERT(initReceiverType); /* auto cls = qtNewExpr.type()->toClassType(); From f8b3d77336ee0106aa2abefdeef02a18fcfdeff8 Mon Sep 17 00:00:00 2001 From: Anna Rift Date: Mon, 7 Oct 2024 13:50:32 -0700 Subject: [PATCH 65/65] Replace assert with returning default value Signed-off-by: Anna Rift --- frontend/lib/resolution/InitResolver.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/lib/resolution/InitResolver.cpp b/frontend/lib/resolution/InitResolver.cpp index 6bb0eb251e38..8261f3f78827 100644 --- a/frontend/lib/resolution/InitResolver.cpp +++ b/frontend/lib/resolution/InitResolver.cpp @@ -319,7 +319,8 @@ static const DomainType* domainTypeFromSubsHelper( } else if (baseDom->id().symbolPath() == "ChapelDistribution.BaseSparseDom") { // TODO: support sparse domains } else { - CHPL_ASSERT(false && "unexpected type of domain"); + // not a recognized domain type + return genericDomain; } } }