You can search for identifiers within the package.
in-package search v0.2.0
Source file note.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946(*---------------------------------------------------------------------------
Copyright (c) 2018 The note programmers. All rights reserved.
SPDX-License-Identifier: ISC
---------------------------------------------------------------------------*)modulerecSrc:sig(* Sources where data is pushed *)typet=V:_typed->tand'atypedvalcompare:t->t->intvalid:t->intvalcell:'atyped->'aC.tvaluntyped:'atyped->tvallogrs:t->Logr.tlistvaladd_logr:Logr.t->t->unitvalrem_logr:Logr.t->t->unitvalreset_stamp:t->unitvalfind_active_step:Step.t->Srcs.t->Step.tvalcreate:?eq:('a->'a->bool)->'a->'atypedend=structtypet=V:_typed->tand'atyped={id:int;(* unique id for the source *)cell:'aC.t;(* Cell holding the source's value *)mutablelogrs:Logr.tlist(* loggers that depend on the source *);self:t;(* self, untyped. *)}letid(Vs)=s.idletcells=s.cellletuntypeds=s.selfletcompare(Vs)(Vt)=(Stdlib.compare:int->int->int)s.idt.idletlogrs(Vs)=s.logrsletadd_logrlogr(Vs)=s.logrs<-logr::s.logrsletrem_logrlogr(Vs)=letrecremlogracc=function|[]->acc|v::vswhenv==logr->List.rev_appendvsacc|v::vs->remlogr(v::acc)vsins.logrs<-remlogr[]s.logrsletreset_stamp(Vs)=C.set_stamps.cellStep.nilexceptionStepofStep.tletfind_active_stepstepss=ifstep!=Step.nilthenstepelseletfind_not_nil(Vs)=letstep=C.stamps.cellinifstep!=Step.nilthenraise_notrace(Stepstep)intrySrcs.iterfind_not_nilss;Step.nilwithSteps->sletuid=letid=ref0infun()->incrid;!idletcreate?eqv=letupdate__=()inletcell=C.create?eq~step:Step.nil~srcs:Srcs.emptyv~updateinletrecsrc={id=uid();cell;logrs=[];self=Vsrc}inC.set_srcscell(Srcs.singletonsrc.self);C.set_srcs_changedcellfalse;srcendandSrcs:Set.Swithtypeelt=Src.t=Set.Make(Src)andC:sig(* Cells *)type'attypeuntyped=C:'at->untypedvalcreate:?eq:('a->'a->bool)->step:Step.t->srcs:Srcs.t->'a->update:(Step.t->'at->unit)->'atvalconst:?eq:('a->'a->bool)->'a->'atvaleq:'at->('a->'a->bool)valset_eq:'at->('a->'a->bool)->unitvalwith_eq:('a->'a->bool)->'at->'atvalstamp:'at->Step.tvalset_stamp:'at->Step.t->unitvalsrcs:'at->Srcs.tvalsrcs_changed:'at->boolvalset_srcs:'at->Srcs.t->unitvalset_srcs_changed:'at->bool->unitvalvalue:'at->'avalvalue_changed:'at->boolvalset_value:'at->'a->unitvalupdate:Step.t->'at->unitvalset_update:'at->(Step.t->'at->unit)->unitvalsrc_update:Step.t->'at->'a->boolvalup_to_date_value:'at->'avalcreate_instant:step:Step.t->srcs:Srcs.t->'aoption->update:(Step.t->'aoptiont->unit)->'aoptiontvalreset_instant:'aoptiont->unitvalset_instant:Step.t->'aoptiont->'aoption->unitvaldelay:'a->'atLazy.t->'atvalfix:?eq:('a->'a->bool)->'a->('at->'at*'b)->'bvaldefer:'a->'at->'atvaldump_src_ids:Format.formatter->'at->unitend=structtype'at={mutableeq:'a->'a->bool;(* testing for cell value equality *)mutablestamp:Step.t;(* last step in which the cell updated *)mutablesrcs:Srcs.t;(* sources the cell depends on *)mutablesrcs_changed:bool;(* [true] if [srcs] changed *)mutablevalue:'a;(* cell value *)mutablevalue_changed:bool;(* [true] if [value] changed *)mutableupdate:Step.t->'at->unit;}(* updates [value] and [srcs] *)typeuntyped=C:'at->untypedletcreate?(eq=(=))~step~srcsvalue~update={eq;stamp=step;srcs;srcs_changed=true;value;value_changed=true;update}letconst?(eq=(=))v={eq;stamp=Step.nil;srcs=Srcs.empty;srcs_changed=false;value=v;value_changed=false;update=(fun__->())}leteqc=c.eqletset_eqceq=c.eq<-eqletwith_eqeqc={cwitheq}letstampc=c.stampletset_stampcstamp=c.stamp<-stampletsrcs_changedc=c.srcs_changedletset_srcs_changedcbool=c.srcs_changed<-boolletsrcsc=c.srcsletset_srcscsrcs=c.srcs_changed<-true;c.srcs<-srcsletvaluec=c.valueletvalue_changedc=c.value_changedletset_valuecv=ifc.eqvc.valuethen()else(c.value_changed<-true;c.value<-v)letupdatestepc=ifstep!=Step.nil&&c.stamp!=stepthenbeginc.stamp<-step;c.srcs_changed<-false;c.value_changed<-false;(* XXX would be nice to avoid constructing the set *)ifSrcs.(is_empty(interc.srcs(Step.srcsstep)))then()(* no need to go there, nothing can update *)elsec.updatestepcendletset_updatecu=c.update<-uletsrc_updatestepcv=c.value_changed<-false;ifc.eqvc.valuethenfalseelse(c.stamp<-step;c.value_changed<-true;c.value<-v;true)letup_to_date_valuec=letstep=Src.find_active_stepStep.nilc.srcsinupdatestepc;c.valueletreset_instantc=c.value_changed<-false;c.value<-Noneletset_instantstepc=function|None->()|Some_asv->c.value_changed<-true;c.value<-v;Step.add_cleanupstep(fun()->reset_instantc)letcreate_instant~step~srcsvalue~update=letvalue_changed=matchvaluewithNone->false|Some_->trueinletc={eq=(=);stamp=step;srcs;srcs_changed=true;value;value_changed;update}inifvalue_changed&&step<>Step.nilthenStep.add_cleanupstep(fun()->reset_instantc);cletdelayiz=failwith"TOOD"letfix?eqicf=letsrc=Src.create?eqiinletsrc=Src.Vsrcandd=Src.cellsrcinletc,r=cfdinletc_update=c.updateinletc_updatestepself=c_updatestepself;ifc.value_changedthen(Step.add_delayedstepsrc);inletd_updatestepself=ifstep==Step.delayedthenset_valueself(valuec)else()inc.update<-c_update;d.update<-d_update;letstep=Src.find_active_stepStep.nil(C.srcsc)inlet()=updatestepcinifstep==Step.nilthenStep.execute_delayed(Srcs.singletonsrc);rletdeferinitc=(** XXX do we really need a source for that. *)letsrc=Src.create~eq:c.eqinitinletsrc=Src.Vsrcandd=Src.cellsrcinletupdatestepself=ifstep==Step.delayedthenset_valueself(valuec)elsebeginC.(updatestepc);ifC.srcs_changedcthenC.set_srcsd(C.srcsc);ifC.value_changedcthenStep.add_delayedstepsrcendind.update<-update;letstep=Src.find_active_stepStep.nil(srcsc)inlet()=updatestepcinlet()=updatestepdinifstep==Step.nilthenStep.execute_delayed(Srcs.singletonsrc);dletdump_src_idsppfc=Format.fprintfppf"@[{%a}@]"Format.(pp_print_list~pp_sep:pp_print_spacepp_print_int)(List.map(funs->Src.ids)(Srcs.elementsc.srcs))endandLogr:sigtype'aobsvalconst:'a->'aobsvalobs_cell:'aC.t->'aobsvalapp:('a->'b)obs->'aobs->'bobsval($):('a->'b)obs->'aobs->'bobstypetvalcreate:?now:bool->unitobs->tvalfor_cell:?now:bool->'aC.t->('a->unit)->tvalforce:t->unitvaldestroy:t->unitvalupdate:Step.t->t->unitvalhold:t->unitvalmay_hold:toption->unitvalunhold_all:unit->unitend=structtype'aobs=C.untypedlist*(unit->'a)letconstv=[],fun()->vletobs_cellc=[C.Cc],fun()->C.valuecletapp(fcs,f)(vcs,v)=List.rev_appendfcsvcs,fun()->(f())(v())let($)=apptypet={mutablestamp:Step.t;mutablesrcs:Srcs.t;(* sources we are registered with *)cells:C.untypedlist;(* cells we are observing *)log:unit->unit(* logger action *)}letupdate_srcsl=letcells_srcsl=letadd_cellacc(C.Cc)=Srcs.unionacc(C.srcsc)inList.fold_leftadd_cellSrcs.emptyl.cellsinletnew_srcs=cells_srcslinletrems=Srcs.diffl.srcsnew_srcsinletadds=Srcs.diffnew_srcsl.srcsinSrcs.iter(Src.rem_logrl)rems;Srcs.iter(Src.add_logrl)adds;l.srcs<-new_srcsletupdatestepl=ifstep!=Step.nil&&step!=l.stampthenbeginl.stamp<-step;letrecloopstepsrcs_changedvalue_changed=function|[]->ifsrcs_changedthenupdate_srcsl;ifvalue_changedthenl.log()|(C.Cc)::cs->C.updatestepc;loopstep(srcs_changed||C.srcs_changedc)(value_changed||C.value_changedc)csinloopstepfalsefalsel.cellsendletforcel=letstep=Src.find_active_stepStep.nill.srcsinupdatestepl;l.log()letcreate?(now=true)(cells,log)=letl={stamp=Step.nil;srcs=Srcs.empty;cells;log}inupdate_srcsl;ifnowthenforcel;lletfor_cell?nowclog=create?now([C.Cc],fun()->log(C.valuec))letdestroyl=Srcs.iter(Src.rem_logrl)l.srcsletheld:tlistref=ref[]letholdl=held:=l::!heldletmay_hold=functionNone->()|Somel->holdlletunhold_all()=List.iterdestroy!held;held:=[]endandStep:sigtypetvalcreate:unit->tvalnil:tvaldelayed:tvalsrcs:t->Srcs.tvaladd_src:t->Src.t->unitvaladd_delayed:t->Src.t->unitvaladd_cleanup:t->(unit->unit)->unitvalexecute:t->unitvalexecute_delayed:Srcs.t->unitend=structtypet={mutablesrcs:Srcs.t;(* sources part of the update step *)mutabledelayed:Srcs.t;(* sources for delayed cells *)mutablecleanup:(unit->unit)list(* for reseting events to None *)}let_createsrcs={srcs;delayed=Srcs.empty;cleanup=[]}letcreate()=_createSrcs.emptyletnil=create()letdelayed=create()letsrcsstep=step.srcsletadd_srcstepsrc=step.srcs<-Srcs.addsrcstep.srcsletadd_delayedstepsrc=step.delayed<-Srcs.addsrcstep.delayedletadd_cleanupstepclean=step.cleanup<-clean::step.cleanupletcleanupstep=List.iter(funf->f())step.cleanup;step.cleanup<-[]letalready_executed()=invalid_arg"step already executed"letrecexecute_delayedsrcs=letupdate_delayed_srcds(Src.Vs)=letc=Src.cellsinC.updatedelayedc;C.set_stampcds;inletds=_createsrcsindelayed.srcs<-srcs;Srcs.iter(update_delayed_srcds)srcs;executedsandexecutestep=letupdate_src_logssrc=List.iter(Logr.updatestep)(Src.logrssrc)inSrcs.iterupdate_src_logsstep.srcs;Srcs.iterSrc.reset_stampstep.srcs;cleanupstep;add_cleanupstepalready_executed;(* error further executes *)matchSrcs.is_emptystep.delayedwith|true->()|false->execute_delayedstep.delayedend(* High-level interface *)type'asignal='aC.ttype'aevent='aoptionC.t(* Signal and event definition always have the same structure.
let combinator ... =
let update step self =
C.update step ...
if C.srcs_changed ... then C.set_srcs self ...
if C.value_changed ... then C.set_{instant,value} self ...
in
let srcs = ...
let step = Src.find_active_step Step.nil srcs in
let () = C.update step ... in
let srcs = ...
let init =
C.create ....
In [update], update dependencies. If dependencies sources changed
update the cell's sources, if dependencies values changed update
the cell's value.
To create the cell. Get the dependency sources. Find the update
step going on (will be Step.nil if there is none). Update the
dependencies with the step. Get the sources again (they may have changed)
and the needed values to create the cell.
XXX it would be nice to see if we can simply invoke [update] for
init, possibly with a special Step.init step on Step.nil. *)moduleE=structtype'at='aeventtype'asend=?step:Step.t->'a->unitletobs=Logr.obs_cellletlog?nowef=letwrap=functionNone->()|Somev->fvinSome(Logr.for_cell?nowewrap)letcreate()=letsrc=Src.createNoneinletsend?stepv=letstep,exec=matchstepwith|None->Step.create(),true|Somestep->step,falseinC.set_stamp(Src.cellsrc)step;C.set_instantstep(Src.cellsrc)(Somev);Step.add_srcstep(Src.untypedsrc);ifexecthenStep.executestepin(Src.cellsrc),sendletvalue=C.up_to_date_valueletnever=(* XXX *)Obj.magic@@C.constNoneletbindef=letstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepeinletcurrent=matchC.valueewithNone->never|Somecurr->fcurrinletcurrent=refcurrentinletupdatestepself=C.updatestepe;matchC.valueewith|None->C.updatestep!current;ifC.(srcs_changede||srcs_changed!current)thenC.set_srcsself(Srcs.union(C.srcse)(C.srcs!current));C.set_instantstepself(C.value!current)|Somecurr->current:=fcurr;C.updatestep!current;C.set_srcsself(Srcs.union(C.srcse)(C.srcs!current));C.set_instantstepself(C.value!current)inletstep=Src.find_active_stepstep(C.srcs!current)inlet()=C.updatestep!currentinletsrcs=Srcs.union(C.srcse)(C.srcs!current)inletinit=C.value!currentinC.create_instant~step~srcsinit~updateletjoinee=bindee(fune->e)letswapes=letstep=Src.find_active_stepStep.nil(C.srcses)inlet()=C.updatestepesinletcurrent=ref(C.valuees)inletupdatestepself=C.updatestepes;beginmatchC.value_changedeswith|false->C.updatestep!current;ifC.(srcs_changedes||srcs_changed!current)thenC.set_srcsself(Srcs.union(C.srcses)(C.srcs!current))|true->current:=C.valuees;C.updatestep!current;C.set_srcsself(Srcs.union(C.srcses)(C.srcs!current));end;C.set_instantstepself(C.value!current)inletstep=Src.find_active_stepstep(C.srcs!current)inlet()=C.updatestep!currentinletsrcs=Srcs.union(C.srcses)(C.srcs!current)inletinit=C.value!currentinC.create_instant~step~srcsinit~updateletmapfe=letmapf=functionNone->None|Somev->Some(fv)inletupdatestepself=C.updatestepe;ifC.srcs_changedethenC.set_srcsself(C.srcse);C.set_instantstepself(mapf(C.valuee))inletstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepeinC.create_instant~step~srcs:(C.srcse)(mapf(C.valuee))~updateletstampev=letstamp=functionNone->None|Some_->Somevinletupdatestepself=C.updatestepe;ifC.srcs_changedethenC.set_srcsself(C.srcse);C.set_instantstepself(stamp(C.valuee))inletstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepeinletinit=stamp(C.valuee)inC.create_instant~step~srcs:(C.srcse)init~updateletfilterfe=letfilterf=function|None->None|Somevasoccwhenfv->occ|Some_->Noneinletupdatestepself=C.updatestepe;ifC.srcs_changedethenC.set_srcsself(C.srcse);C.set_instantstepself(filterf(C.valuee))inletstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepeinletinit=filterf(C.valuee)inC.create_instant~step~srcs:(C.srcse)init~updateletfilter_mapfe=letfilter_mapf=functionNone->None|Somev->fvinletupdatestepself=C.updatestepe;ifC.srcs_changedethenC.set_srcsself(C.srcse);C.set_instantstepself(filter_mapf(C.valuee))inletstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepeinletinit=filter_mapf(C.valuee)inC.create_instant~step~srcs:(C.srcse)init~updateletselectes=letadd_srcsacce=Srcs.unionacc(C.srcse)inletor_srcs_changedacce=acc||C.srcs_changedeinletupdatestepself=List.iter(C.updatestep)es;letsrcs_changed=List.fold_leftor_srcs_changedfalseesinifsrcs_changedthenC.set_srcsself(List.fold_leftadd_srcsSrcs.emptyes);letv=matchList.find(fune->C.valuee<>None)eswith|exceptionNot_found->None|e->C.valueeinC.set_instantstepselfvinletfind_stepstepe=Src.find_active_stepstep(C.srcse)inletstep=List.fold_leftfind_stepStep.nilesinlet()=List.iter(C.updatestep)esinletinit=matchList.find(fune->C.valuee<>None)eswith|exceptionNot_found->None|e->C.valueeinletsrcs=List.fold_leftadd_srcsSrcs.emptyesinC.create_instant~step~srcsinit~updateletaccumacce=letacc=refaccinletaccum=functionNone->None|Somef->acc:=f!acc;Some!accinletupdatestepself=C.updatestepe;ifC.srcs_changedethenC.set_srcsself(C.srcse);C.set_instantstepself(accum(C.valuee))inletstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepeinletinit=accum(C.valuee)inC.create_instant~step~srcs:(C.srcse)init~updateletuntil?(limit=false)~nexte=letnopstepself=()inletupdatestepself=C.(updatestepnext;updatestepe);matchC.valuenextwith|None->ifC.(srcs_changednext||srcs_changede)thenC.set_srcsself(Srcs.union(C.srcsnext)(C.srcse));C.set_instantstepself(C.valuee)|Some_->C.set_srcsselfSrcs.empty;C.set_updateselfnop;C.set_instantstepself(iflimitthenC.valueeelseNone)inletstep=Src.find_active_stepStep.nil(C.srcsnext)inletstep=Src.find_active_stepstep(C.srcse)inlet()=C.(updatestepnext;updatestepe)inmatchC.valuenextwith|None->letsrcs=Srcs.union(C.srcsnext)(C.srcse)inC.create_instant~step~srcs(C.valuee)~update|Some_->letinit=iflimitthenC.valueeelseNoneinC.create_instant~step~srcs:Srcs.emptyinit~update:nopletfollowe~on=(* FIXME rewrite combinators with this style.
FIXME determine why we don't simply call update for init in general *)letdeps_srcseon=Srcs.union(C.srcse)(C.srcson)inletdeps_srcs_changedeon=C.(srcs_changede||srcs_changedon)inletupdate_depsstepeon=C.(updatestepe;updatestepon)inletfolloweon=matchewithSome_asowhenon->o|_->Noneinletupdatestepself=update_depsstepeon;ifdeps_srcs_changedeonthenC.set_srcsself(deps_srcseon);C.set_instantstepself(follow(C.valuee)(C.valueon))inletstep=Src.find_active_stepStep.nil(C.srcse)inletstep=Src.find_active_stepstep(C.srcson)inlet()=update_depsstepeoninletinit=follow(C.valuee)(C.valueon)inC.create_instant~step~srcs:(deps_srcseon)init~updateletdefere=C.deferNoneeletfixef=C.fixNoneefmoduleOption=structleton_somee=filter_map(funx->x)eletsomee=map(funv->Somev)eletvaluee~default=letupdatestepself=C.updatestepe;ifC.srcs_changedethenC.set_srcsself(C.srcse);letocc=matchC.valueewith|None->None|Some(Some_asv)->v|SomeNone->C.updatestepdefault;Some(C.valuedefault)inC.set_instantstepselfoccinletstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepe;C.updatestepdefaultinletinit=matchC.valueewith|None->None|Some(Some_asv)->v|SomeNone->Some(C.valuedefault)inC.create_instant~step~srcs:(C.srcse)init~updateletgete=map(functionSomev->v|None->invalid_arg"option is None")eletbindef=map(functionNone->None|Somev->fv)eletjoine=map(functionSome(Some_aso)->o|_->None)eletis_nonee=map(functionNone->true|Some_->false)eletis_somee=map(functionNone->false|Some_->true)eletmapfe=map(functionNone->None|Somev->Some(fv))eendmodulePair=structletfste=mapfsteletsnde=mapsndeletve0e1=letupdatestepself=C.(updatestepe0;updatestepe1);ifC.(srcs_changede0||srcs_changede1)thenC.set_srcsself(Srcs.union(C.srcse0)(C.srcse1));letocc=matchC.valuee0,C.valuee1with|Somev0,Somev1->Some(v0,v1)|_->NoneinC.set_instantstepselfoccinletstep=Src.find_active_stepStep.nil(C.srcse0)inletstep=Src.find_active_stepstep(C.srcse1)inletsrcs=Srcs.union(C.srcse0)(C.srcse1)inletinit=matchC.valuee0,C.valuee1with|Somev0,Somev1->Some(v0,v1)|_->NoneinC.create_instant~step~srcsinit~updateendletdump_src_ids=C.dump_src_idsendmoduleS=structtype'at='asignaltype'aset=?step:Step.t->'a->unitletlog=Logr.for_cellletobs=Logr.obs_cellleteq=C.eqletwith_eq=C.with_eqletcreate?eqv=letsrc=Src.create?eqvinletset?stepv=letstep,exec=matchstepwith|None->Step.create(),true|Somestep->step,falseinletcell=Src.cellsrcinifC.src_updatestepcellvthenStep.add_srcstep(Src.untypedsrc);ifexecthenStep.executestepinSrc.cellsrc,setletvalue=C.up_to_date_valueletrough_value=C.valueletconst=C.constletbindvf=letstep=Src.find_active_stepStep.nil(C.srcsv)inlet()=C.updatestepvinletcurrent=ref(f(C.valuev))inletupdatestepself=C.updatestepv;matchC.value_changedvwith|false->C.updatestep!current;ifC.(srcs_changedv||srcs_changed!current)thenC.set_srcsself(Srcs.union(C.srcsv)(C.srcs!current));ifC.value_changed!currentthenC.set_valueself(C.value!current)|true->current:=f(C.valuev);C.updatestep!current;C.set_eqself(C.eq!current);C.set_srcsself(Srcs.union(C.srcsv)(C.srcs!current));C.set_valueself(C.value!current)inletstep=Src.find_active_stepstep(C.srcs!current)inlet()=C.updatestep!currentinletsrcs=Srcs.union(C.srcsv)(C.srcs!current)inletinit=C.value!currentinC.create~eq:(C.eq!current)~step~srcsinit~updatelethold?eqie=letupdatestepself=C.updatestepe;ifC.(srcs_changede)thenC.set_srcsself(C.srcse);matchC.valueewith|None->()|Somev->C.set_valueselfvinletstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepeinletinit=matchC.valueewithNone->i|Somev->vinC.create?eq~step~srcs:(C.srcse)init~updateletjoinss=bindss(funs->s)letswapsse=join(hold~eq:(==)sse)letchangess=letupdatestepself=C.updatesteps;ifC.srcs_changedsthenC.set_srcsself(C.srcss);ifC.value_changedsthenC.set_instantstepself(Some(C.values))inletstep=Src.find_active_stepStep.nil(C.srcss)inlet()=C.updatestepsin(* NB: 0 - dt doesn't exist so this is always None *)C.create_instant~step~srcs:(C.srcss)None~updateletsamples~onf=letupdatestepself=C.(updatestepon;updatesteps);ifC.(srcs_changedon||srcs_changeds)thenC.set_srcsself(Srcs.union(C.srcss)(C.srcson));matchC.valueonwith|None->()|Somev->C.set_instantstepself(Some(f(C.values)v))inletstep=Src.find_active_stepStep.nil(C.srcss)inletstep=Src.find_active_stepstep(C.srcson)inlet()=C.(updatestepon;updatesteps)inletsrcs=Srcs.union(C.srcss)(C.srcson)inletinit=matchC.valueonwith|None->None|Somev->Some(f(C.values)v)inC.create_instant~step~srcsinit~updateletsample_filters~onf=E.Option.on_some(samples~onf)letsnapshots~on=samples~on(funv_->v)letmap?eqfv=letupdatestepself=C.updatestepv;ifC.srcs_changedvthenC.set_srcsself(C.srcsv);ifC.value_changedvthenC.set_valueself(f(C.valuev))inletstep=Src.find_active_stepStep.nil(C.srcsv)inlet()=C.updatestepvinC.create?eq~step~srcs:(C.srcsv)(f(C.valuev))~updateletapp?eqfv=letupdatestepself=C.(updatestepf;updatestepv);ifC.(srcs_changedf||srcs_changedv)thenC.set_srcsself(Srcs.union(C.srcsf)(C.srcsv));ifC.(value_changedf||value_changedv)thenC.set_valueself((C.valuef)(C.valuev))inletstep=Src.find_active_stepStep.nil(C.srcsf)inletstep=Src.find_active_stepstep(C.srcsv)inlet()=C.updatestepf;C.updatestepvinletsrcs=Srcs.union(C.srcsf)(C.srcsv)inletinit=(C.valuef)(C.valuev)inC.create?eq~step~srcsinit~updateletaccum?eqie=hold?eqi(E.accumie)letuntil?(limit=false)?init~nexts=letnopstepself=()inletupdatestepself=C.(updatestepnext;updatesteps);matchC.valuenextwith|None->ifC.(srcs_changednext||srcs_changeds)thenC.set_srcsself(Srcs.union(C.srcsnext)(C.srcss));C.set_valueself(C.values)|Some_->C.set_srcsselfSrcs.empty;C.set_updateselfnop;iflimitthenC.set_valueself(C.values)else()inletstep=Src.find_active_stepStep.nil(C.srcsnext)inletstep=Src.find_active_stepstep(C.srcss)inlet()=C.(updatestepnext;updatesteps)inmatchC.valuenextwith|None->letsrcs=Srcs.union(C.srcsnext)(C.srcss)inC.create~eq:(eqs)~step~srcs(C.values)~update|Some_->letinit=matchinitwithNone->C.values|Somei->iinC.create~eq:(eqs)~step~srcs:Srcs.emptyinit~update:nopletfollow?inits~on=letdeps_srcsson=Srcs.union(C.srcss)(C.srcson)inletdeps_srcs_changedson=C.(srcs_changeds||srcs_changedon)inletupdate_depsstepson=C.(updatesteps;updatestepon)inletupdatestepself=update_depsstepson;ifdeps_srcs_changedsonthenC.set_srcsself(deps_srcsson);ifC.valueonthenC.set_valueself(C.values)inletstep=Src.find_active_stepStep.nil(C.srcss)inletstep=Src.find_active_stepstep(C.srcson)inlet()=update_depsstepsoninletinit=matchinitwithNone->(C.values)|Somei->iinC.create~eq:(eqs)~step~srcs:(deps_srcsson)init~updateletdelay=C.delayletdefer?inits=letinit=matchinitwith|Someinit->init|None->letstep=Src.find_active_stepStep.nil(C.srcss)inlet()=C.updatestepsinC.valuesinC.deferinitsletfix=C.fixletl1?eqfx=map?eqfxletl2?eqfxy=letupdatestepself=C.(updatestepx;updatestepy);ifC.(srcs_changedx||srcs_changedy)thenC.set_srcsself(Srcs.union(C.srcsx)(C.srcsy));ifC.(value_changedx||value_changedy)thenC.set_valueself(f(C.valuex)(C.valuey))inletstep=Src.find_active_stepStep.nil(C.srcsx)inletstep=Src.find_active_stepstep(C.srcsy)inlet()=C.(updatestepx;updatestepy)inletsrcs=Srcs.union(C.srcsx)(C.srcsy)inletinit=f(C.valuex)(C.valuey)inC.create?eq~step~srcsinit~updateletl3?eqfxyz=letsrcs_unionxyz=Srcs.union(C.srcsx)(Srcs.union(C.srcsy)(C.srcsz))inletupdatestepself=C.(updatestepx;updatestepy;updatestepz);ifC.(srcs_changedx||srcs_changedy||srcs_changedz)thenC.set_srcsself(srcs_unionxyz);ifC.(value_changedx||value_changedy||value_changedz)thenC.set_valueself(f(C.valuex)(C.valuey)(C.valuez))inletstep=Src.find_active_stepStep.nil(C.srcsx)inletstep=Src.find_active_stepstep(C.srcsy)inletstep=Src.find_active_stepstep(C.srcsz)inlet()=C.(updatestepx;updatestepy;updatestepz)inletsrcs=srcs_unionxyzinletinit=f(C.valuex)(C.valuey)(C.valuez)inC.create?eq~step~srcsinit~updatemoduleBool=structleteq:bool->bool->bool=(=)letfalse'=constfalselettrue'=consttrueletnots=map~eqnotslet(&&)=l2(&&)let(||)=l2(||)letedges=changessletedge_detectedges=letupdatestepself=C.updatesteps;ifC.srcs_changedsthenC.set_srcsself(C.srcss);ifStdlib.(&&)(C.value_changeds)(C.values=edge)thenC.set_instantstepself(Some())inletstep=Src.find_active_stepStep.nil(C.srcss)inlet()=C.updatestepsinC.create_instant~step~srcs:(C.srcss)None~updateletrises=edge_detecttruesletfalls=edge_detectfalsesletflip~inite=letupdatestepself=C.updatestepe;ifC.srcs_changedethenC.set_srcsself(C.srcse);matchC.valueewith|None->()|Some_->C.set_valueself(Stdlib.not(C.valueself))inletstep=Src.find_active_stepStep.nil(C.srcse)inlet()=C.updatestepeinletinit=matchC.valueewith|Some_->Stdlib.notinit|None->initinC.create~eq~step~srcs:(C.srcse)init~updateendmoduleOption=structlet_eqeq=funv0v1->matchv0,v1with|Somev0,Somev1->eqv0v1|None,None->true|_,_->falseletnone=(* XXX *)Obj.magic@@(constNone)letsomes=map~eq:(_eq(eqs))(funv->Somev)slethold_valueis=letupdatestepself=C.updatesteps;if(C.srcs_changeds)thenC.set_srcsself(C.srcss);matchC.valueswithNone->()|Somev->C.set_valueselfvinleteqvv'=C.eqs(Somev)(Somev')inletstep=Src.find_active_stepStep.nil(C.srcss)inlet()=C.updatestepsinletinit=matchC.valueswithNone->i|Somev->vinC.create~eq~step~srcs:(C.srcss)init~updateletvalues~default=letupdatestepself=C.updatestepdefault;C.updatesteps;ifC.(srcs_changeddefault||C.srcs_changeds)thenC.set_srcsself(Srcs.union(C.srcsdefault)(C.srcss));if(C.value_changeddefault||C.value_changeds)thenmatchC.valueswith|None->C.set_valueself(C.valuedefault)|Somev->C.set_valueselfvinletstep=Src.find_active_stepStep.nil(C.srcsdefault)inletstep=Src.find_active_stepstep(C.srcss)inlet()=C.(updatestepdefault;updatesteps)inletinit=matchC.valueswithNone->C.valuedefault|Somev->vinletsrcs=Srcs.union(C.srcsdefault)(C.srcss)inC.create~eq:(eqdefault)~step~srcsinit~updateletget?eqs=map?eq(functionSomev->v|None->invalid_arg"option is None")sletbind?eqsf=map?eq(functionNone->None|Somev->fv)sletjoin?eqs=map?eq(functionSome(Some_aso)->o|_->None)sletis_nones=map~eq:Bool.eq(functionNone->true|Some_->false)sletis_somes=map~eq:Bool.eq(functionNone->false|Some_->true)sletmap?eqfs=map?eq(functionNone->None|Somev->Some(fv))sleteq=_eqendmodulePair=structletfst?eqs=map?eqfstsletsnd?eqs=map?eqsndsletvs0s1=l2(funxy->(x,y))s0s1endletdump_src_ids=C.dump_src_idsend