diff options
author | Alex Auvolat <alex.auvolat@ansys.com> | 2014-06-16 09:56:14 +0200 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ansys.com> | 2014-06-16 09:56:14 +0200 |
commit | b5fd9598302b3e7ac8ab75c36d5a7290d1ad0d78 (patch) | |
tree | 7c77be891d558ce8dfed8a92f61dda43f8a3d533 | |
parent | a1eb0c8e58495358e96d864c72613de162a32f38 (diff) | |
download | scade-analyzer-b5fd9598302b3e7ac8ab75c36d5a7290d1ad0d78.tar.gz scade-analyzer-b5fd9598302b3e7ac8ab75c36d5a7290d1ad0d78.zip |
Implement automata and activate blocks in interpret.
-rw-r--r-- | interpret/interpret2.ml | 140 | ||||
-rw-r--r-- | tests/result/train.out | 192 | ||||
-rw-r--r-- | tests/source/train.scade | 12 | ||||
-rwxr-xr-x | tests/testanalyze.sh | 14 |
4 files changed, 232 insertions, 126 deletions
diff --git a/interpret/interpret2.ml b/interpret/interpret2.ml index 33439e6..d6f7731 100644 --- a/interpret/interpret2.ml +++ b/interpret/interpret2.ml @@ -16,7 +16,7 @@ module I : INTERPRET = struct | VState of id | VPrevious of value list | VBusy (* intermediate value : calculating ! *) - | VCalc of (unit -> value) + | VCalc of (unit -> unit) let int_value i = VInt i let bool_value b = VBool b @@ -78,12 +78,13 @@ module I : INTERPRET = struct Gets the value of a variable relative to a node path. *) - let get_var env node id = + let rec get_var env node id = let p = node^"/"^id in try match Hashtbl.find env.vars p with | VCalc f -> Hashtbl.replace env.vars p VBusy; - f () + f (); + get_var env node id | VBusy -> combinatorial_cycle p | x -> x with @@ -182,6 +183,8 @@ module I : INTERPRET = struct Sets all the init variables to true, and all the state variables to initial state. Does this recursively. + The state reset done by this on the environment is only applied on the + next iteration, when the state info has been extracted by extract_st. *) let rec reset_scope env (node, prefix, eqs) = Hashtbl.replace env.vars (node^"/"^prefix^"init") (VBool true); @@ -226,7 +229,7 @@ module I : INTERPRET = struct let apath = node^"/"^id^"/"^name in let calc () = match eval_expr env (node, prefix) expr with - | [v] -> Hashtbl.replace env.vars apath v; v + | [v] -> Hashtbl.replace env.vars apath v | _ -> loc_error (snd expr) error "Unsupported arity for argument." in Hashtbl.replace env.vars apath (VCalc calc) @@ -237,18 +240,43 @@ module I : INTERPRET = struct let do_eq (e, _) = match e with | AST_assign(vars, e) -> do_expr e; - let calc i () = + let calc () = let vals = eval_expr env (node, prefix) e in List.iter2 (fun (id, _) v -> - Hashtbl.replace env.vars (node^"/"^id) v) vars vals; - List.nth vals i + Hashtbl.replace env.vars (node^"/"^id) v) vars vals in - List.iteri - (fun i (id, _) -> - Hashtbl.replace env.vars (node^"/"^id) (VCalc (calc i))) + List.iter + (fun (id, _) -> + Hashtbl.replace env.vars (node^"/"^id) (VCalc (calc))) vars | AST_assume(_,e) | AST_guarantee(_,e) -> do_expr e - | _ -> not_implemented "activate_scope" + | AST_activate(t, vars) -> + let rec do_tree = function + | AST_activate_body _ -> () + | AST_activate_if(c, a, b) -> + do_expr c; do_tree a; do_tree b + in do_tree t; + let rec needed x () = match x with + | AST_activate_body b -> + activate_scope env (node, b.act_id^".", b.body) + | AST_activate_if (c, t, f) -> + begin match eval_expr env (node, prefix) c with + | [VBool true] -> needed t () + | [VBool false] -> needed f () + | _ -> error "Invalid value in activate if condition." + end + in + List.iter (fun id -> + Hashtbl.replace env.vars (node^"/"^id) (VCalc (needed t))) + vars + | AST_automaton(aid, states, vars) -> + let asn = match VarMap.find (node^"/"^aid^".state") env.st.save with + | VState s -> s + | _ -> assert false + in + let (st, _) = List.find (fun (st, _) -> st.st_name = asn) states in + activate_scope env (node, aid^"."^st.st_name^".", st.body); + List.iter (fun (c, _, _) -> do_expr c) st.until in List.iter do_eq eqs @@ -262,8 +290,50 @@ module I : INTERPRET = struct (* do_weak_transitions : env -> scope -> unit *) - let do_weak_transitions env (node, prefix, eqs) = - not_implemented "do_weak_transitions" + let rec do_weak_transitions env (node, prefix, eqs) = + let do_expr e = + List.iter + (fun (id, eqs, args) -> + do_weak_transitions env (node^"/"^id, "", eqs)) + (extract_instances env.st.p e) + in + let do_eq (e, _) = match e with + | AST_assign(_, e) -> do_expr e + | AST_assume (_, e) | AST_guarantee (_, e) -> do_expr e + | AST_activate(t, _) -> + let rec do_tree = function + | AST_activate_body b -> do_weak_transitions env (node, b.act_id^".", b.body) + | AST_activate_if(c, a, b) -> + do_expr c; do_tree a; do_tree b + in do_tree t + | AST_automaton(aid, states, vars) -> + let svn = node^"/"^aid^".state" in + let stv = VarMap.find svn env.st.save in + let new_st = + if is_scope_active env (node, prefix, eqs) then begin + let asn = match stv with + | VState s -> s + | _ -> assert false + in + let (st, _) = List.find (fun (st, _) -> st.st_name = asn) states in + try + let (_, (next_st,_), rst) = List.find + (fun (c, _, _) -> eval_expr env (node, aid^"."^st.st_name^".") c = [VBool true]) + st.until + in + if rst then begin + let (st, _) = List.find (fun (st, _) -> st.st_name = next_st) states in + reset_scope env (node, aid^"."^next_st^".", st.body) + end; + VState(next_st) + with + | _ -> stv + end else + stv + in + Hashtbl.replace env.vars svn new_st + in + List.iter do_eq eqs (* extract_st : env -> state @@ -282,10 +352,18 @@ module I : INTERPRET = struct let save_expr save e = let save = List.fold_left (fun save (id, expr) -> - VarMap.add - (node^"/"^prefix^id) - (VPrevious (eval_expr env (node, prefix) expr)) - save) + let n = node^"/"^prefix^id in + if is_scope_active env (node, prefix, eqs) then + VarMap.add + n + (VPrevious (eval_expr env (node, prefix) expr)) + save + else + try VarMap.add n + (VarMap.find n env.st.save) + save + with Not_found -> save + ) save (extract_pre e) in let save = List.fold_left (fun save (n, eqs, _) -> @@ -296,8 +374,25 @@ module I : INTERPRET = struct let save_eq save eq = match fst eq with | AST_assign(_, e) | AST_assume(_, e) | AST_guarantee(_, e) -> save_expr save e - | AST_automaton(aid, states, _) -> not_implemented "save_eq automaton" - | AST_activate(r, _) -> not_implemented "save_eq activate" + | AST_automaton(aid, states, _) -> + let svn = node^"/"^aid^".state" in + let st = Hashtbl.find env.vars svn in + let save = VarMap.add (node^"/"^aid^".state") st save in + List.fold_left (fun save (st, _) -> + let save = + List.fold_left (fun save (c, _, _) -> save_expr save c) save st.until in + aux (node, aid^"."^st.st_name^".", st.body) save) + save states + | AST_activate(r, _) -> + let rec do_t save = function + | AST_activate_if(c, t, f) -> + let save = save_expr save c in + let save = do_t save t in + do_t save f + | AST_activate_body b -> + aux (node, b.act_id^".", b.body) save + in + do_t save r in List.fold_left save_eq save eqs @@ -327,7 +422,7 @@ module I : INTERPRET = struct let cpath = "cst/" ^ d.c_name in Hashtbl.replace env.vars cpath (VCalc (fun () -> match eval_expr env ("cst", "") d.value with - | [v] -> Hashtbl.replace env.vars cpath v; v + | [v] -> Hashtbl.replace env.vars cpath v | _ -> loc_error l error "Arity error in constant expression.")) | _ -> ()) p; @@ -348,11 +443,10 @@ module I : INTERPRET = struct let env = { st = st; vars = vars } in activate_scope env st.root_scope; - (* + if false then Hashtbl.iter (fun k v -> Format.printf "%s : %s@." k (str_repr_of_val v)) env.vars; - *) let out = List.map (fun id -> id, get_var env "" id) st.outputs in - (* do_weak_transitions env st.root_scope; *) + do_weak_transitions env st.root_scope; extract_st env, out diff --git a/tests/result/train.out b/tests/result/train.out index 4af78b5..061ff7a 100644 --- a/tests/result/train.out +++ b/tests/result/train.out @@ -1,101 +1,101 @@ -0. 0 0 0 +0. -1 0 0 1. 0 0 0 2. 0 0 0 3. 0 0 0 4. 0 0 0 -5. 0 0 0 +5. 1 0 0 6. 0 0 0 -7. 0 0 0 -8. 0 0 0 -9. 0 0 0 -10. 0 0 0 -11. 0 0 0 -12. 0 0 0 -13. 0 0 0 -14. 0 0 0 -15. 0 0 0 -16. 0 0 0 -17. 0 0 0 -18. 0 0 0 -19. 0 0 0 -20. 0 0 0 -21. 0 0 0 -22. 0 0 0 -23. 0 0 0 -24. 0 0 0 -25. 0 0 0 -26. 0 0 0 -27. 0 0 0 -28. 0 0 0 -29. 0 0 0 -30. 0 0 0 -31. 0 0 0 -32. 0 0 0 -33. 0 0 0 -34. 0 0 0 -35. 0 0 0 -36. 0 0 0 -37. 0 0 0 -38. 0 0 0 -39. 0 0 0 -40. 0 0 0 -41. 0 0 0 -42. 0 0 0 -43. 0 0 0 -44. 0 0 0 -45. 0 0 0 -46. 0 0 0 -47. 0 0 0 -48. 0 0 0 -49. 0 0 0 -50. 0 0 0 -51. 0 0 0 -52. 0 0 0 -53. 0 0 0 -54. 0 0 0 -55. 0 0 0 -56. 0 0 0 -57. 0 0 0 -58. 0 0 0 -59. 0 0 0 -60. 1 0 0 -61. 1 0 0 -62. 1 0 0 -63. 1 0 0 -64. 1 0 0 -65. 1 0 0 -66. 1 0 0 -67. 1 0 0 -68. 1 0 0 -69. 1 0 0 -70. 1 0 0 -71. 1 0 0 -72. 1 0 0 -73. 1 0 0 -74. 1 0 0 -75. 1 0 0 -76. 1 0 0 -77. 1 0 0 -78. 1 0 0 -79. 1 0 0 -80. 1 0 0 -81. 1 0 0 -82. 1 0 0 -83. 1 0 0 -84. 1 0 0 -85. 1 0 0 -86. 1 0 0 -87. 1 0 0 -88. 1 0 0 -89. 1 0 0 -90. 1 0 0 -91. 1 0 0 -92. 1 0 0 -93. 1 0 0 -94. 1 0 0 -95. 1 0 0 -96. 1 0 0 -97. 1 0 0 -98. 1 0 0 -99. 1 0 0 -100. 1 0 0 +7. 1 0 0 +8. 1 0 0 +9. 1 0 0 +10. 1 0 0 +11. 2 0 0 +12. 1 0 0 +13. 2 0 0 +14. 2 0 0 +15. 2 0 0 +16. 2 0 0 +17. 3 0 0 +18. 2 0 0 +19. 3 0 0 +20. 3 0 0 +21. 3 0 0 +22. 3 0 0 +23. 4 0 0 +24. 3 0 0 +25. 4 0 0 +26. 4 0 0 +27. 4 0 0 +28. 4 0 0 +29. 5 0 0 +30. 4 0 0 +31. 5 0 0 +32. 5 0 0 +33. 5 0 0 +34. 5 0 0 +35. 6 0 0 +36. 5 0 0 +37. 6 0 0 +38. 6 0 0 +39. 6 0 0 +40. 6 0 0 +41. 7 0 0 +42. 6 0 0 +43. 7 0 0 +44. 7 0 0 +45. 7 0 0 +46. 7 0 0 +47. 8 0 0 +48. 7 0 0 +49. 8 0 0 +50. 8 0 0 +51. 8 0 0 +52. 8 0 0 +53. 9 0 0 +54. 8 0 0 +55. 9 0 0 +56. 9 0 0 +57. 9 0 0 +58. 9 0 0 +59. 10 0 0 +60. 9 1 0 +61. 10 1 0 +62. 10 1 0 +63. 10 1 0 +64. 10 1 0 +65. 11 1 0 +66. 10 1 0 +67. 11 1 0 +68. 11 1 0 +69. 11 1 0 +70. 11 1 0 +71. 12 1 0 +72. 11 1 0 +73. 12 1 0 +74. 12 1 0 +75. 12 1 0 +76. 12 1 0 +77. 13 1 0 +78. 12 1 0 +79. 13 1 0 +80. 13 1 0 +81. 13 1 0 +82. 13 1 0 +83. 14 1 0 +84. 13 1 0 +85. 14 1 0 +86. 14 1 0 +87. 14 1 0 +88. 14 1 0 +89. 15 1 0 +90. 14 1 0 +91. 15 1 0 +92. 15 1 0 +93. 15 1 0 +94. 15 1 0 +95. 16 1 0 +96. 15 1 0 +97. 16 1 0 +98. 16 1 0 +99. 16 1 0 +100. 16 1 0 diff --git a/tests/source/train.scade b/tests/source/train.scade index c51971e..0b93b2f 100644 --- a/tests/source/train.scade +++ b/tests/source/train.scade @@ -9,8 +9,7 @@ let else 0); tel -node train(beacon, second: bool) returns (early, late: bool) -var probe advance: int; +node train(beacon, second: bool) returns (early, late: bool; probe advance: int) let advance = diff(beacon, second); @@ -50,9 +49,9 @@ let returns alarm; tel -node train_check(beacon, second: bool) returns (early, late, alarm: bool) +node train_check(beacon, second: bool) returns (early, late, alarm: bool; adv: int) let - early, late = train(beacon, second); + early, late, adv = train(beacon, second); alarm = observer(early, late); guarantee ok : not alarm; tel @@ -61,9 +60,8 @@ node test(i: int) returns(a, b, c: int; exit: bool) var early, late, alarm: bool; let exit = i >= 100; - early, late, alarm = train_check((i+1) mod 2 = 0, i mod 3 = 0); + early, late, alarm, a = train_check((i+1) mod 2 = 0, i mod 3 = 0); c = if alarm then 1 else 0; - a = if early then 1 else 0; - b = if late then 1 else 0; + b = if early then 1 else if late then 2 else 0; tel diff --git a/tests/testanalyze.sh b/tests/testanalyze.sh new file mode 100755 index 0000000..8b1add2 --- /dev/null +++ b/tests/testanalyze.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +for a in source/*.scade; do + if ../analyze --test $a > /tmp/analyze_out.txt; + then + if diff -B /tmp/analyze_out.txt result/`basename $a .scade`.out >/dev/null; then + echo "OK $a" + else + echo "FAIL $a" + fi + else + echo "TODO $a" + fi +done |