From 780a0d771edbe21dcfa3405163ffbdf7f7fa4604 Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Mon, 13 Oct 2014 13:16:34 -0700 Subject: Convert container lookups to use Option> --- src/compat/borrow.hpp | 9 ++++++++ src/compat/borrow.py | 18 ++++++++++++++++ src/compat/fwd.hpp | 1 + src/compat/nullpo.hpp | 2 ++ src/compat/option.hpp | 54 ++++++++++++++++++++++++++++++++++++++++++---- src/compat/option.py | 37 +++++++++++++++++++++++++++++++ src/compat/option_test.cpp | 37 +++++++++++++++++++++++++++++++ 7 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 src/compat/borrow.py create mode 100644 src/compat/option.py (limited to 'src/compat') 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::value, "same check"); return Borrowed(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)', ''), + ] 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 Option; } + using option::Option; template 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 @@ -51,6 +51,8 @@ namespace tmwa bool nullpo_chk(const char *file, int line, const char *func, const void *target); +template +bool nullpo_chk(const char *file, int line, const char *func, Borrowed target) = delete; template bool nullpo_chk(const char *file, int line, const char *func, T target) { 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 Option { @@ -210,6 +211,10 @@ namespace option { return repr.is_some(); } + bool is_none() const + { + return !is_some(); + } template auto move_map(F&& f) -> Option(f)(std::move(*repr.ptr())))> @@ -262,6 +267,47 @@ namespace option return None; } } + // wanting members is *so* common + template + Option pmd_get(const M B::*pmd) const + { + if (repr.is_some()) + { + return Some((*repr.ptr()).*pmd); + } + else + { + return None; + } + } + template + void pmd_set(M B::*pmd, M value) + { + if (repr.is_some()) + { + ((*repr.ptr()).*pmd) = std::move(value); + } + } + template + Option pmd_pget(const M B::*pmd) const + { + if (repr.is_some()) + { + return Some((**repr.ptr()).*pmd); + } + else + { + return None; + } + } + template + void pmd_pset(M B::*pmd, M value) + { + if (repr.is_some()) + { + ((**repr.ptr()).*pmd) = std::move(value); + } + } }; template @@ -371,16 +417,16 @@ namespace option #define TRY_UNWRAP(opt, falsy) \ ({ \ tmwa::option::RefWrapper 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()', 'None'), + ('tmwa::Some(1)', 'Some(1)'), + ('tmwa::Option>(tmwa::None)', 'None>'), + ('tmwa::Some(tmwa::borrow(option_borrow_thingy))', 'regex:Some>\(0x[0-9a-f]* \)'), + ] 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 vng = None; + EXPECT_EQ(vng.pmd_get(&Foo::bar).copy_or(42), 42); + Option vsg = Some(Foo()); + EXPECT_EQ(vsg.pmd_get(&Foo::bar).copy_or(42), 404); + + Option vns = None; + vns.pmd_set(&Foo::bar, 42); + EXPECT_EQ(vns.copy_or(Foo()).bar, 404); + Option vss = Some(Foo()); + vss.pmd_set(&Foo::bar, 42); + EXPECT_EQ(vss.copy_or(Foo()).bar, 42); + + Foo foo, alt; + + Option> png = None; + EXPECT_EQ(png.pmd_pget(&Foo::bar).copy_or(42), 42); + Option> psg = Some(borrow(foo)); + EXPECT_EQ(psg.pmd_pget(&Foo::bar).copy_or(42), 404); + + Option> pns = None; + pns.pmd_pset(&Foo::bar, 42); + EXPECT_EQ(pns.copy_or(borrow(alt))->bar, 404); + EXPECT_EQ(foo.bar, 404); + Option> 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 -- cgit v1.2.3-70-g09d2