summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/support/parent_index_iterator.h96
-rw-r--r--src/wasm-type.h61
-rw-r--r--src/wasm/wasm-type.cpp17
-rw-r--r--test/gtest/type-builder.cpp68
4 files changed, 173 insertions, 69 deletions
diff --git a/src/support/parent_index_iterator.h b/src/support/parent_index_iterator.h
new file mode 100644
index 000000000..1375ab204
--- /dev/null
+++ b/src/support/parent_index_iterator.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2022 WebAssembly Community Group participants
+ *
+ * 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 wasm_support_parent_index_iterator_h
+#define wasm_support_parent_index_iterator_h
+
+#include <cstddef>
+#include <iterator>
+
+namespace wasm {
+
+// A helper for defining iterators that contain references to some parent object
+// and indices into that parent object. Provides operator implementations for
+// equality, inequality, index updates, and index differences, but not for
+// dereferencing.
+//
+// Users of this utility should subclass ParentIndexIterator<...> and define the
+// following members in the subclass:
+//
+// - using value_type = ...
+// - using pointer = ...
+// - using reference = ...
+// - reference operator*() const
+//
+// `Parent` is the parent type that the iterator contains and is being indexed
+// into and `Iterator` is the subclass of ParentIndexIterator<...> that is being
+// defined.
+template<typename Parent, typename Iterator> struct ParentIndexIterator {
+ using iterator_category = std::random_access_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+
+ Parent parent;
+ size_t index;
+
+ const Iterator& self() const { return *static_cast<const Iterator*>(this); }
+
+ Iterator& self() { return *static_cast<Iterator*>(this); }
+
+ bool operator==(const Iterator& other) const {
+ return index == other.index && parent == other.parent;
+ }
+ bool operator!=(const Iterator& other) const { return !(*this == other); }
+ Iterator& operator++() {
+ ++index;
+ return self();
+ }
+ Iterator& operator--() {
+ --index;
+ return self();
+ }
+ Iterator operator++(int) {
+ auto it = self();
+ index++;
+ return it;
+ }
+ Iterator operator--(int) {
+ auto it = self();
+ index--;
+ return it;
+ }
+ Iterator& operator+=(difference_type off) {
+ index += off;
+ return self();
+ }
+ Iterator operator+(difference_type off) const {
+ return Iterator(self()) += off;
+ }
+ Iterator& operator-=(difference_type off) {
+ index -= off;
+ return self();
+ }
+ Iterator operator-(difference_type off) const {
+ return Iterator(self()) -= off;
+ }
+ difference_type operator-(const Iterator& other) const {
+ assert(parent == other.parent);
+ return index - other.index;
+ }
+};
+
+} // namespace wasm
+
+#endif // wasm_support_parent_index_iterator_h
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 48b6f2217..c99113317 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -18,6 +18,7 @@
#define wasm_wasm_type_h
#include "support/name.h"
+#include "support/parent_index_iterator.h"
#include "wasm-features.h"
#include <optional>
#include <ostream>
@@ -270,70 +271,24 @@ public:
std::string toString() const;
- struct Iterator {
- // Iterator traits
- using iterator_category = std::random_access_iterator_tag;
+ size_t size() const;
+
+ struct Iterator : ParentIndexIterator<const Type*, Iterator> {
using value_type = Type;
- using difference_type = std::ptrdiff_t;
using pointer = const Type*;
using reference = const Type&;
-
- const Type* parent;
- size_t index;
- Iterator(const Type* parent, size_t index) : parent(parent), index(index) {}
- bool operator==(const Iterator& other) const {
- return index == other.index && parent == other.parent;
- }
- bool operator!=(const Iterator& other) const { return !(*this == other); }
- Iterator& operator++() {
- ++index;
- return *this;
- }
- Iterator& operator--() {
- --index;
- return *this;
- }
- Iterator operator++(int) {
- auto it = *this;
- index++;
- return it;
- }
- Iterator operator--(int) {
- auto it = *this;
- index--;
- return it;
- }
- Iterator& operator+=(difference_type off) {
- index += off;
- return *this;
- }
- Iterator operator+(difference_type off) const {
- return Iterator(*this) += off;
- }
- Iterator& operator-=(difference_type off) {
- index -= off;
- return *this;
- }
- Iterator operator-(difference_type off) const {
- return Iterator(*this) -= off;
- }
- difference_type operator-(const Iterator& other) const {
- assert(parent == other.parent);
- return index - other.index;
- }
- const value_type& operator*() const;
+ reference operator*() const;
};
- Iterator begin() const { return Iterator(this, 0); }
- Iterator end() const;
+ Iterator begin() const { return Iterator{{this, 0}}; }
+ Iterator end() const { return Iterator{{this, size()}}; }
std::reverse_iterator<Iterator> rbegin() const {
return std::make_reverse_iterator(end());
}
std::reverse_iterator<Iterator> rend() const {
return std::make_reverse_iterator(begin());
}
- size_t size() const { return end() - begin(); }
- const Type& operator[](size_t i) const;
+ const Type& operator[](size_t i) const { return *Iterator{{this, i}}; }
};
class HeapType {
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index af382da23..7801cc289 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -1082,13 +1082,13 @@ Type Type::getLeastUpperBound(Type a, Type b) {
return TypeBounder().getLeastUpperBound(a, b);
}
-Type::Iterator Type::end() const {
+size_t Type::size() const {
if (isTuple()) {
- return Iterator(this, getTypeInfo(*this)->tuple.types.size());
+ return getTypeInfo(*this)->tuple.types.size();
} else {
// TODO: unreachable is special and expands to {unreachable} currently.
// see also: https://github.com/WebAssembly/binaryen/issues/3062
- return Iterator(this, size_t(id != Type::none));
+ return size_t(id != Type::none);
}
}
@@ -1096,21 +1096,12 @@ const Type& Type::Iterator::operator*() const {
if (parent->isTuple()) {
return getTypeInfo(*parent)->tuple.types[index];
} else {
- // TODO: see comment in Type::end()
+ // TODO: see comment in Type::size()
assert(index == 0 && parent->id != Type::none && "Index out of bounds");
return *parent;
}
}
-const Type& Type::operator[](size_t index) const {
- if (isTuple()) {
- return getTypeInfo(*this)->tuple.types[index];
- } else {
- assert(index == 0 && "Index out of bounds");
- return *begin();
- }
-}
-
HeapType::HeapType(Signature sig) {
assert(!isTemp(sig.params) && "Leaking temporary type!");
assert(!isTemp(sig.results) && "Leaking temporary type!");
diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp
index 49221f667..1030dc9d4 100644
--- a/test/gtest/type-builder.cpp
+++ b/test/gtest/type-builder.cpp
@@ -17,15 +17,77 @@ protected:
setTypeSystem(originalSystem);
}
};
+
+using TypeTest = TypeSystemTest<TypeSystem::Equirecursive>;
using EquirecursiveTest = TypeSystemTest<TypeSystem::Equirecursive>;
using NominalTest = TypeSystemTest<TypeSystem::Nominal>;
using IsorecursiveTest = TypeSystemTest<TypeSystem::Isorecursive>;
-TEST(TypeBuilder, Growth) {
+TEST_F(TypeTest, TypeBuilderGrowth) {
TypeBuilder builder;
- EXPECT_EQ(builder.size(), size_t{0});
+ EXPECT_EQ(builder.size(), 0u);
builder.grow(3);
- EXPECT_EQ(builder.size(), size_t{3});
+ EXPECT_EQ(builder.size(), 3u);
+}
+
+TEST_F(TypeTest, TypeIterator) {
+ Type none = Type::none;
+ Type i32 = Type::i32;
+ Type i64 = Type::i64;
+ Type f32 = Type::f32;
+ Type f64 = Type::f64;
+ Type tuple = Tuple{i32, i64, f32, f64};
+
+ EXPECT_EQ(none.size(), 0u);
+ EXPECT_EQ(none.begin(), none.end());
+ EXPECT_EQ(none.end() - none.begin(), 0u);
+ EXPECT_EQ(none.begin() + 0, none.end());
+
+ EXPECT_EQ(i32.size(), 1u);
+ EXPECT_NE(i32.begin(), i32.end());
+ EXPECT_EQ(i32.end() - i32.begin(), 1u);
+
+ EXPECT_EQ(*i32.begin(), i32);
+ EXPECT_EQ(i32[0], i32);
+
+ EXPECT_EQ(i32.begin() + 1, i32.end());
+ EXPECT_EQ(i32.end() - 1, i32.begin());
+
+ auto preInc = i32.begin();
+ EXPECT_EQ(++preInc, i32.end());
+ EXPECT_EQ(preInc, i32.end());
+
+ auto postInc = i32.begin();
+ EXPECT_EQ(postInc++, i32.begin());
+ EXPECT_EQ(postInc, i32.end());
+
+ auto preDec = i32.end();
+ EXPECT_EQ(--preDec, i32.begin());
+ EXPECT_EQ(preDec, i32.begin());
+
+ auto postDec = i32.end();
+ EXPECT_EQ(postDec--, i32.end());
+ EXPECT_EQ(postDec, i32.begin());
+
+ EXPECT_EQ(tuple.size(), 4u);
+ EXPECT_NE(tuple.begin(), tuple.end());
+ EXPECT_EQ(tuple.end() - tuple.begin(), 4u);
+
+ EXPECT_EQ(*tuple.begin(), i32);
+ EXPECT_EQ(*(tuple.begin() + 1), i64);
+ EXPECT_EQ(*(tuple.begin() + 2), f32);
+ EXPECT_EQ(*(tuple.begin() + 3), f64);
+ EXPECT_EQ(tuple[0], i32);
+ EXPECT_EQ(tuple[1], i64);
+ EXPECT_EQ(tuple[2], f32);
+ EXPECT_EQ(tuple[3], f64);
+
+ auto reverse = tuple.rbegin();
+ EXPECT_EQ(*reverse++, f64);
+ EXPECT_EQ(*reverse++, f32);
+ EXPECT_EQ(*reverse++, i64);
+ EXPECT_EQ(*reverse++, i32);
+ EXPECT_EQ(reverse, tuple.rend());
}
TEST_F(EquirecursiveTest, Basics) {