summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge (sonata) <tpg@mutabah.net>2015-01-11 20:05:12 +0800
committerJohn Hodge (sonata) <tpg@mutabah.net>2015-01-11 20:05:12 +0800
commitad48a617d5881c14ae5f9d818798d928833a3153 (patch)
tree865a46455098f2b30adadcc5696f1ef1669d1799
parent86938c184b32ce004d5247ad80f924f0ae7a3c86 (diff)
downloadmrust-ad48a617d5881c14ae5f9d818798d928833a3153.tar.gz
Tag paths with base crate, restructure ast.cpp into three files
-rw-r--r--Makefile3
-rw-r--r--src/ast/ast.cpp338
-rw-r--r--src/ast/ast.hpp108
-rw-r--r--src/ast/expr.cpp81
-rw-r--r--src/ast/expr.hpp (renamed from src/ast/ast_expr.hpp)32
-rw-r--r--src/ast/path.cpp237
-rw-r--r--src/ast/path.hpp16
-rw-r--r--src/ast/pattern.hpp88
-rw-r--r--src/common.hpp2
-rw-r--r--src/convert/resolve.cpp22
-rw-r--r--src/include/serialise.hpp10
-rw-r--r--src/serialise.cpp3
12 files changed, 516 insertions, 424 deletions
diff --git a/Makefile b/Makefile
index 5c42b6bb..83c19920 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,8 @@ OBJDIR = .obj/
BIN := bin/mrustc$(EXESUF)
-OBJ := main.o macros.o types.o ast/ast.o serialise.o
+OBJ := main.o macros.o types.o serialise.o
+OBJ += ast/ast.o ast/path.o ast/expr.o
OBJ += parse/parseerror.o parse/lex.o parse/preproc.o parse/root.o parse/expr.o
OBJ += convert/flatten.o convert/resolve.o convert/render.o
OBJ := $(addprefix $(OBJDIR),$(OBJ))
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 51d476f8..edbaa33e 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -8,232 +8,8 @@
namespace AST {
+ExternCrate ExternCrate_std();
-// --- AST::PathNode
-PathNode::PathNode(::std::string name, ::std::vector<TypeRef> args):
- m_name(name),
- m_params(args)
-{
-}
-const ::std::string& PathNode::name() const
-{
- return m_name;
-}
-const ::std::vector<TypeRef>& PathNode::args() const
-{
- return m_params;
-}
-SERIALISE_TYPE(PathNode::, "PathNode", {
- s << m_name;
- s << m_params;
-})
-
-// --- AST::Path
-template<typename T>
-typename ::std::vector<Item<T> >::const_iterator find_named(const ::std::vector<Item<T> >& vec, const ::std::string& name)
-{
- return ::std::find_if(vec.begin(), vec.end(), [&name](const Item<T>& x) {
- return x.name == name;
- });
-}
-
-void Path::resolve()
-{
- DEBUG("*this = " << *this);
- if(m_class != ABSOLUTE)
- throw ParseError::BugCheck("Calling Path::resolve on non-absolute path");
- if(m_crate == nullptr)
- throw ParseError::BugCheck("Calling Path::resolve on path with no crate");
-
- const Module* mod = &m_crate->root_module();
- for(unsigned int i = 0; i < m_nodes.size(); i ++ )
- {
- const bool is_last = (i+1 == m_nodes.size());
- const bool is_sec_last = (i+2 == m_nodes.size());
- const PathNode& node = m_nodes[i];
- DEBUG("node = " << node);
-
- // Sub-modules
- {
- auto& sms = mod->submods();
- auto it = ::std::find_if(sms.begin(), sms.end(), [&node](const ::std::pair<Module,bool>& x) {
- return x.first.name() == node.name();
- });
- if( it != sms.end() )
- {
- DEBUG("Sub-module '" << node.name() << "'");
- if( node.args().size() )
- throw ParseError::Generic("Generic params applied to module");
- mod = &it->first;
- continue;
- }
- }
- // External crates
- {
- auto& crates = mod->extern_crates();
- auto it = find_named(crates, node.name());
- if( it != crates.end() )
- {
- DEBUG("Extern crate '" << node.name() << "'");
- if( node.args().size() )
- throw ParseError::Generic("Generic params applied to extern crate");
- mod = &it->data.root_module();
- continue;
- }
- }
-
- // Start searching for:
- // - Re-exports
- {
- auto& imp = mod->imports();
- auto it = find_named(imp, node.name());
- if( it != imp.end() )
- {
- DEBUG("Re-exported path " << it->data);
- throw ParseError::Todo("Path::resolve() re-export");
- }
- }
- // - Functions
- {
- auto& items = mod->functions();
- auto it = find_named(items, node.name());
- if( it != items.end() )
- {
- DEBUG("Found function");
- if( is_last ) {
- throw ParseError::Todo("Path::resolve() bind to function");
- }
- else {
- throw ParseError::Generic("Import of function, too many extra nodes");
- }
- }
- }
- // - Structs
- {
- auto& items = mod->structs();
- auto it = find_named(items, node.name());
- if( it != items.end() )
- {
- DEBUG("Found struct");
- if( is_last ) {
- bind_struct(it->data, node.args());
- return;
- }
- else if( is_sec_last ) {
- throw ParseError::Todo("Path::resolve() struct method");
- }
- else {
- throw ParseError::Generic("Import of struct, too many extra nodes");
- }
- }
- }
- // - Enums (and variants)
- {
- auto& enums = mod->enums();
- auto it = find_named(enums, node.name());
- if( it != enums.end() )
- {
- DEBUG("Found enum");
- if( is_last ) {
- bind_enum(it->data, node.args());
- return ;
- }
- else if( is_sec_last ) {
- bind_enum_var(it->data, m_nodes[i+1].name(), node.args());
- return ;
- }
- else {
- throw ParseError::Generic("Import of enum, too many extra nodes");
- }
- }
- }
- // - Constants / statics
-
- throw ParseError::Generic("Unable to find component '" + node.name() + "'");
- }
-
- // We only reach here if the path points to a module
- bind_module(*mod);
-}
-void Path::bind_module(const Module& mod)
-{
- m_binding_type = MODULE;
- m_binding.module_ = &mod;
-}
-void Path::bind_enum(const Enum& ent, const ::std::vector<TypeRef>& args)
-{
- m_binding_type = ENUM;
- m_binding.enum_ = &ent;
- if( args.size() > 0 )
- {
- if( args.size() != ent.params().size() )
- throw ParseError::Generic("Parameter count mismatch");
- throw ParseError::Todo("Bind enum with params passed");
- }
-}
-void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std::vector<TypeRef>& args)
-{
- unsigned int idx = 0;
- for( idx = 0; idx < ent.variants().size(); idx ++ )
- {
- if( ent.variants()[idx].first == name ) {
- break;
- }
- }
- if( idx == ent.variants().size() )
- throw ParseError::Generic("Enum variant not found");
-
- if( args.size() > 0 )
- {
- if( args.size() != ent.params().size() )
- throw ParseError::Generic("Parameter count mismatch");
- throw ParseError::Todo("Bind enum variant with params passed");
- }
-
- m_binding_type = ENUM_VAR;
- m_binding.enumvar = {&ent, idx};
-}
-void Path::bind_struct(const Struct& ent, const ::std::vector<TypeRef>& args)
-{
- throw ParseError::Todo("Path::resolve() bind to struct type");
-}
-
-Path& Path::operator+=(const Path& other)
-{
- for(auto& node : other.m_nodes)
- append(node);
- return *this;
-}
-::std::ostream& operator<<(::std::ostream& os, const Path& path)
-{
- switch(path.m_class)
- {
- case Path::RELATIVE:
- os << "Path({" << path.m_nodes << "})";
- break;
- case Path::ABSOLUTE:
- os << "Path(TagAbsolute, {" << path.m_nodes << "})";
- break;
- case Path::LOCAL:
- os << "Path(TagLocal, " << path.m_nodes[0].name() << ")";
- break;
- }
- return os;
-}
-::Serialiser& operator<<(Serialiser& s, Path::Class pc)
-{
- switch(pc)
- {
- case Path::RELATIVE: s << "RELATIVE"; break;
- case Path::ABSOLUTE: s << "ABSOLUTE"; break;
- case Path::LOCAL: s << "LOCAL"; break;
- }
- return s;
-}
-SERIALISE_TYPE(Path::, "AST_Path", {
- s << m_class;
- s << m_nodes;
-})
SERIALISE_TYPE(MetaItem::, "AST_MetaItem", {
s << m_name;
@@ -282,8 +58,32 @@ void Crate::iterate_functions(fcn_visitor_t* visitor)
{
m_root_module.iterate_functions(visitor, *this);
}
+Module& Crate::get_root_module(const ::std::string& name) {
+ return const_cast<Module&>( const_cast<const Crate*>(this)->get_root_module(name) );
+}
+const Module& Crate::get_root_module(const ::std::string& name) const {
+ if( name == "" )
+ return m_root_module;
+ auto it = m_extern_crates.find(name);
+ if( it != m_extern_crates.end() )
+ return it->second.root_module();
+ throw ParseError::Generic("crate name unknown");
+}
+void Crate::load_extern_crate(::std::string name)
+{
+ if( name == "std" )
+ {
+ // HACK! Load std using a hackjob (included within the compiler)
+ m_extern_crates.insert( make_pair( ::std::move(name), ExternCrate_std() ) );
+ }
+ else
+ {
+ throw ParseError::Todo("'extern crate' (not hackjob std)");
+ }
+}
SERIALISE_TYPE(Crate::, "AST_Crate", {
s << m_load_std;
+ s << m_extern_crates;
s << m_root_module;
})
@@ -319,7 +119,7 @@ ExternCrate ExternCrate_std()
Module prelude(crate.crate(), "prelude");
// Re-exports
- #define USE(mod, name, ...) do{ Path p({__VA_ARGS__}); p.set_crate(crate.crate()); p.resolve(); mod.add_alias(true, ::std::move(p), name); } while(0)
+ #define USE(mod, name, ...) do{ Path p({__VA_ARGS__}); mod.add_alias(true, ::std::move(p), name); } while(0)
USE(prelude, "Option", PathNode("option", {}), PathNode("Option",{}) );
USE(prelude, "Some", PathNode("option", {}), PathNode("Option",{}), PathNode("Some",{}) );
USE(prelude, "None", PathNode("option", {}), PathNode("Option",{}), PathNode("None",{}) );
@@ -340,15 +140,9 @@ SERIALISE_TYPE(Module::, "AST_Module", {
void Module::add_ext_crate(::std::string ext_name, ::std::string int_name)
{
DEBUG("add_ext_crate(\"" << ext_name << "\" as " << int_name << ")");
- if( ext_name == "std" )
- {
- // HACK! Load std using a hackjob (included within the compiler)
- m_extern_crates.push_back( Item<ExternCrate>( ::std::move(int_name), ExternCrate_std(), false ) );
- }
- else
- {
- throw ParseError::Todo("'extern crate' (not hackjob std)");
- }
+ m_crate.load_extern_crate(ext_name);
+
+ m_extern_crates.push_back( Item< ::std::string>( ::std::move(int_name), ::std::move(ext_name), false ) );
}
void Module::add_constant(bool is_public, ::std::string name, TypeRef type, Expr val)
{
@@ -401,80 +195,6 @@ SERIALISE_TYPE(Struct::, "AST_Struct", {
s << m_fields;
})
-void Expr::visit_nodes(NodeVisitor& v)
-{
- m_node->visit(v);
-}
-::std::ostream& operator<<(::std::ostream& os, const Expr& pat)
-{
- os << "Expr(TODO)";
- return os;
-}
-
-ExprNode::~ExprNode() {
-}
-
-ExprNode_Block::~ExprNode_Block() {
-}
-void ExprNode_Block::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_Return::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_LetBinding::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_Assign::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_CallPath::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_CallMethod::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_CallObject::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_Match::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_If::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_Integer::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_StructLiteral::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_NamedValue::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_Field::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
-void ExprNode_Cast::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-void ExprNode_BinOp::visit(NodeVisitor& nv) {
- nv.visit(*this);
-}
-
TypeParam::TypeParam(bool is_lifetime, ::std::string name)
{
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 510560fe..70e6f497 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -6,11 +6,16 @@
#include <stdexcept>
#include "../coretypes.hpp"
#include <memory>
+#include <map>
#include "../parse/tokentree.hpp"
#include "../types.hpp"
#include <serialise.hpp>
+#include "pattern.hpp"
+
+#include "expr.hpp"
+
namespace AST {
using ::std::unique_ptr;
@@ -28,6 +33,7 @@ public:
};
typedef ::std::vector<TypeParam> TypeParams;
+typedef ::std::pair< ::std::string, TypeRef> StructItem;
class Crate;
@@ -53,100 +59,6 @@ public:
SERIALISABLE_PROTOTYPES();
};
-class ExprNode;
-
-class Pattern
-{
-public:
- enum BindType {
- MAYBE_BIND,
- ANY,
- VALUE,
- TUPLE,
- TUPLE_STRUCT,
- };
-private:
- BindType m_class;
- ::std::string m_binding;
- Path m_path;
- unique_ptr<ExprNode> m_node;
- ::std::vector<Pattern> m_sub_patterns;
-public:
- Pattern():
- m_class(ANY)
- {}
-
- struct TagBind {};
- Pattern(TagBind, ::std::string name):
- m_class(ANY),
- m_binding(name)
- {}
-
- struct TagMaybeBind {};
- Pattern(TagMaybeBind, ::std::string name):
- m_class(MAYBE_BIND),
- m_binding(name)
- {}
-
- struct TagValue {};
- Pattern(TagValue, unique_ptr<ExprNode> node):
- m_class(VALUE),
- m_node( ::std::move(node) )
- {}
-
- struct TagTuple {};
- Pattern(TagTuple, ::std::vector<Pattern> sub_patterns):
- m_class(TUPLE),
- m_sub_patterns( ::std::move(sub_patterns) )
- {}
-
- struct TagEnumVariant {};
- Pattern(TagEnumVariant, Path path, ::std::vector<Pattern> sub_patterns):
- m_class(TUPLE_STRUCT),
- m_path( ::std::move(path) ),
- m_sub_patterns( ::std::move(sub_patterns) )
- {}
-
- // Mutators
- void set_bind(::std::string name) {
- m_binding = name;
- }
-
- // Accessors
- const ::std::string& binding() const { return m_binding; }
- BindType type() const { return m_class; }
- ExprNode& node() { return *m_node; }
- const ExprNode& node() const { return *m_node; }
- Path& path() { return m_path; }
- const Path& path() const { return m_path; }
- ::std::vector<Pattern>& sub_patterns() { return m_sub_patterns; }
- const ::std::vector<Pattern>& sub_patterns() const { return m_sub_patterns; }
-
- friend ::std::ostream& operator<<(::std::ostream& os, const Pattern& pat);
-};
-
-#include "ast_expr.hpp"
-
-class Expr
-{
- ::std::shared_ptr<ExprNode> m_node;
-public:
- Expr(unique_ptr<ExprNode> node):
- m_node(node.release())
- {
- }
- Expr(ExprNode* node):
- m_node(node)
- {
- }
-
- void visit_nodes(NodeVisitor& v);
-
- friend ::std::ostream& operator<<(::std::ostream& os, const Expr& pat);
-};
-
-typedef ::std::pair< ::std::string, TypeRef> StructItem;
-
class Function:
public Serialisable
{
@@ -266,7 +178,7 @@ class Module:
typedef ::std::vector< Item<Function> > itemlist_fcn_t;
typedef ::std::vector< ::std::pair<Module, bool> > itemlist_mod_t;
typedef ::std::vector< Item<Path> > itemlist_use_t;
- typedef ::std::vector< Item<ExternCrate> > itemlist_ext_t;
+ typedef ::std::vector< Item< ::std::string> > itemlist_ext_t;
typedef ::std::vector< Item<Enum> > itemlist_enum_t;
typedef ::std::vector< Item<Struct> > itemlist_struct_t;
@@ -337,6 +249,7 @@ class Crate:
{
public:
Module m_root_module;
+ ::std::map< ::std::string, ExternCrate> m_extern_crates;
bool m_load_std;
Crate();
@@ -344,6 +257,11 @@ public:
Module& root_module() { return m_root_module; }
const Module& root_module() const { return m_root_module; }
+ Module& get_root_module(const ::std::string& name);
+ const Module& get_root_module(const ::std::string& name) const;
+
+ void load_extern_crate(::std::string name);
+
void iterate_functions( fcn_visitor_t* visitor );
SERIALISABLE_PROTOTYPES();
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
new file mode 100644
index 00000000..a5401fef
--- /dev/null
+++ b/src/ast/expr.cpp
@@ -0,0 +1,81 @@
+/*
+ */
+#include "expr.hpp"
+
+namespace AST {
+
+void Expr::visit_nodes(NodeVisitor& v)
+{
+ m_node->visit(v);
+}
+::std::ostream& operator<<(::std::ostream& os, const Expr& pat)
+{
+ os << "Expr(TODO)";
+ return os;
+}
+
+ExprNode::~ExprNode() {
+}
+
+ExprNode_Block::~ExprNode_Block() {
+}
+void ExprNode_Block::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_Return::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_LetBinding::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_Assign::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_CallPath::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_CallMethod::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_CallObject::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_Match::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_If::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_Integer::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_StructLiteral::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_NamedValue::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_Field::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+
+void ExprNode_Cast::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+void ExprNode_BinOp::visit(NodeVisitor& nv) {
+ nv.visit(*this);
+}
+};
+
diff --git a/src/ast/ast_expr.hpp b/src/ast/expr.hpp
index 9b659bfd..1ebd3090 100644
--- a/src/ast/ast_expr.hpp
+++ b/src/ast/expr.hpp
@@ -3,6 +3,18 @@
#ifndef AST_EXPR_INCLUDED
#define AST_EXPR_INCLUDED
+#include <ostream>
+#include <memory> // unique_ptr
+#include <vector>
+
+#include "../parse/tokentree.hpp"
+#include "../types.hpp"
+#include "pattern.hpp"
+
+namespace AST {
+
+using ::std::unique_ptr;
+
class NodeVisitor;
class ExprNode
@@ -333,5 +345,25 @@ public:
}
};
+class Expr
+{
+ ::std::shared_ptr<ExprNode> m_node;
+public:
+ Expr(unique_ptr<ExprNode> node):
+ m_node(node.release())
+ {
+ }
+ Expr(ExprNode* node):
+ m_node(node)
+ {
+ }
+
+ void visit_nodes(NodeVisitor& v);
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const Expr& pat);
+};
+
+}
+
#endif
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
new file mode 100644
index 00000000..648d4055
--- /dev/null
+++ b/src/ast/path.cpp
@@ -0,0 +1,237 @@
+/*
+ */
+#include "path.hpp"
+#include "ast.hpp"
+#include "../types.hpp"
+#include <iostream>
+#include "../parse/parseerror.hpp"
+#include <algorithm>
+
+namespace AST {
+
+// --- AST::PathNode
+PathNode::PathNode(::std::string name, ::std::vector<TypeRef> args):
+ m_name(name),
+ m_params(args)
+{
+}
+const ::std::string& PathNode::name() const
+{
+ return m_name;
+}
+const ::std::vector<TypeRef>& PathNode::args() const
+{
+ return m_params;
+}
+SERIALISE_TYPE(PathNode::, "PathNode", {
+ s << m_name;
+ s << m_params;
+})
+
+// --- AST::Path
+template<typename T>
+typename ::std::vector<Item<T> >::const_iterator find_named(const ::std::vector<Item<T> >& vec, const ::std::string& name)
+{
+ return ::std::find_if(vec.begin(), vec.end(), [&name](const Item<T>& x) {
+ return x.name == name;
+ });
+}
+
+void Path::resolve(const Crate& root_crate)
+{
+ DEBUG("*this = " << *this);
+ if(m_class != ABSOLUTE)
+ throw ParseError::BugCheck("Calling Path::resolve on non-absolute path");
+ DEBUG("m_crate = '" << m_crate << "'");
+
+ const Module* mod = &root_crate.get_root_module(m_crate);
+ for(unsigned int i = 0; i < m_nodes.size(); i ++ )
+ {
+ const bool is_last = (i+1 == m_nodes.size());
+ const bool is_sec_last = (i+2 == m_nodes.size());
+ const PathNode& node = m_nodes[i];
+ DEBUG("mod = " << mod << ", node = " << node);
+
+ // Sub-modules
+ {
+ auto& sms = mod->submods();
+ auto it = ::std::find_if(sms.begin(), sms.end(), [&node](const ::std::pair<Module,bool>& x) {
+ return x.first.name() == node.name();
+ });
+ if( it != sms.end() )
+ {
+ DEBUG("Sub-module '" << node.name() << "'");
+ if( node.args().size() )
+ throw ParseError::Generic("Generic params applied to module");
+ mod = &it->first;
+ continue;
+ }
+ }
+ // External crates
+ {
+ auto& crates = mod->extern_crates();
+ auto it = find_named(crates, node.name());
+ if( it != crates.end() )
+ {
+ DEBUG("Extern crate '" << node.name() << "' = '" << it->data << "'");
+ if( node.args().size() )
+ throw ParseError::Generic("Generic params applied to extern crate");
+ mod = &root_crate.get_root_module(it->data);
+ continue;
+ }
+ }
+
+ // Start searching for:
+ // - Re-exports
+ {
+ auto& imp = mod->imports();
+ auto it = find_named(imp, node.name());
+ if( it != imp.end() )
+ {
+ DEBUG("Re-exported path " << it->data);
+ throw ParseError::Todo("Path::resolve() re-export");
+ }
+ }
+ // - Functions
+ {
+ auto& items = mod->functions();
+ auto it = find_named(items, node.name());
+ if( it != items.end() )
+ {
+ DEBUG("Found function");
+ if( is_last ) {
+ throw ParseError::Todo("Path::resolve() bind to function");
+ }
+ else {
+ throw ParseError::Generic("Import of function, too many extra nodes");
+ }
+ }
+ }
+ // - Structs
+ {
+ auto& items = mod->structs();
+ auto it = find_named(items, node.name());
+ if( it != items.end() )
+ {
+ DEBUG("Found struct");
+ if( is_last ) {
+ bind_struct(it->data, node.args());
+ return;
+ }
+ else if( is_sec_last ) {
+ throw ParseError::Todo("Path::resolve() struct method");
+ }
+ else {
+ throw ParseError::Generic("Import of struct, too many extra nodes");
+ }
+ }
+ }
+ // - Enums (and variants)
+ {
+ auto& enums = mod->enums();
+ auto it = find_named(enums, node.name());
+ if( it != enums.end() )
+ {
+ DEBUG("Found enum");
+ if( is_last ) {
+ bind_enum(it->data, node.args());
+ return ;
+ }
+ else if( is_sec_last ) {
+ bind_enum_var(it->data, m_nodes[i+1].name(), node.args());
+ return ;
+ }
+ else {
+ throw ParseError::Generic("Import of enum, too many extra nodes");
+ }
+ }
+ }
+ // - Constants / statics
+
+ throw ParseError::Generic("Unable to find component '" + node.name() + "'");
+ }
+
+ // We only reach here if the path points to a module
+ bind_module(*mod);
+}
+void Path::bind_module(const Module& mod)
+{
+ m_binding_type = MODULE;
+ m_binding.module_ = &mod;
+}
+void Path::bind_enum(const Enum& ent, const ::std::vector<TypeRef>& args)
+{
+ m_binding_type = ENUM;
+ m_binding.enum_ = &ent;
+ if( args.size() > 0 )
+ {
+ if( args.size() != ent.params().size() )
+ throw ParseError::Generic("Parameter count mismatch");
+ throw ParseError::Todo("Bind enum with params passed");
+ }
+}
+void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std::vector<TypeRef>& args)
+{
+ unsigned int idx = 0;
+ for( idx = 0; idx < ent.variants().size(); idx ++ )
+ {
+ if( ent.variants()[idx].first == name ) {
+ break;
+ }
+ }
+ if( idx == ent.variants().size() )
+ throw ParseError::Generic("Enum variant not found");
+
+ if( args.size() > 0 )
+ {
+ if( args.size() != ent.params().size() )
+ throw ParseError::Generic("Parameter count mismatch");
+ throw ParseError::Todo("Bind enum variant with params passed");
+ }
+
+ m_binding_type = ENUM_VAR;
+ m_binding.enumvar = {&ent, idx};
+}
+void Path::bind_struct(const Struct& ent, const ::std::vector<TypeRef>& args)
+{
+ throw ParseError::Todo("Path::resolve() bind to struct type");
+}
+
+Path& Path::operator+=(const Path& other)
+{
+ for(auto& node : other.m_nodes)
+ append(node);
+ return *this;
+}
+::std::ostream& operator<<(::std::ostream& os, const Path& path)
+{
+ switch(path.m_class)
+ {
+ case Path::RELATIVE:
+ os << "Path({" << path.m_nodes << "})";
+ break;
+ case Path::ABSOLUTE:
+ os << "Path(TagAbsolute, {" << path.m_nodes << "})";
+ break;
+ case Path::LOCAL:
+ os << "Path(TagLocal, " << path.m_nodes[0].name() << ")";
+ break;
+ }
+ return os;
+}
+::Serialiser& operator<<(Serialiser& s, Path::Class pc)
+{
+ switch(pc)
+ {
+ case Path::RELATIVE: s << "RELATIVE"; break;
+ case Path::ABSOLUTE: s << "ABSOLUTE"; break;
+ case Path::LOCAL: s << "LOCAL"; break;
+ }
+ return s;
+}
+SERIALISE_TYPE(Path::, "AST_Path", {
+ s << m_class;
+ s << m_nodes;
+})
+
+}
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index b518fc8f..17325d10 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -65,7 +65,7 @@ private:
};
/// The crate defining the root of this path (used for path resolution)
- const Crate* m_crate;
+ ::std::string m_crate;
/// Path class (absolute, relative, local)
/// - Absolute is "relative" to the crate root
@@ -85,30 +85,28 @@ private:
} m_binding;
public:
Path():
- m_crate(nullptr),
m_class(RELATIVE)
{}
struct TagAbsolute {};
Path(TagAbsolute):
- m_crate(nullptr),
m_class(ABSOLUTE)
{}
struct TagLocal {};
Path(TagLocal, ::std::string name):
- m_crate(nullptr),
m_class(LOCAL),
m_nodes({PathNode(name, {})})
{}
Path(::std::initializer_list<PathNode> l):
- m_crate(nullptr),
m_class(ABSOLUTE),
m_nodes(l)
{}
- void set_crate(const Crate& crate) {
- if( !m_crate )
- m_crate = &crate;
+ void set_crate(::std::string crate) {
+ if( m_crate == "" ) {
+ m_crate = crate;
+ DEBUG("crate set to " << m_crate);
+ }
}
static Path add_tailing(const Path& a, const Path& b) {
@@ -136,7 +134,7 @@ public:
m_nodes.push_back(node);
}
- void resolve();
+ void resolve(const Crate& crate);
bool is_relative() const { return m_class == RELATIVE; }
size_t size() const { return m_nodes.size(); }
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
new file mode 100644
index 00000000..70253c09
--- /dev/null
+++ b/src/ast/pattern.hpp
@@ -0,0 +1,88 @@
+
+#ifndef _AST__PATTERN_HPP_INCLUDED_
+#define _AST__PATTERN_HPP_INCLUDED_
+
+#include <vector>
+#include <memory>
+#include <string>
+
+namespace AST {
+
+using ::std::unique_ptr;
+using ::std::move;
+
+class ExprNode;
+
+class Pattern
+{
+public:
+ enum BindType {
+ MAYBE_BIND,
+ ANY,
+ VALUE,
+ TUPLE,
+ TUPLE_STRUCT,
+ };
+private:
+ BindType m_class;
+ ::std::string m_binding;
+ Path m_path;
+ unique_ptr<ExprNode> m_node;
+ ::std::vector<Pattern> m_sub_patterns;
+public:
+ Pattern():
+ m_class(ANY)
+ {}
+
+ struct TagBind {};
+ Pattern(TagBind, ::std::string name):
+ m_class(ANY),
+ m_binding(name)
+ {}
+
+ struct TagMaybeBind {};
+ Pattern(TagMaybeBind, ::std::string name):
+ m_class(MAYBE_BIND),
+ m_binding(name)
+ {}
+
+ struct TagValue {};
+ Pattern(TagValue, unique_ptr<ExprNode> node):
+ m_class(VALUE),
+ m_node( ::std::move(node) )
+ {}
+
+ struct TagTuple {};
+ Pattern(TagTuple, ::std::vector<Pattern> sub_patterns):
+ m_class(TUPLE),
+ m_sub_patterns( ::std::move(sub_patterns) )
+ {}
+
+ struct TagEnumVariant {};
+ Pattern(TagEnumVariant, Path path, ::std::vector<Pattern> sub_patterns):
+ m_class(TUPLE_STRUCT),
+ m_path( ::std::move(path) ),
+ m_sub_patterns( ::std::move(sub_patterns) )
+ {}
+
+ // Mutators
+ void set_bind(::std::string name) {
+ m_binding = name;
+ }
+
+ // Accessors
+ const ::std::string& binding() const { return m_binding; }
+ BindType type() const { return m_class; }
+ ExprNode& node() { return *m_node; }
+ const ExprNode& node() const { return *m_node; }
+ Path& path() { return m_path; }
+ const Path& path() const { return m_path; }
+ ::std::vector<Pattern>& sub_patterns() { return m_sub_patterns; }
+ const ::std::vector<Pattern>& sub_patterns() const { return m_sub_patterns; }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const Pattern& pat);
+};
+
+};
+
+#endif
diff --git a/src/common.hpp b/src/common.hpp
index 21f1663e..c7117722 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -9,7 +9,7 @@
#include <iostream>
#include <vector>
-#define DEBUG(ss) do{ ::std::cerr << __func__ << ": " << ss << ::std::endl; } while(0)
+#define DEBUG(ss) do{ ::std::cerr << __FUNCTION__ << ": " << ss << ::std::endl; } while(0)
namespace AST {
template <typename T>
diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp
index 7f36c964..ce9433dd 100644
--- a/src/convert/resolve.cpp
+++ b/src/convert/resolve.cpp
@@ -104,8 +104,7 @@ void CPathResolver::resolve_path(AST::Path& path, bool allow_variables) const
// Already absolute, our job is done
// - However, if the path isn't bound, bind it
if( !path.is_bound() ) {
- path.set_crate(m_crate);
- path.resolve();
+ path.resolve(m_crate);
}
}
else
@@ -166,7 +165,7 @@ void CPathResolver::resolve_path(AST::Path& path, bool allow_variables) const
}
DEBUG("path = " << path);
- path.resolve();
+ path.resolve(m_crate);
throw ParseError::Todo("CPathResolver::resolve_path()");
@@ -280,8 +279,8 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod
// Wildcard import
AST::Path& basepath = imp.data;
- basepath.set_crate(crate);
- basepath.resolve();
+ basepath.resolve(crate);
+ DEBUG("basepath = " << basepath);
switch(basepath.binding_type())
{
case AST::Path::UNBOUND:
@@ -298,13 +297,21 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod
{
if( imp.is_pub )
{
+ DEBUG("Re-export " << imp.data);
if(imp.name == "")
throw ParseError::Generic("Wilcard uses can't be public");
- new_imports.push_back( imp.data );
+ AST::Path path = imp.data;
+ path.resolve(crate);
+ DEBUG("Re-export (resolved) " << path);
+ new_imports.push_back( ::std::move(path) );
}
}
//throw ParseError::Todo("ResolvePaths_HandleModule - wildcard use on module");
break;
+ case AST::Path::ENUM:
+ throw ParseError::Todo("ResolvePaths_HandleModule_Use - ENUM");
+ case AST::Path::ENUM_VAR:
+ throw ParseError::Todo("ResolvePaths_HandleModule_Use - ENUM_VAR");
}
}
}
@@ -312,8 +319,7 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod
for( auto& new_imp : new_imports )
{
if( not new_imp.is_bound() ) {
- new_imp.set_crate(crate);
- new_imp.resolve();
+ new_imp.resolve(crate);
}
mod.add_alias(false, new_imp, new_imp[new_imp.size()-1].name());
}
diff --git a/src/include/serialise.hpp b/src/include/serialise.hpp
index f4b86133..be5658a8 100644
--- a/src/include/serialise.hpp
+++ b/src/include/serialise.hpp
@@ -5,6 +5,7 @@
#include <vector>
#include <string>
+#include <map>
class Serialiser;
@@ -53,6 +54,15 @@ public:
end_array();
return *this;
}
+ template<typename T1, typename T2>
+ Serialiser& operator<<(const ::std::map<T1,T2>& v)
+ {
+ start_object("map");
+ for(const auto& ent : v)
+ *this << ent;
+ end_object("map");
+ return *this;
+ }
};
#endif
diff --git a/src/serialise.cpp b/src/serialise.cpp
index e4825327..65a2ea78 100644
--- a/src/serialise.cpp
+++ b/src/serialise.cpp
@@ -13,7 +13,8 @@ Serialiser& Serialiser::operator<<(const Serialisable& subobj)
Serialiser_TextTree::Serialiser_TextTree(::std::ostream& os):
- m_os(os)
+ m_os(os),
+ m_indent_level(0)
{
}