summaryrefslogtreecommitdiff
path: root/src/hir_conv/constant_evaluation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/hir_conv/constant_evaluation.cpp')
-rw-r--r--src/hir_conv/constant_evaluation.cpp505
1 files changed, 363 insertions, 142 deletions
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index ec313e4a..35669dd9 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -16,8 +16,15 @@
#include <trans/target.hpp>
#include <hir/expr_state.hpp>
+#include "constant_evaluation.hpp"
+#include <trans/monomorphise.hpp> // For handling monomorph of MIR in provided associated constants
+
+#define CHECK_DEFER(var) do { if( var.is_Defer() ) { m_rv = ::HIR::Literal::make_Defer({}); return ; } } while(0)
+
namespace {
- struct NewvalState {
+ struct NewvalState
+ : public HIR::Evaluator::Newval
+ {
const ::HIR::Module& mod;
const ::HIR::ItemPath& mod_path;
::std::string name_prefix;
@@ -31,9 +38,9 @@ namespace {
{
}
- ::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value)
+ virtual ::HIR::Path new_static(::HIR::TypeRef type, ::HIR::Literal value) override
{
- auto name = FMT(name_prefix << next_item_idx);
+ auto name = RcString::new_interned(FMT(name_prefix << next_item_idx));
next_item_idx ++;
DEBUG("mod_path = " << mod_path);
auto rv = mod_path.get_simple_path() + name.c_str();
@@ -47,23 +54,6 @@ namespace {
return rv;
}
};
- struct Evaluator
- {
- const Span& root_span;
- StaticTraitResolve resolve;
- NewvalState nvs;
-
- Evaluator(const Span& sp, const ::HIR::Crate& crate, NewvalState nvs):
- root_span(sp),
- resolve(crate),
- nvs( ::std::move(nvs) )
- {
- }
-
- ::HIR::Literal evaluate_constant(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp);
-
- ::HIR::Literal evaluate_constant_mir(const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args);
- };
::HIR::Literal clone_literal(const ::HIR::Literal& v)
{
@@ -71,6 +61,9 @@ namespace {
(Invalid,
return ::HIR::Literal();
),
+ (Defer,
+ return ::HIR::Literal::make_Defer({});
+ ),
(List,
::std::vector< ::HIR::Literal> vals;
for(const auto& val : e) {
@@ -162,6 +155,8 @@ namespace {
),
(Enum,
),
+ (ExternType,
+ ),
(TypeAlias,
)
)
@@ -267,13 +262,16 @@ namespace {
TODO(sp, "Could not find function for " << path << " - " << rv.tag_str());
}
}
+} // namespace <anon>
+
+namespace HIR {
- ::HIR::Literal Evaluator::evaluate_constant_mir(const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args)
+ ::HIR::Literal Evaluator::evaluate_constant_mir(const ::HIR::ItemPath& ip, const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args)
{
// TODO: Full-blown miri
TRACE_FUNCTION_F("exp=" << exp << ", args=" << args);
- ::MIR::TypeResolve state { this->root_span, this->resolve, FMT_CB(,), exp, {}, fcn };
+ ::MIR::TypeResolve state { this->root_span, this->resolve, FMT_CB(ss, ss<<ip), exp, {}, fcn };
::HIR::Literal retval;
::std::vector< ::HIR::Literal> locals( fcn.locals.size() );
@@ -295,61 +293,66 @@ namespace {
::HIR::Literal& get_lval(const ::MIR::LValue& lv)
{
- TU_MATCHA( (lv), (e),
+ ::HIR::Literal* lit_ptr;
+ TRACE_FUNCTION_FR(lv, *lit_ptr);
+ TU_MATCHA( (lv.m_root), (e),
(Return,
- return retval;
+ lit_ptr = &retval;
),
(Local,
- if( e >= locals.size() )
- MIR_BUG(state, "Local index out of range - " << e << " >= " << locals.size());
- return locals[e];
+ MIR_ASSERT(state, e < locals.size(), "Local index out of range - " << e << " >= " << locals.size());
+ lit_ptr = &locals[e];
),
(Argument,
- if( e.idx >= args.size() )
- MIR_BUG(state, "Local index out of range - " << e.idx << " >= " << args.size());
- return args[e.idx];
+ MIR_ASSERT(state, e < args.size(), "Argument index out of range - " << e << " >= " << args.size());
+ lit_ptr = &args[e];
),
(Static,
MIR_TODO(state, "LValue::Static - " << e);
- ),
- (Field,
- auto& val = get_lval(*e.val);
- MIR_ASSERT(state, val.is_List(), "LValue::Field on non-list literal - " << val.tag_str() << " - " << lv);
- auto& vals = val.as_List();
- MIR_ASSERT(state, e.field_index < vals.size(), "LValue::Field index out of range");
- return vals[ e.field_index ];
- ),
- (Deref,
- auto& val = get_lval(*e.val);
- TU_MATCH_DEF( ::HIR::Literal, (val), (ve),
- (
- MIR_TODO(state, "LValue::Deref - " << lv << " { " << val << " }");
- ),
- (BorrowData,
- return *ve;
- ),
- (String,
- // Just clone the string (hack)
- // - TODO: Create a list?
- return val;
- )
- )
- ),
- (Index,
- auto& val = get_lval(*e.val);
- MIR_ASSERT(state, val.is_List(), "LValue::Index on non-list literal - " << val.tag_str() << " - " << lv);
- auto& idx = get_lval(*e.idx);
- MIR_ASSERT(state, idx.is_Integer(), "LValue::Index with non-integer index literal - " << idx.tag_str() << " - " << lv);
- auto& vals = val.as_List();
- auto idx_v = static_cast<size_t>( idx.as_Integer() );
- MIR_ASSERT(state, idx_v < vals.size(), "LValue::Index index out of range");
- return vals[ idx_v ];
- ),
- (Downcast,
- MIR_TODO(state, "LValue::Downcast - " << lv);
)
)
- throw "";
+
+ for(const auto& w : lv.m_wrappers)
+ {
+ auto& val = *lit_ptr;
+ TU_MATCH_HDRA( (w), {)
+ TU_ARMA(Field, e) {
+ MIR_ASSERT(state, val.is_List(), "LValue::Field on non-list literal - " << val.tag_str() << " - " << lv);
+ auto& vals = val.as_List();
+ MIR_ASSERT(state, e < vals.size(), "LValue::Field index out of range");
+ lit_ptr = &vals[ e ];
+ }
+ TU_ARMA(Deref, e) {
+ TU_MATCH_DEF( ::HIR::Literal, (val), (ve),
+ (
+ MIR_TODO(state, "LValue::Deref - " << lv << " { " << val << " }");
+ ),
+ (BorrowData,
+ lit_ptr = &*ve;
+ ),
+ (String,
+ // Just clone the string (hack)
+ // - TODO: Create a list?
+ lit_ptr = &val;
+ )
+ )
+ }
+ TU_ARMA(Index, e) {
+ MIR_ASSERT(state, val.is_List(), "LValue::Index on non-list literal - " << val.tag_str() << " - " << lv);
+ MIR_ASSERT(state, e < locals.size(), "LValue::Index index local out of range");
+ auto& idx = locals[e];
+ MIR_ASSERT(state, idx.is_Integer(), "LValue::Index with non-integer index literal - " << idx.tag_str() << " - " << lv);
+ auto& vals = val.as_List();
+ auto idx_v = static_cast<size_t>( idx.as_Integer() );
+ MIR_ASSERT(state, idx_v < vals.size(), "LValue::Index index out of range");
+ lit_ptr = &vals[ idx_v ];
+ }
+ TU_ARMA(Downcast, e) {
+ MIR_TODO(state, "LValue::Downcast - " << lv);
+ }
+ }
+ }
+ return *lit_ptr;
}
::HIR::Literal read_lval(const ::MIR::LValue& lv)
{
@@ -377,27 +380,28 @@ namespace {
LocalState local_state( state, retval, args, locals );
auto const_to_lit = [&](const ::MIR::Constant& c)->::HIR::Literal {
- TU_MATCH(::MIR::Constant, (c), (e2),
- (Int,
+ TU_MATCH_HDR( (c), {)
+ TU_ARM(c, Int, e2) {
return ::HIR::Literal(static_cast<uint64_t>(e2.v));
- ),
- (Uint,
+ }
+ TU_ARM(c, Uint, e2)
return ::HIR::Literal(e2.v);
- ),
- (Float,
+ TU_ARM(c, Float, e2)
return ::HIR::Literal(e2.v);
- ),
- (Bool,
+ TU_ARM(c, Bool, e2)
return ::HIR::Literal(static_cast<uint64_t>(e2.v));
- ),
- (Bytes,
+ TU_ARM(c, Bytes, e2)
return ::HIR::Literal::make_String({e2.begin(), e2.end()});
- ),
- (StaticString,
+ TU_ARM(c, StaticString, e2)
return ::HIR::Literal(e2);
- ),
- (Const,
- auto p = ms.monomorph(state.sp, e2.p);
+ TU_ARM(c, Const, e2) {
+ auto p = ms.monomorph(state.sp, *e2.p);
+ // If there's any mention of generics in this path, then return Literal::Defer
+ if( visit_path_tys_with(p, [&](const auto& ty)->bool { return ty.m_data.is_Generic(); }) )
+ {
+ DEBUG("Return Literal::Defer for constant " << *e2.p << " which references a generic parameter");
+ return ::HIR::Literal::make_Defer({});
+ }
MonomorphState const_ms;
auto ent = get_ent_fullpath(state.sp, this->resolve.m_crate, p, EntNS::Value, const_ms);
MIR_ASSERT(state, ent.is_Constant(), "MIR Constant::Const(" << p << ") didn't point to a Constant - " << ent.tag_str());
@@ -407,19 +411,25 @@ namespace {
auto& item = const_cast<::HIR::Constant&>(c);
// Challenge: Adding items to the module might invalidate an iterator.
::HIR::ItemPath mod_ip { item.m_value.m_state->m_mod_path };
- auto eval = Evaluator { item.m_value->span(), resolve.m_crate, NewvalState { item.m_value.m_state->m_module, mod_ip, FMT(&c << "$") } };
+ auto nvs = NewvalState { item.m_value.m_state->m_module, mod_ip, FMT("const" << &c << "#") };
+ auto eval = ::HIR::Evaluator { item.m_value.span(), resolve.m_crate, nvs };
DEBUG("- Evaluate " << p);
DEBUG("- " << ::HIR::ItemPath(p));
item.m_value_res = eval.evaluate_constant(::HIR::ItemPath(p), item.m_value, item.m_type.clone());
//check_lit_type(item.m_value->span(), item.m_type, item.m_value_res);
}
+ auto it = c.m_monomorph_cache.find(*e2.p);
+ if( it != c.m_monomorph_cache.end() )
+ {
+ MIR_ASSERT(state, !it->second.is_Defer(), "Cached literal for " << *e2.p << " is Defer");
+ return clone_literal( it->second );
+ }
return clone_literal( c.m_value_res );
- ),
- (ItemAddr,
- return ::HIR::Literal::make_BorrowPath( ms.monomorph(state.sp, e2) );
- )
- )
+ }
+ TU_ARM(c, ItemAddr, e2)
+ return ::HIR::Literal::make_BorrowPath( ms.monomorph(state.sp, *e2) );
+ }
throw "";
};
auto read_param = [&](const ::MIR::Param& p) -> ::HIR::Literal
@@ -476,17 +486,14 @@ namespace {
MIR_BUG(state, "Only shared borrows are allowed in constants");
}
- if( e.type != ::HIR::BorrowType::Shared ) {
- MIR_BUG(state, "Only shared borrows are allowed in constants");
+ if( !e.val.m_wrappers.empty() && e.val.m_wrappers.back().is_Deref() ) {
+ //if( p->val->is_Deref() )
+ // MIR_TODO(state, "Undo nested deref coercion - " << *p->val);
+ val = local_state.read_lval(e.val.clone_unwrapped());
}
- if( const auto* p = e.val.opt_Deref() ) {
- if( p->val->is_Deref() )
- MIR_TODO(state, "Undo nested deref coercion - " << *p->val);
- val = local_state.read_lval(*p->val);
- }
- else if( const auto* p = e.val.opt_Static() ) {
+ else if( e.val.m_wrappers.empty() && e.val.m_root.is_Static() ){
// Borrow of a static, emit BorrowPath with the same path
- val = ::HIR::Literal::make_BorrowPath( p->clone() );
+ val = ::HIR::Literal::make_BorrowPath( e.val.m_root.as_Static().clone() );
}
else {
auto inner_val = local_state.read_lval(e.val);
@@ -504,6 +511,10 @@ namespace {
),
(Cast,
auto inval = local_state.read_lval(e.val);
+ if( inval.is_Defer() ) {
+ val = ::HIR::Literal::make_Defer({});
+ }
+ else
TU_MATCH_DEF(::HIR::TypeRef::Data, (e.type.m_data), (te),
(
// NOTE: Can be an unsizing!
@@ -585,6 +596,8 @@ namespace {
(BinOp,
auto inval_l = read_param(e.val_l);
auto inval_r = read_param(e.val_r);
+ if( inval_l.is_Defer() || inval_r.is_Defer() )
+ return ::HIR::Literal::make_Defer({});
MIR_ASSERT(state, inval_l.tag() == inval_r.tag(), "Mismatched literal types in binop - " << inval_l << " and " << inval_r);
TU_MATCH_DEF( ::HIR::Literal, (inval_l, inval_r), (l, r),
(
@@ -651,6 +664,8 @@ namespace {
),
(UniOp,
auto inval = local_state.read_lval(e.val);
+ if( inval.is_Defer() )
+ return ::HIR::Literal::make_Defer({});
TU_IFLET( ::HIR::Literal, inval, Integer, i,
switch( e.op )
{
@@ -685,7 +700,9 @@ namespace {
),
(MakeDst,
auto ptr = read_param(e.ptr_val);
+ if(ptr.is_Defer()) return ::HIR::Literal::make_Defer({});
auto meta = read_param(e.meta_val);
+ if(meta.is_Defer()) return ::HIR::Literal::make_Defer({});
if( ! meta.is_Integer() ) {
MIR_TODO(state, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta);
}
@@ -696,26 +713,39 @@ namespace {
(Tuple,
::std::vector< ::HIR::Literal> vals;
vals.reserve( e.vals.size() );
- for(const auto& v : e.vals)
+ for(const auto& v : e.vals) {
vals.push_back( read_param(v) );
+ if( vals.back().is_Defer() ) {
+ return ::HIR::Literal::make_Defer({});
+ }
+ }
val = ::HIR::Literal::make_List( mv$(vals) );
),
(Array,
::std::vector< ::HIR::Literal> vals;
vals.reserve( e.vals.size() );
- for(const auto& v : e.vals)
+ for(const auto& v : e.vals) {
vals.push_back( read_param(v) );
+ if( vals.back().is_Defer() ) {
+ return ::HIR::Literal::make_Defer({});
+ }
+ }
val = ::HIR::Literal::make_List( mv$(vals) );
),
(Variant,
auto ival = read_param(e.val);
+ if(ival.is_Defer()) return ::HIR::Literal::make_Defer({});
val = ::HIR::Literal::make_Variant({ e.index, box$(ival) });
),
(Struct,
::std::vector< ::HIR::Literal> vals;
vals.reserve( e.vals.size() );
- for(const auto& v : e.vals)
+ for(const auto& v : e.vals) {
vals.push_back( read_param(v) );
+ if( vals.back().is_Defer() ) {
+ return ::HIR::Literal::make_Defer({});
+ }
+ }
val = ::HIR::Literal::make_List( mv$(vals) );
)
)
@@ -724,15 +754,18 @@ namespace {
dst = mv$(val);
}
state.set_cur_stmt_term(cur_block);
- TU_MATCH_DEF( ::MIR::Terminator, (block.terminator), (e),
- (
+ TU_MATCH_HDRA( (block.terminator), {)
+ default:
MIR_BUG(state, "Unexpected terminator - " << block.terminator);
- ),
- (Goto,
+ TU_ARMA(Goto, e) {
cur_block = e;
- ),
- (Return,
- if( exp.m_data.is_Primitive() )
+ }
+ TU_ARMA(Return, e) {
+ if( retval.is_Defer() )
+ {
+ //
+ }
+ else if( exp.m_data.is_Primitive() )
{
switch( exp.m_data.as_Primitive() )
{
@@ -773,52 +806,81 @@ namespace {
}
}
return retval;
- ),
- (Call,
- if( !e.fcn.is_Path() )
- MIR_BUG(state, "Unexpected terminator - " << block.terminator);
- const auto& fcnp_raw = e.fcn.as_Path();
- auto fcnp = ms.monomorph(state.sp, fcnp_raw);
-
+ }
+ TU_ARMA(Call, e) {
auto& dst = local_state.get_lval(e.ret_val);
- MonomorphState fcn_ms;
- auto& fcn = get_function(this->root_span, this->resolve.m_crate, fcnp, fcn_ms);
+ if( const auto* te = e.fcn.opt_Intrinsic() )
+ {
+ if( te->name == "size_of" ) {
+ auto ty = ms.monomorph(state.sp, te->params.m_types.at(0));
+ size_t size_val;
+ Target_GetSizeOf(state.sp, this->resolve, ty, size_val);
+ dst = ::HIR::Literal::make_Integer( size_val );
+ }
+ else {
+ MIR_TODO(state, "Call intrinsic \"" << te->name << "\" - " << block.terminator);
+ }
+ }
+ else if( const auto* te = e.fcn.opt_Path() )
+ {
+ const auto& fcnp_raw = *te;
+ auto fcnp = ms.monomorph(state.sp, fcnp_raw);
- ::std::vector< ::HIR::Literal> call_args;
- call_args.reserve( e.args.size() );
- for(const auto& a : e.args)
- call_args.push_back( read_param(a) );
- // TODO: Set m_const during parse and check here
+ MonomorphState fcn_ms;
+ auto& fcn = get_function(this->root_span, this->resolve.m_crate, fcnp, fcn_ms);
- // Call by invoking evaluate_constant on the function
+ ::std::vector< ::HIR::Literal> call_args;
+ call_args.reserve( e.args.size() );
+ for(const auto& a : e.args)
+ call_args.push_back( read_param(a) );
+ // TODO: Set m_const during parse and check here
+
+ // Call by invoking evaluate_constant on the function
+ {
+ TRACE_FUNCTION_F("Call const fn " << fcnp << " args={ " << call_args << " }");
+ auto fcn_ip = ::HIR::ItemPath(fcnp);
+ const auto* mir = this->resolve.m_crate.get_or_gen_mir( fcn_ip, fcn );
+ MIR_ASSERT(state, mir, "No MIR for function " << fcnp);
+ dst = evaluate_constant_mir(fcn_ip, *mir, mv$(fcn_ms), fcn.m_return.clone(), mv$(call_args));
+ }
+ }
+ else
{
- TRACE_FUNCTION_F("Call const fn " << fcnp << " args={ " << call_args << " }");
- const auto* mir = this->resolve.m_crate.get_or_gen_mir( ::HIR::ItemPath(fcnp.clone()), fcn );
- MIR_ASSERT(state, mir, "No MIR for function " << fcnp);
- dst = evaluate_constant_mir(*mir, mv$(fcn_ms), fcn.m_return.clone(), mv$(call_args));
+ MIR_BUG(state, "Unexpected terminator - " << block.terminator);
}
-
cur_block = e.ret_block;
- )
- )
+ }
+ }
}
}
- ::HIR::Literal Evaluator::evaluate_constant(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp)
+ ::HIR::Literal Evaluator::evaluate_constant(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, MonomorphState ms/*={}*/)
{
TRACE_FUNCTION_F(ip);
const auto* mir = this->resolve.m_crate.get_or_gen_mir(ip, expr, exp);
if( mir ) {
- return evaluate_constant_mir(*mir, {}, mv$(exp), {});
+ ::HIR::TypeRef ty_self { "Self", GENERIC_Self };
+ // Might want to have a fully-populated MonomorphState for expanding inside impl blocks
+ // HACK: Generate a roughly-correct one
+ const auto& top_ip = ip.get_top_ip();
+ if( top_ip.trait && !top_ip.ty ) {
+ ms.self_ty = &ty_self;
+ }
+ return evaluate_constant_mir(ip, *mir, mv$(ms), mv$(exp), {});
}
else {
BUG(this->root_span, "Attempting to evaluate constant expression with no associated code");
}
}
+} // namespace HIR
+
+namespace {
void check_lit_type(const Span& sp, const ::HIR::TypeRef& type, ::HIR::Literal& lit)
{
+ if( lit.is_Defer() )
+ return ;
// TODO: Mask down limited size integers
TU_MATCHA( (type.m_data), (te),
(Infer,
@@ -898,12 +960,15 @@ namespace {
const ::HIR::Crate& m_crate;
const ::HIR::Module* m_mod;
const ::HIR::ItemPath* m_mod_path;
+ MonomorphState m_monomorph_state;
+ bool m_recurse_types;
public:
Expander(const ::HIR::Crate& crate):
m_crate(crate),
m_mod(nullptr),
m_mod_path(nullptr)
+ ,m_recurse_types(false)
{}
void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
@@ -918,20 +983,123 @@ namespace {
m_mod = saved_m;
m_mod_path = saved_mp;
}
+ void visit_function(::HIR::ItemPath p, ::HIR::Function& f) override
+ {
+ TRACE_FUNCTION_F(p);
+ ::HIR::Visitor::visit_function(p, f);
+ }
+
+ void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override
+ {
+ static Span sp;
+ TRACE_FUNCTION_F("impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type);
+ const auto& trait = m_crate.get_trait_by_path(sp, trait_path);
+
+ StaticTraitResolve resolve( m_crate );
+ // - TODO: Defer this call until first missing item?
+ resolve.set_impl_generics(impl.m_params);
+
+ auto mp = ::HIR::ItemPath(impl.m_src_module);
+ m_mod_path = &mp;
+ m_mod = &m_crate.get_mod_by_path(sp, impl.m_src_module);
+
+ for(const auto& vi : trait.m_values)
+ {
+ // Search for any constants that are in the trait itself, but NOT in this impl
+ // - For each of these, find the lowest parent specialisation with the constant set
+ // - Ensure that the MIR has been generated for the constant (TODO: This only needs to be done for
+ // specialisations, not trait-provided)
+ // - Monomorphise the MIR for this impl, and let expansion happen as usual
+ if( vi.second.is_Constant() )
+ {
+ if( impl.m_constants.count(vi.first) > 0 )
+ continue;
+ DEBUG("- Constant " << vi.first << " missing, looking for a source");
+ // This trait impl doesn't have this constant, need to find the provided version that applies
+
+ MonomorphState ms;
+ ms.self_ty = &impl.m_type;
+ ms.pp_impl = &impl.m_trait_args;
+
+ resolve.find_impl(sp, trait_path, impl.m_trait_args, impl.m_type, [&](ImplRef found_impl, bool is_fuzzed)->bool {
+ ASSERT_BUG(sp, found_impl.m_data.is_TraitImpl(), "");
+ // If this found impl is the current one, keep searching
+ if( found_impl.m_data.as_TraitImpl().impl == &impl )
+ return false;
+ TODO(sp, "Found a possible parent specialisation of " << trait_path << impl.m_trait_args << " for " << impl.m_type << " - " << found_impl);
+ return false;
+ });
+ const auto& template_const = vi.second.as_Constant();
+ if( template_const.m_value_res.is_Defer() ) {
+ auto nvs = NewvalState { *m_mod, *m_mod_path, FMT("impl" << &impl << "_" << vi.first << "#") };
+ auto eval = ::HIR::Evaluator { sp, m_crate, nvs };
+ ::HIR::ExprPtr ep;
+ Trans_Params tp(sp);
+ tp.self_type = ms.self_ty->clone();
+ tp.pp_impl = ms.pp_impl->clone();
+ ep.m_mir = Trans_Monomorphise(resolve, mv$(tp), template_const.m_value.m_mir);
+ ep.m_state = ::HIR::ExprStatePtr( ::HIR::ExprState(*m_mod, m_mod_path->get_simple_path()) );
+ DEBUG("TMP TMP " << trait_path << " - " << ep.m_state->m_mod_path);
+ ep.m_state->stage = ::HIR::ExprState::Stage::Mir;
+ impl.m_constants.insert(::std::make_pair(
+ vi.first,
+ ::HIR::TraitImpl::ImplEnt<::HIR::Constant> {
+ /*is_specialisable=*/false,
+ ::HIR::Constant {
+ template_const.m_params.clone(),
+ /*m_type=*/ms.monomorph(sp, template_const.m_type),
+ /*m_value=*/mv$(ep),
+ ::HIR::Literal()
+ }
+ }
+ ));
+ }
+ else {
+ //TODO(sp, "Assign associated type " << vi.first << " in impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type);
+ impl.m_constants.insert(::std::make_pair(
+ vi.first,
+ ::HIR::TraitImpl::ImplEnt<::HIR::Constant> {
+ /*is_specialisable=*/false,
+ ::HIR::Constant {
+ template_const.m_params.clone(),
+ /*m_type=*/ms.monomorph(sp, template_const.m_type),
+ /*m_value=*/::HIR::ExprPtr(),
+ clone_literal(template_const.m_value_res)
+ }
+ }
+ ));
+ }
+ }
+ }
+
+ ::HIR::PathParams pp_impl;
+ for(const auto& tp : impl.m_params.m_types)
+ pp_impl.m_types.push_back( ::HIR::TypeRef(tp.m_name, pp_impl.m_types.size() | 256) );
+ m_monomorph_state.pp_impl = &pp_impl;
+
+ ::HIR::Visitor::visit_trait_impl(trait_path, impl);
+
+ m_monomorph_state.pp_impl = nullptr;
+
+ m_mod = nullptr;
+ m_mod_path = nullptr;
+ }
void visit_type(::HIR::TypeRef& ty) override
{
::HIR::Visitor::visit_type(ty);
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
+ TRACE_FUNCTION_FR(ty, ty);
if( e.size_val == ~0u )
{
assert(e.size);
assert(*e.size);
const auto& expr_ptr = *e.size;
- auto ty_name = FMT("ty_" << &ty << "$");
+ auto ty_name = FMT("ty_" << &ty << "#");
- auto eval = Evaluator { expr_ptr->span(), m_crate, NewvalState { *m_mod, *m_mod_path, ty_name } };
+ auto nvs = NewvalState { *m_mod, *m_mod_path, ty_name };
+ auto eval = ::HIR::Evaluator { expr_ptr->span(), m_crate, nvs };
auto val = eval.evaluate_constant(::HIR::ItemPath(*m_mod_path, ty_name.c_str()), expr_ptr, ::HIR::CoreType::Usize);
if( !val.is_Integer() )
ERROR(expr_ptr->span(), E0000, "Array size isn't an integer");
@@ -939,29 +1107,60 @@ namespace {
}
DEBUG("Array " << ty << " - size = " << e.size_val);
)
+
+ if( m_recurse_types )
+ {
+ m_recurse_types = false;
+ if( const auto* te = ty.m_data.opt_Path() )
+ {
+ TU_MATCH_HDRA( (te->binding), {)
+ TU_ARMA(Unbound, _) {
+ }
+ TU_ARMA(Opaque, _) {
+ }
+ TU_ARMA(Struct, pbe) {
+ // If this struct hasn't been visited already, visit it
+ this->visit_struct(te->path.m_data.as_Generic().m_path, const_cast<::HIR::Struct&>(*pbe));
+ }
+ TU_ARMA(Union, pbe) {
+ }
+ TU_ARMA(Enum, pbe) {
+ }
+ TU_ARMA(ExternType, pbe) {
+ }
+ }
+ }
+ m_recurse_types = true;
+ }
}
void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override
{
+ m_recurse_types = true;
::HIR::Visitor::visit_constant(p, item);
+ m_recurse_types = false;
// NOTE: Consteval needed here for MIR match generation to work
- if( item.m_value )
+ if( item.m_value || item.m_value.m_mir )
{
- auto eval = Evaluator { item.m_value->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } };
- item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone());
+ auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "#") };
+ auto eval = ::HIR::Evaluator { item.m_value.span(), m_crate, nvs };
+ item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone(), m_monomorph_state.clone());
- check_lit_type(item.m_value->span(), item.m_type, item.m_value_res);
+ check_lit_type(item.m_value.span(), item.m_type, item.m_value_res);
DEBUG("constant: " << item.m_type << " = " << item.m_value_res);
}
}
void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override
{
+ m_recurse_types = true;
::HIR::Visitor::visit_static(p, item);
+ m_recurse_types = false;
if( item.m_value )
{
- auto eval = Evaluator { item.m_value->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } };
+ auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "#") };
+ auto eval = ::HIR::Evaluator { item.m_value->span(), m_crate, nvs };
item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone());
check_lit_type(item.m_value->span(), item.m_type, item.m_value_res);
@@ -970,6 +1169,7 @@ namespace {
}
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
+ static Span sp;
if( auto* e = item.m_data.opt_Value() )
{
::HIR::TypeRef ty = ::HIR::CoreType::Isize;
@@ -978,7 +1178,8 @@ namespace {
{
if( var.expr )
{
- auto eval = Evaluator { var.expr->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") } };
+ auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "_" << var.name << "#") };
+ auto eval = ::HIR::Evaluator { var.expr->span(), m_crate, nvs };
auto val = eval.evaluate_constant(p, var.expr, ty.clone());
DEBUG("enum variant: " << p << "::" << var.name << " = " << val);
i = val.as_Integer();
@@ -989,6 +1190,15 @@ namespace {
}
::HIR::Visitor::visit_enum(p, item);
}
+ void visit_struct(::HIR::ItemPath p, ::HIR::Struct& item) override {
+ if( item.const_eval_state != HIR::ConstEvalState::Complete )
+ {
+ ASSERT_BUG(Span(), item.const_eval_state == HIR::ConstEvalState::None, "Constant evaluation loop involving " << p);
+ item.const_eval_state = HIR::ConstEvalState::Active;
+ ::HIR::Visitor::visit_struct(p, item);
+ item.const_eval_state = HIR::ConstEvalState::Complete;
+ }
+ }
void visit_expr(::HIR::ExprPtr& expr) override
{
@@ -1003,6 +1213,7 @@ namespace {
void visit_type(::HIR::TypeRef& ty) override {
// Need to evaluate array sizes
+ DEBUG("expr type " << ty);
m_exp.visit_type(ty);
}
void visit_path_params(::HIR::PathParams& pp) override {
@@ -1012,8 +1223,9 @@ namespace {
void visit(::HIR::ExprNode_ArraySized& node) override {
assert( node.m_size );
- auto name = FMT("array_" << &node << "$");
- auto eval = Evaluator { node.span(), m_exp.m_crate, NewvalState { *m_exp.m_mod, *m_exp.m_mod_path, name } };
+ auto name = FMT("array_" << &node << "#");
+ auto nvs = NewvalState { *m_exp.m_mod, *m_exp.m_mod_path, name };
+ auto eval = ::HIR::Evaluator { node.span(), m_exp.m_crate, nvs };
auto val = eval.evaluate_constant( ::HIR::ItemPath(*m_exp.m_mod_path, name.c_str()), node.m_size, ::HIR::CoreType::Usize );
if( !val.is_Integer() )
ERROR(node.span(), E0000, "Array size isn't an integer");
@@ -1025,7 +1237,9 @@ namespace {
if( expr.get() != nullptr )
{
Visitor v { *this };
+ //m_recurse_types = true;
(*expr).visit(v);
+ //m_recurse_types = false;
}
}
};
@@ -1047,7 +1261,7 @@ namespace {
{
// ::std::unique_ptr<VisEnt<ValueItem>>
::std::unique_ptr<::HIR::VisEnt<::HIR::ValueItem>> iv;
- iv.reset( new ::HIR::VisEnt<::HIR::ValueItem> { false, ::HIR::ValueItem::make_Static(mv$(v.second)) } );
+ iv.reset( new ::HIR::VisEnt<::HIR::ValueItem> { ::HIR::Publicity::new_none(), ::HIR::ValueItem::make_Static(mv$(v.second)) } );
mod.m_value_items.insert(::std::make_pair( v.first, mv$(iv) ));
}
mod.m_inline_statics.clear();
@@ -1066,3 +1280,10 @@ void ConvertHIR_ConstantEvaluate(::HIR::Crate& crate)
ExpanderApply().visit_crate(crate);
}
+void ConvertHIR_ConstantEvaluate_Expr(const ::HIR::Crate& crate, const ::HIR::ItemPath& ip, ::HIR::ExprPtr& expr_ptr)
+{
+ TRACE_FUNCTION_F(ip);
+ // Check innards but NOT the value
+ Expander exp { crate };
+ exp.visit_expr( expr_ptr );
+}