summaryrefslogtreecommitdiff
path: root/src/ast/path.cpp
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 /src/ast/path.cpp
parent86938c184b32ce004d5247ad80f924f0ae7a3c86 (diff)
downloadmrust-ad48a617d5881c14ae5f9d818798d928833a3153.tar.gz
Tag paths with base crate, restructure ast.cpp into three files
Diffstat (limited to 'src/ast/path.cpp')
-rw-r--r--src/ast/path.cpp237
1 files changed, 237 insertions, 0 deletions
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;
+})
+
+}