summaryrefslogtreecommitdiff
path: root/src/mir/check.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mir/check.cpp')
-rw-r--r--src/mir/check.cpp287
1 files changed, 3 insertions, 284 deletions
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index aa76139f..24157f41 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -9,293 +9,12 @@
#include "mir.hpp"
#include <hir/visitor.hpp>
#include <hir_typeck/static.hpp>
+#include <mir/helpers.hpp>
-namespace {
- const unsigned int STMT_TERM = ~0u;
-
- #define MIR_BUG(state, ...) ( (state).print_bug( [&](auto& _os){_os << __VA_ARGS__; } ) )
- #define MIR_ASSERT(state, cnd, ...) do { if( !(cnd) ) (state).print_bug( [&](auto& _os){_os << "ASSERT " #cnd " failed - " << __VA_ARGS__; } ); } while(0)
- #define MIR_TODO(state, ...) ( (state).print_todo( [&](auto& _os){_os << __VA_ARGS__; } ) )
-
- struct MirCheckFailure {
- };
-
- struct State {
- typedef ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > t_args;
-
- const StaticTraitResolve& resolve;
- const ::HIR::ItemPath& path;
- const ::MIR::Function& fcn;
- const t_args& args;
- const ::HIR::TypeRef& ret_type;
-
- unsigned int bb_idx = 0;
- unsigned int stmt_idx = 0;
- const ::HIR::SimplePath* m_lang_Box;
-
- Span sp;
-
- State(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::MIR::Function& fcn, const t_args& args, const ::HIR::TypeRef& ret_type):
- resolve(resolve),
- path(path),
- fcn(fcn),
- args(args),
- ret_type(ret_type)
- {
- if( resolve.m_crate.m_lang_items.count("owned_box") > 0 ) {
- m_lang_Box = &resolve.m_crate.m_lang_items.at("owned_box");
- }
- }
-
- void set_cur_stmt(unsigned int bb_idx, unsigned int stmt_idx) {
- this->bb_idx = bb_idx;
- this->stmt_idx = stmt_idx;
- }
- void set_cur_stmt_term(unsigned int bb_idx) {
- this->bb_idx = bb_idx;
- this->stmt_idx = STMT_TERM;
- }
-
- void print_bug(::std::function<void(::std::ostream& os)> cb) const {
- print_msg("ERROR", cb);
- }
- void print_todo(::std::function<void(::std::ostream& os)> cb) const {
- print_msg("TODO", cb);
- }
- void print_msg(const char* tag, ::std::function<void(::std::ostream& os)> cb) const
- {
- auto& os = ::std::cerr;
- os << "MIR " << tag << ": " << this->path << " BB" << this->bb_idx << "/";
- if( this->stmt_idx == STMT_TERM ) {
- os << "TERM";
- }
- else {
- os << this->stmt_idx;
- }
- os << ": ";
- cb(os);
- os << ::std::endl;
- // TODO: Throw something? Or mark an error so the rest of the function can be checked.
- throw MirCheckFailure {};
- }
-
- const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const
- {
- TU_MATCH(::MIR::LValue, (val), (e),
- (Variable,
- return this->fcn.named_variables.at(e);
- ),
- (Temporary,
- return this->fcn.temporaries.at(e.idx);
- ),
- (Argument,
- return this->args.at(e.idx).second;
- ),
- (Static,
- TU_MATCHA( (e.m_data), (pe),
- (Generic,
- MIR_ASSERT(*this, pe.m_params.m_types.empty(), "Path params on static");
- const auto& s = resolve.m_crate.get_static_by_path(sp, pe.m_path);
- return s.m_type;
- ),
- (UfcsKnown,
- MIR_TODO(*this, "LValue::Static - UfcsKnown - " << e);
- ),
- (UfcsUnknown,
- MIR_BUG(*this, "Encountered UfcsUnknown in LValue::Static - " << e);
- ),
- (UfcsInherent,
- MIR_TODO(*this, "LValue::Static - UfcsInherent - " << e);
- )
- )
- ),
- (Return,
- return this->ret_type;
- ),
- (Field,
- const auto& ty = this->get_lvalue_type(tmp, *e.val);
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
- (
- MIR_BUG(*this, "Field access on unexpected type - " << ty);
- ),
- // Array and Slice use LValue::Field when the index is constant and known-good
- (Array,
- return *te.inner;
- ),
- (Slice,
- return *te.inner;
- ),
- (Tuple,
- MIR_ASSERT(*this, e.field_index < te.size(), "Field index out of range in tuple " << e.field_index << " >= " << te.size());
- return te[e.field_index];
- ),
- (Path,
- MIR_ASSERT(*this, te.binding.is_Struct(), "Field on non-Struct - " << ty);
- const auto& str = *te.binding.as_Struct();
- TU_MATCHA( (str.m_data), (se),
- (Unit,
- MIR_BUG(*this, "Field on unit-like struct - " << ty);
- ),
- (Tuple,
- MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in tuple-struct");
- const auto& fld = se[e.field_index];
- if( monomorphise_type_needed(fld.ent) ) {
- tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, fld.ent);
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- }
- else {
- return fld.ent;
- }
- ),
- (Named,
- MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in struct");
- const auto& fld = se[e.field_index].second;
- if( monomorphise_type_needed(fld.ent) ) {
- tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, fld.ent);
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- }
- else {
- return fld.ent;
- }
- )
- )
- )
- )
- ),
- (Deref,
- const auto& ty = this->get_lvalue_type(tmp, *e.val);
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
- (
- MIR_BUG(*this, "Deref on unexpected type - " << ty);
- ),
- (Path,
- if( const auto* inner_ptr = this->is_type_owned_box(ty) )
- {
- return *inner_ptr;
- }
- else {
- MIR_BUG(*this, "Deref on unexpected type - " << ty);
- }
- ),
- (Pointer,
- return *te.inner;
- ),
- (Borrow,
- return *te.inner;
- )
- )
- ),
- (Index,
- const auto& ty = this->get_lvalue_type(tmp, *e.val);
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
- (
- MIR_BUG(*this, "Index on unexpected type - " << ty);
- ),
- (Slice,
- return *te.inner;
- ),
- (Array,
- return *te.inner;
- )
- )
- ),
- (Downcast,
- const auto& ty = this->get_lvalue_type(tmp, *e.val);
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
- (
- MIR_BUG(*this, "Downcast on unexpected type - " << ty);
- ),
- (Path,
- MIR_ASSERT(*this, te.binding.is_Enum() || te.binding.is_Union(), "Downcast on non-Enum");
- if( te.binding.is_Enum() )
- {
- const auto& enm = *te.binding.as_Enum();
- const auto& variants = enm.m_variants;
- MIR_ASSERT(*this, e.variant_index < variants.size(), "Variant index out of range");
- const auto& variant = variants[e.variant_index];
- // TODO: Make data variants refer to associated types (unify enum and struct handling)
- TU_MATCHA( (variant.second), (ve),
- (Value,
- ),
- (Unit,
- ),
- (Tuple,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.ent) );
- tmp = ::HIR::TypeRef( mv$(tys) );
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- ),
- (Struct,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.second.ent) );
- tmp = ::HIR::TypeRef( mv$(tys) );
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- )
- )
- }
- else
- {
- const auto& unm = *te.binding.as_Union();
- MIR_ASSERT(*this, e.variant_index < unm.m_variants.size(), "Variant index out of range");
- const auto& variant = unm.m_variants[e.variant_index];
- const auto& var_ty = variant.second.ent;
-
- if( monomorphise_type_needed(var_ty) ) {
- tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, variant.second.ent);
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
- }
- else {
- return var_ty;
- }
- }
- )
- )
- )
- )
- throw "";
- }
-
- const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const
- {
- if( m_lang_Box )
- {
- if( ! ty.m_data.is_Path() ) {
- return nullptr;
- }
- const auto& te = ty.m_data.as_Path();
-
- if( ! te.path.m_data.is_Generic() ) {
- return nullptr;
- }
- const auto& pe = te.path.m_data.as_Generic();
-
- if( pe.m_path != *m_lang_Box ) {
- return nullptr;
- }
- // TODO: Properly assert?
- return &pe.m_params.m_types.at(0);
- }
- else
- {
- return nullptr;
- }
- }
- };
-}
-
-void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::MIR::Function& fcn, const State::t_args& args, const ::HIR::TypeRef& ret_type)
+void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type)
{
Span sp;
- State state { resolve, path, fcn, args, ret_type };
+ ::MIR::TypeResolve state { sp, resolve, FMT_CB(ss, ss << path;), ret_type, args, fcn };
// Validation rules:
// [CFA] = Control Flow Analysis