summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir/expr_state.hpp2
-rw-r--r--src/hir/hir.hpp9
-rw-r--r--src/hir/hir_ops.cpp11
-rw-r--r--src/hir_conv/constant_evaluation.cpp49
-rw-r--r--src/hir_conv/main_bindings.hpp5
5 files changed, 76 insertions, 0 deletions
diff --git a/src/hir/expr_state.hpp b/src/hir/expr_state.hpp
index 6151fb6b..139c400d 100644
--- a/src/hir/expr_state.hpp
+++ b/src/hir/expr_state.hpp
@@ -23,6 +23,8 @@ public:
enum class Stage {
Created,
+ ConstEvalRequest,
+ ConstEval,
TypecheckRequest,
Typecheck,
MirRequest,
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index 06c6f740..bdfc8d0b 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -71,6 +71,13 @@ public:
friend ::std::ostream& operator<<(::std::ostream& os, const Publicity& x);
};
+enum class ConstEvalState
+{
+ None,
+ Active,
+ Complete,
+};
+
template<typename Ent>
struct VisEnt
{
@@ -323,6 +330,8 @@ public:
TraitMarkings m_markings;
StructMarkings m_struct_markings;
+
+ ConstEvalState const_eval_state = ConstEvalState::None;
};
extern ::std::ostream& operator<<(::std::ostream& os, const Struct::Repr& x);
class Union
diff --git a/src/hir/hir_ops.cpp b/src/hir/hir_ops.cpp
index a548b725..f187bafe 100644
--- a/src/hir/hir_ops.cpp
+++ b/src/hir/hir_ops.cpp
@@ -11,6 +11,7 @@
#include <hir_typeck/expr_visit.hpp> // for invoking typecheck
#include "item_path.hpp"
#include "expr_state.hpp"
+#include <hir_conv/main_bindings.hpp>
#include <hir_expand/main_bindings.hpp>
#include <mir/main_bindings.hpp>
@@ -1087,6 +1088,16 @@ const ::MIR::Function* HIR::Crate::get_or_gen_mir(const ::HIR::ItemPath& ip, con
auto& ep_mut = const_cast<::HIR::ExprPtr&>(ep);
+ // TODO: Ensure that all referenced items have constants evaluated
+ if( ep.m_state->stage < ::HIR::ExprState::Stage::ConstEval )
+ {
+ if( ep.m_state->stage == ::HIR::ExprState::Stage::ConstEvalRequest )
+ ERROR(Span(), E0000, "Loop in constant evaluation");
+ ep.m_state->stage = ::HIR::ExprState::Stage::ConstEvalRequest;
+ ConvertHIR_ConstantEvaluate_Expr(*this, ip, ep_mut);
+ ep.m_state->stage = ::HIR::ExprState::Stage::ConstEval;
+ }
+
// Ensure typechecked
if( ep.m_state->stage < ::HIR::ExprState::Stage::Typecheck )
{
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index 9149a417..35669dd9 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -961,12 +961,14 @@ namespace {
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
@@ -1105,10 +1107,37 @@ 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 || item.m_value.m_mir )
@@ -1124,7 +1153,9 @@ namespace {
}
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 )
{
@@ -1159,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
{
@@ -1197,7 +1237,9 @@ namespace {
if( expr.get() != nullptr )
{
Visitor v { *this };
+ //m_recurse_types = true;
(*expr).visit(v);
+ //m_recurse_types = false;
}
}
};
@@ -1238,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 );
+}
diff --git a/src/hir_conv/main_bindings.hpp b/src/hir_conv/main_bindings.hpp
index e2ec3e34..a7bc9de6 100644
--- a/src/hir_conv/main_bindings.hpp
+++ b/src/hir_conv/main_bindings.hpp
@@ -9,6 +9,8 @@
namespace HIR {
class Crate;
+ class ItemPath;
+ class ExprPtr;
};
extern void ConvertHIR_ExpandAliases(::HIR::Crate& crate);
@@ -17,3 +19,6 @@ extern void ConvertHIR_ResolveUFCS_Outer(::HIR::Crate& crate);
extern void ConvertHIR_ResolveUFCS(::HIR::Crate& crate);
extern void ConvertHIR_Markings(::HIR::Crate& crate);
extern void ConvertHIR_ConstantEvaluate(::HIR::Crate& hir_crate);
+
+extern void ConvertHIR_ConstantEvaluate_Expr(const ::HIR::Crate& crate, const ::HIR::ItemPath& ip, ::HIR::ExprPtr& exp);
+