diff options
author | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-25 17:59:48 +0800 |
---|---|---|
committer | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-25 17:59:48 +0800 |
commit | 76f199888f65fd21ffdae7c3518748098fdc0726 (patch) | |
tree | 6f89e10613cf536e1f95d923dc451451edca67b2 /src | |
parent | 175b02f7934d574778c87028edc9a6ebb97d690c (diff) | |
download | mrust-76f199888f65fd21ffdae7c3518748098fdc0726.tar.gz |
Hacked in dumping as rust
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 193 | ||||
-rw-r--r-- | src/ast/ast.hpp | 26 | ||||
-rw-r--r-- | src/ast/expr.cpp | 178 | ||||
-rw-r--r-- | src/ast/expr.hpp | 76 | ||||
-rw-r--r-- | src/ast/path.cpp | 25 | ||||
-rw-r--r-- | src/ast/path.hpp | 2 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 31 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 8 | ||||
-rw-r--r-- | src/convert/render.cpp | 5 | ||||
-rw-r--r-- | src/convert/typecheck_expr.cpp | 11 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 290 | ||||
-rw-r--r-- | src/include/main_bindings.hpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 12 | ||||
-rw-r--r-- | src/parse/expr.cpp | 49 | ||||
-rw-r--r-- | src/parse/root.cpp | 22 | ||||
-rw-r--r-- | src/types.cpp | 116 | ||||
-rw-r--r-- | src/types.hpp | 22 |
17 files changed, 865 insertions, 203 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 80bc3c57..7f3430f2 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -67,6 +67,87 @@ SERIALISE_TYPE_S(Pattern, { s.item(m_path);
});
+Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
+{
+ DEBUG("types={" << types << "}");
+ INDENT();
+
+ assert(m_params.n_params());
+
+ Impl ret( TypeParams(), m_trait, m_type );
+
+ auto resolver = [&](const char *name) {
+ int idx = m_params.find_name(name);
+ assert(idx >= 0);
+ return types[idx];
+ };
+
+ ret.m_trait.resolve_args(resolver);
+ ret.m_type.resolve_args(resolver);
+
+ for(const auto& fcn : m_functions)
+ {
+ TypeParams new_fcn_params = fcn.data.params();
+ for( auto& b : new_fcn_params.bounds() )
+ b.type().resolve_args(resolver);
+ TypeRef new_ret_type = fcn.data.rettype();
+ new_ret_type.resolve_args(resolver);
+ Function::Arglist new_args = fcn.data.args();
+ for( auto& t : new_args )
+ t.second.resolve_args(resolver);
+
+ ret.add_function( fcn.is_pub, fcn.name, Function( ::std::move(new_fcn_params), fcn.data.fcn_class(), ::std::move(new_ret_type), ::std::move(new_args), Expr() ) );
+ }
+
+ UNINDENT();
+ return ret;
+}
+
+::rust::option<Impl&> Impl::matches(const TypeRef& trait, const TypeRef& type)
+{
+ DEBUG("this = " << *this);
+ if( m_params.n_params() )
+ {
+ ::std::vector<TypeRef> param_types(m_params.n_params());
+ try
+ {
+ auto c = [&](const char* name,const TypeRef& ty){
+ int idx = m_params.find_name(name);
+ assert( idx >= 0 );
+ assert( (unsigned)idx < m_params.n_params() );
+ param_types[idx].merge_with( ty );
+ };
+ m_trait.match_args(trait, c);
+ m_type.match_args(type, c);
+
+ // Check that conditions match
+ // - TODO: Requires locating/checking trait implementations on types
+
+ // The above two will throw if matching failed, so if we get here, it's a match
+ for( auto& i : m_concrete_impls )
+ {
+ if( i.first == param_types )
+ {
+ return ::rust::option<Impl&>(i.second);
+ }
+ }
+ m_concrete_impls.push_back( make_pair(param_types, this->make_concrete(param_types)) );
+ return ::rust::option<Impl&>( m_concrete_impls.back().second );
+ }
+ catch( const ::std::runtime_error& e )
+ {
+ DEBUG("No match - " << e.what());
+ }
+ }
+ else
+ {
+ if( m_trait == trait && m_type == type )
+ {
+ return ::rust::option<Impl&>( *this );
+ }
+ }
+ return ::rust::option<Impl&>();
+}
::std::ostream& operator<<(::std::ostream& os, const Impl& impl)
{
@@ -89,6 +170,25 @@ Crate::Crate(): m_load_std(true)
{
}
+
+static void iterate_module(Module& mod, ::std::function<void(Module& mod)> fcn)
+{
+ fcn(mod);
+ for( auto& sm : mod.submods() )
+ iterate_module(sm.first, fcn);
+}
+
+void Crate::post_parse()
+{
+ // Iterate all modules, grabbing pointers to all impl blocks
+ iterate_module(m_root_module, [this](Module& mod){
+ for( auto& impl : mod.impls() )
+ {
+ m_impl_index.push_back( &impl );
+ }
+ });
+}
+
void Crate::iterate_functions(fcn_visitor_t* visitor)
{
m_root_module.iterate_functions(visitor, *this);
@@ -107,6 +207,8 @@ const Module& Crate::get_root_module(const ::std::string& name) const { ::rust::option<Impl&> Crate::find_impl(const TypeRef& trait, const TypeRef& type)
{
+ DEBUG("trait = " << trait << ", type = " << type);
+
// TODO: Support autoderef here? NO
if( trait.is_wildcard() && !type.is_path() )
{
@@ -118,10 +220,11 @@ const Module& Crate::get_root_module(const ::std::string& name) const { for( auto implptr : m_impl_index )
{
Impl& impl = *implptr;
- // TODO: Pass to impl for comparison (handles type params)
- if( impl.trait() == trait && impl.type() == type )
+ // TODO: What if there's two impls that match this combination?
+ ::rust::option<Impl&> oimpl = impl.matches(trait, type);
+ if( oimpl.is_some() )
{
- return ::rust::option<Impl&>(impl);
+ return oimpl.unwrap();
}
}
DEBUG("No impl of " << trait << " for " << type);
@@ -319,12 +422,12 @@ TypeRef Struct::get_field_type(const char *name, const ::std::vector<TypeRef>& a // TODO: Should the bounds be checked here? Or is the count sufficient?
for(const auto& f : m_fields)
{
- if( f.first == name )
+ if( f.name == name )
{
// Found it!
if( args.size() )
{
- TypeRef res = f.second;
+ TypeRef res = f.data;
res.resolve_args( [&](const char *argname){
for(unsigned int i = 0; i < m_params.n_params(); i ++)
{
@@ -338,7 +441,7 @@ TypeRef Struct::get_field_type(const char *name, const ::std::vector<TypeRef>& a }
else
{
- return f.second;
+ return f.data;
}
}
}
@@ -411,6 +514,84 @@ int TypeParams::find_name(const char* name) const return -1;
}
+bool TypeParams::check_params(Crate& crate, const ::std::vector<TypeRef>& types) const
+{
+ return check_params( crate, const_cast< ::std::vector<TypeRef>&>(types), false );
+}
+bool TypeParams::check_params(Crate& crate, ::std::vector<TypeRef>& types, bool allow_infer) const
+{
+ // XXX: Make sure all params are types
+ {
+ for(const auto& p : m_params)
+ assert(p.is_type());
+ }
+
+ // Check parameter counts
+ if( types.size() > m_params.size() )
+ {
+ throw ::std::runtime_error(FMT("Too many generic params ("<<types.size()<<" passed, expecting "<< m_params.size()<<")"));
+ }
+ else if( types.size() < m_params.size() )
+ {
+ if( allow_infer )
+ {
+ while( types.size() < m_params.size() )
+ {
+ types.push_back( m_params[types.size()].get_default() );
+ }
+ }
+ else
+ {
+ throw ::std::runtime_error(FMT("Too few generic params, (" << types.size() << " passed, expecting " << m_params.size() << ")"));
+ }
+ }
+ else
+ {
+ // Counts are good, time to validate types
+ }
+
+ for( unsigned int i = 0; i < types.size(); i ++ )
+ {
+ auto& type = types[i];
+ auto& param = m_params[i].name();
+ if( type.is_wildcard() )
+ {
+ for( const auto& bound : m_bounds )
+ {
+ if( bound.is_trait() && bound.name() == param )
+ {
+ const auto& trait = bound.type();
+ const auto& ty_traits = type.traits();
+
+ auto it = ::std::find(ty_traits.begin(), ty_traits.end(), trait);
+ if( it == ty_traits.end() )
+ {
+ throw ::std::runtime_error( FMT("No matching impl of "<<trait<<" for "<<type));
+ }
+ }
+ }
+ }
+ else
+ {
+ // Not a wildcard!
+ // Check that the type fits the bounds applied to it
+ for( const auto& bound : m_bounds )
+ {
+ if( bound.is_trait() && bound.name() == param )
+ {
+ const auto& trait = bound.type();
+ // Check if 'type' impls 'trait'
+ if( !crate.find_impl(type, trait).is_some() )
+ {
+ throw ::std::runtime_error( FMT("No matching impl of "<<trait<<" for "<<type));
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
::std::ostream& operator<<(::std::ostream& os, const TypeParams& tps)
{
//return os << "TypeParams({" << tps.m_params << "}, {" << tps.m_bounds << "})";
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 40a44b78..64726ecd 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -43,6 +43,7 @@ public: void setDefault(TypeRef type);
const ::std::string& name() const { return m_name; }
+ const TypeRef& get_default() const { return m_default; }
bool is_type() const { return m_class == TYPE; }
@@ -99,6 +100,8 @@ public: }
int find_name(const char* name) const;
+ bool check_params(Crate& crate, const ::std::vector<TypeRef>& types) const;
+ bool check_params(Crate& crate, ::std::vector<TypeRef>& types, bool allow_infer) const;
friend ::std::ostream& operator<<(::std::ostream& os, const TypeParams& tp);
SERIALISABLE_PROTOTYPES();
@@ -136,7 +139,7 @@ struct Item: template <typename T>
using ItemList = ::std::vector<Item<T> >;
-typedef ::std::pair< ::std::string, TypeRef> StructItem;
+typedef Item<TypeRef> StructItem;
class Crate;
@@ -207,8 +210,10 @@ public: m_type( move(type) ),
m_value( move(value) )
{}
-
+
+ const Class& s_class() const { return m_class; }
const TypeRef& type() const { return m_type; }
+ const Expr& value() const { return m_value; }
SERIALISABLE_PROTOTYPES();
};
@@ -224,7 +229,7 @@ public: CLASS_MUTMETHOD,
CLASS_VALMETHOD,
};
- typedef ::std::vector<StructItem> Arglist;
+ typedef ::std::vector< ::std::pair<AST::Pattern,TypeRef> > Arglist;
private:
Class m_fcn_class;
@@ -344,6 +349,8 @@ class Impl: ItemList<TypeRef> m_types;
ItemList<Function> m_functions;
+
+ ::std::vector< ::std::pair< ::std::vector<TypeRef>, Impl > > m_concrete_impls;
public:
Impl() {}
Impl(TypeParams params, TypeRef impl_type, TypeRef trait_type):
@@ -370,6 +377,10 @@ public: TypeRef& type() { return m_type; }
ItemList<Function>& functions() { return m_functions; }
ItemList<TypeRef>& types() { return m_types; }
+
+ Impl make_concrete(const ::std::vector<TypeRef>& types) const;
+
+ ::rust::option<Impl&> matches(const TypeRef& trait, const TypeRef& type);
friend ::std::ostream& operator<<(::std::ostream& os, const Impl& impl);
SERIALISABLE_PROTOTYPES();
@@ -492,14 +503,15 @@ public: Crate();
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;
-
::std::map< ::std::string, ExternCrate>& extern_crates() { return m_extern_crates; }
+
+ const Module& root_module() const { return m_root_module; }
+ const Module& get_root_module(const ::std::string& name) const;
const ::std::map< ::std::string, ExternCrate>& extern_crates() const { return m_extern_crates; }
+ void post_parse();
+
::rust::option<Impl&> find_impl(const TypeRef& trait, const TypeRef& type);
Function& lookup_method(const TypeRef& type, const char *name);
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 1009709b..91f77633 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -10,7 +10,10 @@ void Expr::visit_nodes(NodeVisitor& v) } ::std::ostream& operator<<(::std::ostream& os, const Expr& pat) { - return os << "Expr(TODO)"; + if( pat.m_node.get() ) + return os << *pat.m_node; + else + return os << "/* null */"; } SERIALISE_TYPE(Expr::, "Expr", { s.item(m_node); @@ -23,6 +26,16 @@ SERIALISE_TYPE(Expr::, "Expr", { m_node.reset(); }); +::std::ostream& operator<<(::std::ostream& os, const ExprNode& node) +{ + if( &node != nullptr ) { + node.print(os); + } + else { + os << "/* NULLPTR */"; + } + return os; +} ::std::unique_ptr<ExprNode> ExprNode::from_deserialiser(Deserialiser& d) { ::std::string tag = d.start_object(); @@ -59,145 +72,151 @@ SERIALISE_TYPE(Expr::, "Expr", { ExprNode::~ExprNode() { } +#define NODE(class, serialise, _print) void class::visit(NodeVisitor& nv) { nv.visit(*this); } SERIALISE_TYPE_S(class, serialise) void class::print(::std::ostream& os) const _print + ExprNode_Block::~ExprNode_Block() { } -void ExprNode_Block::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Block, { +NODE(ExprNode_Block, { s.item(m_nodes); +},{ + os << "{"; + for(const auto& n : m_nodes) + os << *n << ";"; + os << "}"; }) -void ExprNode_Macro::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Macro, { +NODE(ExprNode_Macro, { s.item(m_name); //s.item(m_tokens); +},{ + os << m_name << "!(" << ")"; }) -void ExprNode_Return::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Return, { +NODE(ExprNode_Return, { s.item(m_value); +},{ + os << "return " << *m_value; }) -void ExprNode_LetBinding::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_LetBinding, { +NODE(ExprNode_LetBinding, { s.item(m_pat); s.item(m_value); +},{ + os << "let " << m_pat << ": " << m_type << " = " << *m_value; }) -void ExprNode_Assign::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Assign, { +NODE(ExprNode_Assign, { s.item(m_slot); s.item(m_value); +},{ + os << *m_slot << " = " << *m_value; }) -void ExprNode_CallPath::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_CallPath, { +NODE(ExprNode_CallPath, { s.item(m_path); s.item(m_args); +},{ + os << m_path << "("; + for(const auto& a : m_args) { + os << *a << ","; + } + os << ")"; }) -void ExprNode_CallMethod::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_CallMethod, { +NODE(ExprNode_CallMethod, { s.item(m_val); s.item(m_method); s.item(m_args); +},{ + os << "(" << *m_val << ")." << m_method << "("; + for(const auto& a : m_args) { + os << *a << ","; + } + os << ")"; }) -void ExprNode_CallObject::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_CallObject, { +NODE(ExprNode_CallObject, { s.item(m_val); s.item(m_args); +},{ + os << "(" << *m_val << ")("; + for(const auto& a : m_args) { + os << *a << ","; + } + os << ")"; }) -void ExprNode_Match::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Match, { +NODE(ExprNode_Match, { s.item(m_val); s.item(m_arms); +},{ + os << "match ("<<*m_val<<") {"; + for(const auto& arm : m_arms) + { + os << " " << arm.first << " => " << *arm.second << ","; + } + os << "}"; }) -void ExprNode_If::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_If, { +NODE(ExprNode_If, { s.item(m_cond); s.item(m_true); s.item(m_false); +},{ + os << "if " << *m_cond << " { " << *m_true << " } else { " << *m_false << " }"; }) -void ExprNode_Integer::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Integer, { +NODE(ExprNode_Integer, { s % m_datatype; s.item(m_value); +},{ + os << m_value; }) -void ExprNode_StructLiteral::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_StructLiteral, { +NODE(ExprNode_StructLiteral, { s.item(m_path); s.item(m_base_value); s.item(m_values); +},{ + os << "/* todo: sl */"; }) -void ExprNode_Tuple::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Tuple, { +NODE(ExprNode_Tuple, { s.item(m_values); +},{ + os << "("; + for(const auto& a : m_values) { + os << *a << ","; + } + os << ")"; }) -void ExprNode_NamedValue::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_NamedValue, { +NODE(ExprNode_NamedValue, { s.item(m_path); +},{ + os << m_path; }) -void ExprNode_Field::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Field, { +NODE(ExprNode_Field, { s.item(m_obj); s.item(m_name); +},{ + os << "(" << *m_obj << ")." << m_name; }) -void ExprNode_Deref::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Deref, { +NODE(ExprNode_Deref, { s.item(m_value); +},{ + os << "*(" << *m_value << ")"; }); -void ExprNode_Cast::visit(NodeVisitor& nv) { - nv.visit(*this); -} -SERIALISE_TYPE_S(ExprNode_Cast, { +NODE(ExprNode_Cast, { s.item(m_value); s.item(m_type); +},{ + os << "(" << *m_value << " as " << m_type << ")"; }) -void ExprNode_BinOp::visit(NodeVisitor& nv) { - nv.visit(*this); -} void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) { switch(t) { @@ -222,10 +241,23 @@ void operator%(::Deserialiser& s, ExprNode_BinOp::Type& t) { throw ::std::runtime_error(""); #undef _ } -SERIALISE_TYPE_S(ExprNode_BinOp, { +NODE(ExprNode_BinOp, { s % m_type; s.item(m_left); s.item(m_right); +},{ + os << "(" << *m_left << " "; + switch(m_type) + { + case CMPEQU: os << "=="; break; + case CMPNEQU: os << "!="; break; + case BITAND: os << "&"; break; + case BITOR: os << "|"; break; + case BITXOR: os << "^"; break; + case SHR: os << ">>"; break; + case SHL: os << "<<"; break; + } + os << " " << *m_right << ")"; }) diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index f1d16af0..2744b75e 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -25,12 +25,16 @@ public: virtual ~ExprNode() = 0; virtual void visit(NodeVisitor& nv) = 0; + virtual void print(::std::ostream& os) const = 0; TypeRef& get_res_type() { return m_res_type; } + friend ::std::ostream& operator<<(::std::ostream& os, const ExprNode& node); static ::std::unique_ptr<ExprNode> from_deserialiser(Deserialiser& d); }; +#define NODE_METHODS() virtual void visit(NodeVisitor& nv) override; virtual void print(::std::ostream& os) const override; SERIALISABLE_PROTOTYPES(); + struct ExprNode_Block: public ExprNode { @@ -43,9 +47,7 @@ struct ExprNode_Block: } virtual ~ExprNode_Block() override; - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; struct ExprNode_Macro: @@ -60,9 +62,7 @@ struct ExprNode_Macro: m_tokens( move(tokens) ) {} - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Return a value @@ -77,9 +77,7 @@ struct ExprNode_Return: { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; struct ExprNode_LetBinding: public ExprNode @@ -96,9 +94,7 @@ struct ExprNode_LetBinding: { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; struct ExprNode_Assign: public ExprNode @@ -113,9 +109,7 @@ struct ExprNode_Assign: { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; struct ExprNode_CallPath: public ExprNode @@ -130,9 +124,7 @@ struct ExprNode_CallPath: { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; struct ExprNode_CallMethod: public ExprNode @@ -149,9 +141,7 @@ struct ExprNode_CallMethod: { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Call an object (Fn/FnMut/FnOnce) struct ExprNode_CallObject: @@ -166,9 +156,7 @@ struct ExprNode_CallObject: m_args( move(args) ) { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; struct ExprNode_Match: @@ -184,9 +172,7 @@ struct ExprNode_Match: m_arms( ::std::move(arms) ) { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; struct ExprNode_If: @@ -203,9 +189,7 @@ struct ExprNode_If: m_false( ::std::move(false_code) ) { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Literal integer struct ExprNode_Integer: @@ -221,9 +205,7 @@ struct ExprNode_Integer: { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Literal structure struct ExprNode_StructLiteral: @@ -241,9 +223,7 @@ struct ExprNode_StructLiteral: m_values( move(values) ) {} - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Tuple struct ExprNode_Tuple: @@ -256,9 +236,7 @@ struct ExprNode_Tuple: m_values( ::std::move(vals) ) {} - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Variable / Constant struct ExprNode_NamedValue: @@ -271,9 +249,7 @@ struct ExprNode_NamedValue: m_path( ::std::move(path) ) { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Field dereference struct ExprNode_Field: @@ -288,9 +264,7 @@ struct ExprNode_Field: m_name( ::std::move(name) ) { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Pointer dereference @@ -305,9 +279,7 @@ struct ExprNode_Deref: { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Type cast ('as') @@ -323,9 +295,7 @@ struct ExprNode_Cast: m_type( move(dst_type) ) { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; // Binary operation @@ -356,9 +326,7 @@ struct ExprNode_BinOp: { } - virtual void visit(NodeVisitor& nv) override; - - SERIALISABLE_PROTOTYPES(); + NODE_METHODS(); }; class NodeVisitor diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 6daaf406..cd068694 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -259,7 +259,7 @@ void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std unsigned int idx = 0; for( idx = 0; idx < ent.variants().size(); idx ++ ) { - if( ent.variants()[idx].first == name ) { + if( ent.variants()[idx].name == name ) { break; } } @@ -311,6 +311,27 @@ bool Path::operator==(const Path& x) const return m_class == x.m_class && m_crate == x.m_crate && m_nodes == x.m_nodes; } +void Path::print_pretty(::std::ostream& os) const +{ + switch(m_class) + { + case Path::RELATIVE: + os << "self"; + for(const auto& n : m_nodes) + os << n; + break; + case Path::ABSOLUTE: + if( m_crate != "" ) + os << "::" << m_crate; + for(const auto& n : m_nodes) + os << n; + break; + case Path::LOCAL: + os << m_nodes[0].name(); + break; + } +} + ::std::ostream& operator<<(::std::ostream& os, const Path& path) { #if PRETTY_PATH_PRINT @@ -322,7 +343,7 @@ bool Path::operator==(const Path& x) const os << n; break; case Path::ABSOLUTE: - os << "["<<path.m_crate<<"]"; + os << "{"<<path.m_crate<<"}"; for(const auto& n : path.m_nodes) os << n; break; diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 5325f8ef..cfdf16c2 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -38,6 +38,7 @@ public: const ::std::vector<TypeRef>& args() const; bool operator==(const PathNode& x) const; + void print_pretty(::std::ostream& os) const; friend ::std::ostream& operator<<(::std::ostream& os, const PathNode& pn); SERIALISABLE_PROTOTYPES(); @@ -183,6 +184,7 @@ public: bool operator==(const Path& x) const; SERIALISABLE_PROTOTYPES(); + void print_pretty(::std::ostream& os) const; friend ::std::ostream& operator<<(::std::ostream& os, const Path& path); friend ::Serialiser& operator<<(Serialiser& s, Path::Class pc); friend void operator>>(Deserialiser& s, Path::Class& pc); diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp index 70fc77f4..82db2b7c 100644 --- a/src/ast/pattern.hpp +++ b/src/ast/pattern.hpp @@ -31,6 +31,37 @@ private: unique_ptr<ExprNode> m_node; ::std::vector<Pattern> m_sub_patterns; public: + Pattern(Pattern&& o): + m_class(o.m_class), + m_binding( move(o.m_binding) ), + m_path( move(o.m_path) ), + m_node( move(o.m_node) ), + m_sub_patterns( move(o.m_sub_patterns) ) + { } + + Pattern(const Pattern& o): + m_class(o.m_class), + m_binding(o.m_binding), + m_path(o.m_path), + m_node(nullptr), + m_sub_patterns(o.m_sub_patterns) + { + if( o.m_node.get() ) { + DEBUG("Cloning " << o); + throw ::std::runtime_error(FMT("Cloning pattern with node : " << o)); + } + } + + Pattern& operator=(Pattern o) + { + m_class = o.m_class, + m_binding = move(o.m_binding); + m_path = move(o.m_path); + m_node = move(o.m_node); + m_sub_patterns = move(o.m_sub_patterns); + return *this; + } + Pattern(): m_class(ANY) {} diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index 1c232b33..26ef2191 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -151,8 +151,8 @@ void CASTIterator::handle_function(AST::Path path, AST::Function& fcn) for( auto& arg : fcn.args() ) { handle_type(arg.second); - AST::Pattern pat(AST::Pattern::TagBind(), arg.first); - handle_pattern( pat, arg.second ); + // TODO: Check if pattern is irrefutable? + handle_pattern( arg.first, arg.second ); } if( fcn.code().is_valid() ) @@ -193,7 +193,7 @@ void CASTIterator::handle_struct(AST::Path path, AST::Struct& str) start_scope(); handle_params( str.params() ); for( auto& f : str.fields() ) - handle_type( f.second ); + handle_type( f.data ); end_scope(); } void CASTIterator::handle_enum(AST::Path path, AST::Enum& enm) @@ -201,7 +201,7 @@ void CASTIterator::handle_enum(AST::Path path, AST::Enum& enm) start_scope(); handle_params( enm.params() ); for( auto& f : enm.variants() ) - handle_type( f.second ); + handle_type( f.data ); end_scope(); } void CASTIterator::handle_trait(AST::Path path, AST::Trait& trait) diff --git a/src/convert/render.cpp b/src/convert/render.cpp index 338fdd06..ce64e600 100644 --- a/src/convert/render.cpp +++ b/src/convert/render.cpp @@ -24,7 +24,7 @@ void Render_CStruct(::std::ostream& os, const AST::CStruct& str) for(auto& f : str.fields())
{
os << "\t";
- Render_Type(os, f.second, f.first.c_str());
+ Render_Type(os, f.data, f.name.c_str());
os << ";\n";
}
os << "}\n";
@@ -48,7 +48,8 @@ void Render_Crate(::std::ostream& os, const AST::Flat& crate) if( !is_first )
os << ", ";
is_first = false;
- Render_Type(os, f.second, f.first.c_str());
+ // TODO: handle pattern
+ //Render_Type(os, f.second, f.first.c_str());
}
os << ")\n{\n";
// Dump expression AST
diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index c647ed54..3c39d9a4 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -184,8 +184,7 @@ void CTypeChecker::handle_function(AST::Path path, AST::Function& fcn) for( auto& arg : fcn.args() ) { handle_type(arg.second); - AST::Pattern pat(AST::Pattern::TagBind(), arg.first); - handle_pattern( pat, arg.second ); + handle_pattern( arg.first, arg.second ); } CTC_NodeVisitor nv(*this); @@ -230,8 +229,8 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node) auto idx = p.bound_idx(); // Enum variant: // - Check that this variant takes no arguments - if( !enm.variants()[idx].second.is_unit() ) - throw ::std::runtime_error( FMT("Used a non-unit variant as a raw value - " << enm.variants()[idx].second)); + if( !enm.variants()[idx].data.is_unit() ) + throw ::std::runtime_error( FMT("Used a non-unit variant as a raw value - " << enm.variants()[idx].data)); // - Set output type to the enum (wildcard params, not default) AST::Path tp = p; tp.nodes().pop_back(); @@ -523,8 +522,8 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node) // 2. Create a pattern from the argument types and the format of the variant DEBUG("argtypes = [" << argtypes << "]"); ::std::vector<TypeRef> item_args(enm.params().n_params()); - DEBUG("variant type = " << var.second << ""); - var.second.match_args( + DEBUG("variant type = " << var.data << ""); + var.data.match_args( TypeRef(TypeRef::TagTuple(), argtypes), [&](const char *name, const TypeRef& t) { DEBUG("Binding " << name << " to type " << t); diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp new file mode 100644 index 00000000..1a0b426d --- /dev/null +++ b/src/dump_as_rust.cpp @@ -0,0 +1,290 @@ +/* + * MRustC - Mutabah's Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * dump_as_rust.cpp + * - Dumps the AST of a crate as rust code (annotated) + */ +#include "ast/expr.hpp" +#include <main_bindings.hpp> + +class RustPrinter: + public AST::NodeVisitor +{ + ::std::ostream& m_os; + int m_indent_level; +public: + RustPrinter(::std::ostream& os): + m_os(os), + m_indent_level(0) + {} + + void handle_module(const AST::Module& mod); + void handle_struct(const AST::Struct& s); + void handle_enum(const AST::Enum& s); + void handle_trait(const AST::Trait& s); + + void handle_function(const AST::Item<AST::Function>& f); + +private: + void print_params(const AST::TypeParams& params); + void print_bounds(const AST::TypeParams& params); + void print_pattern(const AST::Pattern& p); + + void inc_indent(); + RepeatLitStr indent(); + void dec_indent(); +}; + +void Dump_Rust(const char *Filename, const AST::Crate& crate) +{ + ::std::ofstream os(Filename); + RustPrinter printer(os); + printer.handle_module(crate.root_module()); +} + +void RustPrinter::handle_module(const AST::Module& mod) +{ + m_os << "\n"; + + for( const auto& sm : mod.submods() ) + { + m_os << indent() << (sm.second ? "pub " : "") << "mod " << sm.first.name() << " {\n"; + inc_indent(); + handle_module(sm.first); + dec_indent(); + m_os << indent() << "}\n"; + m_os << "\n"; + } + + + for( const auto& i : mod.structs() ) + { + m_os << indent() << (i.is_pub ? "pub " : "") << "struct " << i.name; + handle_struct(i.data); + } + + for( const auto& i : mod.enums() ) + { + m_os << indent() << (i.is_pub ? "pub " : "") << "enum " << i.name; + handle_enum(i.data); + } + + for( const auto& i : mod.traits() ) + { + m_os << indent() << (i.is_pub ? "pub " : "") << "trait " << i.name; + handle_trait(i.data); + } + + for( const auto& i : mod.statics() ) + { + m_os << indent() << (i.is_pub ? "pub " : ""); + switch( i.data.s_class() ) + { + case AST::Static::CONST: m_os << "const "; break; + case AST::Static::STATIC: m_os << "static "; break; + case AST::Static::MUT: m_os << "static mut "; break; + } + m_os << i.name << ": " << i.data.type() << " = "; + //handle_expr(i.data.value()); + m_os << ";\n"; + } + + for( const auto& i : mod.functions() ) + { + handle_function(i); + } +} + +void RustPrinter::print_params(const AST::TypeParams& params) +{ + if( params.n_params() > 0 ) + { + bool is_first = true; + m_os << "<"; + for( const auto& p : params.params() ) + { + if( !is_first ) + m_os << ", "; + m_os << p.name(); + is_first = false; + } + m_os << ">"; + } +} + +void RustPrinter::print_bounds(const AST::TypeParams& params) +{ + if( params.bounds().size() ) + { + m_os << indent() << "where\n"; + inc_indent(); + bool is_first = true; + + for( const auto& b : params.bounds() ) + { + if( !is_first ) + m_os << ", "; + is_first = false; + + m_os << indent() << b.name() << ": "; + m_os << "\n"; + } + + dec_indent(); + } +} + +void RustPrinter::print_pattern(const AST::Pattern& p) +{ + if( p.binding() != "" && p.type() == AST::Pattern::ANY ) { + m_os << p.binding(); + return; + } + + if( p.binding() != "" ) + m_os << p.binding() << " @ "; + switch(p.type()) + { + case AST::Pattern::ANY: + m_os << "_"; + break; + case AST::Pattern::VALUE: + m_os << p.node(); + break; + case AST::Pattern::MAYBE_BIND: + m_os << "/*?*/" << p.path(); + break; + case AST::Pattern::TUPLE_STRUCT: + m_os << p.path(); + case AST::Pattern::TUPLE: + m_os << "("; + for(const auto& sp : p.sub_patterns()) + print_pattern(sp); + m_os << ")"; + break; + } +} + +void RustPrinter::handle_struct(const AST::Struct& s) +{ + print_params(s.params()); + + if( s.fields().size() == 0 ) + { + m_os << "()\n"; + print_bounds(s.params()); + m_os << indent() << ";\n"; + } + else if( s.fields().size() == 1 && s.fields()[0].name == "" ) + { + m_os << "(" << "" <<")\n"; + print_bounds(s.params()); + m_os << indent() << ";\n"; + } + else + { + m_os << "\n"; + print_bounds(s.params()); + + m_os << indent() << "{\n"; + inc_indent(); + for( const auto& i : s.fields() ) + { + m_os << indent() << (i.is_pub ? "pub " : "") << i.name << ": " << i.data.print_pretty() << "\n"; + } + dec_indent(); + m_os << indent() << "}\n"; + } + m_os << "\n"; +} + +void RustPrinter::handle_enum(const AST::Enum& s) +{ + print_params(s.params()); + m_os << "\n"; + print_bounds(s.params()); + + m_os << indent() << "{\n"; + inc_indent(); + for( const auto& i : s.variants() ) + { + m_os << indent() << i.name; + if( i.data.sub_types().size() ) + m_os << i.data.print_pretty(); + m_os << ",\n"; + } + dec_indent(); + m_os << indent() << "}\n"; + m_os << "\n"; +} + +void RustPrinter::handle_trait(const AST::Trait& s) +{ + print_params(s.params()); + m_os << "\n"; + print_bounds(s.params()); + + m_os << indent() << "{\n"; + inc_indent(); + + for( const auto& i : s.types() ) + { + m_os << indent() << "type " << i.name << "\n"; + } + for( const auto& i : s.functions() ) + { + handle_function(i); + } + + dec_indent(); + m_os << indent() << "}\n"; + m_os << "\n"; +} + +void RustPrinter::handle_function(const AST::Item<AST::Function>& f) +{ + m_os << indent() << (f.is_pub ? "pub " : "") << "fn " << f.name; + print_params(f.data.params()); + m_os << "("; + bool is_first = true; + for( const auto& a : f.data.args() ) + { + if( !is_first ) + m_os << ", "; + print_pattern( a.first ); + m_os << ": " << a.second.print_pretty(); + is_first = false; + } + m_os << ")"; + if( !f.data.rettype().is_unit() ) + { + m_os << " -> " << f.data.rettype().print_pretty(); + } + + if( f.data.code().is_valid() ) + { + m_os << "\n"; + print_bounds(f.data.params()); + + m_os << indent() << f.data.code() << "\n"; + } + else + { + print_bounds(f.data.params()); + m_os << ";\n"; + } +} + +void RustPrinter::inc_indent() +{ + m_indent_level ++; +} +RepeatLitStr RustPrinter::indent() +{ + return RepeatLitStr { " ", m_indent_level }; +} +void RustPrinter::dec_indent() +{ + m_indent_level --; +} diff --git a/src/include/main_bindings.hpp b/src/include/main_bindings.hpp index b7161edd..fef57184 100644 --- a/src/include/main_bindings.hpp +++ b/src/include/main_bindings.hpp @@ -12,5 +12,7 @@ extern void Typecheck_GenericParams(AST::Crate& crate); extern void Typecheck_Expr(AST::Crate& crate); extern AST::Flat Convert_Flatten(const AST::Crate& crate); +extern void Dump_Rust(const char *Filename, const AST::Crate& crate); + #endif diff --git a/src/main.cpp b/src/main.cpp index 3c2a2787..9e533139 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -75,11 +75,12 @@ int main(int argc, char *argv[]) outfile += ".o";
}
- Serialiser_TextTree s_tt(::std::cout);
- Serialiser& s = s_tt;
+ //Serialiser_TextTree s_tt(::std::cout);
+ //Serialiser& s = s_tt;
try
{
AST::Crate crate = Parse_Crate(infile);
+ crate.post_parse();
//s << crate;
@@ -98,6 +99,8 @@ int main(int argc, char *argv[]) // > Forward pass first
Typecheck_Expr(crate);
+ Dump_Rust( FMT(outfile << ".rs").c_str(), crate );
+
if( strcmp(emit_type, "ast") == 0 )
{
::std::ofstream os(outfile);
@@ -116,5 +119,10 @@ int main(int argc, char *argv[]) ::std::cerr << "Parser Error: " << e.what() << ::std::endl;
return 2;
}
+ catch(const ::std::exception& e)
+ {
+ ::std::cerr << "Misc Error: " << e.what() << ::std::endl;
+ return 2;
+ }
return 0;
}
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index e91a8b26..91cedabd 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -325,30 +325,43 @@ ExprNodeP Parse_IfStmt(TokenStream& lex) return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) );
}
+ExprNodeP Parse_Expr_Match(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ // 1. Get expression
+ ExprNodeP switch_val = Parse_Expr1(lex);
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
+
+ ::std::vector< ::std::pair<AST::Pattern, ExprNodeP> > arms;
+ do {
+ if( GET_TOK(tok, lex) == TOK_BRACE_CLOSE )
+ break;
+ lex.putback(tok);
+ AST::Pattern pat = Parse_Pattern(lex);
+
+ GET_CHECK_TOK(tok, lex, TOK_FATARROW);
+
+ bool opt_semicolon = false;
+ ExprNodeP val = Parse_Stmt(lex, opt_semicolon);
+
+ arms.push_back( ::std::make_pair( ::std::move(pat), ::std::move(val) ) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+ return NEWNODE( AST::ExprNode_Match, ::std::move(switch_val), ::std::move(arms) );
+}
+
// 0.5: Blocks
ExprNodeP Parse_ExprBlocks(TokenStream& lex)
{
+ TRACE_FUNCTION;
Token tok;
switch( GET_TOK(tok, lex) )
{
- case TOK_RWORD_MATCH: {
- // 1. Get expression
- ExprNodeP switch_val = Parse_Expr1(lex);
- GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
- ::std::vector< ::std::pair<AST::Pattern, ::std::unique_ptr<ExprNode>> > arms;
- do {
- if( GET_TOK(tok, lex) == TOK_BRACE_CLOSE )
- break;
- lex.putback(tok);
- AST::Pattern pat = Parse_Pattern(lex);
- GET_CHECK_TOK(tok, lex, TOK_FATARROW);
- bool opt_semicolon = false;
- ExprNodeP val = Parse_Stmt(lex, opt_semicolon);
- arms.push_back( ::std::make_pair( ::std::move(pat), ::std::move(val) ) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
- return NEWNODE( AST::ExprNode_Match, ::std::move(switch_val), ::std::move(arms) );
- }
+ case TOK_RWORD_MATCH:
+ return Parse_Expr_Match(lex);
case TOK_RWORD_IF:
// TODO: if let
return Parse_IfStmt(lex);
diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 2c559d84..2b4126e9 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -8,6 +8,8 @@ unsigned int TraceLog::depth = 0;
+extern AST::Pattern Parse_Pattern(TokenStream& lex);
+
::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex)
{
TRACE_FUNCTION;
@@ -317,19 +319,20 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false) {
// Unbound method
}
- ::std::vector<AST::StructItem> args;
+
+ AST::Function::Arglist args;
if( tok.type() != TOK_PAREN_CLOSE )
{
lex.putback(tok);
// Argument list
do {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
+ AST::Pattern pat = Parse_Pattern(lex);
+
GET_CHECK_TOK(tok, lex, TOK_COLON);
TypeRef type = Parse_Type(lex);
- args.push_back( ::std::make_pair(name, type) );
- tok = lex.getToken();
- } while( tok.type() == TOK_COMMA );
+
+ args.push_back( ::std::make_pair( ::std::move(pat), ::std::move(type) ) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_PAREN_CLOSE);
}
else {
@@ -437,11 +440,12 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons ::std::vector<AST::StructItem> items;
while( (tok = lex.getToken()).type() != TOK_BRACE_CLOSE )
{
+ bool is_pub = false;
CHECK_TOK(tok, TOK_IDENT);
::std::string name = tok.str();
GET_CHECK_TOK(tok, lex, TOK_COLON);
TypeRef type = Parse_Type(lex);
- items.push_back( ::std::make_pair(name, type) );
+ items.push_back( AST::StructItem( ::std::move(name), ::std::move(type), is_pub ) );
tok = lex.getToken();
if(tok.type() == TOK_BRACE_CLOSE)
break;
@@ -556,11 +560,11 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const ::std::vector<AST::MetaItem> met } while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_PAREN_CLOSE);
GET_TOK(tok, lex);
- variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagTuple(), ::std::move(types))) );
+ variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagTuple(), ::std::move(types)), true) );
}
else
{
- variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagUnit())) );
+ variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagUnit()), true) );
}
if( tok.type() != TOK_COMMA )
diff --git a/src/types.cpp b/src/types.cpp index 33b564dd..445f394c 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -64,6 +64,7 @@ bool TypeRef::deref(bool is_implicit) case TypeRef::ASSOCIATED: throw ::std::runtime_error("TODO: TypeRef::deref on ASSOCIATED"); } + throw ::std::runtime_error("BUGCHECK: Fell off end of TypeRef::deref"); } /// Merge the contents of the passed type with this type @@ -72,14 +73,15 @@ bool TypeRef::deref(bool is_implicit) void TypeRef::merge_with(const TypeRef& other) { // Ignore if other is wildcard - if( other.m_class == TypeRef::ANY ) { - assert(other.m_inner_types.size() == 0 && "TODO: merge_with on bounded _"); - return; - } + //if( other.m_class == TypeRef::ANY ) { + // assert(other.m_inner_types.size() == 0 && "TODO: merge_with on bounded _"); + // return; + //} - // If this is a wildcard, then replace with the othet type + // If this is a wildcard, then replace with the other type if( m_class == TypeRef::ANY ) { - assert(m_inner_types.size() == 0 && "TODO: merge_with on bounded _"); + if( m_inner_types.size() && m_inner_types.size() != other.m_inner_types.size() ) + throw ::std::runtime_error("TypeRef::merge_with - Handle bounded wildcards"); *this = other; return; } @@ -177,16 +179,19 @@ void TypeRef::resolve_args(::std::function<TypeRef(const char*)> fcn) /// This is used to handle extracting types passsed to methods/enum variants void TypeRef::match_args(const TypeRef& other, ::std::function<void(const char*,const TypeRef&)> fcn) const { - // If the other type is a wildcard, early return - // - TODO - Might want to restrict the other type to be of the same form as this type - if( other.m_class == TypeRef::ANY ) - return; // If this type is a generic, then call the closure with the other type if( m_class == TypeRef::GENERIC ) { fcn( m_path[0].name().c_str(), other ); return ; } + // If the other type is a wildcard, early return + // - TODO - Might want to restrict the other type to be of the same form as this type + if( other.m_class == TypeRef::ANY ) + return; + + DEBUG("this = " << *this << ", other = " << other); + // Any other case, it's a "pattern" match if( m_class != other.m_class ) throw ::std::runtime_error("Type mismatch (class)"); @@ -215,11 +220,35 @@ void TypeRef::match_args(const TypeRef& other, ::std::function<void(const char*, m_inner_types[0].match_args( other.m_inner_types[0], fcn ); break; case TypeRef::ARRAY: - throw ::std::runtime_error("TODO: TypeRef::match_args on ARRAY"); + m_inner_types[0].match_args( other.m_inner_types[0], fcn ); + if(m_size_expr.get()) + { + throw ::std::runtime_error("TODO: Sized array match_args"); + } + break; case TypeRef::GENERIC: throw ::std::runtime_error("Encountered GENERIC in match_args"); case TypeRef::PATH: - throw ::std::runtime_error("TODO: TypeRef::match_args on PATH"); + if( m_path.size() != other.m_path.size() ) + throw ::std::runtime_error("Type mismatch (path size)"); + for( unsigned int i = 0; i < m_path.size(); i++ ) + { + auto& pn1 = m_path[i]; + auto& pn2 = other.m_path[i]; + if( pn1.name() != pn2.name() ) + throw ::std::runtime_error("Type mismatch (path component)"); + + if( pn1.args().size() != pn2.args().size() ) + throw ::std::runtime_error("Type mismatch (path component param count)"); + + for( unsigned int j = 0; j < pn1.args().size(); j ++ ) + { + auto& t1 = pn1.args()[j]; + auto& t2 = pn2.args()[j]; + t1.match_args( t2, fcn ); + } + } + break; case TypeRef::ASSOCIATED: throw ::std::runtime_error("TODO: TypeRef::match_args on ASSOCIATED"); } @@ -309,14 +338,14 @@ bool TypeRef::operator==(const TypeRef& x) const } ::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr) { - os << "TypeRef("; + //os << "TypeRef("; switch(tr.m_class) { case TypeRef::ANY: //os << "TagAny"; os << "_"; if( tr.m_inner_types.size() ) { - os << ": {" << tr.m_inner_types << "}"; + os << ": " << tr.m_inner_types << ""; } break; case TypeRef::UNIT: @@ -340,21 +369,19 @@ bool TypeRef::operator==(const TypeRef& x) const os << "*" << (tr.m_is_inner_mutable ? "mut" : "const") << " " << tr.m_inner_types[0]; break; case TypeRef::ARRAY: - os << "TagSizedArray, " << tr.m_inner_types[0] << ", " << tr.m_size_expr; + os << "[" << tr.m_inner_types[0] << "; " << tr.m_size_expr << "]"; break; case TypeRef::GENERIC: - os << "TagArg, " << tr.m_path[0].name(); + os << "/* arg */ " << tr.m_path[0].name(); break; case TypeRef::PATH: - //os << "TagPath, " << tr.m_path; os << tr.m_path; break; case TypeRef::ASSOCIATED: - //os << "TagAssoc, <" << tr.m_inner_types[0] << " as " << tr.m_inner_types[1] << ">::" << tr.m_path[0].name(); os << "<" << tr.m_inner_types[0] << " as " << tr.m_inner_types[1] << ">::" << tr.m_path[0].name(); break; } - os << ")"; + //os << ")"; return os; } @@ -442,3 +469,54 @@ SERIALISE_TYPE(TypeRef::, "TypeRef", { m_size_expr.reset(); s.item( m_path ); }) + + +void PrettyPrintType::print(::std::ostream& os) const +{ + switch(m_type.m_class) + { + case TypeRef::ANY: + os << "_"; + if( m_type.m_inner_types.size() ) { + os << "/* : " << m_type.m_inner_types << "*/"; + } + break; + case TypeRef::UNIT: + os << "()"; + break; + case TypeRef::PRIMITIVE: + os << m_type.m_core_type; + break; + case TypeRef::TUPLE: + os << "("; + for(const auto& t : m_type.m_inner_types) + os << t.print_pretty() << ","; + os << ")"; + break; + case TypeRef::REFERENCE: + os << "&" << (m_type.m_is_inner_mutable ? "mut " : "") << m_type.m_inner_types[0].print_pretty(); + break; + case TypeRef::POINTER: + os << "*" << (m_type.m_is_inner_mutable ? "mut" : "const") << " " << m_type.m_inner_types[0].print_pretty(); + break; + case TypeRef::ARRAY: + os << "[" << m_type.m_inner_types[0].print_pretty() << ", " << m_type.m_size_expr << "]"; + break; + case TypeRef::GENERIC: + os << m_type.m_path[0].name(); + break; + case TypeRef::PATH: + os << m_type.m_path; + break; + case TypeRef::ASSOCIATED: + os << "<" << m_type.m_inner_types[0].print_pretty() << " as " << m_type.m_inner_types[1].print_pretty() << ">::" << m_type.m_path[0].name(); + break; + } + +} + +::std::ostream& operator<<(::std::ostream& os, const PrettyPrintType& v) +{ + v.print(os); + return os; +} diff --git a/src/types.hpp b/src/types.hpp index 2cbbd0bb..4864e703 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -24,6 +24,19 @@ class TypeBounds };
+class PrettyPrintType
+{
+ const TypeRef& m_type;
+public:
+ PrettyPrintType(const TypeRef& ty):
+ m_type(ty)
+ {}
+
+ void print(::std::ostream& os) const;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const PrettyPrintType& v);
+};
+
/// A type
class TypeRef:
public Serialisable
@@ -31,6 +44,7 @@ class TypeRef: /// Class
enum Class {
ANY, //< '_' - Wildcard
+ //BOUNDED, //< '_: Traits' - Bounded type (a resolved type parameter usually)
UNIT, //< '()' - Unit / void
PRIMITIVE, //< Any primitive (builtin type)
TUPLE,
@@ -138,7 +152,9 @@ public: /// Returns true if the type is fully known (all sub-types are not wildcards)
bool is_concrete() const;
+ bool is_unbounded() const { return m_class == ANY && m_inner_types.size() == 0; }
bool is_wildcard() const { return m_class == ANY; }
+
bool is_unit() const { return m_class == UNIT; }
bool is_path() const { return m_class == PATH; }
bool is_type_param() const { return m_class == GENERIC; }
@@ -154,7 +170,11 @@ public: bool operator==(const TypeRef& x) const;
bool operator!=(const TypeRef& x) const { return !(*this == x); }
-
+
+ PrettyPrintType print_pretty() const { return PrettyPrintType(*this); }
+
+ friend class PrettyPrintType;
+
friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr);
static const char* class_name(TypeRef::Class c);
|