summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--src/expand/cfg.cpp81
-rw-r--r--src/expand/cfg.hpp6
-rw-r--r--src/expand/concat.cpp50
-rw-r--r--src/expand/file_line.cpp30
-rw-r--r--src/expand/format_args.cpp53
-rw-r--r--src/expand/macro_rules.cpp5
-rw-r--r--src/expand/mod.cpp324
-rw-r--r--src/expand/stringify.cpp28
-rw-r--r--src/include/span.hpp1
-rw-r--r--src/include/synext.hpp7
-rw-r--r--src/include/tagged_union.hpp4
-rw-r--r--src/main.cpp6
-rw-r--r--src/synexts/derive.cpp2
14 files changed, 425 insertions, 175 deletions
diff --git a/Makefile b/Makefile
index f34e5e01..f4bf8931 100644
--- a/Makefile
+++ b/Makefile
@@ -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),
(