-
Notifications
You must be signed in to change notification settings - Fork 36
/
piqi_compile.ml
121 lines (94 loc) · 4.03 KB
/
piqi_compile.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
(*
Copyright 2009, 2010, 2011, 2012, 2013, 2014 Anton Lavrik
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)
(*
* common piqi compiler interfaces used by "piqi compile" and piqic-ocaml
*)
module C = Piqi_common
open C
let flag_strict = ref false
let arg__strict =
let (name, _setter, descr) = Piqi_command.arg__strict in
(* override the original setter but keep the option name and the description;
* we do this, because although it means the same, it is applied at a later
* stage -- we control it manually below *)
(name, Arg.Set flag_strict, descr)
let getopt_speclist = Piqi_command.common_speclist @
[
arg__strict;
Piqi_command.arg__include_extension;
]
let load_self_spec ?(filename="") buf =
trace "piqi_compile: loading self-spec from %s\n" (U.quote filename);
trace_enter ();
let self_spec =
try
(* TODO: we can read piqi directly using Piqi_piqi.parse_piqi, because
* self-spec is guaranteed to not have any incompatibilities with
* piqi_lang including functions and other parts. This makes "piqi
* compile" start faster than if we used "Piqi.piqi_of_pb buf" *)
Piqi.piqi_of_pb buf (* NOTE: not caching the loaded module *)
with exn ->
Printf.eprintf "error: failed to load self-spec from %s:\n" (U.quote filename);
raise exn (* try to give more details about what when wrong *)
in
trace_leave ();
self_spec
let get_self_spec_piqtype ?(filename="") self_spec typename =
let piqi_def =
try Piqi_db.find_local_typedef self_spec.P.resolved_typedef typename
with Not_found ->
Printf.eprintf
"invalid self-spec read from %s: no definition named %s\n"
(U.quote filename) (U.quote typename);
piqi_error "piqi compile: invalid self-spec"
in
(piqi_def: T.typedef :> T.piqtype)
(* make piqi/piqi-list top-level record from the list of piqi piqobjs *)
let make_piqi_list_piqobj piqi_list_piqtype (piqi_piqobj_list: Piqobj.obj list) :Piqobj.obj =
let r =
match piqi_list_piqtype with
| `record r -> r
| _ -> assert false
in
(* the first and the only record field should correspond to the piqi type *)
let f = List.hd r.R.field in
let fields = List.map (fun x -> Piqobj.Field.({t = f; obj = Some x})) piqi_piqobj_list in
let record = Piqobj.Record.({t = r; field = fields; unparsed_piq_fields_ref = None}) in
`record record
(* public library API; currently called only from Piqic_ocaml *)
let compile ?(extensions=[]) self_spec_bin ifile =
trace "compile_to_pb:\n";
trace_enter ();
(* TODO: restore the state after we are done *)
List.iter (fun e -> Piqi_config.add_include_extension e) extensions;
let buf = Piqi_piqirun.init_from_string self_spec_bin in
let self_spec = load_self_spec buf in
let ch = Piqi_command.open_input ifile in
let piqi = Piqi.load_piqi ifile ch in
trace "getting all imported dependencies\n";
let piqi_list = Piqi.get_piqi_deps piqi in
(* get necessary piqtypes from the self-spec *)
let piqi_piqtype = get_self_spec_piqtype self_spec "piqi" in
let piqi_list_piqtype = get_self_spec_piqtype self_spec "piqi-list" in
trace "converting modules to internal representation\n";
Config.flag_strict := !flag_strict;
(* convert all modules to internal representation *)
let piqobj_list = List.map
(fun piqi -> Piqi.piqi_to_piqobj piqi ~piqi_piqtype ~add_codes:true)
piqi_list
in
trace "generating pb\n";
let piqobj = make_piqi_list_piqobj piqi_list_piqtype piqobj_list in
let res = Piqi_convert.to_pb_string (Piqi_convert.Piqobj piqobj) in
trace_leave ();
res