diff options
| author | John Hodge <tpg@mutabah.net> | 2015-03-17 11:52:35 +0800 | 
|---|---|---|
| committer | John Hodge <tpg@mutabah.net> | 2015-03-17 11:52:35 +0800 | 
| commit | 6c571b2d3f99f5e209986dc00710d3fb86caafad (patch) | |
| tree | 6798d420f469432d0c722ca268592070252fa5c9 /src | |
| parent | 6b506092f331a26328a45c00565336ac810b7559 (diff) | |
| download | mrust-6c571b2d3f99f5e209986dc00710d3fb86caafad.tar.gz | |
Replace Enum variant inner type
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast/ast.cpp | 6 | ||||
| -rw-r--r-- | src/ast/ast.hpp | 41 | ||||
| -rw-r--r-- | src/ast/expr.cpp | 18 | ||||
| -rw-r--r-- | src/ast/expr.hpp | 14 | ||||
| -rw-r--r-- | src/ast/path.cpp | 2 | ||||
| -rw-r--r-- | src/ast/path.hpp | 5 | ||||
| -rw-r--r-- | src/convert/ast_iterate.cpp | 7 | ||||
| -rw-r--r-- | src/convert/ast_iterate.hpp | 3 | ||||
| -rw-r--r-- | src/convert/typecheck_expr.cpp | 43 | ||||
| -rw-r--r-- | src/dump_as_rust.cpp | 21 | ||||
| -rw-r--r-- | src/include/serialise.hpp | 2 | ||||
| -rw-r--r-- | src/include/serialiser_texttree.hpp | 2 | ||||
| -rw-r--r-- | src/parse/common.hpp | 2 | ||||
| -rw-r--r-- | src/parse/expr.cpp | 36 | ||||
| -rw-r--r-- | src/parse/root.cpp | 125 | ||||
| -rw-r--r-- | src/serialise.cpp | 13 | ||||
| -rw-r--r-- | src/types.hpp | 9 | 
17 files changed, 286 insertions, 63 deletions
| diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 870d4eff..3eb646e5 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -531,6 +531,12 @@ SERIALISE_TYPE(Trait::, "AST_Trait", {      s.item(m_functions);
  })
 +SERIALISE_TYPE_A(EnumVariant::, "AST_EnumVariant", {
 +    s.item(m_name);
 +    s.item(m_sub_types);
 +    s.item(m_value);
 +})
 +
  SERIALISE_TYPE(Enum::, "AST_Enum", {
      s << m_params;
      s << m_variants;
 diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 8928aa97..b38e9953 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -282,6 +282,7 @@ public:          CLASS_REFMETHOD,
          CLASS_MUTMETHOD,
          CLASS_VALMETHOD,
 +        CLASS_MUTVALMETHOD,
      };
      typedef ::std::vector< ::std::pair<AST::Pattern,TypeRef> >   Arglist;
 @@ -296,15 +297,15 @@ public:      Function():
          m_fcn_class(CLASS_UNBOUND)
      {}
 -    Function(TypeParams params, Class fcn_class, TypeRef ret_type, Arglist args, Expr code):
 +    Function(TypeParams params, Class fcn_class, TypeRef ret_type, Arglist args):
          m_fcn_class(fcn_class),
          m_params(params),
 -        m_code( ::std::move(code) ),
          m_rettype( move(ret_type) ),
          m_args( move(args) )
      {
      }
 +    void set_code(Expr code) { m_code = ::std::move(code); }
      void set_self_lifetime(::std::string s) { m_lifetime = s; }
      const Class fcn_class() const { return m_fcn_class; }
 @@ -353,23 +354,51 @@ public:      SERIALISABLE_PROTOTYPES();
  };
 +struct EnumVariant:
 +    public Serialisable
 +{
 +    ::std::string   m_name;
 +    ::std::vector<TypeRef>  m_sub_types;
 +    int64_t m_value;
 +    
 +    EnumVariant():
 +        m_value(0)
 +    {
 +    }
 +    
 +    EnumVariant(::std::string name, int64_t value):
 +        m_name( ::std::move(name) ),
 +        m_value( value )
 +    {
 +    }
 +    
 +    EnumVariant(::std::string name, ::std::vector<TypeRef> sub_types):
 +        m_name( ::std::move(name) ),
 +        m_sub_types( ::std::move(sub_types) ),
 +        m_value(0)
 +    {
 +    }
 +    
 +    SERIALISABLE_PROTOTYPES();
 +};
 +
  class Enum:
      public Serialisable
  {
      TypeParams    m_params;
 -    ::std::vector<StructItem>   m_variants;
 +    ::std::vector<EnumVariant>   m_variants;
  public:
      Enum() {}
 -    Enum( TypeParams params, ::std::vector<StructItem> variants ):
 +    Enum( TypeParams params, ::std::vector<EnumVariant> variants ):
          m_params( move(params) ),
          m_variants( move(variants) )
      {}
      const TypeParams& params() const { return m_params; }
 -    const ::std::vector<StructItem>& variants() const { return m_variants; }
 +    const ::std::vector<EnumVariant>& variants() const { return m_variants; }
      TypeParams& params() { return m_params; }
 -    ::std::vector<StructItem>& variants() { return m_variants; }
 +    ::std::vector<EnumVariant>& variants() { return m_variants; }
      SERIALISABLE_PROTOTYPES();
  };
 diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 1f5eb377..59fe2162 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -1,6 +1,7 @@  /*   */  #include "expr.hpp" +#include "ast.hpp"  namespace AST { @@ -55,6 +56,7 @@ SERIALISE_TYPE(Expr::, "Expr", {      else _(ExprNode_Flow)      else _(ExprNode_Const)      else _(ExprNode_Import) +    else _(ExprNode_Extern)      else _(ExprNode_LetBinding)      else _(ExprNode_Assign)      else _(ExprNode_CallPath) @@ -154,12 +156,25 @@ NODE(ExprNode_Const, {      os << "const " << m_name << ": " << m_type << " = " << *m_value;  }) + +ExprNode_Extern::ExprNode_Extern() +{} +ExprNode_Extern::ExprNode_Extern(ExprNode_Extern::imports_t imports): +    m_imports( ::std::move(imports) ) +{} +  NODE(ExprNode_Import, {      s.item(m_imports);  },{      os << "/* todo: use /*";  }) +NODE(ExprNode_Extern, { +    s.item(m_imports); +},{ +    os << "/* todo: export /*"; +}) +  NODE(ExprNode_LetBinding, {      s.item(m_pat);      s.item(m_type); @@ -442,6 +457,7 @@ NODE(ExprNode_BinOp, {  	case MODULO:   os << "%"; break;  	case ADD:   os << "+"; break;  	case SUB:   os << "-"; break; +	case RANGE:   os << ".."; break;      }      os << " " << *m_right << ")";  }) @@ -482,6 +498,7 @@ NODE(ExprNode_UniOp, {      case INVERT: os << "(!"; break;      case BOX: os << "(box "; break;      case REF: os << "(&"; break; +    case REFMUT: os << "(&mut "; break;      }      os << *m_value << ")";  }) @@ -510,6 +527,7 @@ NV(ExprNode_Const,      visit(node.m_value);  })  NV(ExprNode_Import, {}) +NV(ExprNode_Extern, {})  NV(ExprNode_LetBinding,  {      // TODO: Handle recurse into Let pattern diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 21f67c2f..e84e3df6 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -128,6 +128,18 @@ struct ExprNode_Import:      NODE_METHODS();  }; +struct ExprNode_Extern: +    public ExprNode +{ +    typedef ::std::vector< ::std::pair< ::std::string, AST::Function> > imports_t; +    imports_t   m_imports; +     +    ExprNode_Extern(); +    ExprNode_Extern(imports_t imports); +    // - Non-local because AST::Function +     +    NODE_METHODS(); +};  struct ExprNode_LetBinding:      public ExprNode  { @@ -583,6 +595,7 @@ public:      NT(ExprNode_Flow);      NT(ExprNode_Const);      NT(ExprNode_Import); +    NT(ExprNode_Extern);      NT(ExprNode_LetBinding);      NT(ExprNode_Assign);      NT(ExprNode_CallPath); @@ -626,6 +639,7 @@ public:      NT(ExprNode_Flow);      NT(ExprNode_Const);      NT(ExprNode_Import); +    NT(ExprNode_Extern);      NT(ExprNode_LetBinding);      NT(ExprNode_Assign);      NT(ExprNode_CallPath); diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 103ca1b2..4f83ae34 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -267,7 +267,7 @@ void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std      unsigned int idx = 0;      for( idx = 0; idx < ent.variants().size(); idx ++ )      { -        if( ent.variants()[idx].name == name ) { +        if( ent.variants()[idx].m_name == name ) {              break;          }      } diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 4ff128c6..51dd70f5 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -105,6 +105,11 @@ public:          m_class(LOCAL),          m_nodes({PathNode(name, {})})      {} +    struct TagSuper {}; +    Path(TagSuper): +        m_class(RELATIVE), +        m_nodes({PathNode("super", {})}) +    {}      Path(::std::initializer_list<PathNode> l):          m_class(ABSOLUTE), diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index 68c84a31..e53e1ba8 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -156,7 +156,7 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)  }  void CASTIterator::handle_pattern_enum(          ::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args, -        const AST::TypeParams& enum_params, const AST::StructItem& var, +        const AST::TypeParams& enum_params, const AST::EnumVariant& var,          ::std::vector<AST::Pattern>& sub_patterns          )  { @@ -278,7 +278,10 @@ void CASTIterator::handle_enum(AST::Path path, AST::Enum& enm)      start_scope();      handle_params( enm.params() );      for( auto& f : enm.variants() ) -        handle_type( f.data ); +    { +        for( auto& t : f.m_sub_types ) +            handle_type(t); +    }      end_scope();  }  void CASTIterator::handle_trait(AST::Path path, AST::Trait& trait) diff --git a/src/convert/ast_iterate.hpp b/src/convert/ast_iterate.hpp index 979831a5..78f6b271 100644 --- a/src/convert/ast_iterate.hpp +++ b/src/convert/ast_iterate.hpp @@ -11,6 +11,7 @@ class ExprNode;  class Pattern;  class TypeParams;  class Impl; +class EnumVariant;  template<typename T> struct Item;  }; @@ -39,7 +40,7 @@ public:      virtual void handle_pattern(AST::Pattern& pat, const TypeRef& type_hint);      virtual void handle_pattern_enum(              ::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args, -            const AST::TypeParams& enum_params, const AST::Item<TypeRef>& var, +            const AST::TypeParams& enum_params, const AST::EnumVariant& var,              ::std::vector<AST::Pattern>& sub_patterns              ); diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index 6d88b1dd..a6a69186 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -40,7 +40,7 @@ public:      virtual void handle_pattern_enum(              ::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args, -            const AST::TypeParams& enum_params, const AST::StructItem& var, +            const AST::TypeParams& enum_params, const AST::EnumVariant& var,              ::std::vector<AST::Pattern>& sub_patterns              ) override; @@ -57,7 +57,7 @@ private:      void check_enum_variant(          ::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes, -        const AST::TypeParams& params, const AST::StructItem& var +        const AST::TypeParams& params, const AST::EnumVariant& var          );      void iterate_traits(::std::function<bool(const TypeRef& trait)> fcn);  }; @@ -128,15 +128,14 @@ void CTypeChecker::handle_params(AST::TypeParams& params)  }  void CTypeChecker::handle_pattern_enum(          ::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args, -        const AST::TypeParams& enum_params, const AST::StructItem& var, +        const AST::TypeParams& enum_params, const AST::EnumVariant& var,          ::std::vector<AST::Pattern>& sub_patterns          )  {      check_enum_variant(pat_args, hint_args, enum_params, var);      // Ensure that sub_patterns is the same length as the variant -    assert(var.data.is_tuple()); -    const auto& var_types = var.data.sub_types(); +    const auto& var_types = var.m_sub_types;      if( sub_patterns.size() != var_types.size() )          throw ::std::runtime_error(FMT("Enum pattern size mismatch"));      for( unsigned int i = 0; i < sub_patterns.size(); i ++ ) @@ -217,6 +216,9 @@ void CTypeChecker::handle_function(AST::Path path, AST::Function& fcn)          local_variable(false, "self", TypeRef(TypeRef::TagReference(), true, get_local_type("Self")));          break;      case AST::Function::CLASS_VALMETHOD: +        local_variable(false, "self", TypeRef(get_local_type("Self"))); +        break; +    case AST::Function::CLASS_MUTVALMETHOD:          local_variable(true, "self", TypeRef(get_local_type("Self")));          break;      } @@ -251,7 +253,7 @@ void CTypeChecker::iterate_traits(::std::function<bool(const TypeRef& trait)> fc      }  } -void CTypeChecker::check_enum_variant(::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes, const AST::TypeParams& params, const AST::StructItem& var) +void CTypeChecker::check_enum_variant(::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes, const AST::TypeParams& params, const AST::EnumVariant& var)  {      // We know the enum, but it might have type params, need to handle that case      if( params.n_params() > 0 ) @@ -263,18 +265,21 @@ void CTypeChecker::check_enum_variant(::std::vector<TypeRef>& path_args, const :          // 2. Create a pattern from the argument types and the format of the variant          DEBUG("argtypes = [" << argtypes << "]");          ::std::vector<TypeRef>  item_args(params.n_params()); -        DEBUG("variant type = " << var.data << ""); -        var.data.match_args( -            TypeRef(TypeRef::TagTuple(), argtypes), -            [&](const char *name, const TypeRef& t) { -                    DEBUG("Binding " << name << " to type " << t); -                    int idx = params.find_name(name); -                    if( idx == -1 ) { -                        throw ::std::runtime_error(FMT("Can't find generic " << name)); +        DEBUG("variant type = " << var.m_sub_types << ""); +        for( unsigned int i = 0; i < var.m_sub_types.size(); i ++ ) +        { +            var.m_sub_types[i].match_args( +                TypeRef(TypeRef::TagTuple(), argtypes), +                [&](const char *name, const TypeRef& t) { +                        DEBUG("Binding " << name << " to type " << t); +                        int idx = params.find_name(name); +                        if( idx == -1 ) { +                            throw ::std::runtime_error(FMT("Can't find generic " << name)); +                        } +                        item_args.at(idx).merge_with( t );                      } -                    item_args.at(idx).merge_with( t ); -                } -            ); +                ); +        }          DEBUG("item_args = [" << item_args << "]");          // 3. Merge the two sets of arguments          for( unsigned int i = 0; i < path_args.size(); i ++ ) @@ -303,8 +308,8 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node)              auto idx = p.bound_idx();              // Enum variant:              // - Check that this variant takes no arguments -            if( !enm.variants()[idx].data.is_unit() ) -                throw ::std::runtime_error( FMT("Used a non-unit variant as a raw value - " << enm.variants()[idx].data)); +            if( enm.variants()[idx].m_sub_types.size() > 0 ) +                throw ::std::runtime_error( FMT("Used a non-unit variant as a raw value - " << enm.variants()[idx].m_sub_types));              // - Set output type to the enum (wildcard params, not default)              AST::Path tp = p;              tp.nodes().pop_back(); diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index d8d5ad13..f76f5942 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -80,6 +80,11 @@ public:          for( const auto& item : n.m_imports )              m_os << "use " << item.second << " as " << item.first << ";\n" << indent();      } +    virtual void visit(AST::ExprNode_Extern& n) override { +        m_expr_root = false; +        for( const auto& item : n.m_imports ) +            m_os << "extern \"\" fn " << item.first /*<< item.second*/ << ";\n" << indent(); +    }      virtual void visit(AST::ExprNode_LetBinding& n) override {          m_expr_root = false;          m_os << "let "; @@ -423,6 +428,7 @@ public:          case AST::ExprNode_BinOp::MODULO:   m_os << "%"; break;          case AST::ExprNode_BinOp::ADD:   m_os << "+"; break;          case AST::ExprNode_BinOp::SUB:   m_os << "-"; break; +        case AST::ExprNode_BinOp::RANGE: m_os << ".."; break;          }          m_os << " ";          if( IS(*n.m_right, AST::ExprNode_BinOp) ) @@ -438,7 +444,7 @@ public:          case AST::ExprNode_UniOp::INVERT:   m_os << "!";    break;          case AST::ExprNode_UniOp::BOX:      m_os << "box ";    break;          case AST::ExprNode_UniOp::REF:    m_os << "&";    break; -        //case AST::ExprNode_UniOp::REFMUT: m_os << "&mut ";    break; +        case AST::ExprNode_UniOp::REFMUT: m_os << "&mut ";    break;          }          if( IS(*n.m_value, AST::ExprNode_BinOp) ) @@ -718,9 +724,16 @@ void RustPrinter::handle_enum(const AST::Enum& s)      inc_indent();      for( const auto& i : s.variants() )      { -        m_os << indent() << i.name; -        if( i.data.sub_types().size() ) -            m_os << i.data.print_pretty(); +        m_os << indent() << i.m_name; +        if( i.m_sub_types.size() ) +        { +            for( const auto& t : i.m_sub_types ) +                m_os << t.print_pretty() << ", "; +        } +        else +        { +            m_os << " = " << i.m_value; +        }          m_os << ",\n";      }      dec_indent(); diff --git a/src/include/serialise.hpp b/src/include/serialise.hpp index e70ec113..07812899 100644 --- a/src/include/serialise.hpp +++ b/src/include/serialise.hpp @@ -44,6 +44,7 @@ public:      virtual Serialiser& operator<<(bool val) = 0;      virtual Serialiser& operator<<(uint64_t val) = 0; +    virtual Serialiser& operator<<(int64_t val) = 0;      virtual Serialiser& operator<<(double val) = 0;      virtual Serialiser& operator<<(const char* s) = 0;      Serialiser& operator<<(const ::std::string& s) { @@ -106,6 +107,7 @@ protected:  public:      virtual void item(bool& b) = 0;      virtual void item(uint64_t& v) = 0; +    virtual void item(int64_t& val) = 0;      virtual void item(double& v) = 0;      virtual void item(::std::string& s) = 0; diff --git a/src/include/serialiser_texttree.hpp b/src/include/serialiser_texttree.hpp index 890be31a..bdad7d7a 100644 --- a/src/include/serialiser_texttree.hpp +++ b/src/include/serialiser_texttree.hpp @@ -19,6 +19,7 @@ public:      virtual Serialiser& operator<<(bool val) override;      virtual Serialiser& operator<<(uint64_t val) override; +    virtual Serialiser& operator<<(int64_t val) override;      virtual Serialiser& operator<<(double val) override;      virtual Serialiser& operator<<(const char* s) override; @@ -54,6 +55,7 @@ protected:  public:      virtual void item(bool& b) override;      virtual void item(uint64_t& v) override; +    virtual void item(int64_t& v) override;      virtual void item(double& v) override;      virtual void item(::std::string& s) override; diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 4af48174..da7d767d 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -1,6 +1,7 @@  #ifndef PARSE_COMMON_HPP_INCLUDED
  #define PARSE_COMMON_HPP_INCLUDED
  #include <iostream>
 +#include "../ast/ast.hpp"
  #define GET_TOK(tok, lex) ((tok = lex.getToken()).type())
  #define LOOK_AHEAD(lex) (lex.lookahead(0))
 @@ -28,6 +29,7 @@ extern AST::Path   Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMo  extern ::std::vector<TypeRef>   Parse_Path_GenericList(TokenStream& lex);
  extern TypeRef     Parse_Type(TokenStream& lex);
  extern void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> fcn);
 +extern AST::Function    Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self, bool can_be_prototype);
  extern AST::Expr   Parse_Expr(TokenStream& lex, bool const_only);
  extern AST::Expr   Parse_ExprBlock(TokenStream& lex);
 diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index a8a16c7d..eadd8e56 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -255,6 +255,42 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon)              });
          return NEWNODE( AST::ExprNode_Import, ::std::move(imports) );
          }
 +    // 'extern' blocks
 +    case TOK_RWORD_EXTERN: {
 +        opt_semicolon = true;
 +        // - default ABI is "C"
 +        ::std::string    abi = "C";
 +        if( GET_TOK(tok, lex) == TOK_STRING ) {
 +            abi = tok.str();
 +        }
 +        else
 +            lex.putback(tok);
 +        
 +        ::std::vector< ::std::pair< ::std::string, AST::Function> >  imports;
 +        bool is_block = false;
 +        if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
 +            is_block = true;
 +        else
 +            lex.putback(tok);
 +        
 +        do {
 +            ::std::string   name;
 +            switch( GET_TOK(tok, lex) )
 +            {
 +            case TOK_RWORD_FN:
 +                GET_CHECK_TOK(tok, lex, TOK_IDENT);
 +                name = tok.str();
 +                imports.push_back( ::std::make_pair( ::std::move(name), Parse_FunctionDef(lex, abi, AST::MetaItems(), false, true) ) );
 +                GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
 +                break;
 +            default:
 +                throw ParseError::Unexpected(lex, tok);
 +            }
 +        } while( is_block && LOOK_AHEAD(lex) != TOK_BRACE_CLOSE );
 +        if( is_block )
 +            GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
 +        return NEWNODE( AST::ExprNode_Extern, ::std::move(imports) );
 +        }
      case TOK_RWORD_CONST: {
          opt_semicolon = false;
          GET_CHECK_TOK(tok, lex, TOK_IDENT);
 diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 0e22b117..f84b11f6 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -167,7 +167,7 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi);  TypeRef Parse_Type(TokenStream& lex)
  {
 -    TRACE_FUNCTION;
 +    //TRACE_FUNCTION;
      Token tok;
 @@ -417,7 +417,7 @@ void Parse_WhereClause(TokenStream& lex, AST::TypeParams& params)      return ::std::make_pair( ::std::move(pat), ::std::move(type) );
  }
 -/// Parse a function definition (after the 'fn')
 +/// Parse a function definition (after the 'fn <name>')
  AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self, bool can_be_prototype)
  {
      TRACE_FUNCTION;
 @@ -483,6 +483,17 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt              lex.putback(tok);   // un-eat the '&'
          }
      }
 +    else if( tok.type() == TOK_RWORD_MUT )
 +    {
 +        if( LOOK_AHEAD(lex) == TOK_RWORD_SELF )
 +        {
 +            GET_TOK(tok, lex);
 +            if( allow_self == false )
 +                throw ParseError::Generic(lex, "Self binding not expected");
 +            fcn_class = AST::Function::CLASS_MUTVALMETHOD;
 +            GET_TOK(tok, lex);
 +        }
 +    }
      else if( tok.type() == TOK_RWORD_SELF )
      {
          // By-value method
 @@ -541,23 +552,19 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt      else {
          lex.putback(tok);
      }
 -    
 -    AST::Expr   code;
 -    if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
 -    {
 -        lex.putback(tok);
 -        code = Parse_ExprBlock(lex);
 -    }
 -    else
 -    {
 -        CHECK_TOK(tok, TOK_SEMICOLON);
 -        if( !can_be_prototype )
 -        {
 -            throw ParseError::Generic("Expected code for function");
 -        }
 -    }
 -    return AST::Function(params, fcn_class, ret_type, args, code);
 +    return AST::Function(params, fcn_class, ret_type, args);
 +}
 +
 +AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self)
 +{
 +    TRACE_FUNCTION;
 +    Token   tok;
 +    auto ret = Parse_FunctionDef(lex, abi, ::std::move(attrs), allow_self, false);
 +    GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
 +    lex.putback(tok);
 +    ret.set_code( Parse_ExprBlock(lex) );
 +    return ret;
  }
  AST::TypeAlias Parse_TypeAlias(TokenStream& lex, const AST::MetaItems meta_items)
 @@ -709,7 +716,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)              GET_TOK(tok, lex);
          }
 -        
 +        ::std::string   abi = "rust";
          switch(tok.type())
          {
          case TOK_RWORD_STATIC: {
 @@ -739,15 +746,41 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)              CHECK_TOK(tok, TOK_SEMICOLON);
              trait.add_type( ::std::move(name), ::std::move(default_type) );
              break; }
 +
          // Functions (possibly unsafe)
          case TOK_RWORD_UNSAFE:
              item_attrs.push_back( AST::MetaItem("#UNSAFE") );
 -            GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
 +            if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN )
 +        case TOK_RWORD_EXTERN:
 +            {
 +                abi = "C";
 +                if( GET_TOK(tok, lex) == TOK_STRING )
 +                    abi = tok.str();
 +                else
 +                    lex.putback(tok);
 +                
 +                GET_TOK(tok, lex);
 +            }
 +            CHECK_TOK(tok, TOK_RWORD_FN);
          case TOK_RWORD_FN: {
              GET_CHECK_TOK(tok, lex, TOK_IDENT);
              ::std::string name = tok.str();
              // Self allowed, prototype-form allowed (optional names and no code)
 -            trait.add_function( ::std::move(name), Parse_FunctionDef(lex, "rust", item_attrs, true, true) );
 +            auto fcn = Parse_FunctionDef(lex, abi, item_attrs, true, true);
 +            if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
 +            {
 +                lex.putback(tok);
 +                fcn.set_code( Parse_ExprBlock(lex) );
 +            }
 +            else if( tok.type() == TOK_SEMICOLON )
 +            {
 +                // Accept it
 +            }
 +            else
 +            {
 +                throw ParseError::Unexpected(lex, tok);
 +            }
 +            trait.add_function( ::std::move(name), ::std::move(fcn) );
              break; }
          default:
              throw ParseError::Unexpected(lex, tok);
 @@ -780,27 +813,46 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items)      // Body
      CHECK_TOK(tok, TOK_BRACE_OPEN);
 -    ::std::vector<AST::StructItem>   variants;
 +    ::std::vector<AST::EnumVariant>   variants;
      while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
      {
 +        AST::MetaItems  item_attrs;
 +        while( tok.type() == TOK_ATTR_OPEN )
 +        {
 +            item_attrs.push_back( Parse_MetaItem(lex) );
 +            GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
 +            GET_TOK(tok, lex);
 +        }
 +        
          CHECK_TOK(tok, TOK_IDENT);
          ::std::string   name = tok.str();
          if( GET_TOK(tok, lex) == TOK_PAREN_OPEN )
          {
              ::std::vector<TypeRef>  types;
              // Get type list
 -            // TODO: Handle 'Variant()'?
              do
              {
                  types.push_back( Parse_Type(lex) );
              } while( GET_TOK(tok, lex) == TOK_COMMA );
              CHECK_TOK(tok, TOK_PAREN_CLOSE);
              GET_TOK(tok, lex);
 -            variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagTuple(), ::std::move(types)), true) );
 +            variants.push_back( AST::EnumVariant(::std::move(name), ::std::move(types)) );
 +        }
 +        else if( tok.type() == TOK_EQUAL )
 +        {
 +            bool is_neg = false;
 +            if( GET_TOK(tok, lex) == TOK_DASH )
 +                is_neg = true;
 +            else
 +                lex.putback(tok);
 +            GET_CHECK_TOK(tok, lex, TOK_INTEGER);
 +            int64_t val = (is_neg ? -tok.intval() : tok.intval());
 +            variants.push_back( AST::EnumVariant(::std::move(name), val) );
 +            GET_TOK(tok, lex);
          }
          else
          {
 -            variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagUnit()), true) );
 +            variants.push_back( AST::EnumVariant(::std::move(name), ::std::vector<TypeRef>()) );
          }
          if( tok.type() != TOK_COMMA )
 @@ -928,6 +980,7 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe=false)              GET_TOK(tok, lex);
          }
 +        ::std::string   abi = "rust";
          switch(tok.type())
          {
          case TOK_RWORD_TYPE: {
 @@ -937,11 +990,22 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe=false)              impl.add_type(is_public, name, Parse_Type(lex));
              GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
              break; }
 +        case TOK_RWORD_EXTERN:
 +            {
 +                abi = "C";
 +                if( GET_TOK(tok, lex) == TOK_STRING )
 +                    abi = tok.str();
 +                else
 +                    lex.putback(tok);
 +                
 +                GET_TOK(tok, lex);
 +            }
 +            CHECK_TOK(tok, TOK_RWORD_FN);
          case TOK_RWORD_FN: {
              GET_CHECK_TOK(tok, lex, TOK_IDENT);
              ::std::string name = tok.str();
              // - Self allowed, can't be prototype-form
 -            impl.add_function(is_public, name, Parse_FunctionDef(lex, "rust", item_attrs, true, false));
 +            impl.add_function(is_public, ::std::move(name), Parse_FunctionDefWithCode(lex, abi, ::std::move(item_attrs), true));
              break; }
          default:
 @@ -979,6 +1043,7 @@ void Parse_ExternBlock(TokenStream& lex, AST::Module& mod, ::std::string abi)              // parse function as prototype
              // - no self
              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;
          default:
              throw ParseError::Unexpected(lex, tok);
 @@ -1004,7 +1069,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)>          path = AST::Path( );    // relative path
          break;
      case TOK_RWORD_SUPER:
 -        throw ParseError::Todo(lex, "Parse_Use - super");
 +        path = AST::Path( AST::Path::TagSuper() );
          break;
      case TOK_IDENT:
          path.append( AST::PathNode(tok.str(), {}) );
 @@ -1302,7 +1367,7 @@ void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems& meta_i  void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*>& modstack, const ::std::string& path)
  {
 -    TRACE_FUNCTION;
 +    //TRACE_FUNCTION;
      const bool nested_module = (path == "-");  // 'mod name { code }', as opposed to 'mod name;'
      Token   tok;
 @@ -1473,7 +1538,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod,              case TOK_RWORD_FN:
                  GET_CHECK_TOK(tok, lex, TOK_IDENT);
                  // - self not allowed, not prototype
 -                mod.add_function(is_public, tok.str(), Parse_FunctionDef(lex, "rust", ::std::move(meta_items), false, false));
 +                mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false));
                  break;
              case TOK_RWORD_TRAIT: {
                  GET_CHECK_TOK(tok, lex, TOK_IDENT);
 @@ -1492,7 +1557,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod,              GET_CHECK_TOK(tok, lex, TOK_IDENT);
              ::std::string name = tok.str();
              // - self not allowed, not prototype
 -            mod.add_function(is_public, name, Parse_FunctionDef(lex, "rust", ::std::move(meta_items), false, false));
 +            mod.add_function(is_public, name, Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false));
              break; }
          case TOK_RWORD_TYPE: {
              GET_CHECK_TOK(tok, lex, TOK_IDENT);
 diff --git a/src/serialise.cpp b/src/serialise.cpp index 55555c7c..72a6dc50 100644 --- a/src/serialise.cpp +++ b/src/serialise.cpp @@ -80,6 +80,12 @@ Serialiser& Serialiser_TextTree::operator<<(uint64_t val)      m_os << val << "\n";      return *this;  } +Serialiser& Serialiser_TextTree::operator<<(int64_t val) +{ +    print_indent(); +    m_os << val << "\n"; +    return *this; +}  Serialiser& Serialiser_TextTree::operator<<(double val)  {      print_indent(); @@ -195,6 +201,13 @@ void Deserialiser_TextTree::item(uint64_t& v)      if( !m_is.good() )          throw ::std::runtime_error("TODO: Less shit exception, item(uint64_t)");  } +void Deserialiser_TextTree::item(int64_t& v) +{ +    eat_ws(); +    m_is >> v; +    if( !m_is.good() ) +        throw ::std::runtime_error("TODO: Less shit exception, item(int64_t)"); +}  void Deserialiser_TextTree::item(double& v)  {      eat_ws(); diff --git a/src/types.hpp b/src/types.hpp index adc28f6f..9505f2cd 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -201,4 +201,13 @@ public:      SERIALISABLE_PROTOTYPES(); 
  };
 +class Type_Function:
 +    public Serialisable
 +{
 +    bool    is_unsafe;
 +    ::std::string   m_abi;
 +    TypeRef m_rettype;
 +    ::std::vector<TypeRef>  m_arg_types;
 +};
 +
  #endif // TYPES_HPP_INCLUDED
 | 
