From beaad85791e078f9128fbab3f5758e001340a6a8 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 25 Feb 2016 13:52:39 +0800 Subject: Heaps more parse fixes against the rustc tests --- src/ast/attrs.hpp | 81 +++++++++++++++++++++++++++++++++++++++++++++ src/ast/expr.cpp | 16 +++++---- src/ast/path.cpp | 2 +- src/ast/path.hpp | 5 +-- src/ast/pattern.cpp | 34 +++++++++++++++++++ src/ast/pattern.hpp | 8 ++++- src/convert/ast_iterate.cpp | 37 +++++++++++++++++++-- src/dump_as_rust.cpp | 26 ++++++++++++++- src/parse/expr.cpp | 27 ++++++++++++--- src/parse/parseerror.hpp | 2 +- src/parse/paths.cpp | 4 +++ src/parse/pattern.cpp | 48 +++++++++++++++++++++++++-- src/parse/root.cpp | 69 +++++++++++++++++++++++++++++--------- src/synexts/derive.cpp | 6 ++-- 14 files changed, 328 insertions(+), 37 deletions(-) create mode 100644 src/ast/attrs.hpp (limited to 'src') 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 m_items; + + MetaItems() {} + MetaItems(::std::vector 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 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(m_node.get())->visit(v); - m_node->visit(v); + if( m_node ) + { + assert(v.is_const()); + //const_cast(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 nodes; ) ), (Super, ( // Parent-relative + unsigned int count; ::std::vector nodes; ) ), (Absolute, ( // Absolute @@ -184,8 +185,8 @@ public: {} // SUPER struct TagSuper {}; - Path(TagSuper, ::std::vector nodes): - m_class( Class::make_Super({nodes: nodes}) ) + Path(TagSuper, unsigned int count, ::std::vector 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 start; unique_ptr end;) ), (Tuple, (::std::vector sub_patterns;) ), (StructTuple, (Path path; ::std::vector 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 leading; ::std::string extra_bind; ::std::vector 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 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 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 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 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 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 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 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; -- cgit v1.2.3