diff options
-rw-r--r-- | src/hir/expr_state.hpp | 2 | ||||
-rw-r--r-- | src/hir/hir.hpp | 9 | ||||
-rw-r--r-- | src/hir/hir_ops.cpp | 11 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 49 | ||||
-rw-r--r-- | src/hir_conv/main_bindings.hpp | 5 |
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); + |