diff options
author | Ben Longbons <b.r.longbons@gmail.com> | 2015-01-03 21:07:56 -0800 |
---|---|---|
committer | Ben Longbons <b.r.longbons@gmail.com> | 2015-01-03 21:58:26 -0800 |
commit | 00da6b5977574a0564169172227d8aab45be188f (patch) | |
tree | dd52eee506a98e1eb9fcdea52e7db25079a7ad28 /src/compat | |
parent | 4c91abd6a020ee030114ae3f22d8f6066e7528be (diff) | |
download | tmwa-00da6b5977574a0564169172227d8aab45be188f.tar.gz tmwa-00da6b5977574a0564169172227d8aab45be188f.tar.bz2 tmwa-00da6b5977574a0564169172227d8aab45be188f.tar.xz tmwa-00da6b5977574a0564169172227d8aab45be188f.zip |
Switch MATCH to separate begin/end macros
The for loop trick turned out to be very prone to infinite loops
at runtime. It's better to force compiler errors even if it's ugly.
Diffstat (limited to 'src/compat')
-rw-r--r-- | src/compat/attr.hpp | 24 | ||||
-rw-r--r-- | src/compat/attr_test.cpp | 50 | ||||
-rw-r--r-- | src/compat/option.hpp | 49 | ||||
-rw-r--r-- | src/compat/option_test.cpp | 32 |
4 files changed, 60 insertions, 95 deletions
diff --git a/src/compat/attr.hpp b/src/compat/attr.hpp index 9ddf654..5ebef6d 100644 --- a/src/compat/attr.hpp +++ b/src/compat/attr.hpp @@ -30,28 +30,4 @@ namespace tmwa #endif #define JOIN(a, b) a##b - -// first loop: -// declare flag 'guard' (initially true) -// declare flag 'broken' (initially false) -// condition is 'guard' must be true, which is the case only for the first iteration -// post checks 'broken' and if set, break the loop -// second loop: -// declare public 'var' variable -// condition is that 'guard' must be true -// post sets 'guard' to false to make this loop run only once -// third loop: -// enable broken flag; it will remain set if 'break' is in the loop -// condition is that 'broken' must be true -// post sets 'broken' to false, which then fails the condition -// if user has a 'break' inside, then 'broken' will be true -// in either case, go back to the second loop's post -#define WITH_VAR_INLOOP(ty, var, expr) \ - for (bool JOIN(var, _guard) = true, JOIN(var, _broken) = false; JOIN(var, _guard); ({if (JOIN(var, _broken)) { break; } })) \ - for (ty var = expr; JOIN(var, _guard); JOIN(var, _guard) = false) \ - for (JOIN(var, _broken) = true; JOIN(var, _broken); JOIN(var, _broken) = false) -#define WITH_VAR_NOLOOP(ty, var, expr) \ - for (bool JOIN(var, _guard) = true, JOIN(var, _broken) = false; JOIN(var, _guard); ({if (JOIN(var, _broken)) {abort();} })) \ - for (ty var = expr; JOIN(var, _guard); JOIN(var, _guard) = false) \ - for (JOIN(var, _broken) = true; JOIN(var, _broken); JOIN(var, _broken) = false) } // namespace tmwa diff --git a/src/compat/attr_test.cpp b/src/compat/attr_test.cpp deleted file mode 100644 index eb9042d..0000000 --- a/src/compat/attr_test.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "attr.hpp" -// attr_test.cpp - Tests for attributes -// -// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -#include <gtest/gtest.h> - -#include "../poison.hpp" - - -namespace tmwa -{ -TEST(attr, withvar) -{ - int x = 41; - for (int i = 0; i < 2; ++i) - { - WITH_VAR_NOLOOP(auto, y, x + 1) - { - x = y; - } - } - EXPECT_EQ(x, 43); - for (int i = 0; i < 2; ++i) - { - if (i == 1) - WITH_VAR_INLOOP(auto, y, i) - { - x = y; - break; - } - } - EXPECT_EQ(x, 1); -} -} // namespace tmwa diff --git a/src/compat/option.hpp b/src/compat/option.hpp index 7beef6f..b6e7655 100644 --- a/src/compat/option.hpp +++ b/src/compat/option.hpp @@ -24,8 +24,6 @@ #include <utility> -#include "attr.hpp" - namespace tmwa { @@ -423,13 +421,46 @@ namespace option 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_INLOOP(var, expr) \ - ((expr).is_some()) \ - WITH_VAR_INLOOP(auto&, var, *(expr).ptr_or(nullptr)) -#define OPTION_IS_SOME_NOLOOP(var, expr) \ - ((expr).is_some()) \ - WITH_VAR_NOLOOP(auto&, var, *(expr).ptr_or(nullptr)) + +#define OMATCH_BEGIN(expr) \ + { \ + auto&& _omatch_var = (expr); \ + switch (_omatch_var.is_some()) \ + { \ + { \ + { \ + /*}}}}*/ +#define OMATCH_END() \ + /*{{{{*/ \ + } \ + } \ + } \ + (void) _omatch_var; \ + } + +#define OMATCH_BEGIN_SOME(var, expr) \ + OMATCH_BEGIN (expr) \ + OMATCH_CASE_SOME (var) + +#define OMATCH_CASE_SOME(var) \ + /*{{{{*/ \ + } \ + break; \ + } \ + { \ + case true: \ + { \ + auto&& var = *_omatch_var.ptr_or(nullptr); \ + /*}}}}*/ +#define OMATCH_CASE_NONE() \ + /*{{{{*/ \ + } \ + break; \ + } \ + { \ + case false: \ + { \ + /*}}}}*/ } // namespace option //using option::Option; diff --git a/src/compat/option_test.cpp b/src/compat/option_test.cpp index f9cec0e..69f3a60 100644 --- a/src/compat/option_test.cpp +++ b/src/compat/option_test.cpp @@ -398,24 +398,32 @@ TEST(Option, unwrap) v = None; TRY_UNWRAP(fcr(), v = Some(1)); v = None; - if OPTION_IS_SOME_NOLOOP(o, v) + OMATCH_BEGIN (v) { - EXPECT_NE(o, o); - } - else - { - SUCCEED(); + OMATCH_CASE_SOME (o) + { + EXPECT_NE(o, o); + } + OMATCH_CASE_NONE () + { + SUCCEED(); + } } + OMATCH_END (); v = Some(1); - if OPTION_IS_SOME_NOLOOP(o, v) + OMATCH_BEGIN (v) { - EXPECT_EQ(o, 1); - } - else - { - FAIL(); + OMATCH_CASE_SOME (o) + { + EXPECT_EQ(o, 1); + } + OMATCH_CASE_NONE () + { + FAIL(); + } } + OMATCH_END (); } TEST(Option, flatten) |