summaryrefslogtreecommitdiff
path: root/src/Helium
diff options
context:
space:
mode:
authorGreg Brown <greg.brown@cl.cam.ac.uk>2022-02-13 13:51:43 +0000
committerGreg Brown <greg.brown@cl.cam.ac.uk>2022-02-13 13:51:43 +0000
commit687f7031131ac12bd382be831114661be785dd0d (patch)
tree8ea3f77db9fc3e11b60fa6b17445837edc68fb9a /src/Helium
parent6915398a9facdbd19cbfddb36a912143811e5030 (diff)
Finish definition of denotational semantics.
Diffstat (limited to 'src/Helium')
-rw-r--r--src/Helium/Data/Pseudocode.agda32
-rw-r--r--src/Helium/Data/Pseudocode/Core.agda84
-rw-r--r--src/Helium/Data/Pseudocode/Types.agda264
-rw-r--r--src/Helium/Semantics/Denotational/Core.agda323
4 files changed, 384 insertions, 319 deletions
diff --git a/src/Helium/Data/Pseudocode.agda b/src/Helium/Data/Pseudocode.agda
index 9e4707d..9f936f2 100644
--- a/src/Helium/Data/Pseudocode.agda
+++ b/src/Helium/Data/Pseudocode.agda
@@ -71,19 +71,15 @@ BeatId = state 6
-- Indirect
-tup⇒array : ∀ {n Γ t m} → Expression {n} Γ (tuple (suc m) (Vec.replicate t)) → Expression Γ (array t (suc m))
-tup⇒array {m = zero} xs = [ head xs ]
-tup⇒array {m = suc m} xs = [ head xs ] ∶ tup⇒array (tail xs)
-
group : ∀ {n Γ t k} m → Expression {n} Γ (asType t (k ℕ.* suc m)) → Expression Γ (array (asType t k) (suc m))
group {k = k} zero x = [ cast (P.trans (ℕₚ.*-comm k 1) (ℕₚ.+-comm k 0)) x ]
-group {k = k} (suc m) x = [ slice (cast (ℕₚ.+-comm k _) x′) (lit (zero ′f)) ] ∶ group m (slice (cast (P.cong (k ℕ.+_) (ℕₚ.*-comm (suc m) k)) x′) (lit (Fin.fromℕ k ′f)))
+group {k = k} (suc m) x = group m (slice x′ (lit (Fin.fromℕ k ′f))) ∶ [ slice (cast (ℕₚ.+-comm k _) x′) (lit (zero ′f)) ]
where
- x′ = cast (ℕₚ.*-comm k (suc (suc m))) x
+ x′ = cast (P.trans (ℕₚ.*-comm k _) (P.cong (k ℕ.+_) (ℕₚ.*-comm _ k))) x
join : ∀ {n Γ t k m} → Expression {n} Γ (array (asType t k) (suc m)) → Expression Γ (asType t (k ℕ.* suc m))
join {k = k} {zero} x = cast (P.trans (ℕₚ.+-comm 0 k) (ℕₚ.*-comm 1 k)) (unbox x)
-join {k = k} {suc m} x = cast eq (unbox (slice {i = suc m} (cast (ℕₚ.+-comm 1 (suc m)) x) (lit (zero ′f))) ∶ join (slice x (lit (Fin.fromℕ 1 ′f))))
+join {k = k} {suc m} x = cast eq (join (slice x (lit (Fin.fromℕ 1 ′f))) ∶ unbox (slice {i = suc m} (cast (ℕₚ.+-comm 1 _) x) (lit (zero ′f))))
where
eq = P.trans (P.cong (k ℕ.+_) (ℕₚ.*-comm k (suc m))) (ℕₚ.*-comm (suc (suc m)) k)
@@ -106,7 +102,7 @@ hasBit {n} x i = index x i ≟ lit ((true ∷ []) ′x)
sliceⁱ : ∀ {n Γ m} → ℕ → Expression {n} Γ int → Expression Γ (bits m)
sliceⁱ {m = zero} n i = lit ([] ′x)
-sliceⁱ {m = suc m} n i = get (m ℕ.+ n) i ∶ sliceⁱ n i
+sliceⁱ {m = suc m} n i = sliceⁱ (suc n) i ∶ get n i
--- Functions
@@ -126,18 +122,18 @@ SignedSatQ n = declare (lit (true ′b)) (
var 0 ≔ lit (false ′b)
∙return tup (sliceⁱ 0 (var 1) ∷ var 0 ∷ []))
where
- max = lit (2 ′i) ^ lit (n ′i) + - lit (1 ′i)
- min = - (lit (2 ′i) ^ lit (n ′i))
+ max = lit (2 ′i) ^ n + - lit (1 ′i)
+ min = - (lit (2 ′i) ^ n)
-- actual shift if 'shift + 1'
LSL-C : ∀ {n} (shift : ℕ) → Function (bits n ∷ []) (tuple 2 (bits n ∷ bit ∷ []))
LSL-C {n} shift = declare (var 0 ∶ lit ((Vec.replicate {n = (suc shift)} false) ′x))
(skip ∙return tup
- ( slice (cast (ℕₚ.+-comm n _) (var 0)) (lit (zero ′f))
- ∷ slice (cast eq₂ (var 0)) (lit (Fin.inject+ shift (Fin.fromℕ n) ′f))
+ ( slice (var 0) (lit (zero ′f))
+ ∷ slice (cast eq (var 0)) (lit (Fin.inject+ shift (Fin.fromℕ n) ′f))
∷ []))
where
- eq₂ = P.trans (P.cong (n ℕ.+_) (ℕₚ.+-comm 1 shift)) (P.sym (ℕₚ.+-assoc n shift 1))
+ eq = P.trans (ℕₚ.+-comm 1 (shift ℕ.+ n)) (P.cong (ℕ._+ 1) (ℕₚ.+-comm shift n))
--- Procedures
@@ -229,7 +225,7 @@ module _ (d : Instr.VecOp₂) where
declare (lit (Vec.replicate false ′x)) (
-- 0:elmtMask 1:curBeat
tup (var 1 ∷ var 0 ∷ []) ≔ call GetCurInstrBeat (tup []) ∙
- declare (lit (Vec.replicate (Vec.replicate false ′x) ′a)) (
+ declare (lit ((Vec.replicate false ′x) ′a)) (
declare (from32 size (index (index Q (lit (src₁ ′f))) (var 2))) (
-- 0:op₁ 1:result 2:elmtMask 3:curBeat
for (toℕ elements) (
@@ -266,7 +262,7 @@ vmulh d = vec-op₂ op₂ (skip ∙return sliceⁱ (toℕ esize) (toInt (var 0)
open Instr.VMulH d; toInt = λ i → call Int (tup (i ∷ lit (unsigned ′b) ∷ []))
vrmulh : Instr.VRMulH → Procedure []
-vrmulh d = vec-op₂ op₂ (skip ∙return sliceⁱ (toℕ esize) (toInt (var 0) * toInt (var 1) + lit (1 ′i) << lit (toℕ esize-1 ′i)))
+vrmulh d = vec-op₂ op₂ (skip ∙return sliceⁱ (toℕ esize) (toInt (var 0) * toInt (var 1) + lit (1 ′i) << toℕ esize-1))
where
open Instr.VRMulH d; toInt = λ i → call Int (tup (i ∷ lit (unsigned ′b) ∷ []))
@@ -277,7 +273,7 @@ private
declare (lit (Vec.replicate false ′x)) (
-- 0:elmtMask 1:curBeat
tup (var 1 ∷ var 0 ∷ []) ≔ call GetCurInstrBeat (tup []) ∙
- declare (lit (Vec.replicate (Vec.replicate false ′x) ′a)) (
+ declare (lit ((Vec.replicate false ′x) ′a)) (
declare (from32 size (index (index Q (lit (src₁ ′f))) (var 2))) (
-- 0:op₁ 1:result 2:elmtMask 3:curBeat
for (toℕ elements) (
@@ -313,9 +309,9 @@ private
helper Instr.32bit i = Fin.combine i zero
vqdmulh : Instr.VQDMulH → Procedure []
-vqdmulh d = vqr?dmulh d (skip ∙return lit (2 ′i) * var 0 * var 1 >> lit (toℕ esize ′i))
+vqdmulh d = vqr?dmulh d (skip ∙return lit (2 ′i) * var 0 * var 1 >> toℕ esize)
where open Instr.VecOp₂ d using (esize)
vqrdmulh : Instr.VQRDMulH → Procedure []
-vqrdmulh d = vqr?dmulh d (skip ∙return (lit (2 ′i) * var 0 * var 1 + lit (1 ′i) << lit (toℕ esize-1 ′i)) >> lit (toℕ esize ′i))
+vqrdmulh d = vqr?dmulh d (skip ∙return lit (2 ′i) * var 0 * var 1 + lit (1 ′i) << toℕ esize-1 >> toℕ esize)
where open Instr.VecOp₂ d using (esize; esize-1)
diff --git a/src/Helium/Data/Pseudocode/Core.agda b/src/Helium/Data/Pseudocode/Core.agda
index 7b21824..a63cc39 100644
--- a/src/Helium/Data/Pseudocode/Core.agda
+++ b/src/Helium/Data/Pseudocode/Core.agda
@@ -8,9 +8,10 @@
module Helium.Data.Pseudocode.Core where
-open import Data.Bool using (Bool)
+open import Data.Bool using (Bool; true; false)
open import Data.Fin using (Fin; #_)
-open import Data.Nat as ℕ using (ℕ; suc)
+open import Data.Nat as ℕ using (ℕ; zero; suc)
+open import Data.Nat.Properties using (+-comm)
open import Data.Product using (∃; _,_; proj₂; uncurry)
open import Data.Vec using (Vec; []; _∷_; lookup; map)
open import Data.Vec.Relation.Unary.All using (All; []; _∷_; reduce; all?)
@@ -29,7 +30,6 @@ data Type : Set where
fin : (n : ℕ) → Type
real : Type
bits : (n : ℕ) → Type
- enum : (n : ℕ) → Type
tuple : ∀ n → Vec Type n → Type
array : Type → (n : ℕ) → Type
@@ -42,7 +42,6 @@ data HasEquality : Type → Set where
fin : ∀ {n} → HasEquality (fin n)
real : HasEquality real
bits : ∀ {n} → HasEquality (bits n)
- enum : ∀ {n} → HasEquality (enum n)
hasEquality? : Decidable HasEquality
hasEquality? unit = no (λ ())
@@ -51,7 +50,6 @@ hasEquality? int = yes int
hasEquality? (fin n) = yes fin
hasEquality? real = yes real
hasEquality? (bits n) = yes bits
-hasEquality? (enum n) = yes enum
hasEquality? (tuple n x) = no (λ ())
hasEquality? (array t n) = no (λ ())
@@ -66,7 +64,6 @@ isNumeric? int = yes int
isNumeric? real = yes real
isNumeric? (fin n) = no (λ ())
isNumeric? (bits n) = no (λ ())
-isNumeric? (enum n) = no (λ ())
isNumeric? (tuple n x) = no (λ ())
isNumeric? (array t n) = no (λ ())
@@ -95,8 +92,7 @@ data Literal : Type → Set where
_′f : ∀ {n} → Fin n → Literal (fin n)
_′r : ℕ → Literal real
_′x : ∀ {n} → Vec Bool n → Literal (bits n)
- _′e : ∀ {n} → Fin n → Literal (enum n)
- _′a : ∀ {n t} → Vec (Literal t) n → Literal (array t n)
+ _′a : ∀ {n t} → Literal t → Literal (array t n)
--- Expressions, references, statements, functions and procedures
@@ -111,7 +107,8 @@ module Code {o} (Σ : Vec Type o) where
infix 8 -_
infixr 7 _^_
- infixl 6 _*_ _/_ _and_
+ infixl 6 _*_ _and_ _>>_
+ -- infixl 6 _/_
infixl 5 _+_ _or_ _&&_ _||_ _∶_
infix 4 _≟_ _<?_
@@ -130,42 +127,37 @@ module Code {o} (Σ : Vec Type o) where
_or_ : ∀ {n} → Expression Γ (bits n) → Expression Γ (bits n) → Expression Γ (bits n)
[_] : ∀ {t} → Expression Γ t → Expression Γ (array t 1)
unbox : ∀ {t} → Expression Γ (array t 1) → Expression Γ t
- _∶_ : ∀ {m n t} → Expression Γ (asType t m) → Expression Γ (asType t n) → Expression Γ (asType t (m ℕ.+ n))
+ _∶_ : ∀ {m n t} → Expression Γ (asType t m) → Expression Γ (asType t n) → Expression Γ (asType t (n ℕ.+ m))
slice : ∀ {i j t} → Expression Γ (asType t (i ℕ.+ j)) → Expression Γ (fin (suc i)) → Expression Γ (asType t j)
cast : ∀ {i j t} → .(eq : i ≡ j) → Expression Γ (asType t i) → Expression Γ (asType t j)
-_ : ∀ {t} {isNumeric : True (isNumeric? t)} → Expression Γ t → Expression Γ t
_+_ : ∀ {t₁ t₂} {isNumeric₁ : True (isNumeric? t₁)} {isNumeric₂ : True (isNumeric? t₂)} → Expression Γ t₁ → Expression Γ t₂ → Expression Γ (combineNumeric t₁ t₂ {isNumeric₁} {isNumeric₂})
_*_ : ∀ {t₁ t₂} {isNumeric₁ : True (isNumeric? t₁)} {isNumeric₂ : True (isNumeric? t₂)} → Expression Γ t₁ → Expression Γ t₂ → Expression Γ (combineNumeric t₁ t₂ {isNumeric₁} {isNumeric₂})
- _/_ : Expression Γ real → Expression Γ real → Expression Γ real
- _^_ : ∀ {t} {isNumeric : True (isNumeric? t)} → Expression Γ t → Expression Γ int → Expression Γ t
- sint : ∀ {n} → Expression Γ (bits n) → Expression Γ int
- uint : ∀ {n} → Expression Γ (bits n) → Expression Γ int
+ -- _/_ : Expression Γ real → Expression Γ real → Expression Γ real
+ _^_ : ∀ {t} {isNumeric : True (isNumeric? t)} → Expression Γ t → ℕ → Expression Γ t
+ _>>_ : Expression Γ int → ℕ → Expression Γ int
rnd : Expression Γ real → Expression Γ int
- get : ℕ → Expression Γ int → Expression Γ bit
+ -- get : ℕ → Expression Γ int → Expression Γ bit
fin : ∀ {k ms n} → (All (Fin) ms → Fin n) → Expression Γ (tuple k (map fin ms)) → Expression Γ (fin n)
asInt : ∀ {n} → Expression Γ (fin n) → Expression Γ int
tup : ∀ {m ts} → All (Expression Γ) ts → Expression Γ (tuple m ts)
- head : ∀ {m t ts} → Expression Γ (tuple (suc m) (t ∷ ts)) → Expression Γ t
- tail : ∀ {m t ts} → Expression Γ (tuple (suc m) (t ∷ ts)) → Expression Γ (tuple m ts)
call : ∀ {t m Δ} → Function Δ t → Expression Γ (tuple m Δ) → Expression Γ t
if_then_else_ : ∀ {t} → Expression Γ bool → Expression Γ t → Expression Γ t → Expression Γ t
data CanAssign {n} {Γ} where
- state : ∀ {i} {i<o : True (i ℕ.<? o)} → CanAssign (state i {i<o})
- var : ∀ {i} {i<n : True (i ℕ.<? n)} → CanAssign (var i {i<n})
+ state : ∀ i {i<o : True (i ℕ.<? o)} → CanAssign (state i {i<o})
+ var : ∀ i {i<n : True (i ℕ.<? n)} → CanAssign (var i {i<n})
abort : ∀ {t} {e : Expression Γ (fin 0)} → CanAssign (abort {t = t} e)
_∶_ : ∀ {m n t} {e₁ : Expression Γ (asType t m)} {e₂ : Expression Γ (asType t n)} → CanAssign e₁ → CanAssign e₂ → CanAssign (e₁ ∶ e₂)
[_] : ∀ {t} {e : Expression Γ t} → CanAssign e → CanAssign [ e ]
unbox : ∀ {t} {e : Expression Γ (array t 1)} → CanAssign e → CanAssign (unbox e)
- slice : ∀ {i j t} {e₁ : Expression Γ (asType t (i ℕ.+ j))} {e₂ : Expression Γ (fin (suc i))} → CanAssign e₁ → CanAssign (slice e₁ e₂)
- cast : ∀ {i j t} {e : Expression Γ (asType t i)} .{eq : i ≡ j} → CanAssign e → CanAssign (cast eq e)
+ slice : ∀ {i j t} {e₁ : Expression Γ (asType t (i ℕ.+ j))} → CanAssign e₁ → (e₂ : Expression Γ (fin (suc i))) → CanAssign (slice e₁ e₂)
+ cast : ∀ {i j t} {e : Expression Γ (asType t i)} .(eq : i ≡ j) → CanAssign e → CanAssign (cast eq e)
tup : ∀ {m ts} {es : All (Expression Γ) {m} ts} → All (CanAssign ∘ proj₂) (reduce (λ {x} e → x , e) es) → CanAssign (tup es)
- head : ∀ {m t ts} {e : Expression Γ (tuple (suc m) (t ∷ ts))} → CanAssign e → CanAssign (head e)
- tail : ∀ {m t ts} {e : Expression Γ (tuple (suc m) (t ∷ ts))} → CanAssign e → CanAssign (tail e)
canAssign? (lit x) = no λ ()
- canAssign? (state i) = yes state
- canAssign? (var i) = yes var
+ canAssign? (state i) = yes (state i)
+ canAssign? (var i) = yes (var i)
canAssign? (abort e) = yes abort
canAssign? (e ≟ e₁) = no λ ()
canAssign? (e <? e₁) = no λ ()
@@ -178,22 +170,19 @@ module Code {o} (Σ : Vec Type o) where
canAssign? [ e ] = map′ [_] (λ { [ e ] → e }) (canAssign? e)
canAssign? (unbox e) = map′ unbox (λ { (unbox e) → e }) (canAssign? e)
canAssign? (e ∶ e₁) = map′ (uncurry _∶_) (λ { (e ∶ e₁) → e , e₁ }) (canAssign? e ×-dec canAssign? e₁)
- canAssign? (slice e e₁) = map′ slice (λ { (slice e) → e }) (canAssign? e)
- canAssign? (cast eq e) = map′ cast (λ { (cast e) → e }) (canAssign? e)
+ canAssign? (slice e e₁) = map′ (λ e → slice e e₁) (λ { (slice e e₁) → e }) (canAssign? e)
+ canAssign? (cast eq e) = map′ (cast eq) (λ { (cast eq e) → e }) (canAssign? e)
canAssign? (- e) = no λ ()
canAssign? (e + e₁) = no λ ()
canAssign? (e * e₁) = no λ ()
- canAssign? (e / e₁) = no λ ()
+ -- canAssign? (e / e₁) = no λ ()
canAssign? (e ^ e₁) = no λ ()
- canAssign? (sint e) = no λ ()
- canAssign? (uint e) = no λ ()
+ canAssign? (e >> e₁) = no λ ()
canAssign? (rnd e) = no λ ()
- canAssign? (get x e) = no λ ()
+ -- canAssign? (get x e) = no λ ()
canAssign? (fin x e) = no λ ()
canAssign? (asInt e) = no λ ()
canAssign? (tup es) = map′ tup (λ { (tup es) → es }) (canAssignAll? es)
- canAssign? (head e) = map′ head (λ { (head e) → e }) (canAssign? e)
- canAssign? (tail e) = map′ tail (λ { (tail e) → e }) (canAssign? e)
canAssign? (call x e) = no λ ()
canAssign? (if e then e₁ else e₂) = no λ ()
@@ -222,13 +211,34 @@ module Code {o} (Σ : Vec Type o) where
_∙end : Statement Γ unit → Procedure Γ
declare : ∀ {t} → Expression Γ t → Procedure (t ∷ Γ) → Procedure Γ
- infixl 6 _<<_ _>>_
+ infixl 6 _<<_
infixl 5 _-_
+
+ slice′ : ∀ {n Γ i j t} → Expression {n} Γ (asType t (i ℕ.+ j)) → Expression Γ (fin (suc j)) → Expression Γ (asType t i)
+ slice′ {i = i} e₁ e₂ = slice (cast (+-comm i _) e₁) e₂
+
_-_ : ∀ {n Γ t₁ t₂} {isNumeric₁ : True (isNumeric? t₁)} {isNumeric₂ : True (isNumeric? t₂)} → Expression {n} Γ t₁ → Expression Γ t₂ → Expression Γ (combineNumeric t₁ t₂ {isNumeric₁} {isNumeric₂})
_-_ {isNumeric₂ = isNumeric₂} x y = x + (-_ {isNumeric = isNumeric₂} y)
- _<<_ : ∀ {n Γ} → Expression {n} Γ int → Expression Γ int → Expression Γ int
+ _<<_ : ∀ {n Γ} → Expression {n} Γ int → ℕ → Expression Γ int
x << n = rnd (x * lit (2 ′r) ^ n)
- _>>_ : ∀ {n Γ} → Expression {n} Γ int → Expression Γ int → Expression Γ int
- x >> n = rnd (x * lit (2 ′r) ^ - n)
+ get : ∀ {n Γ} → ℕ → Expression {n} Γ int → Expression Γ bit
+ get i x = if x - x >> suc i << suc i <? lit (2 ′i) ^ i then lit ((false ∷ []) ′x) else lit ((true ∷ []) ′x)
+
+ uint : ∀ {n Γ m} → Expression {n} Γ (bits m) → Expression Γ int
+ uint {m = zero} x = lit (0 ′i)
+ uint {m = suc m} x =
+ lit (2 ′i) * uint {m = m} (slice x (lit ((# 1) ′f))) +
+ ( if slice′ x (lit ((# 0) ′f)) ≟ lit ((true ∷ []) ′x)
+ then lit (1 ′i)
+ else lit (0 ′i))
+
+ sint : ∀ {n Γ m} → Expression {n} Γ (bits m) → Expression Γ int
+ sint {m = zero} x = lit (0 ′i)
+ sint {m = suc zero} x = if x ≟ lit ((true ∷ []) ′x) then - lit (1 ′i) else lit (0 ′i)
+ sint {m = suc (suc m)} x =
+ lit (2 ′i) * sint (slice {i = 1} x (lit ((# 1) ′f))) +
+ ( if slice′ x (lit ((# 0) ′f)) ≟ lit ((true ∷ []) ′x)
+ then lit (1 ′i)
+ else lit (0 ′i))
diff --git a/src/Helium/Data/Pseudocode/Types.agda b/src/Helium/Data/Pseudocode/Types.agda
index a545ddc..971ca12 100644
--- a/src/Helium/Data/Pseudocode/Types.agda
+++ b/src/Helium/Data/Pseudocode/Types.agda
@@ -77,82 +77,6 @@ record RawPseudocode b₁ b₂ i₁ i₂ i₃ r₁ r₂ r₃ : Set (ℓsuc (b₁
_/1 : ℤ → ℝ
⌊_⌋ : ℝ → ℤ
- cast : ∀ {m n} → .(eq : m ≡ n) → Bits m → Bits n
- cast eq x i = x $ Fin.cast (P.sym eq) i
-
- 2ℤ : ℤ
- 2ℤ = 2 ℤ′.×′ 1ℤ
-
- getᵇ : ∀ {n} → Fin n → Bits n → Bit
- getᵇ i x = x (opposite i)
-
- setᵇ : ∀ {n} → Fin n → Bit → Op₁ (Bits n)
- setᵇ i b = updateAt (opposite i) λ _ → b
-
- sliceᵇ : ∀ {n} (i : Fin (suc n)) j → Bits n → Bits (toℕ (i - j))
- sliceᵇ zero zero x = []
- sliceᵇ {suc n} (suc i) zero x = getᵇ i x ∷ sliceᵇ i zero (tail x)
- sliceᵇ {suc n} (suc i) (suc j) x = sliceᵇ i j (tail x)
-
- updateᵇ : ∀ {n} (i : Fin (suc n)) j → Bits (toℕ (i - j)) → Op₁ (Bits n)
- updateᵇ {n} = Induction.<-weakInduction P (λ _ _ → id) helper
- where
- P : Fin (suc n) → Set b₁
- P i = ∀ j → Bits (toℕ (i - j)) → Op₁ (Bits n)
-
- eq : ∀ {n} {i : Fin n} → toℕ i ≡ toℕ (inject₁ i)
- eq = P.sym $ Fₚ.toℕ-inject₁ _
-
- eq′ : ∀ {n} {i : Fin n} j → toℕ (i - j) ≡ toℕ (inject₁ i - Fin.cast eq j)
- eq′ zero = eq
- eq′ {i = suc _} (suc j) = eq′ j
-
- helper : ∀ i → P (inject₁ i) → P (suc i)
- helper i rec zero y = rec zero (cast eq (tail y)) ∘′ setᵇ i (y zero)
- helper i rec (suc j) y = rec (Fin.cast eq j) (cast (eq′ j) y)
-
- hasBit : ∀ {n} → Fin n → Bits n → Bool
- hasBit i x = does (getᵇ i x ≟ᵇ₁ 1𝔹)
-
- infixl 7 _div_ _mod_
-
- _div_ : ∀ (x y : ℤ) → {y≉0 : False (y /1 ≟ʳ 0ℝ)} → ℤ
- (x div y) {y≉0} = ⌊ x /1 ℝ.* toWitnessFalse y≉0 ℝ.⁻¹ ⌋
-
- _mod_ : ∀ (x y : ℤ) → {y≉0 : False (y /1 ≟ʳ 0ℝ)} → ℤ
- (x mod y) {y≉0} = x ℤ.+ ℤ.- y ℤ.* (x div y) {y≉0}
-
- infixl 5 _<<_
- _<<_ : ℤ → ℕ → ℤ
- x << n = 2ℤ ℤ′.^′ n ℤ.* x
-
- module ShiftNotZero
- (1<<n≉0 : ∀ n → False ((1ℤ << n) /1 ≟ʳ 0ℝ))
- where
-
- infixl 5 _>>_
- _>>_ : ℤ → ℕ → ℤ
- x >> zero = x
- x >> suc n = (x div (1ℤ << suc n)) {1<<n≉0 (suc n)}
-
- getᶻ : ℕ → ℤ → Bit
- getᶻ n x =
- if does ((x mod (1ℤ << suc n)) {1<<n≉0 (suc n)} <ᶻ? 1ℤ << n)
- then 1𝔹
- else 0𝔹
-
- sliceᶻ : ∀ n i → ℤ → Bits (n ℕ-ℕ i)
- sliceᶻ zero zero x = []
- sliceᶻ (suc n) zero x = getᶻ n x ∷ sliceᶻ n zero x
- sliceᶻ (suc n) (suc i) x = sliceᶻ n i (x >> 1)
-
- uint : ∀ {n} → Bits n → ℤ
- uint x = ℤ′.sum λ i → if hasBit i x then 1ℤ << toℕ i else 0ℤ
-
- sint : ∀ {n} → Bits n → ℤ
- sint {zero} x = 0ℤ
- sint {suc n} x = uint x ℤ.+ ℤ.- (if hasBit (fromℕ n) x then 1ℤ << suc n else 0ℤ)
-
record Pseudocode b₁ b₂ i₁ i₂ i₃ r₁ r₂ r₃ :
Set (ℓsuc (b₁ ⊔ b₂ ⊔ i₁ ⊔ i₂ ⊔ i₃ ⊔ r₁ ⊔ r₂ ⊔ r₃)) where
field
@@ -222,191 +146,3 @@ record Pseudocode b₁ b₂ i₁ i₂ i₃ r₁ r₂ r₃ :
; _/1 = _/1
; ⌊_⌋ = ⌊_⌋
}
-
- open RawPseudocode rawPseudocode public
- using
- ( 2ℤ; cast; getᵇ; setᵇ; sliceᵇ; updateᵇ; hasBit
- ; _div_; _mod_; _<<_; uint; sint
- )
-
- private
- -- FIXME: move almost all of these proofs into a separate module
- a<b⇒ca<cb : ∀ {a b c} → 0ℤ ℤ.< c → a ℤ.< b → c ℤ.* a ℤ.< c ℤ.* b
- a<b⇒ca<cb {a} {b} {c} 0<c a<b = begin-strict
- c ℤ.* a ≈˘⟨ ℤ.+-identityʳ _ ⟩
- c ℤ.* a ℤ.+ 0ℤ <⟨ ℤ.+-invariantˡ _ $ ℤ.0<a+0<b⇒0<ab 0<c 0<b-a ⟩
- c ℤ.* a ℤ.+ c ℤ.* (b ℤ.- a) ≈˘⟨ ℤ.distribˡ c a (b ℤ.- a) ⟩
- c ℤ.* (a ℤ.+ (b ℤ.- a)) ≈⟨ ℤ.*-congˡ $ ℤ.+-congˡ $ ℤ.+-comm b (ℤ.- a) ⟩
- c ℤ.* (a ℤ.+ (ℤ.- a ℤ.+ b)) ≈˘⟨ ℤ.*-congˡ $ ℤ.+-assoc a (ℤ.- a) b ⟩
- c ℤ.* ((a ℤ.+ ℤ.- a) ℤ.+ b) ≈⟨ ℤ.*-congˡ $ ℤ.+-congʳ $ ℤ.-‿inverseʳ a ⟩
- c ℤ.* (0ℤ ℤ.+ b) ≈⟨ (ℤ.*-congˡ $ ℤ.+-identityˡ b) ⟩
- c ℤ.* b ∎
- where
- open ℤ-Reasoning
-
- 0<b-a : 0ℤ ℤ.< b ℤ.- a
- 0<b-a = begin-strict
- 0ℤ ≈˘⟨ ℤ.-‿inverseʳ a ⟩
- a ℤ.- a <⟨ ℤ.+-invariantʳ (ℤ.- a) a<b ⟩
- b ℤ.- a ∎
-
- -‿idem : ∀ x → ℤ.- (ℤ.- x) ℤ.≈ x
- -‿idem x = begin-equality
- ℤ.- (ℤ.- x) ≈˘⟨ ℤ.+-identityˡ _ ⟩
- 0ℤ ℤ.- ℤ.- x ≈˘⟨ ℤ.+-congʳ $ ℤ.-‿inverseʳ x ⟩
- x ℤ.- x ℤ.- ℤ.- x ≈⟨ ℤ.+-assoc x (ℤ.- x) _ ⟩
- x ℤ.+ (ℤ.- x ℤ.- ℤ.- x) ≈⟨ ℤ.+-congˡ $ ℤ.-‿inverseʳ (ℤ.- x) ⟩
- x ℤ.+ 0ℤ ≈⟨ ℤ.+-identityʳ x ⟩
- x ∎
- where open ℤ-Reasoning
-
- -a*b≈-ab : ∀ a b → ℤ.- a ℤ.* b ℤ.≈ ℤ.- (a ℤ.* b)
- -a*b≈-ab a b = begin-equality
- ℤ.- a ℤ.* b ≈˘⟨ ℤ.+-identityʳ _ ⟩
- ℤ.- a ℤ.* b ℤ.+ 0ℤ ≈˘⟨ ℤ.+-congˡ $ ℤ.-‿inverseʳ _ ⟩
- ℤ.- a ℤ.* b ℤ.+ (a ℤ.* b ℤ.- a ℤ.* b) ≈˘⟨ ℤ.+-assoc _ _ _ ⟩
- ℤ.- a ℤ.* b ℤ.+ a ℤ.* b ℤ.- a ℤ.* b ≈˘⟨ ℤ.+-congʳ $ ℤ.distribʳ b _ a ⟩
- (ℤ.- a ℤ.+ a) ℤ.* b ℤ.- a ℤ.* b ≈⟨ ℤ.+-congʳ $ ℤ.*-congʳ $ ℤ.-‿inverseˡ a ⟩
- 0ℤ ℤ.* b ℤ.- a ℤ.* b ≈⟨ ℤ.+-congʳ $ ℤ.zeroˡ b ⟩
- 0ℤ ℤ.- a ℤ.* b ≈⟨ ℤ.+-identityˡ _ ⟩
- ℤ.- (a ℤ.* b) ∎
- where open ℤ-Reasoning
-
- a*-b≈-ab : ∀ a b → a ℤ.* ℤ.- b ℤ.≈ ℤ.- (a ℤ.* b)
- a*-b≈-ab a b = begin-equality
- a ℤ.* ℤ.- b ≈⟨ ℤ.*-comm a (ℤ.- b) ⟩
- ℤ.- b ℤ.* a ≈⟨ -a*b≈-ab b a ⟩
- ℤ.- (b ℤ.* a) ≈⟨ ℤ.-‿cong $ ℤ.*-comm b a ⟩
- ℤ.- (a ℤ.* b) ∎
- where open ℤ-Reasoning
-
- 0<a⇒0>-a : ∀ {a} → 0ℤ ℤ.< a → 0ℤ ℤ.> ℤ.- a
- 0<a⇒0>-a {a} 0<a = begin-strict
- ℤ.- a ≈˘⟨ ℤ.+-identityˡ _ ⟩
- 0ℤ ℤ.- a <⟨ ℤ.+-invariantʳ _ 0<a ⟩
- a ℤ.- a ≈⟨ ℤ.-‿inverseʳ a ⟩
- 0ℤ ∎
- where open ℤ-Reasoning
-
- 0>a⇒0<-a : ∀ {a} → 0ℤ ℤ.> a → 0ℤ ℤ.< ℤ.- a
- 0>a⇒0<-a {a} 0>a = begin-strict
- 0ℤ ≈˘⟨ ℤ.-‿inverseʳ a ⟩
- a ℤ.- a <⟨ ℤ.+-invariantʳ _ 0>a ⟩
- 0ℤ ℤ.- a ≈⟨ ℤ.+-identityˡ _ ⟩
- ℤ.- a ∎
- where open ℤ-Reasoning
-
- 0<-a⇒0>a : ∀ {a} → 0ℤ ℤ.< ℤ.- a → 0ℤ ℤ.> a
- 0<-a⇒0>a {a} 0<-a = begin-strict
- a ≈˘⟨ ℤ.+-identityʳ a ⟩
- a ℤ.+ 0ℤ <⟨ ℤ.+-invariantˡ a 0<-a ⟩
- a ℤ.- a ≈⟨ ℤ.-‿inverseʳ a ⟩
- 0ℤ ∎
- where open ℤ-Reasoning
-
- 0>-a⇒0<a : ∀ {a} → 0ℤ ℤ.> ℤ.- a → 0ℤ ℤ.< a
- 0>-a⇒0<a {a} 0>-a = begin-strict
- 0ℤ ≈˘⟨ ℤ.-‿inverseʳ a ⟩
- a ℤ.- a <⟨ ℤ.+-invariantˡ a 0>-a ⟩
- a ℤ.+ 0ℤ ≈⟨ ℤ.+-identityʳ a ⟩
- a ∎
- where open ℤ-Reasoning
-
- 0>a+0<b⇒0>ab : ∀ {a b} → 0ℤ ℤ.> a → 0ℤ ℤ.< b → 0ℤ ℤ.> a ℤ.* b
- 0>a+0<b⇒0>ab {a} {b} 0>a 0<b = 0<-a⇒0>a $ begin-strict
- 0ℤ <⟨ ℤ.0<a+0<b⇒0<ab (0>a⇒0<-a 0>a) 0<b ⟩
- ℤ.- a ℤ.* b ≈⟨ -a*b≈-ab a b ⟩
- ℤ.- (a ℤ.* b) ∎
- where open ℤ-Reasoning
-
- 0<a+0>b⇒0>ab : ∀ {a b} → 0ℤ ℤ.< a → 0ℤ ℤ.> b → 0ℤ ℤ.> a ℤ.* b
- 0<a+0>b⇒0>ab {a} {b} 0<a 0>b = 0<-a⇒0>a $ begin-strict
- 0ℤ <⟨ ℤ.0<a+0<b⇒0<ab 0<a (0>a⇒0<-a 0>b) ⟩
- a ℤ.* ℤ.- b ≈⟨ a*-b≈-ab a b ⟩
- ℤ.- (a ℤ.* b) ∎
- where open ℤ-Reasoning
-
- 0>a+0>b⇒0<ab : ∀ {a b} → 0ℤ ℤ.> a → 0ℤ ℤ.> b → 0ℤ ℤ.< a ℤ.* b
- 0>a+0>b⇒0<ab {a} {b} 0>a 0>b = begin-strict
- 0ℤ <⟨ ℤ.0<a+0<b⇒0<ab (0>a⇒0<-a 0>a) (0>a⇒0<-a 0>b) ⟩
- ℤ.- a ℤ.* ℤ.- b ≈⟨ -a*b≈-ab a (ℤ.- b) ⟩
- ℤ.- (a ℤ.* ℤ.- b) ≈⟨ ℤ.-‿cong $ a*-b≈-ab a b ⟩
- ℤ.- (ℤ.- (a ℤ.* b)) ≈⟨ -‿idem (a ℤ.* b) ⟩
- a ℤ.* b ∎
- where open ℤ-Reasoning
-
- a≉0+b≉0⇒ab≉0 : ∀ {a b} → a ℤ.≉ 0ℤ → b ℤ.≉ 0ℤ → a ℤ.* b ℤ.≉ 0ℤ
- a≉0+b≉0⇒ab≉0 {a} {b} a≉0 b≉0 ab≈0 with ℤ.compare a 0ℤ | ℤ.compare b 0ℤ
- ... | tri< a<0 _ _ | tri< b<0 _ _ = ℤ.irrefl (ℤ.Eq.sym ab≈0) $ 0>a+0>b⇒0<ab a<0 b<0
- ... | tri< a<0 _ _ | tri≈ _ b≈0 _ = b≉0 b≈0
- ... | tri< a<0 _ _ | tri> _ _ b>0 = ℤ.irrefl ab≈0 $ 0>a+0<b⇒0>ab a<0 b>0
- ... | tri≈ _ a≈0 _ | _ = a≉0 a≈0
- ... | tri> _ _ a>0 | tri< b<0 _ _ = ℤ.irrefl ab≈0 $ 0<a+0>b⇒0>ab a>0 b<0
- ... | tri> _ _ a>0 | tri≈ _ b≈0 _ = b≉0 b≈0
- ... | tri> _ _ a>0 | tri> _ _ b>0 = ℤ.irrefl (ℤ.Eq.sym ab≈0) $ ℤ.0<a+0<b⇒0<ab a>0 b>0
-
- ab≈0⇒a≈0⊎b≈0 : ∀ {a b} → a ℤ.* b ℤ.≈ 0ℤ → a ℤ.≈ 0ℤ ⊎ b ℤ.≈ 0ℤ
- ab≈0⇒a≈0⊎b≈0 {a} {b} ab≈0 with a ℤ.≟ 0ℤ | b ℤ.≟ 0ℤ
- ... | yes a≈0 | _ = inj₁ a≈0
- ... | no a≉0 | yes b≈0 = inj₂ b≈0
- ... | no a≉0 | no b≉0 = ⊥-elim (a≉0+b≉0⇒ab≉0 a≉0 b≉0 ab≈0)
-
- 2a<<n≈a<<1+n : ∀ a n → 2ℤ ℤ.* (a << n) ℤ.≈ a << suc n
- 2a<<n≈a<<1+n a zero = ℤ.*-congˡ $ ℤ.*-identityˡ a
- 2a<<n≈a<<1+n a (suc n) = begin-equality
- 2ℤ ℤ.* (a << suc n) ≈˘⟨ ℤ.*-assoc 2ℤ _ a ⟩
- (2ℤ ℤ.* _) ℤ.* a ≈⟨ ℤ.*-congʳ $ ℤ.*-comm 2ℤ _ ⟩
- a << suc (suc n) ∎
- where open ℤ-Reasoning
-
- 0<1 : 0ℤ ℤ.< 1ℤ
- 0<1 with ℤ.compare 0ℤ 1ℤ
- ... | tri< 0<1 _ _ = 0<1
- ... | tri≈ _ 0≈1 _ = ⊥-elim (1≉0 (ℤ.Eq.sym 0≈1))
- ... | tri> _ _ 0>1 = begin-strict
- 0ℤ ≈˘⟨ ℤ.zeroʳ (ℤ.- 1ℤ) ⟩
- ℤ.- 1ℤ ℤ.* 0ℤ <⟨ a<b⇒ca<cb (0>a⇒0<-a 0>1) (0>a⇒0<-a 0>1) ⟩
- ℤ.- 1ℤ ℤ.* ℤ.- 1ℤ ≈⟨ -a*b≈-ab 1ℤ (ℤ.- 1ℤ) ⟩
- ℤ.- (1ℤ ℤ.* ℤ.- 1ℤ) ≈⟨ ℤ.-‿cong $ ℤ.*-identityˡ (ℤ.- 1ℤ) ⟩
- ℤ.- (ℤ.- 1ℤ) ≈⟨ -‿idem 1ℤ ⟩
- 1ℤ ∎
- where open ℤ-Reasoning
-
- 0<2 : 0ℤ ℤ.< 2ℤ
- 0<2 = begin-strict
- 0ℤ ≈˘⟨ ℤ.+-identity² ⟩
- 0ℤ ℤ.+ 0ℤ <⟨ ℤ.+-invariantˡ 0ℤ 0<1 ⟩
- 0ℤ ℤ.+ 1ℤ <⟨ ℤ.+-invariantʳ 1ℤ 0<1 ⟩
- 2ℤ ∎
- where open ℤ-Reasoning
-
- 1<<n≉0 : ∀ n → 1ℤ << n ℤ.≉ 0ℤ
- 1<<n≉0 zero eq = 1≉0 1≈0
- where
- open ℤ-Reasoning
- 1≈0 = begin-equality
- 1ℤ ≈˘⟨ ℤ.*-identity² ⟩
- 1ℤ ℤ.* 1ℤ ≈⟨ eq ⟩
- 0ℤ ∎
- 1<<n≉0 (suc zero) eq = ℤ.irrefl 0≈2 0<2
- where
- open ℤ-Reasoning
- 0≈2 = begin-equality
- 0ℤ ≈˘⟨ eq ⟩
- 2ℤ ℤ.* 1ℤ ≈⟨ ℤ.*-identityʳ 2ℤ ⟩
- 2ℤ ∎
- 1<<n≉0 (suc (suc n)) eq =
- [ (λ 2≈0 → ℤ.irrefl (ℤ.Eq.sym 2≈0) 0<2) , 1<<n≉0 (suc n) ]′
- $ ab≈0⇒a≈0⊎b≈0 $ ℤ.Eq.trans (2a<<n≈a<<1+n 1ℤ (suc n)) eq
-
- 1<<n≉0ℝ : ∀ n → (1ℤ << n) /1 ℝ.≉ 0ℝ
- 1<<n≉0ℝ n eq = 1<<n≉0 n $ (begin-equality
- 1ℤ << n ≈˘⟨ ⌊⌋∘/1≗id (1ℤ << n) ⟩
- ⌊ (1ℤ << n) /1 ⌋ ≈⟨ ⌊⌋.cong $ eq ⟩
- ⌊ 0ℝ ⌋ ≈⟨ ⌊⌋.0#-homo ⟩
- 0ℤ ∎)
- where open ℤ-Reasoning
-
- open RawPseudocode rawPseudocode using (module ShiftNotZero)
-
- open ShiftNotZero (λ n → fromWitnessFalse (1<<n≉0ℝ n)) public
diff --git a/src/Helium/Semantics/Denotational/Core.agda b/src/Helium/Semantics/Denotational/Core.agda
new file mode 100644
index 0000000..6dd76b0
--- /dev/null
+++ b/src/Helium/Semantics/Denotational/Core.agda
@@ -0,0 +1,323 @@
+------------------------------------------------------------------------
+-- Agda Helium
+--
+-- Base definitions for the denotational semantics.
+------------------------------------------------------------------------
+
+{-# OPTIONS --safe --without-K #-}
+
+open import Helium.Data.Pseudocode.Types using (RawPseudocode)
+
+module Helium.Semantics.Denotational.Core
+ {b₁ b₂ i₁ i₂ i₃ r₁ r₂ r₃}
+ (rawPseudocode : RawPseudocode b₁ b₂ i₁ i₂ i₃ r₁ r₂ r₃)
+ where
+
+private
+ open module C = RawPseudocode rawPseudocode
+
+open import Data.Bool as Bool using (Bool; true; false)
+open import Data.Fin as Fin using (Fin; zero; suc; #_)
+import Data.Fin.Properties as Finₚ
+open import Data.Nat as ℕ using (ℕ; zero; suc)
+import Data.Nat.Properties as ℕₚ
+open import Data.Product as P using (_×_; _,_)
+open import Data.Sum as S using (_⊎_) renaming (inj₁ to next; inj₂ to ret)
+open import Data.Unit using (⊤)
+open import Data.Vec as Vec using (Vec; []; _∷_)
+open import Data.Vec.Relation.Unary.All using (All; []; _∷_)
+import Data.Vec.Functional as VecF
+open import Function using (case_of_; _∘′_; id)
+open import Helium.Data.Pseudocode.Core
+import Induction as I
+import Induction.WellFounded as Wf
+open import Level hiding (zero; suc)
+open import Relation.Binary.PropositionalEquality as ≡ using (_≡_; module ≡-Reasoning)
+open import Relation.Nullary using (does)
+open import Relation.Nullary.Decidable.Core using (True; False; toWitness; fromWitness)
+
+⟦_⟧ₗ : Type → Level
+⟦ unit ⟧ₗ = 0ℓ
+⟦ bool ⟧ₗ = 0ℓ
+⟦ int ⟧ₗ = i₁
+⟦ fin n ⟧ₗ = 0ℓ
+⟦ real ⟧ₗ = r₁
+⟦ bits n ⟧ₗ = b₁
+⟦ tuple n ts ⟧ₗ = helper ts
+ where
+ helper : ∀ {n} → Vec Type n → Level
+ helper [] = 0ℓ
+ helper (t ∷ ts) = ⟦ t ⟧ₗ ⊔ helper ts
+⟦ array t n ⟧ₗ = ⟦ t ⟧ₗ
+
+⟦_⟧ₜ : ∀ t → Set ⟦ t ⟧ₗ
+⟦_⟧ₜ′ : ∀ {n} ts → Set ⟦ tuple n ts ⟧ₗ
+
+⟦ unit ⟧ₜ = ⊤
+⟦ bool ⟧ₜ = Bool
+⟦ int ⟧ₜ = ℤ
+⟦ fin n ⟧ₜ = Fin n
+⟦ real ⟧ₜ = ℝ
+⟦ bits n ⟧ₜ = Bits n
+⟦ tuple n ts ⟧ₜ = ⟦ ts ⟧ₜ′
+⟦ array t n ⟧ₜ = Vec ⟦ t ⟧ₜ n
+
+⟦ [] ⟧ₜ′ = ⟦ unit ⟧ₜ
+⟦ t ∷ [] ⟧ₜ′ = ⟦ t ⟧ₜ
+⟦ t ∷ t′ ∷ ts ⟧ₜ′ = ⟦ t ⟧ₜ × ⟦ t′ ∷ ts ⟧ₜ′
+
+-- The case for bitvectors looks odd so that the right-most bit is bit 0.
+𝒦 : ∀ {t} → Literal t → ⟦ t ⟧ₜ
+𝒦 (x ′b) = x
+𝒦 (x ′i) = x ℤ′.×′ 1ℤ
+𝒦 (x ′f) = x
+𝒦 (x ′r) = x ℝ′.×′ 1ℝ
+𝒦 (xs ′x) = Vec.foldl Bits (λ bs b → (Bool.if b then 1𝔹 else 0𝔹) VecF.∷ bs) VecF.[] xs
+𝒦 (x ′a) = Vec.replicate (𝒦 x)
+
+
+fetch : ∀ {n} ts → ⟦ tuple n ts ⟧ₜ → ∀ i → ⟦ Vec.lookup ts i ⟧ₜ
+fetch (_ ∷ []) x zero = x
+fetch (_ ∷ _ ∷ _) (x , xs) zero = x
+fetch (_ ∷ t ∷ ts) (x , xs) (suc i) = fetch (t ∷ ts) xs i
+
+updateAt : ∀ {n} ts i → ⟦ Vec.lookup ts i ⟧ₜ → ⟦ tuple n ts ⟧ₜ → ⟦ tuple n ts ⟧ₜ
+updateAt (_ ∷ []) zero v _ = v
+updateAt (_ ∷ _ ∷ _) zero v (_ , xs) = v , xs
+updateAt (_ ∷ t ∷ ts) (suc i) v (x , xs) = x , updateAt (t ∷ ts) i v xs
+
+tupCons : ∀ {n t} ts → ⟦ t ⟧ₜ → ⟦ tuple n ts ⟧ₜ → ⟦ tuple _ (t ∷ ts) ⟧ₜ
+tupCons [] x xs = x
+tupCons (t ∷ ts) x xs = x , xs
+
+tupHead : ∀ {n t} ts → ⟦ tuple (suc n) (t ∷ ts) ⟧ₜ → ⟦ t ⟧ₜ
+tupHead {t = t} ts xs = fetch (t ∷ ts) xs zero
+
+tupTail : ∀ {n t} ts → ⟦ tuple _ (t ∷ ts) ⟧ₜ → ⟦ tuple n ts ⟧ₜ
+tupTail [] x = _
+tupTail (_ ∷ _) (x , xs) = xs
+
+equal : ∀ {t} → HasEquality t → ⟦ t ⟧ₜ → ⟦ t ⟧ₜ → Bool
+equal bool x y = does (x Bool.≟ y)
+equal int x y = does (x ≟ᶻ y)
+equal fin x y = does (x Fin.≟ y)
+equal real x y = does (x ≟ʳ y)
+equal bits x y = does (x ≟ᵇ y)
+
+comp : ∀ {t} → IsNumeric t → ⟦ t ⟧ₜ → ⟦ t ⟧ₜ → Bool
+comp int x y = does (x <ᶻ? y)
+comp real x y = does (x <ʳ? y)
+
+-- 0 of y is 0 of result
+join : ∀ t {m n} → ⟦ asType t m ⟧ₜ → ⟦ asType t n ⟧ₜ → ⟦ asType t (n ℕ.+ m) ⟧ₜ
+join bits {m} x y = y VecF.++ x
+join (array _) {m} x y = y Vec.++ x
+
+-- take from 0
+take : ∀ t i {j} → ⟦ asType t (i ℕ.+ j) ⟧ₜ → ⟦ asType t i ⟧ₜ
+take bits i x = VecF.take i x
+take (array _) i x = Vec.take i x
+
+-- drop from 0
+drop : ∀ t i {j} → ⟦ asType t (i ℕ.+ j) ⟧ₜ → ⟦ asType t j ⟧ₜ
+drop bits i x = VecF.drop i x
+drop (array _) i x = Vec.drop i x
+
+casted : ∀ t {i j} → .(eq : i ≡ j) → ⟦ asType t i ⟧ₜ → ⟦ asType t j ⟧ₜ
+casted bits eq x = x ∘′ Fin.cast (≡.sym eq)
+casted (array _) {j = zero} eq [] = []
+casted (array t) {j = suc _} eq (x ∷ y) = x ∷ casted (array t) (ℕₚ.suc-injective eq) y
+
+module _ where
+ m≤n⇒m+k≡n : ∀ {m n} → m ℕ.≤ n → P.∃ λ k → m ℕ.+ k ≡ n
+ m≤n⇒m+k≡n ℕ.z≤n = _ , ≡.refl
+ m≤n⇒m+k≡n (ℕ.s≤s m≤n) = P.dmap id (≡.cong suc) (m≤n⇒m+k≡n m≤n)
+
+ slicedSize : ∀ i j (off : Fin (suc i)) → P.∃ λ k → i ℕ.+ j ≡ Fin.toℕ off ℕ.+ (j ℕ.+ k)
+ slicedSize i j off = k , (begin
+ i ℕ.+ j ≡˘⟨ ≡.cong (ℕ._+ j) (P.proj₂ off+k≤i) ⟩
+ (Fin.toℕ off ℕ.+ k) ℕ.+ j ≡⟨ ℕₚ.+-assoc (Fin.toℕ off) k j ⟩
+ Fin.toℕ off ℕ.+ (k ℕ.+ j) ≡⟨ ≡.cong (Fin.toℕ off ℕ.+_) (ℕₚ.+-comm k j) ⟩
+ Fin.toℕ off ℕ.+ (j ℕ.+ k) ∎)
+ where
+ open ≡-Reasoning
+ off+k≤i = m≤n⇒m+k≡n (ℕₚ.≤-pred (Finₚ.toℕ<n off))
+ k = P.proj₁ off+k≤i
+
+ sliced : ∀ t {i j} → ⟦ asType t (i ℕ.+ j) ⟧ₜ → ⟦ fin (suc i) ⟧ₜ → ⟦ asType t j ⟧ₜ
+ sliced t {i} {j} x off = take t j (drop t (Fin.toℕ off) (casted t (P.proj₂ (slicedSize i j off)) x))
+
+updateSliced : ∀ {a} {A : Set a} t {i j} → ⟦ asType t (i ℕ.+ j) ⟧ₜ → ⟦ fin (suc i) ⟧ₜ → ⟦ asType t j ⟧ₜ → (⟦ asType t (i ℕ.+ j) ⟧ₜ → A) → A
+updateSliced t {i} {j} orig off v f = f (casted t (≡.sym eq) (join t (join t untaken v) dropped))
+ where
+ eq = P.proj₂ (slicedSize i j off)
+ dropped = take t (Fin.toℕ off) (casted t eq orig)
+ untaken = drop t j (drop t (Fin.toℕ off) (casted t eq orig))
+
+neg : ∀ {t} → IsNumeric t → ⟦ t ⟧ₜ → ⟦ t ⟧ₜ
+neg int x = ℤ.- x
+neg real x = ℝ.- x
+
+add : ∀ {t₁ t₂} (isNum₁ : True (isNumeric? t₁)) (isNum₂ : True (isNumeric? t₂)) → ⟦ t₁ ⟧ₜ → ⟦ t₂ ⟧ₜ → ⟦ combineNumeric t₁ t₂ {isNum₁} {isNum₂} ⟧ₜ
+add {t₁ = int} {t₂ = int} _ _ x y = x ℤ.+ y
+add {t₁ = int} {t₂ = real} _ _ x y = x /1 ℝ.+ y
+add {t₁ = real} {t₂ = int} _ _ x y = x ℝ.+ y /1
+add {t₁ = real} {t₂ = real} _ _ x y = x ℝ.+ y
+
+mul : ∀ {t₁ t₂} (isNum₁ : True (isNumeric? t₁)) (isNum₂ : True (isNumeric? t₂)) → ⟦ t₁ ⟧ₜ → ⟦ t₂ ⟧ₜ → ⟦ combineNumeric t₁ t₂ {isNum₁} {isNum₂} ⟧ₜ
+mul {t₁ = int} {t₂ = int} _ _ x y = x ℤ.* y
+mul {t₁ = int} {t₂ = real} _ _ x y = x /1 ℝ.* y
+mul {t₁ = real} {t₂ = int} _ _ x y = x ℝ.* y /1
+mul {t₁ = real} {t₂ = real} _ _ x y = x ℝ.* y
+
+pow : ∀ {t} → IsNumeric t → ⟦ t ⟧ₜ → ℕ → ⟦ t ⟧ₜ
+pow int x n = x ℤ′.^′ n
+pow real x n = x ℝ′.^′ n
+
+shiftr : 2 ℝ′.×′ 1ℝ ℝ.≉ 0ℝ → ⟦ int ⟧ₜ → ℕ → ⟦ int ⟧ₜ
+shiftr 2≉0 x n = ⌊ x /1 ℝ.* 2≉0 ℝ.⁻¹ ℝ′.^′ n ⌋
+
+module _
+ {o} {Σ : Vec Type o}
+ (2≉0 : 2 ℝ′.×′ 1ℝ ℝ.≉ 0ℝ)
+ where
+
+ open Code Σ
+
+ ⟦_⟧ᵉ : ∀ {n} {Γ : Vec Type n} {t} → Expression Γ t → ⟦ Σ ⟧ₜ′ → ⟦ Γ ⟧ₜ′ → ⟦ Σ ⟧ₜ′ × ⟦ t ⟧ₜ
+ ⟦_⟧ˢ : ∀ {n} {Γ : Vec Type n} {ret} → Statement Γ ret → ⟦ Σ ⟧ₜ′ → ⟦ Γ ⟧ₜ′ → ⟦ Σ ⟧ₜ′ × (⟦ Γ ⟧ₜ′ ⊎ ⟦ ret ⟧ₜ)
+ ⟦_⟧ᶠ : ∀ {n} {Γ : Vec Type n} {ret} → Function Γ ret → ⟦ Σ ⟧ₜ′ → ⟦ Γ ⟧ₜ′ → ⟦ Σ ⟧ₜ′ × ⟦ ret ⟧ₜ
+ ⟦_⟧ᵖ : ∀ {n} {Γ : Vec Type n} → Procedure Γ → ⟦ Σ ⟧ₜ′ → ⟦ Γ ⟧ₜ′ → ⟦ Σ ⟧ₜ′
+ update : ∀ {n Γ t e} → CanAssign {n} {Γ} {t} e → ⟦ t ⟧ₜ → ⟦ Σ ⟧ₜ′ → ⟦ Γ ⟧ₜ′ → ⟦ Σ ⟧ₜ′ × ⟦ Γ ⟧ₜ′
+
+ ⟦ lit x ⟧ᵉ σ γ = σ , 𝒦 x
+ ⟦ state i ⟧ᵉ σ γ = σ , fetch Σ σ (# i)
+ ⟦_⟧ᵉ {Γ = Γ} (var i) σ γ = σ , fetch Γ γ (# i)
+ ⟦ abort e ⟧ᵉ σ γ = case P.proj₂ (⟦ e ⟧ᵉ σ γ) of λ ()
+ ⟦ _≟_ {hasEquality = hasEq} e e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , y = ⟦ e ⟧ᵉ σ′ γ
+ σ′′ , equal (toWitness hasEq) x y
+ ⟦ _<?_ {isNumeric = isNum} e e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , y = ⟦ e ⟧ᵉ σ′ γ
+ σ′′ , comp (toWitness isNum) x y
+ ⟦ inv e ⟧ᵉ σ γ = P.map₂ Bool.not (⟦ e ⟧ᵉ σ γ)
+ ⟦ e && e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ Bool.if x then ⟦ e₁ ⟧ᵉ σ′ γ else σ′ , false
+ ⟦ e || e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ Bool.if x then σ′ , true else ⟦ e₁ ⟧ᵉ σ′ γ
+ ⟦ not e ⟧ᵉ σ γ = P.map₂ Bits.¬_ (⟦ e ⟧ᵉ σ γ)
+ ⟦ e and e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , y = ⟦ e₁ ⟧ᵉ σ′ γ
+ σ′′ , x Bits.∧ y
+ ⟦ e or e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , y = ⟦ e₁ ⟧ᵉ σ′ γ
+ σ′′ , x Bits.∨ y
+ ⟦ [ e ] ⟧ᵉ σ γ = P.map₂ (Vec._∷ []) (⟦ e ⟧ᵉ σ γ)
+ ⟦ unbox e ⟧ᵉ σ γ = P.map₂ Vec.head (⟦ e ⟧ᵉ σ γ)
+ ⟦ _∶_ {t = t} e e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , y = ⟦ e₁ ⟧ᵉ σ′ γ
+ σ′′ , join t x y
+ ⟦ slice {t = t} e e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , y = ⟦ e₁ ⟧ᵉ σ′ γ
+ σ′′ , sliced t x y
+ ⟦ cast {t = t} eq e ⟧ᵉ σ γ = P.map₂ (casted t eq) (⟦ e ⟧ᵉ σ γ)
+ ⟦ -_ {isNumeric = isNum} e ⟧ᵉ σ γ = P.map₂ (neg (toWitness isNum)) (⟦ e ⟧ᵉ σ γ)
+ ⟦ _+_ {isNumeric₁ = isNum₁} {isNumeric₂ = isNum₂} e e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , y = ⟦ e₁ ⟧ᵉ σ′ γ
+ σ′′ , add isNum₁ isNum₂ x y
+ ⟦ _*_ {isNumeric₁ = isNum₁} {isNumeric₂ = isNum₂} e e₁ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , y = ⟦ e₁ ⟧ᵉ σ′ γ
+ σ′′ , mul isNum₁ isNum₂ x y
+ -- ⟦ e / e₁ ⟧ᵉ σ γ = {!!}
+ ⟦ _^_ {isNumeric = isNum} e n ⟧ᵉ σ γ = P.map₂ (λ x → pow (toWitness isNum) x n) (⟦ e ⟧ᵉ σ γ)
+ ⟦ _>>_ e n ⟧ᵉ σ γ = P.map₂ (λ x → shiftr 2≉0 x n) (⟦ e ⟧ᵉ σ γ)
+ ⟦ rnd e ⟧ᵉ σ γ = P.map₂ ⌊_⌋ (⟦ e ⟧ᵉ σ γ)
+ ⟦ fin x e ⟧ᵉ σ γ = P.map₂ (apply x) (⟦ e ⟧ᵉ σ γ)
+ where
+ apply : ∀ {k ms n} → (All Fin ms → Fin n) → ⟦ Vec.map {n = k} fin ms ⟧ₜ′ → ⟦ fin n ⟧ₜ
+ apply {zero} {[]} f xs = f []
+ apply {suc k} {_ ∷ ms} f xs =
+ apply (λ x → f (tupHead (Vec.map fin ms) xs ∷ x)) (tupTail (Vec.map fin ms) xs)
+ ⟦ asInt e ⟧ᵉ σ γ = P.map₂ (λ i → Fin.toℕ i ℤ′.×′ 1ℤ) (⟦ e ⟧ᵉ σ γ)
+ ⟦ tup [] ⟧ᵉ σ γ = σ , _
+ ⟦ tup (e ∷ []) ⟧ᵉ σ γ = ⟦ e ⟧ᵉ σ γ
+ ⟦ tup (e ∷ e′ ∷ es) ⟧ᵉ σ γ = do
+ let σ′ , v = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , vs = ⟦ tup (e′ ∷ es) ⟧ᵉ σ′ γ
+ σ′′ , (v , vs)
+ ⟦ call f e ⟧ᵉ σ γ = P.uncurry ⟦ f ⟧ᶠ (⟦ e ⟧ᵉ σ γ)
+ ⟦ if e then e₁ else e₂ ⟧ᵉ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ Bool.if x then ⟦ e₁ ⟧ᵉ σ′ γ else ⟦ e₂ ⟧ᵉ σ′ γ
+
+ ⟦ s ∙ s₁ ⟧ˢ σ γ = do
+ let σ′ , v = ⟦ s ⟧ˢ σ γ
+ S.[ ⟦ s ⟧ˢ σ′ , (λ v → σ′ , ret v) ] v
+ ⟦ skip ⟧ˢ σ γ = σ , next γ
+ ⟦ _≔_ ref {canAssign = canAssign} e ⟧ˢ σ γ = do
+ let σ′ , v = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , γ′ = update (toWitness canAssign) v σ′ γ
+ σ′′ , next γ′
+ ⟦_⟧ˢ {Γ = Γ} (declare e s) σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ let σ′′ , v = ⟦ s ⟧ˢ σ′ (tupCons Γ x γ)
+ σ′′ , S.map₁ (tupTail Γ) v
+ ⟦ invoke p e ⟧ˢ σ γ = do
+ let σ′ , v = ⟦ e ⟧ᵉ σ γ
+ ⟦ p ⟧ᵖ σ′ v , next γ
+ ⟦ if e then s₁ else s₂ ⟧ˢ σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ Bool.if x then ⟦ s₁ ⟧ˢ σ′ γ else ⟦ s₂ ⟧ˢ σ′ γ
+ ⟦_⟧ˢ {Γ = Γ} {ret = t} (for m s) σ γ = helper m ⟦ s ⟧ˢ σ γ
+ where
+ helper : ∀ m → (⟦ Σ ⟧ₜ′ → ⟦ fin m ∷ Γ ⟧ₜ′ → ⟦ Σ ⟧ₜ′ × (⟦ fin m ∷ Γ ⟧ₜ′ ⊎ ⟦ t ⟧ₜ)) → ⟦ Σ ⟧ₜ′ → ⟦ Γ ⟧ₜ′ → ⟦ Σ ⟧ₜ′ × (⟦ Γ ⟧ₜ′ ⊎ ⟦ t ⟧ₜ)
+ helper zero s σ γ = σ , next γ
+ helper (suc m) s σ γ with s σ (tupCons Γ zero γ)
+ ... | σ′ , ret v = σ′ , ret v
+ ... | σ′ , next γ′ = helper m s′ σ′ (tupTail Γ γ′)
+ where
+ s′ : ⟦ Σ ⟧ₜ′ → ⟦ fin m ∷ Γ ⟧ₜ′ → ⟦ Σ ⟧ₜ′ × (⟦ fin m ∷ Γ ⟧ₜ′ ⊎ ⟦ t ⟧ₜ)
+ s′ σ γ =
+ P.map₂ (S.map₁ (tupCons Γ (tupHead Γ γ) ∘′ (tupTail Γ)))
+ (s σ (tupCons Γ (suc (tupHead Γ γ)) (tupTail Γ γ)))
+
+ ⟦ s ∙return e ⟧ᶠ σ γ with ⟦ s ⟧ˢ σ γ
+ ... | σ′ , ret v = σ′ , v
+ ... | σ′ , next γ′ = ⟦ e ⟧ᵉ σ′ γ′
+ ⟦_⟧ᶠ {Γ = Γ} (declare e f) σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ ⟦ f ⟧ᶠ σ′ (tupCons Γ x γ)
+
+ ⟦ s ∙end ⟧ᵖ σ γ = P.proj₁ (⟦ s ⟧ˢ σ γ)
+ ⟦_⟧ᵖ {Γ = Γ} (declare e p) σ γ = do
+ let σ′ , x = ⟦ e ⟧ᵉ σ γ
+ ⟦ p ⟧ᵖ σ′ (tupCons Γ x γ)
+
+ update (state i {i<o}) v σ γ = updateAt Σ (#_ i {m<n = i<o}) v σ , γ
+ update {Γ = Γ} (var i {i<n}) v σ γ = σ , updateAt Γ (#_ i {m<n = i<n}) v γ
+ update abort v σ γ = σ , γ
+ update (_∶_ {m = m} {t = t} e e₁) v σ γ = do
+ let σ′ , γ′ = update e (sliced t v (Fin.fromℕ _)) σ γ
+ update e₁ (sliced t (casted t (ℕₚ.+-comm _ m) v) zero) σ′ γ′
+ update [ e ] v σ γ = update e (Vec.head v) σ γ
+ update (unbox e) v σ γ = update e (v ∷ []) σ γ
+ update (slice {t = t} {e₁ = e₁} a e₂) v σ γ = do
+ let σ′ , off = ⟦ e₂ ⟧ᵉ σ γ
+ let σ′′ , orig = ⟦ e₁ ⟧ᵉ σ′ γ
+ updateSliced t orig off v (λ v → update a v σ′′ γ)
+ update (cast {t = t} eq e) v σ γ = update e (casted t (≡.sym eq) v) σ γ
+ update (tup {es = []} x) v σ γ = σ , γ
+ update (tup {es = _ ∷ []} (x ∷ [])) v σ γ = update x v σ γ
+ update (tup {es = _ ∷ _ ∷ _} (x ∷ xs)) (v , vs) σ γ = do
+ let σ′ , γ′ = update x v σ γ
+ update (tup xs) vs σ′ γ′