From 3d8538bb3eba616001ff3c89d995e4190cfe1272 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 15 Mar 2015 10:27:03 +0800 Subject: Function types --- src/parse/root.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/types.cpp | 34 +++++++++++++++++++++ src/types.hpp | 10 +++++++ 3 files changed, 123 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/parse/root.cpp b/src/parse/root.cpp index c64dbb17..2083389d 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -145,6 +145,35 @@ static const struct { {"usize", CORETYPE_UINT}, }; +TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi) +{ + TRACE_FUNCTION; + Token tok; + + ::std::vector args; + GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); + while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE ) + { + args.push_back( Parse_Type(lex) ); + if( GET_TOK(tok, lex) != TOK_COMMA ) { + lex.putback(tok); + break; + } + } + GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); + + TypeRef ret_type = TypeRef(TypeRef::TagUnit()); + if( GET_TOK(tok, lex) == TOK_THINARROW ) + { + ret_type = Parse_Type(lex); + } + else { + lex.putback(tok); + } + + return TypeRef(TypeRef::TagFunction(), ::std::move(abi), ::std::move(args), ::std::move(ret_type)); +} + TypeRef Parse_Type(TokenStream& lex) { TRACE_FUNCTION; @@ -153,12 +182,14 @@ TypeRef Parse_Type(TokenStream& lex) switch( GET_TOK(tok, lex) ) { - case TOK_RWORD_EXTERN: + case TOK_RWORD_EXTERN: { GET_CHECK_TOK(tok, lex, TOK_STRING); - // abi = tok.str(); + ::std::string abi = tok.str(); GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); + return Parse_Type_Fn(lex, abi); + } case TOK_RWORD_FN: - throw ParseError::Todo(lex, "Function types"); + return Parse_Type_Fn(lex, ""); case TOK_LT: { DEBUG("Associated type"); // ::Inner @@ -524,9 +555,14 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons else if(tok.type() == TOK_BRACE_OPEN) { ::std::vector items; - while( (tok = lex.getToken()).type() != TOK_BRACE_CLOSE ) + while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) { - bool is_pub = false; + bool is_pub = false; + if(tok.type() == TOK_RWORD_PUB) { + is_pub = true; + GET_TOK(tok, lex); + } + CHECK_TOK(tok, TOK_IDENT); ::std::string name = tok.str(); GET_CHECK_TOK(tok, lex, TOK_COLON); @@ -794,6 +830,31 @@ AST::Impl Parse_Impl(TokenStream& lex) return impl; } +void Parse_ExternBlock(TokenStream& lex, AST::Module& mod, ::std::string abi) +{ + TRACE_FUNCTION; + Token tok; + + while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) + { + bool is_public = false; + if( tok.type() == TOK_RWORD_PUB ) { + is_public = true; + GET_TOK(tok, lex); + } + switch(tok.type()) + { + case TOK_RWORD_FN: + // parse function as prototype + throw ParseError::Todo(lex, "Extern block - fn"); + default: + throw ParseError::Unexpected(lex, tok); + } + } + + throw ParseError::Todo(lex, "'extern \"\"' block"); +} + void Parse_Use_Wildcard(const AST::Path& base_path, ::std::function fcn) { fcn(base_path, ""); // HACK! Empty path indicates wilcard import @@ -1186,8 +1247,19 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, case TOK_RWORD_EXTERN: switch( GET_TOK(tok, lex) ) { - case TOK_STRING: - throw ParseError::Todo("'extern \"C\"'"); + case TOK_STRING: { + ::std::string abi = tok.str(); + switch(GET_TOK(tok, lex)) + { + case TOK_RWORD_FN: + throw ParseError::Todo(lex, "'extern \"\" fn'"); + case TOK_BRACE_OPEN: + Parse_ExternBlock(lex, mod, ::std::move(abi)); + break; + default: + throw ParseError::Unexpected(lex, tok); + } + } break; case TOK_RWORD_CRATE: { ::std::string path, name; diff --git a/src/types.cpp b/src/types.cpp index 445f394c..b1f4735e 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -48,6 +48,8 @@ bool TypeRef::deref(bool is_implicit) throw ::std::runtime_error("Dereferencing a primtive type"); case TypeRef::GENERIC: throw ::std::runtime_error("Dereferencing a generic"); + case TypeRef::FUNCTION: + throw ::std::runtime_error("Dereferencing a function"); case TypeRef::REFERENCE: *this = m_inner_types[0]; return true; @@ -105,6 +107,10 @@ void TypeRef::merge_with(const TypeRef& other) case TypeRef::UNIT: case TypeRef::PRIMITIVE: throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard"); + case TypeRef::FUNCTION: + if( m_inner_types.size() != other.m_inner_types.size() ) + throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [function sz]"); + // - fall through to tuple code case TypeRef::TUPLE: // Other is known not to be wildcard, and is also a tuple, so it must be the same size if( m_inner_types.size() != other.m_inner_types.size() ) @@ -148,6 +154,7 @@ void TypeRef::resolve_args(::std::function fcn) case TypeRef::UNIT: case TypeRef::PRIMITIVE: break; + case TypeRef::FUNCTION: case TypeRef::TUPLE: case TypeRef::REFERENCE: case TypeRef::POINTER: @@ -207,6 +214,11 @@ void TypeRef::match_args(const TypeRef& other, ::std::function " << tr.m_inner_types.back(); + break; case TypeRef::TUPLE: //os << "TagTuple, {" << tr.m_inner_types << "}"; os << "(" << tr.m_inner_types << ",)"; @@ -416,6 +440,7 @@ const char* TypeRef::class_name(TypeRef::Class c) { _(ANY) _(UNIT) _(PRIMITIVE) + _(FUNCTION) _(TUPLE) _(REFERENCE) _(POINTER) @@ -434,6 +459,7 @@ void operator>>(::Deserialiser& d, TypeRef::Class& c) { /**/ _(ANY) else _(UNIT) else _(PRIMITIVE) + else _(FUNCTION) else _(TUPLE) else _(REFERENCE) else _(POINTER) @@ -487,6 +513,14 @@ void PrettyPrintType::print(::std::ostream& os) const case TypeRef::PRIMITIVE: os << m_type.m_core_type; break; + case TypeRef::FUNCTION: + if( m_type.m_path[0].name() != "" ) + os << "extern \"" << m_type.m_path[0].name() << "\" "; + os << "fn ("; + for( unsigned int i = 0; i < m_type.m_inner_types.size()-1; i ++ ) + os << m_type.m_inner_types[i].print_pretty() << ", "; + os << ") -> " << m_type.m_inner_types.back().print_pretty(); + break; case TypeRef::TUPLE: os << "("; for(const auto& t : m_type.m_inner_types) diff --git a/src/types.hpp b/src/types.hpp index d15c77ab..dad4493b 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -47,6 +47,7 @@ class TypeRef: //BOUNDED, //< '_: Traits' - Bounded type (a resolved type parameter usually) UNIT, //< '()' - Unit / void PRIMITIVE, //< Any primitive (builtin type) + FUNCTION, TUPLE, REFERENCE, POINTER, @@ -88,6 +89,15 @@ public: m_class(TUPLE), m_inner_types( ::std::move(inner_types) ) {} + struct TagFunction {}; + TypeRef(TagFunction, ::std::string abi, ::std::vector args, TypeRef ret): + m_class(FUNCTION), + m_path( {AST::PathNode( ::std::move(abi), {})} ), // abuse path for string + m_inner_types( ::std::move(args) ) + { + m_inner_types.push_back( ::std::move(ret) ); + } + struct TagReference {}; TypeRef(TagReference _, bool is_mut, TypeRef inner_type): m_class(REFERENCE), -- cgit v1.2.3