From semantics.ts.stlc Require Export lang. Set Default Proof Using "Type". (* We declare two notation scopes, one for values and one for expressions. Afterwards, we add notations to them, which then do not interfere with any existing Coq notations. *) Declare Scope expr_scope. Declare Scope val_scope. Delimit Scope expr_scope with E. Delimit Scope val_scope with V. Bind Scope expr_scope with expr. Bind Scope val_scope with val. (* Values can be embedded into expressions with of_val and integers into expressions with LitInt. The following coercions allow us to omit the embeddings. With them (e1 v2 n3) desugars to (e3 (of_val v2) (LitInt n1)). *) Coercion of_val : val >-> expr. Coercion LitInt : Z >-> expr. Coercion LitIntV : Z >-> val. Coercion App : expr >-> Funclass. Coercion Var : string >-> expr. Notation "e1 + e2" := (Plus e1%E e2%E) : expr_scope. (* The breaking point '/ ' makes sure that the body of the λ: is indented by two spaces in case the whole λ: does not fit on a single line. *) Notation "λ: x , e" := (Lam x%binder e%E) (at level 200, x at level 1, e at level 200, format "'[' 'λ:' x , '/ ' e ']'") : expr_scope. Notation "λ: x y .. z , e" := (Lam x%binder (Lam y%binder .. (Lam z%binder e%E) ..)) (at level 200, x, y, z at level 1, e at level 200, format "'[' 'λ:' x y .. z , '/ ' e ']'") : expr_scope. Notation "λ: x , e" := (LamV x%binder e%E) (at level 200, x at level 1, e at level 200, format "'[' 'λ:' x , '/ ' e ']'") : val_scope. Notation "λ: x y .. z , e" := (LamV x%binder (Lam y%binder .. (Lam z%binder e%E) .. )) (at level 200, x, y, z at level 1, e at level 200, format "'[' 'λ:' x y .. z , '/ ' e ']'") : val_scope. Notation "'let:' x := e1 'in' e2" := (Lam x%binder e2%E e1%E) (only parsing, at level 200, x at level 1, e1, e2 at level 200 (*, format "'[' 'let:' x := '[' e1 ']' 'in' '/' e2 ']'" *) ) : expr_scope. Notation "e1 ;; e2" := (Lam BAnon e2%E e1%E) (at level 100, e2 at level 200, format "'[' '[hv' '[' e1 ']' ;; ']' '/' e2 ']'") : expr_scope.