@@ -623,23 +623,23 @@ namespace {
623
623
}
624
624
}
625
625
626
- void show (llvm::raw_ostream &buffer, bool normalize = true ) const {
626
+ void show (llvm::raw_ostream &buffer, bool forDisplay = true ) const {
627
627
switch (getKind ()) {
628
628
case SpaceKind::Empty:
629
- if (normalize ) {
629
+ if (forDisplay ) {
630
630
buffer << " _" ;
631
631
} else {
632
632
buffer << " [EMPTY]" ;
633
633
}
634
634
break ;
635
635
case SpaceKind::Disjunct: {
636
- if (normalize ) {
636
+ if (forDisplay ) {
637
637
assert (false && " Attempted to display disjunct to user!" );
638
638
} else {
639
639
buffer << " DISJOIN(" ;
640
640
for (auto &sp : Spaces) {
641
641
buffer << " \n " ;
642
- sp.show (buffer, normalize );
642
+ sp.show (buffer, forDisplay );
643
643
buffer << " |" ;
644
644
}
645
645
buffer << " )" ;
@@ -665,7 +665,7 @@ namespace {
665
665
if (!first) {
666
666
buffer << " , " ;
667
667
}
668
- param.show (buffer, normalize );
668
+ param.show (buffer, forDisplay );
669
669
if (first) {
670
670
first = false ;
671
671
}
@@ -674,7 +674,7 @@ namespace {
674
674
}
675
675
break ;
676
676
case SpaceKind::Type:
677
- if (!normalize ) {
677
+ if (!forDisplay ) {
678
678
getType ()->print (buffer);
679
679
}
680
680
buffer << " _" ;
@@ -937,9 +937,6 @@ namespace {
937
937
for (auto &uncoveredSpace : uncovered.getSpaces ()) {
938
938
SmallVector<Space, 4 > flats;
939
939
flatten (uncoveredSpace, flats);
940
- if (flats.empty ()) {
941
- flats.append ({ uncoveredSpace });
942
- }
943
940
for (auto &flat : flats) {
944
941
OS << tok::kw_case << " " ;
945
942
flat.show (OS);
@@ -956,9 +953,6 @@ namespace {
956
953
for (auto &uncoveredSpace : uncovered.getSpaces ()) {
957
954
SmallVector<Space, 4 > flats;
958
955
flatten (uncoveredSpace, flats);
959
- if (flats.empty ()) {
960
- flats.append ({ uncoveredSpace });
961
- }
962
956
for (auto &flat : flats) {
963
957
Buffer.clear ();
964
958
flat.show (OS);
@@ -972,39 +966,91 @@ namespace {
972
966
private:
973
967
// Recursively unpacks a space of disjunctions or constructor parameters
974
968
// into its component parts such that the resulting array of flattened
975
- // spaces contains no further disjunctions. If there were no disjunctions
976
- // in the starting space, the original space is already flat and the
977
- // returned array of spaces will be empty.
969
+ // spaces contains no further disjunctions. The resulting flattened array
970
+ // will never be empty.
978
971
static void flatten (const Space space, SmallVectorImpl<Space> &flats) {
979
972
switch (space.getKind ()) {
980
973
case SpaceKind::Constructor: {
981
- size_t i = 0 ;
982
- for (auto ¶m : space.getSpaces ()) {
983
- // We're only interested in recursively unpacking constructors and
984
- // disjunctions (booleans are considered constructors).
985
- if (param.getKind () != SpaceKind::Constructor
986
- || param.getKind () != SpaceKind::Disjunct
987
- || param.getKind () != SpaceKind::BooleanConstant)
988
- continue ;
974
+ // Optimization: If this space is just a constructor head, it is already
975
+ // flat.
976
+ if (space.getSpaces ().empty ()) {
977
+ flats.push_back (space);
978
+ return ;
979
+ }
980
+
981
+ // To recursively recover a pattern matrix from a bunch of disjuncts:
982
+ // 1) Unpack the arguments to the constructor under scrutiny.
983
+ // 2) Traverse each argument in turn.
984
+ // 3) Flatten the argument space into a column vector.
985
+ // 4) Extend the existing pattern matrix by a factor of the size of
986
+ // the column vector and copy each previous component.
987
+ // 5) Extend the expanded matrix with multiples of the column vector's
988
+ // components until filled.
989
+ // 6) Wrap each matrix row in the constructor under scrutiny.
990
+ size_t multiplier = 1 ;
991
+ SmallVector<SmallVector<Space, 4 >, 2 > matrix;
992
+ for (auto &subspace : space.getSpaces ()) {
993
+ SmallVector<Space, 4 > columnVect;
994
+ flatten (subspace, columnVect);
995
+
996
+ // Pattern matrices grow quasi-factorially in the size of the
997
+ // input space.
998
+ multiplier *= columnVect.size ();
999
+
1000
+ size_t startSize = matrix.size ();
1001
+ if (!matrix.empty () && columnVect.size () > 1 ) {
1002
+ size_t oldCount = matrix.size ();
1003
+ matrix.reserve (multiplier * oldCount);
1004
+ // Indexing starts at 1, we already have 'startSize'-many elements
1005
+ // in the matrix; multiplies by 1 are no-ops.
1006
+ for (size_t i = 1 ; i < multiplier; ++i) {
1007
+ std::copy_n (matrix.begin (), oldCount, std::back_inserter (matrix));
1008
+ }
1009
+ }
1010
+
1011
+ if (matrix.empty ()) {
1012
+ // Get the empty matrix setup with its starting row vectors.
1013
+ for (auto &vspace : columnVect) {
1014
+ matrix.push_back ({});
1015
+ matrix.back ().push_back (vspace);
1016
+ }
1017
+ } else {
1018
+ // Given a matrix of 'n' rows and '(m-1)*k' columns, to make a
1019
+ // matrix of size 'n' by 'm*k' we need to copy each element of the
1020
+ // column vector into a row 'm' times - as many times as there were
1021
+ // elements of the original matrix before multiplication.
1022
+ size_t stride = multiplier;
1023
+ if (startSize == 1 ) {
1024
+ // Special case: If the column vector is bigger than the matrix
1025
+ // before multiplication, we need to index it linearly
1026
+ stride = 1 ;
1027
+ } else if (columnVect.size () == 1 ) {
1028
+ // Special case: If the column vector has size 1 then we needn't
1029
+ // stride at all.
1030
+ stride = matrix.size ();
1031
+ }
1032
+
1033
+ for (size_t rowIdx = 0 , colIdx = 0 ; rowIdx < matrix.size (); ++rowIdx) {
1034
+ if (rowIdx != 0 && (rowIdx % stride) == 0 ) {
1035
+ colIdx++;
1036
+ }
989
1037
990
- SmallVector<Space, 4 > flattenedParams;
991
- flatten (param, flattenedParams);
992
- for (auto &space : flattenedParams) {
993
- SmallVector<Space, 4 > row (space.getSpaces ().begin (),
994
- space.getSpaces ().end ());
995
- row[i] = space;
996
- Space cs (space.getType (), space.getHead (), row);
997
- flats.push_back (cs);
1038
+ matrix[rowIdx].push_back (columnVect[colIdx]);
1039
+ }
998
1040
}
999
- ++i;
1041
+ }
1042
+
1043
+ // Wrap the matrix rows into this constructor.
1044
+ for (auto &row : matrix) {
1045
+ flats.push_back (Space (space.getType (), space.getHead (), row));
1000
1046
}
1001
1047
}
1002
1048
break ;
1003
1049
case SpaceKind::Disjunct: {
1004
- auto begin = space.getSpaces (). begin ();
1005
- auto end = space. getSpaces (). end () ;
1006
- for (; begin != end; ++begin) {
1007
- flatten (* begin, flats );
1050
+ for ( auto &subspace : space.getSpaces ()) {
1051
+ SmallVector<Space, 4 > buf ;
1052
+ flatten (subspace, buf);
1053
+ flats. append (buf. begin (), buf. end () );
1008
1054
}
1009
1055
}
1010
1056
break ;
@@ -1114,5 +1160,4 @@ void SpaceEngine::Space::dump() const {
1114
1160
llvm::raw_svector_ostream os (buf);
1115
1161
this ->show (os, /* normalize*/ false );
1116
1162
llvm::errs () << buf.str ();
1117
- llvm::errs () << " \n " ;
1118
1163
}
0 commit comments