(*

{ initial_core : nat -> M -> C -> Values.val -> list Values.val -> Prop;
    at_external : C -> M -> option (AST.external_function * AST.signature * list Values.val);
    after_external : option Values.val -> C -> M -> option C;
    halted : C -> Integers.Int.int -> Prop;
    corestep : G -> C -> M -> C -> M -> Prop;
    corestep_not_at_external : forall (ge : G) (m : M) (q : C) (m' : M) (q' : C),
                               corestep ge q m q' m' -> at_external q m = None }

 *)

Inductive state_sum (Cs Ct:Type): Type :=
| SState (c:Cs)
| TState (c:Ct).(*

{ initial_core : nat -> M -> C -> Values.val -> list Values.val -> Prop;
    at_external : C -> M -> option (AST.external_function * AST.signature * list Values.val);
    after_external : option Values.val -> C -> M -> option C;
    halted : C -> Integers.Int.int -> Prop;
    corestep : G -> C -> M -> C -> M -> Prop;
    corestep_not_at_external : forall (ge : G) (m : M) (q : C) (m' : M) (q' : C),
                               corestep ge q m q' m' -> at_external q m = None }

 *)

Inductive state_sum (Cs Ct:Type): Type :=
| SState (c:Cs)
| TState (c:Ct).(*

{ initial_core : nat -> M -> C -> Values.val -> list Values.val -> Prop;
    at_external : C -> M -> option (AST.external_function * AST.signature * list Values.val);
    after_external : option Values.val -> C -> M -> option C;
    halted : C -> Integers.Int.int -> Prop;
    corestep : G -> C -> M -> C -> M -> Prop;
    corestep_not_at_external : forall (ge : G) (m : M) (q : C) (m' : M) (q' : C),
                               corestep ge q m q' m' -> at_external q m = None }

 *)

Inductive state_sum (Cs Ct:Type): Type :=
| SState (c:Cs)
| TState (c:Ct).Definition state_sum_options {Cs Ct:Type} (cso: option Cs): option (state_sum Cs Ct) :=
  match cso with
  | Some cs => Some (SState _ _ cs)
  | _ => None
  end.Definition state_sum_optiont {Cs Ct:Type} (cto: option Ct): option (state_sum Cs Ct) :=
  match cto with
  | Some ct => Some (TState _ _ ct)
  | _ => None
  end.Definition state_sum_optionms {Cs Ct M:Type} (cso: option (Cs * option M)): option (state_sum Cs Ct * option M) :=
  match cso with
  | Some (cs, m) => Some (SState _ _ cs, m)
  | _ => None
  end.Definition state_sum_optionmt {Cs Ct M:Type} (cto: option (Ct * option M)): option (state_sum Cs Ct * option M) :=
  match cto with
  | Some (ct, m) => Some (TState _ _ ct, m)
  | _ => None
  end.Definition lt_op (n: nat) (no:option nat): Prop :=
  match no with
    | None => False
    | Some n' => n < n' 
  end.Definition initial_core_sum (no:option nat) (Cs Ct:Type) (M: Type)
           (sinitial_core : nat -> M -> Cs -> M -> Values.val -> list Values.val -> Prop)
           (tinitial_core : nat -> M -> Ct -> M -> Values.val -> list Values.val -> Prop):
  nat -> M -> state_sum Cs Ct -> M -> Values.val -> list Values.val -> Prop :=
  fun (n:nat) m c m' val vals =>
    match c with
    | SState c => lt_op n no /\ sinitial_core n m c m' val vals
    | TState c => ~lt_op n no /\ tinitial_core n m c m' val vals
    end.Definition sum_func {Cs Ct X:Type} (fs:Cs -> X) (ft:Ct-> X) s:=
  match s with
  | SState c => (fs c)
  | TState c => (ft c)
  end.Definition sum_func_option {Cs Ct Cs' Ct':Type} 
           (fs: Cs -> option Cs') (ft: Ct-> option Ct') s:=
  match s with
  | SState c => state_sum_options (fs c) 
  | TState c => state_sum_optiont (ft c) 
  end.Definition at_external_sum (Cs Ct M: Type)
           (sat_external: Cs -> M -> option (AST.external_function * list Values.val))
           (tat_external: Ct -> M -> option (AST.external_function * list Values.val))
           :=
  sum_func sat_external tat_external.Definition after_external_sum (Cs Ct M: Type)
           (safter_external: option Values.val -> Cs -> M -> option Cs)
           (tafter_external: option Values.val -> Ct -> M -> option Ct)
           :=
  fun vals c m => sum_func_option (fun c => safter_external vals c m)
                                  (fun c => tafter_external vals c m) c.Definition halted_sum Cs Ct
           (shalted: Cs -> Integers.Int.int -> Prop)
           (thalted: Ct -> Integers.Int.int -> Prop) :=
  sum_func shalted thalted.Inductive corestep_sum {M Cs Ct}
          (scorestep: Cs -> M -> Cs -> M -> Prop)
          (tcorestep: Ct -> M -> Ct -> M -> Prop):
  state_sum Cs Ct -> M -> state_sum Cs Ct -> M -> Prop:=
| SCorestep: forall s m s' m',
    scorestep s m s' m' ->
    corestep_sum scorestep tcorestep (SState _ _ s) m (SState _ _ s') m'
| TCorestep: forall s m s' m',
    tcorestep s m s' m' ->
    corestep_sum scorestep tcorestep (TState _ _ s) m (TState _ _ s') m'.Inductive corestep_sum {M Cs Ct}
          (scorestep: Cs -> M -> Cs -> M -> Prop)
          (tcorestep: Ct -> M -> Ct -> M -> Prop):
  state_sum Cs Ct -> M -> state_sum Cs Ct -> M -> Prop:=
| SCorestep: forall s m s' m',
    scorestep s m s' m' ->
    corestep_sum scorestep tcorestep (SState _ _ s) m (SState _ _ s') m'
| TCorestep: forall s m s' m',
    tcorestep s m s' m' ->
    corestep_sum scorestep tcorestep (TState _ _ s) m (TState _ _ s') m'.Inductive corestep_sum {M Cs Ct}
          (scorestep: Cs -> M -> Cs -> M -> Prop)
          (tcorestep: Ct -> M -> Ct -> M -> Prop):
  state_sum Cs Ct -> M -> state_sum Cs Ct -> M -> Prop:=
| SCorestep: forall s m s' m',
    scorestep s m s' m' ->
    corestep_sum scorestep tcorestep (SState _ _ s) m (SState _ _ s') m'
| TCorestep: forall s m s' m',
    tcorestep s m s' m' ->
    corestep_sum scorestep tcorestep (TState _ _ s) m (TState _ _ s') m'.

Lemma corestep_not_at_external_sum: forall M Cs Ct {scorestep: Cs -> M -> Cs -> M -> Prop} {sat_external: Cs -> M -> option (AST.external_function * list Values.val)} (scorestep_not_at_external: forall (m : M) (q : Cs) (m' : M) (q' : Cs), scorestep q m q' m' -> sat_external q m = None) {tcorestep: Ct -> M -> Ct -> M -> Prop} {tat_external: Ct -> M -> option (AST.external_function * list Values.val)} (tcorestep_not_at_external: forall (m : M) (q : Ct) (m' : M) (q' : Ct), tcorestep q m q' m' -> tat_external q m = None), forall (m : M) (q : state_sum Cs Ct) (m' : M) (q' : state_sum Cs Ct), corestep_sum scorestep tcorestep q m q' m' -> at_external_sum _ _ _ sat_external tat_external q m = None.