@@ -30,23 +30,22 @@ Section VM.
3030 Let World := @h_state _ _ IOH.
3131
3232 CoInductive Program (Mailbox : Set ) : Type :=
33- | p_dead : (* Program terminted *)
33+ | die : (* Program termintes *)
3434 Program Mailbox
3535 | p_yield :
36- (* Interrupt the computation without producing any side effects.
37- This primitive is used to softly introduce the concept of
38- Erlang's "reductions", and to side-step termination checker,
39- making programs non-Turing in a practically useful, as opposed
40- to forced, way.
41-
42- In Erlang, reduction counting improves responsiveness of the
43- system, in SLOT it *additionally* gives a structural argument
44- "for free". *)
45- forall {CTX : Type }
46- (ctx : CTX)
47- (continuation : CTX -> Program Mailbox),
48- Program Mailbox
49- | p_cont : (* Program is doing I/O *)
36+ (** Interrupt the computation without producing any side effects.
37+
38+ This primitive is used to softly introduce the concept of
39+ Erlang's "reductions", and to side-step termination checker,
40+ making programs non-Turing in a practically useful, as opposed
41+ to forced, way.
42+
43+ In Erlang, reduction counting improves responsiveness of the
44+ system, in SLOT it *additionally* gives a structural argument
45+ "for free". *)
46+ forall (continuation : Program Mailbox),
47+ Program Mailbox
48+ | p_io : (* Program is doing I/O *)
5049 forall (pending_req : Request)
5150 (continuation : Reply pending_req -> Program Mailbox),
5251 Program Mailbox
@@ -57,34 +56,35 @@ Section VM.
5756 Program Mailbox.
5857
5958 Record Process :=
60- { proc_mb_t : Set ;
61- proc_prog : @Program proc_mb_t;
62- }.
59+ mkProcess
60+ { pid : PID;
61+ proc_mb_t : Set ;
62+ cont : @Program proc_mb_t;
63+ }.
64+
65+ #[export] Instance etaProc : Settable _ := settable! mkProcess <pid; proc_mb_t; cont>.
6366
6467 Record VM :=
6568 mkVM
6669 { (* State of the I/O handler *)
6770 world : World;
6871 (* Set of runnable processes *)
69- runq : list (PID * Process);
70- (* Set of sleeping processes *)
71- sleepq : list (PID * Process);
72+ runq : list Process;
7273 (* Counter that gets incremented when process spawns a child.
7374 This counter is used as a suffix of the child's pid *)
7475 child_ctr : Pid.FMap.t positive;
7576 }.
7677
77- #[export] Instance etaX : Settable _ := settable! mkVM <world; runq; sleepq ; child_ctr>.
78+ #[export] Instance etaVM : Settable _ := settable! mkVM <world; runq; child_ctr>.
7879
79- Program Definition vm_setoid : Setoid VM :=
80+ Global Program Definition vm_setoid : Setoid VM :=
8081 {| equiv a b :=
81- let (w1, rq1, sq1, cc1) := a in
82- let (w2, rq2, sq2, cc2) := b in
82+ let (w1, rq1, cc1) := a in
83+ let (w2, rq2, cc2) := b in
8384 let w_eq := @equiv _ h_setoid in
8485 let p_eq := @equiv _ (setoid_permutation _) in
8586 w_eq w1 w2 /\
8687 p_eq rq1 rq2 /\
87- p_eq sq1 sq2 /\
8888 @equiv _ (eq_setoid _) cc1 cc2;
8989 |}.
9090 Next Obligation .
@@ -103,38 +103,118 @@ Section VM.
103103 end in
104104 (v<| child_ctr := cc |>, ctr).
105105
106- Definition do_spawn {Mailbox : Set } (parent : PID) (prog : @Program Mailbox) (v : VM) : VM :=
106+ Definition do_spawn {Mailbox : Set } (parent : PID) (prog : @Program Mailbox) (v : VM) : (PID * VM) :=
107107 let (v, child_pid_suffix) := new_child_id parent v in
108108 let rq := runq v in
109109 let new_pid := parent ++ [child_pid_suffix] in
110- let new_process := {| proc_mb_t := Mailbox; proc_prog := prog |} in
110+ let new_process := {|
111+ pid := new_pid;
112+ proc_mb_t := Mailbox;
113+ cont := prog
114+ |} in
111115 let w' := h_spawn new_pid Mailbox (world v) in
112- v<| runq := (new_pid, new_process) :: rq|> <|world := w'|>.
116+ (new_pid, v<| runq := new_process :: rq|> <|world := w'|>) .
113117
114118 Definition initVm {Mailbox : Set } (w : World) (p : @Program Mailbox) :=
115119 let vm :=
116120 {|
117121 world := w;
118122 runq := [];
119- sleepq := [];
120123 child_ctr := Pid.FMap.empty _;
121124 |} in
122- do_spawn [] p vm.
125+ let (_, vm) := do_spawn [] p vm in
126+ vm.
127+
128+ Definition vmte_canon_rel (a b : Process) :=
129+ (* Order of events is canonical when pid a =< pid b: *)
130+ match PIDOrd.compare_ (pid a) (pid b) with
131+ | Gt => False
132+ | _ => True
133+ end .
134+
135+ Lemma vmte_canon_rel_dec a b : Decidable.decidable (vmte_canon_rel a b).
136+ Proof .
137+ unfold Decidable.decidable, vmte_canon_rel.
138+ sauto.
139+ Qed .
140+
141+ Lemma vmte_canon_rel_total a b : vmte_canon_rel a b \/ vmte_canon_rel b a.
142+ Proof .
143+ unfold Decidable.decidable, vmte_canon_rel.
144+ sauto use:PIDOrd.compare_asymm.
145+ Qed .
146+
147+ Global Instance vmevCanonOrder : CanonicalOrder vmte_canon_rel :=
148+ { canon_rel_dec := vmte_canon_rel_dec;
149+ canon_rel_total := vmte_canon_rel_total;
150+ }.
151+
152+ Definition exec_proc (proc : Process) (vm vm' : VM) : Prop :=
153+ match proc with
154+ {| pid := pid; proc_mb_t := mb_t; cont := prog |} =>
155+ match prog with
156+ | die _ =>
157+ vm' = vm <| world := h_terminate pid (world vm) |>
158+ | p_yield _ next =>
159+ let proc := {| pid := pid; proc_mb_t := mb_t; cont := next |} in
160+ vm' = vm <| runq := proc :: (runq vm) |>
161+ | p_io _ req next =>
162+ exists w' io_reply,
163+ let proc := {| pid := pid; proc_mb_t := mb_t; cont := next io_reply |} in
164+ morphism (h_handler pid req) (world vm) (io_reply, w') /\
165+ vm' = vm <| runq := proc :: (runq vm) |> <| world := w' |>
166+ | @p_spawn _ child_mb_t child_prog next =>
167+ let (child_pid, vm) := do_spawn pid child_prog vm in
168+ let addr := mkAddress child_mb_t child_pid in
169+ let proc := {| pid := pid; proc_mb_t := mb_t; cont := next addr |} in
170+ vm' = vm <| runq := proc :: (runq vm) |>
171+ end
172+ end .
173+
174+ Program Definition vm_state_trans : MFun VM (@ts_ret VM Process) :=
175+ {|
176+ morphism vm ret :=
177+ match runq vm, ret with
178+ | [], None =>
179+ (* No runnable processes: *)
180+ True
181+ | rq, Some (te, vm') =>
182+ exists proc rq',
183+ Pick rq proc rq' /\ exec_proc proc (vm <|runq := rq'|>) vm'
184+ | _, _ =>
185+ False
186+ end
187+ |}.
188+ Next Obligation .
189+ sauto.
190+ Qed .
191+ Next Obligation .
192+ destruct x' as [w rq sq cctr].
193+ destruct rq as [|firstproc rq_].
194+ - exists None. sauto.
195+ - simpl in *.
196+ destruct y as [[te vm']|].
197+ + destruct H0 as [proc [rq' [Hrq' Hexec]]].
198+ destruct proc as [pid mb_t prog].
199+ destruct prog.
200+ * simpl in Hexec.
201+ Admitted .
202+
203+ Global Instance vmTS : @TransitionSystem VM Process :=
204+ { ts_state_trans := vm_state_trans;
205+ }.
123206End VM.
124207
125208Global Arguments VM {_ _} _.
126- Global Arguments p_dead {_ _ _}.
209+ Global Arguments die {_ _ _}.
127210Global Arguments p_yield {_ _ _}.
128- Global Arguments p_cont {_ _ _}.
211+ Global Arguments p_io {_ _ _}.
129212Global Arguments p_spawn {_ _ _ _}.
130213
131214(* begin details *)
132- Notation "'do' V '<-' I ; C" := (p_cont (I) (fun V => C))
215+ Notation "'do' V '<-' I ; C" := (p_io (I) (fun V => C))
133216 (at level 100, C at next level, V name, right associativity) : slot_scope.
134217
135- Notation "'done'" := (p_cont (fun _ => p_dead))
136- (at level 100, right associativity) : slot_scope.
137-
138218Notation "'call' V '<-' I ; C" := (I (fun V => C))
139219 (at level 100, C at next level, V ident,
140220 right associativity) : slot_scope.
@@ -143,9 +223,8 @@ Notation "'spawn' V '<-' I ; C" := (p_spawn (I) (fun V => C))
143223 (at level 100, C at next level, V ident,
144224 right associativity) : slot_scope.
145225
146- Notation "P '!' M ; C" := (p_cont (send P (appmsg M)) (fun _ => C))
226+ Notation "P '!' M ; C" := (p_io (send P (appmsg M)) (fun _ => C))
147227 (at level 99, C at next level, right associativity) : slot_scope.
148-
149228(* end details *)
150229
151230Definition prog_t `(IOHandler) mb_t :=
@@ -155,14 +234,21 @@ Section test.
155234 Let h := mailboxHandler.
156235 Let VM := VM h.
157236
158- Let child1 : prog_t h positive := p_dead .
237+ Let child1 : prog_t h positive := die .
159238
160- Let child2 : prog_t h bool := p_dead .
239+ Let child2 : prog_t h bool := die .
161240
162241 Let prog : prog_t h True :=
163242 spawn c1 <- child1;
164243 c1 ! 1;
165244 spawn c2 <- child2;
166245 c2 ! false;
167- p_dead.
246+ die.
247+
248+ Fail Let prog' : prog_t h True :=
249+ spawn c1 <- child1;
250+ c1 ! 1;
251+ spawn c2 <- child2;
252+ c2 ! 1;
253+ die.
168254End test.
0 commit comments