+definition exec_move ≝
+ cfg_to_obj · tape_move_obj · restart_tape prg 2 · obj_to_cfg.
+
+definition R_exec_move ≝ λt1,t2:Vector (tape FSUnialpha) 3.
+∀c,m,ls1,ls2,rs2.
+ nth cfg ? t1 (niltape ?) = mk_tape FSUnialpha (c::ls1@[bar]) (None ?) [ ] →
+ nth prg ? t1 (niltape ?) = midtape FSUnialpha (ls2@[bar]) m rs2 →
+ only_bits (list_of_tape ? (nth obj ? t1 (niltape ?))) →
+ c ≠ bar → m ≠ bar →
+ let new_obj ≝
+ tape_move_mono ? (nth obj ? t1 (niltape ?))
+ 〈char_to_bit_option c, char_to_move m〉 in
+ let next_c ≝ low_char' (current ? new_obj) in
+ let new_cfg ≝ midtape ? [ ] bar ((reverse ? ls1)@[next_c]) in
+ let new_prg ≝ midtape FSUnialpha [ ] bar ((reverse ? ls2)@m::rs2) in
+ t2 = Vector_of_list ? [new_obj;new_cfg;new_prg].
+
+
+lemma sem_exec_move: exec_move ⊨ R_exec_move.
+@(sem_seq_app ??????? sem_cfg_to_obj1
+ (sem_seq ?????? sem_tape_move_obj
+ (sem_seq ?????? (sem_restart_tape ???) sem_obj_to_cfg1))) //
+#ta #tout * #t1 * #semM1 * #t2 * #semM2 * #t3 * #semM3 #semM4
+#c #m #ls1 #ls2 #rs2 #Hcfg #Hprg #Honlybits #Hc #Hm
+(* M1 = cfg_to_obj *)
+lapply (semM1 … Hcfg Hc) #Ht1
+(* M2 = tape_move *)
+whd in semM2; >Ht1 in semM2; -Ht1
+>nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+>nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+>Hprg #Ht2 lapply (Ht2 … (refl ??)) -Ht2
+>nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+>nth_change_vec // >change_vec_commute [2:@eqb_false_to_not_eq %]
+>change_vec_change_vec #Ht2
+(* M3 = restart prg *)
+whd in semM3; >Ht2 in semM3; #semM3 lapply (semM3 … (refl ??)); -semM3
+>nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+>nth_change_vec_neq [2:@eqb_false_to_not_eq %] #Ht3
+(* M4 = obj_to_cfg *)
+whd in semM4; >Ht3 in semM4;
+>nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+>nth_change_vec [2:@leb_true_to_le %] #semM4 lapply (semM4 … (refl ??)) -semM4
+>nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+>nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+>nth_change_vec [2:@leb_true_to_le %] #semM4 >(semM4 ?)
+ [(* tape by tape *)
+ @(eq_vec … (niltape ?)) #i #lei2
+ cases (le_to_or_lt_eq … (le_S_S_to_le …lei2))
+ [#lei1 cases (le_to_or_lt_eq … (le_S_S_to_le …lei1))
+ [#lei0 lapply(le_n_O_to_eq … (le_S_S_to_le …lei0)) #eqi <eqi
+ >nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+ >nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+ >nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+ >nth_change_vec [2:@leb_true_to_le %] %
+ |#Hi >Hi (* obj tape *)
+ >nth_change_vec [2:@leb_true_to_le %] whd in ⊢ (???%);
+ >reverse_cons >reverse_append >reverse_single
+ whd in match (option_hd ??); whd in match (tail ??);
+ whd in ⊢ (??%?); %
+ ]
+ |#Hi >Hi (* prg tape *)
+ >nth_change_vec_neq [2:@eqb_false_to_not_eq %]
+ >nth_change_vec [2:@leb_true_to_le %] whd in ⊢ (???%);
+ >Hprg whd in match (list_of_tape ??); >reverse_append
+ >reverse_single %
+ ]
+ |#b #Hcurrent @(list_of_tape_write ? is_bit … (char_to_bit_option c) ? Honlybits)
+ [#b0 cases c
+ [#b1 whd in ⊢ (??%?→?); #Hbit destruct (Hbit) %
+ |whd in ⊢ (??%?→?); #Hbit destruct (Hbit)
+ |whd in ⊢ (??%?→?); #Hbit destruct (Hbit)
+ ]
+ |>(list_of_tape_move … (char_to_move m)) @current_in_list @Hcurrent
+ ]
+ ]
+qed.
+