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 | |
parent | 86938c184b32ce004d5247ad80f924f0ae7a3c86 (diff) | |
download | mrust-ad48a617d5881c14ae5f9d818798d928833a3153.tar.gz |
Tag paths with base crate, restructure ast.cpp into three files
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | src/ast/ast.cpp | 338 | ||||
-rw-r--r-- | src/ast/ast.hpp | 108 | ||||
-rw-r--r-- | src/ast/expr.cpp | 81 | ||||
-rw-r--r-- | src/ast/expr.hpp (renamed from src/ast/ast_expr.hpp) | 32 | ||||
-rw-r--r-- | src/ast/path.cpp | 237 | ||||
-rw-r--r-- | src/ast/path.hpp | 16 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 88 | ||||
-rw-r--r-- | src/common.hpp | 2 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 22 | ||||
-rw-r--r-- | src/include/serialise.hpp | 10 | ||||
-rw-r--r-- | src/serialise.cpp | 3 |
12 files changed, 516 insertions, 424 deletions
@@ -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) { } |