(* TML5 -- generated on vendredi 24 juillet 2009, 19:25:00 (UTC+0200) from /home/deleuzec/Rech/TML/Doc/tml_impl.tex *)


(* insert bfoncteur *)


module type SVAL_TYPE = sig type t end

module Gen_TML = functor(SV:SVAL_TYPE) ->
  struct
    type sval_t = SV.t
(* end  bfoncteur *)

type process = unit -> coop
and coop = 
  | Done 
  | Next
  | Pause   of process
  | Wait    of signal_t * awproc
  | Wait_im of signal_t * awproc
  | Present of signal_t * process * process
        
and awproc = 
  | No  of (unit -> coop)
  | One of (sval_t -> coop)
  | All of (sval_t list -> coop)
        
and signal_t = {
    mutable last_emit : int;
    mutable prev_emit : int;
    mutable value : sval_t list;
    mutable prev_value : sval_t list;
    mutable used : bool;
    gather : (sval_t list -> sval_t list);
    
    mutable await : (ctxt * awproc) list;
    mutable await_im : (ctxt * awproc) list;
    mutable present : (ctxt * process * process) list
  }
      
and ctxt =
    Free
  | Until of signal_t * process
  | Untilv of signal_t * (sval_t list -> coop) * process
  | Control of signal_t * process
  | When of signal_t * awproc

(* insert def2 *)


let instant = ref 1

let runq   = ref []
and pauseq = ref []

let run f = f ()
let term () = Done
let pause p = Pause p

let put_in_runq p = runq := p :: !runq
(* end  def2 *)

  let put_in_await_im s p =
    s.await_im <- p :: s.await_im

(* insert signal *)


let signal () =
  { last_emit = -1; prev_emit = -1; value = []; prev_value = [];
    used = false; gather = (fun x -> x); await = []; await_im = [];
    present = [] 
  }

let signalc g =
  { last_emit = -1; prev_emit = -1; value = []; prev_value = [];
    used = false; gather = g; await = []; await_im = [];
    present = [] 
  }
(* end  signal *)

(* insert used *)


let used_signals = ref ([]:signal_t list)

let signal_is_used s =
  if not s.used then begin
    s.used <- true;
    used_signals := s :: !used_signals
  end
(* end  used *)

(* insert await4 *)


let ispst = fun s -> s.last_emit = !instant

let await s p = Wait(s, All p)

let await_one s p = Wait(s, One p)

let await_immediate s p =
  if ispst s then p () else Wait_im(s, No p)
          
let await_immediate_one s p =
  if ispst s then p (List.hd s.value) else Wait_im(s, One p)

let present s p1 p2 =
  if ispst s then p1 () else Present(s,p1,p2)

let pre s = s.prev_emit = !instant - 1 || s.last_emit = !instant - 1

let prev s = if s.last_emit = !instant then s.prev_value else s.value
(* end  await4 *)

let emit s v =
  if s.last_emit <> !instant then begin
    s.prev_emit <- s.last_emit;
    s.last_emit <- !instant;
    s.prev_value <- s.value;
    s.value <- [];
    signal_is_used s
  end;
  s.value <- v :: s.value;
  List.iter 
    (fun (c,awp) -> match awp with
    | No p -> put_in_runq (c, p)
    | One p -> put_in_runq (c, fun () -> p v))
    s.await_im;
  s.await_im <- [];
  List.iter (fun (c,p1,p2) -> put_in_runq (c,p1)) s.present;
  s.present <- []

let dountil s e k =
  put_in_runq (Until(s,k), e); Next

let dountilv s e e2 k =
  put_in_runq (Untilv(s,e2,k), e); Next

let controlwith s e k =
  put_in_runq (Control(s,k), e); Next

let dowhen s e k =
  if s.last_emit = !instant then put_in_runq (When(s,No k), e)
  else put_in_await_im s (When(s,No k), No e);
  Next

let pause2   = ref []  (* pour les proc. suspensibles et désactivables *)
let unactive = ref []  (* pour les proc. désactivés *)
        
let current_context = ref Free

let put_in_unact p = unactive := p :: !unactive

let ispst = fun s -> s.last_emit = !instant

