12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273moduleValue=Runtime.ValuemoduleIO=Runtime.Sim.Io(* The state consists of:
- current evaluation context
- current arch
- list of transmissions to perform *)types=Value.t*Value.t*IO.txlist(* State monad with failure *)type'astate=s->'aoption*s(* Get, Put, Modify: state manipulation functions *)letget:sstate=funs->(Somes,s)letput(x:s):unitstate=fun_->(Some(),x)letmodify(f:s->s):unitstate=funs->(Some(),fs)(* Return: wrap a value into the monad *)letreturn(a:'a):'astate=funs->(Somea,s)(* Bind: sequence two computations in the monad *)letbind(m:'astate)(f:'a->'bstate)s=matchmswithSomea,s->fas|None,s->(None,s)let(>>)(ma:'astate)(mb:'bstate)=bindma(fun_->mb)let(let*)=bind(* Map: apply a function to the result of a computation in the monad *)letmap(m:'astate)(f:'a->'b)=bindm(funa->return(fa))let(let+)=map(* Sequence: run each state action from left to right and return accumulated result *)letsequence(ms:'astatelist):'aliststate=letrecseqacc=function|[]->return(List.revacc)|m::ms->let*x=minseq(x::acc)msinseq[]ms(* Combinators *)(* If computation succeeds, run `some`. Otherwise, run `none` *)leton_result(m:'astate)~(some:'a->'bstate)~(none:unit->'bstate):'bstate=funs->letresult,s'=msinmatchresultwithSomex->somexs'|None->none()s'(* Apply: apply a function to the current context and arch, updating them *)letapply(f:Value.t->Value.t->Value.t*Value.t*'a):'astate=let*value_ctx,value_arch,txs=getinletvalue_ctx,value_arch,result=fvalue_ctxvalue_archinlet+()=put(value_ctx,value_arch,txs)inresult(* Guard: fail the computation if the condition is false *)letguard(cond:bool):unitstate=ifcondthenreturn()elsefuns->(None,s)letempty:'astate=funs->(None,s)letrun(m:'astate)(s:s):'aoption*s=ms