Lvc.IL.ILN

Require Import List.
Require Export Util Var Val Exp Env Map CSet AutoIndTac IL Bisim Infra.Status Pos.

Set Implicit Arguments.

Inductive nstmt : Type :=
| nstmtLet (x : var) (e: exp) (s : nstmt)
| nstmtIf (e : exp) (s : nstmt) (t : nstmt)
| nstmtApp (l : lab) (Y:args)
| nstmtReturn (e : exp)
| nstmtExtern (x : var) (f:external) (Y:args) (s:nstmt)

| nstmtFun (l : lab) (Z:params) (s : nstmt) (t : nstmt).

Fixpoint freeVars (s:nstmt) : set var :=
  match s with
    | nstmtLet x e s0(freeVars s0 \ {{x}}) Exp.freeVars e
    | nstmtIf e s1 s2freeVars s1 freeVars s2 Exp.freeVars e
    | nstmtApp l Ylist_union (List.map Exp.freeVars Y)
    | nstmtReturn eExp.freeVars e
    | nstmtExtern x f Y s(freeVars s \ {{x}}) list_union (List.map Exp.freeVars Y)
    | nstmtFun l Z s1 s2(freeVars s1 \ of_list Z) freeVars s2
  end.

Functional Semantics

Module F.

  Inductive block : Type :=
    blockI {
        block_L : onv block;
        block_E : onv val;
        block_F : lab × params × nstmt
      }.

  Definition labenv := onv block.
  Definition state : Type := (labenv × onv val × nstmt)%type.

  Inductive step : stateeventstateProp :=
  | nstepExp L E x e b v
    (def:exp_eval E e = Some v)
    : step (L, E, nstmtLet x e b) EvtTau (L, E[x<-Some v], b)

  | nstepIfT L E
    (e:exp) b1 b2 v
    (def:exp_eval E e = Some v)
    (condTrue: val2bool v = true)
    : step (L, E, nstmtIf e b1 b2) EvtTau (L, E, b1)

  | nstepIfF L E
    (e:exp) b1 b2 v
    (def:exp_eval E e = Some v)
    (condFalse:val2bool v = false)
    : step (L, E, nstmtIf e b1 b2) EvtTau (L, E, b2)


  | nstepGoto (L:labenv) (E:onv val) (l :lab) Y Z (s:nstmt)
    (len:length Z = length Y)
    (lEQ:l = )

    (Ldef:L (counted l) = Some (blockI (,Z,s))) E´´ vl
    (def:omap (exp_eval E) Y = Some vl)
    (updOk:[Z <-- List.map Some vl] = E´´)
    : step (L, E, nstmtApp l Y)
           EvtTau
           ([(counted l) <- Some (blockI (l,Z,s))], E´´, s)

  | stepLet L E f s Z t
    : step (L, E, nstmtFun f Z s t) EvtTau (L[counted f <- Some (blockI L E (f,Z,s))], E, t)

  | stepExtern L E x f Y s vl v
    (def:omap (exp_eval E) Y = Some vl)
    : step (L, E, nstmtExtern x f Y s)
            (EvtExtern (ExternI f vl v))
            (L, E[x <- Some v], s).

  Lemma step_internally_deterministic :
    internally_deterministic step.

  Lemma step_dec
  : reddec step.

End F.

Imperative Semantics

