diff options
Diffstat (limited to 'src/compat')
-rw-r--r-- | src/compat/borrow.hpp | 9 | ||||
-rw-r--r-- | src/compat/borrow.py | 18 | ||||
-rw-r--r-- | src/compat/fwd.hpp | 1 | ||||
-rw-r--r-- | src/compat/nullpo.hpp | 2 | ||||
-rw-r--r-- | src/compat/option.hpp | 54 | ||||
-rw-r--r-- | src/compat/option.py | 37 | ||||
-rw-r--r-- | src/compat/option_test.cpp | 37 |
7 files changed, 154 insertions, 4 deletions
diff --git a/src/compat/borrow.hpp b/src/compat/borrow.hpp index 5cb6a7c..0ea6a26 100644 --- a/src/compat/borrow.hpp +++ b/src/compat/borrow.hpp @@ -68,6 +68,15 @@ namespace tmwa static_assert(!std::is_same<T, U>::value, "same check"); return Borrowed<U>(stupid); } + + friend bool operator == (Borrowed l, Borrowed r) + { + return l.stupid == r.stupid; + } + friend bool operator != (Borrowed l, Borrowed r) + { + return !(l == r); + } }; namespace option diff --git a/src/compat/borrow.py b/src/compat/borrow.py new file mode 100644 index 0000000..58cd19b --- /dev/null +++ b/src/compat/borrow.py @@ -0,0 +1,18 @@ +class Borrowed(object): + __slots__ = ('_value') + name = 'tmwa::Borrowed' + enabled = True + + def __init__(self, value): + self._value = value['stupid'] + + def to_string(self): + return self._value + + test_extra = ''' + static int borrow_thingy; + ''' + + tests = [ + ('tmwa::borrow(borrow_thingy)', '<borrow_thingy>'), + ] diff --git a/src/compat/fwd.hpp b/src/compat/fwd.hpp index 7e2be28..c16e196 100644 --- a/src/compat/fwd.hpp +++ b/src/compat/fwd.hpp @@ -28,6 +28,7 @@ namespace tmwa template<class T> class Option; } + using option::Option; template<class T> class Borrowed; diff --git a/src/compat/nullpo.hpp b/src/compat/nullpo.hpp index 5be674a..718c7aa 100644 --- a/src/compat/nullpo.hpp +++ b/src/compat/nullpo.hpp @@ -52,6 +52,8 @@ bool nullpo_chk(const char *file, int line, const char *func, const void *target); template<class T> +bool nullpo_chk(const char *file, int line, const char *func, Borrowed<T> target) = delete; +template<class T> bool nullpo_chk(const char *file, int line, const char *func, T target) { return nullpo_chk(file, line, func, target.operator->()); diff --git a/src/compat/option.hpp b/src/compat/option.hpp index ad83395..27ee0bc 100644 --- a/src/compat/option.hpp +++ b/src/compat/option.hpp @@ -66,6 +66,7 @@ namespace option return rv; } + // TODO all *_or and *_set methods should have a lazy version too template<class T> class Option { @@ -210,6 +211,10 @@ namespace option { return repr.is_some(); } + bool is_none() const + { + return !is_some(); + } template<class F> auto move_map(F&& f) -> Option<decltype(std::forward<F>(f)(std::move(*repr.ptr())))> @@ -262,6 +267,47 @@ namespace option return None; } } + // wanting members is *so* common + template<class M, class B> + Option<M> pmd_get(const M B::*pmd) const + { + if (repr.is_some()) + { + return Some((*repr.ptr()).*pmd); + } + else + { + return None; + } + } + template<class M, class B> + void pmd_set(M B::*pmd, M value) + { + if (repr.is_some()) + { + ((*repr.ptr()).*pmd) = std::move(value); + } + } + template<class M, class B> + Option<M> pmd_pget(const M B::*pmd) const + { + if (repr.is_some()) + { + return Some((**repr.ptr()).*pmd); + } + else + { + return None; + } + } + template<class M, class B> + void pmd_pset(M B::*pmd, M value) + { + if (repr.is_some()) + { + ((**repr.ptr()).*pmd) = std::move(value); + } + } }; template<class T> @@ -371,16 +417,16 @@ namespace option #define TRY_UNWRAP(opt, falsy) \ ({ \ tmwa::option::RefWrapper<decltype((opt))> o = {(opt)}; \ - if (!o.maybe_ref.is_some()) falsy; \ + if (o.maybe_ref.is_none()) falsy; \ tmwa::option::option_unwrap(std::move(o)); \ }).maybe_ref_fun() // immediately preceded by 'if'; not double-eval-safe -#define OPTION_IS_SOME(var, expr) \ - ((expr).is_some()) \ +#define OPTION_IS_SOME(var, expr) \ + ((expr).is_some()) \ WITH_VAR(auto&, var, *(expr).ptr_or(nullptr)) } // namespace option -using option::Option; +//using option::Option; using option::None; using option::Some; } // namespace tmwa diff --git a/src/compat/option.py b/src/compat/option.py new file mode 100644 index 0000000..a410ac8 --- /dev/null +++ b/src/compat/option.py @@ -0,0 +1,37 @@ +class Option(object): + __slots__ = ('_value') + name = 'tmwa::option::Option' + enabled = True + + def __init__(self, value): + self._value = value['repr'] + + def to_string(self): + value = self._value + ty = value.type.template_argument(0) + try: + some = bool(value['_some']) + except gdb.error: + stupider = value['stupider'] + if stupider: + return 'Some<%s>(%s)' % (ty, stupider) + else: + return 'None<%s>' % ty + else: + if some: + data = value['_data'] + data = data.address.cast(ty.pointer()).dereference() + return 'Some<%s>(%s)' % (ty, data) + else: + return 'None<%s>' % ty + + test_extra = ''' + static int option_borrow_thingy; + ''' + + tests = [ + ('tmwa::None<int>()', 'None<int>'), + ('tmwa::Some(1)', 'Some<int>(1)'), + ('tmwa::Option<tmwa::Borrowed<int>>(tmwa::None)', 'None<tmwa::Borrowed<int>>'), + ('tmwa::Some(tmwa::borrow(option_borrow_thingy))', 'regex:Some<tmwa::Borrowed<int>>\(0x[0-9a-f]* <option_borrow_thingy>\)'), + ] diff --git a/src/compat/option_test.cpp b/src/compat/option_test.cpp index d99eda9..b963a29 100644 --- a/src/compat/option_test.cpp +++ b/src/compat/option_test.cpp @@ -255,6 +255,43 @@ TEST(Option, map) } } +TEST(Option, member) +{ + struct Foo + { + int bar = 404; + }; + + Option<Foo> vng = None; + EXPECT_EQ(vng.pmd_get(&Foo::bar).copy_or(42), 42); + Option<Foo> vsg = Some(Foo()); + EXPECT_EQ(vsg.pmd_get(&Foo::bar).copy_or(42), 404); + + Option<Foo> vns = None; + vns.pmd_set(&Foo::bar, 42); + EXPECT_EQ(vns.copy_or(Foo()).bar, 404); + Option<Foo> vss = Some(Foo()); + vss.pmd_set(&Foo::bar, 42); + EXPECT_EQ(vss.copy_or(Foo()).bar, 42); + + Foo foo, alt; + + Option<P<Foo>> png = None; + EXPECT_EQ(png.pmd_pget(&Foo::bar).copy_or(42), 42); + Option<P<Foo>> psg = Some(borrow(foo)); + EXPECT_EQ(psg.pmd_pget(&Foo::bar).copy_or(42), 404); + + Option<P<Foo>> pns = None; + pns.pmd_pset(&Foo::bar, 42); + EXPECT_EQ(pns.copy_or(borrow(alt))->bar, 404); + EXPECT_EQ(foo.bar, 404); + Option<P<Foo>> pss = Some(borrow(foo)); + pss.pmd_pset(&Foo::bar, 42); + EXPECT_EQ(pss.copy_or(borrow(alt))->bar, 42); + EXPECT_EQ(foo.bar, 42); + EXPECT_EQ(alt.bar, 404); +} + #if __cplusplus >= 201300 // c++14 as given by gcc 4.9 # define DECLTYPE_AUTO decltype(auto) #else |