From ad4b6b707dedcdc779435b16081ed0445f71ff05 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 29 Mar 2015 23:02:21 +0800 Subject: Handling for 'T::method()' (where T is a type param) --- src/ast/expr.hpp | 4 ++++ src/ast/path.cpp | 2 +- src/ast/path.hpp | 7 ++++++- src/convert/resolve.cpp | 40 +++++++++++++++++++++++++++------------- src/parse/expr.cpp | 3 ++- 5 files changed, 40 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index d455f3cb..663beae0 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -21,6 +21,7 @@ class ExprNode: public Serialisable { TypeRef m_res_type; + Position m_pos; public: virtual ~ExprNode() = 0; @@ -28,6 +29,9 @@ public: //virtual void visit(NodeVisitor& nv) const = 0; virtual void print(::std::ostream& os) const = 0; + void set_pos(Position p) { m_pos = ::std::move(p); } + const Position& get_pos() const { return m_pos; } + TypeRef& get_res_type() { return m_res_type; } friend ::std::ostream& operator<<(::std::ostream& os, const ExprNode& node); diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 686647a5..c06a63a4 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -386,7 +386,7 @@ void Path::print_pretty(::std::ostream& os) const ::std::ostream& operator<<(::std::ostream& os, const Path& path) { - if( path.m_nodes.size() == 0 ) + if( path.m_nodes.size() == 0 && path.m_class == Path::RELATIVE ) { os << "/* null path */"; return os; diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 027f8f35..1e70389d 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -215,7 +215,12 @@ public: } /// Grab the args from the first node of b, and add the rest to the end of the path void add_tailing(const Path& b) { - m_nodes.back().args() = b[0].args(); + if( m_nodes.size() > 0 ) + m_nodes.back().args() = b[0].args(); + else if( b[0].args().size() > 0 ) + throw ::std::runtime_error("add_tail to empty path, but generics in source"); + else + ; for(unsigned int i = 1; i < b.m_nodes.size(); i ++) m_nodes.push_back(b.m_nodes[i]); m_binding = PathBinding(); diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 86c56578..411d1ae4 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -36,7 +36,7 @@ class CPathResolver: friend ::std::ostream& operator<<(::std::ostream& os, const LocalItem& x) { //return os << "'" << x.name << "' = " << x.path; - return os << "'" << x.name << "'"; + return os << (x.type == TYPE ? "type" : "var") << " '" << x.name << "'"; } }; const AST::Crate& m_crate; @@ -67,7 +67,7 @@ public: } virtual void end_scope() override; - ::rust::option lookup_local(LocalItem::Type type, const ::std::string& name) const; + ::rust::option lookup_local(LocalItem::Type type, const ::std::string& name) const; // TODO: Handle a block and obtain the local module (if any) }; @@ -99,7 +99,7 @@ public: m_res.handle_path(node.m_path, CASTIterator::MODE_EXPR); } void visit(AST::ExprNode_CallPath& node) { - DEBUG("ExprNode_CallPath - " << node); + DEBUG(node.get_pos() << " ExprNode_CallPath - " << node); AST::NodeVisitorDef::visit(node); m_res.handle_path(node.m_path, CASTIterator::MODE_EXPR); } @@ -252,16 +252,16 @@ void CPathResolver::end_scope() m_locals.clear(); } // Returns the bound path for the local item -::rust::option CPathResolver::lookup_local(LocalItem::Type type, const ::std::string& name) const +::rust::option CPathResolver::lookup_local(LocalItem::Type type, const ::std::string& name) const { DEBUG("m_locals = [" << m_locals << "]"); for( auto it = m_locals.end(); it -- != m_locals.begin(); ) { if( it->type == type && it->name == name ) { - return ::rust::option(it->path); + return ::rust::option(*it); } } - return ::rust::option(); + return ::rust::option(); } // Search relative to current module @@ -377,24 +377,38 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) bool is_trivial_path = (path.size() == 1 && path[0].args().size() == 0); LocalItem::Type search_type = (is_trivial_path && mode == MODE_EXPR ? LocalItem::VAR : LocalItem::TYPE); - auto local = lookup_local( search_type, path[0].name() ); - if( local.is_some() ) + auto local_o = lookup_local( search_type, path[0].name() ); + if( local_o.is_some() ) { - auto rpath = local.unwrap(); - DEBUG("Local hit: " << path[0].name() << " = " << rpath); + auto local = local_o.unwrap(); + DEBUG("Local hit: " << path[0].name() << " = " << local); switch(mode) { // Local variable? // - TODO: What would happen if MODE_EXPR but path isn't a single ident? case MODE_EXPR: - if( is_trivial_path ) + if( local.type == LocalItem::VAR ) { + if( !is_trivial_path ) + throw ParseError::Todo("TODO: MODE_EXPR, but not a single identifer, what do?"); DEBUG("Local variable " << path[0].name()); path = AST::Path(AST::Path::TagLocal(), path[0].name()); - return ; } - throw ParseError::Todo("TODO: MODE_EXPR, but not a single identifer, what do?"); + else + { + if( is_trivial_path ) + throw ParseError::Generic("Type used in expression context?"); + // Convert to a UFCS path + DEBUG("Local type"); + auto np = AST::Path(AST::Path::TagUfcs(), TypeRef(TypeRef::TagArg(), path[0].name()), TypeRef()); + DEBUG("np = " << np); + np.add_tailing(path); + DEBUG("np = " << np); + path = ::std::move(np); + DEBUG("path = " << path); + } + return ; // Type parameter case MODE_TYPE: DEBUG("Local type " << path); diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 7f4e73a1..cd449670 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -18,7 +18,8 @@ #include "tokentree.hpp" typedef ::std::unique_ptr ExprNodeP; -#define NEWNODE(type, ...) ExprNodeP(new type(__VA_ARGS__)) +static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){en->set_pos(lex.getPosition()); return ExprNodeP(en); } +#define NEWNODE(type, ...) mk_exprnodep(lex, new type(__VA_ARGS__)) using AST::ExprNode; ExprNodeP Parse_ExprBlockNode(TokenStream& lex); -- cgit v1.2.3