summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--samples/log.rs5
-rw-r--r--src/ast/ast.cpp31
-rw-r--r--src/ast/ast.hpp3
-rw-r--r--src/ast/expr.cpp52
-rw-r--r--src/ast/expr.hpp22
-rw-r--r--src/ast/pattern.hpp2
-rw-r--r--src/dump_as_rust.cpp24
-rw-r--r--src/parse/expr.cpp95
-rw-r--r--src/parse/lex.hpp29
-rw-r--r--src/parse/parseerror.cpp5
-rw-r--r--src/parse/parseerror.hpp1
-rw-r--r--src/parse/root.cpp37
13 files changed, 255 insertions, 60 deletions
diff --git a/Makefile b/Makefile
index 6561e33e..41d68943 100644
--- a/Makefile
+++ b/Makefile
@@ -29,11 +29,14 @@ all: $(BIN)
clean:
$(RM) -r $(BIN) $(OBJ)
-test: $(BIN) samples/1.rs
+output/%.ast: samples/%.rs
+ @mkdir -p output/
+ $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt ; test $${PIPESTATUS[0]} -eq 0
+
+test: $(BIN) samples/1.rs output/std.ast output/log.ast
mkdir -p output/
- $(DBG) $(BIN) samples/std.rs --emit ast -o output/std.ast 2>&1 | tee output/ast_dbg.txt ; test $${PIPESTATUS[0]} -eq 0
# $(DBG) $(BIN) samples/1.rs --crate-path output/std.ast -o output/test.c 2>&1 | tee output/1_dbg.txt
- $(DBG) $(BIN) ../../BinaryView2/src/main.rs --crate-path output/std.ast -o output/test.c 2>&1 | tee output/1_dbg.txt ; test $${PIPESTATUS[0]} -eq 0
+ $(DBG) $(BIN) ../../BinaryView2/src/main.rs --crate-path output/ -o output/test.c 2>&1 | tee output/1_dbg.txt ; test $${PIPESTATUS[0]} -eq 0
$(BIN): $(OBJ)
@mkdir -p $(dir $@)
diff --git a/samples/log.rs b/samples/log.rs
new file mode 100644
index 00000000..eb9f544e
--- /dev/null
+++ b/samples/log.rs
@@ -0,0 +1,5 @@
+
+macro_rules! error{
+ ($( $v:tt )*) => {};
+}
+
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index e6187001..8a903cca 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -48,8 +48,10 @@ SERIALISE_TYPE(MetaItem::, "AST_MetaItem", {
case Pattern::MAYBE_BIND:
os << "Pattern(TagMaybeBind, '" << pat.m_binding << "')";
break;
+ case Pattern::REF:
+ os << "Pattern(TagReference, '" << pat.m_binding << "' @ " << pat.m_sub_patterns[0] << ")";
+ break;
case Pattern::VALUE:
- //os << "Pattern(TagValue, " << *pat.m_node << ")";
os << "Pattern(TagValue, '" << pat.m_binding << "' @ TODO:ExprNode)";
break;
case Pattern::TUPLE:
@@ -64,18 +66,28 @@ SERIALISE_TYPE(MetaItem::, "AST_MetaItem", {
void operator%(Serialiser& s, Pattern::BindType c) {
switch(c)
{
- case Pattern::ANY: s << "ANY"; return;
- case Pattern::MAYBE_BIND: s << "MAYBE_BIND"; return;
- case Pattern::VALUE: s << "VALUE"; return;
- case Pattern::TUPLE: s << "TUPLE"; return;
- case Pattern::TUPLE_STRUCT: s << "TUPLE_STRUCT"; return;
+ #define _(v) case Pattern::v: s << #v; return;
+ _(ANY)
+ _(MAYBE_BIND)
+ _(REF)
+ _(VALUE)
+ _(TUPLE)
+ _(TUPLE_STRUCT)
+ #undef _
}
}
void operator%(::Deserialiser& s, Pattern::BindType& c) {
::std::string n;
s.item(n);
- if(n == "ANY") c = Pattern::ANY;
- else if(n == "MAYBE_BIND") c = Pattern::MAYBE_BIND;
+ if(1) ;
+ #define _(v) else if(n == #v) c = Pattern::v;
+ _(ANY)
+ _(MAYBE_BIND)
+ _(REF)
+ _(VALUE)
+ _(TUPLE)
+ _(TUPLE_STRUCT)
+ #undef _
else
throw ::std::runtime_error("");
}
@@ -89,6 +101,8 @@ SERIALISE_TYPE_S(Pattern, {
Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
{
DEBUG("types={" << types << "}");
+ throw ParseError::Todo("Impl::make_concrete");
+/*
INDENT();
assert(m_params.n_params());
@@ -120,6 +134,7 @@ Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
UNINDENT();
return ret;
+*/
}
::rust::option<Impl&> Impl::matches(const TypeRef& trait, const TypeRef& type)
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 775ed943..c1c9c283 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -268,6 +268,7 @@ public:
private:
Class m_fcn_class;
+ ::std::string m_lifetime;
TypeParams m_params;
Expr m_code;
TypeRef m_rettype;
@@ -285,6 +286,8 @@ public:
{
}
+ void set_self_lifetime(::std::string s) { m_lifetime = s; }
+
const Class fcn_class() const { return m_fcn_class; }
TypeParams& params() { return m_params; }
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
index 3e20655d..9ddd75a9 100644
--- a/src/ast/expr.cpp
+++ b/src/ast/expr.cpp
@@ -60,6 +60,7 @@ SERIALISE_TYPE(Expr::, "Expr", {
else _(ExprNode_CallObject)
else _(ExprNode_Match)
else _(ExprNode_If)
+ else _(ExprNode_IfLet)
else _(ExprNode_Integer)
else _(ExprNode_StructLiteral)
else _(ExprNode_Tuple)
@@ -178,6 +179,14 @@ NODE(ExprNode_If, {
},{
os << "if " << *m_cond << " { " << *m_true << " } else { " << *m_false << " }";
})
+NODE(ExprNode_IfLet, {
+ s.item(m_pattern);
+ s.item(m_value);
+ s.item(m_true);
+ s.item(m_false);
+},{
+ os << "if let " << m_pattern << " = (" << *m_value << ") { " << *m_true << " } else { " << *m_false << " }";
+})
NODE(ExprNode_Integer, {
s % m_datatype;
@@ -247,6 +256,10 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) {
#define _(v) case ExprNode_BinOp::v: s << #v; return
_(CMPEQU);
_(CMPNEQU);
+ _(CMPLT);
+ _(CMPLTE);
+ _(CMPGT);
+ _(CMPGTE);
_(BOOLAND);
_(BOOLOR);
_(BITAND);
@@ -257,18 +270,37 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) {
_(MULTIPLY);
_(DIVIDE);
_(MODULO);
+ _(ADD);
+ _(SUB);
#undef _
}
}
void operator%(::Deserialiser& s, ExprNode_BinOp::Type& t) {
::std::string n;
s.item(n);
- #define _(v) if(n == #v) t = ExprNode_BinOp::v
- _(CMPEQU);
- else _(CMPNEQU);
+ if(0) ;
+ #define _(v) else if(n == #v) t = ExprNode_BinOp::v
+ _(CMPEQU);
+ _(CMPNEQU);
+ _(CMPLT);
+ _(CMPLTE);
+ _(CMPGT);
+ _(CMPGTE);
+ _(BOOLAND);
+ _(BOOLOR);
+ _(BITAND);
+ _(BITOR);
+ _(BITXOR);
+ _(SHL);
+ _(SHR);
+ _(MULTIPLY);
+ _(DIVIDE);
+ _(MODULO);
+ _(ADD);
+ _(SUB);
+ #undef _
else
throw ::std::runtime_error("");
- #undef _
}
NODE(ExprNode_BinOp, {
s % m_type;
@@ -280,6 +312,10 @@ NODE(ExprNode_BinOp, {
{
case CMPEQU: os << "=="; break;
case CMPNEQU: os << "!="; break;
+ case CMPLT: os << "<"; break;
+ case CMPLTE: os << "<="; break;
+ case CMPGT: os << ">"; break;
+ case CMPGTE: os << ">="; break;
case BOOLAND: os << "&&"; break;
case BOOLOR: os << "||"; break;
case BITAND: os << "&"; break;
@@ -402,6 +438,14 @@ NV(ExprNode_If,
visit(node.m_false);
UNINDENT();
})
+NV(ExprNode_IfLet,
+{
+ INDENT();
+ visit(node.m_value);
+ visit(node.m_true);
+ visit(node.m_false);
+ UNINDENT();
+})
NV(ExprNode_Integer, {})
NV(ExprNode_Float, {})
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp
index 28526377..55da44d6 100644
--- a/src/ast/expr.hpp
+++ b/src/ast/expr.hpp
@@ -202,6 +202,24 @@ struct ExprNode_If:
}
NODE_METHODS();
};
+struct ExprNode_IfLet:
+ public ExprNode
+{
+ AST::Pattern m_pattern;
+ unique_ptr<ExprNode> m_value;
+ unique_ptr<ExprNode> m_true;
+ unique_ptr<ExprNode> m_false;
+
+ ExprNode_IfLet() {}
+ ExprNode_IfLet(AST::Pattern pattern, unique_ptr<ExprNode>&& cond, unique_ptr<ExprNode>&& true_code, unique_ptr<ExprNode>&& false_code):
+ m_pattern( ::std::move(pattern) ),
+ m_value( ::std::move(cond) ),
+ m_true( ::std::move(true_code) ),
+ m_false( ::std::move(false_code) )
+ {
+ }
+ NODE_METHODS();
+};
// Literal integer
struct ExprNode_Integer:
public ExprNode
@@ -363,6 +381,8 @@ struct ExprNode_BinOp:
MULTIPLY,
DIVIDE,
MODULO,
+ ADD,
+ SUB,
};
Type m_type;
@@ -425,6 +445,7 @@ public:
NT(ExprNode_CallObject);
NT(ExprNode_Match);
NT(ExprNode_If);
+ NT(ExprNode_IfLet);
NT(ExprNode_Integer);
NT(ExprNode_Float);
@@ -461,6 +482,7 @@ public:
NT(ExprNode_CallObject);
NT(ExprNode_Match);
NT(ExprNode_If);
+ NT(ExprNode_IfLet);
NT(ExprNode_Integer);
NT(ExprNode_Float);
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
index 78b224d0..5b03a8a2 100644
--- a/src/ast/pattern.hpp
+++ b/src/ast/pattern.hpp
@@ -32,7 +32,7 @@ private:
unique_ptr<ExprNode> m_node;
::std::vector<Pattern> m_sub_patterns;
public:
- Pattern(Pattern&& o):
+ Pattern(Pattern&& o) noexcept:
m_class(o.m_class),
m_binding( move(o.m_binding) ),
m_path( move(o.m_path) ),
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp
index e5d225bd..c9a64371 100644
--- a/src/dump_as_rust.cpp
+++ b/src/dump_as_rust.cpp
@@ -155,6 +155,21 @@ public:
m_expr_root = false;
m_os << "if ";
AST::NodeVisitor::visit(n.m_cond);
+
+ visit_if_common(expr_root, n.m_true, n.m_false);
+ }
+ virtual void visit(AST::ExprNode_IfLet& n) override {
+ bool expr_root = m_expr_root;
+ m_expr_root = false;
+ m_os << "if let ";
+ print_pattern(n.m_pattern);
+ m_os << " = ";
+ AST::NodeVisitor::visit(n.m_value);
+
+ visit_if_common(expr_root, n.m_true, n.m_false);
+ }
+ void visit_if_common(bool expr_root, const ::std::unique_ptr<AST::ExprNode>& tv, const ::std::unique_ptr<AST::ExprNode>& fv)
+ {
if( expr_root )
{
m_os << "\n";
@@ -164,15 +179,16 @@ public:
{
m_os << " ";
}
- AST::NodeVisitor::visit(n.m_true);
- if(n.m_false.get())
+
+ AST::NodeVisitor::visit(tv);
+ if(fv.get())
{
if( expr_root )
{
m_os << "\n";
m_os << indent() << "else";
// handle chained if statements nicely
- if( IS(*n.m_false, AST::ExprNode_If) ) {
+ if( IS(*fv, AST::ExprNode_If) || IS(*fv, AST::ExprNode_IfLet) ) {
m_expr_root = true;
m_os << " ";
}
@@ -183,7 +199,7 @@ public:
{
m_os << " else ";
}
- AST::NodeVisitor::visit(n.m_false);
+ AST::NodeVisitor::visit(fv);
}
}
virtual void visit(AST::ExprNode_Integer& n) override {
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index 2ae94794..7fb41b0f 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -16,6 +16,7 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex);
ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon);
ExprNodeP Parse_Expr0(TokenStream& lex);
ExprNodeP Parse_ExprBlocks(TokenStream& lex);
+ExprNodeP Parse_IfStmt(TokenStream& lex);
ExprNodeP Parse_Expr1(TokenStream& lex);
AST::Expr Parse_Expr(TokenStream& lex, bool const_only)
@@ -175,7 +176,9 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path)
Token tok;
::std::vector<AST::Pattern> child_pats;
do {
- child_pats.push_back( Parse_Pattern(lex) );
+ AST::Pattern pat = Parse_Pattern(lex);
+ DEBUG("pat = " << pat);
+ child_pats.push_back( ::std::move(pat) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_PAREN_CLOSE);
return child_pats;
@@ -251,6 +254,9 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon)
throw ParseError::Todo("for");
case TOK_RWORD_WHILE:
throw ParseError::Todo("while");
+ case TOK_RWORD_IF:
+ opt_semicolon = true;
+ return Parse_IfStmt(lex);
default:
lex.putback(tok);
return Parse_Expr0(lex);
@@ -299,11 +305,17 @@ ExprNodeP Parse_Expr0(TokenStream& lex)
ExprNodeP Parse_IfStmt(TokenStream& lex)
{
TRACE_FUNCTION;
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
Token tok;
ExprNodeP cond;
+ AST::Pattern pat;
+ bool if_let = false;
if( GET_TOK(tok, lex) == TOK_RWORD_LET ) {
- throw ParseError::Todo("if let");
+ if_let = true;
+ pat = Parse_Pattern(lex);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ cond = Parse_Expr0(lex);
}
else {
lex.putback(tok);
@@ -332,7 +344,10 @@ ExprNodeP Parse_IfStmt(TokenStream& lex)
lex.putback(tok);
}
- return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) );
+ if( if_let )
+ return NEWNODE( AST::ExprNode_IfLet, ::std::move(pat), ::std::move(cond), ::std::move(code), ::std::move(altcode) );
+ else
+ return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) );
}
ExprNodeP Parse_Expr_Match(TokenStream& lex)
@@ -479,9 +494,11 @@ LEFTASSOC(Parse_Expr8, Parse_Expr9,
// 9: Add / Subtract
LEFTASSOC(Parse_Expr9, Parse_Expr10,
case TOK_PLUS:
- throw ParseError::Todo("expr - add");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::ADD, ::std::move(rv), next(lex));
+ break;
case TOK_DASH:
- throw ParseError::Todo("expr - sub");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SUB, ::std::move(rv), next(lex));
+ break;
)
// 10: Cast
LEFTASSOC(Parse_Expr10, Parse_Expr11,
@@ -563,6 +580,37 @@ ExprNodeP Parse_ExprFC(TokenStream& lex)
}
}
+ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ // Braced structure literal
+ // - A series of 0 or more pairs of <ident>: <expr>,
+ // - '..' <expr>
+ ::std::vector< ::std::pair< ::std::string, ::std::unique_ptr<AST::ExprNode>> > items;
+ while( GET_TOK(tok, lex) == TOK_IDENT )
+ {
+ ::std::string name = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ ExprNodeP val = Parse_Expr0(lex);
+ items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
+ if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
+ break;
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ ExprNodeP base_val;
+ if( tok.type() == TOK_DOUBLE_DOT )
+ {
+ // default
+ base_val = Parse_Expr0(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+ return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) );
+}
+
ExprNodeP Parse_ExprVal(TokenStream& lex)
{
TRACE_FUNCTION;
@@ -580,37 +628,13 @@ ExprNodeP Parse_ExprVal(TokenStream& lex)
path = Parse_Path(lex, true, PATH_GENERIC_EXPR);
switch( GET_TOK(tok, lex) )
{
- case TOK_BRACE_OPEN: {
- // Braced structure literal
- // - A series of 0 or more pairs of <ident>: <expr>,
- // - '..' <expr>
- ::std::vector< ::std::pair< ::std::string, ::std::unique_ptr<AST::ExprNode>> > items;
- while( GET_TOK(tok, lex) == TOK_IDENT )
- {
- ::std::string name = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- ExprNodeP val = Parse_Expr0(lex);
- items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
- if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
- break;
- CHECK_TOK(tok, TOK_COMMA);
- }
- ExprNodeP base_val;
- if( tok.type() == TOK_DOUBLE_DOT )
- {
- // default
- base_val = Parse_Expr0(lex);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
- return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) );
- }
- case TOK_PAREN_OPEN: {
- lex.putback(tok);
+ case TOK_PAREN_OPEN:
// Function call
- ::std::vector<ExprNodeP> args = Parse_ParenList(lex);
- return NEWNODE( AST::ExprNode_CallPath, ::std::move(path), ::std::move(args) );
- }
+ lex.putback(tok);
+ return NEWNODE( AST::ExprNode_CallPath, ::std::move(path), Parse_ParenList(lex) );
+ case TOK_BRACE_OPEN:
+ if( !CHECK_PARSE_FLAG(lex, disallow_struct_literal) )
+ return Parse_ExprVal_StructLiteral(lex, ::std::move(path));
default:
// Value
lex.putback(tok);
@@ -634,6 +658,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex)
}
else
{
+ CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
lex.putback(tok);
ExprNodeP rv = Parse_Expr0(lex);
diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp
index d28b0afd..41bac795 100644
--- a/src/parse/lex.hpp
+++ b/src/parse/lex.hpp
@@ -56,20 +56,49 @@ struct Position
};
extern ::std::ostream& operator<<(::std::ostream& os, const Position& p);
+/// State the parser needs to pass down via a second channel.
+struct ParseState
+{
+ bool disallow_struct_literal = false;
+};
+
class TokenStream
{
bool m_cache_valid;
Token m_cache;
+ ParseState m_parse_state;
public:
TokenStream();
virtual ~TokenStream();
Token getToken();
void putback(Token tok);
virtual Position getPosition() const = 0;
+
+ ParseState& parse_state() { return m_parse_state; }
+
protected:
virtual Token realGetToken() = 0;
};
+class SavedParseState
+{
+ TokenStream& m_lex;
+ ParseState m_state;
+public:
+ SavedParseState(TokenStream& lex, ParseState state):
+ m_lex(lex),
+ m_state(state)
+ {}
+ ~SavedParseState()
+ {
+ m_lex.parse_state() = m_state;
+ }
+};
+
+#define SET_PARSE_FLAG(lex, flag) SavedParseState(lex, lex.parse_state()); lex.parse_state().flag = true
+#define CLEAR_PARSE_FLAG(lex, flag) SavedParseState(lex, lex.parse_state()); lex.parse_state().flag = false
+#define CHECK_PARSE_FLAG(lex, flag) (lex.parse_state().flag == true)
+
class Lexer
{
::std::ifstream m_istream;
diff --git a/src/parse/parseerror.cpp b/src/parse/parseerror.cpp
index ed7a845c..b0674c07 100644
--- a/src/parse/parseerror.cpp
+++ b/src/parse/parseerror.cpp
@@ -24,6 +24,11 @@ ParseError::Todo::Todo(::std::string message):
{
::std::cout << "Todo(" << message << ")" << ::std::endl;
}
+ParseError::Todo::Todo(const TokenStream& lex, ::std::string message):
+ m_message(message)
+{
+ ::std::cout << lex.getPosition() << ": Todo(" << message << ")" << ::std::endl;
+}
ParseError::Todo::~Todo() throw()
{
}
diff --git a/src/parse/parseerror.hpp b/src/parse/parseerror.hpp
index 33c02a92..5868f629 100644
--- a/src/parse/parseerror.hpp
+++ b/src/parse/parseerror.hpp
@@ -37,6 +37,7 @@ class Todo:
::std::string m_message;
public:
Todo(::std::string message);
+ Todo(const TokenStream& lex, ::std::string message);
virtual ~Todo() throw ();
};
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index f5f48132..e3d0ac0a 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -12,12 +12,23 @@ extern AST::Pattern Parse_Pattern(TokenStream& lex);
::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex)
{
TRACE_FUNCTION;
+ Token tok;
::std::vector<TypeRef> types;
- Token tok;
+ ::std::vector< ::std::string> lifetimes;
do {
- types.push_back( Parse_Type(lex) );
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_LIFETIME:
+ lifetimes.push_back( tok.str() );
+ 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));
@@ -25,6 +36,8 @@ extern AST::Pattern Parse_Pattern(TokenStream& lex);
else {
CHECK_TOK(tok, TOK_GT);
}
+
+
return types;
}
@@ -293,14 +306,18 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false)
}
AST::Function::Class fcn_class = AST::Function::CLASS_UNBOUND;
+ AST::Function::Arglist args;
+
GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
GET_TOK(tok, lex);
if( tok.type() == TOK_AMP )
{
// By-reference method
+ ::std::string lifetime;
if( GET_TOK(tok, lex) == TOK_LIFETIME )
{
- throw ParseError::Todo("Lifetimes on self in methods");
+ lifetime = tok.str();
+ GET_TOK(tok, lex);
}
if( tok.type() == TOK_RWORD_MUT )
{
@@ -312,6 +329,8 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false)
CHECK_TOK(tok, TOK_RWORD_SELF);
fcn_class = AST::Function::CLASS_REFMETHOD;
}
+ DEBUG("TODO: UFCS / self lifetimes");
+ //args.push_back( ::std::make_pair( AST::Pattern(), TypeRef(TypeRef::TagReference(), lifetime, (fcn_class == AST::Function::CLASS_MUTMETHOD), ) ) );
GET_TOK(tok, lex);
}
else if( tok.type() == TOK_RWORD_SELF )
@@ -325,10 +344,17 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false)
// Unbound method
}
- AST::Function::Arglist args;
if( tok.type() != TOK_PAREN_CLOSE )
{
- lex.putback(tok);
+ // Comma after self
+ if( fcn_class != AST::Function::CLASS_UNBOUND )
+ {
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ else {
+ lex.putback(tok);
+ }
+
// Argument list
do {
AST::Pattern pat = Parse_Pattern(lex);
@@ -992,6 +1018,7 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, LList<AST:
{
throw ParseError::Unexpected(lex, tok);
}
+ crate.load_extern_crate(path);
mod.add_ext_crate(path, name);
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break; }