diff options
| author | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-16 09:14:38 +0800 | 
|---|---|---|
| committer | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-16 09:14:38 +0800 | 
| commit | 80e4060188913eb12ad8a774b07d3b938485a49a (patch) | |
| tree | f8e978f4c1c93920aa16119199cf728b36915121 /src | |
| parent | 7d04ce9d4c945cedf08ff2a7fa0af49ea4e6e1b0 (diff) | |
| download | mrust-80e4060188913eb12ad8a774b07d3b938485a49a.tar.gz | |
Added associated type reference parse, and tuple value parse
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast/ast.cpp | 6 | ||||
| -rw-r--r-- | src/ast/ast.hpp | 73 | ||||
| -rw-r--r-- | src/ast/expr.cpp | 4 | ||||
| -rw-r--r-- | src/ast/expr.hpp | 22 | ||||
| -rw-r--r-- | src/parse/expr.cpp | 13 | ||||
| -rw-r--r-- | src/parse/root.cpp | 119 | ||||
| -rw-r--r-- | src/types.hpp | 11 | 
7 files changed, 215 insertions, 33 deletions
| 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 <typename T>
 +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 <typename T>
 +using ItemList = ::std::vector<Item<T> >;
 +
  typedef ::std::vector<TypeParam>    TypeParams;
  typedef ::std::pair< ::std::string, TypeRef>    StructItem;
 @@ -161,6 +185,28 @@ public:      SERIALISABLE_PROTOTYPES();
  };
 +class Trait:
 +    public Serialisable
 +{
 +    ::std::vector<TypeParam>    m_params;
 +    ItemList<TypeRef>   m_types;
 +    ItemList<Function>  m_functions;
 +public:
 +    Trait(TypeParams params):
 +        m_params(params)
 +    {
 +    }
 +    
 +    void add_type(::std::string name, TypeRef type) {
 +        m_types.push_back( Item<TypeRef>(move(name), move(type), true) );
 +    }
 +    void add_function(::std::string name, Function fcn) {
 +        m_functions.push_back( Item<Function>(move(name), move(fcn), true) );
 +    }
 +    
 +    SERIALISABLE_PROTOTYPES();
 +};
 +
  class Enum:
      public Serialisable
  {
 @@ -195,28 +241,6 @@ public:      SERIALISABLE_PROTOTYPES();
  };
 -template <typename T>
 -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<Trait> m_traits;
      itemlist_enum_t m_enums;
      itemlist_struct_t m_structs;
      ::std::vector<Impl> 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<Static>( 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<Trait>( move(name), move(trait), is_public) );
 +    }
      void add_struct(bool is_public, ::std::string name, TypeParams params, ::std::vector<StructItem> items) {
          m_structs.push_back( Item<Struct>( move(name), Struct(move(params), move(items)), is_public) );
      }
 @@ -337,6 +365,7 @@ public:      const ::std::vector<Item<TypeAlias> >& 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<Trait>& 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<ExprNode> >   m_values; +     +    ExprNode_Tuple(::std::vector< unique_ptr<ExprNode> > 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<ExprNode> take_node() { return ::std::move(m_node); } +    ::std::shared_ptr<ExprNode> 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<ExprNodeP> 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<A,B>"
              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::<Type1,Type2>(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");
 +        // <Type as Trait>::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 '<Type as Trait>' 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<TypeRef>  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<AST::MetaItem> 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<AST::MetaItem> 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<TypeRef>& sub_types() { return m_inner_types; }
 | 
