summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge (bugs) <tpg@mutabah.net>2014-12-07 09:46:00 +0800
committerJohn Hodge (bugs) <tpg@mutabah.net>2014-12-07 09:46:00 +0800
commitc325b671c1a44c90c8ce570b901219bcc2ae0a38 (patch)
tree5dff25da15192ad0b0635fa96bab5f510df018c6
parent1ac5429531c195755c7e1690912291e20e9a1717 (diff)
downloadmrust-c325b671c1a44c90c8ce570b901219bcc2ae0a38.tar.gz
Macro evaluation hacked in (... not quite in yet, but framework is there)
Macro definitions not implemented, evil hack to define try! is present
-rw-r--r--ast/ast.cpp8
-rw-r--r--ast/ast.hpp17
-rw-r--r--macros.cpp105
-rw-r--r--macros.hpp69
-rw-r--r--parse/expr.cpp162
-rw-r--r--parse/lex.cpp50
-rw-r--r--parse/lex.hpp42
-rw-r--r--parse/parseerror.cpp12
-rw-r--r--parse/parseerror.hpp18
-rw-r--r--parse/preproc.cpp20
-rw-r--r--parse/preproc.hpp6
-rw-r--r--parse/root.cpp41
-rw-r--r--parse/tokentree.hpp10
13 files changed, 516 insertions, 44 deletions
diff --git a/ast/ast.cpp b/ast/ast.cpp
index 1683bf91..a6eaa039 100644
--- a/ast/ast.cpp
+++ b/ast/ast.cpp
@@ -39,7 +39,7 @@ Pattern::Pattern(TagEnumVariant, Path path, ::std::vector<Pattern> sub_patterns)
}
-Function::Function(::std::string name, TypeParams params, TypeRef ret_type, ::std::vector<StructItem> args, Expr code)
+Function::Function(::std::string name, TypeParams params, Class fcn_class, TypeRef ret_type, ::std::vector<StructItem> args, Expr code)
{
}
@@ -76,9 +76,15 @@ ExprNode::ExprNode()
ExprNode::ExprNode(TagBlock, ::std::vector<ExprNode> nodes)
{
}
+ExprNode::ExprNode(TagLetBinding, Pattern pat, ExprNode value)
+{
+}
ExprNode::ExprNode(TagInteger, uint64_t value, enum eCoreType datatype)
{
}
+ExprNode::ExprNode(TagStructLiteral, Path path, ExprNode base_value, ::std::vector< ::std::pair< ::std::string,ExprNode> > values )
+{
+}
ExprNode::ExprNode(TagCallPath, Path path, ::std::vector<ExprNode> args)
{
}
diff --git a/ast/ast.hpp b/ast/ast.hpp
index ab5f73f5..2c8b06c0 100644
--- a/ast/ast.hpp
+++ b/ast/ast.hpp
@@ -69,12 +69,18 @@ public:
struct TagBlock {};
ExprNode(TagBlock, ::std::vector<ExprNode> nodes);
+ struct TagLetBinding {};
+ ExprNode(TagLetBinding, Pattern pat, ExprNode value);
+
struct TagAssign {};
ExprNode(TagAssign, ExprNode slot, ExprNode value) {}
struct TagInteger {};
ExprNode(TagInteger, uint64_t value, enum eCoreType datatype);
+ struct TagStructLiteral {};
+ ExprNode(TagStructLiteral, Path path, ExprNode base_value, ::std::vector< ::std::pair< ::std::string,ExprNode> > values );
+
struct TagCallPath {};
ExprNode(TagCallPath, Path path, ::std::vector<ExprNode> args);
@@ -95,7 +101,16 @@ public:
class Function
{
public:
- Function(::std::string name, TypeParams params, TypeRef ret_type, ::std::vector<StructItem> args, Expr code);
+
+ enum Class
+ {
+ CLASS_UNBOUND,
+ CLASS_REFMETHOD,
+ CLASS_MUTMETHOD,
+ CLASS_VALMETHOD,
+ };
+
+ Function(::std::string name, TypeParams params, Class fcn_class, TypeRef ret_type, ::std::vector<StructItem> args, Expr code);
};
class Impl
diff --git a/macros.cpp b/macros.cpp
new file mode 100644
index 00000000..3561a911
--- /dev/null
+++ b/macros.cpp
@@ -0,0 +1,105 @@
+/*
+ */
+#include "macros.hpp"
+#include "parse/parseerror.hpp"
+#include "parse/tokentree.hpp"
+
+#define FOREACH(basetype, it, src) for(basetype::const_iterator it = src.begin(); it != src.end(); ++ it)
+
+typedef ::std::map< ::std::string, MacroRules> t_macro_regs;
+
+t_macro_regs g_macro_registrations;
+
+void Macro_InitDefaults()
+{
+ // try!() macro
+ {
+ MacroRule rule;
+ rule.m_pattern.push_back( MacroPatEnt("val", MacroPatEnt::PAT_EXPR) );
+ // match $rule {
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_RWORD_MATCH)) );
+ rule.m_contents.push_back( MacroRuleEnt("val") );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_BRACE_OPEN)) );
+ // Ok(v) => v,
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_IDENT, "Ok")) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_OPEN)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_IDENT, "v")) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_CLOSE)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_FATARROW)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_IDENT, "v")) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_COMMA)) );
+ // Err(e) => return Err(r),
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_IDENT, "Err")) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_OPEN)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_IDENT, "e")) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_CLOSE)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_FATARROW)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_RWORD_RETURN)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_IDENT, "Err")) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_OPEN)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_IDENT, "e")) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_CLOSE)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_COMMA)) );
+ // }
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_BRACE_CLOSE)) );
+ MacroRules rules;
+ rules.push_back(rule);
+ g_macro_registrations.insert( make_pair(::std::string("try"), rules));
+ }
+}
+
+MacroExpander Macro_Invoke(const char* name, TokenTree input)
+{
+ // XXX: EVIL HACK! - This should be removed when std loading is implemented
+ if( g_macro_registrations.size() == 0 ) {
+ Macro_InitDefaults();
+ }
+ // 1. Locate macro with that name
+ t_macro_regs::iterator macro_reg = g_macro_registrations.find(name);
+ if( macro_reg != g_macro_registrations.end() )
+ {
+ const MacroRules& rules = macro_reg->second;
+ // 2. Check input token tree against possible variants
+ // 3. Bind names
+ // 4. Return expander
+ FOREACH(MacroRules, rule_it, rules)
+ {
+ // Create token stream for input tree
+ TTStream lex(input);
+ ::std::map<const char*,TokenTree> bound_tts;
+ // Parse according to rules
+ bool fail = false;
+ FOREACH(::std::vector<MacroPatEnt>, pat_it, rule_it->m_pattern)
+ {
+ const MacroPatEnt& pat = *pat_it;
+ switch(pat.type)
+ {
+ case MacroPatEnt::PAT_TOKEN:
+ if( lex.getToken().type() != pat.tok.type() ) {
+ fail = true;
+ break;
+ }
+ break;
+ case MacroPatEnt::PAT_EXPR:
+ bound_tts.insert( std::make_pair(pat.name.c_str(), Parse_TT_Expr(lex)) );
+ break;
+ default:
+ throw ParseError::Todo("macro pattern matching");
+ }
+ if( fail )
+ break;
+ }
+ if( !fail ) {
+ throw ParseError::Todo("Macro expansions");
+ }
+ }
+ throw ParseError::Todo("Error when macro fails to match");
+ }
+
+ throw ParseError::Generic( ::std::string("Macro '") + name + "' was not found" );
+}
+
+Token MacroExpander::realGetToken()
+{
+ throw ParseError::Todo("MacroExpander");
+}
diff --git a/macros.hpp b/macros.hpp
new file mode 100644
index 00000000..5c86e22c
--- /dev/null
+++ b/macros.hpp
@@ -0,0 +1,69 @@
+#ifndef MACROS_HPP_INCLUDED
+#define MACROS_HPP_INCLUDED
+
+#include "parse/lex.hpp"
+#include <map>
+
+class MacroRuleEnt
+{
+ Token tok;
+ ::std::string name;
+public:
+ MacroRuleEnt(Token tok):
+ tok(tok),
+ name("")
+ {
+ }
+ MacroRuleEnt(::std::string name):
+ name(name)
+ {
+ }
+};
+struct MacroPatEnt
+{
+ Token tok;
+ ::std::string name;
+ enum Type {
+ PAT_TOKEN,
+ PAT_TT,
+ PAT_IDENT,
+ PAT_PATH,
+ PAT_EXPR,
+ PAT_STMT,
+ PAT_BLOCK,
+ } type;
+
+ MacroPatEnt(::std::string name, Type type):
+ tok(),
+ name(name),
+ type(type)
+ {
+ }
+};
+
+/// A rule within a macro_rules! blcok
+class MacroRule
+{
+ struct MacroRuleState
+ {
+ ::std::map< ::std::string, TokenTree> m_mappings;
+ size_t ofs;
+ };
+public:
+ ::std::vector<MacroPatEnt> m_pattern;
+ ::std::vector<MacroRuleEnt> m_contents;
+};
+
+/// A sigle 'macro_rules!' block
+typedef ::std::vector<MacroRule> MacroRules;
+
+class MacroExpander:
+ public TokenStream
+{
+public:
+ virtual Token realGetToken();
+};
+
+extern MacroExpander Macro_Invoke(const char* name, TokenTree input);
+
+#endif // MACROS_HPP_INCLUDED
diff --git a/parse/expr.cpp b/parse/expr.cpp
index 90a39b04..cb3b80e7 100644
--- a/parse/expr.cpp
+++ b/parse/expr.cpp
@@ -4,7 +4,9 @@
#include "parseerror.hpp"
#include "../ast/ast.hpp"
#include "common.hpp"
+#include "../macros.hpp"
#include <iostream>
+#include "tokentree.hpp"
using AST::ExprNode;
@@ -82,6 +84,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex)
default:
throw ParseError::Unexpected(tok);
}
+ throw ParseError::BugCheck("Parse_TT_Stmt should early return");
}
ExprNode Parse_ExprBlockNode(TokenStream& lex)
@@ -102,12 +105,15 @@ ExprNode Parse_ExprBlockNode(TokenStream& lex)
nodes.push_back(Parse_ExprBlockNode(lex));
trailing_value = true;
break;
- case TOK_RWORD_LET:
+ case TOK_RWORD_LET: {
//ret.append();
- throw ParseError::Todo("block let");
+ AST::Pattern pat = Parse_Pattern(lex);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ AST::ExprNode val = Parse_Expr1(lex);
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
trailing_value = false;
- break;
+ nodes.push_back( ExprNode(ExprNode::TagLetBinding(), pat, val));
+ break; }
case TOK_RWORD_LOOP:
throw ParseError::Todo("loop");
break;
@@ -360,10 +366,31 @@ AST::ExprNode Parse_ExprVal(TokenStream& lex)
path = Parse_Path(lex, true, PATH_GENERIC_EXPR);
switch( GET_TOK(tok, lex) )
{
- case TOK_BRACE_OPEN:
- // Structure literal
- throw ParseError::Todo("Structure literal");
- break;
+ case TOK_BRACE_OPEN: {
+ // Braced structure literal
+ // - A series of 0 or more pairs of <ident>: <expr>,
+ // - '..' <expr>
+ ::std::vector< ::std::pair< ::std::string, AST::ExprNode> > items;
+ while( GET_TOK(tok, lex) == TOK_IDENT )
+ {
+ ::std::string name = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ AST::ExprNode val = Parse_Expr0(lex);
+ items.push_back( ::std::make_pair(name, val) );
+ if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
+ break;
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ AST::ExprNode 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 ExprNode(ExprNode::TagStructLiteral(), path, base_val, items);
+ }
case TOK_PAREN_OPEN: {
lex.putback(tok);
// Function call
@@ -379,7 +406,128 @@ AST::ExprNode Parse_ExprVal(TokenStream& lex)
return ExprNode(ExprNode::TagInteger(), tok.intval(), tok.datatype());
case TOK_FLOAT:
throw ParseError::Todo("Float");
+ case TOK_MACRO: {
+ // Need to create a token tree, pass to the macro, then pass the result of that to Parse_Expr0
+ MacroExpander expanded_macro = Macro_Invoke(tok.str().c_str(), Parse_TT(lex));
+
+ return Parse_Expr0(expanded_macro);
+ }
default:
throw ParseError::Unexpected(tok);
}
}
+
+// Token Tree Parsing
+TokenTree Parse_TT(TokenStream& lex)
+{
+ Token tok = lex.getToken();
+ eTokenType closer = TOK_PAREN_CLOSE;
+ switch(tok.type())
+ {
+ case TOK_PAREN_OPEN:
+ closer = TOK_PAREN_CLOSE;
+ break;
+ case TOK_SQUARE_OPEN:
+ closer = TOK_SQUARE_CLOSE;
+ break;
+ case TOK_BRACE_OPEN:
+ closer = TOK_BRACE_CLOSE;
+ break;
+ default:
+ return TokenTree(tok);
+ }
+
+ ::std::vector<TokenTree> items;
+ items.push_back(tok);
+ while(GET_TOK(tok, lex) != closer && tok.type() != TOK_EOF)
+ {
+ lex.putback(tok);
+ items.push_back(Parse_TT(lex));
+ }
+ items.push_back(tok);
+ return TokenTree(items);
+}
+
+TokenTree Parse_TT_Path(TokenStream& lex)
+{
+ throw ParseError::Todo("TokenTree path");
+}
+TokenTree Parse_TT_Val(TokenStream& lex)
+{
+ Token tok;
+ ::std::vector<TokenTree> ret;
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_PAREN_OPEN:
+ lex.putback(tok);
+ return Parse_TT(lex);
+
+ case TOK_IDENT:
+ case TOK_DOUBLE_COLON: {
+ lex.putback(tok);
+ TokenTree inner = Parse_TT_Path(lex);
+ if(GET_TOK(tok, lex) == TOK_BRACE_OPEN) {
+ lex.putback(tok);
+ ret.push_back(inner);
+ ret.push_back(Parse_TT(lex));
+ }
+ else {
+ lex.putback(tok);
+ return inner;
+ }
+ break; }
+ case TOK_RWORD_MATCH:
+ ret.push_back(TokenTree(tok));
+ ret.push_back(Parse_TT(lex));
+ break;
+ case TOK_RWORD_IF:
+ ret.push_back(TokenTree(tok));
+ ret.push_back(Parse_TT(lex));
+ if( GET_TOK(tok, lex) == TOK_RWORD_ELSE ) {
+ ret.push_back(TokenTree(tok));
+ ret.push_back(Parse_TT(lex));
+ }
+ else {
+ lex.putback(tok);
+ }
+ break;
+ default:
+ // Oh, fail :(
+ break;
+ }
+ return TokenTree(ret);
+}
+TokenTree Parse_TT_Expr(TokenStream& lex)
+{
+ Token tok;
+ ::std::vector<TokenTree> ret;
+
+ ret.push_back(Parse_TT_Val(lex));
+ // 1. Get left associative blocks until nothing matches
+ bool cont = true;
+ while(cont)
+ {
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_PLUS:
+ case TOK_DASH:
+ ret.push_back(tok);
+ ret.push_back(Parse_TT_Val(lex));
+ break;
+ default:
+ lex.putback(tok);
+ cont = false;
+ break;
+ }
+ }
+ return TokenTree(ret);
+
+}
+TokenTree Parse_TT_Stmt(TokenStream& lex)
+{
+ throw ParseError::Todo("Parse_TT_Stmt");
+}
+TokenTree Parse_TT_Block(TokenStream& lex)
+{
+ throw ParseError::Todo("Parse_TT_Block");
+}
diff --git a/parse/lex.cpp b/parse/lex.cpp
index 99568a11..99d787fb 100644
--- a/parse/lex.cpp
+++ b/parse/lex.cpp
@@ -133,9 +133,9 @@ static const struct {
TOKENT("pure", TOK_RWORD_PURE),
TOKENT("ref", TOK_RWORD_REF),
TOKENT("return", TOK_RWORD_RETURN),
+ TOKENT("self", TOK_RWORD_SELF),
TOKENT("sizeof", TOK_RWORD_SIZEOF),
TOKENT("static", TOK_RWORD_STATIC),
- TOKENT("self", TOK_RWORD_SELF),
TOKENT("struct", TOK_RWORD_STRUCT),
TOKENT("super", TOK_RWORD_SUPER),
TOKENT("true", TOK_RWORD_TRUE),
@@ -416,7 +416,6 @@ const char* Token::typestr(enum eTokenType type)
case TOK_INTEGER: return "TOK_INTEGER";
case TOK_CHAR: return "TOK_CHAR";
case TOK_FLOAT: return "TOK_FLOAT";
- case TOK_UNDERSCORE: return "TOK_UNDERSCORE";
case TOK_CATTR_OPEN: return "TOK_CATTR_OPEN";
case TOK_ATTR_OPEN: return "TOK_ATTR_OPEN";
@@ -542,3 +541,50 @@ const char* Token::typestr(enum eTokenType type)
return os;
}
+TokenTree::TokenTree(Token tok)
+{
+
+}
+TokenTree::TokenTree(::std::vector<TokenTree> subtrees)
+{
+
+}
+
+TTStream::TTStream(const TokenTree& input_tt):
+ m_input_tt(input_tt),
+ m_cur_layer(&input_tt)
+{
+}
+TTStream::~TTStream()
+{
+}
+Token TTStream::realGetToken()
+{
+ return Token(TOK_EOF);
+}
+
+TokenStream::TokenStream():
+ m_cache_valid(false)
+{
+}
+TokenStream::~TokenStream()
+{
+}
+
+Token TokenStream::getToken()
+{
+ if( m_cache_valid )
+ {
+ m_cache_valid = false;
+ return m_cache;
+ }
+ else
+ {
+ return this->realGetToken();
+ }
+}
+void TokenStream::putback(Token tok)
+{
+ m_cache_valid = true;
+ m_cache = tok;
+}
diff --git a/parse/lex.hpp b/parse/lex.hpp
index a219ae94..88aef072 100644
--- a/parse/lex.hpp
+++ b/parse/lex.hpp
@@ -20,7 +20,6 @@ enum eTokenType
TOK_INTEGER,
TOK_CHAR,
TOK_FLOAT,
- TOK_UNDERSCORE,
TOK_CATTR_OPEN,
TOK_ATTR_OPEN,
@@ -154,11 +153,11 @@ public:
Token(uint64_t val, enum eCoreType datatype);
Token(double val, enum eCoreType datatype);
- enum eTokenType type() { return m_type; }
- const ::std::string& str() { return m_str; }
- enum eCoreType datatype() { return m_datatype; }
- uint64_t intval() { return m_intval; }
- double floatval() { return m_floatval; }
+ enum eTokenType type() const { return m_type; }
+ const ::std::string& str() const { return m_str; }
+ enum eCoreType datatype() const { return m_datatype; }
+ uint64_t intval() const { return m_intval; }
+ double floatval() const { return m_floatval; }
static const char* typestr(enum eTokenType type);
};
@@ -167,9 +166,15 @@ extern ::std::ostream& operator<<(::std::ostream& os, Token& tok);
class TokenStream
{
+ bool m_cache_valid;
+ Token m_cache;
public:
- virtual Token getToken() = 0;
- virtual void putback(Token tok) = 0;
+ TokenStream();
+ virtual ~TokenStream();
+ Token getToken();
+ void putback(Token tok);
+protected:
+ virtual Token realGetToken() = 0;
};
class Lexer
@@ -192,4 +197,25 @@ private:
class EndOfFile {};
};
+class TokenTree
+{
+public:
+ TokenTree(Token tok);
+ TokenTree(::std::vector<TokenTree> subtrees);
+};
+
+class TTStream:
+ public TokenStream
+{
+ const TokenTree& m_input_tt;
+ const TokenTree* m_cur_layer;
+ ::std::vector<unsigned int> m_index_stack;
+public:
+ TTStream(const TokenTree& input_tt);
+ ~TTStream();
+
+protected:
+ virtual Token realGetToken();
+};
+
#endif // LEX_HPP_INCLUDED
diff --git a/parse/parseerror.cpp b/parse/parseerror.cpp
index 044847e7..37beb863 100644
--- a/parse/parseerror.cpp
+++ b/parse/parseerror.cpp
@@ -7,6 +7,18 @@ ParseError::Base::~Base() throw()
{
}
+ParseError::Generic::Generic(::std::string message):
+ m_message(message)
+{
+ ::std::cout << "Generic(" << message << ")" << ::std::endl;
+}
+
+ParseError::BugCheck::BugCheck(::std::string message):
+ m_message(message)
+{
+ ::std::cout << "BugCheck(" << message << ")" << ::std::endl;
+}
+
ParseError::Todo::Todo(::std::string message):
m_message(message)
{
diff --git a/parse/parseerror.hpp b/parse/parseerror.hpp
index b708565d..11324476 100644
--- a/parse/parseerror.hpp
+++ b/parse/parseerror.hpp
@@ -13,6 +13,24 @@ public:
virtual ~Base() throw();
};
+class Generic:
+ public Base
+{
+ ::std::string m_message;
+public:
+ Generic(::std::string message);
+ virtual ~Generic() throw () {}
+};
+
+class BugCheck:
+ public Base
+{
+ ::std::string m_message;
+public:
+ BugCheck(::std::string message);
+ virtual ~BugCheck() throw () {}
+};
+
class Todo:
public Base
{
diff --git a/parse/preproc.cpp b/parse/preproc.cpp
index fa051a3e..2287c41e 100644
--- a/parse/preproc.cpp
+++ b/parse/preproc.cpp
@@ -2,8 +2,7 @@
#include <iostream>
Preproc::Preproc(::std::string path):
- m_lex(path),
- m_cache_valid(false)
+ m_lex(path)
{
//ctor
}
@@ -31,20 +30,7 @@ Token Preproc::getTokenInt()
}
}
-Token Preproc::getToken()
+Token Preproc::realGetToken()
{
- if( m_cache_valid )
- {
- m_cache_valid = false;
- return m_cache;
- }
- else
- {
- return this->getTokenInt();
- }
-}
-void Preproc::putback(Token tok)
-{
- m_cache_valid = true;
- m_cache = tok;
+ return getTokenInt();
}
diff --git a/parse/preproc.hpp b/parse/preproc.hpp
index 827ce249..bedb3076 100644
--- a/parse/preproc.hpp
+++ b/parse/preproc.hpp
@@ -8,15 +8,11 @@ class Preproc:
{
Lexer m_lex;
- bool m_cache_valid;
- Token m_cache;
-
public:
Preproc(::std::string path);
~Preproc();
- virtual Token getToken();
- virtual void putback(Token tok);
+ virtual Token realGetToken();
private:
Token getTokenInt();
};
diff --git a/parse/root.cpp b/parse/root.cpp
index c82527a2..2dac321a 100644
--- a/parse/root.cpp
+++ b/parse/root.cpp
@@ -232,6 +232,8 @@ void Parse_TypeConds(TokenStream& lex, AST::TypeParams& params)
/// Parse a function definition (after the 'fn')
AST::Function Parse_FunctionDef(TokenStream& lex)
{
+ TRACE_FUNCTION;
+
Token tok;
// Name
@@ -254,12 +256,45 @@ AST::Function Parse_FunctionDef(TokenStream& lex)
else {
lex.putback(tok);
}
+
+ AST::Function::Class fcn_class = AST::Function::CLASS_UNBOUND;
GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
+ GET_TOK(tok, lex);
+ if( tok.type() == TOK_AMP )
+ {
+ // By-reference method
+ if( GET_TOK(tok, lex) == TOK_LIFETIME )
+ {
+ throw ParseError::Todo("Lifetimes on self in methods");
+ }
+ if( tok.type() == TOK_RWORD_MUT )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_SELF);
+ fcn_class = AST::Function::CLASS_MUTMETHOD;
+ }
+ else
+ {
+ CHECK_TOK(tok, TOK_RWORD_SELF);
+ fcn_class = AST::Function::CLASS_REFMETHOD;
+ }
+ GET_TOK(tok, lex);
+ }
+ else if( tok.type() == TOK_RWORD_SELF )
+ {
+ // By-value method
+ fcn_class = AST::Function::CLASS_VALMETHOD;
+ GET_TOK(tok, lex);
+ throw ParseError::Todo("By-value methods");
+ }
+ else
+ {
+ // Unbound method
+ }
::std::vector<AST::StructItem> args;
- if( GET_TOK(tok, lex) != TOK_PAREN_CLOSE )
+ if( tok.type() != TOK_PAREN_CLOSE )
{
- // Argument list
lex.putback(tok);
+ // Argument list
do {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
@@ -287,7 +322,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex)
AST::Expr code = Parse_ExprBlock(lex);
- return AST::Function(name, params, ret_type, args, code);
+ return AST::Function(name, params, fcn_class, ret_type, args, code);
}
AST::Module Parse_ModRoot(bool is_own_file, Preproc& lex)
diff --git a/parse/tokentree.hpp b/parse/tokentree.hpp
new file mode 100644
index 00000000..52871cce
--- /dev/null
+++ b/parse/tokentree.hpp
@@ -0,0 +1,10 @@
+#ifndef TOKENTREE_HPP_INCLUDED
+#define TOKENTREE_HPP_INCLUDED
+
+#include "lex.hpp"
+
+
+extern TokenTree Parse_TT(TokenStream& lex);
+extern TokenTree Parse_TT_Expr(TokenStream& lex);
+
+#endif // TOKENTREE_HPP_INCLUDED