Further code generation ** NOT WORKING **
[virt-mem.git] / extract / codegen / code_generation.ml
1 (* Memory info command for virtual domains.
2    (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc.
3    http://libvirt.org/
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *)
19
20 open Camlp4.PreCast
21 open Syntax
22 (*open Ast*)
23
24 open ExtList
25 open ExtString
26 open Printf
27
28 module PP = Pahole_parser
29 module SC = Struct_classify
30
31 (* We don't care about locations when generating code, so it's
32  * useful to just have a single global _loc.
33  *)
34 let _loc = Loc.ghost
35
36 (* Some handy camlp4 construction functions which do some
37  * things that ought to be easy/obvious but aren't.
38  *
39  * 'concat_str_items' concatenates a list of str_item together into
40  * one big str_item.
41  *
42  * 'concat_record_fields' concatenates a list of records fields into
43  * a record.  The list must have at least one element.
44  *
45  * 'build_record' builds a record out of record fields.
46  * 
47  * 'build_tuple_from_exprs' builds an arbitrary length tuple from
48  * a list of expressions of length >= 2.
49  *
50  * Thanks to bluestorm on #ocaml for getting these working.
51  *)
52 let concat_str_items items =
53   match items with
54   | [] -> <:str_item< >>
55   | x :: xs ->
56       List.fold_left (fun xs x -> <:str_item< $xs$ $x$ >>) x xs
57
58 let concat_sig_items items =
59   match items with
60   | [] -> <:sig_item< >>
61   | x :: xs ->
62       List.fold_left (fun xs x -> <:sig_item< $xs$ $x$ >>) x xs
63
64 let concat_record_fields fields =
65   match fields with
66     | [] -> assert false
67     | f :: fs ->
68         List.fold_left (fun fs f -> <:ctyp< $fs$ ; $f$ >>) f fs
69
70 let concat_record_bindings rbs =
71   match rbs with
72     | [] -> assert false
73     | rb :: rbs ->
74         List.fold_left (fun rbs rb -> <:rec_binding< $rbs$ ; $rb$ >>) rb rbs
75
76 let build_record rbs =
77   Ast.ExRec (_loc, rbs, Ast.ExNil _loc)
78
79 let build_tuple_from_exprs exprs =
80   match exprs with
81   | [] | [_] -> assert false
82   | x :: xs ->
83       Ast.ExTup (_loc,
84                  List.fold_left (fun xs x -> Ast.ExCom (_loc, x, xs)) x xs)
85
86 let ocaml_type_of_field_type = function
87   | PP.FInteger -> <:ctyp< int64 >>
88   | PP.FString _ -> <:ctyp< string >>
89   | PP.FStructPointer _ | PP.FVoidPointer
90   | PP.FAnonListHeadPointer | PP.FListHeadPointer _ ->
91       <:ctyp< Virt_mem_mmap.addr >>
92
93 let generate_types xs =
94   let strs = List.map (
95     fun (struct_name, sflist, cflist) ->
96       let sflist = List.map (
97         fun { SC.sf_name = name; sf_fields = fields } ->
98           if fields <> [] then (
99             let fields = List.map (
100               fun { PP.field_name = name; PP.field_type = t } ->
101                 let t = ocaml_type_of_field_type t in
102                 <:ctyp< $lid:name$ : $t$ >>
103             ) fields in
104             let fields = concat_record_fields fields in
105
106             <:str_item<
107               type $lid:name$ = { $fields$ }
108             >>
109           ) else
110             <:str_item< type $lid:name$ = unit >>
111       ) sflist in
112       let sflist = concat_str_items sflist in
113
114       let cflist = List.map (
115         fun { SC.cf_name = name; cf_fields = fields } ->
116           if fields <> [] then (
117             let fields = List.map (
118               fun { PP.field_name = name; PP.field_type = t } ->
119                 let t = ocaml_type_of_field_type t in
120                 <:ctyp< $lid:name$ : $t$ >>
121             ) fields in
122             let fields = concat_record_fields fields in
123
124             <:str_item<
125               type $lid:name$ = { $fields$ }
126             >>
127           ) else
128             <:str_item< type $lid:name$ = unit >>
129       ) cflist in
130       let cflist = concat_str_items cflist in
131
132       <:str_item<
133         type ('a, 'b) $lid:struct_name$ = {
134           $lid:struct_name^"_shape"$ : 'a;
135           $lid:struct_name^"_content"$ : 'b;
136         }
137         $sflist$
138         $cflist$
139       >>
140   ) xs in
141
142   let sigs =
143     List.map (
144       fun (struct_name, _, _) ->
145         <:sig_item<
146           type ('a, 'b) $lid:struct_name$
147         >>
148     ) xs in
149
150   concat_str_items strs, concat_sig_items sigs
151
152 let output_interf ~output_file types =
153   let sigs = concat_sig_items [ types ] in
154   Printers.OCaml.print_interf ~output_file sigs
155
156 let output_implem ~output_file types =
157   let strs = concat_str_items [ types ] in
158   Printers.OCaml.print_implem ~output_file strs