summaryrefslogtreecommitdiff
path: root/src/Wasm/Data.agda
diff options
context:
space:
mode:
authorChloe Brown <chloe.brown.00@outlook.com>2021-08-10 19:11:38 +0100
committerChloe Brown <chloe.brown.00@outlook.com>2021-08-10 19:11:38 +0100
commit904924c33720c3481f738966f32e9c34736f92cf (patch)
tree0365bccd7afa6a0c4031866e8681f495a1e3c8bf /src/Wasm/Data.agda
parenta3a8a44b4bc0d60164452826645066a5ffed5bc5 (diff)
Rewrite so only valid modules can be constructed.
Diffstat (limited to 'src/Wasm/Data.agda')
-rw-r--r--src/Wasm/Data.agda272
1 files changed, 272 insertions, 0 deletions
diff --git a/src/Wasm/Data.agda b/src/Wasm/Data.agda
new file mode 100644
index 0000000..f7ed8da
--- /dev/null
+++ b/src/Wasm/Data.agda
@@ -0,0 +1,272 @@
+{-# OPTIONS --safe --without-K #-}
+
+module Wasm.Data where
+
+open import Data.Fin using (Fin; zero; suc)
+open import Data.List using (List; []; _∷_; _++_; length; lookup; map)
+open import Data.List.Relation.Binary.Pointwise using (Pointwise)
+open import Data.List.Relation.Unary.All using (All)
+open import Data.List.Relation.Unary.Any using (Any)
+open import Data.List.Relation.Unary.AllPairs using (AllPairs)
+open import Data.Maybe using (Maybe; just; nothing; maybe)
+open import Data.Nat using (ℕ; suc; _+_; _≤_; z≤n)
+open import Data.Product using (_×_; _,_; proj₁)
+open import Data.Sum using (_⊎_)
+open import Data.Unit using (⊤)
+open import Data.Vec using (Vec)
+open import Function as _ using (_∋_)
+open import Relation.Binary.PropositionalEquality using (_≡_; _≢_)
+open import Wasm.Data.Instruction as Inst using (Expression; Constant)
+open import Wasm.Value using (Byte; Name)
+open import Wasm.Type
+
+record ExternTypes : Set where
+ field
+ funcs : List FuncType
+ tables : List TableType
+ mems : List MemType
+ globals : List GlobalType
+
+record Context : Set where
+ field
+ funcs : List FuncType
+ tables : List TableType
+ mems : List MemType
+ globals : List GlobalType
+ elems : List RefType
+ datas : ℕ
+
+private
+ makeContext : (Cᵢ : ExternTypes) → (Cₘ : Context) → (refs : List (Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)))) → Inst.Context
+ makeContext Cᵢ Cₘ refs = record
+ { funcs = Cᵢ.funcs ++ Cₘ.funcs
+ ; tables = Cᵢ.tables ++ Cₘ.tables
+ ; mems = Cᵢ.mems ++ Cₘ.mems
+ ; globals = Cᵢ.globals ++ Cₘ.globals
+ ; elems = Cₘ.elems
+ ; datas = Cₘ.datas
+ ; locals = []
+ ; labels = []
+ ; return = nothing
+ ; refs = refs
+ }
+ where
+ module Cᵢ = ExternTypes Cᵢ
+ module Cₘ = Context Cₘ
+
+ makeGlobalContext : (Cᵢ : ExternTypes) → (Cₘ : Context) → (refs : List (Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)))) → Inst.Context
+ makeGlobalContext Cᵢ Cₘ refs = record
+ { funcs = Cᵢ.funcs ++ Cₘ.funcs
+ ; tables = []
+ ; mems = []
+ ; globals = Cᵢ.globals
+ ; elems = []
+ ; datas = 0
+ ; locals = []
+ ; labels = []
+ ; return = nothing
+ ; refs = refs
+ }
+ where
+ module Cᵢ = ExternTypes Cᵢ
+ module Cₘ = Context Cₘ
+
+record Function (Cᵢ : ExternTypes) (Cₘ : Context) (refs : List (Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)))) (idx : Fin (length (Context.funcs Cₘ))) : Set where
+ private
+ module Cₘ = Context Cₘ
+
+ type = lookup Cₘ.funcs idx
+
+ private
+ module type = FuncType type
+
+ field
+ locals : List ValType
+
+ private
+ C = Inst.Context ∋ record (makeContext Cᵢ Cₘ refs)
+ { locals = type.from ++ locals
+ ; labels = type.to ∷ []
+ ; return = just type.to
+ }
+ field
+ body : Expression C type.to
+
+record Global (Cᵢ : ExternTypes) (Cₘ : Context) (refs : List (Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)))) (idx : Fin (length (Context.globals Cₘ))) : Set where
+ private
+ module Cₘ = Context Cₘ
+ C = Inst.Context ∋ makeGlobalContext Cᵢ Cₘ refs
+
+ type = lookup Cₘ.globals idx
+
+ private
+ module type = GlobalType type
+
+ field
+ {body} : Expression C (type.type ∷ [])
+ constant : Constant body
+
+GlobalRef : ∀ {Cᵢ Cₘ refs idx} → Global Cᵢ Cₘ refs idx → Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)) → Set
+GlobalRef global x = Inst.InstructionRef (Global.body global) x
+
+data ElemMode (C : Inst.Context) : RefType → Set where
+ passive : ∀ {τ} → ElemMode C τ
+ active : ∀ table {offset : Expression C (num i32 ∷ [])} → Constant offset → ElemMode C (TableType.type (lookup (Inst.Context.tables C) table))
+ declarative : ∀ {τ} → ElemMode C τ
+
+data ElemModeRef {C : Inst.Context} : ∀ {τ} → ElemMode C τ → Fin (length (Inst.Context.funcs C)) → Set where
+ activeRef : ∀ {x} table {offset} constant → Inst.InstructionRef offset x → ElemModeRef (active table {offset} constant) x
+
+record Elem (Cᵢ : ExternTypes) (Cₘ : Context) (refs : List (Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)))) (idx : Fin (length (Context.elems Cₘ))) : Set where
+ private
+ module Cₘ = Context Cₘ
+ C = Inst.Context ∋ makeContext Cᵢ Cₘ refs
+
+ type = lookup Cₘ.elems idx
+
+ field
+ {inits} : List (Expression C (ref type ∷ []))
+ constant : All Constant inits
+ mode : ElemMode C type
+
+data ElemRef {Cᵢ} {Cₘ} {refs} {idx} (elem : Elem Cᵢ Cₘ refs idx) (x : Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ))) : Set where
+ initsRef : Any (λ init → Inst.InstructionRef init x) (Elem.inits elem) → ElemRef elem x
+ modeRef : ElemModeRef (Elem.mode elem) x → ElemRef elem x
+
+data DataMode (C : Inst.Context) : Set where
+ passive : DataMode C
+ active : ∀ (memory : Fin (length (Inst.Context.mems C))) {offset : Expression C (num i32 ∷ [])} → Constant offset → DataMode C
+
+
+data DataModeRef {C : Inst.Context} : DataMode C → Fin (length (Inst.Context.funcs C)) → Set where
+ activeRef : ∀ {x} memory {offset} constant → Inst.InstructionRef offset x → DataModeRef (active memory {offset} constant) x
+
+record Data (Cᵢ : ExternTypes) (Cₘ : Context) (refs : List (Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)))) (idx : Fin (Context.datas Cₘ)) : Set where
+ private
+ C = Inst.Context ∋ makeContext Cᵢ Cₘ refs
+ field
+ init : List Byte
+ mode : DataMode C
+
+DataRef : ∀ {Cᵢ Cₘ refs idx} → Data Cᵢ Cₘ refs idx → Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)) → Set
+DataRef dta x = DataModeRef (Data.mode dta) x
+
+record Exports (Cᵢ : ExternTypes) (Cₘ : Context) (refs : List (Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)))) (Cₑ : ExternTypes) : Set where
+ private
+ C = Inst.Context ∋ makeContext Cᵢ Cₘ refs
+ module Cₑ = ExternTypes Cₑ
+ module C = Inst.Context C
+ field
+ funcs : List (Name × Fin (length (C.funcs)))
+ tables : List (Name × Fin (length (C.tables)))
+ mems : List (Name × Fin (length (C.mems)))
+ globals : List (Name × Fin (length (C.globals)))
+ funcsOk : Pointwise (λ (_ , x) τ → lookup C.funcs x ≡ τ) funcs Cₑ.funcs
+ tablesOk : Pointwise (λ (_ , x) τ → lookup C.tables x ≡ τ) tables Cₑ.tables
+ memsOk : Pointwise (λ (_ , x) τ → lookup C.mems x ≡ τ) mems Cₑ.mems
+ globalsOk : Pointwise (λ (_ , x) τ → lookup C.globals x ≡ τ) globals Cₑ.globals
+ names = map proj₁ funcs ++ map proj₁ tables ++ map proj₁ mems ++ map proj₁ globals
+ field
+ namesDisjoint : AllPairs _≢_ names
+
+ExportsRef : ∀ {Cᵢ Cₘ refs Cₑ} → Exports Cᵢ Cₘ refs Cₑ → Fin (length (ExternTypes.funcs Cᵢ ++ Context.funcs Cₘ)) → Set
+ExportsRef exports x = Any (λ (_ , y) → y ≡ x) (Exports.funcs exports)
+
+record Imports (Cᵢ : ExternTypes) : Set where
+ private
+ module Cᵢ = ExternTypes Cᵢ
+ field
+ funcs : Vec (Name × Name) (length Cᵢ.funcs)
+ tables : Vec (Name × Name) (length Cᵢ.tables)
+ mems : Vec (Name × Name) (length Cᵢ.mems)
+ globals : Vec (Name × Name) (length Cᵢ.globals)
+
+infixr 5 _∷_
+
+data DList : ∀ {n} → (A : Fin n → Set) → Set₁ where
+ [] : ∀ {A} → DList {0} A
+ _∷_ : ∀ {n A} → A zero → DList {n} (λ i → A (suc i)) → DList A
+
+data DAny : ∀ {n A} → (∀ {i} → A i → Set) → DList {n} A → Set₁ where
+ here : ∀ {n A} {P : ∀ {i} → A i → Set} {x xs} → P x → DAny {suc n} {A} P (x ∷ xs)
+ there : ∀ {n A} {P : ∀ {i} → A i → Set} {x xs} → DAny (λ {i} → P {suc i}) xs → DAny {suc n} {A} P (x ∷ xs)
+
+record Module (it et : ExternTypes) : Set₁ where
+ private
+ module it = ExternTypes it
+ field
+ ft : List FuncType
+ tables : List TableType
+ mems : List MemType
+ rt : List RefType
+ n : ℕ
+ start : Maybe (Fin (length (it.funcs ++ ft)))
+ private
+ Cₘ = Context ∋ record
+ { funcs = ft
+ ; tables = tables
+ ; mems = mems
+ ; globals = it.globals
+ ; elems = rt
+ ; datas = n
+ }
+ field
+ refs : List (Fin (length (it.funcs ++ ft)))
+ funcs : DList (Function it Cₘ refs)
+ globals : DList (Global it Cₘ refs)
+ elems : DList (Elem it Cₘ refs)
+ datas : DList (Data it Cₘ refs)
+ startOk : maybe (λ x → lookup (it.funcs ++ ft) x ≡ ([] ⟶ [])) ⊤ start
+ exports : Exports it Cₘ refs et
+ memCount : length it.mems + length mems ≤ 1
+ refsUsed : All (λ i → DAny (λ g → GlobalRef g i) globals
+ ⊎ DAny (λ e → ElemRef e i) elems
+ ⊎ DAny (λ d → DataRef d i) datas
+ ⊎ ExportsRef exports i)
+ refs
+
+private
+ module Test where
+ open import Data.List.Relation.Binary.Pointwise using ([]; _∷_)
+ open import Data.List.Relation.Unary.All using ([])
+ open import Data.List.Relation.Unary.AllPairs using ([]; _∷_)
+ open import Relation.Binary.PropositionalEquality using (refl)
+ open Inst
+
+ addTwoImports : ExternTypes
+ addTwoImports = record { funcs = [] ; tables = [] ; mems = [] ; globals = [] }
+
+ addTwoExports : ExternTypes
+ addTwoExports = record { funcs = (num i32 ∷ num i32 ∷ [] ⟶ num i32 ∷ []) ∷ [] ; tables = [] ; mems = [] ; globals = [] }
+
+ addTwoModule : Module addTwoImports addTwoExports
+ addTwoModule = record
+ { ft = (num i32 ∷ num i32 ∷ [] ⟶ num i32 ∷ []) ∷ []
+ ; tables = []
+ ; mems = []
+ ; rt = []
+ ; n = 0
+ ; start = nothing
+ ; refs = []
+ ; funcs = record
+ { locals = []
+ ; body = seq (local-get zero) (seq (frame (local-get (suc zero))) (i32-binop i32.add))
+ } ∷ []
+ ; globals = []
+ ; elems = []
+ ; datas = []
+ ; startOk = _
+ ; exports = record
+ { funcs = ("addTwo" , zero) ∷ []
+ ; tables = []
+ ; mems = []
+ ; globals = []
+ ; funcsOk = refl ∷ []
+ ; tablesOk = []
+ ; memsOk = []
+ ; globalsOk = []
+ ; namesDisjoint = [] ∷ []
+ }
+ ; memCount = z≤n
+ ; refsUsed = []
+ }