summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/expr.hpp4
-rw-r--r--src/ast/path.cpp2
-rw-r--r--src/ast/path.hpp7
-rw-r--r--src/convert/resolve.cpp40
-rw-r--r--src/parse/expr.cpp3
5 files changed, 40 insertions, 16 deletions
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<const AST::Path&> lookup_local(LocalItem::Type type, const ::std::string& name) const;
+ ::rust::option<const LocalItem&> 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<const AST::Path&> CPathResolver::lookup_local(LocalItem::Type type, const ::std::string& name) const
+::rust::option<const CPathResolver::LocalItem&> 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<const AST::Path&>(it->path);
+ return ::rust::option<const LocalItem&>(*it);
}
}
- return ::rust::option<const AST::Path&>();
+ return ::rust::option<const LocalItem&>();
}
// 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<AST::ExprNode> 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);