diff options
-rw-r--r-- | src/ast/attrs.hpp | 81 | ||||
-rw-r--r-- | src/ast/expr.cpp | 16 | ||||
-rw-r--r-- | src/ast/path.cpp | 2 | ||||
-rw-r--r-- | src/ast/path.hpp | 5 | ||||
-rw-r--r-- | src/ast/pattern.cpp | 34 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 8 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 37 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 26 | ||||
-rw-r--r-- | src/parse/expr.cpp | 27 | ||||
-rw-r--r-- | src/parse/parseerror.hpp | 2 | ||||
-rw-r--r-- | src/parse/paths.cpp | 4 | ||||
-rw-r--r-- | src/parse/pattern.cpp | 48 | ||||
-rw-r--r-- | src/parse/root.cpp | 69 | ||||
-rw-r--r-- | src/synexts/derive.cpp | 6 |
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; |