summaryrefslogtreecommitdiff
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
parentbd913f6259896ce7317061e3607f3c8fd2371d89 (diff)
downloadmrust-59d95e289122a84ea057ff5ed15d7d0e583138ed.tar.gz
AST - Add asm! as an AST node
-rw-r--r--src/ast/dump.cpp4
-rw-r--r--src/ast/expr.cpp19
-rw-r--r--src/ast/expr.hpp35
-rw-r--r--src/expand/asm.cpp114
-rw-r--r--src/expand/mod.cpp6
-rw-r--r--src/hir/from_ast_expr.cpp3
-rw-r--r--src/hir/hir.cpp5
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 ) {