From e7282f3b1595936af4553a72beee6a296780a33e Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 29 Sep 2016 13:24:21 +0800 Subject: AST - Store `const`/`unsafe`/variadic on functions --- src/ast/ast.cpp | 10 +++-- src/ast/ast.hpp | 13 +++++- src/expand/derive.cpp | 4 ++ src/parse/root.cpp | 110 ++++++++++++++++++++++++-------------------------- 4 files changed, 75 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 0ec36f82..157461c1 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -84,11 +84,15 @@ Static Static::clone() const return Static( m_class, m_type, m_value.is_valid() ? AST::Expr( m_value.node().clone() ) : AST::Expr() ); } -Function::Function(Span sp, GenericParams params, TypeRef ret_type, Arglist args): +Function::Function(Span sp, GenericParams params, ::std::string abi, bool is_unsafe, bool is_const, bool is_variadic, TypeRef ret_type, Arglist args): m_span(sp), m_params( move(params) ), m_rettype( move(ret_type) ), - m_args( move(args) ) + m_args( move(args) ), + m_abi( mv$(abi) ), + m_is_const(is_const), + m_is_unsafe(is_unsafe), + m_is_variadic(is_variadic) { } Function Function::clone() const @@ -97,7 +101,7 @@ Function Function::clone() const for(const auto& arg : m_args) new_args.push_back( ::std::make_pair( arg.first.clone(), arg.second ) ); - auto rv = Function( m_span, m_params, m_rettype, mv$(new_args) ); + auto rv = Function( m_span, m_params, m_abi, m_is_unsafe, m_is_const, m_is_variadic, m_rettype, mv$(new_args) ); if( m_code.is_valid() ) { rv.m_code = AST::Expr( m_code.node().clone() ); diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 0b2f6729..866dcf6e 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -163,7 +163,12 @@ private: Expr m_code; TypeRef m_rettype; Arglist m_args; + // TODO: ABI, const, and unsafe + ::std::string m_abi; + bool m_is_const; + bool m_is_unsafe; + bool m_is_variadic; // extern only public: Function() {} @@ -171,10 +176,16 @@ public: Function& operator=(const Function&) = delete; Function(Function&&) = default; Function& operator=(Function&&) = default; - Function(Span sp, GenericParams params, TypeRef ret_type, Arglist args); + + Function(Span sp, GenericParams params, ::std::string abi, bool is_unsafe, bool is_const, bool is_variadic, TypeRef ret_type, Arglist args); void set_code(Expr code) { m_code = ::std::move(code); } + const ::std::string& abi() const { return m_abi; }; + bool is_const() const { return m_is_const; } + bool is_unsafe() const { return m_is_unsafe; } + bool is_variadic() const { return m_is_variadic; } + const GenericParams& params() const { return m_params; } GenericParams& params() { return m_params; } const Expr& code() const { return m_code; } diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index c6a733cb..2995c374 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -237,6 +237,7 @@ class Deriver_Debug: AST::Function fcn( sp, AST::GenericParams(), + "rust", false, false, false, ret_type, vec$( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ), @@ -413,6 +414,7 @@ class Deriver_PartialEq: AST::Function fcn( sp, AST::GenericParams(), + "rust", false, false, false, TypeRef(sp, CORETYPE_BOOL), vec$( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ), @@ -596,6 +598,7 @@ class Deriver_Eq: AST::Function fcn( sp, AST::GenericParams(), + "rust", false, false, false, TypeRef(TypeRef::TagUnit(), sp), vec$( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ) @@ -733,6 +736,7 @@ class Deriver_Clone: AST::Function fcn( sp, AST::GenericParams(), + "rust", false, false, false, TypeRef("Self", 0xFFFF), vec$( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ) diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 2e776332..6755c99a 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -233,7 +233,7 @@ void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params) } /// 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) +AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_self, bool can_be_prototype, bool is_unsafe, bool is_const) { TRACE_FUNCTION; ProtoSpan ps = lex.start_span(); @@ -341,6 +341,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt // Unbound method } + bool is_variadic = false; if( tok.type() != TOK_PAREN_CLOSE ) { // Comma after self @@ -360,7 +361,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt } if( LOOK_AHEAD(lex) == TOK_TRIPLE_DOT ) { GET_TOK(tok, lex); - // TODO: Mark function as vardic + is_variadic = true; GET_TOK(tok, lex); break; } @@ -391,13 +392,13 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt PUTBACK(tok, lex); } - return AST::Function(lex.end_span(ps), mv$(params), mv$(ret_type), mv$(args)); + return AST::Function(lex.end_span(ps), mv$(params), mv$(abi), is_unsafe, is_const, is_variadic, mv$(ret_type), mv$(args)); } -AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST::MetaItems& attrs, bool allow_self) +AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, bool allow_self, bool is_unsafe, bool is_const) { Token tok; - auto ret = Parse_FunctionDef(lex, abi, attrs, allow_self, false); + auto ret = Parse_FunctionDef(lex, abi, allow_self, false, is_unsafe, is_const); GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); PUTBACK(tok, lex); ret.set_code( Parse_ExprBlock(lex) ); @@ -454,7 +455,6 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items) if(tok.type() == TOK_PAREN_OPEN) { // Tuple structs - // TODO: Using `StructItem` here isn't the best option. Should have another type ::std::vector refs; while(GET_TOK(tok, lex) != TOK_PAREN_CLOSE) { @@ -608,6 +608,8 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) // TODO: Mark specialisation (void)is_specialisable; + bool fn_is_const = false; + bool fn_is_unsafe = false; ::std::string abi = "rust"; switch(tok.type()) { @@ -671,8 +673,9 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) break; } // Functions (possibly unsafe) + // TODO: Const? case TOK_RWORD_UNSAFE: - item_attrs.push_back( AST::MetaItem("#UNSAFE") ); + fn_is_unsafe = true; if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN ) case TOK_RWORD_EXTERN: { @@ -689,7 +692,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); // Self allowed, prototype-form allowed (optional names and no code) - auto fcn = Parse_FunctionDef(lex, abi, item_attrs, true, true); + auto fcn = Parse_FunctionDef(lex, abi, true, true, fn_is_unsafe, fn_is_const); if( GET_TOK(tok, lex) == TOK_BRACE_OPEN ) { PUTBACK(tok, lex); @@ -704,7 +707,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) throw ParseError::Unexpected(lex, tok); } // TODO: Store `item_attrs` - trait.add_function( ::std::move(name), ::std::move(fcn) ); + trait.add_function( ::std::move(name), /*mv$(item_attrs),*/ ::std::move(fcn) ); break; } default: throw ParseError::Unexpected(lex, tok); @@ -801,7 +804,6 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items) auto name = mv$(tok.str()); GET_CHECK_TOK(tok, lex, TOK_COLON); auto ty = Parse_Type(lex); - // TODO: Field attributes fields.push_back( ::AST::StructItem(mv$(field_attrs), true, mv$(name), mv$(ty)) ); } while( GET_TOK(tok, lex) == TOK_COMMA ); CHECK_TOK(tok, TOK_BRACE_CLOSE); @@ -1006,12 +1008,9 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) GET_TOK(tok, lex); } - if(tok.type() == TOK_RWORD_UNSAFE) { - item_attrs.push_back( AST::MetaItem("#UNSAFE") ); - GET_TOK(tok, lex); - } - ::std::string abi = "rust"; + bool fn_is_unsafe = false; + bool fn_is_const = false; switch(tok.type()) { case TOK_RWORD_TYPE: { @@ -1021,31 +1020,35 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) impl.add_type(is_public, is_specialisable, name, Parse_Type(lex)); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); break; } - case TOK_RWORD_CONST: + case TOK_RWORD_UNSAFE: + fn_is_unsafe = true; GET_TOK(tok, lex); - if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE ) - { - CHECK_TOK(tok, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - auto ty = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - auto val = Parse_Expr(lex); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - - auto i = ::AST::Static(AST::Static::CONST, mv$(ty), mv$(val)); - // TODO: Attributes on associated constants - impl.add_static( is_public, is_specialisable, mv$(name), mv$(i) /*, mv$(item_attrs)*/ ); - break ; - } - else if( tok.type() == TOK_RWORD_UNSAFE ) + if( tok.type() == TOK_RWORD_CONST ) + case TOK_RWORD_CONST: { - GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); - // TODO: Use a better marker - item_attrs.push_back( AST::MetaItem("#UNSAFE") ); + GET_TOK(tok, lex); + if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE ) + { + CHECK_TOK(tok, TOK_IDENT); + auto name = mv$(tok.str()); + GET_CHECK_TOK(tok, lex, TOK_COLON); + auto ty = Parse_Type(lex); + GET_CHECK_TOK(tok, lex, TOK_EQUAL); + auto val = Parse_Expr(lex); + GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); + + auto i = ::AST::Static(AST::Static::CONST, mv$(ty), mv$(val)); + // TODO: Attributes on associated constants + impl.add_static( is_public, is_specialisable, mv$(name), mv$(i) /*, mv$(item_attrs)*/ ); + break ; + } + else if( tok.type() == TOK_RWORD_UNSAFE ) + { + fn_is_unsafe = true; + GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); + } + fn_is_const = true; } - // TODO: Mark `const fn` as const (properly) - item_attrs.push_back( AST::MetaItem("#CONST") ); if( 0 ) // FALL case TOK_RWORD_EXTERN: @@ -1065,7 +1068,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) ::std::string name = tok.str(); DEBUG("Function " << name); // - Self allowed, can't be prototype-form - auto fcn = Parse_FunctionDefWithCode(lex, abi, item_attrs, true); + auto fcn = Parse_FunctionDefWithCode(lex, abi, true, fn_is_unsafe, fn_is_const); impl.add_function(is_public, is_specialisable, mv$(name), mv$(fcn)); break; } @@ -1115,8 +1118,8 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::M GET_CHECK_TOK(tok, lex, TOK_IDENT); auto name = mv$(tok.str()); // parse function as prototype - // - no self - auto i = ::AST::Item( Parse_FunctionDef(lex, abi, meta_items, false, true) ); + // - no self, "safe" and not const + auto i = ::AST::Item( Parse_FunctionDef(lex, abi, false, true, false,false) ); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); i.attrs = mv$(meta_items); @@ -1362,9 +1365,9 @@ void Parse_Use(TokenStream& lex, ::std::function