summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-05-27 13:47:04 +0800
committerJohn Hodge <tpg@mutabah.net>2016-05-27 13:47:04 +0800
commit99b04898383e9d66c97e8f89504420263ba96c0b (patch)
treefeeaa3370bd644c4889e5030415474846d27f1af
parent46b2f9450a438a597492e0015b735e625ee0cd3a (diff)
downloadmrust-99b04898383e9d66c97e8f89504420263ba96c0b.tar.gz
HIR Conv - Constant evaluation pass running (fully?)
-rw-r--r--Makefile2
-rw-r--r--src/hir/hir.cpp102
-rw-r--r--src/hir/hir.hpp6
-rw-r--r--src/hir/visitor.cpp26
-rw-r--r--src/hir/visitor.hpp8
-rw-r--r--src/hir_conv/constant_evaluation.cpp302
-rw-r--r--src/hir_conv/expand_type.cpp2
-rw-r--r--src/hir_conv/main_bindings.hpp1
-rw-r--r--src/hir_conv/resolve_ufcs.cpp217
-rw-r--r--src/main.cpp3
10 files changed, 629 insertions, 40 deletions
diff --git a/Makefile b/Makefile
index 029853ca..e43578d5 100644
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ OBJ += hir/hir.o
OBJ += hir/crate_ptr.o hir/type_ptr.o hir/expr_ptr.o
OBJ += hir/type.o hir/path.o hir/expr.o
OBJ += hir/visitor.o
-OBJ += hir_conv/expand_type.o hir_conv/constant_evaluation.o
+OBJ += hir_conv/expand_type.o hir_conv/constant_evaluation.o hir_conv/resolve_ufcs.o
OBJ += dump_as_rust.o
PCHS := ast/ast.hpp
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index 5b9401f5..bc1fecd5 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -28,3 +28,105 @@ namespace HIR {
return os;
}
}
+
+namespace {
+ bool matches_type_int(const ::HIR::GenericParams& params, const ::HIR::TypeRef& left, const ::HIR::TypeRef& right)
+ {
+ assert(! left.m_data.is_Infer() );
+ if( right.m_data.is_Infer() ) {
+ return false;
+ }
+
+ if( left.m_data.is_Generic() ) {
+ // True?
+ return true;
+ }
+
+ if( left.m_data.tag() != right.m_data.tag() ) {
+ return false;
+ }
+ TU_MATCH(::HIR::TypeRef::Data, (left.m_data, right.m_data), (le, re),
+ (Infer, assert(!"infer");),
+ (Diverge, return true; ),
+ (Primitive, return le == re;),
+ (Path,
+ if( le.m_data.tag() != re.m_data.tag() )
+ return false;
+ TU_MATCH_DEF(::HIR::Path::Data, (le.m_data, re.m_data), (ple, pre),
+ (
+ return false;
+ ),
+ (Generic,
+ if( ple.m_path.m_crate_name != pre.m_path.m_crate_name )
+ return false;
+ if( ple.m_path.m_components.size() != pre.m_path.m_components.size() )
+ return false;
+ for(unsigned int i = 0; i < ple.m_path.m_components.size(); i ++ )
+ {
+ if( ple.m_path.m_components[i] != pre.m_path.m_components[i] )
+ return false;
+ }
+
+ if( ple.m_params.m_types.size() > 0 || pre.m_params.m_types.size() > 0 ) {
+ TODO(Span(), "Match paths " << ple << " and " << pre);
+ }
+ return true;
+ )
+ )
+ ),
+ (Generic,
+ throw "";
+ ),
+ (TraitObject,
+ DEBUG("TODO: Compare " << left << " and " << right);
+ return false;
+ ),
+ (Array,
+ if( ! matches_type_int(params, *le.inner, *re.inner) )
+ return false;
+ if( le.size_val != re.size_val )
+ return false;
+ return true;
+ ),
+ (Slice,
+ return matches_type_int(params, *le.inner, *re.inner);
+ ),
+ (Tuple,
+ if( le.size() != re.size() )
+ return false;
+ for( unsigned int i = 0; i < le.size(); i ++ )
+ if( !matches_type_int(params, le[i], re[i]) )
+ return false;
+ return true;
+ ),
+ (Borrow,
+ if( le.type != re.type )
+ return false;
+ return matches_type_int(params, *le.inner, *re.inner);
+ ),
+ (Pointer,
+ if( le.is_mut != re.is_mut )
+ return false;
+ return matches_type_int(params, *le.inner, *re.inner);
+ ),
+ (Function,
+ DEBUG("TODO: Compare " << left << " and " << right);
+ return false;
+ )
+ )
+ return false;
+ }
+}
+
+bool ::HIR::TraitImpl::matches_type(const ::HIR::TypeRef& type) const
+{
+ return matches_type_int(m_params, m_type, type);
+}
+bool ::HIR::TypeImpl::matches_type(const ::HIR::TypeRef& type) const
+{
+ return matches_type_int(m_params, m_type, type);
+}
+bool ::HIR::MarkerImpl::matches_type(const ::HIR::TypeRef& type) const
+{
+ return matches_type_int(m_params, m_type, type);
+}
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index 2887fd13..ef565c4e 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -199,6 +199,8 @@ public:
::HIR::TypeRef m_type;
::std::map< ::std::string, ::HIR::Function> m_methods;
+
+ bool matches_type(const ::HIR::TypeRef& tr) const;
};
class TraitImpl
@@ -211,6 +213,8 @@ public:
::std::map< ::std::string, ::HIR::Function> m_methods;
::std::map< ::std::string, ::HIR::ExprPtr> m_constants;
::std::map< ::std::string, ::HIR::TypeRef> m_types;
+
+ bool matches_type(const ::HIR::TypeRef& tr) const;
};
class MarkerImpl
@@ -220,6 +224,8 @@ public:
::HIR::PathParams m_trait_args;
bool is_positive;
::HIR::TypeRef m_type;
+
+ bool matches_type(const ::HIR::TypeRef& tr) const;
};
class Crate
diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp
index 9a38aa20..13fdd0f2 100644
--- a/src/hir/visitor.cpp
+++ b/src/hir/visitor.cpp
@@ -114,7 +114,7 @@ void ::HIR::Visitor::visit_trait(::HIR::Trait& item)
{
this->visit_params(item.m_params);
for(auto& par : item.m_parent_traits) {
- this->visit_generic_path(par);
+ this->visit_generic_path(par, ::HIR::Visitor::PathContext::TYPE);
}
for(auto& i : item.m_types) {
this->visit_params(i.second.m_params);
@@ -214,7 +214,7 @@ void ::HIR::Visitor::visit_params(::HIR::GenericParams& params)
),
(TraitBound,
this->visit_type(e.type);
- this->visit_generic_path(e.trait.m_path);
+ this->visit_generic_path(e.trait.m_path, ::HIR::Visitor::PathContext::TYPE);
),
(TraitUnbound,
this->visit_type(e.type);
@@ -241,13 +241,13 @@ void ::HIR::Visitor::visit_type(::HIR::TypeRef& ty)
(Primitive,
),
(Path,
- this->visit_path(e);
+ this->visit_path(e, ::HIR::Visitor::PathContext::TYPE);
),
(Generic,
),
(TraitObject,
for(auto& trait : e.m_traits) {
- this->visit_generic_path(trait);
+ this->visit_generic_path(trait, ::HIR::Visitor::PathContext::TYPE);
}
),
(Array,
@@ -292,12 +292,12 @@ void ::HIR::Visitor::visit_pattern(::HIR::Pattern& pat)
this->visit_pattern(sp);
),
(StructTuple,
- this->visit_generic_path(e.path);
+ this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE);
for(auto& sp : e.sub_patterns)
this->visit_pattern(sp);
),
(Struct,
- this->visit_generic_path(e.path);
+ this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE);
for(auto& sp : e.sub_patterns)
this->visit_pattern(sp.second);
),
@@ -310,12 +310,12 @@ void ::HIR::Visitor::visit_pattern(::HIR::Pattern& pat)
this->visit_pattern_val(e.end);
),
(EnumTuple,
- this->visit_generic_path(e.path);
+ this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE);
for(auto& sp : e.sub_patterns)
this->visit_pattern(sp);
),
(EnumStruct,
- this->visit_generic_path(e.path);
+ this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE);
for(auto& sp : e.sub_patterns)
this->visit_pattern(sp.second);
),
@@ -339,15 +339,15 @@ void ::HIR::Visitor::visit_pattern_val(::HIR::Pattern::Value& val)
(String,
),
(Named,
- this->visit_path(e);
+ this->visit_path(e, ::HIR::Visitor::PathContext::VALUE);
)
)
}
-void ::HIR::Visitor::visit_path(::HIR::Path& p)
+void ::HIR::Visitor::visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc)
{
TU_MATCH(::HIR::Path::Data, (p.m_data), (e),
(Generic,
- this->visit_generic_path(e);
+ this->visit_generic_path(e, pc);
),
(UfcsInherent,
this->visit_type(*e.type);
@@ -355,7 +355,7 @@ void ::HIR::Visitor::visit_path(::HIR::Path& p)
),
(UfcsKnown,
this->visit_type(*e.type);
- this->visit_generic_path(e.trait);
+ this->visit_generic_path(e.trait, ::HIR::Visitor::PathContext::TYPE);
this->visit_path_params(e.params);
),
(UfcsUnknown,
@@ -371,7 +371,7 @@ void ::HIR::Visitor::visit_path_params(::HIR::PathParams& p)
this->visit_type(ty);
}
}
-void ::HIR::Visitor::visit_generic_path(::HIR::GenericPath& p)
+void ::HIR::Visitor::visit_generic_path(::HIR::GenericPath& p, ::HIR::Visitor::PathContext /*pc*/)
{
this->visit_path_params(p.m_params);
}
diff --git a/src/hir/visitor.hpp b/src/hir/visitor.hpp
index 814dac67..7e8bcf63 100644
--- a/src/hir/visitor.hpp
+++ b/src/hir/visitor.hpp
@@ -35,9 +35,13 @@ public:
virtual void visit_pattern_val(::HIR::Pattern::Value& val);
virtual void visit_type(::HIR::TypeRef& tr);
- virtual void visit_path(::HIR::Path& p);
+ enum class PathContext {
+ TYPE,
+ VALUE,
+ };
+ virtual void visit_path(::HIR::Path& p, PathContext );
virtual void visit_path_params(::HIR::PathParams& p);
- virtual void visit_generic_path(::HIR::GenericPath& p);
+ virtual void visit_generic_path(::HIR::GenericPath& p, PathContext );
virtual void visit_expr(::HIR::ExprPtr& exp);
};
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index 2544f85c..e64dd289 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -1,33 +1,176 @@
/*
* Evaluate constants
+ *
+ * HACK - Should be replaced with a reentrant typeck/mir pass
*/
#include "main_bindings.hpp"
#include <hir/hir.hpp>
#include <hir/expr.hpp>
#include <hir/visitor.hpp>
-
+#include <algorithm>
namespace {
- ::HIR::Function& get_function(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path)
+ ::HIR::Literal clone_literal(const ::HIR::Literal& v)
+ {
+ TU_MATCH(::HIR::Literal, (v), (e),
+ (Invalid,
+ return ::HIR::Literal();
+ ),
+ (List,
+ ::std::vector< ::HIR::Literal> vals;
+ for(const auto& val : e) {
+ vals.push_back( clone_literal(val) );
+ }
+ return ::HIR::Literal( mv$(vals) );
+ ),
+ (Integer,
+ return ::HIR::Literal(e);
+ ),
+ (Float,
+ return ::HIR::Literal(e);
+ ),
+ (String,
+ return ::HIR::Literal(e);
+ )
+ )
+ throw "";
+ }
+
+ enum class EntType {
+ Function,
+ Constant,
+ Struct,
+ };
+ const void* get_ent_simplepath(const Span& sp, const ::HIR::Crate& crate, const ::HIR::SimplePath& path, EntType et)
+ {
+ if( path.m_crate_name != "" )
+ TODO(sp, "get_ent_simplepath in crate");
+
+ const ::HIR::Module* mod = &crate.m_root_module;
+ for( unsigned int i = 0; i < path.m_components.size() - 1; i ++ )
+ {
+ const auto& pc = path.m_components[i];
+ auto it = mod->m_mod_items.find( pc );
+ if( it == mod->m_mod_items.end() ) {
+ BUG(sp, "Couldn't find component " << i << " of " << path);
+ }
+ TU_MATCH_DEF( ::HIR::TypeItem, (it->second->ent), (e2),
+ (
+ BUG(sp, "Node " << i << " of path " << path << " wasn't a module");
+ ),
+ (Module,
+ mod = &e2;
+ )
+ )
+ }
+
+ switch( et )
+ {
+ case EntType::Function: {
+ auto it = mod->m_value_items.find( path.m_components.back() );
+ if( it == mod->m_value_items.end() ) {
+ return nullptr;
+ }
+
+ TU_IFLET( ::HIR::ValueItem, it->second->ent, Function, e,
+ return &e;
+ )
+ else {
+ BUG(sp, "Path " << path << " didn't point to a functon");
+ }
+ } break;
+ case EntType::Constant: {
+ auto it = mod->m_value_items.find( path.m_components.back() );
+ if( it == mod->m_value_items.end() ) {
+ return nullptr;
+ }
+
+ TU_IFLET( ::HIR::ValueItem, it->second->ent, Constant, e,
+ return &e;
+ )
+ else {
+ BUG(sp, "Path " << path << " didn't point to a functon");
+ }
+ } break;
+ case EntType::Struct: {
+ auto it = mod->m_mod_items.find( path.m_components.back() );
+ if( it == mod->m_mod_items.end() ) {
+ return nullptr;
+ }
+
+ TU_IFLET( ::HIR::TypeItem, it->second->ent, Struct, e,
+ return &e;
+ )
+ else {
+ BUG(sp, "Path " << path << " didn't point to a struct");
+ }
+ } break;
+ }
+ throw "";
+ }
+ const void* get_ent_fullpath(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path, EntType et)
{
TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
(Generic,
- TODO(sp, "get_function(path = " << path << ")");
+ return get_ent_simplepath(sp, crate, e.m_path, et);
),
(UfcsInherent,
// Easy (ish)
- TODO(sp, "get_function(path = " << path << ")");
+ for( const auto& impl : crate.m_type_impls )
+ {
+ if( ! impl.matches_type(*e.type) ) {
+ continue ;
+ }
+ switch( et )
+ {
+ case EntType::Function: {
+ auto fit = impl.m_methods.find(e.item);
+ if( fit == impl.m_methods.end() )
+ continue ;
+ return &fit->second;
+ } break;
+ case EntType::Struct:
+ break;
+ case EntType::Constant:
+ break;
+ }
+ }
+ return nullptr;
),
(UfcsKnown,
- TODO(sp, "get_function(path = " << path << ")");
+ TODO(sp, "get_ent_fullpath(path = " << path << ")");
),
(UfcsUnknown,
// TODO - Since this isn't known, can it be searched properly?
- TODO(sp, "get_function(path = " << path << ")");
+ TODO(sp, "get_ent_fullpath(path = " << path << ")");
)
)
throw "";
}
+ const ::HIR::Function& get_function(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path)
+ {
+ auto* rv_p = reinterpret_cast<const ::HIR::Function*>( get_ent_fullpath(sp, crate, path, EntType::Function) );
+ if( !rv_p ) {
+ TODO(sp, "get_function(path = " << path << ")");
+ }
+ return *rv_p;
+ }
+ const ::HIR::Struct& get_struct(const Span& sp, const ::HIR::Crate& crate, const ::HIR::SimplePath& path)
+ {
+ auto rv_p = reinterpret_cast<const ::HIR::Struct*>( get_ent_simplepath(sp, crate, path, EntType::Struct) );
+ if( !rv_p ) {
+ BUG(sp, "Could not find struct name in " << path);
+ }
+ return *rv_p;
+ }
+ const ::HIR::Constant& get_constant(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path)
+ {
+ auto rv_p = reinterpret_cast<const ::HIR::Constant*>( get_ent_fullpath(sp, crate, path, EntType::Constant) );
+ if( !rv_p ) {
+ BUG(sp, "Could not find constant in " << path);
+ }
+ return *rv_p;
+ }
::HIR::Literal evaluate_constant(const ::HIR::Crate& crate, const ::HIR::ExprNode& expr)
{
@@ -35,6 +178,7 @@ namespace {
public ::HIR::ExprVisitor
{
const ::HIR::Crate& m_crate;
+ ::std::vector< ::std::pair< ::std::string, ::HIR::Literal > > m_values;
::HIR::Literal m_rv;
@@ -47,7 +191,8 @@ namespace {
}
void visit(::HIR::ExprNode_Block& node) override {
- TODO(node.span(), "ExprNode_Block");
+ for(const auto& e : node.m_nodes)
+ e->visit(*this);
}
void visit(::HIR::ExprNode_Return& node) override {
TODO(node.span(), "ExprNode_Return");
@@ -169,10 +314,33 @@ namespace {
}
}
void visit(::HIR::ExprNode_UniOp& node) override {
- TODO(node.span(), "ExprNode_UniOp");
+ node.m_value->visit(*this);
+ auto val = mv$(m_rv);
+
+ switch(node.m_op)
+ {
+ case ::HIR::ExprNode_UniOp::Op::Ref:
+ case ::HIR::ExprNode_UniOp::Op::RefMut:
+ TODO(node.span(), "&/&mut in constant");
+ break;
+ case ::HIR::ExprNode_UniOp::Op::Invert:
+ TU_MATCH_DEF(::HIR::Literal, (val), (e),
+ ( throw ""; ),
+ (Integer, m_rv = ::HIR::Literal(~e); ),
+ (Float, ERROR(node.span(), E0000, "not operator on float in constant"); )
+ )
+ case ::HIR::ExprNode_UniOp::Op::Negate:
+ TU_MATCH_DEF(::HIR::Literal, (val), (e),
+ ( throw ""; ),
+ (Integer, m_rv = ::HIR::Literal(-e); ),
+ (Float, m_rv = ::HIR::Literal(-e); )
+ )
+ }
}
void visit(::HIR::ExprNode_Cast& node) override {
- TODO(node.span(), "ExprNode_Cast");
+ node.m_value->visit(*this);
+ //auto val = mv$(m_rv);
+ //DEBUG("ExprNode_Cast - val = " << val << " as " << node.m_type);
}
void visit(::HIR::ExprNode_Index& node) override {
badnode(node);
@@ -182,17 +350,35 @@ namespace {
}
void visit(::HIR::ExprNode_CallPath& node) override {
- ::std::vector<HIR::Literal> arg_vals;
- for(const auto& arg : node.m_args) {
- arg->visit(*this);
- arg_vals.push_back( mv$(m_rv) );
+ auto& fcn = get_function(node.span(), m_crate, node.m_path);
+ // TODO: Set m_const during parse
+ //if( ! fcn.m_const ) {
+ // ERROR(node.span(), E0000, "Calling non-const function in const context - " << node.m_path);
+ //}
+ if( fcn.m_args.size() != node.m_args.size() ) {
+ ERROR(node.span(), E0000, "Incorrect argument count for " << node.m_path);
+ }
+ for(unsigned int i = 0; i < fcn.m_args.size(); i ++ )
+ {
+ const auto& pattern = fcn.m_args[i].first;
+ node.m_args[i]->visit(*this);
+ auto arg_val = mv$(m_rv);
+ TU_IFLET(::HIR::Pattern::Data, pattern.m_data, Any, e,
+ m_values.push_back( ::std::make_pair(pattern.m_binding.m_name, mv$(arg_val)) );
+ )
+ else {
+ ERROR(node.span(), E0000, "Constant functions can't have destructuring pattern argments");
+ }
}
- auto& fcn = get_function(node.span(), m_crate, node.m_path);
- if( ! fcn.m_const ) {
- ERROR(node.span(), E0000, "Calling non-const function in const context");
+ const_cast<HIR::ExprNode&>(*fcn.m_code).visit( *this );
+ assert( ! m_rv.is_Invalid() );
+ //TODO(node.span(), "exec const fn - " << node.m_path);
+
+ for(unsigned int i = 0; i < fcn.m_args.size(); i ++ )
+ {
+ m_values.pop_back();
}
- TODO(node.span(), "exec const fn - " << node.m_path);
}
void visit(::HIR::ExprNode_CallValue& node) override {
badnode(node);
@@ -226,20 +412,85 @@ namespace {
)
}
void visit(::HIR::ExprNode_PathValue& node) override {
- TODO(node.span(), "ExprNode_PathValue");
+ const auto& c = get_constant(node.span(), m_crate, node.m_path);
+ if( c.m_value_res.is_Invalid() ) {
+ const_cast<HIR::ExprNode&>(*c.m_value).visit(*this);
+ }
+ else {
+ m_rv = clone_literal(c.m_value_res);
+ }
}
void visit(::HIR::ExprNode_Variable& node) override {
- TODO(node.span(), "ExprNode_Variable");
+ for(auto it = m_values.rbegin(); it != m_values.rend(); ++it)
+ {
+ if( it->first == node.m_name) {
+ TU_MATCH_DEF(::HIR::Literal, (it->second), (e),
+ (
+ m_rv = mv$(it->second);
+ ),
+ (Integer,
+ m_rv = ::HIR::Literal(e);
+ ),
+ (Float,
+ m_rv = ::HIR::Literal(e);
+ )
+ )
+ return;
+ }
+ }
+ ERROR(node.span(), E0000, "Couldn't find variable " << node.m_name);
}
void visit(::HIR::ExprNode_StructLiteral& node) override {
- TODO(node.span(), "ExprNode_StructLiteral");
+ const auto& str = get_struct(node.span(), m_crate, node.m_path.m_path);
+ const auto& fields = str.m_data.as_Named();
+
+ ::std::vector< ::HIR::Literal> vals;
+ if( node.m_base_value ) {
+ node.m_base_value->visit(*this);
+ auto base_val = mv$(m_rv);
+ if( !base_val.is_List() || base_val.as_List().size() != fields.size() ) {
+ BUG(node.span(), "Struct literal base value had an incorrect field count");
+ }
+ vals = mv$(base_val.as_List());
+ }
+ else {
+ vals.resize( fields.size() );
+ }
+ for( const auto& val_set : node.m_values ) {
+ unsigned int idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& v) { return v.first == val_set.first; } ) - fields.begin();
+ if( idx == fields.size() ) {
+ ERROR(node.span(), E0000, "Field name " << val_set.first << " isn't a member of " << node.m_path);
+ }
+ val_set.second->visit(*this);
+ vals[idx] = mv$(m_rv);
+ }
+ for( unsigned int i = 0; i < vals.size(); i ++ ) {
+ const auto& val = vals[i];
+ if( val.is_Invalid() ) {
+ ERROR(node.span(), E0000, "Field " << fields[i].first << " wasn't set");
+ }
+ }
+
+ m_rv = ::HIR::Literal::make_List(mv$(vals));
}
void visit(::HIR::ExprNode_Tuple& node) override {
- TODO(node.span(), "ExprNode_Tuple");
+ ::std::vector< ::HIR::Literal> vals;
+ for(const auto& vn : node.m_vals ) {
+ vn->visit(*this);
+ assert( !m_rv.is_Invalid() );
+ vals.push_back( mv$(m_rv) );
+ }
+ m_rv = ::HIR::Literal::make_List(mv$(vals));
}
void visit(::HIR::ExprNode_ArrayList& node) override {
- TODO(node.span(), "ExprNode_ArrayList");
+ ::std::vector< ::HIR::Literal> vals;
+ for(const auto& vn : node.m_vals ) {
+ vn->visit(*this);
+ assert( !m_rv.is_Invalid() );
+ vals.push_back( mv$(m_rv) );
+ }
+ m_rv = ::HIR::Literal::make_List(mv$(vals));
}
void visit(::HIR::ExprNode_ArraySized& node) override {
TODO(node.span(), "ExprNode_ArraySized");
@@ -288,7 +539,12 @@ namespace {
void visit_constant(::HIR::Constant& item) override
{
item.m_value_res = evaluate_constant(m_crate, *item.m_value);
- DEBUG("constant = " << item.m_value_res);
+ DEBUG("constant: " << item.m_type << " = " << item.m_value_res);
+ }
+ void visit_static(::HIR::Static& item) override
+ {
+ item.m_value_res = evaluate_constant(m_crate, *item.m_value);
+ DEBUG("static: " << item.m_type << " = " << item.m_value_res);
}
void visit_expr(::HIR::ExprPtr& expr) override
{
diff --git a/src/hir_conv/expand_type.cpp b/src/hir_conv/expand_type.cpp
index 7e47b3a3..6112e67d 100644
--- a/src/hir_conv/expand_type.cpp
+++ b/src/hir_conv/expand_type.cpp
@@ -103,7 +103,7 @@ public:
void visit(::HIR::ExprNode_CallPath& node) override
{
- upper_visitor.visit_path(node.m_path);
+ upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE);
::HIR::ExprVisitorDef::visit(node);
}
void visit(::HIR::ExprNode_CallMethod& node) override
diff --git a/src/hir_conv/main_bindings.hpp b/src/hir_conv/main_bindings.hpp
index 286b7d9d..fc288975 100644
--- a/src/hir_conv/main_bindings.hpp
+++ b/src/hir_conv/main_bindings.hpp
@@ -6,5 +6,6 @@ namespace HIR {
class Crate;
};
+extern void ConvertHIR_ResolveUFCS(::HIR::Crate& crate);
extern void ConvertHIR_ExpandAliases(::HIR::Crate& crate);
extern void ConvertHIR_ConstantEvaluate(::HIR::Crate& hir_crate);
diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp
new file mode 100644
index 00000000..6e61e8c4
--- /dev/null
+++ b/src/hir_conv/resolve_ufcs.cpp
@@ -0,0 +1,217 @@
+/*
+ * Resolve unkown UFCS traits into inherent or trait
+ *
+ * HACK - Will likely be replaced with a proper typeck pass
+ */
+#include "main_bindings.hpp"
+#include <hir/hir.hpp>
+#include <hir/expr.hpp>
+#include <hir/visitor.hpp>
+
+namespace {
+ class Visitor:
+ public ::HIR::Visitor
+ {
+ const ::HIR::Crate& m_crate;
+
+ ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits;
+
+ public:
+ Visitor(const ::HIR::Crate& crate):
+ m_crate(crate)
+ {}
+
+ void visit_module(::HIR::Module& mod) override
+ {
+ for( const auto& trait_path : mod.m_traits )
+ m_traits.push_back( ::std::make_pair( &trait_path, &this->find_trait(trait_path) ) );
+ ::HIR::Visitor::visit_module(mod);
+ for(unsigned int i = 0; i < mod.m_traits.size(); i ++ )
+ m_traits.pop_back();
+ }
+
+
+ void visit_expr(::HIR::ExprPtr& expr) override
+ {
+ struct ExprVisitor:
+ public ::HIR::ExprVisitorDef
+ {
+ Visitor& upper_visitor;
+
+ ExprVisitor(Visitor& uv):
+ upper_visitor(uv)
+ {}
+
+ void visit(::HIR::ExprNode_Let& node) override
+ {
+ upper_visitor.visit_type(node.m_type);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ void visit(::HIR::ExprNode_Cast& node) override
+ {
+ upper_visitor.visit_type(node.m_type);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+
+ void visit(::HIR::ExprNode_CallPath& node) override
+ {
+ upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ void visit(::HIR::ExprNode_CallMethod& node) override
+ {
+ upper_visitor.visit_path_params(node.m_params);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+
+ void visit(::HIR::ExprNode_Closure& node) override
+ {
+ upper_visitor.visit_type(node.m_return);
+ for(auto& arg : node.m_args) {
+ upper_visitor.visit_pattern(arg.first);
+ upper_visitor.visit_type(arg.second);
+ }
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+
+ void visit(::HIR::ExprNode_Block& node) override
+ {
+ for( const auto& trait_path : node.m_traits )
+ upper_visitor.m_traits.push_back( ::std::make_pair( &trait_path, &upper_visitor.find_trait(trait_path) ) );
+ ::HIR::ExprVisitorDef::visit(node);
+ for(unsigned int i = 0; i < node.m_traits.size(); i ++ )
+ upper_visitor.m_traits.pop_back();
+ }
+ };
+
+ if( &*expr != nullptr )
+ {
+ ExprVisitor v { *this };
+ (*expr).visit(v);
+ }
+ }
+
+ void visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc) override
+ {
+ TU_IFLET(::HIR::Path::Data, p.m_data, UfcsUnknown, e,
+ DEBUG("UfcsUnknown - p=" << p);
+ // 1. Search all impls of in-scope traits for this method on this type
+ for( const auto& trait_info : m_traits )
+ {
+ const auto& trait_path = *trait_info.first;
+ const auto& trait = *trait_info.second;
+
+ switch( pc )
+ {
+ case ::HIR::Visitor::PathContext::VALUE: {
+ auto it1 = trait.m_values.find( e.item );
+ if( it1 == trait.m_values.end() ) {
+ continue ;
+ }
+ // Found it, just keep going (don't care about details here)
+ } break;
+ case ::HIR::Visitor::PathContext::TYPE: {
+ auto it1 = trait.m_types.find( e.item );
+ if( it1 == trait.m_types.end() ) {
+ continue ;
+ }
+ // Found it, just keep going (don't care about details here)
+ } break;
+ }
+
+ auto trait_impl_it = m_crate.m_trait_impls.equal_range( trait_path );
+ if( trait_impl_it.first == trait_impl_it.second ) {
+ continue ;
+ }
+ for( auto it = trait_impl_it.first; it != trait_impl_it.second; it ++ )
+ {
+ const auto& impl = it->second;
+ if( !impl.matches_type(*e.type) ) {
+ continue ;
+ }
+
+ auto new_data = ::HIR::Path::Data::make_UfcsKnown({ mv$(e.type), ::HIR::GenericPath(trait_path), mv$(e.item), mv$(e.params)} );
+ p.m_data = mv$(new_data);
+ DEBUG("- Resolved, replace with " << p);
+ return ;
+ }
+ }
+
+ // 2. No trait matched, search for inherent impl
+ for( const auto& impl : m_crate.m_type_impls )
+ {
+ if( !impl.matches_type(*e.type) ) {
+ continue ;
+ }
+ DEBUG("- matched impl " << *e.type);
+ // TODO: Search for item
+ switch( pc )
+ {
+ case ::HIR::Visitor::PathContext::VALUE: {
+ auto it1 = impl.m_methods.find( e.item );
+ if( it1 == impl.m_methods.end() ) {
+ continue ;
+ }
+ // Found it, just keep going (don't care about details here)
+ } break;
+ case ::HIR::Visitor::PathContext::TYPE: {
+ continue ;
+ // Found it, just keep going (don't care about details here)
+ } break;
+ }
+
+ auto new_data = ::HIR::Path::Data::make_UfcsInherent({ mv$(e.type), mv$(e.item), mv$(e.params)} );
+ p.m_data = mv$(new_data);
+ DEBUG("- Resolved, replace with " << p);
+ return ;
+ }
+
+ // Couldn't find it
+ DEBUG("Failed to find impl with '" << e.item << "' for " << *e.type);
+ )
+ }
+
+
+ const ::HIR::Trait& find_trait(const ::HIR::SimplePath& path) const
+ {
+ if( path.m_crate_name != "" )
+ TODO(Span(), "find_trait in crate");
+
+ const ::HIR::Module* mod = &m_crate.m_root_module;
+ for( unsigned int i = 0; i < path.m_components.size() - 1; i ++ )
+ {
+ const auto& pc = path.m_components[i];
+ auto it = mod->m_mod_items.find( pc );
+ if( it == mod->m_mod_items.end() ) {
+ BUG(Span(), "Couldn't find component " << i << " of " << path);
+ }
+ TU_MATCH_DEF( ::HIR::TypeItem, (it->second->ent), (e2),
+ (
+ BUG(Span(), "Node " << i << " of path " << path << " wasn't a module");
+ ),
+ (Module,
+ mod = &e2;
+ )
+ )
+ }
+ auto it = mod->m_mod_items.find( path.m_components.back() );
+ if( it == mod->m_mod_items.end() ) {
+ BUG(Span(), "Could not find type name in " << path);
+ }
+
+ TU_IFLET( ::HIR::TypeItem, it->second->ent, Trait, e,
+ return e;
+ )
+ else {
+ BUG(Span(), "Trait path " << path << " didn't point to a trait");
+ }
+ }
+ };
+
+}
+
+void ConvertHIR_ResolveUFCS(::HIR::Crate& crate)
+{
+ Visitor exp { crate };
+ exp.visit_crate( crate );
+}
diff --git a/src/main.cpp b/src/main.cpp
index f163e736..bc22654c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -154,6 +154,9 @@ int main(int argc, char *argv[])
CompilePhaseV("Resolve Type Aliases", [&]() {
ConvertHIR_ExpandAliases(*hir_crate);
});
+ CompilePhaseV("Resolve UFCS paths", [&]() {
+ ConvertHIR_ResolveUFCS(*hir_crate);
+ });
CompilePhaseV("Constant Evaluate", [&]() {
ConvertHIR_ConstantEvaluate(*hir_crate);