Skip to content
Snippets Groups Projects
  • Erwan Jahier's avatar
    d7905aff
    Split expressions into atomic expressions. In other words, introduce · d7905aff
    Erwan Jahier authored
    as many  new local  variables as necessary  so that an  expression is
    made at most of one operator.
    
    The rational  for that  is to obtain  a lic  code that is  trivial to
    clock check (nested node calls, for example, make it less simple).
    
    The old behavior can still be obtained using --keep-nested-calls.
    
    During  that  change,   I  realised  that  I  did   not  clock  check
    asserts. Hence, I have also added this check.
    d7905aff
    History
    Split expressions into atomic expressions. In other words, introduce
    Erwan Jahier authored
    as many  new local  variables as necessary  so that an  expression is
    made at most of one operator.
    
    The rational  for that  is to obtain  a lic  code that is  trivial to
    clock check (nested node calls, for example, make it less simple).
    
    The old behavior can still be obtained using --keep-nested-calls.
    
    During  that  change,   I  realised  that  I  did   not  clock  check
    asserts. Hence, I have also added this check.
unifyClock.ml 3.17 KiB
(** Time-stamp: <modified the 19/08/2008 (at 09:26) by Erwan Jahier> *)


open SyntaxTree
open SyntaxTreeCore
open CompiledData
open LicDump
open Printf
open Lxm
open Errors


let ci2str = LicDump.string_of_clock2

(* exported *)
type subst = (Ident.t * Ident.t) list  * (int * clock_eff) list

(* exported *)
let (empty_subst:subst) = [],[]

(******************************************************************************)
(* Stuff to generate fresh clock vars *)

let var_type = ref 0
let reset_var_type () = var_type := 0

let (get_var_type : unit -> int) = 
  fun () -> incr var_type; !var_type


(* exported *)
let (get_constant_clock : unit -> clock_eff) =
  fun () -> ClockVar (get_var_type ())

(******************************************************************************)

let subst_to_string (s1,s2) =
  let v2s v = Ident.to_string v in
    (String.concat ", " (List.map (fun (v1,v2) -> (v2s v1) ^ "/" ^ (v2s v2)) s1)) ^
      " + " ^
      (String.concat ", " (List.map (fun (v1,v2) -> (string_of_int v1) ^ "/" ^ 
				       (ci2str v2)) s2))
      
(* exported *)
let rec (apply_subst:subst -> clock_eff -> clock_eff) =
  fun (s1,s2) c -> 
    match c with
      | BaseEff -> BaseEff 
      | On(v,clk) -> 
	  let v = try List.assoc v s1 with Not_found -> v in
	    On(v, apply_subst (s1,s2) clk)
      | ClockVar i -> 
	  try apply_subst (s1,s2) (List.assoc i s2) 
	  with Not_found -> c 
	    
(* exported *)
let (f : Lxm.t -> subst -> clock_eff -> clock_eff -> subst) =
  fun lxm (s1,s2) ci1 ci2 -> 
    let ci1 = apply_subst (s1,s2) ci1 in
    let ci2 = apply_subst (s1,s2) ci2 in
    let rec aux (s1,s2) arg = match arg with
	| On(v,clk), BaseEff
	| BaseEff, On(v,clk) -> (s1,s2)
	    (* not unifiable: we stop trying to find a substitution and return s;
	       the error message will be issued outside [aux].
	    *)
	| BaseEff, BaseEff -> (s1,s2) (* ok *)
	| On(v1,clk1), On(v2,clk2) ->
	    let s1 = if v1 = v2 then s1 else ((v2,v1)::s1) in
	      aux (s1,s2) (clk1, clk2)
	| ClockVar i, ClockVar j -> if i<>j then s1,((i,ClockVar j)::s2) else s1,s2
	| ClockVar i, ci 
	| ci, ClockVar i -> s1,((i,ci)::s2)
    in
    let s = aux (s1,s2) (ci1,ci2) in
    let unifiable = 
      (* two clocks are unifiable iff, once s have been applied, they are
      equal modulo the left-most hand-side *)
      match apply_subst s ci1, apply_subst s ci2 with
	| On(_,c1),On(_,c2) -> c1 = c2
	| BaseEff, BaseEff -> true
	| BaseEff,On(_,_)
	| On(_,_),BaseEff -> false    
	| ClockVar _, _
	| _, ClockVar _ -> true
    in
      if unifiable then (
	Verbose.print_string ~level:3 (
	  "# clock checking: unifying '" ^ (ci2str ci1) ^
	    "' and '" ^ (ci2str ci2) ^ "' ->  "^ (subst_to_string s) ^"\n");
	flush stdout;
	s
      ) 
      else
	let msg =  
	  "\n*** clock error: The expression has clock '" ^ 
	    (ci2str ci1) ^ "', \n***             but it is used with clock '" ^ 
	    (ci2str ci2) ^ "'.\n"
	in
	  raise(Compile_error(lxm, msg))

(* exported *)
let (list : Lxm.t -> clock_eff list -> subst -> clock_eff * subst) =
  fun lxm cl s -> 
    List.fold_left 
      (fun (clk,s) clk2 -> 
	 let s = f lxm s clk clk2 in
	 let clk = apply_subst s clk in (* necessary? *)
	   (clk,s)
      )
      (List.hd cl, s)
      (List.tl cl)