blob: e16797304ccc9c81382c0f092fe01e6bc1232efa [file] [log] [blame] [edit]
;;
;; NanoWasm
;;
;; Abstract Syntax
syntax localidx = nat
syntax globalidx = nat
syntax mut = MUT
syntax valtype = I32 | I64 | F32 | F64
syntax functype = valtype* -> valtype*
syntax globaltype = mut? valtype
syntax const = nat
syntax instr =
| NOP
| DROP
| SELECT
| CONST valtype const hint(show %.CONST %)
| LOCAL.GET localidx
| LOCAL.SET localidx
| GLOBAL.GET globalidx
| GLOBAL.SET globalidx
;; Validation
syntax context = { GLOBALS globaltype*, LOCALS valtype* }
var C : context
relation Instr_ok: context |- instr : functype
rule Instr_ok/nop:
C |- NOP : eps -> eps
rule Instr_ok/drop:
C |- DROP : t -> eps
rule Instr_ok/select:
C |- SELECT : t t I32 -> t
rule Instr_ok/const:
C |- CONST t c : eps -> t
rule Instr_ok/local.get:
C |- LOCAL.GET x : eps -> t
-- if C.LOCALS[x] = t
rule Instr_ok/local.set:
C |- LOCAL.SET x : t -> eps
-- if C.LOCALS[x] = t
rule Instr_ok/global.get:
C |- GLOBAL.GET x : eps -> t
-- if C.GLOBALS[x] = MUT? t
rule Instr_ok/global.set:
C |- GLOBAL.GET x : t -> eps
-- if C.GLOBALS[x] = MUT t
;; Execution
syntax addr = nat
syntax moduleinst = { GLOBALS addr* }
syntax val = CONST valtype const
syntax store = { GLOBALS val* }
syntax frame = { LOCALS val*, MODULE moduleinst }
syntax state = store; frame
syntax config = state; instr*
var f : frame
var s : store
var z : state
def $local(state, localidx) : val
def $local((s; f), x) = f.LOCALS[x]
def $global(state, globalidx) : val
def $global((s; f), x) = s.GLOBALS[f.MODULE.GLOBALS[x]]
def $update_local(state, localidx, val) : state
def $update_local((s; f), x, v) = s; f[.LOCALS[x] = v]
def $update_global(state, globalidx, val) : state
def $update_global((s; f), x, v) = s[.GLOBALS[f.MODULE.GLOBALS[x]] = v]; f
relation Step: config ~> config
relation Step_pure: instr* ~> instr*
relation Step hint(tabular)
relation Step_pure hint(tabular)
rule Step/pure:
z; instr* ~> z; instr'*
-- Step_pure: instr* ~> instr'*
rule Step_pure/nop:
NOP ~> eps
rule Step_pure/drop:
val DROP ~> eps
rule Step_pure/select-true:
val_1 val_2 (CONST I32 c) SELECT ~> val_1 -- if c =/= 0
rule Step_pure/select-false:
val_1 val_2 (CONST I32 c) SELECT ~> val_2 -- otherwise
rule Step/local.get:
z; (LOCAL.GET x) ~> z; val
-- if val = $local(z, x)
rule Step/local.set:
z; val (LOCAL.SET x) ~> z'; eps
-- if z' = $update_local(z, x, val)
rule Step/global.get:
z; (GLOBAL.GET x) ~> z; val
-- if val = $global(z, x)
rule Step/global.set:
z; val (GLOBAL.SET x) ~> z'; eps
-- if z' = $update_global(z, x, val)
;; Binary Format
def $float(nat, nat*) : const
grammar Bbyte : nat = 0x00 | ... | 0xFF
grammar Bu(N : nat) : nat =
| n:Bbyte => n -- if $(n < 2^7 /\ n < 2^N)
| n:Bbyte m:Bu($(N-7)) => $(2^7 * m + (n - 2^7)) -- if $(n >= 2^7 /\ N > 7)
grammar Bu32 : const = Bu(32)
grammar Bu64 : const = Bu(64)
grammar Bf(N : nat) : nat =
| b*:Bbyte^(N/8) => $float(N, b*)
grammar Bf32 : const = Bf(32)
grammar Bf64 : const = Bf(64)
grammar Bvaltype : valtype =
| 0x7F => I32
| 0x7E => I64
| 0x7D => F32
| 0x7C => F64
grammar Bmut : mut? =
| 0x00 => eps
| 0x01 => MUT
grammar Bglobaltype : globaltype =
| t:Bvaltype mut:Bmut => mut t
grammar Bresulttype : valtype* =
| n:Bu32 (t:Bvaltype)^n => t^n
grammar Bfunctype : functype =
| 0x60 t_1*:Bresulttype t_2*:Bresulttype => t_1* -> t_2*
grammar Bglobalidx : globalidx = x:Bu32 => x
grammar Blocalidx : localidx = x:Bu32 => x
grammar Binstr : instr =
| 0x01 => NOP
| 0x1A => DROP
| 0x1B => SELECT
| 0x20 x:Blocalidx => LOCAL.GET x
| 0x21 x:Blocalidx => LOCAL.SET x
| 0x23 x:Bglobalidx => GLOBAL.GET x
| 0x24 x:Bglobalidx => GLOBAL.SET x
| 0x41 n:Bu32 => CONST I32 n
| 0x42 n:Bu64 => CONST I64 n
| 0x43 p:Bf32 => CONST F32 p
| 0x44 p:Bf64 => CONST F64 p