summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge (sonata) <tpg@mutabah.net>2015-01-16 09:14:38 +0800
committerJohn Hodge (sonata) <tpg@mutabah.net>2015-01-16 09:14:38 +0800
commit80e4060188913eb12ad8a774b07d3b938485a49a (patch)
treef8e978f4c1c93920aa16119199cf728b36915121
parent7d04ce9d4c945cedf08ff2a7fa0af49ea4e6e1b0 (diff)
downloadmrust-80e4060188913eb12ad8a774b07d3b938485a49a.tar.gz
Added associated type reference parse, and tuple value parse
-rw-r--r--samples/std.rs2
-rw-r--r--src/ast/ast.cpp6
-rw-r--r--src/ast/ast.hpp73
-rw-r--r--src/ast/expr.cpp4
-rw-r--r--src/ast/expr.hpp22
-rw-r--r--src/parse/expr.cpp13
-rw-r--r--src/parse/root.cpp119
-rw-r--r--src/types.hpp11
8 files changed, 216 insertions, 34 deletions
diff --git a/samples/std.rs b/samples/std.rs
index 23f9b1b6..26039934 100644
--- a/samples/std.rs
+++ b/samples/std.rs
@@ -33,7 +33,7 @@ pub mod iter
{
type Item;
fn next(&self) -> Option<<Self as Iterator>::Item>;
- fn size_hint(&self) -> (usize, Option(usize)) {
+ fn size_hint(&self) -> (usize, Option<usize>) {
return (0, None);
}
}
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index a9336c31..f176122b 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -230,6 +230,12 @@ SERIALISE_TYPE(Function::, "AST_Function", {
//s << m_code;
})
+SERIALISE_TYPE(Trait::, "AST_Trait", {
+ s << m_params;
+ s << m_types;
+ s << m_functions;
+})
+
SERIALISE_TYPE(Enum::, "AST_Enum", {
s << m_params;
s << m_variants;
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index f04c5ab0..f5f9b2fb 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -51,6 +51,30 @@ public:
SERIALISABLE_PROTOTYPES();
};
+template <typename T>
+struct Item:
+ public Serialisable
+{
+ ::std::string name;
+ T data;
+ bool is_pub;
+
+ Item(::std::string&& name, T&& data, bool is_pub):
+ name( move(name) ),
+ data( move(data) ),
+ is_pub( is_pub )
+ {
+ }
+
+ SERIALISE_TYPE(, "Item", {
+ s << is_pub;
+ s << name;
+ s << data;
+ })
+};
+template <typename T>
+using ItemList = ::std::vector<Item<T> >;
+
typedef ::std::vector<TypeParam> TypeParams;
typedef ::std::pair< ::std::string, TypeRef> StructItem;
@@ -161,6 +185,28 @@ public:
SERIALISABLE_PROTOTYPES();
};
+class Trait:
+ public Serialisable
+{
+ ::std::vector<TypeParam> m_params;
+ ItemList<TypeRef> m_types;
+ ItemList<Function> m_functions;
+public:
+ Trait(TypeParams params):
+ m_params(params)
+ {
+ }
+
+ void add_type(::std::string name, TypeRef type) {
+ m_types.push_back( Item<TypeRef>(move(name), move(type), true) );
+ }
+ void add_function(::std::string name, Function fcn) {
+ m_functions.push_back( Item<Function>(move(name), move(fcn), true) );
+ }
+
+ SERIALISABLE_PROTOTYPES();
+};
+
class Enum:
public Serialisable
{
@@ -195,28 +241,6 @@ public:
SERIALISABLE_PROTOTYPES();
};
-template <typename T>
-struct Item:
- public Serialisable
-{
- ::std::string name;
- T data;
- bool is_pub;
-
- Item(::std::string&& name, T&& data, bool is_pub):
- name( move(name) ),
- data( move(data) ),
- is_pub( is_pub )
- {
- }
-
- SERIALISE_TYPE(, "Item", {
- s << is_pub;
- s << name;
- s << data;
- })
-};
-
class Impl:
public Serialisable
{
@@ -277,6 +301,7 @@ class Module:
itemlist_static_t m_statics;
+ ItemList<Trait> m_traits;
itemlist_enum_t m_enums;
itemlist_struct_t m_structs;
::std::vector<Impl> m_impls;
@@ -298,6 +323,9 @@ public:
void add_global(bool is_public, bool is_mut, ::std::string name, TypeRef type, Expr val) {
m_statics.push_back( Item<Static>( move(name), Static(is_mut ? Static::MUT : Static::STATIC, move(type), move(val)), is_public) );
}
+ void add_trait(bool is_public, ::std::string name, Trait trait) {
+ m_traits.push_back( Item<Trait>( move(name), move(trait), is_public) );
+ }
void add_struct(bool is_public, ::std::string name, TypeParams params, ::std::vector<StructItem> items) {
m_structs.push_back( Item<Struct>( move(name), Struct(move(params), move(items)), is_public) );
}
@@ -337,6 +365,7 @@ public:
const ::std::vector<Item<TypeAlias> >& type_aliases() const { return m_type_aliases; }
const itemlist_ext_t& extern_crates() const { return m_extern_crates; }
const itemlist_static_t& statics() const { return m_statics; }
+ const ItemList<Trait>& traits() const { return m_traits; }
const itemlist_enum_t& enums () const { return m_enums; }
const itemlist_struct_t& structs() const { return m_structs; }
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
index a5401fef..b125eea3 100644
--- a/src/ast/expr.cpp
+++ b/src/ast/expr.cpp
@@ -63,6 +63,10 @@ void ExprNode_StructLiteral::visit(NodeVisitor& nv) {
nv.visit(*this);
}
+void ExprNode_Tuple::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
void ExprNode_NamedValue::visit(NodeVisitor& nv) {
nv.visit(*this);
}
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp
index 340d0bb2..bf238c6f 100644
--- a/src/ast/expr.hpp
+++ b/src/ast/expr.hpp
@@ -202,6 +202,18 @@ struct ExprNode_StructLiteral:
virtual void visit(NodeVisitor& nv) override;
};
+// Tuple
+struct ExprNode_Tuple:
+ public ExprNode
+{
+ ::std::vector< unique_ptr<ExprNode> > m_values;
+
+ ExprNode_Tuple(::std::vector< unique_ptr<ExprNode> > vals):
+ m_values( ::std::move(vals) )
+ {}
+
+ virtual void visit(NodeVisitor& nv) override;
+};
// Variable / Constant
struct ExprNode_NamedValue:
public ExprNode
@@ -329,6 +341,10 @@ public:
for( auto& val : node.m_values )
visit(val.second);
}
+ virtual void visit(ExprNode_Tuple& node) {
+ for( auto& val : node.m_values )
+ visit(val);
+ }
virtual void visit(ExprNode_NamedValue& node) {
// LEAF
}
@@ -357,8 +373,12 @@ public:
m_node(node)
{
}
+ Expr():
+ m_node(nullptr)
+ {
+ }
- ::std::shared_ptr<ExprNode> take_node() { return ::std::move(m_node); }
+ ::std::shared_ptr<ExprNode> take_node() { assert(m_node.get()); return ::std::move(m_node); }
void visit_nodes(NodeVisitor& v);
friend ::std::ostream& operator<<(::std::ostream& os, const Expr& pat);
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index fdf35740..3899a3c3 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -491,7 +491,18 @@ ExprNodeP Parse_ExprVal(TokenStream& lex)
return NEWNODE( AST::ExprNode_NamedValue, AST::Path(AST::Path::TagLocal(), "self") );
case TOK_PAREN_OPEN: {
ExprNodeP rv = Parse_Expr0(lex);
- GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
+ if( GET_TOK(tok, lex) == TOK_COMMA ) {
+ ::std::vector<ExprNodeP> ents;
+ ents.push_back( ::std::move(rv) );
+ do {
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
+ break;
+ lex.putback(tok);
+ ents.push_back( Parse_Expr0(lex) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ rv = NEWNODE( AST::ExprNode_Tuple, ::std::move(ents) );
+ }
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
return rv; }
case TOK_MACRO:
//return NEWNODE( AST::ExprNode_Macro, tok.str(), Parse_TT(lex) );
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 10eeacaf..66b1d0fb 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -42,8 +42,12 @@ AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode
::std::string component = tok.str();
tok = lex.getToken();
- if(generic_mode == PATH_GENERIC_TYPE && tok.type() == TOK_LT)
+ if( generic_mode == PATH_GENERIC_TYPE && (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();
@@ -53,8 +57,12 @@ AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode
break;
}
tok = lex.getToken();
- if( generic_mode == PATH_GENERIC_EXPR && tok.type() == TOK_LT )
+ 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();
@@ -89,11 +97,13 @@ static const struct {
{"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)
@@ -103,6 +113,19 @@ TypeRef Parse_Type(TokenStream& lex)
Token tok = lex.getToken();
switch(tok.type())
{
+ 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() == "_" )
@@ -165,15 +188,17 @@ TypeRef Parse_Type(TokenStream& lex)
throw ParseError::BugCheck("Reached end of Parse_Type:SQUARE");
}
case TOK_PAREN_OPEN: {
+ DEBUG("Tuple");
::std::vector<TypeRef> types;
- if( (tok = lex.getToken()).type() == TOK_PAREN_CLOSE)
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
return TypeRef(TypeRef::TagTuple(), types);
+ lex.putback(tok);
do
{
TypeRef type = Parse_Type(lex);
types.push_back(type);
- } while( (tok = lex.getToken()).type() == TOK_COMMA );
- GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
return TypeRef(TypeRef::TagTuple(), types); }
case TOK_EXCLAM:
throw ParseError::Todo("noreturn type");
@@ -237,7 +262,7 @@ void Parse_TypeConds(TokenStream& lex, AST::TypeParams& params)
}
/// Parse a function definition (after the 'fn')
-AST::Function Parse_FunctionDef(TokenStream& lex)
+AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false)
{
TRACE_FUNCTION;
@@ -323,7 +348,19 @@ AST::Function Parse_FunctionDef(TokenStream& lex)
lex.putback(tok);
}
- AST::Expr code = Parse_ExprBlock(lex);
+ AST::Expr code;
+ if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
+ {
+ lex.putback(tok);
+ code = Parse_ExprBlock(lex);
+ }
+ else
+ {
+ if( !allow_no_code )
+ {
+ throw ParseError::Generic("Expected code for function");
+ }
+ }
return AST::Function(params, fcn_class, ret_type, args, code);
}
@@ -420,6 +457,67 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons
}
}
+AST::Trait Parse_TraitDef(TokenStream& lex, const ::std::vector<AST::MetaItem> meta_items)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+
+ AST::TypeParams params;
+ if( GET_TOK(tok, lex) == TOK_LT )
+ {
+ params = Parse_TypeParams(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ tok = lex.getToken();
+ }
+ // TODO: Support "for Sized?"
+ if(tok.type() == TOK_RWORD_WHERE)
+ {
+ if( params.size() == 0 )
+ throw ParseError::Generic("Where clause with no generic params");
+ Parse_TypeConds(lex, params);
+ tok = lex.getToken();
+ }
+
+
+ AST::Trait trait(params);
+
+ CHECK_TOK(tok, TOK_BRACE_OPEN);
+ while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
+ {
+ switch(tok.type())
+ {
+ case TOK_RWORD_STATIC: {
+ throw ParseError::Todo("Associated static");
+ break; }
+ case TOK_RWORD_TYPE: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string name = tok.str();
+ if( GET_TOK(tok, lex) == TOK_COLON ) {
+ throw ParseError::Todo("Type bounds on associated type");
+ }
+ if( tok.type() == TOK_RWORD_WHERE ) {
+ throw ParseError::Todo("Where clause on associated type");
+ }
+ TypeRef default_type;
+ if( tok.type() == TOK_EQUAL ) {
+ default_type = Parse_Type(lex);
+ }
+ trait.add_type( ::std::move(name), ::std::move(default_type) );
+ break; }
+ case TOK_RWORD_FN: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string name = tok.str();
+ trait.add_function( ::std::move(name), Parse_FunctionDef(lex, true) );
+ break; }
+ default:
+ throw ParseError::Generic("Unexpected token, expected 'type' or 'fn'");
+ }
+ }
+
+ return trait;
+}
+
AST::Enum Parse_EnumDef(TokenStream& lex, const ::std::vector<AST::MetaItem> meta_items)
{
TRACE_FUNCTION;
@@ -765,8 +863,11 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st
case TOK_RWORD_IMPL:
mod.add_impl(Parse_Impl(lex));
break;
- case TOK_RWORD_TRAIT:
- throw ParseError::Todo("modroot trait");
+ case TOK_RWORD_TRAIT: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string name = tok.str();
+ mod.add_trait(is_public, name, Parse_TraitDef(lex, meta_items));
+ break; }
case TOK_RWORD_MOD: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
diff --git a/src/types.hpp b/src/types.hpp
index 4ef24685..1dfeebac 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -26,6 +26,7 @@ class TypeRef:
ARRAY,
GENERIC,
PATH,
+ ASSOCIATED,
};
Class m_class;
@@ -97,6 +98,16 @@ public:
TypeRef(TagPath(), ::std::move(path))
{}
+ struct TagAssoc {};
+ TypeRef(TagAssoc, TypeRef base, TypeRef trait, ::std::string assoc_name):
+ TypeRef(::std::move(base), ::std::move(trait), ::std::move(assoc_name))
+ {}
+ TypeRef(TypeRef base, TypeRef trait, ::std::string assoc_name):
+ m_class(ASSOCIATED),
+ m_path( {AST::PathNode(assoc_name, {})} ),
+ m_inner_types( {::std::move(base), ::std::move(trait)} )
+ {}
+
bool is_path() const { return m_class == PATH; }
AST::Path& path() { assert(is_path()); return m_path; }
::std::vector<TypeRef>& sub_types() { return m_inner_types; }