Guest User

Untitled

a guest
Jun 25th, 2018
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 10.45 KB | None | 0 0
  1. #nowarn "62" // --mlcompatibility
  2. #light "off"
  3. open System.Collections.Generic
  4.  
  5. type program = statement list
  6. and statement = {
  7.   name : string;
  8.   exp  : exp;
  9.   cond : exp;
  10.   io   : io }
  11. and exp =
  12. | Empty
  13. | Int of int
  14. | Bool of bool
  15. | Var of id
  16. | Not of exp
  17. | Par of exp
  18. | BinOp of binop * exp * exp
  19. | RelBinOp of relbinop * exp * exp
  20. and io =
  21. | Input
  22. | Output
  23. | Temp
  24. and id = string
  25. and binop =
  26. | Plus
  27. | Minus
  28. | Times
  29. | Div
  30. and relbinop =
  31. | Eq
  32. | Less
  33. | Great
  34. | Leq
  35. | Geq
  36. | Diff
  37. | And
  38. | Or
  39.  
  40. type env = (id * value) list
  41. and value = Null | I of int | B of bool
  42.  
  43. module List = begin
  44.   let assoc x = List.find (fst >> (=) x) >> snd
  45.  
  46.   let mem x = List.exists ((=) x)
  47.  
  48.   let union xs ys =
  49.     List.foldBack (fun y zs -> if mem y xs then zs else y :: zs) ys xs
  50.  
  51.   let diff xs ys =
  52.     List.foldBack (fun x zs -> if mem x ys then zs else x :: zs) xs []
  53.  
  54.   let equal xs ys = (diff xs ys) = [] && (diff ys xs) = []
  55. end
  56.  
  57. [<AutoOpen>]
  58. module Utils = begin
  59.   let private binOpStr = [ Plus, "+"; Times, "*"; Minus, "-"; Div, "/" ]
  60.   let private relBinOpStr = [ Eq, "="; Less, "<"; Great, ">"; Leq, "<="; Geq, ">="; Diff, "!="; And, "&&"; Or, "||" ]
  61.      
  62.   let binOps = [ Plus, (+); Times, (*); Minus, (-); Div, (/) ]
  63.   let relBinOps = [ Eq, (=); Less, (<); Great, (>); Leq, (<=); Geq, (>=); Diff, (<>) ]
  64.  
  65.   let rec pgToStr pg =
  66.     pg |> List.fold (fun acc st -> sprintf "%s%s\n" acc (stToStr st)) ""
  67.   and stToStr st =
  68.     sprintf "(%s; %s; %s; %s)" st.name (expToStr st.exp) (expToStr st.cond) (ioToStr st.io)
  69.   and private expToStr = function
  70.   | Empty -> ""
  71.   | Int i -> string i
  72.   | Bool b -> string b
  73.   | Var v -> v
  74.   | Not c -> sprintf "!(%s)" (expToStr c)
  75.   | Par e -> sprintf "(%s)" (expToStr e)
  76.   | BinOp (op, e1, e2) -> sprintf "%s %s %s" (expToStr e1) (List.assoc op binOpStr) (expToStr e2)
  77.   | RelBinOp (op, e1, e2) -> sprintf "%s %s %s" (expToStr e1) (List.assoc op relBinOpStr) (expToStr e2)
  78.   and private ioToStr = function
  79.   | Input -> "Input"
  80.   | Output -> "Output"
  81.   | Temp -> ""
  82. end
  83.  
  84. [<AutoOpen>]
  85. module TP = begin
  86.   let rec private useExp = function
  87.   | Var v -> [ v ]
  88.   | Par e -> useExp e
  89.   | BinOp (_, e1, e2)
  90.   | RelBinOp (_, e1, e2) -> List.union (useExp e1) (useExp e2)
  91.   | _ -> []
  92.  
  93.   let private useStat st = List.union (useExp st.exp) (useExp st.cond)
  94.  
  95.   let private defStat st = st.name
  96.  
  97.   let private fixPoint f eq x0 =
  98.     let rec fixFunc x =
  99.       let y = f x in
  100.       if eq x y then y else fixFunc y
  101.     in
  102.     fixFunc x0
  103.  
  104.   let private statByIO io = List.filter (fun st -> st.io = io)
  105.  
  106.   let inStat = statByIO Input
  107.  
  108.   let outStat = statByIO Output
  109.  
  110.   let usePg pg = List.fold (fun ids st -> List.union ids (useStat st)) [] pg
  111.  
  112.   let defPg pg = List.map defStat pg
  113.  
  114.   let private getSomeStat pg id = List.tryFind (defStat >> (=) id) pg
  115.  
  116.   let getStat pg id =
  117.     match getSomeStat pg id with Some st -> st | _ -> raise (KeyNotFoundException ())
  118.  
  119.   let useDirectIndirect pg st =
  120.     let f ids = List.union ids (usePg (List.choose (getSomeStat pg) ids)) in
  121.     fixPoint f List.equal (useStat st)
  122.  
  123.   let cyclicStat pg st = List.mem (defStat st) (useDirectIndirect pg st)
  124.  
  125.   let cyclicPg pg = pg |> List.exists (cyclicStat pg)
  126.  
  127.   let incompleteStat pg =
  128.     let def = defPg pg in
  129.     let udi = useDirectIndirect pg in
  130.     List.fold (fun acc st -> if List.diff (udi st) def = [] then acc else st :: acc) [] pg
  131.  
  132.   let superfluousStat pg =
  133.     let output = outStat pg in
  134.     let used = List.fold (fun acc st -> List.union acc (useDirectIndirect pg st)) [] output in
  135.     let allButOut = List.diff (defPg pg) (defPg output) in
  136.     List.diff allButOut used
  137.     |> List.map (getStat pg)
  138.  
  139.   let slice pg id =
  140.     let st = getStat pg id in
  141.     (useDirectIndirect pg st |> List.map (getStat pg)) @ [ st ]
  142.  
  143.   let outputSlices pg =
  144.     outStat pg
  145.     |> List.map (defStat >> fun id -> id, slice pg id)
  146.  
  147.   let private sortPg pg =
  148.     let lower st1 st2 = if List.mem (defStat st1) (useDirectIndirect pg st2) then -1 else 1 in
  149.     List.sortWith lower pg
  150.  
  151.   let evalPg env pg =
  152.     let rec evalStat env = function
  153.     | { io = Input } -> env
  154.     | { name = n; exp = e; cond = c; io = _ } ->
  155.       match evalExp env c with
  156.       | B true -> (n, evalExp env e) :: env
  157.       | _ -> (n, Null) :: env
  158.     and evalExp env exp =
  159.       try
  160.         match exp with
  161.         | Int i -> I i
  162.         | Bool b -> B b
  163.         | Par e -> evalExp env e
  164.         | Not c ->
  165.           (match evalExp env c with
  166.           | B b -> B (not b)
  167.           | _ -> Null)
  168.         | RelBinOp (And, e1, e2) ->
  169.           (match evalExp env e1, evalExp env e2 with
  170.           | B b1, B b2 -> B (b1 && b2)
  171.           | _ -> Null)
  172.         | RelBinOp (Or, e1, e2) ->
  173.           (match evalExp env e1, evalExp env e2 with
  174.           | B b1, B b2 -> B (b1 || b2)
  175.           | _ -> Null)
  176.         | BinOp (op, e1, e2) ->
  177.           (match evalExp env e1, evalExp env e2 with
  178.           | I i1, I i2 -> I (List.assoc op binOps i1 i2)
  179.           | _ -> Null)
  180.         | RelBinOp (op, e1, e2) ->
  181.           (match evalExp env e1, evalExp env e2 with
  182.           | I i1, I i2 -> B (List.assoc op relBinOps i1 i2)
  183.           | _ -> Null)
  184.         | Var v -> List.assoc v env
  185.         | Empty -> failwith "theorically must'nt happen"
  186.       with
  187.       | :? KeyNotFoundException -> Null
  188.     in
  189.     List.fold evalStat env (sortPg pg)
  190. end
  191.  
  192. [<AutoOpen>]
  193. module Tests = begin
  194.   let private st01 = { name = "e"; exp = Empty; cond = Bool true; io = Input }
  195.   let private st02 = { name = "f"; exp = Empty; cond = Bool true; io = Input }
  196.   let private st03 = { name = "g"; exp = Empty; cond = Bool true; io = Input }
  197.   let private st04 = { name = "h"; exp = BinOp (Plus, Var "e", Int 1); cond = Bool true; io = Temp }
  198.   let private st05 = { name = "d"; exp = Int 0; cond = Bool true; io = Output }
  199.   let private st06 = { name = "j"; exp = RelBinOp (Less, Var "i", Int 11); cond = RelBinOp (Great, Var "e", Int 1); io = Output }
  200.   let private st07 = { name = "i"; exp = BinOp (Times, Var "e", Var "f"); cond = Bool true; io = Temp }
  201.   let private st08 = { name = "b"; exp = Var "i"; cond = RelBinOp (Great, Var "i", Int 1); io = Output }
  202.   let private st09 = { name = "c"; exp = BinOp (Minus, Int 2, Var "b"); cond = RelBinOp (Great, Var "b", Int 2); io = Output }
  203.   let private st10 = { name = "a"; exp = Var "b"; cond = RelBinOp (Leq, Var "c", Int 0); io = Output }
  204.      
  205.   let pg01 : program = [ st06; st09; st03; st05; st10; st01; st07; st04; st02; st08 ]
  206.      
  207.   let private st11 = { name = "k"; exp = BinOp (Times, Int 2, Var "l"); cond = Bool true; io = Output }
  208.   let private st12 = { name = "l"; exp = BinOp (Times, Int 2, Var "m"); cond = Bool true; io = Output }
  209.   let private st13 = { name = "m"; exp = BinOp (Times, Int 2, Var "k"); cond = Bool true; io = Output }
  210.      
  211.   let pg02 : program = [ st11; st12; st13 ]
  212.      
  213.   let private st14 = { name = "o"; exp = Var "z"; cond = Bool true; io = Temp }
  214.   let private st15 = { name = "p"; exp = Var "o"; cond = Bool true; io = Output }
  215.      
  216.   let pg03 : program = [ st14; st15 ]
  217.  
  218.   let samples = [ pg01; pg02; pg03 ]
  219.  
  220.   let env1 = [ "e", I 5; "f", I 2; "g", I 0 ]
  221.   let env2 = [ "e", I 6; "f", I 2; "g", I 0 ]
  222.   let env3 = [ "e", I 1; "f", I 1; "g", I 0 ]
  223.   let env4 = [ "e", I 2; "f", I 1; "g", I 0 ]
  224.   let env5 = [ "e", I 6 ]
  225.  
  226.   let ``Display Sample`` () =
  227.     printfn "\nDisplay Sample:";
  228.     printfn "-----------------";
  229.     samples |> List.iter (pgToStr >> printfn "%s")
  230.  
  231.   let ``inStat Sample`` () =
  232.     printfn "\ninStat Sample:";
  233.     printfn "----------------";
  234.     samples |> List.iter (inStat >> pgToStr >> printfn "%s")
  235.  
  236.   let ``outStat Sample`` () =
  237.     printfn "\noutStat Sample:";
  238.     printfn "-----------------";
  239.     samples |> List.iter (outStat >> pgToStr >> printfn "%s")
  240.  
  241.   let ``usePg Sample`` () =
  242.     printfn "\nusePg Sample:";
  243.     printfn "---------------";
  244.     samples |> List.iter (usePg >> printfn "%A")
  245.  
  246.   let ``defPg Sample`` () =
  247.     printfn "\ndefPg Sample:";
  248.     printfn "---------------";
  249.     samples |> List.iter (defPg >> printfn "%A")
  250.  
  251.   let ``getStat Sample`` () =
  252.     printfn "\ngetStat Sample:";
  253.     printfn "-----------------";
  254.     (getStat pg01 "a") |> stToStr |> printfn "%s";
  255.     (getStat pg02 "l") |> stToStr |> printfn "%s";
  256.     try (getStat pg01 "y") |> stToStr |> printfn "%s" with :? KeyNotFoundException -> printfn "erreur"
  257.  
  258.   let ``useDirectIndirect Sample`` () =
  259.     printfn "\nuseDirectIndirect Sample:";
  260.     printfn "---------------------------";
  261.     samples |> List.map (fun pg ->
  262.       pg |> List.map (fun st -> st.name, useDirectIndirect pg st))
  263.     |> List.iter (printfn "%A")
  264.  
  265.   let ``cyclicStat Sample`` () =
  266.     printfn "\ncyclicStat Sample:";
  267.     printfn "--------------------";
  268.     samples |> List.map (fun pg ->
  269.       pg |> List.map (cyclicStat pg))
  270.     |> List.iter (printfn "%A")
  271.  
  272.   let ``cyclicPg Sample`` () =
  273.     printfn "\ncyclicPg Sample:";
  274.     printfn "------------------";
  275.     samples |> List.iter (cyclicPg >> printfn "%A")
  276.  
  277.   let ``incompleteStat Sample`` () =
  278.     printfn "\nincompleteStat Sample:";
  279.     printfn "------------------------";
  280.     samples |> List.iter (incompleteStat >> printfn "%A")
  281.  
  282.   let ``superfluousStat Sample`` () =
  283.     printfn "\nsuperfluousStat Sample:";
  284.     printfn "-------------------------";
  285.     samples |> List.iter (superfluousStat >> printfn "%A")
  286.  
  287.   let ``slice Sample`` () =
  288.     printfn "\nslice Sample:";
  289.     printfn "---------------";
  290.     [ "a"; "i"; "b" ] |> List.iter (slice pg01 >> pgToStr >> printfn "%s")
  291.  
  292.   let ``outputSlices Sample`` () =
  293.     printfn "\noutputSlices Sample:";
  294.     printfn "----------------------";
  295.     pg01 |> outputSlices |> List.iter (fun (id, pg) -> printfn "%s:\n%s" id (pgToStr pg))
  296.  
  297.   let ``evalPg Sample`` () =
  298.     printfn "\nevalPg Sample:";
  299.     printfn "----------------";
  300.     evalPg env1 pg01 |> printfn "%A";
  301.     evalPg env2 pg01 |> printfn "%A";
  302.     evalPg env3 pg01 |> printfn "%A";
  303.     evalPg env4 pg01 |> printfn "%A";
  304.     evalPg env5 pg01 |> printfn "%A";
  305.     evalPg [] pg02 |> printfn "%A";
  306.     evalPg [] pg03 |> printfn "%A"
  307. end
  308.  
  309. module Sample = begin
  310.   ``Display Sample`` ();
  311.   ``inStat Sample`` ();
  312.   ``outStat Sample`` ();
  313.   ``usePg Sample`` ();
  314.   ``defPg Sample`` ();
  315.   ``getStat Sample`` ();
  316.   ``useDirectIndirect Sample`` ();
  317.   ``cyclicStat Sample`` ();
  318.   ``cyclicPg Sample`` ();
  319.   ``incompleteStat Sample`` ();
  320.   ``superfluousStat Sample`` ();
  321.   ``slice Sample`` ();
  322.   ``outputSlices Sample`` ();
  323.   ``evalPg Sample`` ()
  324. end
Add Comment
Please, Sign In to add comment