let next_instant_unactive_pause2 () = 
  
  unactive := List.filter
      (fun (Control(s',k) as c,p) ->
        if ispst s' then (put_in_runq (c,p); false)
        else true)
      !unactive;
    
  List.iter
    (fun (c,p) -> match c with
    | Until(s',k) -> put_in_runq
          (if ispst s' then (Free, k) else (c, p))
          
    | Untilv(s',e2,k) ->
        put_in_runq
          (if ispst s' 
          then (Free, fun () -> e2 s'.value; k())
          else (c, p))
          
    | Control(s',k) ->
        (if ispst s' then put_in_unact else put_in_runq) (c,p)
    )
    !pause2;
  pause2 := []

let do_await_queue_absent s  =
  let new_list, used = List.fold_left
      (fun (acc,used) (c,qp) -> match c with
      | Free -> (Free, qp)::acc, used
                                  
      | When(s',k) -> 
          let next = match qp with
          | One p -> fun () -> await_one s p
          | All p -> fun () -> await s p
          in
          put_in_await_im s' (c, No next); acc, used
                
      | Until(s',k) -> 
          if ispst s' then (put_in_runq (Free, k); acc, used)
          else (c, qp)::acc, true
                              
      | Untilv(s',e2,k) -> 
          if ispst s' then 
            (put_in_runq (Free, fun () -> e2 s'.value; k()); acc, used)
          else 
            (c, qp)::acc, true
                           
      | Control(s',k) ->
          let next = match qp with
          | One p -> fun () -> await_one s p
          | All p -> fun () -> await s p
          in
          if ispst s' then (put_in_unact (c, next); acc, used)
          else (c, qp)::acc, true
      )
      
      ([], false)
      s.await
  in s.await <- new_list;
  used

let do_await_im_queue_absent s  =
  let new_list, used = List.fold_left
      (fun (acc,used) (c,qp) -> match c with
      | Free -> (Free, qp)::acc, used
                                  
      | When(s',k) -> 
          let next = match qp with
          | One p -> fun () -> await_immediate_one s p
          | No p -> fun () -> await_immediate s p
          in
          put_in_await_im s' (c, No next); acc, used
                
      | Until(s',k) -> 
          if ispst s' then (put_in_runq (Free, k); acc, used)
          else (c, qp)::acc, true
                              
      | Untilv(s',e2,k) -> 
          if ispst s' then 
            (put_in_runq (Free, fun () -> e2 s'.value; k()); acc, used)
          else 
            (c, qp)::acc, true
                           
      | Control(s',k) ->
          let next = match qp with
          | One p -> fun () -> await_immediate_one s p
          | No p -> fun () -> await_immediate s p
          in
          if ispst s' then (put_in_unact (c, next); acc, used)
          else (c, qp)::acc, true
      )
      ([], false)
      s.await_im
  in s.await_im <- new_list; used

  let do_await_queue_present s v ov = 
    List.iter 
      (fun (c, qp) -> 
        let next = match qp with
        | One p -> fun () -> p ov
        | All p -> fun () -> p v
        in 
        match c with
      | Free -> put_in_runq (Free, next)
            
      | When(s',k) -> put_in_await_im s' (c, No next)
            
      | Until(s',k) -> put_in_runq
            (if ispst s' then (Free, k) else (c, next))
            
      | Untilv(s',e2,k) ->
            put_in_runq
            (if ispst s' 
            then (Free, fun () -> e2 s'.value; k())
            else (c,    next))
            
      | Control(s',k) ->
          (if ispst s' then put_in_unact else put_in_runq)
            (c, next)
      )
      s.await;
      s.await <- []

  let do_present_queue_absent s =
    List.iter 
      (fun (c, p1, p2) -> match c with
      | Free -> put_in_runq (Free, p2)

      | When(s',k) -> put_in_runq (c, p2)
            
      | Until(s',k) -> put_in_runq (if ispst s' then (Free, k) else (c, p2))
            
      | Untilv(s',e2, k) ->
          put_in_runq
            (if ispst s'
              then (Free, fun () -> e2 s.value; k())
            else (c, p2))
            
      | Control(s',k) ->
          (if ispst s' then put_in_unact else put_in_runq) (c, p2)
      )
      s.present;
    s.present <- []

let next_instant () =
  runq:=!pauseq; pauseq:=[];
  next_instant_unactive_pause2 ();
  
  let new_used = List.filter
      (fun s -> 
        let keep = 
          if ispst s then                 (* s présent *)
            let v  = s.gather s.value in
            let ov = List.hd s.value
            in
            do_await_queue_present s v ov;
            false
          else begin                                (* s absent *)
            do_present_queue_absent s;
            let u1 = do_await_queue_absent s in
            let u2 = do_await_im_queue_absent s
            in u1 or u2
          end
        in
        if not keep then s.used <- false;
        keep)
      !used_signals
  in
  incr instant;
  used_signals := new_used

let until_or_ctrl c =
  match c with
  | Until _
  | Untilv _
  | Control _ -> true
  | _ -> false

let rec sched () =
  match !runq with
  | [] -> 
      next_instant();
      if !runq=[] then () else sched()
          
  | (c,p)::t -> begin runq := t; current_context := c; match p() with

    | Next -> sched ()

    | Done -> begin match c with
      | Free -> sched ()
      | Until(s,k)
      | Untilv(s,_,k)
      | When(s, No k)
      | Control(s,k)  -> put_in_runq (Free,k); sched ()
    end

    | Pause p -> begin match c with
      | Free      -> pauseq := (c,p) :: !pauseq; sched ()
      | When(s,_) -> s.await_im <- (c,No(fun _ -> p ()))::s.await_im; sched ()
      | Until _   
      | Untilv _  
      | Control _ -> pause2 := (c,p) :: !pause2; sched ()
    end
            
    | Wait(s,p) -> 
        s.await <- (c,p) :: s.await;
        if until_or_ctrl c then signal_is_used s;
        sched ()

    | Wait_im(s,p) ->
        s.await_im <- (c,p) :: s.await_im;
        if until_or_ctrl c then signal_is_used s;
        sched ()

    | Present(s, p1, p2) ->
        s.present <- (c,p1,p2) :: s.present;
        signal_is_used s;
        sched ()
  end

let spawn = fun p -> runq := (!current_context,p) :: !runq

let start pl =
  runq := List.map (fun p -> Free,p) pl;
  sched ()  

(* insert par *)


let par_help k1 k2 k3 =
  let you_re_last = ref false in
  let test _ = 
    if !you_re_last then k3 () else begin
        you_re_last := true;
        term()
      end
  in
  (fun () -> k1 test),
  (fun () -> k2 test)
    
let par p1 p2 k =
  let k1, k2 = par_help p1 p2 k
  in
  spawn k1;
  k2 ()
let tail_par p1 p2 =
  spawn p1;
  p2 ()
let tail_parn (p::ps) =
  List.iter spawn ps;
  p ()

let parn (p::ps) k =
  let cpt = ref (List.length ps) in
  let pk::pks = List.map
            (fun p -> 
              fun () -> p
                  (fun () -> if !cpt=0 then k () else 
                  begin decr cpt; term() end)
                  ())
            (p::ps)
  in
  List.iter spawn pks;
  pk ()
let fordopar e1 e2 pi k =
  let cpt = ref (e2-e1+1) in
  let finish () = decr cpt; if !cpt = 0 then k () else term()
  in
  for i=e1 to e2 do
    spawn (fun () -> pi i finish)
  done;
  term ()
  
let tail_fordopar e1 e2 pi =
  for i=e1 to e2 do
    spawn (fun () -> pi i)
  done;
  term ()
let letand_help p1 p2 k =
  let r1 = ref None
  and r2 = ref None
  in
  p1 
    (fun r -> match !r2 with
    | None -> r1 := Some r; term()
    | Some v2 -> k (r, v2)),
  p2
    (fun r -> match !r1 with
    | None -> r2 := Some r; term()
    | Some v1 -> k (v1, r))

let letand p1 p2 k =
  let k1, k2 = letand_help p1 p2 k
  in
  spawn k1;
  k2 ()
(* end  par *)

(* insert efoncteur *)


  end
(* end  efoncteur *)


This document was generated using caml2html