-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcfg.ml
70 lines (54 loc) · 2.06 KB
/
cfg.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
type label = int
type field_name = string
type var_name = string
type method_name = string
type class_name = string
type inst =
| Assign of var_name * string
| New of var_name * class_name * int
| Set of var_name * field_name * var_name
| Get of var_name * var_name * field_name
| Call of var_name * method_name * (var_name list)
type edge = label * inst * label
module CfgSet = Lib.Set.Make(struct type t = edge let compare = compare end)
type t = label * CfgSet.t * label
let fold f_cfg f_edge (cfg : t) a_init =
let (init, cfgset, final) = cfg in
f_cfg init final (CfgSet.fold f_edge cfgset a_init)
let make init final edges =
(init, (CfgSet.from_list edges), final)
let inst_from_ast_inst i =
match i with
| Lang.Ast.Assign (v, s) -> Assign (v, s)
| Lang.Ast.New (v, cl, id) -> New (v, cl, id)
| Lang.Ast.Set (v1, f, v2) -> Set (v1, f, v2)
| Lang.Ast.Get (v1, v2, f) -> Get (v1, v2, f)
| Lang.Ast.Call (v, m, args) -> Call (v, m, args)
let from_ast_insts il =
let init = 0 in
let rec add_insts il (cfgset, label) =
match il with
| [] -> (cfgset, label)
| i::tl ->
let next = label + 1 in
let i' = inst_from_ast_inst i in
add_insts tl (CfgSet.add (label, i', next) cfgset, label + 1) in
let (cfgset, final) = add_insts il (CfgSet.empty, init) in
(init, cfgset, final)
let string_of_inst i =
let fmt = Printf.sprintf in
match i with
| Assign (v, s) -> fmt "%s = \"%s\"" v s
| New (v, cl, id) -> fmt "%s = new:%d %s" v id cl
| Set (v1, f, v2) -> fmt "%s.%s = %s" v1 f v2
| Get (v1, v2, f) -> fmt "%s = %s.%s" v1 v2 f
| Call (v, m, args) ->
let arg_str = List.fold_left (fun s a -> s ^ (if s = "" then "" else ", ") ^ a) "" args in
fmt "%s.%s(%s)" v m arg_str
let string_of_edge e =
let (i, instr, o) = e in
Printf.sprintf "(%s, %s, %s)" (string_of_int i) (string_of_inst instr) (string_of_int o)
let string_of_cfgset = CfgSet.to_string string_of_edge
let to_string c =
let (init, cfgset, final) = c in
Printf.sprintf "(%s, %s, %s)" (string_of_int init) (string_of_cfgset cfgset) (string_of_int final)