From 80e4060188913eb12ad8a774b07d3b938485a49a Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Fri, 16 Jan 2015 09:14:38 +0800 Subject: Added associated type reference parse, and tuple value parse --- samples/std.rs | 2 +- src/ast/ast.cpp | 6 +++ src/ast/ast.hpp | 73 ++++++++++++++++++++++---------- src/ast/expr.cpp | 4 ++ src/ast/expr.hpp | 22 +++++++++- src/parse/expr.cpp | 13 +++++- src/parse/root.cpp | 119 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/types.hpp | 11 +++++ 8 files changed, 216 insertions(+), 34 deletions(-) diff --git a/samples/std.rs b/samples/std.rs index 23f9b1b6..26039934 100644 --- a/samples/std.rs +++ b/samples/std.rs @@ -33,7 +33,7 @@ pub mod iter { type Item; fn next(&self) -> Option<::Item>; - fn size_hint(&self) -> (usize, Option(usize)) { + fn size_hint(&self) -> (usize, Option) { return (0, None); } } diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index a9336c31..f176122b 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -230,6 +230,12 @@ SERIALISE_TYPE(Function::, "AST_Function", { //s << m_code; }) +SERIALISE_TYPE(Trait::, "AST_Trait", { + s << m_params; + s << m_types; + s << m_functions; +}) + SERIALISE_TYPE(Enum::, "AST_Enum", { s << m_params; s << m_variants; diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index f04c5ab0..f5f9b2fb 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -51,6 +51,30 @@ public: SERIALISABLE_PROTOTYPES(); }; +template +struct Item: + public Serialisable +{ + ::std::string name; + T data; + bool is_pub; + + Item(::std::string&& name, T&& data, bool is_pub): + name( move(name) ), + data( move(data) ), + is_pub( is_pub ) + { + } + + SERIALISE_TYPE(, "Item", { + s << is_pub; + s << name; + s << data; + }) +}; +template +using ItemList = ::std::vector >; + typedef ::std::vector TypeParams; typedef ::std::pair< ::std::string, TypeRef> StructItem; @@ -161,6 +185,28 @@ public: SERIALISABLE_PROTOTYPES(); }; +class Trait: + public Serialisable +{ + ::std::vector m_params; + ItemList m_types; + ItemList m_functions; +public: + Trait(TypeParams params): + m_params(params) + { + } + + void add_type(::std::string name, TypeRef type) { + m_types.push_back( Item(move(name), move(type), true) ); + } + void add_function(::std::string name, Function fcn) { + m_functions.push_back( Item(move(name), move(fcn), true) ); + } + + SERIALISABLE_PROTOTYPES(); +}; + class Enum: public Serialisable { @@ -195,28 +241,6 @@ public: SERIALISABLE_PROTOTYPES(); }; -template -struct Item: - public Serialisable -{ - ::std::string name; - T data; - bool is_pub; - - Item(::std::string&& name, T&& data, bool is_pub): - name( move(name) ), - data( move(data) ), - is_pub( is_pub ) - { - } - - SERIALISE_TYPE(, "Item", { - s << is_pub; - s << name; - s << data; - }) -}; - class Impl: public Serialisable { @@ -277,6 +301,7 @@ class Module: itemlist_static_t m_statics; + ItemList m_traits; itemlist_enum_t m_enums; itemlist_struct_t m_structs; ::std::vector m_impls; @@ -298,6 +323,9 @@ public: void add_global(bool is_public, bool is_mut, ::std::string name, TypeRef type, Expr val) { m_statics.push_back( Item( move(name), Static(is_mut ? Static::MUT : Static::STATIC, move(type), move(val)), is_public) ); } + void add_trait(bool is_public, ::std::string name, Trait trait) { + m_traits.push_back( Item( move(name), move(trait), is_public) ); + } void add_struct(bool is_public, ::std::string name, TypeParams params, ::std::vector items) { m_structs.push_back( Item( move(name), Struct(move(params), move(items)), is_public) ); } @@ -337,6 +365,7 @@ public: const ::std::vector >& type_aliases() const { return m_type_aliases; } const itemlist_ext_t& extern_crates() const { return m_extern_crates; } const itemlist_static_t& statics() const { return m_statics; } + const ItemList& traits() const { return m_traits; } const itemlist_enum_t& enums () const { return m_enums; } const itemlist_struct_t& structs() const { return m_structs; } diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index a5401fef..b125eea3 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -63,6 +63,10 @@ void ExprNode_StructLiteral::visit(NodeVisitor& nv) { nv.visit(*this); } +void ExprNode_Tuple::visit(NodeVisitor& nv) { + nv.visit(*this); +} + void ExprNode_NamedValue::visit(NodeVisitor& nv) { nv.visit(*this); } diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 340d0bb2..bf238c6f 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -202,6 +202,18 @@ struct ExprNode_StructLiteral: virtual void visit(NodeVisitor& nv) override; }; +// Tuple +struct ExprNode_Tuple: + public ExprNode +{ + ::std::vector< unique_ptr > m_values; + + ExprNode_Tuple(::std::vector< unique_ptr > vals): + m_values( ::std::move(vals) ) + {} + + virtual void visit(NodeVisitor& nv) override; +}; // Variable / Constant struct ExprNode_NamedValue: public ExprNode @@ -329,6 +341,10 @@ public: for( auto& val : node.m_values ) visit(val.second); } + virtual void visit(ExprNode_Tuple& node) { + for( auto& val : node.m_values ) + visit(val); + } virtual void visit(ExprNode_NamedValue& node) { // LEAF } @@ -357,8 +373,12 @@ public: m_node(node) { } + Expr(): + m_node(nullptr) + { + } - ::std::shared_ptr take_node() { return ::std::move(m_node); } + ::std::shared_ptr take_node() { assert(m_node.get()); return ::std::move(m_node); } void visit_nodes(NodeVisitor& v); friend ::std::ostream& operator<<(::std::ostream& os, const Expr& pat); diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index fdf35740..3899a3c3 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -491,7 +491,18 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) return NEWNODE( AST::ExprNode_NamedValue, AST::Path(AST::Path::TagLocal(), "self") ); case TOK_PAREN_OPEN: { ExprNodeP rv = Parse_Expr0(lex); - GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); + if( GET_TOK(tok, lex) == TOK_COMMA ) { + ::std::vector ents; + ents.push_back( ::std::move(rv) ); + do { + if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) + break; + lex.putback(tok); + ents.push_back( Parse_Expr0(lex) ); + } while( GET_TOK(tok, lex) == TOK_COMMA ); + rv = NEWNODE( AST::ExprNode_Tuple, ::std::move(ents) ); + } + CHECK_TOK(tok, TOK_PAREN_CLOSE); return rv; } case TOK_MACRO: //return NEWNODE( AST::ExprNode_Macro, tok.str(), Parse_TT(lex) ); diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 10eeacaf..66b1d0fb 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -42,8 +42,12 @@ AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode ::std::string component = tok.str(); tok = lex.getToken(); - if(generic_mode == PATH_GENERIC_TYPE && tok.type() == TOK_LT) + if( generic_mode == PATH_GENERIC_TYPE && (tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT) ) { + // HACK! Handle breaking << into < < + if( tok.type() == TOK_DOUBLE_LT ) + lex.putback( Token(TOK_LT) ); + // Type-mode generics "::path::to::Type" params = Parse_Path_GenericList(lex); tok = lex.getToken(); @@ -53,8 +57,12 @@ AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode break; } tok = lex.getToken(); - if( generic_mode == PATH_GENERIC_EXPR && tok.type() == TOK_LT ) + if( generic_mode == PATH_GENERIC_EXPR && (tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT) ) { + // HACK! Handle breaking << into < < + if( tok.type() == TOK_DOUBLE_LT ) + lex.putback( Token(TOK_LT) ); + // Expr-mode generics "::path::to::function::(arg1, arg2)" params = Parse_Path_GenericList(lex); tok = lex.getToken(); @@ -89,11 +97,13 @@ static const struct { {"i64", CORETYPE_I64}, {"i8", CORETYPE_I8}, {"int", CORETYPE_INT}, + {"isize", CORETYPE_INT}, {"u16", CORETYPE_U16}, {"u32", CORETYPE_U32}, {"u64", CORETYPE_U64}, {"u8", CORETYPE_U8}, {"uint", CORETYPE_UINT}, + {"usize", CORETYPE_UINT}, }; TypeRef Parse_Type(TokenStream& lex) @@ -103,6 +113,19 @@ TypeRef Parse_Type(TokenStream& lex) Token tok = lex.getToken(); switch(tok.type()) { + case TOK_LT: { + DEBUG("Associated type"); + // ::Inner + TypeRef base = Parse_Type(lex); + GET_CHECK_TOK(tok, lex, TOK_RWORD_AS); + TypeRef trait = Parse_Type(lex); + GET_CHECK_TOK(tok, lex, TOK_GT); + // TODO: Is just '' valid? + GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string inner_name = tok.str(); + return TypeRef(TypeRef::TagAssoc(), ::std::move(base), ::std::move(trait), ::std::move(inner_name)); + } case TOK_IDENT: // Either a path (with generics) if( tok.str() == "_" ) @@ -165,15 +188,17 @@ TypeRef Parse_Type(TokenStream& lex) throw ParseError::BugCheck("Reached end of Parse_Type:SQUARE"); } case TOK_PAREN_OPEN: { + DEBUG("Tuple"); ::std::vector types; - if( (tok = lex.getToken()).type() == TOK_PAREN_CLOSE) + if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) return TypeRef(TypeRef::TagTuple(), types); + lex.putback(tok); do { TypeRef type = Parse_Type(lex); types.push_back(type); - } while( (tok = lex.getToken()).type() == TOK_COMMA ); - GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); + } while( GET_TOK(tok, lex) == TOK_COMMA ); + CHECK_TOK(tok, TOK_PAREN_CLOSE); return TypeRef(TypeRef::TagTuple(), types); } case TOK_EXCLAM: throw ParseError::Todo("noreturn type"); @@ -237,7 +262,7 @@ void Parse_TypeConds(TokenStream& lex, AST::TypeParams& params) } /// Parse a function definition (after the 'fn') -AST::Function Parse_FunctionDef(TokenStream& lex) +AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false) { TRACE_FUNCTION; @@ -323,7 +348,19 @@ AST::Function Parse_FunctionDef(TokenStream& lex) lex.putback(tok); } - AST::Expr code = Parse_ExprBlock(lex); + AST::Expr code; + if( GET_TOK(tok, lex) == TOK_BRACE_OPEN ) + { + lex.putback(tok); + code = Parse_ExprBlock(lex); + } + else + { + if( !allow_no_code ) + { + throw ParseError::Generic("Expected code for function"); + } + } return AST::Function(params, fcn_class, ret_type, args, code); } @@ -420,6 +457,67 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons } } +AST::Trait Parse_TraitDef(TokenStream& lex, const ::std::vector meta_items) +{ + TRACE_FUNCTION; + + Token tok; + + AST::TypeParams params; + if( GET_TOK(tok, lex) == TOK_LT ) + { + params = Parse_TypeParams(lex); + GET_CHECK_TOK(tok, lex, TOK_GT); + tok = lex.getToken(); + } + // TODO: Support "for Sized?" + if(tok.type() == TOK_RWORD_WHERE) + { + if( params.size() == 0 ) + throw ParseError::Generic("Where clause with no generic params"); + Parse_TypeConds(lex, params); + tok = lex.getToken(); + } + + + AST::Trait trait(params); + + CHECK_TOK(tok, TOK_BRACE_OPEN); + while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) + { + switch(tok.type()) + { + case TOK_RWORD_STATIC: { + throw ParseError::Todo("Associated static"); + break; } + case TOK_RWORD_TYPE: { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + if( GET_TOK(tok, lex) == TOK_COLON ) { + throw ParseError::Todo("Type bounds on associated type"); + } + if( tok.type() == TOK_RWORD_WHERE ) { + throw ParseError::Todo("Where clause on associated type"); + } + TypeRef default_type; + if( tok.type() == TOK_EQUAL ) { + default_type = Parse_Type(lex); + } + trait.add_type( ::std::move(name), ::std::move(default_type) ); + break; } + case TOK_RWORD_FN: { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + trait.add_function( ::std::move(name), Parse_FunctionDef(lex, true) ); + break; } + default: + throw ParseError::Generic("Unexpected token, expected 'type' or 'fn'"); + } + } + + return trait; +} + AST::Enum Parse_EnumDef(TokenStream& lex, const ::std::vector meta_items) { TRACE_FUNCTION; @@ -765,8 +863,11 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st case TOK_RWORD_IMPL: mod.add_impl(Parse_Impl(lex)); break; - case TOK_RWORD_TRAIT: - throw ParseError::Todo("modroot trait"); + case TOK_RWORD_TRAIT: { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + mod.add_trait(is_public, name, Parse_TraitDef(lex, meta_items)); + break; } case TOK_RWORD_MOD: { GET_CHECK_TOK(tok, lex, TOK_IDENT); diff --git a/src/types.hpp b/src/types.hpp index 4ef24685..1dfeebac 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -26,6 +26,7 @@ class TypeRef: ARRAY, GENERIC, PATH, + ASSOCIATED, }; Class m_class; @@ -97,6 +98,16 @@ public: TypeRef(TagPath(), ::std::move(path)) {} + struct TagAssoc {}; + TypeRef(TagAssoc, TypeRef base, TypeRef trait, ::std::string assoc_name): + TypeRef(::std::move(base), ::std::move(trait), ::std::move(assoc_name)) + {} + TypeRef(TypeRef base, TypeRef trait, ::std::string assoc_name): + m_class(ASSOCIATED), + m_path( {AST::PathNode(assoc_name, {})} ), + m_inner_types( {::std::move(base), ::std::move(trait)} ) + {} + bool is_path() const { return m_class == PATH; } AST::Path& path() { assert(is_path()); return m_path; } ::std::vector& sub_types() { return m_inner_types; } -- cgit v1.2.3