@@ -1243,68 +1243,78 @@ function typeCrefDim
12431243 input SourceInfo info;
12441244 output Dimension dim;
12451245 output TypingError error;
1246+ protected
1247+ list< ComponentRef > crl;
1248+ list< Subscript > subs;
1249+ Integer index, dim_count, dim_total = 0 ;
1250+ InstNode node;
1251+ Component c;
1252+ Type ty;
12461253algorithm
1247- (dim, error) := match cref
1248- case ComponentRef . CREF (node = InstNode . COMPONENT_NODE ())
1249- then typeComponentDim(cref. node, dimIndex, listLength(cref. subscripts), origin, info);
1254+ // TODO: If the cref has subscripts it becomes trickier to correctly calculate
1255+ // the dimension. For now we take the easy way out and just type the
1256+ // whole cref, but doing so might introduce unnecessary cycles.
1257+ if ComponentRef . hasSubscripts(cref) then
1258+ (_, ty) := typeCref(cref, origin, info);
1259+ (dim, error) := nthDimensionBoundsChecked(ty, dimIndex);
1260+ return ;
1261+ end if ;
12501262
1251- else
1252- algorithm
1253- Error . assertion(false , getInstanceName() + " got invalid cref." , sourceInfo());
1254- then
1255- fail();
1263+ // Loop through the cref in reverse, reducing the index by the number of
1264+ // dimensions each component has until we find a component that the index is
1265+ // valid for. This is done even if the index is 0 or negative, since the loop
1266+ // also sums up the total number of dimensions which is needed to give a good
1267+ // error message.
1268+ crl := ComponentRef . toListReverse(cref);
1269+ index := dimIndex;
1270+
1271+ for cr in crl loop
1272+ () := match cr
1273+ case ComponentRef . CREF (node = InstNode . COMPONENT_NODE (), subscripts = subs)
1274+ algorithm
1275+ node := InstNode . resolveOuter(cr. node);
1276+ c := InstNode . component(node);
12561277
1257- end match;
1258- end typeCrefDim;
1278+ dim_count := match c
1279+ case Component . UNTYPED_COMPONENT ()
1280+ algorithm
1281+ dim_count := arrayLength(c. dimensions);
12591282
1260- function typeComponentDim
1261- input InstNode component;
1262- input Integer dimIndex;
1263- input Integer offset "The number of dimensions to skip due to subscripts." ;
1264- input ExpOrigin . Type origin;
1265- input SourceInfo info;
1266- output Dimension dim;
1267- output TypingError error;
1268- protected
1269- InstNode node = InstNode . resolveOuter(component);
1270- Component c = InstNode . component(node);
1271- algorithm
1272- (dim, error) := match c
1273- local
1274- Dimension d;
1275- Type ty;
1276- Integer index, dim_count;
1283+ if index <= dim_count and index > 0 then
1284+ error := TypingError . NO_ERROR ();
1285+ dim := typeDimension(c. dimensions, index, node, c. binding, origin, c. info);
1286+ return ;
1287+ end if ;
1288+ then
1289+ dim_count;
12771290
1278- // An untyped component, get the requested dimension from the component and type it.
1279- case Component . UNTYPED_COMPONENT ()
1280- algorithm
1281- index := dimIndex + offset;
1282- dim_count := arrayLength(c. dimensions);
1291+ case Component . TYPED_COMPONENT ()
1292+ algorithm
1293+ dim_count := Type . dimensionCount(c. ty);
12831294
1284- if index < 1 then
1285- error := TypingError . OUT_OF_BOUNDS (max(dim_count - offset, 0 ));
1286- d := Dimension . UNKNOWN ();
1287- elseif index > dim_count then
1288- node := InstNode . parent(node);
1295+ if index <= dim_count and index > 0 then
1296+ error := TypingError . NO_ERROR ();
1297+ dim := Type . nthDimension(c. ty, index);
1298+ return ;
1299+ end if ;
1300+ then
1301+ dim_count;
12891302
1290- if InstNode . isComponent(node) then
1291- (d, error) := typeComponentDim(node, dimIndex - dim_count, offset - dim_count, origin, info);
1292- else
1293- error := TypingError . OUT_OF_BOUNDS (max(dim_count - offset, 0 ));
1294- d := Dimension . UNKNOWN ();
1295- end if ;
1296- else
1297- error := TypingError . NO_ERROR ();
1298- d := typeDimension(c. dimensions, index, node, c. binding, origin, c. info);
1299- end if ;
1300- then
1301- (d, error);
1303+ else 0 ;
1304+ end match;
1305+
1306+ index := index - dim_count;
1307+ dim_total := dim_total + dim_count;
1308+ then
1309+ ();
13021310
1303- // A typed component, get the requested dimension from its type.
1304- else nthDimensionBoundsChecked(Component . getType(c), dimIndex, offset);
1311+ else ();
1312+ end match;
1313+ end for ;
13051314
1306- end match;
1307- end typeComponentDim;
1315+ dim := Dimension . UNKNOWN ();
1316+ error := TypingError . OUT_OF_BOUNDS (dim_total);
1317+ end typeCrefDim;
13081318
13091319function nthDimensionBoundsChecked
13101320 "Returns the requested dimension from the given type, along with a TypingError
0 commit comments