summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-20 13:18:29 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-20 13:18:29 +0800
commitde16b83e86ac67aa02c188bdcbb3d19088a90b97 (patch)
tree5376e84a3419203162225a2fe82359a5f3f4060c /src
parent66fcd19348efb2e16a21124c4465f4b911d87ded (diff)
downloadmrust-de16b83e86ac67aa02c188bdcbb3d19088a90b97.tar.gz
Split parse/root.cpp up
Diffstat (limited to 'src')
-rw-r--r--src/parse/common.hpp1
-rw-r--r--src/parse/paths.cpp180
-rw-r--r--src/parse/root.cpp380
-rw-r--r--src/parse/types.cpp221
4 files changed, 425 insertions, 357 deletions
diff --git a/src/parse/common.hpp b/src/parse/common.hpp
index 3ee985c0..3fb5a9ec 100644
--- a/src/parse/common.hpp
+++ b/src/parse/common.hpp
@@ -26,6 +26,7 @@ enum eParsePathGenericMode
};
extern AST::MetaItem Parse_MetaItem(TokenStream& lex);
+extern AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode); // Auto-determines
extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
extern AST::Path Parse_PathFrom(TokenStream& lex, AST::Path src, eParsePathGenericMode generic_mode);
extern ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp
new file mode 100644
index 00000000..3fb1d779
--- /dev/null
+++ b/src/parse/paths.cpp
@@ -0,0 +1,180 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/paths.cpp
+ * - Parsing for module paths
+ */
+#include "parseerror.hpp"
+#include "common.hpp"
+#include "../ast/ast.hpp"
+
+AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode);
+AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
+AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode);
+::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
+
+AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode)
+{
+ Token tok;
+ if( GET_TOK(tok, lex) == TOK_DOUBLE_COLON )
+ return Parse_Path(lex, true, generic_mode);
+ else
+ {
+ lex.putback(tok);
+ return Parse_Path(lex, false, generic_mode);
+ }
+}
+AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode)
+{
+ if( is_abs )
+ {
+ Token tok;
+ if( GET_TOK(tok, lex) == TOK_STRING ) {
+ ::std::string cratename = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
+ return Parse_PathFrom(lex, AST::Path(cratename, {}), generic_mode);
+ }
+ else {
+ lex.putback(tok);
+ return Parse_PathFrom(lex, AST::Path(AST::Path::TagAbsolute()), generic_mode);
+ }
+ }
+ else
+ return Parse_PathFrom(lex, AST::Path(), generic_mode);
+}
+
+AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode)
+{
+ TRACE_FUNCTION_F("path = " << path);
+
+ Token tok;
+
+ tok = lex.getToken();
+ while(true)
+ {
+ ::std::vector<TypeRef> params;
+
+ CHECK_TOK(tok, TOK_IDENT);
+ ::std::string component = tok.str();
+
+ GET_TOK(tok, lex);
+ if( generic_mode == PATH_GENERIC_TYPE )
+ {
+ if( tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT )
+ {
+ // HACK! Handle breaking << into < <
+ if( tok.type() == TOK_DOUBLE_LT )
+ lex.putback( Token(TOK_LT) );
+
+ // Type-mode generics "::path::to::Type<A,B>"
+ params = Parse_Path_GenericList(lex);
+ tok = lex.getToken();
+ }
+ // HACK - 'Fn*(...) -> ...' notation
+ else if( tok.type() == TOK_PAREN_OPEN )
+ {
+ DEBUG("Fn() hack");
+ ::std::vector<TypeRef> args;
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
+ {
+ // Empty list
+ }
+ else
+ {
+ lex.putback(tok);
+ do {
+ args.push_back( Parse_Type(lex) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ }
+ CHECK_TOK(tok, 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);
+ }
+ DEBUG("- Fn("<<args<<")->"<<ret_type<<"");
+
+ // Encode into path, by converting Fn(A,B)->C into Fn<(A,B),Ret=C>
+ params = ::std::vector<TypeRef> { TypeRef(TypeRef::TagTuple(), ::std::move(args)) };
+ // TODO: Use 'ret_type' as an associated type bound
+
+ GET_TOK(tok, lex);
+ }
+ else
+ {
+ }
+ }
+ if( tok.type() != TOK_DOUBLE_COLON ) {
+ path.append( AST::PathNode(component, params) );
+ break;
+ }
+ tok = lex.getToken();
+ if( generic_mode == PATH_GENERIC_EXPR && (tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT) )
+ {
+ // HACK! Handle breaking << into < <
+ if( tok.type() == TOK_DOUBLE_LT )
+ lex.putback( Token(TOK_LT) );
+
+ // Expr-mode generics "::path::to::function::<Type1,Type2>(arg1, arg2)"
+ params = Parse_Path_GenericList(lex);
+ tok = lex.getToken();
+ if( tok.type() != TOK_DOUBLE_COLON ) {
+ path.append( AST::PathNode(component, params) );
+ break;
+ }
+ GET_TOK(tok, lex);
+ }
+ path.append( AST::PathNode(component, params) );
+ }
+ lex.putback(tok);
+ DEBUG("path = " << path);
+ return path;
+}
+/// Parse a list of parameters within a path
+::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ ::std::vector<TypeRef> types;
+ ::std::vector< ::std::string> lifetimes;
+ ::std::map< ::std::string, TypeRef> assoc_bounds;
+ ::std::vector<unsigned int> int_args;
+ do {
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_LIFETIME:
+ lifetimes.push_back( tok.str() );
+ break;
+ case TOK_IDENT:
+ if( LOOK_AHEAD(lex) == TOK_EQUAL )
+ {
+ ::std::string name = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ assoc_bounds.insert( ::std::make_pair( ::std::move(name), Parse_Type(lex) ) );
+ break;
+ }
+ default:
+ lex.putback(tok);
+ types.push_back( Parse_Type(lex) );
+ break;
+ }
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+
+ // HACK: Split >> into >
+ if(tok.type() == TOK_DOUBLE_GT) {
+ lex.putback(Token(TOK_GT));
+ }
+ else {
+ CHECK_TOK(tok, TOK_GT);
+ }
+
+ // TODO: Actually use the lifetimes/assoc_bounds
+
+ return types;
+}
+
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 7f2ed359..8b8f3b2f 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -10,357 +10,6 @@ extern AST::Pattern Parse_Pattern(TokenStream& lex);
AST::MetaItem Parse_MetaItem(TokenStream& lex);
void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*> *prev_modstack, const ::std::string& path);
-AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode);
-AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
-AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode);
-::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
-
-AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode)
-{
- Token tok;
- if( GET_TOK(tok, lex) == TOK_DOUBLE_COLON )
- return Parse_Path(lex, true, generic_mode);
- else
- {
- lex.putback(tok);
- return Parse_Path(lex, false, generic_mode);
- }
-}
-AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode)
-{
- if( is_abs )
- {
- Token tok;
- if( GET_TOK(tok, lex) == TOK_STRING ) {
- ::std::string cratename = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- return Parse_PathFrom(lex, AST::Path(cratename, {}), generic_mode);
- }
- else {
- lex.putback(tok);
- return Parse_PathFrom(lex, AST::Path(AST::Path::TagAbsolute()), generic_mode);
- }
- }
- else
- return Parse_PathFrom(lex, AST::Path(), generic_mode);
-}
-
-AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode)
-{
- TRACE_FUNCTION_F("path = " << path);
-
- Token tok;
-
- tok = lex.getToken();
- while(true)
- {
- ::std::vector<TypeRef> params;
-
- CHECK_TOK(tok, TOK_IDENT);
- ::std::string component = tok.str();
-
- GET_TOK(tok, lex);
- if( generic_mode == PATH_GENERIC_TYPE )
- {
- if( tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT )
- {
- // HACK! Handle breaking << into < <
- if( tok.type() == TOK_DOUBLE_LT )
- lex.putback( Token(TOK_LT) );
-
- // Type-mode generics "::path::to::Type<A,B>"
- params = Parse_Path_GenericList(lex);
- tok = lex.getToken();
- }
- // HACK - 'Fn*(...) -> ...' notation
- else if( tok.type() == TOK_PAREN_OPEN )
- {
- DEBUG("Fn() hack");
- ::std::vector<TypeRef> args;
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- {
- // Empty list
- }
- else
- {
- lex.putback(tok);
- do {
- args.push_back( Parse_Type(lex) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- }
- CHECK_TOK(tok, 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);
- }
- DEBUG("- Fn("<<args<<")->"<<ret_type<<"");
-
- // Encode into path, by converting Fn(A,B)->C into Fn<(A,B),Ret=C>
- params = ::std::vector<TypeRef> { TypeRef(TypeRef::TagTuple(), ::std::move(args)) };
- // TODO: Use 'ret_type' as an associated type bound
-
- GET_TOK(tok, lex);
- }
- else
- {
- }
- }
- if( tok.type() != TOK_DOUBLE_COLON ) {
- path.append( AST::PathNode(component, params) );
- break;
- }
- tok = lex.getToken();
- if( generic_mode == PATH_GENERIC_EXPR && (tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT) )
- {
- // HACK! Handle breaking << into < <
- if( tok.type() == TOK_DOUBLE_LT )
- lex.putback( Token(TOK_LT) );
-
- // Expr-mode generics "::path::to::function::<Type1,Type2>(arg1, arg2)"
- params = Parse_Path_GenericList(lex);
- tok = lex.getToken();
- if( tok.type() != TOK_DOUBLE_COLON ) {
- path.append( AST::PathNode(component, params) );
- break;
- }
- GET_TOK(tok, lex);
- }
- path.append( AST::PathNode(component, params) );
- }
- lex.putback(tok);
- DEBUG("path = " << path);
- return path;
-}
-/// Parse a list of parameters within a path
-::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex)
-{
- TRACE_FUNCTION;
- Token tok;
-
- ::std::vector<TypeRef> types;
- ::std::vector< ::std::string> lifetimes;
- ::std::map< ::std::string, TypeRef> assoc_bounds;
- ::std::vector<unsigned int> int_args;
- do {
- switch(GET_TOK(tok, lex))
- {
- case TOK_LIFETIME:
- lifetimes.push_back( tok.str() );
- break;
- case TOK_IDENT:
- if( LOOK_AHEAD(lex) == TOK_EQUAL )
- {
- ::std::string name = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- assoc_bounds.insert( ::std::make_pair( ::std::move(name), Parse_Type(lex) ) );
- break;
- }
- default:
- lex.putback(tok);
- types.push_back( Parse_Type(lex) );
- break;
- }
- } while( GET_TOK(tok, lex) == TOK_COMMA );
-
- // HACK: Split >> into >
- if(tok.type() == TOK_DOUBLE_GT) {
- lex.putback(Token(TOK_GT));
- }
- else {
- CHECK_TOK(tok, TOK_GT);
- }
-
- // TODO: Actually use the lifetimes/assoc_bounds
-
- return types;
-}
-
-static const struct {
- const char* name;
- enum eCoreType type;
-} CORETYPES[] = {
- {"char", CORETYPE_CHAR},
- {"f32", CORETYPE_F32},
- {"f64", CORETYPE_F64},
- {"i16", CORETYPE_I16},
- {"i32", CORETYPE_I32},
- {"i64", CORETYPE_I64},
- {"i8", CORETYPE_I8},
- {"int", CORETYPE_INT},
- {"isize", CORETYPE_INT},
- {"u16", CORETYPE_U16},
- {"u32", CORETYPE_U32},
- {"u64", CORETYPE_U64},
- {"u8", CORETYPE_U8},
- {"uint", CORETYPE_UINT},
- {"usize", CORETYPE_UINT},
-};
-
-TypeRef Parse_Type(TokenStream& lex);
-TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi);
-
-TypeRef Parse_Type(TokenStream& lex)
-{
- //TRACE_FUNCTION;
-
- Token tok;
-
- switch( GET_TOK(tok, lex) )
- {
- case TOK_UNDERSCORE:
- return TypeRef();
- case TOK_RWORD_EXTERN: {
- GET_CHECK_TOK(tok, lex, TOK_STRING);
- ::std::string abi = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
- return Parse_Type_Fn(lex, abi);
- }
- case TOK_RWORD_FN:
- return Parse_Type_Fn(lex, "");
- case TOK_LT: {
- DEBUG("Associated type");
- // <Type as Trait>::Inner
- TypeRef base = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
- TypeRef trait = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- // TODO: Is just '<Type as Trait>' valid?
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string inner_name = tok.str();
- return TypeRef(TypeRef::TagAssoc(), ::std::move(base), ::std::move(trait), ::std::move(inner_name));
- }
- case TOK_IDENT:
- // Either a path (with generics)
- if( tok.str() == "_" )
- return TypeRef();
- // or a primitive
- for(unsigned int i = 0; i < sizeof(CORETYPES)/sizeof(CORETYPES[0]); i ++)
- {
- if( tok.str() < CORETYPES[i].name )
- break;
- if( tok.str() == CORETYPES[i].name )
- return TypeRef(TypeRef::TagPrimitive(), CORETYPES[i].type);
- }
- lex.putback(tok);
- return TypeRef(TypeRef::TagPath(), Parse_Path(lex, false, PATH_GENERIC_TYPE)); // relative path
- case TOK_DOUBLE_COLON:
- // Path with generics
- return TypeRef(TypeRef::TagPath(), Parse_Path(lex, true, PATH_GENERIC_TYPE));
- case TOK_RWORD_SUPER:
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- return TypeRef(TypeRef::TagPath(), Parse_PathFrom(lex, AST::Path(AST::Path::TagSuper()), PATH_GENERIC_TYPE));
-
- // HACK! Convert && into & &
- case TOK_DOUBLE_AMP:
- lex.putback(Token(TOK_AMP));
- case TOK_AMP: {
- ::std::string lifetime;
- // Reference
- tok = lex.getToken();
- if( tok.type() == TOK_LIFETIME ) {
- lifetime = tok.str();
- tok = lex.getToken();
- }
- if( tok.type() == TOK_RWORD_MUT ) {
- // Mutable reference
- return TypeRef(TypeRef::TagReference(), true, Parse_Type(lex));
- }
- else {
- lex.putback(tok);
- // Immutable reference
- return TypeRef(TypeRef::TagReference(), false, Parse_Type(lex));
- }
- throw ParseError::BugCheck("Reached end of Parse_Type:AMP");
- }
- case TOK_STAR:
- // Pointer
- switch( GET_TOK(tok, lex) )
- {
- case TOK_RWORD_MUT:
- // Mutable pointer
- return TypeRef(TypeRef::TagPointer(), true, Parse_Type(lex));
- case TOK_RWORD_CONST:
- // Immutable pointer
- return TypeRef(TypeRef::TagPointer(), false, Parse_Type(lex));
- default:
- throw ParseError::Unexpected(lex, tok, Token(TOK_RWORD_CONST));
- }
- throw ParseError::BugCheck("Reached end of Parse_Type:STAR");
- case TOK_SQUARE_OPEN: {
- // Array
- TypeRef inner = Parse_Type(lex);
- if( GET_TOK(tok, lex) == TOK_SEMICOLON ) {
- // Sized array
- AST::Expr array_size = Parse_Expr(lex, true);
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- return TypeRef(TypeRef::TagSizedArray(), inner, array_size.take_node());
- }
- else if( tok.type() == TOK_SQUARE_CLOSE )
- {
- return TypeRef(TypeRef::TagUnsizedArray(), inner);
- }
- else {
- throw ParseError::Unexpected(lex, tok/*, "; or ]"*/);
- }
- }
- case TOK_PAREN_OPEN: {
- DEBUG("Tuple");
- ::std::vector<TypeRef> types;
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- return TypeRef(TypeRef::TagTuple(), types);
- lex.putback(tok);
- do
- {
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- break;
- else
- lex.putback(tok);
- types.push_back(Parse_Type(lex));
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
- return TypeRef(TypeRef::TagTuple(), types); }
- case TOK_EXCLAM:
- throw ParseError::Generic(lex, "! is not a real type");
- default:
- throw ParseError::Unexpected(lex, tok);
- }
- throw ParseError::BugCheck("Reached end of Parse_Type");
-}
-
-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));
-}
-
/// Parse type parameters in a definition
void Parse_TypeBound(TokenStream& lex, AST::TypeParams& ret, TypeRef checked_type)
{
@@ -383,6 +32,7 @@ void Parse_TypeBound(TokenStream& lex, AST::TypeParams& ret, TypeRef checked_typ
lex.putback(tok);
}
+/// Parse type parameters within '<' and '>' (definition)
AST::TypeParams Parse_TypeParams(TokenStream& lex)
{
TRACE_FUNCTION;
@@ -430,17 +80,23 @@ AST::TypeParams Parse_TypeParams(TokenStream& lex)
return ret;
}
+
+/// Parse the contents of a 'where' clause
void Parse_WhereClause(TokenStream& lex, AST::TypeParams& params)
{
TRACE_FUNCTION;
Token tok;
do {
- if( GET_TOK(tok, lex) == TOK_LIFETIME )
+ GET_TOK(tok, lex);
+ if( tok.type() == TOK_BRACE_OPEN ) {
+ break;
+ }
+
+ if( tok.type() == TOK_LIFETIME )
{
+ throw ParseError::Todo(lex, "Lifetime bounds in 'where' clauses");
}
- else if( tok.type() == TOK_BRACE_OPEN )
- break;
else
{
lex.putback(tok);
@@ -460,7 +116,17 @@ void Parse_WhereClause(TokenStream& lex, AST::TypeParams& params)
AST::Pattern pat;
- if( expect_named || LOOK_AHEAD(lex) == TOK_UNDERSCORE || LOOK_AHEAD(lex) == TOK_RWORD_MUT || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON) )
+ // If any of the following
+ // - Expecting a named parameter (i.e. defining a function in root or impl)
+ // - Next token is an underscore (only valid as a pattern here)
+ // - Next token is 'mut' (a mutable parameter slot)
+ // - Next two are <ident> ':' (a trivial named parameter)
+ // NOTE: When not expecting a named param, destructuring patterns are not allowed
+ if( expect_named
+ || LOOK_AHEAD(lex) == TOK_UNDERSCORE
+ || LOOK_AHEAD(lex) == TOK_RWORD_MUT
+ || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON)
+ )
{
pat = Parse_Pattern(lex);
GET_CHECK_TOK(tok, lex, TOK_COLON);
@@ -1464,7 +1130,7 @@ void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_it
void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*>& modstack, const ::std::string& path)
{
//TRACE_FUNCTION;
- const bool nested_module = (path == "-"); // 'mod name { code }', as opposed to 'mod name;'
+ const bool nested_module = (path == "-" || path == "!"); // 'mod name { code }', as opposed to 'mod name;'
Token tok;
for(;;)
@@ -1687,7 +1353,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod,
break; }
case TOK_SEMICOLON:
DEBUG("Mod = " << name << ", curpath = " << path);
- if( path == "-" || path == "!" ) {
+ if( nested_module ) {
throw ParseError::Generic(lex, "Cannot load module from file within nested context");
}
else if( path.back() != '/' )
diff --git a/src/parse/types.cpp b/src/parse/types.cpp
new file mode 100644
index 00000000..b9cf3cc1
--- /dev/null
+++ b/src/parse/types.cpp
@@ -0,0 +1,221 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/types.cpp
+ * - Parsing for type usages
+ */
+#include "common.hpp"
+#include "parseerror.hpp"
+#include "../types.hpp"
+#include "../ast/ast.hpp"
+
+/// Mappings from internal type names to the core type enum
+static const struct {
+ const char* name;
+ enum eCoreType type;
+} CORETYPES[] = {
+ {"char", CORETYPE_CHAR},
+ {"f32", CORETYPE_F32},
+ {"f64", CORETYPE_F64},
+ {"i16", CORETYPE_I16},
+ {"i32", CORETYPE_I32},
+ {"i64", CORETYPE_I64},
+ {"i8", CORETYPE_I8},
+ {"int", CORETYPE_INT},
+ {"isize", CORETYPE_INT},
+ {"u16", CORETYPE_U16},
+ {"u32", CORETYPE_U32},
+ {"u64", CORETYPE_U64},
+ {"u8", CORETYPE_U8},
+ {"uint", CORETYPE_UINT},
+ {"usize", CORETYPE_UINT},
+};
+
+// === PROTOTYPES ===
+TypeRef Parse_Type(TokenStream& lex);
+TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi);
+
+// === CODE ===
+TypeRef Parse_Type(TokenStream& lex)
+{
+ //TRACE_FUNCTION;
+
+ Token tok;
+
+ switch( GET_TOK(tok, lex) )
+ {
+ // '_' = Wildcard (type inferrence variable)
+ case TOK_UNDERSCORE:
+ return TypeRef();
+ // 'extern' - A function type with an ABI
+ case TOK_RWORD_EXTERN: {
+ GET_CHECK_TOK(tok, lex, TOK_STRING);
+ ::std::string abi = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ return Parse_Type_Fn(lex, abi);
+ }
+ // 'fn' - Rust function
+ case TOK_RWORD_FN:
+ return Parse_Type_Fn(lex, "");
+ // '<' - An associated type cast
+ case TOK_LT: {
+ DEBUG("Associated type");
+ // <Type as Trait>::Inner
+ TypeRef base = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
+ TypeRef trait = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ // TODO: Is just '<Type as Trait>' valid?
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string inner_name = tok.str();
+ return TypeRef(TypeRef::TagAssoc(), ::std::move(base), ::std::move(trait), ::std::move(inner_name));
+ }
+ // <ident> - Either a primitive, or a path
+ case TOK_IDENT:
+ // or a primitive
+ for(unsigned int i = 0; i < sizeof(CORETYPES)/sizeof(CORETYPES[0]); i ++)
+ {
+ if( tok.str() < CORETYPES[i].name )
+ break;
+ if( tok.str() == CORETYPES[i].name )
+ return TypeRef(TypeRef::TagPrimitive(), CORETYPES[i].type);
+ }
+ lex.putback(tok);
+ return TypeRef(TypeRef::TagPath(), Parse_Path(lex, false, PATH_GENERIC_TYPE)); // relative path
+ // '::' - Absolute path
+ case TOK_DOUBLE_COLON:
+ // Path with generics
+ return TypeRef(TypeRef::TagPath(), Parse_Path(lex, true, PATH_GENERIC_TYPE));
+ // 'super' - Parent relative path
+ case TOK_RWORD_SUPER:
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
+ return TypeRef(TypeRef::TagPath(), Parse_PathFrom(lex, AST::Path(AST::Path::TagSuper()), PATH_GENERIC_TYPE));
+
+ // HACK! Convert && into & &
+ case TOK_DOUBLE_AMP:
+ lex.putback(Token(TOK_AMP));
+ // '&' - Reference type
+ case TOK_AMP: {
+ ::std::string lifetime;
+ // Reference
+ tok = lex.getToken();
+ if( tok.type() == TOK_LIFETIME ) {
+ lifetime = tok.str();
+ tok = lex.getToken();
+ }
+ if( tok.type() == TOK_RWORD_MUT ) {
+ // Mutable reference
+ return TypeRef(TypeRef::TagReference(), true, Parse_Type(lex));
+ }
+ else {
+ lex.putback(tok);
+ // Immutable reference
+ return TypeRef(TypeRef::TagReference(), false, Parse_Type(lex));
+ }
+ throw ParseError::BugCheck("Reached end of Parse_Type:AMP");
+ }
+ // '*' - Raw pointer
+ case TOK_STAR:
+ // Pointer
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_RWORD_MUT:
+ // Mutable pointer
+ return TypeRef(TypeRef::TagPointer(), true, Parse_Type(lex));
+ case TOK_RWORD_CONST:
+ // Immutable pointer
+ return TypeRef(TypeRef::TagPointer(), false, Parse_Type(lex));
+ default:
+ throw ParseError::Unexpected(lex, tok, Token(TOK_RWORD_CONST));
+ }
+ throw ParseError::BugCheck("Reached end of Parse_Type:STAR");
+ // '[' - Array type
+ case TOK_SQUARE_OPEN: {
+ // Array
+ TypeRef inner = Parse_Type(lex);
+ if( GET_TOK(tok, lex) == TOK_SEMICOLON ) {
+ // Sized array
+ AST::Expr array_size = Parse_Expr(lex, true);
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ return TypeRef(TypeRef::TagSizedArray(), inner, array_size.take_node());
+ }
+ else if( tok.type() == TOK_SQUARE_CLOSE )
+ {
+ return TypeRef(TypeRef::TagUnsizedArray(), inner);
+ }
+ else {
+ throw ParseError::Unexpected(lex, tok/*, "; or ]"*/);
+ }
+ }
+
+ // '(' - Tuple (or lifetime bounded trait)
+ case TOK_PAREN_OPEN: {
+ DEBUG("Tuple");
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
+ return TypeRef(TypeRef::TagTuple(), {});
+ lex.putback(tok);
+
+ TypeRef inner = Parse_Type(lex);
+ if( GET_TOK(tok, lex) == TOK_PLUS )
+ {
+ // Lifetime bounded type, NOT a tuple
+ GET_CHECK_TOK(tok, lex, TOK_LIFETIME);
+ ::std::string lifetime = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
+ throw ParseError::Todo(lex, "Type lifetime bounds");
+ }
+ else
+ {
+ ::std::vector<TypeRef> types;
+ types.push_back( ::std::move(inner) );
+ lex.putback(tok);
+ while( GET_TOK(tok, lex) == TOK_COMMA )
+ {
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
+ break;
+ else
+ lex.putback(tok);
+ types.push_back(Parse_Type(lex));
+ }
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ return TypeRef(TypeRef::TagTuple(), types); }
+ }
+ case TOK_EXCLAM:
+ throw ParseError::Generic(lex, "! is not a real type");
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ throw ParseError::BugCheck("Reached end of Parse_Type");
+}
+
+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));
+}
+