diff options
-rw-r--r-- | src/support/parent_index_iterator.h | 96 | ||||
-rw-r--r-- | src/wasm-type.h | 61 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 17 | ||||
-rw-r--r-- | test/gtest/type-builder.cpp | 68 |
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) { |