summaryrefslogtreecommitdiff
path: root/src/compat
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-10-13 13:16:34 -0700
committerBen Longbons <b.r.longbons@gmail.com>2014-10-13 14:03:46 -0700
commit780a0d771edbe21dcfa3405163ffbdf7f7fa4604 (patch)
treeac202254d015d2a2a28ab5bca60c3f5474d168ba /src/compat
parenta5e0fe8204a8b3299507a645f3479e9ead6c6110 (diff)
downloadtmwa-780a0d771edbe21dcfa3405163ffbdf7f7fa4604.tar.gz
tmwa-780a0d771edbe21dcfa3405163ffbdf7f7fa4604.tar.bz2
tmwa-780a0d771edbe21dcfa3405163ffbdf7f7fa4604.tar.xz
tmwa-780a0d771edbe21dcfa3405163ffbdf7f7fa4604.zip
Convert container lookups to use Option<Borrowed<T>>
Diffstat (limited to 'src/compat')
-rw-r--r--src/compat/borrow.hpp9
-rw-r--r--src/compat/borrow.py18
-rw-r--r--src/compat/fwd.hpp1
-rw-r--r--src/compat/nullpo.hpp2
-rw-r--r--src/compat/option.hpp54
-rw-r--r--src/compat/option.py37
-rw-r--r--src/compat/option_test.cpp37
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