130
129
match (x,!exists) with
131
130
(CTL.True,Exists) -> CTL.EF(CTL.FORWARD,y)
132
131
| (CTL.True,Forall) -> CTL.AF(CTL.FORWARD,s,y)
133
| (CTL.True,ReverseForall) -> failwith "not supported"
134
132
| (_,Exists) -> CTL.EU(CTL.FORWARD,x,y)
135
133
| (_,Forall) -> CTL.AU(CTL.FORWARD,s,x,y)
136
| (_,ReverseForall) -> failwith "not supported"
138
135
let ctl_anti_au s x y = (* only for ..., where the quantifier is changed *)
140
137
(match (x,!exists) with
141
138
(CTL.True,Exists) -> CTL.AF(CTL.FORWARD,s,y)
142
139
| (CTL.True,Forall) -> CTL.EF(CTL.FORWARD,y)
143
| (CTL.True,ReverseForall) -> failwith "not supported"
144
140
| (_,Exists) -> CTL.AU(CTL.FORWARD,s,x,y)
145
| (_,Forall) -> CTL.EU(CTL.FORWARD,x,y)
146
| (_,ReverseForall) -> failwith "not supported")
141
| (_,Forall) -> CTL.EU(CTL.FORWARD,x,y))
148
143
let ctl_uncheck = function
149
144
CTL.True -> CTL.True
1004
1010
| _ -> failwith "not possible" in
1005
1011
let (e2fvs,b2fvs,s2fvs) =
1006
1012
(* fvs on else? *)
1007
match seq_fvs quantified
1008
[Ast.get_fvs ifheader;Ast.get_fvs branch2;afvs] with
1013
(* just combine with the else branch. no point to have separate
1014
quantifier, since there is only one possible control-flow path *)
1015
let else_fvs = Common.union_set (Ast.get_fvs els) (Ast.get_fvs branch2) in
1016
match seq_fvs quantified [Ast.get_fvs ifheader;else_fvs;afvs] with
1009
1017
[(e2fvs,b2fvs);(s2fvs,b2afvs);_] ->
1010
(e2fvs,Common.union_set b2fvs b2afvs,s2fvs)
1018
(e2fvs,Common.union_set b2fvs b2afvs,s2fvs)
1011
1019
| _ -> failwith "not possible" in
1012
1020
let bothfvs = union (union b1fvs b2fvs) (intersect s1fvs s2fvs) in
1013
1021
let exponlyfvs = intersect e1fvs e2fvs in
1196
1210
let prelabel_pred =
1197
1211
CTL.Pred (Lib_engine.PrefixLabel(label_var),CTL.Control) in
1198
1212
let matcher d = make_match None guard (make_meta_rule_elem d fvinfo) in
1213
let stmt_fvs = Ast.get_fvs stmt in
1214
let fvs = get_unquantified quantified stmt_fvs in
1215
let (new_fvs,body) =
1200
1216
match (d,after) with
1201
1217
(Ast.CONTEXT(pos,Ast.NOTHING),(Tail|End|VeryEnd)) ->
1202
1218
(* just match the root. don't care about label; always ok *)
1203
make_raw_match None false ast
1219
(fvs,function f -> f(make_raw_match None false ast))
1204
1220
| (Ast.MINUS(pos,inst,adj,[]),(Tail|End|VeryEnd)) ->
1205
1221
(* don't have to put anything before the beginning, so don't have to
1206
1222
distinguish the first node. so don't have to bother about paths,
1207
1223
just use the label. label ensures that found nodes match up with
1208
1224
what they should because it is in the lhs of the andany. *)
1209
CTL.HackForStmt(CTL.FORWARD,CTL.NONSTRICT,
1210
ctl_and CTL.NONSTRICT label_pred
1211
(make_raw_match label false ast),
1212
ctl_and CTL.NONSTRICT (matcher d) prelabel_pred)
1226
CTL.HackForStmt(CTL.FORWARD,CTL.NONSTRICT,
1227
ctl_and CTL.NONSTRICT label_pred
1228
(make_raw_match label false ast),
1229
ctl_and CTL.NONSTRICT (matcher d) prelabel_pred) in
1231
function f -> ctl_and CTL.NONSTRICT label_pred (f ender))
1214
1233
(* more safe but less efficient *)
1215
1234
let first_metamatch = matcher d in
1221
1240
| Ast.PLUS -> failwith "not possible") in
1222
1241
let rest_nodes = ctl_and CTL.NONSTRICT rest_metamatch prelabel_pred in
1223
1242
let last_node = and_after guard (ctl_not prelabel_pred) after in
1224
(ctl_and CTL.NONSTRICT (make_raw_match label false ast)
1227
ctl_au CTL.NONSTRICT rest_nodes last_node])) in
1228
let body f = ctl_and CTL.NONSTRICT label_pred (f ender) in
1229
let stmt_fvs = Ast.get_fvs stmt in
1230
let fvs = get_unquantified quantified stmt_fvs in
1231
quantify guard (label_var::fvs)
1244
ctl_and CTL.NONSTRICT (make_raw_match label false ast)
1247
ctl_au CTL.NONSTRICT rest_nodes last_node]) in
1249
function f -> ctl_and CTL.NONSTRICT label_pred (f ender)) in
1250
quantify guard new_fvs
1232
1251
(sequencibility body label_pred process_bef_aft seqible)
1234
1253
(* --------------------------------------------------------------------- *)
1235
1254
(* dots and nests *)
1237
let dots_au is_strict toend label s wrapcode x seq_after y quantifier =
1256
let dots_au is_strict toend label s wrapcode n x seq_after y quantifier =
1238
1257
let matchgoto = gotopred None in
1239
1258
let matchbreak =
1240
1259
make_match None false
2022
2056
Common.union_set mb1fvs
2023
2057
(Common.union_set mb2fvs
2024
2058
(Common.union_set mb3fvs minus_quantified)) in
2026
2060
match (Ast.undots body,
2027
2061
contains_modif rbrace or contains_pos rbrace) with
2028
2062
([body],false) ->
2029
2063
(match Ast.unwrap body with
2030
Ast.Nest(stmt_dots,[],multi,_,_) ->
2032
then None (* not sure how to optimize this case *)
2033
else Some (Common.Left stmt_dots)
2034
| Ast.Dots(_,whencode,_,_) when
2064
Ast.Nest(stmt_dots,[],false,_,_) ->
2065
(* special case for function header + body - header is unambiguous
2066
and unique, so we can just look for the nested body anywhere
2070
(CTL.FORWARD,guard_to_strict guard,start_brace,
2071
statement_list stmt_dots
2072
(* discards match on right brace, but don't need it *)
2073
(Guard (make_seq_after end_brace after))
2074
new_quantified3 new_mquantified3
2075
None llabel slabel true guard))
2076
| Ast.Dots((_,i,d,_),whencode,_,_) when
2036
2078
(* flow sensitive, so not optimizable *)
2037
2079
(function Ast.WhenNotTrue(_) | Ast.WhenNotFalse(_) ->
2039
2081
| _ -> true) whencode) ->
2040
Some (Common.Right whencode)
2045
Some (Common.Left stmt_dots) ->
2046
(* special case for function header + body - header is unambiguous
2047
and unique, so we can just look for the nested body anywhere
2050
(CTL.FORWARD,guard_to_strict guard,start_brace,
2051
statement_list stmt_dots
2052
(* discards match on right brace, but don't need it *)
2053
(Guard (make_seq_after end_brace after))
2054
new_quantified3 new_mquantified3
2055
None llabel slabel true guard)
2056
| Some (Common.Right whencode) ->
2057
(* try to be more efficient for the case where the body is just
2082
(* try to be more efficient for the case where the body is just
2058
2083
... Perhaps this is too much of a special case, but useful
2059
2084
for dropping a parameter and checking that it is never used. *)
2071
Ast.WhenAlways(s) -> prev
2072
| Ast.WhenNot(sl) ->
2074
statement_list sl Tail
2075
new_quantified3 new_mquantified3
2076
label llabel slabel true true in
2078
| Ast.WhenNotTrue(_) | Ast.WhenNotFalse(_) ->
2079
failwith "unexpected"
2080
| Ast.WhenModifier(Ast.WhenAny) -> CTL.False
2081
| Ast.WhenModifier(_) -> prev)
2082
CTL.False whencode))
2086
Ast.WhenAlways(s) ->
2089
new_quantified3 new_mquantified3
2090
label llabel slabel true in
2092
| Ast.WhenNot(sl) -> prev
2093
| Ast.WhenNotTrue(_) | Ast.WhenNotFalse(_) ->
2094
failwith "unexpected"
2095
| Ast.WhenModifier(Ast.WhenAny) -> CTL.True
2096
| Ast.WhenModifier(_) -> prev)
2097
CTL.True whencode) in
2098
ctl_au leftarg (make_match stripped_rbrace)]
2086
Ast.MINUS(_,_,_,_) -> None
2100
Ast.WhenAlways(s) -> prev
2101
| Ast.WhenNot(sl) ->
2103
statement_list sl Tail
2109
| Ast.WhenNotTrue(_)
2110
| Ast.WhenNotFalse(_) ->
2111
failwith "unexpected"
2113
(Ast.WhenAny) -> CTL.False
2114
| Ast.WhenModifier(_) -> prev)
2115
CTL.False whencode))
2119
Ast.WhenAlways(s) ->
2124
label llabel slabel true in
2126
| Ast.WhenNot(sl) -> prev
2127
| Ast.WhenNotTrue(_)
2128
| Ast.WhenNotFalse(_) ->
2129
failwith "unexpected"
2130
| Ast.WhenModifier(Ast.WhenAny) ->
2132
| Ast.WhenModifier(_) -> prev)
2133
CTL.True whencode) in
2134
ctl_au leftarg (make_match stripped_rbrace)]))
2138
(* function body is all minus, no whencode *)
2139
match Ast.undots body with
2141
(match Ast.unwrap body with
2143
((_,i,(Ast.MINUS(_,_,_,[]) as d),_),[],_,_) ->
2144
(match (Ast.unwrap lbrace,Ast.unwrap rbrace) with
2145
(Ast.SeqStart((_,_,Ast.MINUS(_,_,_,[]),_)),
2146
Ast.SeqEnd((_,_,Ast.MINUS(_,_,_,[]),_)))
2147
when not (contains_pos rbrace) ->
2149
(* andany drops everything to the end, including close
2150
braces - not just function body, could check
2151
label to keep braces *)
2152
(ctl_and start_brace
2155
(CTL.FORWARD,guard_to_strict guard,CTL.True,
2157
(make_meta_rule_elem d ([],[],[]))))))
2162
match (optim1,optim2) with
2102
2168
quantify guard b3fvs