summaryrefslogtreecommitdiff
path: root/abstract/transform.ml
diff options
context:
space:
mode:
Diffstat (limited to 'abstract/transform.ml')
-rw-r--r--abstract/transform.ml203
1 files changed, 203 insertions, 0 deletions
diff --git a/abstract/transform.ml b/abstract/transform.ml
new file mode 100644
index 0000000..56d54ce
--- /dev/null
+++ b/abstract/transform.ml
@@ -0,0 +1,203 @@
+open Ast
+open Util
+open Ast_util
+open Formula
+
+open Interpret (* used for constant evaluation ! *)
+
+
+(* Transform SCADE program to logical formula. *)
+
+(* node * prefix * equations *)
+type scope = id * id * eqn ext list
+
+type transform_data = {
+ p : Ast.prog;
+ consts : I.value VarMap.t;
+ root_scope : scope;
+ (* future : the automata state *)
+}
+
+let f_and a b =
+ if a = BConst true then b
+ else if b = BConst true then a
+ else BAnd(a, b)
+
+
+(* f_of_nexpr :
+ transform_data -> (string, string) -> (num_expr list -> 'a) -> expr -> 'a
+*)
+let rec f_of_nexpr td (node, prefix) where expr =
+ let sub = f_of_nexpr td (node, prefix) in
+ match fst expr with
+ (* ident *)
+ | AST_identifier(id, _) -> where [NIdent (node^"/"^id)]
+ | AST_idconst(id, _) ->
+ begin let x = VarMap.find ("cst/"^id) td.consts in
+ try where [NIntConst (I.as_int x)]
+ with _ -> try where [NRealConst (I.as_real x)]
+ with _ -> error "Invalid data for supposedly numerical constant."
+ end
+ (* numerical *)
+ | AST_int_const(i, _) -> where [NIntConst(int_of_string i)]
+ | AST_real_const(r, _) -> where [NRealConst(float_of_string r)]
+ | AST_unary(op, e) ->
+ sub (function
+ | [x] -> where [NUnary(op, x)]
+ | _ -> invalid_arity "Unary operator") e
+ | AST_binary(op, a, b) ->
+ sub (function
+ | [x] ->
+ sub (function
+ | [y] -> where [NBinary(op, x, y)]
+ | _ -> invalid_arity "binary_operator") b
+ | _ -> invalid_arity "binary operator") a
+ (* temporal *)
+ | AST_pre(_, id) -> where [NIdent id]
+ | AST_arrow(a, b) ->
+ BOr(
+ BAnd(BRel(AST_EQ, NIdent(node^"/"^prefix^"time"), NIntConst 0),
+ sub where a),
+ BAnd(BRel(AST_GE, NIdent(node^"/"^prefix^"time"), NIntConst 1),
+ sub where b))
+ (* other *)
+ | AST_if(c, a, b) ->
+ BOr(
+ BAnd(f_of_bexpr td (node, prefix) c, sub where a),
+ BAnd(BNot(f_of_bexpr td (node, prefix) c), sub where b))
+ | AST_instance ((f, _), args, nid) ->
+ let (n, _) = find_node_decl td.p f in
+ where (List.map (fun (_, (id, _), _) -> NIdent (node^"/"^nid^"/"^id)) n.ret)
+
+ (* boolean values treated as integers *)
+ | _ ->
+ BOr(
+ BAnd ((f_of_bexpr td (node, prefix) expr), where [NIntConst 1]),
+ BAnd (BNot(f_of_bexpr td (node, prefix) expr), where [NIntConst 0])
+ )
+
+(* f_of_expr :
+ transform_data -> (string, string) -> expr -> bool_expr
+*)
+and f_of_bexpr td (node, prefix) expr =
+ let sub = f_of_bexpr td (node, prefix) in
+ match fst expr with
+ | AST_bool_const b -> BConst b
+ | AST_binary_bool(AST_AND, a, b) -> BAnd(sub a, sub b)
+ | AST_binary_bool(AST_OR, a, b) -> BOr(sub a, sub b)
+ | AST_not(a) -> BNot(sub a)
+ | AST_binary_rel(rel, a, b) ->
+ f_of_nexpr td (node, prefix)
+ (function
+ | [x] -> f_of_nexpr td (node, prefix)
+ (function
+ | [y] -> BRel(rel, x, y)
+ | _ -> invalid_arity "boolean relation") b
+ | _ -> invalid_arity "boolean relation")
+ a
+ | _ -> loc_error (snd expr) error "Invalid type : expected boolean value"
+
+
+
+and f_of_scope active td (node, prefix, eqs) =
+ let expr_eq e eq =
+ let instance_eq (id, eqs, args) =
+ let eq = f_of_scope active td (node^"/"^id, "", eqs) in
+ if active then
+ List.fold_left (fun eq ((_,(argname,_),_), expr) ->
+ let eq_arg = f_of_nexpr td (node, prefix) (function
+ | [v] -> BRel(AST_EQ, NIdent(node^"/"^id^"/"^argname), v)
+ | _ -> invalid_arity "in argument")
+ expr
+ in f_and eq eq_arg)
+ eq args
+ else
+ eq
+ in
+ let eq = List.fold_left (fun x i -> f_and (instance_eq i) x)
+ eq (extract_instances td.p e)
+ in
+ let pre_expr (id, expr) =
+ if active then
+ f_of_nexpr td (node, prefix) (function
+ | [v] -> BRel(AST_EQ, NIdent("N"^id), v)
+ | _ -> invalid_arity "pre on complex data not supported")
+ expr
+ else
+ BRel(AST_EQ, NIdent("N"^id), NIdent id)
+ in
+ List.fold_left (fun x i -> f_and (pre_expr i) x)
+ eq (extract_pre e)
+ in
+ let do_eq eq = match fst eq with
+ | AST_assign(ids, e) ->
+ let assign_eq =
+ if active then
+ f_of_nexpr td (node, prefix)
+ (fun vs ->
+ let rels =
+ List.map2 (fun (id, _) v -> BRel(AST_EQ, NIdent (node^"/"^id), v))
+ ids vs
+ in
+ list_fold_op f_and rels)
+ e
+ else
+ BConst true
+ in
+ expr_eq e assign_eq
+ | AST_assume (_, e) ->
+ if active then
+ f_of_bexpr td (node, prefix) e
+ else
+ BConst true
+ | AST_guarantee _ -> BConst true
+ | AST_activate (b, _) ->
+ let rec cond_eq = function
+ | AST_activate_body b -> BConst true
+ | AST_activate_if(c, a, b) ->
+ f_and (expr_eq c (BConst true))
+ (f_and (cond_eq a) (cond_eq b))
+ in
+ let rec do_tree_act = function
+ | AST_activate_body b ->
+ f_of_scope true td (node, b.act_id^"_", b.body)
+ | AST_activate_if(c, a, b) ->
+ BOr(
+ f_and (f_of_bexpr td (node, prefix) c)
+ (f_and (do_tree_act a) (do_tree_inact b)),
+ f_and (BNot(f_of_bexpr td (node, prefix) c))
+ (f_and (do_tree_act b) (do_tree_inact a))
+ )
+ and do_tree_inact = function
+ | AST_activate_body b ->
+ f_of_scope false td (node, b.act_id^"_", b.body)
+ | AST_activate_if(_, a, b) ->
+ f_and (do_tree_inact a) (do_tree_inact b)
+ in
+ f_and (cond_eq b) (if active then do_tree_act b else do_tree_inact b)
+ | AST_automaton _ -> not_implemented "f_of_scope do_eq automaton"
+ in
+ let time_incr_eq =
+ if active then
+ BRel(AST_EQ, NIdent("N"^node^"/"^prefix^"time"),
+ NBinary(AST_PLUS, NIntConst 1, NIdent(node^"/"^prefix^"time")))
+ else
+ BRel(AST_EQ,
+ NIdent("N"^node^"/"^prefix^"time"),
+ NIdent(node^"/"^prefix^"time"))
+ in
+ List.fold_left f_and
+ time_incr_eq
+ (List.map do_eq eqs)
+
+and f_of_prog p root =
+ let (n, _) = find_node_decl p root in
+ let root_scope = ("", "", n.body) in
+ let td = {
+ root_scope = root_scope;
+ p = p;
+ consts = I.consts p root;
+ } in
+
+ f_of_scope true td td.root_scope
+