@@ -350,11 +350,47 @@ static auto helpExtractFields(ResolutionContext* rc, const BasicClassType* bct,
350
350
return ret;
351
351
}
352
352
353
+ // same as above, but consider parent classes
354
+ template <typename FoundEach, typename ...FieldNames, size_t ... Is>
355
+ static auto helpExtractFieldsHierarchy (ResolutionContext* rc, const BasicClassType* bct, FoundEach& foundEach, std::index_sequence<Is...>, FieldNames... names) {
356
+ typename ImplCreateNTuple<Is...>::type ret;
357
+
358
+ while (bct) {
359
+ auto & rf = fieldsForTypeDecl (rc, bct,
360
+ DefaultsPolicy::IGNORE_DEFAULTS);
361
+ for (int i = 0 ; i < rf.numFields (); i++) {
362
+ ((rf.fieldName (i) == names ?
363
+ (std::get<Is>(ret) = rf.fieldType (i),
364
+ std::get<Is>(foundEach) += 1 ,
365
+ 0 ) : 0 ), ...);
366
+ }
367
+
368
+ bct = bct->parentClassType ();
369
+
370
+ // if we've found all of them, stop
371
+ if ((std::get<Is>(foundEach) && ...)) {
372
+ break ;
373
+ }
374
+ }
375
+
376
+ return ret;
377
+ }
378
+
353
379
template <typename ...FieldNames>
354
380
static auto extractFields (ResolutionContext* rc, const BasicClassType* bct, FieldNames... names) {
355
381
return helpExtractFields (rc, bct, std::make_index_sequence<sizeof ...(FieldNames)>(), names...);
356
382
}
357
383
384
+ // similar to extractFields, but instead of assuming the fields are in the given
385
+ // class, traverse the class hierarchy to find them. Also, the additional
386
+ // foundEach template argument is used to count how many times each field
387
+ // has occurred. This is useful to know when to stop searching, and to
388
+ // issue errors for missing fields.
389
+ template <typename FoundEach, typename ...FieldNames>
390
+ static auto extractFieldsHierarchy (ResolutionContext* rc, const BasicClassType* bct, FoundEach& foundEach, FieldNames... names) {
391
+ return helpExtractFieldsHierarchy (rc, bct, foundEach, std::make_index_sequence<sizeof ...(FieldNames)>(), names...);
392
+ }
393
+
358
394
static std::tuple<QualifiedType, QualifiedType, QualifiedType>
359
395
extractRectangularInfo (ResolutionContext* rc, const BasicClassType* bct) {
360
396
return extractFields (rc, bct, " rank" , " idxType" , " strides" );
@@ -424,60 +460,21 @@ static const ArrayType* arrayTypeFromSubsHelper(
424
460
auto [instanceBct, baseArr] = extractBasicSubclassFromInstance (instanceQt);
425
461
if (!instanceBct || !baseArr) return genericArray;
426
462
427
- if (baseArr->id ().symbolPath () == " ChapelDistribution.BaseRectangularArr" ) {
428
- auto [domInstanceQt] = extractFields (rc, instanceBct, " dom" );
429
- auto domain = domainTypeFromInstance (rc, domInstanceQt);
430
- CHPL_ASSERT (domain);
431
-
432
- auto [eltType] = extractFields (rc, baseArr, " eltType" );
433
- return ArrayType::getArrayType (context, instanceQt,
434
- QualifiedType (QualifiedType::TYPE, domain),
435
- eltType);
436
- } else if (instanceBct->id ().symbolPath () ==
437
- " DefaultAssociative.DefaultAssociativeArr" ||
438
- instanceBct->id ().symbolPath () ==
439
- " ArrayViewReindex.ArrayViewReindexArr" ||
440
- instanceBct->id ().symbolPath () ==
441
- " ArrayViewSlice.ArrayViewSliceArr" ||
442
- instanceBct->id ().symbolPath () ==
443
- " ArrayViewRankChange.ArrayViewRankChangeArr" ) {
444
- auto [domInstanceQt] = extractFields (rc, instanceBct, " dom" );
445
- auto domain = domainTypeFromInstance (rc, domInstanceQt);
446
- CHPL_ASSERT (domain);
447
-
448
- CHPL_ASSERT (baseArr &&
449
- baseArr->id ().symbolPath () == " ChapelDistribution.AbsBaseArr" );
450
- auto [eltType] = extractFields (rc, baseArr, " eltType" );
451
-
452
- return ArrayType::getArrayType (context, instanceQt,
453
- QualifiedType (QualifiedType::TYPE, domain),
454
- eltType);
455
- } else if (baseArr->id ().symbolPath () ==
456
- " ChapelDistribution.BaseSparseArrImpl" ) {
457
- // The Impl doesn't have the data, the parent class does.
458
- auto baseArrSparse = baseArr->parentClassType ();
459
- CHPL_ASSERT (baseArrSparse &&
460
- baseArrSparse->id ().symbolPath () ==
461
- " ChapelDistribution.BaseSparseArr" );
462
- auto absBaseArr = baseArrSparse->parentClassType ();
463
- CHPL_ASSERT (absBaseArr &&
464
- absBaseArr->id ().symbolPath () ==
465
- " ChapelDistribution.AbsBaseArr" );
466
-
467
- auto [domInstanceQt] = extractFields (rc, baseArrSparse," dom" );
468
- auto [eltType] = extractFields (rc, absBaseArr, " eltType" );
469
- auto domain = domainTypeFromInstance (rc, domInstanceQt);
470
- CHPL_ASSERT (domain);
471
-
472
- return ArrayType::getArrayType (context, instanceQt,
473
- QualifiedType (QualifiedType::TYPE, domain),
474
- eltType);
475
- } else {
476
- CHPL_UNIMPL (" unknown kind of array class" );
463
+ auto fieldCounts = std::make_pair (0 , 0 );
464
+ auto [domInstanceQt, eltType] = extractFieldsHierarchy (rc, instanceBct, fieldCounts, " dom" , " eltType" );
465
+
466
+ if (fieldCounts.first == 0 ) {
467
+ rc->context ()->error (instanceBct->id (), " array implementation class doesn't have required field 'dom'" );
477
468
}
469
+ if (fieldCounts.second == 0 ) {
470
+ rc->context ()->error (instanceBct->id (), " array implementation class doesn't have required field 'eltType'" );
471
+ }
472
+
473
+ auto domain = domainTypeFromInstance (rc, domInstanceQt);
478
474
479
- // If we reach here, we weren't able to resolve the array type
480
- return genericArray;
475
+ return ArrayType::getArrayType (context, instanceQt,
476
+ QualifiedType (QualifiedType::TYPE, domain),
477
+ eltType);
481
478
}
482
479
483
480
static const Type* ctFromSubs (ResolutionContext* rc,
0 commit comments