Skip to content

Commit

Permalink
output normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
Th0mz committed Jun 27, 2024
1 parent 341f576 commit 3c925ef
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 27 deletions.
5 changes: 3 additions & 2 deletions bin/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ let main (filename : string) (output_path : string) (verbose : bool) (generate_m

(* STEP 2 : Generate MDG for the normalized code *)
if generate_mdg then (
let graph, _ = Mdg.Analyse.program verbose norm_program in
Mdg.Pp.Dot.output (graph_dir ^ "graph") graph
let graph = Mdg.Analyse.program verbose norm_program in
Mdg.Pp.Dot.output graph_dir graph;
Mdg.Pp.CSV.output graph_dir graph
);

0
Expand Down
2 changes: 1 addition & 1 deletion lib/ast/normalize.ml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ and normalize_statement (context : context) (stmt : ('M, 'T) Ast'.Statement.t) :
let loc = loc_f loc in
let test_stmts, test_expr = ne test in
let body_stmts = ns body in

let true_val = Expression.Literal.build loc (Expression.Literal.Boolean true) "true" in
let setup, update, test_expr = if test_stmts = []
then
Expand Down
5 changes: 5 additions & 0 deletions lib/ast/structures/grammar.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ module Location = struct
and convert_flow_pos ({line; column} : Loc.position) : position =
{ line = line; column = column };;

let rec to_string (loc : t) : string =
"{\"start\":" ^ position_to_string loc._start ^ ",\"end\":" ^ position_to_string loc._end ^ "}"
and position_to_string (position : position) : string =
"{\"line\":" ^ string_of_int position.line ^ ",\"column\":" ^ string_of_int position.column ^ "}"

end

type m = Location.t;;
Expand Down
7 changes: 4 additions & 3 deletions lib/mdg/analyse.ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ open State
let verbose = ref false;;


let rec program (is_verbose : bool) ((_, program) : m Program.t) : Graph.t * Store.t =
let rec program (is_verbose : bool) ((_, program) : m Program.t) : Graph.t =
verbose := is_verbose;
let state = empty_state in
let state' = initialize_functions state program.functions in

analyse_sequence state' program.body;
state'.graph, state'.store
state'.graph

and analyse (state : state) (statement : m Statement.t) : unit =
let graph = state.graph in
Expand Down Expand Up @@ -134,7 +134,8 @@ and analyse (state : state) (statement : m Statement.t) : unit =
(* argument edges *)
let params = get_param_names f in
List.iteri ( fun i _Ls ->
LocationSet.iter (fun l -> add_arg_edge l l_call (List.nth params i)) _Ls
let param_name = List.nth params i in
LocationSet.iter (fun l -> add_arg_edge l l_call i param_name) _Ls
) _Lss;

(* call edge *)
Expand Down
78 changes: 69 additions & 9 deletions lib/mdg/pp/pp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,85 @@ end

let convert_graph (graph : Graph.t) : G.t =
let result = ref G.empty in
Graph.iter (fun from edegs _ ->
Graph.iter_edges (fun from edge ->
result := G.add_vertex !result from;
EdgeSet.iter (fun ({_to ; _} as edge) ->
let edge = G.E.create from (Graph.Edge.label edge) _to in
result := G.add_edge_e !result edge;
) edegs
let edge = G.E.create from (Graph.Edge.label edge) (Graph.Edge.get_to edge) in
result := G.add_edge_e !result edge;
) graph;

!result

let output (filename : string) (graph : Graph.t) : unit =
let dot_file = filename ^ ".dot" in
let svg_file = filename ^ ".svg" in
let output (file_path : string) (graph : Graph.t) : unit =
let dot_file = file_path ^ "graph.dot" in
let svg_file = file_path ^ "graph.svg" in

let file = Out_channel.open_bin dot_file in
let file = open_out_bin dot_file in
Dot.set_info graph.nodes;
Dot.output_graph file (convert_graph graph);
Out_channel.close file;

let _ = Sys.command ("dot -Tsvg " ^ dot_file ^ " -o " ^ svg_file ^ "; rm " ^ dot_file) in
()
end

module CSV = struct
let output (file_path : string) (graph : Graph.t) : unit =
Graph.add_literal_node graph;

let nodes_file = file_path ^ "nodes.csv" in
let edges_file = file_path ^ "rels.csv" in
let graph_stats = file_path ^ "graph_stats.json" in

(* process node information *)
let out_channel = open_out nodes_file in
output_string out_channel "Id:ID¿Type¿SubType¿IdentifierName¿Raw¿InternalStructure¿Location¿Code¿Label:LABEL\n";

Graph.iter_nodes (fun loc node_info ->
let info = [
loc; (* node id *)
Node.get_type node_info; (* node type *)
Node.get_subtype node_info; (* node subtype *)
Node.get_id node_info; (* node identifier name *)
Node.get_raw node_info; (* node raw *)
Node.get_structure node_info; (* node internal structure *)
Node.get_location node_info; (* node location *)
Node.get_code node_info; (* node code *)
Node.get_label node_info (* node label *)
] in
output_string out_channel ((String.concat "¿" info) ^ "\n");
) graph;

close_out out_channel;

(* process edge information *)
let out_channel = open_out edges_file in
output_string out_channel "FromId:START_ID¿ToId:END_ID¿RelationLabel:TYPE¿RelationType¿IdentifierName¿ArgumentIndex¿ParamIndex¿StmtIndex¿ElementIndex¿ExpressionIndex¿MethodIndex¿SourceObjName¿IsProp\n";
Graph.iter_edges (fun loc edge ->
let info = [
loc; (* edge from *)
Edge.get_to edge; (* edge to *)
Edge.get_rel_label edge; (* edge relation label *)
Edge.get_rel_type edge; (* edge relation type *)
Edge.get_id edge; (* edge identifier name *)
Edge.get_arg_i edge; (* edge argument index *)
Edge.get_par_i edge; (* edge param index *)
Edge.get_stm_i edge; (* edge stmt index *)
Edge.get_elm_i edge; (* edge element index *)
Edge.get_exp_i edge; (* edge expression index *)
Edge.get_met_i edge; (* edge method index *)
Edge.get_src_obj edge; (* edge source obj name *)
Edge.get_dep_of_prop edge; (* edge is dependency of property *)
] in
output_string out_channel ((String.concat "¿" info) ^ "\n")
) graph;

close_out out_channel;

(* save graph stats *)
let out_channel = open_out graph_stats in
let edges = string_of_int (Graph.num_edges graph) in
let nodes = string_of_int (Graph.num_nodes graph) in
output_string out_channel ("{ \"edges\": " ^ edges ^ ", \"nodes\": " ^ nodes ^ "}");

close_out out_channel
end
65 changes: 55 additions & 10 deletions lib/mdg/structures/graph'.ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,30 @@ module Node = struct
| Object of string
| Function of Functions.Id.t
| Parameter of string
| Literal

let equal (node : t) (node' : t) = match (node, node') with
| Object x, Object x'
| Parameter x, Parameter x' -> String.equal x x'
| Function x, Function x' -> Functions.Id.equal x x'
| Literal, Literal -> true
| _ -> false

let label (node : t) = match node with
| Object obj -> obj
| Function func -> func.name
| Parameter param -> param
| Literal -> "literal value"

(* get node information *)
let get_type (_ : t) : string = ""
let get_subtype (_ : t) : string = ""
let get_id (_ : t) : string = ""
let get_raw (_ : t) : string = ""
let get_structure (_ : t) : string = ""
let get_location (_ : t) : string = ""
let get_code (_ : t) : string = ""
let get_label (_ : t) : string = ""

end

Expand All @@ -29,7 +42,7 @@ module Edge = struct
| Property of property option
| Version of property option
| Dependency
| Argument of string
| Argument of int (* argument index *) * string (* argument name *)
| Parameter of string
| Call
| Return
Expand All @@ -43,7 +56,6 @@ module Edge = struct
let is_version (edge : t) = match edge._type with Version _ -> true | _ -> false
let is_param (edge : t) = match edge._type with Parameter _ -> true | _ -> false
let get_property (edge : t) : property option = match edge._type with Property p | Version p -> p | _ -> failwith "edge is neither a property edge nor a version edge"
let get_to (edge : t) : location = edge._to

let _type_to_int (t : _type) : int =
match t with
Expand All @@ -57,7 +69,7 @@ module Edge = struct
match Int.compare (_type_to_int t) (_type_to_int t'), t, t' with
| 0, Property x, Property x'
| 0, Version x, Version x' -> Option.compare (String.compare) x x'
| 0, Argument x, Argument x'
| 0, Argument (_, x), Argument (_, x')
| 0, Parameter x, Parameter x' -> String.compare x x'
| c, _, _ -> c

Expand All @@ -71,12 +83,39 @@ module Edge = struct
| Property prop -> map_default (fun prop -> "P(" ^ prop ^ ")") "P(*)" prop
| Version prop -> map_default (fun prop -> "V(" ^ prop ^ ")") "V(*)" prop
| Dependency -> "D"
| Argument id -> "ARG(" ^ id ^ ")"
| Argument (_, id) -> "ARG(" ^ id ^ ")"
| Parameter pos -> "param " ^ pos
| Call -> "CG"
| Return -> "RET"

let to_string (edge : t) : string = " --" ^ label edge ^ "-> " ^ edge._to

(* get edge information *)
let get_to (edge : t) : location = edge._to
let get_rel_label (edge : t) : string =
match edge._type with
| Property _ | Version _ | Dependency -> "MDG"
| Call -> "CG"
| _ -> "TODO"

let get_rel_type (_ : t) : string = ""
let get_id (_ : t) : string = ""
let get_arg_i (edge : t) : string =
match edge._type with
| Argument (i, _) -> string_of_int i
| _ -> ""

let get_par_i (edge : t) : string =
match edge._type with
| Parameter i -> i
| _ -> ""

let get_stm_i (_ : t) : string = ""
let get_elm_i (_ : t) : string = ""
let get_exp_i (_ : t) : string = ""
let get_met_i (_ : t) : string = ""
let get_src_obj (_ : t) : string = ""
let get_dep_of_prop (_ : t) : string = ""
end

module EdgeSet = struct
Expand All @@ -101,11 +140,12 @@ type t = {
(* ------- S T R U C T U R E F U N C T I O N S ------- *)

(* > EDGES FUNCTIONS : *)
let iter_edges (f : location -> EdgeSet.t -> unit) (graph : t) = HashTable.iter f graph.edges
let iter_edges (f : location -> Edge.t -> unit) (graph : t) = HashTable.iter (fun loc edges -> EdgeSet.iter (f loc) edges) graph.edges
let fold_edges (f : location -> EdgeSet.t -> 'acc -> 'acc) (graph : t) : 'acc -> 'acc = HashTable.fold f graph.edges
let find_edges_opt (graph : t) : location -> EdgeSet.t option = HashTable.find_opt graph.edges
let find_edges (graph : t) : location -> EdgeSet.t = HashTable.find graph.edges
let mem_edges (graph : t) : location -> bool = HashTable.mem graph.edges
let num_edges (graph : t) : int = HashTable.fold (fun _ edges acc -> acc + EdgeSet.cardinal edges) graph.edges 0

let replace_edges (graph : t) (location : location) (edges : EdgeSet.t) : unit =
let old_edges = find_edges_opt graph location in
Expand All @@ -116,15 +156,16 @@ let rec print (graph : t) : unit =
iter_edges print_edge graph;
print_string "\n";

and print_edge (from : location) (edges : EdgeSet.t) : unit =
EdgeSet.iter (fun edge -> print_string (from ^ (Edge.to_string edge) ^ "\n")) edges
and print_edge (from : location) (edge : Edge.t) : unit =
print_string (from ^ (Edge.to_string edge) ^ "\n")

(* > NODE FUNCTIONS : *)
let iter_nodes (f : location -> Node.t -> unit) (graph : t) = HashTable.iter f graph.nodes

let find_node_opt' : Node.t HashTable.t -> location -> Node.t option = HashTable.find_opt
let find_node_opt (graph : t) : location -> Node.t option = find_node_opt' graph.nodes
let find_node (graph : t) : location -> Node.t = HashTable.find graph.nodes
let num_nodes (graph : t) : int = HashTable.length graph.nodes

let replace_node (graph : t) (location : location) (node : Node.t) =
let old_node = find_node_opt graph location in
Expand All @@ -134,7 +175,7 @@ let replace_node (graph : t) (location : location) (node : Node.t) =
(* > GRAPH FUNCTIONS : *)
let copy (graph : t) : t = {graph with edges = HashTable.copy graph.edges; nodes = HashTable.copy graph.nodes}
let empty (register : unit -> unit) : t = {edges = HashTable.create 100; nodes = HashTable.create 50; register = register}
let iter (f : location -> EdgeSet.t -> Node.t option -> unit) (graph : t) = iter_edges (fun loc edges -> let node = find_node_opt graph loc in f loc edges node) graph
let iter (f : location -> EdgeSet.t -> Node.t option -> unit) (graph : t) = HashTable.iter (fun loc edges -> let node = find_node_opt graph loc in f loc edges node) graph.edges


(* ------- A U X I L I A R Y F U N C T I O N S -------*)
Expand Down Expand Up @@ -284,6 +325,10 @@ let add_param_node (graph : t) (loc : location) (param : string) : unit =
let node : Node.t = Parameter param in
add_node graph loc node

let add_literal_node (graph : t) : unit =
let node : Node.t = Literal in
add_node graph literal node


let add_edge (graph : t) (edge : Edge.t) (_to : location) (from : location) : unit =
let edges = get_edges graph from in
Expand All @@ -301,8 +346,8 @@ let add_version_edge (graph : t) (from : location) (_to : location) (property :
let edge = {Edge._to = _to; _type = Version property} in
add_edge graph edge _to from

let add_arg_edge (graph : t) (from : location) (_to : location) (identifier : string) : unit =
let edge = {Edge._to = _to; _type = Argument identifier} in
let add_arg_edge (graph : t) (from : location) (_to : location) (index : int) (identifier : string) : unit =
let edge = {Edge._to = _to; _type = Argument (index, identifier)} in
add_edge graph edge _to from

let add_param_edge (graph : t) (from : location) (_to : location) (index : string) : unit =
Expand Down
4 changes: 2 additions & 2 deletions lib/mdg/structures/store.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ type t = LocationSet.t HashTable.t


let empty () : t = HashTable.create 100
let literal_loc = LocationSet.singleton (loc_obj_prefix ^ "literal")
let this_loc = LocationSet.singleton "this"
let literal_loc = LocationSet.singleton literal
let this_loc = LocationSet.singleton this

(* =============== F U N C T I O N S =============== *)

Expand Down
3 changes: 3 additions & 0 deletions lib/mdg/structures/structures.ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ let loc_obj_prefix : location = "l_"
let loc_par_prefix : location = "p_"
let loc_fun_prefix : location = "f_"

let literal : location = loc_obj_prefix ^ "literal"
let this : location = "this"

module LocationSet = struct
module LocationSet' = Set.Make(AbstractLocation)
include LocationSet'
Expand Down

0 comments on commit 3c925ef

Please sign in to comment.