Module I.

  Inductive block : Type :=
    blockI {
        block_L : onv block;
        block_F : lab × params × nstmt
      }.

  Definition labenv := onv block.
  Definition state : Type := (labenv × onv val × nstmt)%type.
  Definition labenv_empty : labenv := fun _None.

  Inductive step : stateeventstateProp :=
  | nstepExp L E x e b v
    (def:exp_eval E e = Some v)
    : step (L, E, nstmtLet x e b) EvtTau (L, E[x<-Some v], b)

  | nstepIfT L E
    (e:exp) b1 b2 v
    (def:exp_eval E e = Some v)
    (condTrue: val2bool v = true)
    : step (L, E, nstmtIf e b1 b2) EvtTau (L, E, b1)

  | nstepIfF L E
    (e:exp) b1 b2 v
    (def:exp_eval E e = Some v)
    (condFalse:val2bool v = false)
    : step (L, E, nstmtIf e b1 b2) EvtTau (L, E, b2)

  | nstepGoto (L:labenv) (E:onv val) (l :lab) Y Z (s:nstmt) vl
    (len:length Z = length Y)
    (lEQ: l = )
    (Ldef:L (counted l) = Some (blockI (,Z,s))) E´´
    (def:omap (exp_eval E) Y = Some vl)
    (updOk:E [Z <-- List.map Some vl] = E´´)
    : step (L, E, nstmtApp l Y)
           EvtTau
           ([(counted l) <- Some (blockI (l,Z,s))], E´´, s)

  | stepLet L E f s Z t
    : step (L, E, nstmtFun f Z s t)
           EvtTau
           (L[counted f <- Some (blockI L (f,Z,s))], E, t)

  | stepExtern L E x f Y s vl v
    (def:omap (exp_eval E) Y = Some vl)
    : step (L, E, nstmtExtern x f Y s)
            (EvtExtern (ExternI f vl v))
            (L, E[x <- Some v], s).

  Lemma step_internally_deterministic :
    internally_deterministic step.

  Lemma step_externally_determined
  : externally_determined step.

  Lemma step_dec
  : reddec step.

End I.

Fixpoint labIndices (s:nstmt) (symb: list lab) : status stmt :=
  match s with
    | nstmtLet x e ssdo <- (labIndices s symb); Success (stmtLet x e )
    | nstmtIf x s1 s2
      sdo s1´ <- (labIndices s1 symb);
      sdo s2´ <- (labIndices s2 symb);
      Success (stmtIf x s1´ s2´)
    | nstmtApp l Y
      sdo f <- option2status (pos symb l 0) "labIndices: Undeclared function" ; Success (stmtApp (LabI f) Y)
    | nstmtReturn xSuccess (stmtReturn x)
    | nstmtExtern x f Y s
      sdo <- (labIndices s symb); Success (stmtExtern x f Y )
    | nstmtFun l Z s1 s2
      sdo s1´ <- labIndices s1 (l::symb);
      sdo s2´ <- labIndices s2 (l::symb);
      Success (stmtFun Z s1´ s2´)
  end.

Definition state_result X (s:X×onv val×nstmt) : option val :=
  match s with
    | (_, E, nstmtReturn e)exp_eval E e
    | _None
  end.

Instance statetype_I : StateType I.state := {
  step := I.step;
  result := (@state_result I.labenv);
  step_dec := I.step_dec;
  step_internally_deterministic := I.step_internally_deterministic;
  step_externally_determined := I.step_externally_determined
}.

Inductive lab_approx : list labenv (option I.block) → list IL.I.blockProp :=
  Lai symb L
    (LEQ: f s Z Lb,
             L (counted f) = Some (I.blockI Lb (,Z,s))
             → i ,
                 get i (IL.I.blockI Z )
                  labIndices s (drop i symb) = Success
                  pos symb f 0 = Some i lab_approx (drop (S i) symb) (Lb ) (drop (S i) )
                  ( l b, Lb (counted l) = Some bfst (fst (I.block_F b)) = l)
                  ( f k, pos (drop (S i) symb) f k = Some Lb (counted f) None)
                  f = )
  : lab_approx symb L .

Inductive labIndicesSim : I.stateIL.I.stateProp :=
  | labIndicesSimI (L:env (option I.block)) E s symb
    (EQ:labIndices s symb = Success )
    (LA:lab_approx symb L )
    (LL: l b, L (counted l) = Some bfst (fst (I.block_F b)) = l)
    (EX: f i k, pos symb f k = Some iL (counted f) None)
  : labIndicesSim (L, E, s) (, E, ).

Lemma pos_drop_eq symb (l:lab) x
: pos symb l 0 = Some x
  → drop x symb = l::tl (drop x symb).

Lemma pos_plus symb (f:lab) n i
: pos symb f 0 = Some (n + i)
  → pos (drop n symb) f 0 = Some i.

Lemma labIndicesSim_sim σ1 σ2
  : labIndicesSim σ1 σ2bisim σ1 σ2.