summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-15 10:27:03 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-15 10:27:03 +0800
commit3d8538bb3eba616001ff3c89d995e4190cfe1272 (patch)
tree620979c6897bd0e75067c6a16df5dd9a649acc73 /src
parentbf14a518b591b8f43a92c13d85b1ae5db8965703 (diff)
downloadmrust-3d8538bb3eba616001ff3c89d995e4190cfe1272.tar.gz
Function types
Diffstat (limited to 'src')
-rw-r--r--src/parse/root.cpp86
-rw-r--r--src/types.cpp34
-rw-r--r--src/types.hpp10
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),