diff options
author | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-11 20:05:12 +0800 |
---|---|---|
committer | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-11 20:05:12 +0800 |
commit | ad48a617d5881c14ae5f9d818798d928833a3153 (patch) | |
tree | 865a46455098f2b30adadcc5696f1ef1669d1799 /src/ast/path.cpp | |
parent | 86938c184b32ce004d5247ad80f924f0ae7a3c86 (diff) | |
download | mrust-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.cpp | 237 |
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; +}) + +} |