diff options
author | John Hodge <tpg@mutabah.net> | 2015-03-15 10:27:03 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-03-15 10:27:03 +0800 |
commit | 3d8538bb3eba616001ff3c89d995e4190cfe1272 (patch) | |
tree | 620979c6897bd0e75067c6a16df5dd9a649acc73 /src | |
parent | bf14a518b591b8f43a92c13d85b1ae5db8965703 (diff) | |
download | mrust-3d8538bb3eba616001ff3c89d995e4190cfe1272.tar.gz |
Function types
Diffstat (limited to 'src')
-rw-r--r-- | src/parse/root.cpp | 86 | ||||
-rw-r--r-- | src/types.cpp | 34 | ||||
-rw-r--r-- | src/types.hpp | 10 |
3 files changed, 123 insertions, 7 deletions
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<TypeRef> 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");
// <Type as Trait>::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<AST::StructItem> 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 \"<ABI>\"' block");
+}
+
void Parse_Use_Wildcard(const AST::Path& base_path, ::std::function<void(AST::Path, ::std::string)> 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 \"<ABI>\" 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<TypeRef(const char*)> 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<void(const char*, if( m_core_type != other.m_core_type ) throw ::std::runtime_error("Type mismatch (core)"); break; + case TypeRef::FUNCTION: + if( m_path[0].name() != other.m_path[0].name() ) + throw ::std::runtime_error("Type mismatch (function abo)"); + if( m_inner_types.size() != other.m_inner_types.size() ) + throw ::std::runtime_error("Type mismatch (function size)"); case TypeRef::TUPLE: if( m_inner_types.size() != other.m_inner_types.size() ) throw ::std::runtime_error("Type mismatch (tuple size)"); @@ -264,6 +276,7 @@ bool TypeRef::is_concrete() const case TypeRef::UNIT: case TypeRef::PRIMITIVE: return true; + case TypeRef::FUNCTION: case TypeRef::TUPLE: case TypeRef::REFERENCE: case TypeRef::POINTER: @@ -309,6 +322,9 @@ bool TypeRef::operator==(const TypeRef& x) const return true; case TypeRef::PRIMITIVE: return m_core_type == x.m_core_type; + case TypeRef::FUNCTION: + if( m_path[0].name() != x.m_path[0].name() ) + return false; case TypeRef::TUPLE: return m_inner_types == x.m_inner_types; case TypeRef::REFERENCE: @@ -356,6 +372,14 @@ bool TypeRef::operator==(const TypeRef& x) const //os << "TagPrimitive, " << tr.m_core_type; os << tr.m_core_type; break; + case TypeRef::FUNCTION: + if( tr.m_path[0].name() != "" ) + os << "extern \"" << tr.m_path[0].name() << "\" "; + os << "fn ("; + for( unsigned int i = 0; i < tr.m_inner_types.size()-1; i ++ ) + os << tr.m_inner_types[i] << ", "; + os << ") -> " << 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<TypeRef> 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),
|