diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | src/expand/cfg.cpp | 81 | ||||
-rw-r--r-- | src/expand/cfg.hpp | 6 | ||||
-rw-r--r-- | src/expand/concat.cpp | 50 | ||||
-rw-r--r-- | src/expand/file_line.cpp | 30 | ||||
-rw-r--r-- | src/expand/format_args.cpp | 53 | ||||
-rw-r--r-- | src/expand/macro_rules.cpp | 5 | ||||
-rw-r--r-- | src/expand/mod.cpp | 324 | ||||
-rw-r--r-- | src/expand/stringify.cpp | 28 | ||||
-rw-r--r-- | src/include/span.hpp | 1 | ||||
-rw-r--r-- | src/include/synext.hpp | 7 | ||||
-rw-r--r-- | src/include/tagged_union.hpp | 4 | ||||
-rw-r--r-- | src/main.cpp | 6 | ||||
-rw-r--r-- | src/synexts/derive.cpp | 2 |
14 files changed, 425 insertions, 175 deletions
@@ -29,7 +29,8 @@ OBJ += ast/ast.o ast/crate.o ast/path.o ast/expr.o ast/pattern.o OBJ += ast/provided_module.o OBJ += parse/parseerror.o parse/lex.o OBJ += parse/root.o parse/paths.o parse/types.o parse/expr.o parse/pattern.o parse/macro_rules.o -OBJ += expand/mod.o expand/macro_rules.o expand/cfg.o +OBJ += expand/mod.o expand/macro_rules.o expand/cfg.o expand/format_args.o +OBJ += expand/concat.o expand/stringify.o expand/file_line.o OBJ += dump_as_rust.o OBJ += convert/ast_iterate.o #OBJ += convert/decorators.o diff --git a/src/expand/cfg.cpp b/src/expand/cfg.cpp index d178b9ae..c77ada2a 100644 --- a/src/expand/cfg.cpp +++ b/src/expand/cfg.cpp @@ -3,11 +3,68 @@ #include <parse/tokentree.hpp> #include <parse/lex.hpp> #include <parse/common.hpp> +#include "cfg.hpp" -bool check_cfg(const ::AST::MetaItem& mi) { - // TODO: Handle cfg conditions - throw ::std::runtime_error("TODO: Handle #[cfg] or cfg! conditions"); - return true; +#include <map> +#include <set> + +::std::map< ::std::string, ::std::string> g_cfg_values; +::std::set< ::std::string > g_cfg_flags; + +void Cfg_SetFlag(::std::string name) { + g_cfg_flags.insert( mv$(name) ); +} +void Cfg_SetValue(::std::string name, ::std::string val) { + g_cfg_values.insert( ::std::make_pair(mv$(name), mv$(name)) ); +} + +bool check_cfg(Span sp, const ::AST::MetaItem& mi) { + + if( mi.has_sub_items() ) { + // Must be `any`/`not`/`all` + if( mi.name() == "any" || mi.name() == "cfg" ) { + for(const auto& si : mi.items()) { + if( check_cfg(sp, si) ) + return true; + } + return false; + } + else if( mi.name() == "not" ) { + if( mi.items().size() != 1 ) + ERROR(sp, E0000, "cfg(not()) with != 1 argument"); + return !check_cfg(sp, mi.items()[0]); + } + else if( mi.name() == "all" ) { + for(const auto& si : mi.items()) { + if( ! check_cfg(sp, si) ) + return false; + } + return true; + } + else { + // oops + ERROR(sp, E0000, "Unknown cfg() function - " << mi.name()); + } + } + else if( mi.has_string() ) { + // Equaliy + auto it = g_cfg_values.find(mi.name()); + if( it != g_cfg_values.end() ) + { + return it->second == mi.string(); + } + else + { + WARNING(sp, W0000, "Unknown cfg() param '" << mi.name() << "'"); + return false; + } + } + else { + // Flag + auto it = g_cfg_flags.find(mi.name()); + return (it != g_cfg_flags.end()); + } + BUG(sp, "Fell off the end of check_cfg"); } class CCfgExpander: @@ -15,7 +72,7 @@ class CCfgExpander: { bool expand_early() const override { return true; } - ::std::unique_ptr<TokenStream> expand(Span sp, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr<TokenStream> expand(Span sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override { if( ident != "" ) { ERROR(sp, E0000, "cfg! doesn't take an identifier"); @@ -25,7 +82,7 @@ class CCfgExpander: auto attrs = Parse_MetaItem(lex); DEBUG("cfg!() - " << attrs); - if( check_cfg(attrs) ) { + if( check_cfg(sp, attrs) ) { return box$( TTStreamO(TokenTree(TOK_RWORD_TRUE )) ); } else { @@ -41,24 +98,24 @@ class CCfgHandler: AttrStage stage() const override { return AttrStage::EarlyPre; } - void handle(const AST::MetaItem& mi, AST::Crate& crate, AST::MacroInvocation& mac) const override { - if( check_cfg(mi) ) { + void handle(const AST::MetaItem& mi, ::AST::Crate& crate, AST::MacroInvocation& mac) const override { + if( check_cfg(mac.span(), mi) ) { // Leave as is } else { mac.clear(); } } - void handle(const AST::MetaItem& mi, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const override { - if( check_cfg(mi) ) { + void handle(const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const override { + if( check_cfg(Span(), mi) ) { // Leave } else { i = AST::Item::make_None({}); } } - void handle(const AST::MetaItem& mi, ::std::unique_ptr<AST::ExprNode>& expr) const override { - if( check_cfg(mi) ) { + void handle(const AST::MetaItem& mi, ::AST::Crate& crate, ::std::unique_ptr<AST::ExprNode>& expr) const override { + if( check_cfg(Span(expr->get_pos()), mi) ) { // Leave } else { diff --git a/src/expand/cfg.hpp b/src/expand/cfg.hpp new file mode 100644 index 00000000..ae5e1054 --- /dev/null +++ b/src/expand/cfg.hpp @@ -0,0 +1,6 @@ + +#pragma once + +extern void Cfg_SetFlag(::std::string name); +extern void Cfg_SetValue(::std::string name, ::std::string val); +extern bool check_cfg(Span sp, const ::AST::MetaItem& mi); diff --git a/src/expand/concat.cpp b/src/expand/concat.cpp new file mode 100644 index 00000000..c7da73a1 --- /dev/null +++ b/src/expand/concat.cpp @@ -0,0 +1,50 @@ +/* + */ +#include <synext.hpp> +#include "../parse/common.hpp" +#include "../parse/parseerror.hpp" +#include "../parse/tokentree.hpp" +#include "../parse/lex.hpp" + +class CConcatExpander: + public ExpandProcMacro +{ + bool expand_early() const override { return true; } + + ::std::unique_ptr<TokenStream> expand(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"); + + ::std::string rv; + do { + auto v = Parse_Expr0(lex); + DEBUG("concat - v=" << *v); + Expand_Expr(true , *const_cast<AST::Crate*>(&crate), LList<const AST::Module*>(nullptr, &mod), v); + Expand_Expr(false, *const_cast<AST::Crate*>(&crate), LList<const AST::Module*>(nullptr, &mod), v); + DEBUG("concat[pe] - v=" << *v); + if( auto* vp = dynamic_cast<AST::ExprNode_String*>(v.get()) ) + { + rv += vp->m_value; + } + else if( auto* vp = dynamic_cast<AST::ExprNode_Integer*>(v.get()) ) + { + rv += FMT(vp->m_value); + } + else + { + ERROR(sp, E0000, "Unexpected expression type"); + } + } while( GET_TOK(tok, lex) == TOK_COMMA ); + if( tok.type() != TOK_EOF ) + throw ParseError::Unexpected(lex, tok, {TOK_COMMA, TOK_EOF}); + + return box$( TTStreamO(TokenTree(Token(TOK_STRING, mv$(rv)))) ); + } +}; + +STATIC_MACRO("concat", CConcatExpander); + diff --git a/src/expand/file_line.cpp b/src/expand/file_line.cpp new file mode 100644 index 00000000..a4117d70 --- /dev/null +++ b/src/expand/file_line.cpp @@ -0,0 +1,30 @@ +/* + */ +#include <synext.hpp> +#include "../parse/common.hpp" + +class CExpanderFile: + public ExpandProcMacro +{ + bool expand_early() const override { return true; } + + ::std::unique_ptr<TokenStream> expand(Span sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + { + return box$( TTStreamO(TokenTree(Token(TOK_STRING, sp.filename))) ); + } +}; + +class CExpanderLine: + public ExpandProcMacro +{ + bool expand_early() const override { return true; } + + ::std::unique_ptr<TokenStream> expand(Span sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + { + return box$( TTStreamO(TokenTree(Token((uint64_t)sp.start_line, CORETYPE_I32))) ); + } +}; + +STATIC_MACRO("file", CExpanderFile); +STATIC_MACRO("line", CExpanderLine); + diff --git a/src/expand/format_args.cpp b/src/expand/format_args.cpp new file mode 100644 index 00000000..d12096a7 --- /dev/null +++ b/src/expand/format_args.cpp @@ -0,0 +1,53 @@ +/* + */ +#include <synext.hpp> +#include "../parse/common.hpp" +#include "../parse/parseerror.hpp" +#include "../parse/tokentree.hpp" +#include "../parse/lex.hpp" + +class CFormatArgsExpander: + public ExpandProcMacro +{ + bool expand_early() const override { return true; } + + ::std::unique_ptr<TokenStream> expand(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"); + + GET_CHECK_TOK(tok, lex, TOK_STRING); + auto format_string = mv$(tok.str()); + + // TODO: Interpolated expression "tokens" + ::std::map< ::std::string, TokenTree> named_args; + ::std::vector<TokenTree> free_args; + + while( GET_TOK(tok, lex) == TOK_COMMA ) + { + if( lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_EQUAL ) + { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + auto name = mv$(tok.str()); + GET_CHECK_TOK(tok, lex, TOK_EQUAL); + auto expr_tt = Parse_TT_Expr(lex); + + named_args.insert( ::std::make_pair(mv$(name), mv$(expr_tt)) ); + } + else + { + auto expr_tt = Parse_TT_Expr(lex); + free_args.push_back( mv$(expr_tt) ); + } + } + + // TODO: Expand format_args! + return box$( TTStreamO(TokenTree(::std::vector<TokenTree>{TokenTree(TOK_PAREN_OPEN), TokenTree(TOK_PAREN_CLOSE)})) ); + } +}; + +STATIC_MACRO("format_args", CFormatArgsExpander); + diff --git a/src/expand/macro_rules.cpp b/src/expand/macro_rules.cpp index fac987ff..bd9348e5 100644 --- a/src/expand/macro_rules.cpp +++ b/src/expand/macro_rules.cpp @@ -10,14 +10,13 @@ class CMacroRulesExpander: { bool expand_early() const override { return true; } - ::std::unique_ptr<TokenStream> expand(Span sp, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + ::std::unique_ptr<TokenStream> expand(Span sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override { if( ident == "" ) ERROR(sp, E0000, "macro_rules! requires an identifier" ); TTStream lex(tt); auto mac = Parse_MacroRules(lex); - // TODO: Place into current module using `ident` as the name mod.add_macro( false, ident, mac ); return box$( TTStreamO(TokenTree()) ); @@ -29,7 +28,7 @@ class CMacroUseHandler: { AttrStage stage() const override { return AttrStage::EarlyPost; } - void handle(const AST::MetaItem& mi, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override + void handle(const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override { TRACE_FUNCTION_F("path=" << path); if( !i.is_Module() ) diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 78225a2f..b7aa6518 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -8,13 +8,14 @@ #include "macro_rules.hpp" #include "../parse/common.hpp" // For reparse from macros #include <ast/expr.hpp> - - -extern bool check_cfg(const ::AST::MetaItem& mi); +#include "cfg.hpp" ::std::map< ::std::string, ::std::unique_ptr<ExpandDecorator> > g_decorators; ::std::map< ::std::string, ::std::unique_ptr<ExpandProcMacro> > g_macros; +void Expand_Attrs(const ::AST::MetaItems& attrs, AttrStage stage, ::std::function<void(const ExpandDecorator& d,const ::AST::MetaItem& a)> f); +void Expand_Mod(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Path modpath, ::AST::Module& mod); + void Register_Synext_Decorator(::std::string name, ::std::unique_ptr<ExpandDecorator> handler) { g_decorators[name] = mv$(handler); } @@ -47,7 +48,7 @@ void Expand_Attrs(const ::AST::MetaItems& attrs, AttrStage stage, ::std::functi for( auto& a : attrs.m_items ) { if( a.name() == "cfg_attr" ) { - if( check_cfg(a.items().at(0)) ) { + if( check_cfg(Span(), a.items().at(0)) ) { Expand_Attr(a.items().at(1), stage, f); } } @@ -62,7 +63,7 @@ void Expand_Attrs(const ::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& } ::std::unique_ptr<TokenStream> Expand_Macro( - bool is_early, LList<const AST::Module*> modstack, ::AST::Module& mod, + bool is_early, const ::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Module& mod, Span mi_span, const ::std::string& name, const ::std::string& input_ident, const TokenTree& input_tt ) { @@ -70,7 +71,7 @@ void Expand_Attrs(const ::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& { if( name == m.first && m.second->expand_early() == is_early ) { - auto e = m.second->expand(mi_span, input_ident, input_tt, mod); + auto e = m.second->expand(mi_span, crate, input_ident, input_tt, mod); return e; } } @@ -114,66 +115,72 @@ void Expand_Attrs(const ::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& // Leave valid and return an empty expression return ::std::unique_ptr<TokenStream>(); } - -void Expand_Expr(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Path item_path, AST::Expr& node) +struct CExpandExpr: + public ::AST::NodeVisitor { - struct CExpandExpr: - public ::AST::NodeVisitor + bool is_early; + ::AST::Crate& crate; + LList<const AST::Module*> modstack; + ::std::unique_ptr<::AST::ExprNode> replacement; + + CExpandExpr(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> ms): + is_early(is_early), + crate(crate), + modstack(ms) { - bool is_early; - LList<const AST::Module*> modstack; - ::std::unique_ptr<::AST::ExprNode> replacement; - - CExpandExpr(bool is_early, LList<const AST::Module*> ms): - is_early(is_early), - modstack(ms) + } + + void visit(::std::unique_ptr<AST::ExprNode>& cnode) { + if(cnode.get()) + Expand_Attrs(cnode->attrs(), stage_pre(is_early), [&](const auto& d, const auto& a){ d.handle(a, this->crate, cnode); }); + if(cnode.get()) { - } - - void visit(::std::unique_ptr<AST::ExprNode>& cnode) { - if(cnode.get()) - Expand_Attrs(cnode->attrs(), stage_pre(is_early), [&](const auto& d, const auto& a){ d.handle(a, cnode); }); - if(cnode.get()) + cnode->visit(*this); + if( auto* n_mac = dynamic_cast<AST::ExprNode_Macro*>(cnode.get()) ) { - cnode->visit(*this); - if( this->replacement.get() ) { - cnode = mv$(this->replacement); - } + if( n_mac->m_name == "" ) + cnode.reset(); } - - if(cnode.get()) - Expand_Attrs(cnode->attrs(), stage_post(is_early), [&](const auto& d, const auto& a){ d.handle(a, cnode); }); - } - void visit_nodelete(const ::AST::ExprNode& parent, ::std::unique_ptr<AST::ExprNode>& cnode) { - if( cnode.get() != nullptr ) - { - this->visit(cnode); - if(cnode.get() == nullptr) - ERROR(parent.get_pos(), E0000, "#[cfg] not allowed in this position"); + if( this->replacement.get() ) { + cnode = mv$(this->replacement); } } - void visit_vector(::std::vector< ::std::unique_ptr<AST::ExprNode> >& cnodes) { - for( auto& child : cnodes ) { - this->visit(child); + + if(cnode.get()) + Expand_Attrs(cnode->attrs(), stage_post(is_early), [&](const auto& d, const auto& a){ d.handle(a, this->crate, cnode); }); + } + void visit_nodelete(const ::AST::ExprNode& parent, ::std::unique_ptr<AST::ExprNode>& cnode) { + if( cnode.get() != nullptr ) + { + this->visit(cnode); + if(cnode.get() == nullptr) + ERROR(parent.get_pos(), E0000, "#[cfg] not allowed in this position"); + } + } + void visit_vector(::std::vector< ::std::unique_ptr<AST::ExprNode> >& cnodes) { + for( auto& child : cnodes ) { + this->visit(child); + } + // Delete null children + for( auto it = cnodes.begin(); it != cnodes.end(); ) { + if( it->get() == nullptr ) { + it = cnodes.erase( it ); } - // Delete null children - for( auto it = cnodes.begin(); it != cnodes.end(); ) { - if( it->get() == nullptr ) { - it = cnodes.erase( it ); - } - else { - ++ it; - } + else { + ++ it; } } - - void visit(::AST::ExprNode_Macro& node) override { - auto ttl = Expand_Macro( - is_early, modstack, *(::AST::Module*)(modstack.m_item), - Span(node.get_pos()), - node.m_name, node.m_ident, node.m_tokens - ); - if( ttl.get() != nullptr && ttl->lookahead(0) != TOK_EOF ) + } + + void visit(::AST::ExprNode_Macro& node) override { + auto ttl = Expand_Macro( + is_early, crate, modstack, *(::AST::Module*)(modstack.m_item), + Span(node.get_pos()), + node.m_name, node.m_ident, node.m_tokens + ); + if( ttl.get() != nullptr ) + { + if( ttl->lookahead(0) != TOK_EOF ) { // Reparse as expression / item auto newexpr = Parse_Expr0(*ttl); @@ -182,98 +189,113 @@ void Expand_Expr(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> m // And schedule it to replace the previous replacement = mv$(newexpr); } + else + { + node.m_name = ""; + } } - - void visit(::AST::ExprNode_Block& node) override { - this->visit_vector(node.m_nodes); - } - void visit(::AST::ExprNode_Flow& node) override { - this->visit_nodelete(node, node.m_value); - } - void visit(::AST::ExprNode_LetBinding& node) override { - // TODO: Pattern and type - this->visit_nodelete(node, node.m_value); - } - void visit(::AST::ExprNode_Assign& node) override { - this->visit_nodelete(node, node.m_slot); - this->visit_nodelete(node, node.m_value); - } - void visit(::AST::ExprNode_CallPath& node) override { - // TODO: path? - this->visit_vector(node.m_args); - } - void visit(::AST::ExprNode_CallMethod& node) override { - this->visit_nodelete(node, node.m_val); - this->visit_vector(node.m_args); - } - void visit(::AST::ExprNode_CallObject& node) override { - this->visit_nodelete(node, node.m_val); - this->visit_vector(node.m_args); - } - void visit(::AST::ExprNode_Loop& node) override { - this->visit_nodelete(node, node.m_cond); - this->visit_nodelete(node, node.m_code); - } - void visit(::AST::ExprNode_Match& node) override { - this->visit_nodelete(node, node.m_val); - // TODO: Arms - } - void visit(::AST::ExprNode_If& node) override { - this->visit_nodelete(node, node.m_cond); - this->visit_nodelete(node, node.m_true); - this->visit_nodelete(node, node.m_false); // TODO: Can the false branch be `#[cfg]`d off? - } - void visit(::AST::ExprNode_IfLet& node) override { - // TODO: Pattern - this->visit_nodelete(node, node.m_value); - this->visit_nodelete(node, node.m_true); - this->visit_nodelete(node, node.m_false); // TODO: Can the false branch be `#[cfg]`d off? - } - void visit(::AST::ExprNode_Integer& node) override { } - void visit(::AST::ExprNode_Float& node) override { } - void visit(::AST::ExprNode_Bool& node) override { } - void visit(::AST::ExprNode_String& node) override { } - void visit(::AST::ExprNode_Closure& node) override { - // TODO: Arg patterns and types - // TODO: Return type - this->visit_nodelete(node, node.m_code); - } - void visit(::AST::ExprNode_StructLiteral& node) override { - this->visit_nodelete(node, node.m_base_value); - // TODO: Values (with #[cfg] support) - } - void visit(::AST::ExprNode_Array& node) override { - this->visit_nodelete(node, node.m_size); - this->visit_vector(node.m_values); - } - void visit(::AST::ExprNode_Tuple& node) override { - this->visit_vector(node.m_values); - } - void visit(::AST::ExprNode_NamedValue& node) override { } - void visit(::AST::ExprNode_Field& node) override { - this->visit_nodelete(node, node.m_obj); - } - void visit(::AST::ExprNode_Index& node) override { - this->visit_nodelete(node, node.m_obj); - this->visit_nodelete(node, node.m_idx); - } - void visit(::AST::ExprNode_Deref& node) override { - this->visit_nodelete(node, node.m_value); - } - void visit(::AST::ExprNode_Cast& node) override { - this->visit_nodelete(node, node.m_value); - // TODO: Type - } - void visit(::AST::ExprNode_BinOp& node) override { - this->visit_nodelete(node, node.m_left); - this->visit_nodelete(node, node.m_right); - } - void visit(::AST::ExprNode_UniOp& node) override { - this->visit_nodelete(node, node.m_value); + } + + void visit(::AST::ExprNode_Block& node) override { + // TODO! Use a proper path here + if( node.m_inner_mod ) { + Expand_Mod(is_early, crate, modstack, AST::Path(), *node.m_inner_mod); } - }; + this->visit_vector(node.m_nodes); + } + void visit(::AST::ExprNode_Flow& node) override { + this->visit_nodelete(node, node.m_value); + } + void visit(::AST::ExprNode_LetBinding& node) override { + // TODO: Pattern and type + this->visit_nodelete(node, node.m_value); + } + void visit(::AST::ExprNode_Assign& node) override { + this->visit_nodelete(node, node.m_slot); + this->visit_nodelete(node, node.m_value); + } + void visit(::AST::ExprNode_CallPath& node) override { + // TODO: path? + this->visit_vector(node.m_args); + } + void visit(::AST::ExprNode_CallMethod& node) override { + this->visit_nodelete(node, node.m_val); + this->visit_vector(node.m_args); + } + void visit(::AST::ExprNode_CallObject& node) override { + this->visit_nodelete(node, node.m_val); + this->visit_vector(node.m_args); + } + void visit(::AST::ExprNode_Loop& node) override { + this->visit_nodelete(node, node.m_cond); + this->visit_nodelete(node, node.m_code); + } + void visit(::AST::ExprNode_Match& node) override { + this->visit_nodelete(node, node.m_val); + // TODO: Arms + } + void visit(::AST::ExprNode_If& node) override { + this->visit_nodelete(node, node.m_cond); + this->visit_nodelete(node, node.m_true); + this->visit_nodelete(node, node.m_false); // TODO: Can the false branch be `#[cfg]`d off? + } + void visit(::AST::ExprNode_IfLet& node) override { + // TODO: Pattern + this->visit_nodelete(node, node.m_value); + this->visit_nodelete(node, node.m_true); + this->visit_nodelete(node, node.m_false); // TODO: Can the false branch be `#[cfg]`d off? + } + void visit(::AST::ExprNode_Integer& node) override { } + void visit(::AST::ExprNode_Float& node) override { } + void visit(::AST::ExprNode_Bool& node) override { } + void visit(::AST::ExprNode_String& node) override { } + void visit(::AST::ExprNode_Closure& node) override { + // TODO: Arg patterns and types + // TODO: Return type + this->visit_nodelete(node, node.m_code); + } + void visit(::AST::ExprNode_StructLiteral& node) override { + this->visit_nodelete(node, node.m_base_value); + // TODO: Values (with #[cfg] support) + } + void visit(::AST::ExprNode_Array& node) override { + this->visit_nodelete(node, node.m_size); + this->visit_vector(node.m_values); + } + void visit(::AST::ExprNode_Tuple& node) override { + this->visit_vector(node.m_values); + } + void visit(::AST::ExprNode_NamedValue& node) override { } + void visit(::AST::ExprNode_Field& node) override { + this->visit_nodelete(node, node.m_obj); + } + void visit(::AST::ExprNode_Index& node) override { + this->visit_nodelete(node, node.m_obj); + this->visit_nodelete(node, node.m_idx); + } + void visit(::AST::ExprNode_Deref& node) override { + this->visit_nodelete(node, node.m_value); + } + void visit(::AST::ExprNode_Cast& node) override { + this->visit_nodelete(node, node.m_value); + // TODO: Type + } + void visit(::AST::ExprNode_BinOp& node) override { + this->visit_nodelete(node, node.m_left); + this->visit_nodelete(node, node.m_right); + } + void visit(::AST::ExprNode_UniOp& node) override { + this->visit_nodelete(node, node.m_value); + } +}; - auto visitor = CExpandExpr(is_early, modstack); +void Expand_Expr(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> modstack, ::std::unique_ptr<AST::ExprNode>& node) { + auto visitor = CExpandExpr(is_early, crate, modstack); + visitor.visit(node); +} +void Expand_Expr(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Path item_path, AST::Expr& node) +{ + auto visitor = CExpandExpr(is_early, crate, modstack); node.visit_nodes(visitor); } @@ -298,7 +320,8 @@ void Expand_Mod(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> mo // Move out of the module to avoid invalidation if a new macro invocation is added auto mi_owned = mv$(mi); - auto ttl = Expand_Macro(is_early, modstack, mod, mi_owned.span(), mi_owned.name(), mi_owned.input_ident(), mi_owned.input_tt()); + auto ttl = Expand_Macro(is_early, crate, modstack, mod, + mi_owned.span(), mi_owned.name(), mi_owned.input_ident(), mi_owned.input_tt()); if( ! ttl.get() ) { @@ -378,14 +401,7 @@ void Expand(::AST::Crate& crate) auto modstack = LList<const ::AST::Module*>(nullptr, &crate.m_root_module); // 1. Crate attributes - for( auto& a : crate.m_attrs.m_items ) - { - for( auto& d : g_decorators ) { - if( d.first == a.name() && d.second->stage() == AttrStage::EarlyPre ) { - d.second->handle(a, crate); - } - } - } + Expand_Attrs(crate.m_attrs, AttrStage::EarlyPre, [&](const auto& d, const auto& a){ d.handle(a, crate); }); // 2. Module attributes for( auto& a : crate.m_attrs.m_items ) diff --git a/src/expand/stringify.cpp b/src/expand/stringify.cpp new file mode 100644 index 00000000..e4abb99b --- /dev/null +++ b/src/expand/stringify.cpp @@ -0,0 +1,28 @@ +/* + */ +#include <synext.hpp> +#include "../parse/common.hpp" + +class CExpander: + public ExpandProcMacro +{ + bool expand_early() const override { return true; } + + ::std::unique_ptr<TokenStream> expand(Span sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + { + Token tok; + ::std::string rv; + + auto lex = TTStream(tt); + while( GET_TOK(tok, lex) != TOK_EOF ) + { + rv += tok.to_str(); + rv += " "; + } + + return box$( TTStreamO(TokenTree(Token(TOK_STRING, mv$(rv)))) ); + } +}; + +STATIC_MACRO("stringify", CExpander); + diff --git a/src/include/span.hpp b/src/include/span.hpp index 05417a83..0a1033e4 100644 --- a/src/include/span.hpp +++ b/src/include/span.hpp @@ -64,6 +64,7 @@ struct Spanned }; #define ERROR(span, code, msg) do { ::Span(span).error(code, [&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Error fell through" #code); } while(0) +#define WARNING(span, code, msg) do { ::Span(span).warning(code, [&](::std::ostream& os) { os << msg; }); } while(0) #define BUG(span, msg) do { ::Span(span).bug([&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Bug fell through"); } while(0) #define TODO(span, msg) do { ::Span(span).bug([&](::std::ostream& os) { os << "TODO: " << msg; }); throw ::std::runtime_error("Bug (todo) fell through"); } while(0) diff --git a/src/include/synext.hpp b/src/include/synext.hpp index 3ab594a5..aa72e985 100644 --- a/src/include/synext.hpp +++ b/src/include/synext.hpp @@ -44,7 +44,7 @@ public: virtual void handle(const AST::MetaItem& mi, AST::Crate& crate) const {} virtual void handle(const AST::MetaItem& mi, AST::Crate& crate, AST::MacroInvocation& mac) const {} virtual void handle(const AST::MetaItem& mi, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const {} - virtual void handle(const AST::MetaItem& mi, ::std::unique_ptr<AST::ExprNode>& expr) const {}; + virtual void handle(const AST::MetaItem& mi, AST::Crate& crate, ::std::unique_ptr<AST::ExprNode>& expr) const {}; }; enum class MacroPosition @@ -61,7 +61,7 @@ class ExpandProcMacro public: virtual bool expand_early() const = 0; - virtual ::std::unique_ptr<TokenStream> expand(Span sp, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) = 0; + virtual ::std::unique_ptr<TokenStream> expand(Span sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) = 0; }; #define STATIC_DECORATOR(ident, _handler_class) \ @@ -80,5 +80,8 @@ public: extern void Register_Synext_Decorator(::std::string name, ::std::unique_ptr<ExpandDecorator> handler); extern void Register_Synext_Macro(::std::string name, ::std::unique_ptr<ExpandProcMacro> handler); + +extern void Expand_Expr(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> modstack, ::std::unique_ptr<AST::ExprNode>& node); + #endif diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp index d0d6ef7e..7019f34e 100644 --- a/src/include/tagged_union.hpp +++ b/src/include/tagged_union.hpp @@ -197,8 +197,8 @@ class _name TU_EXP _inherit { \ _name(): m_tag(TAG_##_def) { new((void*)m_data) TU_DATANAME(_def); }/* */ _name(const _name&) = delete;/* */ _name(_name&& x) noexcept: m_tag(x.m_tag) TU_EXP _extra_move { switch(m_tag) { TU_MOVE_CASES _variants } }/* -*/ _name& operator =(_name&& x) { this->~_name(); m_tag = x.m_tag; TU_EXP _extra_assign switch(m_tag) { TU_MOVE_CASES _variants }; return *this; }/* -*/ ~_name() { switch(m_tag) { TU_DEST_CASES _variants } } \ +*/ _name& operator =(_name&& x) { switch(m_tag) { TU_DEST_CASES _variants } m_tag = x.m_tag; TU_EXP _extra_assign switch(m_tag) { TU_MOVE_CASES _variants }; return *this; }/* +*/ ~_name() { switch(m_tag) { TU_DEST_CASES _variants } m_tag = TAG_##_def; new((void*)m_data) TU_DATANAME(_def); } \ \ Tag tag() const { return m_tag; }\ TU_CONSS(_name, TU_EXP _variants) \ diff --git a/src/main.cpp b/src/main.cpp index 47be9ebc..ddc233fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,7 @@ #include <cstring>
#include <main_bindings.hpp>
+#include "expand/cfg.hpp"
int g_debug_indent_level = 0;
::std::string g_cur_phase;
@@ -70,6 +71,11 @@ int main(int argc, char *argv[]) ProgramParams params(argc, argv);
+ // Set up cfg values
+ Cfg_SetFlag("linux");
+ Cfg_SetValue("target_pointer_width", "64");
+
+
try
{
diff --git a/src/synexts/derive.cpp b/src/synexts/derive.cpp index 5849e280..e4c10f4e 100644 --- a/src/synexts/derive.cpp +++ b/src/synexts/derive.cpp @@ -149,7 +149,7 @@ class Decorator_Derive: { public: AttrStage stage() const override { return AttrStage::LatePost; } - void handle(const AST::MetaItem& attr, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override + void handle(const AST::MetaItem& attr, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override { TU_MATCH_DEF(::AST::Item, (i), (e), ( |