Library iris.proofmode.intro_patterns

From iris.prelude Require Export strings.

Inductive intro_pat :=
  | IName : string intro_pat
  | IAnom : intro_pat
  | IAnomPure : intro_pat
  | IDrop : intro_pat
  | IFrame : intro_pat
  | IRelevant : intro_pat intro_pat
  | IList : list (list intro_pat) intro_pat
  | ISimpl : intro_pat
  | IAlways : intro_pat
  | IAffine : intro_pat
  | INext : intro_pat
  | IForall : intro_pat
  | IAll : intro_pat
  | IClear : list (bool × string) intro_pat.
Module intro_pat.
Inductive token :=
  | TName : string token
  | TAnom : token
  | TAnomPure : token
  | TDrop : token
  | TFrame : token
  | TRelevant : token
  | TAffine : token
  | TBar : token
  | TBracketL : token
  | TBracketR : token
  | TAmp : token
  | TParenL : token
  | TParenR : token
  | TSimpl : token
  | TAlways : token
  | TNext : token
  | TClearL : token
  | TClearR : token
  | TForall : token
  | TAll : token.

Fixpoint cons_name (kn : string) (k : list token) : list token :=
  match kn with "" ⇒ k | _TName (string_rev kn) :: k end.
Fixpoint tokenize_go (s : string) (k : list token) (kn : string) : list token :=
  match s with
  | "" ⇒ rev (cons_name kn k)
  | String " " stokenize_go s (cons_name kn k) ""
  | String "?" stokenize_go s (TAnom :: cons_name kn k) ""
  | String "%" stokenize_go s (TAnomPure :: cons_name kn k) ""
  | String "_" stokenize_go s (TDrop :: cons_name kn k) ""
  | String "$" stokenize_go s (TFrame :: cons_name kn k) ""
  | String "#" stokenize_go s (TRelevant :: cons_name kn k) ""
  | String "[" stokenize_go s (TBracketL :: cons_name kn k) ""
  | String "]" stokenize_go s (TBracketR :: cons_name kn k) ""
  | String "|" stokenize_go s (TBar :: cons_name kn k) ""
  | String "(" stokenize_go s (TParenL :: cons_name kn k) ""
  | String ")" stokenize_go s (TParenR :: cons_name kn k) ""
  | String "&" stokenize_go s (TAmp :: cons_name kn k) ""
  | String "!" stokenize_go s (TAlways :: cons_name kn k) ""
  | String "@" stokenize_go s (TAffine :: cons_name kn k) ""
  | String ">" stokenize_go s (TNext :: cons_name kn k) ""
  | String "{" stokenize_go s (TClearL :: cons_name kn k) ""
  | String "}" stokenize_go s (TClearR :: cons_name kn k) ""
  | String "/" (String "=" s) ⇒ tokenize_go s (TSimpl :: cons_name kn k) ""
  | String "*" (String "*" s) ⇒ tokenize_go s (TAll :: cons_name kn k) ""
  | String "*" stokenize_go s (TForall :: cons_name kn k) ""
  | String a stokenize_go s k (String a kn)
  end.
Definition tokenize (s : string) : list token := tokenize_go s [] "".

Inductive stack_item :=
  | SPat : intro_pat stack_item
  | SRelevant : stack_item
  | SList : stack_item
  | SConjList : stack_item
  | SBar : stack_item
  | SAmp : stack_item.
Notation stack := (list stack_item).

Fixpoint close_list (k : stack)
    (ps : list intro_pat) (pss : list (list intro_pat)) : option stack :=
  match k with
  | SList :: kSome (SPat (IList (ps :: pss)) :: k)
  | SPat pat :: kclose_list k (pat :: ps) pss
  | SRelevant :: k
     '(p,ps) maybe2 (::) ps; close_list k (IRelevant p :: ps) pss
  | SBar :: kclose_list k [] (ps :: pss)
  | _None
  end.

Fixpoint big_conj (ps : list intro_pat) : intro_pat :=
  match ps with
  | []IList [[]]
| [p]IList [[ p ]]
| [p1;p2]IList [[ p1 ; p2 ]]
| p :: psIList [[ p ; big_conj ps ]]
end.

Fixpoint close_conj_list (k : stack)
    (cur : option intro_pat) (ps : list intro_pat) : option stack :=
  match k with
  | SConjList :: k
     ps match cur with
          | Noneguard (ps = []); Some [] | Some pSome (p :: ps)
          end;
     Some (SPat (big_conj ps) :: k)
  | SPat pat :: kguard (cur = None); close_conj_list k (Some pat) ps
  | SRelevant :: kp cur; close_conj_list k (Some (IRelevant p)) ps
  | SAmp :: kp cur; close_conj_list k None (p :: ps)
  | _None
  end.

Fixpoint parse_go (ts : list token) (k : stack) : option stack :=
  match ts with
  | []Some k
  | TName s :: tsparse_go ts (SPat (IName s) :: k)
  | TAnom :: tsparse_go ts (SPat IAnom :: k)
  | TAnomPure :: tsparse_go ts (SPat IAnomPure :: k)
  | TDrop :: tsparse_go ts (SPat IDrop :: k)
  | TFrame :: tsparse_go ts (SPat IFrame :: k)
  | TRelevant :: tsparse_go ts (SRelevant :: k)
  | TBracketL :: tsparse_go ts (SList :: k)
  | TBar :: tsparse_go ts (SBar :: k)
  | TBracketR :: tsclose_list k [] [] ≫= parse_go ts
  | TParenL :: tsparse_go ts (SConjList :: k)
  | TAmp :: tsparse_go ts (SAmp :: k)
  | TParenR :: tsclose_conj_list k None [] ≫= parse_go ts
  | TSimpl :: tsparse_go ts (SPat ISimpl :: k)
  | TAlways :: tsparse_go ts (SPat IAlways :: k)
  | TAffine :: tsparse_go ts (SPat IAffine :: k)
  | TNext :: tsparse_go ts (SPat INext :: k)
  | TAll :: tsparse_go ts (SPat IAll :: k)
  | TForall :: tsparse_go ts (SPat IForall :: k)
  | TClearL :: tsparse_clear ts [] k
  | _None
  end
with parse_clear (ts : list token)
    (ss : list (bool × string)) (k : stack) : option stack :=
  match ts with
  | TFrame :: TName s :: tsparse_clear ts ((true,s) :: ss) k
  | TName s :: tsparse_clear ts ((false,s) :: ss) k
  | TClearR :: tsparse_go ts (SPat (IClear (reverse ss)) :: k)
  | _None
  end.

Definition parse (s : string) : option (list intro_pat) :=
  match k parse_go (tokenize s) [SList]; close_list k [] [] with
  | Some [SPat (IList [ps])]Some ps
  | _None
  end.

Ltac parse s :=
  lazymatch type of s with
  | list intro_pats
  | list string
     lazymatch eval vm_compute in (mjoin <$> mapM parse s) with
     | Some ?patspats | _fail "invalid list intro_pat" s
     end
  | string
     lazymatch eval vm_compute in (parse s) with
     | Some ?patspats | _fail "invalid list intro_pat" s
     end
  end.
Ltac parse_one s :=
  lazymatch type of s with
  | intro_pats
  | string
     lazymatch eval vm_compute in (parse s) with
     | Some [?pat]pat | _fail "invalid intro_pat" s
     end
  end.
End intro_pat.