From ad48a617d5881c14ae5f9d818798d928833a3153 Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Sun, 11 Jan 2015 20:05:12 +0800 Subject: Tag paths with base crate, restructure ast.cpp into three files --- Makefile | 3 +- src/ast/ast.cpp | 338 ++++-------------------------------------- src/ast/ast.hpp | 108 ++------------ src/ast/ast_expr.hpp | 337 ------------------------------------------ src/ast/expr.cpp | 81 ++++++++++ src/ast/expr.hpp | 369 ++++++++++++++++++++++++++++++++++++++++++++++ src/ast/path.cpp | 237 +++++++++++++++++++++++++++++ src/ast/path.hpp | 16 +- src/ast/pattern.hpp | 88 +++++++++++ src/common.hpp | 2 +- src/convert/resolve.cpp | 22 ++- src/include/serialise.hpp | 10 ++ src/serialise.cpp | 3 +- 13 files changed, 853 insertions(+), 761 deletions(-) delete mode 100644 src/ast/ast_expr.hpp create mode 100644 src/ast/expr.cpp create mode 100644 src/ast/expr.hpp create mode 100644 src/ast/path.cpp create mode 100644 src/ast/pattern.hpp 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 args): - m_name(name), - m_params(args) -{ -} -const ::std::string& PathNode::name() const -{ - return m_name; -} -const ::std::vector& PathNode::args() const -{ - return m_params; -} -SERIALISE_TYPE(PathNode::, "PathNode", { - s << m_name; - s << m_params; -}) - -// --- AST::Path -template -typename ::std::vector >::const_iterator find_named(const ::std::vector >& vec, const ::std::string& name) -{ - return ::std::find_if(vec.begin(), vec.end(), [&name](const Item& 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& 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& 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& 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& 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( const_cast(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( ::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 #include "../coretypes.hpp" #include +#include #include "../parse/tokentree.hpp" #include "../types.hpp" #include +#include "pattern.hpp" + +#include "expr.hpp" + namespace AST { using ::std::unique_ptr; @@ -28,6 +33,7 @@ public: }; typedef ::std::vector 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 m_node; - ::std::vector 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 node): - m_class(VALUE), - m_node( ::std::move(node) ) - {} - - struct TagTuple {}; - Pattern(TagTuple, ::std::vector sub_patterns): - m_class(TUPLE), - m_sub_patterns( ::std::move(sub_patterns) ) - {} - - struct TagEnumVariant {}; - Pattern(TagEnumVariant, Path path, ::std::vector 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& sub_patterns() { return m_sub_patterns; } - const ::std::vector& 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 m_node; -public: - Expr(unique_ptr 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 > itemlist_fcn_t; typedef ::std::vector< ::std::pair > itemlist_mod_t; typedef ::std::vector< Item > itemlist_use_t; - typedef ::std::vector< Item > itemlist_ext_t; + typedef ::std::vector< Item< ::std::string> > itemlist_ext_t; typedef ::std::vector< Item > itemlist_enum_t; typedef ::std::vector< Item > 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/ast_expr.hpp b/src/ast/ast_expr.hpp deleted file mode 100644 index 9b659bfd..00000000 --- a/src/ast/ast_expr.hpp +++ /dev/null @@ -1,337 +0,0 @@ -/* - */ -#ifndef AST_EXPR_INCLUDED -#define AST_EXPR_INCLUDED - -class NodeVisitor; - -class ExprNode -{ -public: - virtual ~ExprNode() = 0; - - virtual void visit(NodeVisitor& nv) = 0; -}; - -struct ExprNode_Block: - public ExprNode -{ - ::std::vector< ::std::unique_ptr > m_nodes; - - ExprNode_Block(const ExprNode_Block& x) = delete; - ExprNode_Block(::std::vector< ::std::unique_ptr >&& nodes): - m_nodes( move(nodes) ) - { - } - virtual ~ExprNode_Block() override; - - virtual void visit(NodeVisitor& nv) override; -}; - -struct ExprNode_Macro: - public ExprNode -{ - ::std::string m_name; - ::TokenTree m_tokens; - - ExprNode_Macro(::std::string name, ::TokenTree&& tokens): - m_name(name), - m_tokens( move(tokens) ) - {} - - virtual void visit(NodeVisitor& nv) override; -}; - -// Return a value -struct ExprNode_Return: - public ExprNode -{ - unique_ptr m_value; - - ExprNode_Return(unique_ptr&& value): - m_value( move(value) ) - { - } - - virtual void visit(NodeVisitor& nv) override; -}; -struct ExprNode_LetBinding: - public ExprNode -{ - Pattern m_pat; - unique_ptr m_value; - - ExprNode_LetBinding(Pattern pat, unique_ptr&& value): - m_pat( move(pat) ), - m_value( move(value) ) - { - } - - virtual void visit(NodeVisitor& nv) override; -}; -struct ExprNode_Assign: - public ExprNode -{ - unique_ptr m_slot; - unique_ptr m_value; - - ExprNode_Assign(unique_ptr&& slot, unique_ptr&& value): - m_slot( move(slot) ), - m_value( move(value) ) - { - } - - virtual void visit(NodeVisitor& nv) override; -}; -struct ExprNode_CallPath: - public ExprNode -{ - Path m_path; - ::std::vector> m_args; - - ExprNode_CallPath(Path&& path, ::std::vector>&& args): - m_path( move(path) ), - m_args( move(args) ) - { - } - - virtual void visit(NodeVisitor& nv) override; -}; -struct ExprNode_CallMethod: - public ExprNode -{ - unique_ptr m_val; - PathNode m_method; - ::std::vector> m_args; - - ExprNode_CallMethod(unique_ptr&& obj, PathNode&& method, ::std::vector>&& args): - m_val( move(obj) ), - m_method( move(method) ), - m_args( move(args) ) - { - } - - virtual void visit(NodeVisitor& nv) override; -}; -// Call an object (Fn/FnMut/FnOnce) -struct ExprNode_CallObject: - public ExprNode -{ - unique_ptr m_val; - ::std::vector> m_args; - - ExprNode_CallObject(unique_ptr&& val, ::std::vector< unique_ptr >&& args): - m_val( move(val) ), - m_args( move(args) ) - { - } - virtual void visit(NodeVisitor& nv) override; -}; - -struct ExprNode_Match: - public ExprNode -{ - typedef ::std::vector< ::std::pair > > arm_t; - unique_ptr m_val; - arm_t m_arms; - - ExprNode_Match(unique_ptr&& val, arm_t&& arms): - m_val( ::std::move(val) ), - m_arms( ::std::move(arms) ) - { - } - virtual void visit(NodeVisitor& nv) override; -}; - -struct ExprNode_If: - public ExprNode -{ - unique_ptr m_cond; - unique_ptr m_true; - unique_ptr m_false; - - ExprNode_If(unique_ptr&& cond, unique_ptr&& true_code, unique_ptr&& false_code): - m_cond( ::std::move(cond) ), - m_true( ::std::move(true_code) ), - m_false( ::std::move(false_code) ) - { - } - virtual void visit(NodeVisitor& nv) override; -}; -// Literal integer -struct ExprNode_Integer: - public ExprNode -{ - enum eCoreType m_datatype; - uint64_t m_value; - - ExprNode_Integer(uint64_t value, enum eCoreType datatype): - m_datatype(datatype), - m_value(value) - { - } - - virtual void visit(NodeVisitor& nv) override; -}; -// Literal structure -struct ExprNode_StructLiteral: - public ExprNode -{ - typedef ::std::vector< ::std::pair< ::std::string, unique_ptr > > t_values; - Path m_path; - unique_ptr m_base_value; - t_values m_values; - - ExprNode_StructLiteral(Path path, unique_ptr&& base_value, t_values&& values ): - m_path( move(path) ), - m_base_value( move(base_value) ), - m_values( move(values) ) - {} - - virtual void visit(NodeVisitor& nv) override; -}; -// Variable / Constant -struct ExprNode_NamedValue: - public ExprNode -{ - Path m_path; - ExprNode_NamedValue(Path&& path): - m_path( ::std::move(path) ) - { - } - virtual void visit(NodeVisitor& nv) override; -}; -// Field dereference -struct ExprNode_Field: - public ExprNode -{ - ::std::unique_ptr m_obj; - ::std::string m_name; - - ExprNode_Field(::std::unique_ptr&& obj, ::std::string&& name): - m_obj( ::std::move(obj) ), - m_name( ::std::move(name) ) - { - } - virtual void visit(NodeVisitor& nv) override; -}; - -// Type cast ('as') -struct ExprNode_Cast: - public ExprNode -{ - unique_ptr m_value; - TypeRef m_type; - - ExprNode_Cast(unique_ptr&& value, TypeRef&& dst_type): - m_value( move(value) ), - m_type( move(dst_type) ) - { - } - virtual void visit(NodeVisitor& nv) override; -}; - -// Binary operation -struct ExprNode_BinOp: - public ExprNode -{ - enum Type { - CMPEQU, - CMPNEQU, - - BITAND, - BITOR, - BITXOR, - - SHL, - SHR, - }; - - Type m_type; - ::std::unique_ptr m_left; - ::std::unique_ptr m_right; - - ExprNode_BinOp(Type type, ::std::unique_ptr left, ::std::unique_ptr right): - m_type(type), - m_left( ::std::move(left) ), - m_right( ::std::move(right) ) - { - } - - virtual void visit(NodeVisitor& nv) override; -}; - -class NodeVisitor -{ -public: - void visit(const unique_ptr& cnode) { - if(cnode.get()) - cnode->visit(*this); - } - - virtual void visit(ExprNode_Block& node) { - for( auto& child : node.m_nodes ) - visit(child); - } - virtual void visit(ExprNode_Return& node) { - visit(node.m_value); - } - virtual void visit(ExprNode_LetBinding& node) { - // TODO: Handle recurse into Let pattern - visit(node.m_value); - } - virtual void visit(ExprNode_Assign& node) { - visit(node.m_slot); - visit(node.m_value); - } - virtual void visit(ExprNode_CallPath& node) { - for( auto& arg : node.m_args ) - visit(arg); - } - virtual void visit(ExprNode_CallMethod& node) { - visit(node.m_val); - for( auto& arg : node.m_args ) - visit(arg); - } - virtual void visit(ExprNode_CallObject& node) { - visit(node.m_val); - for( auto& arg : node.m_args ) - visit(arg); - } - virtual void visit(ExprNode_Match& node) { - visit(node.m_val); - for( auto& arm : node.m_arms ) - visit(arm.second); - } - virtual void visit(ExprNode_If& node) { - visit(node.m_cond); - visit(node.m_true); - visit(node.m_false); - } - - virtual void visit(ExprNode_Integer& node) { - // LEAF - } - virtual void visit(ExprNode_StructLiteral& node) { - visit(node.m_base_value); - for( auto& val : node.m_values ) - visit(val.second); - } - virtual void visit(ExprNode_NamedValue& node) { - // LEAF - } - - virtual void visit(ExprNode_Field& node) { - visit(node.m_obj); - } - virtual void visit(ExprNode_Cast& node) { - visit(node.m_value); - } - virtual void visit(ExprNode_BinOp& node) { - visit(node.m_left); - visit(node.m_right); - } -}; - -#endif - 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/expr.hpp b/src/ast/expr.hpp new file mode 100644 index 00000000..1ebd3090 --- /dev/null +++ b/src/ast/expr.hpp @@ -0,0 +1,369 @@ +/* + */ +#ifndef AST_EXPR_INCLUDED +#define AST_EXPR_INCLUDED + +#include +#include // unique_ptr +#include + +#include "../parse/tokentree.hpp" +#include "../types.hpp" +#include "pattern.hpp" + +namespace AST { + +using ::std::unique_ptr; + +class NodeVisitor; + +class ExprNode +{ +public: + virtual ~ExprNode() = 0; + + virtual void visit(NodeVisitor& nv) = 0; +}; + +struct ExprNode_Block: + public ExprNode +{ + ::std::vector< ::std::unique_ptr > m_nodes; + + ExprNode_Block(const ExprNode_Block& x) = delete; + ExprNode_Block(::std::vector< ::std::unique_ptr >&& nodes): + m_nodes( move(nodes) ) + { + } + virtual ~ExprNode_Block() override; + + virtual void visit(NodeVisitor& nv) override; +}; + +struct ExprNode_Macro: + public ExprNode +{ + ::std::string m_name; + ::TokenTree m_tokens; + + ExprNode_Macro(::std::string name, ::TokenTree&& tokens): + m_name(name), + m_tokens( move(tokens) ) + {} + + virtual void visit(NodeVisitor& nv) override; +}; + +// Return a value +struct ExprNode_Return: + public ExprNode +{ + unique_ptr m_value; + + ExprNode_Return(unique_ptr&& value): + m_value( move(value) ) + { + } + + virtual void visit(NodeVisitor& nv) override; +}; +struct ExprNode_LetBinding: + public ExprNode +{ + Pattern m_pat; + unique_ptr m_value; + + ExprNode_LetBinding(Pattern pat, unique_ptr&& value): + m_pat( move(pat) ), + m_value( move(value) ) + { + } + + virtual void visit(NodeVisitor& nv) override; +}; +struct ExprNode_Assign: + public ExprNode +{ + unique_ptr m_slot; + unique_ptr m_value; + + ExprNode_Assign(unique_ptr&& slot, unique_ptr&& value): + m_slot( move(slot) ), + m_value( move(value) ) + { + } + + virtual void visit(NodeVisitor& nv) override; +}; +struct ExprNode_CallPath: + public ExprNode +{ + Path m_path; + ::std::vector> m_args; + + ExprNode_CallPath(Path&& path, ::std::vector>&& args): + m_path( move(path) ), + m_args( move(args) ) + { + } + + virtual void visit(NodeVisitor& nv) override; +}; +struct ExprNode_CallMethod: + public ExprNode +{ + unique_ptr m_val; + PathNode m_method; + ::std::vector> m_args; + + ExprNode_CallMethod(unique_ptr&& obj, PathNode&& method, ::std::vector>&& args): + m_val( move(obj) ), + m_method( move(method) ), + m_args( move(args) ) + { + } + + virtual void visit(NodeVisitor& nv) override; +}; +// Call an object (Fn/FnMut/FnOnce) +struct ExprNode_CallObject: + public ExprNode +{ + unique_ptr m_val; + ::std::vector> m_args; + + ExprNode_CallObject(unique_ptr&& val, ::std::vector< unique_ptr >&& args): + m_val( move(val) ), + m_args( move(args) ) + { + } + virtual void visit(NodeVisitor& nv) override; +}; + +struct ExprNode_Match: + public ExprNode +{ + typedef ::std::vector< ::std::pair > > arm_t; + unique_ptr m_val; + arm_t m_arms; + + ExprNode_Match(unique_ptr&& val, arm_t&& arms): + m_val( ::std::move(val) ), + m_arms( ::std::move(arms) ) + { + } + virtual void visit(NodeVisitor& nv) override; +}; + +struct ExprNode_If: + public ExprNode +{ + unique_ptr m_cond; + unique_ptr m_true; + unique_ptr m_false; + + ExprNode_If(unique_ptr&& cond, unique_ptr&& true_code, unique_ptr&& false_code): + m_cond( ::std::move(cond) ), + m_true( ::std::move(true_code) ), + m_false( ::std::move(false_code) ) + { + } + virtual void visit(NodeVisitor& nv) override; +}; +// Literal integer +struct ExprNode_Integer: + public ExprNode +{ + enum eCoreType m_datatype; + uint64_t m_value; + + ExprNode_Integer(uint64_t value, enum eCoreType datatype): + m_datatype(datatype), + m_value(value) + { + } + + virtual void visit(NodeVisitor& nv) override; +}; +// Literal structure +struct ExprNode_StructLiteral: + public ExprNode +{ + typedef ::std::vector< ::std::pair< ::std::string, unique_ptr > > t_values; + Path m_path; + unique_ptr m_base_value; + t_values m_values; + + ExprNode_StructLiteral(Path path, unique_ptr&& base_value, t_values&& values ): + m_path( move(path) ), + m_base_value( move(base_value) ), + m_values( move(values) ) + {} + + virtual void visit(NodeVisitor& nv) override; +}; +// Variable / Constant +struct ExprNode_NamedValue: + public ExprNode +{ + Path m_path; + ExprNode_NamedValue(Path&& path): + m_path( ::std::move(path) ) + { + } + virtual void visit(NodeVisitor& nv) override; +}; +// Field dereference +struct ExprNode_Field: + public ExprNode +{ + ::std::unique_ptr m_obj; + ::std::string m_name; + + ExprNode_Field(::std::unique_ptr&& obj, ::std::string&& name): + m_obj( ::std::move(obj) ), + m_name( ::std::move(name) ) + { + } + virtual void visit(NodeVisitor& nv) override; +}; + +// Type cast ('as') +struct ExprNode_Cast: + public ExprNode +{ + unique_ptr m_value; + TypeRef m_type; + + ExprNode_Cast(unique_ptr&& value, TypeRef&& dst_type): + m_value( move(value) ), + m_type( move(dst_type) ) + { + } + virtual void visit(NodeVisitor& nv) override; +}; + +// Binary operation +struct ExprNode_BinOp: + public ExprNode +{ + enum Type { + CMPEQU, + CMPNEQU, + + BITAND, + BITOR, + BITXOR, + + SHL, + SHR, + }; + + Type m_type; + ::std::unique_ptr m_left; + ::std::unique_ptr m_right; + + ExprNode_BinOp(Type type, ::std::unique_ptr left, ::std::unique_ptr right): + m_type(type), + m_left( ::std::move(left) ), + m_right( ::std::move(right) ) + { + } + + virtual void visit(NodeVisitor& nv) override; +}; + +class NodeVisitor +{ +public: + void visit(const unique_ptr& cnode) { + if(cnode.get()) + cnode->visit(*this); + } + + virtual void visit(ExprNode_Block& node) { + for( auto& child : node.m_nodes ) + visit(child); + } + virtual void visit(ExprNode_Return& node) { + visit(node.m_value); + } + virtual void visit(ExprNode_LetBinding& node) { + // TODO: Handle recurse into Let pattern + visit(node.m_value); + } + virtual void visit(ExprNode_Assign& node) { + visit(node.m_slot); + visit(node.m_value); + } + virtual void visit(ExprNode_CallPath& node) { + for( auto& arg : node.m_args ) + visit(arg); + } + virtual void visit(ExprNode_CallMethod& node) { + visit(node.m_val); + for( auto& arg : node.m_args ) + visit(arg); + } + virtual void visit(ExprNode_CallObject& node) { + visit(node.m_val); + for( auto& arg : node.m_args ) + visit(arg); + } + virtual void visit(ExprNode_Match& node) { + visit(node.m_val); + for( auto& arm : node.m_arms ) + visit(arm.second); + } + virtual void visit(ExprNode_If& node) { + visit(node.m_cond); + visit(node.m_true); + visit(node.m_false); + } + + virtual void visit(ExprNode_Integer& node) { + // LEAF + } + virtual void visit(ExprNode_StructLiteral& node) { + visit(node.m_base_value); + for( auto& val : node.m_values ) + visit(val.second); + } + virtual void visit(ExprNode_NamedValue& node) { + // LEAF + } + + virtual void visit(ExprNode_Field& node) { + visit(node.m_obj); + } + virtual void visit(ExprNode_Cast& node) { + visit(node.m_value); + } + virtual void visit(ExprNode_BinOp& node) { + visit(node.m_left); + visit(node.m_right); + } +}; + +class Expr +{ + ::std::shared_ptr m_node; +public: + Expr(unique_ptr 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 +#include "../parse/parseerror.hpp" +#include + +namespace AST { + +// --- AST::PathNode +PathNode::PathNode(::std::string name, ::std::vector args): + m_name(name), + m_params(args) +{ +} +const ::std::string& PathNode::name() const +{ + return m_name; +} +const ::std::vector& PathNode::args() const +{ + return m_params; +} +SERIALISE_TYPE(PathNode::, "PathNode", { + s << m_name; + s << m_params; +}) + +// --- AST::Path +template +typename ::std::vector >::const_iterator find_named(const ::std::vector >& vec, const ::std::string& name) +{ + return ::std::find_if(vec.begin(), vec.end(), [&name](const Item& 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& 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& 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& 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& 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 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 +#include +#include + +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 m_node; + ::std::vector 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 node): + m_class(VALUE), + m_node( ::std::move(node) ) + {} + + struct TagTuple {}; + Pattern(TagTuple, ::std::vector sub_patterns): + m_class(TUPLE), + m_sub_patterns( ::std::move(sub_patterns) ) + {} + + struct TagEnumVariant {}; + Pattern(TagEnumVariant, Path path, ::std::vector 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& sub_patterns() { return m_sub_patterns; } + const ::std::vector& 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 #include -#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 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 #include +#include class Serialiser; @@ -53,6 +54,15 @@ public: end_array(); return *this; } + template + Serialiser& operator<<(const ::std::map& 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) { } -- cgit v1.2.3