diff --git a/regression-tests/mixed-bounds-safety-with-assert-2.cpp2 b/regression-tests/mixed-bounds-safety-with-assert-2.cpp2 index d3036710af..054cfb7e49 100644 --- a/regression-tests/mixed-bounds-safety-with-assert-2.cpp2 +++ b/regression-tests/mixed-bounds-safety-with-assert-2.cpp2 @@ -9,8 +9,8 @@ main: () -> int = { add_42_to_subrange: (inout rng:_, start:int, end:int) = { - [[assert Bounds: 0 <= start]] - [[assert Bounds: end <= rng.ssize()]] + assert( 0 <= start ) + assert( end <= rng.ssize() ) count := 0; for rng diff --git a/regression-tests/mixed-bounds-safety-with-assert.cpp2 b/regression-tests/mixed-bounds-safety-with-assert.cpp2 index 43c2b2ac26..d4245c6bab 100644 --- a/regression-tests/mixed-bounds-safety-with-assert.cpp2 +++ b/regression-tests/mixed-bounds-safety-with-assert.cpp2 @@ -7,8 +7,8 @@ main: () -> int = { } print_subrange: (rng:_, start:int, end:int) = { - [[assert Bounds: 0 <= start]] - [[assert Bounds: end <= rng.ssize()]] + assert( 0 <= start ) + assert( end <= rng.ssize() ) count := 0; for rng diff --git a/regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2 b/regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2 index fab5bec55d..2600a3a668 100644 --- a/regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2 +++ b/regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2 @@ -1,7 +1,7 @@ #include using namespace std::chrono_literals; main: () = { - [[assert: 10 as i32 == 10]] - [[assert: 10LL as i32 == 10]] - [[assert: 10s as std::chrono::seconds == 10s]] + assert( 10 as i32 == 10 ) + assert( 10LL as i32 == 10 ) + assert( 10s as std::chrono::seconds == 10s ) } diff --git a/regression-tests/mixed-captures-in-expressions-and-postconditions.cpp2 b/regression-tests/mixed-captures-in-expressions-and-postconditions.cpp2 index afa1847504..6fa8c800fd 100644 --- a/regression-tests/mixed-captures-in-expressions-and-postconditions.cpp2 +++ b/regression-tests/mixed-captures-in-expressions-and-postconditions.cpp2 @@ -17,8 +17,8 @@ main: () -> int = { vec: std::vector = (); insert_at: (where: int, val: int) - [[pre: 0 <= where && where <= vec.ssize()]] - [[post: vec.ssize() == vec.ssize()$ + 1]] + pre( 0 <= where && where <= vec.ssize() ) + post( vec.ssize() == vec.ssize()$ + 1 ) = { _ = vec.insert( vec.begin()+where, val ); } diff --git a/regression-tests/mixed-initialization-safety-1-error.cpp2 b/regression-tests/mixed-initialization-safety-1-error.cpp2 index 9f2411969c..e3d9bcd2b8 100644 --- a/regression-tests/mixed-initialization-safety-1-error.cpp2 +++ b/regression-tests/mixed-initialization-safety-1-error.cpp2 @@ -10,8 +10,8 @@ fill: ( out x: std::string, in value: std::string, in count: int - ) - [[pre: value.size() >= count, "fill: value must contain at least count elements"]] + ) + pre( value.size() >= count, "fill: value must contain at least count elements" ) = { x = value.substr(0, count); } diff --git a/regression-tests/mixed-initialization-safety-2-error.cpp2 b/regression-tests/mixed-initialization-safety-2-error.cpp2 index a2eabc0568..39da2f34dd 100644 --- a/regression-tests/mixed-initialization-safety-2-error.cpp2 +++ b/regression-tests/mixed-initialization-safety-2-error.cpp2 @@ -10,8 +10,8 @@ fill: ( out x: std::string, in value: std::string, in count: int - ) - [[pre: value.size() >= count, "fill: value must contain at least count elements"]] + ) + pre( value.size() >= count, "fill: value must contain at least count elements" ) = { x = value.substr(0, count); } diff --git a/regression-tests/mixed-initialization-safety-3-contract-violation.cpp2 b/regression-tests/mixed-initialization-safety-3-contract-violation.cpp2 index 78ec475084..666fa9b22b 100644 --- a/regression-tests/mixed-initialization-safety-3-contract-violation.cpp2 +++ b/regression-tests/mixed-initialization-safety-3-contract-violation.cpp2 @@ -20,7 +20,7 @@ fill: ( value: std::string, count: int ) - [[pre: value.ssize() >= count, "fill: value must contain at least count elements"]] + pre( value.ssize() >= count, "fill: value must contain at least count elements" ) = { x = value.substr(0, count); } diff --git a/regression-tests/mixed-initialization-safety-3.cpp2 b/regression-tests/mixed-initialization-safety-3.cpp2 index 236ab7b29f..290e50867e 100644 --- a/regression-tests/mixed-initialization-safety-3.cpp2 +++ b/regression-tests/mixed-initialization-safety-3.cpp2 @@ -18,7 +18,7 @@ fill: ( value: std::string, count: int ) - [[pre: value.ssize() >= count, "fill: value must contain at least count elements"]] + pre( value.ssize() >= count, "fill: value must contain at least count elements" ) = { x = value.substr(0, count); } diff --git a/regression-tests/mixed-postexpression-with-capture.cpp2 b/regression-tests/mixed-postexpression-with-capture.cpp2 index f986406aff..0029d1568f 100644 --- a/regression-tests/mixed-postexpression-with-capture.cpp2 +++ b/regression-tests/mixed-postexpression-with-capture.cpp2 @@ -11,9 +11,9 @@ main: () -> int = { vec: std::vector = (); -insert_at: (where: int, val: int) - [[pre: 0 <= where && where <= vec.ssize()]] - [[post: vec.size() == vec.size()$ + 1]] +insert_at: (where: int, val: int) + pre ( 0 <= where && where <= vec.ssize() ) + post( vec.size() == vec.size()$ + 1 ) = { vec.push_back(val); } diff --git a/regression-tests/pure2-bugfix-for-assign-expression-list.cpp2 b/regression-tests/pure2-bugfix-for-assign-expression-list.cpp2 index 7d6b639a8b..b7eb84a0d6 100644 --- a/regression-tests/pure2-bugfix-for-assign-expression-list.cpp2 +++ b/regression-tests/pure2-bugfix-for-assign-expression-list.cpp2 @@ -2,9 +2,9 @@ main: () = { vec: type == std::vector; v: vec = (0); v = (); - [[assert: v == :vec = ()]] + assert( v == :vec = () ) v = (1); - [[assert: v == :vec = (1)]] + assert( v == :vec = (1) ) v = (2, 3); - [[assert: v == :vec = (2, 3)]] + assert( v == :vec = (2, 3) ) } diff --git a/regression-tests/pure2-bugfix-for-non-local-initialization.cpp2 b/regression-tests/pure2-bugfix-for-non-local-initialization.cpp2 index 67d6709d52..3079f017c5 100644 --- a/regression-tests/pure2-bugfix-for-non-local-initialization.cpp2 +++ b/regression-tests/pure2-bugfix-for-non-local-initialization.cpp2 @@ -3,6 +3,6 @@ t: @struct type = { this: std::integral_constant; } main: () = { - [[assert Testing: t::value[0] == 17]] - [[assert Testing: t::value[1] == 29]] + assert( t::value[0] == 17 ) + assert( t::value[1] == 29 ) } diff --git a/regression-tests/pure2-concept-definition.cpp2 b/regression-tests/pure2-concept-definition.cpp2 index 3ab3679c06..6a5c52c380 100644 --- a/regression-tests/pure2-concept-definition.cpp2 +++ b/regression-tests/pure2-concept-definition.cpp2 @@ -1,5 +1,5 @@ arithmetic: concept = std::integral || std::floating_point; main: () = { - [[assert Testing: arithmetic]] - [[assert Testing: arithmetic]] + assert( arithmetic ) + assert( arithmetic ) } diff --git a/regression-tests/pure2-forward-return.cpp2 b/regression-tests/pure2-forward-return.cpp2 index 6f598d60e5..8e56460ad9 100644 --- a/regression-tests/pure2-forward-return.cpp2 +++ b/regression-tests/pure2-forward-return.cpp2 @@ -1,6 +1,6 @@ first: (forward rng) -> forward _ - [[pre Bounds: !std::empty(rng)]] + pre( !std::empty(rng) ) = std::begin(rng)*; diff --git a/regression-tests/pure2-print.cpp2 b/regression-tests/pure2-print.cpp2 index 36e0638474..9791701e23 100644 --- a/regression-tests/pure2-print.cpp2 +++ b/regression-tests/pure2-print.cpp2 @@ -29,8 +29,8 @@ outer: @print type = { } private h: (s: std::string, inout m: std::map ) -> std::string - [[pre: m.empty() == false || false]] - [[pre Bounds: 0 < m.ssize() < 100 && true != false]] + pre( m.empty() == false || false, "message" ) + pre( 0 < m.ssize() < 100 && true != false ) = { a := :()={}; b := :()={}; @@ -46,7 +46,7 @@ outer: @print type = { else if !m.empty() { b(); } else { c(); } - [[assert: true]] + assert( true ) return :() -> std::string = (s + m[0])$; (); } diff --git a/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp b/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp index d2793a692a..69e0e9cab0 100644 --- a/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp +++ b/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp @@ -21,7 +21,7 @@ extern std::vector vec; auto insert_at(cpp2::in where, cpp2::in val) -> void; - + //=== Cpp2 function definitions ================================================= diff --git a/regression-tests/test-results/mixed-postexpression-with-capture.cpp b/regression-tests/test-results/mixed-postexpression-with-capture.cpp index 90bcbb3d25..39bb747344 100644 --- a/regression-tests/test-results/mixed-postexpression-with-capture.cpp +++ b/regression-tests/test-results/mixed-postexpression-with-capture.cpp @@ -24,7 +24,7 @@ extern std::vector vec; auto insert_at(cpp2::in where, cpp2::in val) -> void; - + //=== Cpp2 function definitions ================================================= diff --git a/regression-tests/test-results/pure2-print.cpp b/regression-tests/test-results/pure2-print.cpp index 75450fa083..33cfe32365 100644 --- a/regression-tests/test-results/pure2-print.cpp +++ b/regression-tests/test-results/pure2-print.cpp @@ -122,7 +122,7 @@ requires (true) #line 34 "pure2-print.cpp2" { - cpp2::Default.expects(CPP2_UFCS_0(empty, m) == false || false, ""); + cpp2::Default.expects(CPP2_UFCS_0(empty, m) == false || false, "message"); cpp2::Bounds.expects([_0 = 0, _1 = CPP2_UFCS_0(ssize, m), _2 = 100]{ return cpp2::cmp_less(_0,_1) && cpp2::cmp_less(_1,_2); }() && true != false, ""); #line 35 "pure2-print.cpp2" auto a {[]() -> void{}}; diff --git a/regression-tests/test-results/pure2-print.cpp2.output b/regression-tests/test-results/pure2-print.cpp2.output index 0e6b7ba16f..04793ee775 100644 --- a/regression-tests/test-results/pure2-print.cpp2.output +++ b/regression-tests/test-results/pure2-print.cpp2.output @@ -32,8 +32,8 @@ outer: type = in s: std::string, inout m: std::map ) -> move std::string - [[pre: m.empty() == false || false]] - [[pre Bounds: 0 < m.ssize() < 100 && true != false]] = + pre( m.empty() == false || false, "message" ) + pre( 0 < m.ssize() < 100 && true != false ) = { a: = :() = { @@ -75,7 +75,7 @@ outer: type = c(); } } - [[assert: true]] + assert( true ) return :() -> move std::string = (s + m[0])$;(); } diff --git a/regression-tests/test-results/pure2-union.cpp b/regression-tests/test-results/pure2-union.cpp index f74851b2d9..94d6176194 100644 --- a/regression-tests/test-results/pure2-union.cpp +++ b/regression-tests/test-results/pure2-union.cpp @@ -82,16 +82,16 @@ auto main() -> int; [[nodiscard]] auto name_or_number::is_name() const& -> bool { return _discriminator == 0; } [[nodiscard]] auto name_or_number::name() const& -> std::string const& { - cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } [[nodiscard]] auto name_or_number::name() & -> std::string& { - cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } auto name_or_number::set_name(cpp2::in _value) & -> void{if (!(is_name())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _value);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = _value;}_discriminator = 0;} auto name_or_number::set_name(auto&& ..._args) & -> void{if (!(is_name())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _args...);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = std::string{_args...};}_discriminator = 0;} [[nodiscard]] auto name_or_number::is_num() const& -> bool { return _discriminator == 1; } [[nodiscard]] auto name_or_number::num() const& -> cpp2::i32 const& { - cpp2::Default.expects(is_num(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + cpp2::Default.expects(is_num(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } [[nodiscard]] auto name_or_number::num() & -> cpp2::i32& { - cpp2::Default.expects(is_num(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + cpp2::Default.expects(is_num(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } auto name_or_number::set_num(cpp2::in _value) & -> void{if (!(is_num())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _value);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = _value;}_discriminator = 1;} auto name_or_number::set_num(auto&& ..._args) & -> void{if (!(is_num())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _args...);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = cpp2::i32{_args...};}_discriminator = 1;} auto name_or_number::_destroy() & -> void{ @@ -138,16 +138,16 @@ name_or_number::name_or_number(name_or_number const& that) template [[nodiscard]] auto name_or_other::is_name() const& -> bool { return _discriminator == 0; } template [[nodiscard]] auto name_or_other::name() const& -> std::string const& { - cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } template [[nodiscard]] auto name_or_other::name() & -> std::string& { - cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } template auto name_or_other::set_name(cpp2::in _value) & -> void{if (!(is_name())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _value);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = _value;}_discriminator = 0;} template auto name_or_other::set_name(auto&& ..._args) & -> void{if (!(is_name())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _args...);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = std::string{_args...};}_discriminator = 0;} template [[nodiscard]] auto name_or_other::is_other() const& -> bool { return _discriminator == 1; } template [[nodiscard]] auto name_or_other::other() const& -> T const& { - cpp2::Default.expects(is_other(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + cpp2::Default.expects(is_other(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } template [[nodiscard]] auto name_or_other::other() & -> T& { - cpp2::Default.expects(is_other(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + cpp2::Default.expects(is_other(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } template auto name_or_other::set_other(cpp2::in _value) & -> void{if (!(is_other())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _value);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = _value;}_discriminator = 1;} template auto name_or_other::set_other(auto&& ..._args) & -> void{if (!(is_other())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _args...);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = T{_args...};}_discriminator = 1;} template auto name_or_other::_destroy() & -> void{ diff --git a/regression-tests/test-results/version b/regression-tests/test-results/version index d06fda8168..900f8ffd05 100644 --- a/regression-tests/test-results/version +++ b/regression-tests/test-results/version @@ -1,5 +1,5 @@ -cppfront compiler v0.3.0 Build 8A27:1514 +cppfront compiler v0.3.0 Build 8B07:1638 Copyright(c) Herb Sutter All rights reserved SPDX-License-Identifier: CC-BY-NC-ND-4.0 diff --git a/source/build.info b/source/build.info index 7a7c6158b4..2def373b0a 100644 --- a/source/build.info +++ b/source/build.info @@ -1 +1 @@ -"8A27:1514" \ No newline at end of file +"8B07:1638" \ No newline at end of file diff --git a/source/parse.h b/source/parse.h index bedb265b65..9a8537ce2b 100644 --- a/source/parse.h +++ b/source/parse.h @@ -4531,19 +4531,19 @@ auto pretty_print_visualize(contract_node const& n, int indent) { assert (n.kind && n.condition); - auto ret = std::string{"\n"} + pre(indent) + "[[" + n.kind->as_string_view(); + auto ret = std::string{"\n"} + pre(indent) + n.kind->as_string_view(); if (n.group) { - ret += " " + pretty_print_visualize(*n.group, indent); + ret += "<" + pretty_print_visualize(*n.group, indent) + ">"; } - ret += ": " + pretty_print_visualize(*n.condition, indent); + ret += "( " + pretty_print_visualize(*n.condition, indent); if (n.message) { - ret += " " + n.message->to_string(); + ret += ", " + n.message->to_string(); } - ret += "]]"; + ret += " )"; return ret; } @@ -7001,9 +7001,9 @@ class parser //G jump-statement //G iteration-statement //G compound-statement + //G contract //G declaration //G expression-statement - //G contract // //GTODO try-block //G @@ -7084,25 +7084,25 @@ class parser return n; } - else if (auto s = declaration(true, false, false, n.get())) { + else if (auto s = contract()) { + if (*s->kind != "assert") { + error("only 'assert' contracts are allowed at statement scope"); + return {}; + } n->statement = std::move(s); - assert (n->is_declaration()); + assert (n->is_contract()); return n; } - else if (auto s = expression_statement(semicolon_required)) { + else if (auto s = declaration(true, false, false, n.get())) { n->statement = std::move(s); - assert (n->is_expression()); + assert (n->is_declaration()); return n; } - else if (auto s = contract()) { - if (*s->kind != "assert") { - error("only 'assert' contracts are allowed at statement scope"); - return {}; - } + else if (auto s = expression_statement(semicolon_required)) { n->statement = std::move(s); - assert (n->is_contract()); + assert (n->is_expression()); return n; } @@ -7467,8 +7467,11 @@ class parser //G contract: - //G '[' '[' contract-kind id-expression? ':' logical-or-expression ']' ']' - //G '[' '[' contract-kind id-expression? ':' logical-or-expression ',' string-literal ']' ']' + //G contract-kind contract-group? ':' logical-or-expression ']' ']' + //G contract-kind contract-group? ':' logical-or-expression ',' string-literal ']' ']' + //G + //G contract-group: + //G '<' id-expression '>' //G //G contract-kind: one of //G 'pre' 'post' 'assert' @@ -7476,26 +7479,8 @@ class parser auto contract() -> std::unique_ptr { - // Note: For now I'm using [[ ]] mainly so that existing Cpp1 syntax highlighters - // don't get confused... I initially implemented single [ ], but then - // my editor's default Cpp1 highlighter didn't colorize the following - // multiline // comment correctly as a comment - - // If there's no [ [ then this isn't a contract - if ( - done() - || curr().type() != lexeme::LeftBracket - || !peek(1) - || peek(1)->type() != lexeme::LeftBracket - ) - { - return {}; - } - auto n = std::make_unique(curr().position()); auto guard = capture_groups_stack_guard(this, &n->captures); - next(); - next(); if ( curr() != "pre" @@ -7503,18 +7488,30 @@ class parser && curr() != "assert" ) { - error("[ begins a contract and must be followed by 'pre', 'post', or 'assert'"); return {}; } n->kind = &curr(); next(); - if (auto id = id_expression()) { - n->group = std::move(id); + if (curr().type() == lexeme::Less) { + next(); + if (auto id = id_expression()) { + n->group = std::move(id); + } + else { + error("invalid contract group after '<'"); + return {}; + } + + if (curr().type() != lexeme::Greater) { + error("expected '>' after contract group"); + return {}; + } + next(); } - if (curr().type() != lexeme::Colon) { - error("expected : before the contract condition"); + if (curr().type() != lexeme::LeftParen) { + error("expected '(' before the contract condition"); return {}; } next(); @@ -7537,17 +7534,22 @@ class parser next(); } + if (curr().type() != lexeme::RightParen) { + error("expected ')' at the end of the contract"); + return {}; + } + next(); + + // Allow optional ';' after an assert, which is really an empty + // statement (I'm not putting it in the grammar) and so this is + // to skip the "empty statement" check and error if ( - curr().type() != lexeme::RightBracket - || !peek(1) - || peek(1)->type() != lexeme::RightBracket + *n->kind == "assert" + && curr().type() == lexeme::Semicolon ) { - error("expected ]] at the end of the contract"); - return {}; + next(); } - next(); - next(); return n; } @@ -7607,11 +7609,12 @@ class parser } - // If we're not at a '->' or 'requires' and what follows is an expression, - // this is a ":(params) expr" shorthand function syntax + // If we're not at a '->' or 'requires' or contract and what follows is + // an expression, this is a ":(params) expr" shorthand function syntax if ( curr().type() != lexeme::Arrow && curr() != "requires" + && (curr() != "pre" && curr() != "post") ) { auto start_pos = pos; diff --git a/source/reflect.h b/source/reflect.h index 9ea03adcdb..59cc45b5c0 100644 --- a/source/reflect.h +++ b/source/reflect.h @@ -156,7 +156,7 @@ type_id: @polymorphic_base @copyable type = = { compiler_services = s; n = n_; - [[assert: n, "a meta::type_id must point to a valid type_id_node, not null"]] + assert( n, "a meta::type_id must point to a valid type_id_node, not null" ) } is_wildcard : (this) -> bool = n.is_wildcard(); @@ -1652,9 +1652,9 @@ std::string comma = ""; { CPP2_UFCS(add_member, t, " is_" + cpp2::to_string(a.name) + ": (this) -> bool = _discriminator == " + cpp2::to_string(a.value) + ";\n"); - CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (this) -> forward " + cpp2::to_string(a.type) + " [[pre: is_" + cpp2::to_string(a.name) + "()]] = reinterpret_cast<* const " + cpp2::to_string(a.type) + ">(_storage&)*;\n"); + CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (this) -> forward " + cpp2::to_string(a.type) + " pre(is_" + cpp2::to_string(a.name) + "()) = reinterpret_cast<* const " + cpp2::to_string(a.type) + ">(_storage&)*;\n"); - CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (inout this) -> forward " + cpp2::to_string(a.type) + " [[pre: is_" + cpp2::to_string(a.name) + "()]] = reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)*;\n"); + CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (inout this) -> forward " + cpp2::to_string(a.type) + " pre(is_" + cpp2::to_string(a.name) + "()) = reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)*;\n"); CPP2_UFCS(add_member, t, " set_" + cpp2::to_string(a.name) + ": (inout this, _value: " + cpp2::to_string(a.type) + ") = { if !is_" + cpp2::to_string(a.name) + "() { _destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), _value); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = _value; } _discriminator = " + cpp2::to_string(a.value) + "; }\n"); diff --git a/source/reflect.h2 b/source/reflect.h2 index 3e842618c5..370f77fb17 100644 --- a/source/reflect.h2 +++ b/source/reflect.h2 @@ -107,7 +107,7 @@ compiler_services: @polymorphic_base @copyable type = tokens := generated_lexers.back()&; tokens*.lex( lines*, true ); - [[assert: std::ssize(tokens*.get_map()) == 1]] + assert( std::ssize(tokens* .get_map()) == 1 ) // Now parse this single declaration from // the lexed tokens @@ -168,7 +168,7 @@ type_id: @polymorphic_base @copyable type = = { compiler_services = s; n = n_; - [[assert: n, "a meta::type_id must point to a valid type_id_node, not null"]] + assert( n, "a meta::type_id must point to a valid type_id_node, not null" ) } is_wildcard : (this) -> bool = n*.is_wildcard(); @@ -204,7 +204,7 @@ declaration_base: @polymorphic_base @copyable type = = { compiler_services = s; n = n_; - [[assert: n, "a meta::declaration must point to a valid declaration_node, not null"]] + assert( n, "a meta::declaration must point to a valid declaration_node, not null" ) } position: (override this) -> source_position = n*.position(); @@ -282,10 +282,10 @@ declaration: @polymorphic_base @copyable type = parent_is_polymorphic: (this) -> bool = n*.parent_is_polymorphic(); mark_for_removal_from_enclosing_type: (inout this) - [[pre Type: parent_is_type()]] // this precondition should be sufficient ... + pre( parent_is_type() ) // this precondition should be sufficient ... = { test := n*.type_member_mark_for_removal(); - [[assert: test]] // ... to ensure this assert is true + assert( test ) // ... to ensure this assert is true } } @@ -304,7 +304,7 @@ function_declaration: @copyable type = ) = { declaration = (n_, s); - [[assert: n*.is_function()]] + assert( n*.is_function() ) } index_of_parameter_named : (this, s: std::string_view) -> int = n*.index_of_parameter_named(s); @@ -361,7 +361,7 @@ object_declaration: @copyable type = ) = { declaration = (n_, s); - [[assert: n*.is_object()]] + assert( n*.is_object() ) } is_const : (this) -> bool = n*.is_const(); @@ -397,7 +397,7 @@ type_declaration: @copyable type = ) = { declaration = (n_, s); - [[assert: n*.is_type()]] + assert( n*.is_type() ) } reserve_names: (this, name: std::string_view, forward etc...) = @@ -510,7 +510,7 @@ alias_declaration: @copyable type = ) = { declaration = (n_, s); - [[assert: n*.is_alias()]] + assert( n*.is_alias() ) } } @@ -1167,9 +1167,9 @@ union: (inout t : meta::type_declaration) { t.add_member( " is_(a.name)$: (this) -> bool = _discriminator == (a.value)$;\n"); - t.add_member( " (a.name)$: (this) -> forward (a.type)$ [[pre: is_(a.name)$()]] = reinterpret_cast<* const (a.type)$>(_storage&)*;\n"); + t.add_member( " (a.name)$: (this) -> forward (a.type)$ pre(is_(a.name)$()) = reinterpret_cast<* const (a.type)$>(_storage&)*;\n"); - t.add_member( " (a.name)$: (inout this) -> forward (a.type)$ [[pre: is_(a.name)$()]] = reinterpret_cast<*(a.type)$>(_storage&)*;\n"); + t.add_member( " (a.name)$: (inout this) -> forward (a.type)$ pre(is_(a.name)$()) = reinterpret_cast<*(a.type)$>(_storage&)*;\n"); t.add_member( " set_(a.name)$: (inout this, _value: (a.type)$) = { if !is_(a.name)$() { _destroy(); std::construct_at( reinterpret_cast<*(a.type)$>(_storage&), _value); } else { reinterpret_cast<*(a.type)$>(_storage&)* = _value; } _discriminator = (a.value)$; }\n"); @@ -1239,7 +1239,7 @@ apply_metafunctions: ( ) -> bool = { - [[assert: n.is_type()]] + assert( n.is_type() ) // Check for _names reserved for the metafunction implementation for rtype.get_members()