diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-28 20:19:18 +1100 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-28 20:19:18 +1100 |
commit | 59d95e289122a84ea057ff5ed15d7d0e583138ed (patch) | |
tree | 663b285db0a406a8fbe181a89a3dc4f61accca6b | |
parent | bd913f6259896ce7317061e3607f3c8fd2371d89 (diff) | |
download | mrust-59d95e289122a84ea057ff5ed15d7d0e583138ed.tar.gz |
AST - Add asm! as an AST node
-rw-r--r-- | src/ast/dump.cpp | 4 | ||||
-rw-r--r-- | src/ast/expr.cpp | 19 | ||||
-rw-r--r-- | src/ast/expr.hpp | 35 | ||||
-rw-r--r-- | src/expand/asm.cpp | 114 | ||||
-rw-r--r-- | src/expand/mod.cpp | 6 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 3 | ||||
-rw-r--r-- | src/hir/hir.cpp | 5 |
7 files changed, 182 insertions, 4 deletions
diff --git a/src/ast/dump.cpp b/src/ast/dump.cpp index 07343de4..a875506c 100644 --- a/src/ast/dump.cpp +++ b/src/ast/dump.cpp @@ -75,6 +75,10 @@ public: m_expr_root = false; m_os << n.m_name << "!( /* TODO: Macro TT */ )"; } + virtual void visit(AST::ExprNode_Asm& n) override { + m_os << "asm!("; + m_os << ")"; + } virtual void visit(AST::ExprNode_Flow& n) override { m_expr_root = false; switch(n.m_type) diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index cc6ca98f..6983221d 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -101,6 +101,18 @@ NODE(ExprNode_Macro, { return NEWNODE(ExprNode_Macro, m_name, m_ident, m_tokens.clone()); }) +NODE(ExprNode_Asm, { + os << "asm!()"; +},{ + ::std::vector<ExprNode_Asm::ValRef> outputs; + for(const auto& v : m_output) + outputs.push_back( ExprNode_Asm::ValRef { v.name, v.value->clone() }); + ::std::vector<ExprNode_Asm::ValRef> inputs; + for(const auto& v : m_input) + inputs.push_back( ExprNode_Asm::ValRef { v.name, v.value->clone() }); + return NEWNODE(ExprNode_Asm, m_text, mv$(outputs), mv$(inputs), m_clobbers, m_flags); +}) + NODE(ExprNode_Flow, { switch(m_type) { @@ -418,6 +430,13 @@ NV(ExprNode_Macro, { BUG(node.get_pos(), "Hit unexpanded macro in expression - " << node); }) +NV(ExprNode_Asm, +{ + for(auto& v : node.m_output) + visit(v.value); + for(auto& v : node.m_input) + visit(v.value); +}) NV(ExprNode_Flow, { visit(node.m_value); diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 4c80bcb5..ee1da656 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -1,4 +1,9 @@ /* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * ast/expr.hpp + * - AST Expression Nodes */ #ifndef AST_EXPR_INCLUDED #define AST_EXPR_INCLUDED @@ -88,6 +93,34 @@ struct ExprNode_Macro: NODE_METHODS(); }; +// asm! macro +struct ExprNode_Asm: + public ExprNode +{ + struct ValRef + { + ::std::string name; + unique_ptr<ExprNode> value; + }; + + ::std::string m_text; + ::std::vector<ValRef> m_output; + ::std::vector<ValRef> m_input; + ::std::vector<::std::string> m_clobbers; + ::std::vector<::std::string> m_flags; + + ExprNode_Asm(::std::string text, ::std::vector<ValRef> output, ::std::vector<ValRef> input, ::std::vector<::std::string> clobbers, ::std::vector<::std::string> flags): + m_text( move(text) ), + m_output( move(output) ), + m_input( move(input) ), + m_clobbers( move(clobbers) ), + m_flags( move(flags) ) + { + } + + NODE_METHODS(); +}; + // Break/Continue/Return struct ExprNode_Flow: public ExprNode @@ -599,6 +632,7 @@ public: virtual void visit(const nt& node) = 0*/ NT(ExprNode_Block); NT(ExprNode_Macro); + NT(ExprNode_Asm); NT(ExprNode_Flow); NT(ExprNode_LetBinding); NT(ExprNode_Assign); @@ -643,6 +677,7 @@ public: virtual void visit(const nt& node) override*/ NT(ExprNode_Block); NT(ExprNode_Macro); + NT(ExprNode_Asm); NT(ExprNode_Flow); NT(ExprNode_LetBinding); NT(ExprNode_Assign); 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()) )))); } }; diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index a2537218..3e67ed15 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -385,6 +385,12 @@ struct CExpandExpr: Expand_Mod(crate, modstack, node.m_local_mod->path(), *node.m_local_mod, mod_item_count); } } + void visit(::AST::ExprNode_Asm& node) override { + for(auto& v : node.m_output) + this->visit_nodelete(node, v.value); + for(auto& v : node.m_input) + this->visit_nodelete(node, v.value); + } void visit(::AST::ExprNode_Flow& node) override { this->visit_nodelete(node, node.m_value); } diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index 39b33e53..08e49aa4 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -46,6 +46,9 @@ struct LowerHIR_ExprNode_Visitor: virtual void visit(::AST::ExprNode_Macro& v) override { BUG(v.get_pos(), "Hit ExprNode_Macro"); } + virtual void visit(::AST::ExprNode_Asm& v) override { + TODO(v.get_pos(), "Convert asm! to HIR"); + } virtual void visit(::AST::ExprNode_Flow& v) override { switch( v.m_type ) { diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 2ec4d40b..18b09fac 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -512,8 +512,6 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const return false; } - //assert(m_params.m_types.size() == other.m_params.m_types.size()); - if( other.m_params.m_bounds.size() == 0 ) { return m_params.m_bounds.size() > 0; } @@ -527,13 +525,14 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const DEBUG("bounds_t = " << bounds_t); DEBUG("bounds_o = " << bounds_o); + // If there are less bounds in this impl, it can't be more specific. if( bounds_t.size() < bounds_o.size() ) return false; auto it_t = bounds_t.begin(); for(auto it_o = bounds_o.begin(); it_o != bounds_o.end(); ++it_o) { - // TODO: `T: Foo<T>` is more specific than `T: Foo<U>` + // TODO: `T: Foo<T>` is more specific than `T: Foo<U>`, this method doesn't pick that. while( ::ord(*it_t, *it_o) == OrdLess && it_t != bounds_t.end() ) ++ it_t; if( it_t == bounds_t.end() || ::ord(*it_t, *it_o) > OrdEqual ) { |