1919#include " rust-ast-fragment.h"
2020#include " rust-macro-builtins.h"
2121#include " rust-macro-builtins-helpers.h"
22+ #include " rust-ast-builder.h"
23+ #include " optional.h"
24+ #include " rust-ast-collector.h"
2225
2326namespace Rust {
2427tl::optional<AST ::Fragment>
@@ -27,6 +30,79 @@ MacroBuiltin::assert_handler (location_t invoc_locus,
2730 AST ::InvocKind semicolon)
2831{
2932 rust_debug (" assert!() called" );
33+ auto tt = invoc.get_delim_tok_tree ();
34+ MacroInvocLexer lex (tt.to_token_stream ());
35+ Parser<MacroInvocLexer> parser (lex);
36+
37+ auto last_token_id = macro_end_token (tt, parser);
38+ bool has_error = false ;
39+
40+ auto expanded_expr = try_expand_many_expr (parser, last_token_id,
41+ invoc.get_expander (), has_error);
42+ if (expanded_expr.size () < 1 )
43+ {
44+ rust_error_at (invoc_locus,
45+ " macro requires a boolean expression as an argument" );
46+ return AST::Fragment::create_error ();
47+ }
48+ auto expr_to_assert = std::move (expanded_expr[0 ]);
49+ expanded_expr.erase (expanded_expr.begin ());
50+
51+ if (expanded_expr.size () > 1 )
52+ {
53+ rust_sorry_at (
54+ invoc_locus,
55+ " The second form of assert with a message is not supported yet" );
56+
57+ return AST::Fragment::create_error ();
58+ }
59+
60+ auto pending_invocations = check_for_eager_invocations (expanded_expr);
61+ if (!pending_invocations.empty ())
62+ return make_eager_builtin_invocation (BuiltinMacro::Assert, invoc_locus,
63+ invoc.get_delim_tok_tree (),
64+ std::move (pending_invocations));
65+
66+ if (expr_to_assert->get_expr_kind () != AST ::Expr::Kind::MacroInvocation)
67+ {
68+ AST ::Builder b (invoc_locus);
69+
70+ std::vector<std::unique_ptr<AST ::TokenTree>> panic_tree;
71+ const_TokenPtr open = Token::make (TokenId::LEFT_PAREN , invoc_locus);
72+ panic_tree.push_back (std::make_unique<AST ::Token> (std::move (open)));
73+
74+ const_TokenPtr close = Token::make (TokenId::RIGHT_PAREN , invoc_locus);
75+ panic_tree.push_back (std::make_unique<AST ::Token> (std::move (close)));
76+
77+ auto panic = AST::MacroInvocation::Regular (
78+ AST::MacroInvocData (AST::SimplePath (Identifier (" panic" )),
79+ AST::DelimTokenTree (AST ::DelimType::PARENS ,
80+ std::move (panic_tree),
81+ invoc_locus)),
82+ {} /* outer attributes */ , invoc_locus, true /* semicoloned */ );
83+ auto stmt = b.statementify (std::move (panic));
84+ std::vector<std::unique_ptr<AST ::Stmt>> stmts;
85+ stmts.push_back (std::move (stmt));
86+ auto block = b.block (std::move (stmts));
87+ auto negated_condition = std::unique_ptr<AST ::NegationExpr> (
88+ new AST::NegationExpr (std::move (expr_to_assert),
89+ AST ::NegationExpr::ExprType::NOT , {},
90+ invoc_locus));
91+
92+ auto if_expr = std::make_unique<AST ::IfExpr> (
93+ std::move (negated_condition) /* condition*/ , std::move (block),
94+ std::vector<AST ::Attribute>{}, invoc_locus);
95+
96+ auto node = AST::SingleASTNode (std::move (if_expr));
97+
98+ AST ::TokenCollector collector;
99+ collector.visit (node);
100+ std::vector<std::unique_ptr<AST ::Token>> tokens;
101+ for (auto &&token : collector.collect_tokens ())
102+ tokens.push_back (std::make_unique<AST ::Token> (token));
103+
104+ return AST::Fragment ({node}, std::move (tokens));
105+ }
30106
31107 return AST::Fragment::create_error ();
32108}
0 commit comments