From 59d95e289122a84ea057ff5ed15d7d0e583138ed Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 28 Dec 2016 20:19:18 +1100 Subject: AST - Add asm! as an AST node --- src/expand/asm.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) (limited to 'src/expand/asm.cpp') 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 #include +#include // for Expand_BareExpr #include #include +#include +#include +#include // for ExprNode_* +#include + +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(&*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 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()) )))); } }; -- cgit v1.2.3