summaryrefslogtreecommitdiff
path: root/src/expand/asm.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-28 20:19:18 +1100
committerJohn Hodge <tpg@mutabah.net>2016-12-28 20:19:18 +1100
commit59d95e289122a84ea057ff5ed15d7d0e583138ed (patch)
tree663b285db0a406a8fbe181a89a3dc4f61accca6b /src/expand/asm.cpp
parentbd913f6259896ce7317061e3607f3c8fd2371d89 (diff)
downloadmrust-59d95e289122a84ea057ff5ed15d7d0e583138ed.tar.gz
AST - Add asm! as an AST node
Diffstat (limited to 'src/expand/asm.cpp')
-rw-r--r--src/expand/asm.cpp114
1 files changed, 113 insertions, 1 deletions
diff --git a/src/expand/asm.cpp b/src/expand/asm.cpp
index 3ca7bb72..6ca90f3e 100644
--- a/src/expand/asm.cpp
+++ b/src/expand/asm.cpp
@@ -7,16 +7,128 @@
*/
#include <common.hpp>
#include <synext_macro.hpp>
+#include <synext.hpp> // for Expand_BareExpr
#include <parse/tokentree.hpp>
#include <parse/ttstream.hpp>
+#include <parse/common.hpp>
+#include <parse/parseerror.hpp>
+#include <ast/expr.hpp> // for ExprNode_*
+#include <parse/interpolated_fragment.hpp>
+
+namespace
+{
+ ::std::string get_string(const Span& sp, TokenStream& lex, const ::AST::Crate& crate, AST::Module& mod)
+ {
+ auto n = Parse_ExprVal(lex);
+ ASSERT_BUG(sp, n, "No expression returned");
+ Expand_BareExpr(crate, mod, n);
+
+ auto* format_string_np = dynamic_cast<AST::ExprNode_String*>(&*n);
+ if( !format_string_np ) {
+ ERROR(sp, E0000, "asm! requires a string literal - got " << *n);
+ }
+ //const auto& format_string_sp = format_string_np->span();
+ return mv$( format_string_np->m_value );
+ }
+}
class CAsmExpander:
public ExpandProcMacro
{
::std::unique_ptr<TokenStream> expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override
{
+ Token tok;
+ auto lex = TTStream(tt);
+ if( ident != "" )
+ ERROR(sp, E0000, "format_args! doesn't take an ident");
+
+ auto template_text = get_string(sp, lex, crate, mod);
+ ::std::vector<::AST::ExprNode_Asm::ValRef> outputs;
+ ::std::vector<::AST::ExprNode_Asm::ValRef> inputs;
+ ::std::vector<::std::string> clobbers;
+ ::std::vector<::std::string> flags;
+
+ // Outputs
+ if( lex.lookahead(0) == TOK_COLON )
+ {
+ GET_TOK(tok, lex);
+
+ while( lex.lookahead(0) == TOK_STRING )
+ {
+ //auto name = get_string(sp, lex);
+ GET_CHECK_TOK(tok, lex, TOK_STRING);
+ auto name = mv$(tok.str());
+
+ GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
+ auto val = Parse_Expr0(lex);
+ GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
+
+ outputs.push_back( ::AST::ExprNode_Asm::ValRef { mv$(name), mv$(val) } );
+
+ if( lex.lookahead(0) != TOK_COMMA )
+ break;
+
+ GET_TOK(tok, lex);
+ }
+ }
+
+ // Inputs
+ if( lex.lookahead(0) == TOK_COLON )
+ {
+ GET_TOK(tok, lex);
+
+ while( lex.lookahead(0) == TOK_STRING )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_STRING);
+ auto name = mv$(tok.str());
+
+ GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
+ auto val = Parse_Expr0(lex);
+ GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
+
+ inputs.push_back( ::AST::ExprNode_Asm::ValRef { mv$(name), mv$(val) } );
+
+ if( lex.lookahead(0) != TOK_COMMA )
+ break;
+ GET_TOK(tok, lex);
+ }
+ }
+
+ // Clobbers
+ if( lex.lookahead(0) == TOK_COLON )
+ {
+ GET_TOK(tok, lex);
+
+ while( lex.lookahead(0) == TOK_STRING )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_STRING);
+ clobbers.push_back( mv$(tok.str()) );
+
+ if( lex.lookahead(0) != TOK_COMMA )
+ break;
+ GET_TOK(tok, lex);
+ }
+ }
+
+ // Flags
+ if( lex.lookahead(0) == TOK_COLON )
+ {
+ GET_TOK(tok, lex);
+
+ while( lex.lookahead(0) == TOK_STRING )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_STRING);
+ flags.push_back( mv$(tok.str()) );
+
+ if( lex.lookahead(0) != TOK_COMMA )
+ break;
+ GET_TOK(tok, lex);
+ }
+ }
+
+ ::AST::ExprNodeP rv = ::AST::ExprNodeP( new ::AST::ExprNode_Asm { mv$(template_text), mv$(outputs), mv$(inputs), mv$(clobbers), mv$(flags) } );
// TODO: Convert this into an AST node
- return box$( TTStreamO(TokenTree()) );
+ return box$( TTStreamO(TokenTree(Token( InterpolatedFragment(InterpolatedFragment::EXPR, rv.release()) ))));
}
};