summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/attrs.hpp81
-rw-r--r--src/ast/expr.cpp16
-rw-r--r--src/ast/path.cpp2
-rw-r--r--src/ast/path.hpp5
-rw-r--r--src/ast/pattern.cpp34
-rw-r--r--src/ast/pattern.hpp8
-rw-r--r--src/convert/ast_iterate.cpp37
-rw-r--r--src/dump_as_rust.cpp26
-rw-r--r--src/parse/expr.cpp27
-rw-r--r--src/parse/parseerror.hpp2
-rw-r--r--src/parse/paths.cpp4
-rw-r--r--src/parse/pattern.cpp48
-rw-r--r--src/parse/root.cpp69
-rw-r--r--src/synexts/derive.cpp6
14 files changed, 328 insertions, 37 deletions
diff --git a/src/ast/attrs.hpp b/src/ast/attrs.hpp
new file mode 100644
index 00000000..ebbad066
--- /dev/null
+++ b/src/ast/attrs.hpp
@@ -0,0 +1,81 @@
+#ifndef _AST_ATTRS_HPP_
+#define _AST_ATTRS_HPP_
+
+
+namespace AST {
+
+//
+class MetaItem;
+
+class MetaItems:
+ public Serialisable
+{
+public:
+ ::std::vector<MetaItem> m_items;
+
+ MetaItems() {}
+ MetaItems(::std::vector<MetaItem> items):
+ m_items(items)
+ {
+ }
+
+ void push_back(MetaItem i);
+
+ MetaItem* get(const char *name);
+ bool has(const char *name) {
+ return get(name) != 0;
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const MetaItems& x) {
+ return os << "[" << x.m_items << "]";
+ }
+
+ SERIALISABLE_PROTOTYPES();
+};
+
+class MetaItem:
+ public Serialisable
+{
+ ::std::string m_name;
+ MetaItems m_sub_items;
+ ::std::string m_str_val;
+public:
+ MetaItem() {}
+ MetaItem(::std::string name):
+ m_name(name)
+ {
+ }
+ MetaItem(::std::string name, ::std::string str_val):
+ m_name(name),
+ m_str_val(str_val)
+ {
+ }
+ MetaItem(::std::string name, ::std::vector<MetaItem> items):
+ m_name(name),
+ m_sub_items(items)
+ {
+ }
+
+ void mark_used() {}
+ const ::std::string& name() const { return m_name; }
+ const ::std::string& string() const { return m_str_val; }
+ bool has_sub_items() const { return m_sub_items.m_items.size() > 0; }
+ const MetaItems& items() const { return m_sub_items; }
+ MetaItems& items() { return m_sub_items; }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const MetaItem& x) {
+ os << x.m_name;
+ if(x.m_sub_items.m_items.size())
+ os << "(" << x.m_sub_items.m_items << ")";
+ else
+ os << "=\"" << x.m_str_val << "\"";
+ return os;
+ }
+
+ SERIALISABLE_PROTOTYPES();
+};
+
+} // namespace AST
+
+#endif
+
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
index 48e080d6..dc0eb59f 100644
--- a/src/ast/expr.cpp
+++ b/src/ast/expr.cpp
@@ -7,15 +7,19 @@ namespace AST {
void Expr::visit_nodes(NodeVisitor& v)
{
- assert(!!m_node);
- m_node->visit(v);
+ if( m_node )
+ {
+ m_node->visit(v);
+ }
}
void Expr::visit_nodes(NodeVisitor& v) const
{
- assert(!!m_node);
- assert(v.is_const());
- //const_cast<const ExprNode*>(m_node.get())->visit(v);
- m_node->visit(v);
+ if( m_node )
+ {
+ assert(v.is_const());
+ //const_cast<const ExprNode*>(m_node.get())->visit(v);
+ m_node->visit(v);
+ }
}
::std::ostream& operator<<(::std::ostream& os, const Expr& pat)
{
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index 9ad36515..5c0510fe 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -110,7 +110,7 @@ AST::Path::Path(const Path& x):
m_class = Class::make_Self({nodes: ent.nodes});
),
(Super,
- m_class = Class::make_Super({nodes: ent.nodes});
+ m_class = Class::make_Super({count: ent.count, nodes: ent.nodes});
),
(Absolute,
m_class = Class::make_Absolute({nodes: ent.nodes});
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index cbe009f9..1260ece3 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -114,6 +114,7 @@ public:
::std::vector<PathNode> nodes;
) ),
(Super, ( // Parent-relative
+ unsigned int count;
::std::vector<PathNode> nodes;
) ),
(Absolute, ( // Absolute
@@ -184,8 +185,8 @@ public:
{}
// SUPER
struct TagSuper {};
- Path(TagSuper, ::std::vector<PathNode> nodes):
- m_class( Class::make_Super({nodes: nodes}) )
+ Path(TagSuper, unsigned int count, ::std::vector<PathNode> nodes):
+ m_class( Class::make_Super({count: count, nodes: mv$(nodes)}) )
{}
void set_crate(::std::string crate) {
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp
index 7ebdb35d..35df2a1e 100644
--- a/src/ast/pattern.cpp
+++ b/src/ast/pattern.cpp
@@ -43,6 +43,30 @@ namespace AST {
),
(Struct,
os << ent.path << " {" << ent.sub_patterns << "}";
+ ),
+ (Slice,
+ os << "[";
+ bool needs_comma = false;
+ if(ent.leading.size()) {
+ os << ent.leading;
+ needs_comma = true;
+ }
+ if(ent.extra_bind.size() > 0) {
+ if( needs_comma ) {
+ os << ", ";
+ }
+ if(ent.extra_bind != "_")
+ os << ent.extra_bind;
+ os << "..";
+ needs_comma = true;
+ }
+ if(ent.trailing.size()) {
+ if( needs_comma ) {
+ os << ", ";
+ }
+ os << ent.trailing;
+ }
+ os << "]";
)
)
os << ")";
@@ -89,6 +113,11 @@ SERIALISE_TYPE(Pattern::, "Pattern", {
(Struct,
s << e.path;
s << e.sub_patterns;
+ ),
+ (Slice,
+ s << e.leading;
+ s << e.extra_bind;
+ s << e.trailing;
)
)
},{
@@ -125,6 +154,11 @@ SERIALISE_TYPE(Pattern::, "Pattern", {
s.item( ent.path );
s.item( ent.sub_patterns );
)
+ _D(Slice,
+ s.item( ent.leading );
+ s.item( ent.extra_bind );
+ s.item( ent.trailing );
+ )
}
});
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
index 6cd78e91..ce4844f9 100644
--- a/src/ast/pattern.hpp
+++ b/src/ast/pattern.hpp
@@ -28,7 +28,8 @@ public:
(Value, (unique_ptr<ExprNode> start; unique_ptr<ExprNode> end;) ),
(Tuple, (::std::vector<Pattern> sub_patterns;) ),
(StructTuple, (Path path; ::std::vector<Pattern> sub_patterns;) ),
- (Struct, (Path path; ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns;) )
+ (Struct, (Path path; ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns;) ),
+ (Slice, (::std::vector<Pattern> leading; ::std::string extra_bind; ::std::vector<Pattern> trailing;) )
);
private:
::std::string m_binding;
@@ -93,6 +94,11 @@ public:
Pattern(TagStruct, Path path, ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns):
m_data( Data::make_Struct( { ::std::move(path), ::std::move(sub_patterns) } ) )
{}
+
+ struct TagSlice {};
+ Pattern(TagSlice):
+ m_data( Data::make_Slice( {} ) )
+ {}
// Mutators
void set_bind(::std::string name, bool is_ref, bool is_mut) {
diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp
index f5bc805e..142064e6 100644
--- a/src/convert/ast_iterate.cpp
+++ b/src/convert/ast_iterate.cpp
@@ -237,7 +237,37 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
)
)
}
- })
+ }),
+ (Slice,
+ TypeRef null_type;
+ const auto* inner_type = &null_type;
+ if( !type_hint.is_wildcard() )
+ {
+ TU_MATCH_DEF( TypeData, (type_hint.m_data), (v),
+ (
+ ERROR(Span(), E0000, "Slice pattern on non-slice/array");
+ ),
+ (Array,
+ inner_type = v.inner.get();
+ ),
+ (Borrow,
+ if( v.inner->is_wildcard() ) {
+ }
+ else if( v.inner->m_data.is_Array() ) {
+ inner_type = v.inner->m_data.as_Array().inner.get();
+ }
+ else {
+ // TODO: Deref more?
+ ERROR(Span(), E0000, "Slice pattern on non-slice/array");
+ }
+ )
+ )
+ }
+ for( auto& sp : v.leading )
+ handle_pattern(sp, *inner_type);
+ for( auto& sp : v.trailing )
+ handle_pattern(sp, *inner_type);
+ )
)
// Extract bindings and add to namespace
if( pat.binding().size() > 0 )
@@ -289,7 +319,10 @@ void CASTIterator::handle_module(AST::Path path, AST::Module& mod)
{
DEBUG("handling static " << stat.name);
handle_type(stat.data.type());
- handle_expr(stat.data.value().node());
+ if( stat.data.value().is_valid() )
+ {
+ handle_expr(stat.data.value().node());
+ }
}
for( auto& fcn : mod.functions() )
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp
index f7f1d30b..86439115 100644
--- a/src/dump_as_rust.cpp
+++ b/src/dump_as_rust.cpp
@@ -797,7 +797,31 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable)
m_os << ",";
}
m_os << ")";
- })
+ }),
+ (Slice,
+ m_os << "[";
+ bool needs_comma = false;
+ if(v.leading.size()) {
+ m_os << v.leading;
+ needs_comma = true;
+ }
+ if(v.extra_bind.size() > 0) {
+ if( needs_comma ) {
+ m_os << ", ";
+ }
+ if(v.extra_bind != "_")
+ m_os << v.extra_bind;
+ m_os << "..";
+ needs_comma = true;
+ }
+ if(v.trailing.size()) {
+ if( needs_comma ) {
+ m_os << ", ";
+ }
+ m_os << v.trailing;
+ }
+ m_os << "]";
+ )
)
}
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index 47443ee1..1026b5f5 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -64,6 +64,7 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex)
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
{
+ DEBUG("tok = " << tok);
AST::MetaItems item_attrs;
while( tok.type() == TOK_ATTR_OPEN )
{
@@ -202,8 +203,12 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex)
lex.putback(tok);
bool expect_end = false;
nodes.push_back(Parse_ExprBlockLine(lex, &expect_end));
- // TODO: VVV
- //nodes.back().set_attrs( item_attrs );
+ if( nodes.back() ) {
+ nodes.back()->set_attrs( mv$(item_attrs) );
+ }
+ else {
+ // TODO: Error if attribute on void expression?
+ }
// Set to TRUE if there was no semicolon after a statement
if( expect_end )
{
@@ -477,13 +482,14 @@ ExprNodeP Parse_Expr_Match(TokenStream& lex)
TRACE_FUNCTION;
Token tok;
+ CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
// 1. Get expression
ExprNodeP switch_val;
{
SET_PARSE_FLAG(lex, disallow_struct_literal);
switch_val = Parse_Expr1(lex);
}
- ASSERT(lex, !CHECK_PARSE_FLAG(lex, disallow_struct_literal) );
+ //ASSERT(lex, !CHECK_PARSE_FLAG(lex, disallow_struct_literal) );
GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
::std::vector< AST::ExprNode_Match::Arm > arms;
@@ -586,6 +592,9 @@ ExprNodeP Parse_Stmt(TokenStream& lex)
}
return NEWNODE( AST::ExprNode_Flow, type, lifetime, ::std::move(val) );
}
+ case TOK_BRACE_OPEN:
+ lex.putback(tok);
+ return Parse_ExprBlockNode(lex);
default:
lex.putback(tok);
return Parse_Expr0(lex);
@@ -605,6 +614,10 @@ ExprNodeP Parse_Stmt(TokenStream& lex)
{
lex.putback(tok);
do {
+ if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE ) {
+ GET_TOK(tok, lex);
+ break;
+ }
rv.push_back( Parse_Stmt(lex) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_PAREN_CLOSE);
@@ -1077,7 +1090,13 @@ ExprNodeP Parse_ExprVal(TokenStream& lex)
case TOK_RWORD_SUPER:
{
GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- path = AST::Path(AST::Path::TagSuper(), Parse_PathNodes(lex, PATH_GENERIC_EXPR));
+ unsigned int count = 1;
+ while( LOOK_AHEAD(lex) == TOK_RWORD_SUPER ) {
+ count += 1;
+ GET_TOK(tok, lex);
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
+ }
+ path = AST::Path(AST::Path::TagSuper(), count, Parse_PathNodes(lex, PATH_GENERIC_EXPR));
}
if(0)
case TOK_IDENT:
diff --git a/src/parse/parseerror.hpp b/src/parse/parseerror.hpp
index bae5de6a..1888a105 100644
--- a/src/parse/parseerror.hpp
+++ b/src/parse/parseerror.hpp
@@ -32,7 +32,7 @@ public:
};
-#define ASSERT(lex, cnd) do { if( !(cnd) ) throw CompileError::BugCheck(lex, "Assertion failed: "#cnd); } while(0)
+#define ASSERT(lex, cnd) do { if( !(cnd) ) throw CompileError::BugCheck(lex, "Assertion failed: " __FILE__ " - " #cnd); } while(0)
}
diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp
index 1b48dbb3..c3618e85 100644
--- a/src/parse/paths.cpp
+++ b/src/parse/paths.cpp
@@ -171,6 +171,10 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
::std::map< ::std::string, TypeRef> assoc_bounds;
::std::vector<unsigned int> int_args;
do {
+ if( LOOK_AHEAD(lex) == TOK_GT || LOOK_AHEAD(lex) == TOK_DOUBLE_GT ) {
+ GET_TOK(tok, lex);
+ break;
+ }
switch(GET_TOK(tok, lex))
{
case TOK_LIFETIME:
diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp
index 4e4fa862..12f35aa7 100644
--- a/src/parse/pattern.cpp
+++ b/src/parse/pattern.cpp
@@ -16,6 +16,7 @@ using AST::ExprNode;
::std::vector<AST::Pattern> Parse_PatternList(TokenStream& lex, bool is_refutable);
+AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable);
AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_refutable);
AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable);
AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refutable);
@@ -198,9 +199,9 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable)
case TOK_BYTESTRING:
return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_String, tok.str()) );
case TOK_PAREN_OPEN:
- return AST::Pattern(AST::Pattern::TagTuple(), Parse_PatternList(lex, is_refutable));
+ return AST::Pattern( AST::Pattern::TagTuple(), Parse_PatternList(lex, is_refutable) );
case TOK_SQUARE_OPEN:
- throw ParseError::Todo(lex, "array patterns");
+ return Parse_PatternReal_Slice(lex, is_refutable);
default:
throw ParseError::Unexpected(lex, tok);
}
@@ -221,6 +222,49 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_re
}
}
+AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable)
+{
+ auto sp = lex.start_span();
+ Token tok;
+
+ auto rv = ::AST::Pattern( AST::Pattern::TagSlice() );
+ auto& rv_array = rv.data().as_Slice();
+
+ bool is_trailing = false;
+ while(GET_TOK(tok, lex) != TOK_SQUARE_CLOSE)
+ {
+ if( tok.type() == TOK_IDENT && lex.lookahead(1) == TOK_DOUBLE_DOT) {
+ if(is_trailing)
+ ERROR(lex.end_span(sp), E0000, "Multiple instances of .. in a slice pattern");
+ rv_array.extra_bind = mv$(tok.str());
+ is_trailing = true;
+
+ GET_TOK(tok, lex); // TOK_DOUBLE_DOT
+ }
+ else if( tok.type() == TOK_DOUBLE_DOT ) {
+ if(is_trailing)
+ ERROR(lex.end_span(sp), E0000, "Multiple instances of .. in a slice pattern");
+ rv_array.extra_bind = "_";
+ is_trailing = true;
+ }
+ else {
+ lex.putback(tok);
+ if(is_trailing) {
+ rv_array.trailing.push_back( Parse_Pattern(lex, is_refutable) );
+ }
+ else {
+ rv_array.leading.push_back( Parse_Pattern(lex, is_refutable) );
+ }
+ }
+
+ if( GET_TOK(tok, lex) != TOK_COMMA )
+ break;
+ }
+ CHECK_TOK(tok, TOK_SQUARE_CLOSE);
+
+ return rv;
+}
+
::std::vector<AST::Pattern> Parse_PatternList(TokenStream& lex, bool is_refutable)
{
TRACE_FUNCTION;
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index d9e47626..5706d958 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -437,7 +437,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items)
break;
}
CHECK_TOK(tok, TOK_PAREN_CLOSE);
-
+
if(LOOK_AHEAD(lex) == TOK_RWORD_WHERE)
{
GET_TOK(tok, lex);
@@ -445,8 +445,8 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items)
}
// TODO: Where block
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- if( refs.size() == 0 )
- throw ParseError::Generic(lex, "Use 'struct Name;' instead of 'struct Name();' ... ning-nong");
+ //if( refs.size() == 0 )
+ // WARNING( , W000, "Use 'struct Name;' instead of 'struct Name();' ... ning-nong");
return AST::Struct(::std::move(meta_items), ::std::move(params), ::std::move(refs));
}
else if(tok.type() == TOK_SEMICOLON)
@@ -484,8 +484,8 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items)
break;
CHECK_TOK(tok, TOK_COMMA);
}
- if( items.size() == 0 )
- throw ParseError::Generic(lex, "Use 'struct Name;' instead of 'struct Name { }' ... ning-nong");
+ //if( items.size() == 0 )
+ // WARNING( , W000, "Use 'struct Name;' instead of 'struct Nam { };' ... ning-nong");
return AST::Struct(::std::move(meta_items), ::std::move(params), ::std::move(items));
}
else
@@ -693,6 +693,11 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items)
// Get type list
do
{
+ if(LOOK_AHEAD(lex) == TOK_PAREN_CLOSE)
+ {
+ GET_TOK(tok, lex);
+ break;
+ }
types.push_back( Parse_Type(lex) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_PAREN_CLOSE);
@@ -704,6 +709,11 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items)
::std::vector<::AST::StructItem> fields;
do
{
+ if(LOOK_AHEAD(lex) == TOK_BRACE_CLOSE)
+ {
+ GET_TOK(tok, lex);
+ break;
+ }
GET_CHECK_TOK(tok, lex, TOK_IDENT);
auto name = mv$(tok.str());
GET_CHECK_TOK(tok, lex, TOK_COLON);
@@ -749,10 +759,16 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex)
return AST::MetaItem(name, tok.str());
case TOK_PAREN_OPEN: {
::std::vector<AST::MetaItem> items;
- do {
- items.push_back(Parse_MetaItem(lex));
- } while(GET_TOK(tok, lex) == TOK_COMMA);
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ if( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE )
+ {
+ do {
+ items.push_back(Parse_MetaItem(lex));
+ } while(GET_TOK(tok, lex) == TOK_COMMA);
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ }
+ else {
+ GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
+ }
return AST::MetaItem(name, items); }
default:
lex.putback(tok);
@@ -983,8 +999,17 @@ void Parse_ExternBlock(TokenStream& lex, AST::Module& mod, ::std::string abi)
mod.add_function(is_public, tok.str(), Parse_FunctionDef(lex, abi, ::std::move(meta_items), false, true));
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break;
+ case TOK_RWORD_STATIC: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto type = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ mod.add_static(is_public, mv$(name), ::AST::Static(mv$(meta_items), ::AST::Static::STATIC, type, ::AST::Expr()));
+ break; }
default:
- throw ParseError::Unexpected(lex, tok);
+ throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_STATIC});
}
}
}
@@ -1028,9 +1053,15 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)>
case TOK_RWORD_SELF:
path = AST::Path( AST::Path::TagSelf(), {} ); // relative path
break;
- case TOK_RWORD_SUPER:
- path = AST::Path( AST::Path::TagSuper(), {} );
- break;
+ case TOK_RWORD_SUPER: {
+ unsigned int count = 1;
+ while( LOOK_AHEAD(lex) == TOK_DOUBLE_COLON && lex.lookahead(1) == TOK_RWORD_SUPER ) {
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_SUPER);
+ count += 1;
+ }
+ path = AST::Path( AST::Path::TagSuper(), count, {} );
+ break; }
case TOK_IDENT:
path.append( AST::PathNode(tok.str(), {}) );
break;
@@ -1147,8 +1178,10 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)>
ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_TYPE) );
else if( type == "meta" )
ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_META) );
+ else if( type == "block" )
+ ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_BLOCK) );
else
- throw ParseError::Generic(lex, FMT("Unknown fragment type " << type));
+ throw ParseError::Generic(lex, FMT("Unknown fragment type '" << type << "'"));
break; }
case TOK_PAREN_OPEN:
if( allow_sub )
@@ -1513,7 +1546,8 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod,
break; }
// `extern fn ...`
case TOK_RWORD_FN:
- throw ParseError::Todo(lex, "'extern fn'");
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "C", ::std::move(meta_items), false));
break;
// `extern { ...`
case TOK_BRACE_OPEN:
@@ -1544,6 +1578,11 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod,
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
mod.add_static(is_public, name, AST::Static(::std::move(meta_items), AST::Static::CONST, type, val));
break; }
+ case TOK_RWORD_UNSAFE:
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false));
+ break;
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
// - self not allowed, not prototype
diff --git a/src/synexts/derive.cpp b/src/synexts/derive.cpp
index 749da870..b8741cfe 100644
--- a/src/synexts/derive.cpp
+++ b/src/synexts/derive.cpp
@@ -113,8 +113,10 @@ static const Deriver* find_impl(const ::std::string& trait_name)
template<typename T>
static void derive_item(AST::Module& mod, const AST::MetaItem& attr, const AST::Path& path, const T& item)
{
- if( !attr.has_sub_items() )
- throw CompileError::Generic("#[derive()] requires a list of known traits to derive");
+ if( !attr.has_sub_items() ) {
+ //throw CompileError::Generic("#[derive()] requires a list of known traits to derive");
+ return ;
+ }
DEBUG("path = " << path);
bool fail = false;