\begin{code}
{-# OPTIONS --cubical --safe #-}

module Snippets.Expr where

open import Prelude hiding (_⟨_⟩_; T; ; tt)

module DataTop where
\end{code}
%<*data-top>
\begin{code}
  data  : Type₀ where
    tt : 
\end{code}
%</data-top>
\begin{code}

open import Data.Unit
open import Data.Maybe
open import Data.Maybe.Sugar
open import Data.Nat hiding (_∸_)
open import Data.Nat.Properties using () renaming (_≤ᴮ_ to _≤_; _≡ᴮ_ to _≟_)

\end{code}
%<*op-def>
\begin{code}
data Op : Type₀ where
  +′  : Op
  ×′  : Op
  -′  : Op
  ÷′  : Op
\end{code}
%</op-def>
%<*expr-def>
\begin{code}
data Expr : Type₀ where
  lit :   Expr
  _⟨_⟩_ : Expr  Op  Expr  Expr
\end{code}
%</expr-def>
\begin{code}
_ : Expr
_ =
\end{code}
%<*example-expr>
\begin{code}
  lit 4  +′  lit 5
\end{code}
%</example-expr>
\begin{code}
module IncorrectEval where
  open import Data.Nat renaming (_∸_ to _-_)
\end{code}
%<*incorrect-eval>
\begin{code}
  ⟦_⟧ : Expr  
   lit x  = x
   xs  +′   ys  =  xs  +  ys 
   xs  ×′   ys  =  xs  *  ys 
   xs  -′   ys  =  xs  -  ys 
   xs  ÷′   ys  with  ys 
   xs  ÷′   ys  | zero     = zero
   xs  ÷′   ys  | suc ys′  =  xs  ÷ suc ys′
\end{code}
%</incorrect-eval>
%<*safe-sub>
\begin{code}
_-_ :     Maybe 
n      - zero   = just n
suc n  - suc m  = n - m
zero   - suc m  = nothing
\end{code}
%</safe-sub>
\begin{code}
private
 module NoApplEval where
    ⟦_⟧ : Expr  Maybe 
\end{code}
%<*add-helper>
\begin{code}
     x  +′  y  = add-helper  x   y 
      where
      add-helper : Maybe   Maybe   Maybe 
      add-helper nothing   nothing   = nothing
      add-helper nothing   (just x)  = nothing
      add-helper (just x)  nothing   = nothing
      add-helper (just x)  (just y)  = just (x + y)
\end{code}
%</add-helper>
\begin{code}
     _  = nothing
private
 module ExplicitApplMonEval where
    ⟦_⟧ : Expr  Maybe 
\end{code}
%<*add-helper-app>
\begin{code}
     x  +′  y  = pure _+_ <*>  x  <*>  y 
\end{code}
%</add-helper-app>
%<*sub-bind>
\begin{code}
     x  -′  y  =
       x   >>= λ x′  
       y   >>= λ y′  
      x′ - y′
\end{code}
%</sub-bind>
\begin{code}
     _  = nothing
\end{code}
%<*eval-ty>
\begin{code}
⟦_⟧ : Expr  Maybe 
\end{code}
%</eval-ty>
%<*lit-case>
\begin{code}
 lit x  = just x
\end{code}
%</lit-case>
%<*appl-cases>
\begin{code}
 x  +′   y  =   x  +   y  
 x  ×′   y  =   x  *   y  
\end{code}
%</appl-cases>
%<*sub-case>
\begin{code}
 x  -′  y  =
  do  x′   x 
      y′   y 
      x′ - y′
\end{code}
%</sub-case>
%<*div-case>
\begin{code}
 x  ÷′  y  = do
  suc y′   y 
    where zero  nothing
  x′   x 
  guard (rem x′ (suc y′)  0)
  just (x′ ÷ suc y′)
\end{code}
%</div-case>
%<*is-just>
\begin{code}
is-just : Maybe A  Bool
is-just nothing   = false
is-just (just _)  = true
\end{code}
%</is-just>
%<*tee>
\begin{code}
T : Bool  Type₀
T true   = 
T false  = 
\end{code}
%</tee>
%<*valid>
\begin{code}
Valid : Expr  Type₀
Valid e = T (is-just  e )
\end{code}
%</valid>
\begin{code}
module StaticEvalExplicit where
\end{code}
%<*static-eval-explicit>
\begin{code}
  ⟦_⟧! : (e : Expr)  Valid e  
   e ⟧! v with  e 
   e ⟧! v | just x = x
\end{code}
%</static-eval-explicit>
\begin{code}
module StaticEvalRetrieve where
\end{code}
%<*retrieve-implicit>
\begin{code}
  ⟦_⟧! : (e : Expr)  { _ : Valid e }  
   e ⟧! { valid } with  e 
   e ⟧! { valid } | just x = x
\end{code}
%</retrieve-implicit>
%<*static-eval>
\begin{code}
⟦_⟧! : (e : Expr)  { _ : Valid e }  
 e ⟧! with  e 
 e ⟧! | just x = x
\end{code}
%</static-eval>
%<*example-eval>
\begin{code}
example-eval : Maybe 
example-eval =  lit 4  ×′  lit 2 
\end{code}
%</example-eval>
%<*pair>
\begin{code}
record Pair (A : Type a) (B : Type b) : Type (a ℓ⊔ b) where
  field
    fst  : A
    snd  : B
\end{code}
%</pair>
%<*example-static-eval>
\begin{code}
example-static-eval : 
example-static-eval =  lit 4  ×′  lit 2 ⟧!
\end{code}
%</example-static-eval>
%<*example-static-proof>
\begin{code}
example-static-proof :  lit 4  ×′  lit 2 ⟧!  8
example-static-proof = refl
\end{code}
%</example-static-proof>
%<*quot-expr>
\begin{code}
data Expr/ : Type₀ where
  lit/ :   Expr/
  _⟪_⟫_ : Expr/  Op  Expr/  Expr/
  +-comm :  x y  x  +′  y  y  +′  x
  trunc/ : (x y : Expr/)  (p q : x  y)  p  q
\end{code}
%</quot-expr>
\begin{code}
m-+-comm : (x y : Maybe )   x + y    y + x 
m-+-comm nothing nothing = refl
m-+-comm nothing (just x) = refl
m-+-comm (just x) nothing = refl
m-+-comm (just x) (just y) i = just (Data.Nat.Properties.+-comm x y i)

open import Data.Maybe.Properties

eval/ : Expr/  Maybe 
eval/ (lit/ x) = just x
eval/ (xs  +′  ys) =  eval/ xs + eval/ ys 
eval/ (xs  ×′  ys) =  eval/ xs * eval/ ys 
eval/ (xs  -′  ys) =
  do  x′  eval/ xs
      y′  eval/ ys
      x′ - y′
eval/ (xs  ÷′  ys) = do
  suc y′  eval/ ys
    where zero  nothing
  x′  eval/ xs
  guard (rem x′ (suc y′)  0)
  just (x′ ÷ suc y′)
eval/ (+-comm xs ys i) = m-+-comm (eval/ xs) (eval/ ys) i
eval/ (trunc/ x y p q i j) = Discrete→isSet (discreteMaybe Data.Nat.Properties.discreteℕ) (eval/ x) (eval/ y) (cong eval/ p) (cong eval/ q) i j
\end{code}