From 6c571b2d3f99f5e209986dc00710d3fb86caafad Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 17 Mar 2015 11:52:35 +0800 Subject: Replace Enum variant inner type --- src/ast/ast.cpp | 6 ++ src/ast/ast.hpp | 41 ++++++++++-- src/ast/expr.cpp | 18 ++++++ src/ast/expr.hpp | 14 ++++ src/ast/path.cpp | 2 +- src/ast/path.hpp | 5 ++ src/convert/ast_iterate.cpp | 7 +- src/convert/ast_iterate.hpp | 3 +- src/convert/typecheck_expr.cpp | 43 +++++++------ src/dump_as_rust.cpp | 21 ++++-- src/include/serialise.hpp | 2 + src/include/serialiser_texttree.hpp | 2 + src/parse/common.hpp | 2 + src/parse/expr.cpp | 36 +++++++++++ src/parse/root.cpp | 125 +++++++++++++++++++++++++++--------- src/serialise.cpp | 13 ++++ src/types.hpp | 9 +++ 17 files changed, 286 insertions(+), 63 deletions(-) (limited to 'src') 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 > 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 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 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 m_variants; + ::std::vector m_variants; public: Enum() {} - Enum( TypeParams params, ::std::vector variants ): + Enum( TypeParams params, ::std::vector variants ): m_params( move(params) ), m_variants( move(variants) ) {} const TypeParams& params() const { return m_params; } - const ::std::vector& variants() const { return m_variants; } + const ::std::vector& variants() const { return m_variants; } TypeParams& params() { return m_params; } - ::std::vector& variants() { return m_variants; } + ::std::vector& 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 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& pat_args, const ::std::vector& hint_args, - const AST::TypeParams& enum_params, const AST::StructItem& var, + const AST::TypeParams& enum_params, const AST::EnumVariant& var, ::std::vector& 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 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& pat_args, const ::std::vector& hint_args, - const AST::TypeParams& enum_params, const AST::Item& var, + const AST::TypeParams& enum_params, const AST::EnumVariant& var, ::std::vector& 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& pat_args, const ::std::vector& hint_args, - const AST::TypeParams& enum_params, const AST::StructItem& var, + const AST::TypeParams& enum_params, const AST::EnumVariant& var, ::std::vector& sub_patterns ) override; @@ -57,7 +57,7 @@ private: void check_enum_variant( ::std::vector& path_args, const ::std::vector& argtypes, - const AST::TypeParams& params, const AST::StructItem& var + const AST::TypeParams& params, const AST::EnumVariant& var ); void iterate_traits(::std::function fcn); }; @@ -128,15 +128,14 @@ void CTypeChecker::handle_params(AST::TypeParams& params) } void CTypeChecker::handle_pattern_enum( ::std::vector& pat_args, const ::std::vector& hint_args, - const AST::TypeParams& enum_params, const AST::StructItem& var, + const AST::TypeParams& enum_params, const AST::EnumVariant& var, ::std::vector& 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 fc } } -void CTypeChecker::check_enum_variant(::std::vector& path_args, const ::std::vector& argtypes, const AST::TypeParams& params, const AST::StructItem& var) +void CTypeChecker::check_enum_variant(::std::vector& path_args, const ::std::vector& 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& path_args, const : // 2. Create a pattern from the argument types and the format of the variant DEBUG("argtypes = [" << argtypes << "]"); ::std::vector 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 +#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 Parse_Path_GenericList(TokenStream& lex); extern TypeRef Parse_Type(TokenStream& lex); extern void Parse_Use(TokenStream& lex, ::std::function 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 ') 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 variants; + ::std::vector 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 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()) ); } 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 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& 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 m_arg_types; +}; + #endif // TYPES_HPP_INCLUDED -- cgit v1.2.3