Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 292 lines (252 sloc) 10.653 kb
fccc685 Initial open-source release
MLstate authored
1 (*
2 Copyright © 2011 MLstate
3
4 This file is part of OPA.
5
6 OPA is free software: you can redistribute it and/or modify it under the
7 terms of the GNU Affero General Public License, version 3, as published by
8 the Free Software Foundation.
9
10 OPA is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
13 more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with OPA. If not, see <http://www.gnu.org/licenses/>.
17 *)
18 (* TODOK1 - Documents pre and post condition*)
19 (** Resolve slicer directives by stubs and skeletons.
20
21 {6 Resolving directive}
22 This module provides 2 main functions, for transform server and
23 client code. Both functions have the same behavior for resolve
24 directives. We have 3 types of directives where functions works :
25
26 - [publish_directive] : Resolved by skeleton generation and by
27 registration of this in a rpc dispatcher.
28
29 - [call_directive] : Resolved by stub generation and by
30 replacement of the call_directive by the ident of generated
31 stub. Of course stubs are shared. For example if in code we have
32 several @*_call(toto) we generate only one toto_stub.
33
34 - [insert_directive] : This directive have a sense only on client
35 side. It's resolved by generation of a new directive for the
36 client code compiler. This directive is [\@hybrid_value] and it
37 contains two expressions. First of them is a client expression,
38 this expression is type [string -> 'a]. Second is a expression that
39 must be computed on server, and this expression is a [string].
40
41
42 {9 Skeleton generation}
43
44 Skeleton maybe generated for functional value, or non-functional
45 value. Generated skeletons get only one arguments, it's a
46 [string]. This arguments represents the serialized request. This
47 request should be contains all arguments of the functions (or any
48 if it's a skeleton for value). And should contains for all type
49 variable (in type of this function) an type argument (or any if
50 it's a skeleton for value). After several verification on request,
51 it call a non optimized (for explicit instantiation) function.
52 Finally it serialize the result.
53
54 A generic example (in Opa Style) :
55 {[
56 fun str ->
57 match OpaRPC.unserialize str with
58 | {some = request} ->
59 (match OpaRPC.extract_type request with
60 | [i1; i2; ...] ->
61 (match OpaTsc.implementation [i1; i2; ...] tsc with
62 | { TyArrow_params = [t1; t2; t3; ...]; TyArrow_res = tres } ->
63 (match OpaRPC.extract_value [t1; t2; t3; ...] request with
64 | { some = [a1; a2; a3; ...] } ->
65 { some = OpaValue.serialize tres
66 (sliced_fun i1 i2 ... a1 a2 a3 ...) }
67 | _ -> { none = () })
68 | _ -> { none = () })
69 | _ -> { none = () })
70 | _ -> { none = () }
71 : string -> string option
72 ]}
73
74 An concret example : skeleton for toto of type [list('a) -> int ->
75 option('a)]
76 {[
77 val tsc = {
78 quantifier = [{TyVar = "'a"}];
79 body = {TyArrow_params = [list('a); int];
80 TyArrow_res = option('a)}
81 }
82 fun str ->
83 match OpaRPC.unserialize str with
84 | {some = request} ->
85 (match OpaRPC.extract_type request with
86 | [i1] ->
87 (match OpaTYpe.instantiate [i1] tsc with
88 | { TyArrow_params = [t1; t2]; TyArrow_res = tres } ->
89 (match OpaRPC.extract_value [t1; t2] request with
90 | { some = [a1; a2] } ->
91 { some = OpaValue.serialize tres (toto_exp i1 a1 a2) }
92 | _ -> { none = () })
93 | _ -> { none = () })
94 | _ -> { none = () })
95 | _ -> { none = () }
96 : string -> string option
97 ]}
98
99 For conclusion, generated skeleton make :
100 - Unserialize RPC request represented by argument of the
101 skeleton.
102 - Extract instantiate types include in request (if original type
103 scheme have type variable).
104 - Extract value and check with instantiate type of function.
105 - Call to the function with type arguments and values.
106 - Serialize the response.
107
108 {9 Stub generation}
109 Generated stub is just a function that make a correct request for
110 the correspondig skeleton, and execute a distant call to the other
111 side. For finish it check response.
112
113 A generic example (in Opa Style) :
114 {[
115 fun i1 -> fun i2 -> ... ->
116 fun a1 -> fun a2 -> fun a3 ->
117 match OpaTsc.implementation [i1; i2; ...] tsc /*type scheme of the function*/ with
118 | { TyArrow_params = [t1; t2; t3; ...]; TyArrow_res = tres } } ->
119 match
120 send_to_<side>
121 "<function_id>"
122 (OpaRPC.serialize
123 (OpaRPC.add_args t3 a3
124 (OpaRPC.add_args t2 a2
125 (OpaRPC.add_args t1 a1
126 (OpaRPC.add_var_types i2
127 (OpaRPC.add_var_types i1 OpaRPC.empty_request))))))
128 tres
129 with
130 | { some = res } -> res
131 | _ -> /* Make an error */
132 | _ -> /* Make an error */
133 ]}
134
135 A concret example : stub for toto of type [list('a) -> int ->
136 option('a)]
137 {[
138 val tsc = {
139 quantifier = [{TyVar = "'a"}];
140 body = {TyArrow_params = [list('a); int];
141 TyArrow_res = option('a)}
142 }
143 fun t1 -> fun a1 -> fun a2 ->
144 match OpaTsc.implementation [i1] tsc with
145 | { TyArrow_params = [t1; t2]; TyArrow_res = tres } } ->
146 match
147 send_to_<side>
148 "<function_id>"
149 (OpaRPC.serialize
150 (OpaRPC.add_args t2 a2
151 (OpaRPC.add_args t1 a1
152 (OpaRPC.add_var_types i1 OpaRPC.empty_request))))
153 tres
154 with
155 | { some = res } -> res
156 | _ -> /* Make an error */
157 | _ -> /* Make an error */
158 ]}
159
160 For conclusion, generated skeleton make :
161 - Instantiate type scheme
162 - Match the instantiated type scheme
163 - Add instantiate type variable of the function to an empty
164 request. (Type given at runtime, like exp-inst).
165 - Add argument (with here type) to request
166 - Send serialized request, and check returned value with tres.
167
168 {9 Pre-conditions}
169
170 {9 Post-conditions}
171
172 - All generated stubs, skeletons (and registration of skeletons) are
173 added on the code, but it's not guaranteed that the code is well
174 ordered.
175
176 - Code is already typed.
177
178 - Doesn't break lambda lifting.
179
180 @author Quentin Bourgerie
181 *)
182
183 (** Check if expression on hybrid_value is well formed. *)
184 val check_hybrid_value :
185 QmlAst.annotmap -> QmlAst.expr -> QmlAst.expr -> bool
186
187 (**{6 Main functions} *)
188 (** Options for main functions. That contains levels of
189 optimizations :
190 [optimize_insert] :
191 - 0 : No optimizations. Server value is fully serialize
192 and fully unserialize on client.
193 - 1 : Server values are inserted with their back-end
194 representations. No unserialization on client.
195 [optimize_publish] :
196 - 0 : No optimizations.
197 - 1 : Use factorized skeletons.
198 [optimize_stub] :
199 - 0 : No optimizations.
200 *)
201 type options = {
202 optimize_insert : int;
203 optimize_publish : int;
204 optimize_call : int;
205 }
206
207 (** Default options (0,0,0) *)
208 val default_options : options
209
210 val prelude : gamma:QmlTypes.gamma -> annotmap:QmlAst.annotmap -> QmlAst.code -> QmlAst.code -> unit
211 val postlude : QmlRenamingMap.t -> QmlRenamingMap.t -> QmlRenamingMap.t * QmlRenamingMap.t
212 val need_to_process_code : QmlAst.code -> QmlAst.code -> bool
213
214 (** Work on server code. Resolve :
215
216 [\@ajax_publish] :
217 - Generate server skeletons for catch RPC request.
218 - Register generated skeletons on a dispatcher for RPC request.
219
220 [\@comet_call] : Like [\@ajax_call] (see :
221 perform_on_client_code), but for server side.
222
223 [perform_on_sever_code ~annotmap ~gamma expmap_server
224 expmap_client renaming_server renaming_client code] Perform
225 transformations on server code.
226 [exmap_sever] It's a map which contains non-optimized server
227 functions in view of explicit instantiation
228 [exmap_client] It's a map which contains non-optimized client
229 functions in view of explicit instantiation
230 [renaming_server] It's the renaming map of server, this map it's
231 updated
232 [renaming_client] It's the renaming map of client.
233 [code] The server code
234 *)
235 val perform_on_server_code :
236 ?options:options ->
237 annotmap:QmlAst.annotmap ->
238 stdlib_gamma:QmlTypes.gamma ->
239 gamma:QmlTypes.gamma ->
240 Pass_ExplicitInstantiation.published_map ->
241 Pass_ExplicitInstantiation.published_map ->
242 QmlRenamingMap.t -> QmlRenamingMap.t ->
243 QmlAst.code ->
244 QmlAst.annotmap * QmlTypes.gamma * QmlAst.code * QmlAst.code
245
246 (** Work on client code. Resolve :
247
248 [\@ajax_call] :
249 - Generate client stubs for send a RPC request on server, and
250 catch result.
251 - Replace call of remote functions by call of generated stubs.
252
253 [\@comet_publish] :
254 - Like [\@ajax_publish] (see : perform_on_server_code), but for client side.
255
256 [\@insert_server_value] :
257 - Replace by a directive [\@hybrid_value] for qmljs. More info, see
258 [QmlAst.qml_directive].
259
260 [perform_on_sever_code ~annotmap ~gamma expmap_client
261 expmap_server code] Perform transformations on client code.
262 [exmap_client] It's a map which contains non-optimized client
263 functions in view of explicit instantiation
264 [exmap_sever] It's a map which contains non-optimized server
265 functions in view of explicit instantiation
266 [renaming_client] It's the renaming map of client, this map it's
267 updated
268 [renaming_server] It's the renaming map of server.
269 [code] The client code
270
271 *)
272 val perform_on_client_code :
273 ?options:options ->
274 annotmap:QmlAst.annotmap ->
275 stdlib_gamma:QmlTypes.gamma ->
276 gamma:QmlTypes.gamma ->
277 Pass_ExplicitInstantiation.published_map ->
278 Pass_ExplicitInstantiation.published_map ->
279 QmlRenamingMap.t -> QmlRenamingMap.t ->
280 QmlAst.code ->
281 QmlAst.annotmap * QmlTypes.gamma * QmlAst.code * QmlAst.code
282
283 (**
284 Saving and loading of explicit maps across compilation units
285 *)
286 module R2 :
287 sig
288 val save : side:[`client|`server] -> QmlAst.annotmap -> Pass_ExplicitInstantiation.published_map -> unit
289 val load : side:[`client|`server] -> QmlAst.annotmap -> Pass_ExplicitInstantiation.published_map ->
290 QmlAst.annotmap * Pass_ExplicitInstantiation.published_map
291 end
Something went wrong with that request. Please try again.