diff options
-rw-r--r-- | src/mir/from_hir.hpp | 6 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 3 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 25 |
3 files changed, 33 insertions, 1 deletions
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index 11a18a6d..b11a380a 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -103,6 +103,11 @@ TAGGED_UNION(ScopeType, Owning, ::std::map<unsigned int,VarState> changed_args; bool exit_state_valid; SplitEnd exit_state; + }), + // State which should end up with no mutation of variable states + (Freeze, struct { + //::std::map<unsigned int,VarState> changed_slots; + //::std::map<unsigned int,VarState> changed_args; }) ); @@ -257,6 +262,7 @@ public: ScopeHandle new_scope_temp(const Span& sp); ScopeHandle new_scope_split(const Span& sp); ScopeHandle new_scope_loop(const Span& sp); + ScopeHandle new_scope_freeze(const Span& sp); /// Raises every variable defined in the source scope into the target scope void raise_all(const Span& sp, ScopeHandle src, const ScopeHandle& target); diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index cbb39b34..c10f170b 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -372,17 +372,18 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod ac.cond_start = builder.new_bb_unlinked(); builder.set_cur_block( ac.cond_start ); + auto freeze_scope = builder.new_scope_freeze(arm.m_cond->span()); auto tmp_scope = builder.new_scope_temp(arm.m_cond->span()); conv.visit_node_ptr( arm.m_cond ); auto cond_lval = builder.get_result_in_if_cond(arm.m_cond->span()); builder.terminate_scope( arm.m_code->span(), mv$(tmp_scope) ); ac.cond_false = builder.new_bb_unlinked(); builder.end_block(::MIR::Terminator::make_If({ mv$(cond_lval), ac.code, ac.cond_false })); - // TODO: Emit the `if` (to new blocks) and insert an early termination of the this split arm builder.set_cur_block(ac.cond_false); builder.end_split_arm(arm.m_cond->span(), match_scope, true, true); builder.pause_cur_block(); + builder.terminate_scope( arm.m_code->span(), mv$(freeze_scope) ); // NOTE: Paused so that later code (which knows what the false branch will be) can end it correctly diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 54269144..5dcb2ed2 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -745,6 +745,14 @@ ScopeHandle MirBuilder::new_scope_loop(const Span& sp) DEBUG("START (loop) scope " << idx); return ScopeHandle { *this, idx }; } +ScopeHandle MirBuilder::new_scope_freeze(const Span& sp) +{ + unsigned int idx = m_scopes.size(); + m_scopes.push_back( ScopeDef {sp, ScopeType::make_Freeze({})} ); + m_scope_stack.push_back( idx ); + DEBUG("START (freeze) scope " << idx); + return ScopeHandle { *this, idx }; +} void MirBuilder::terminate_scope(const Span& sp, ScopeHandle scope, bool emit_cleanup/*=true*/) { TRACE_FUNCTION_F("DONE scope " << scope.idx << " - " << (emit_cleanup ? "CLEANUP" : "NO CLEANUP")); @@ -1510,6 +1518,9 @@ void MirBuilder::complete_scope(ScopeDef& sd) DEBUG("Loop"); ), (Split, + ), + (Freeze, + //DEBUG("Freeze"); ) ) @@ -1886,6 +1897,18 @@ VarState& MirBuilder::get_slot_state_mut(const Span& sp, unsigned int idx, SlotT } } } + else if( scope_def.data.is_Freeze() ) + { + if( type == SlotType::Local && idx == m_if_cond_lval.as_Local() ) + { + } + else + { + // NOTE: This is only used in match conditions + DEBUG("Mutating state of ?" << idx); + ERROR(sp, E0000, "Attempting to move/initialise a value where not allowed"); + } + } else { } @@ -2159,6 +2182,8 @@ void MirBuilder::drop_scope_values(const ScopeDef& sd) ), (Loop, // No values + ), + (Freeze, ) ) } |