Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 352 lines (263 sloc) 11.959 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 (**
19 Standard interface for back-end specific low_level operations.
20 *)
21
22 (**
23
24 {6 General documentation}
25
26 This is the standard interface for low-level operations that all backends
27 must provide.
28
29 It is intended to be used by the primitives of any BSL implementations.
30
31 This is a server lib, meaning that it is used \@runtime.
32 It is not included in libbsl, neither used \@compiletime
33
34 Currently, we have 3 implementations of this interface :
35 + qmltop
36 + qmlflat
37 + qmlfake
38
39 The BSL are compiled as library with just a mli called {b serverLib.mli}
40 containing just an [include BslServerLib.S].
41
42 At link time, we provide the corresponding implementation.
43 <!> this is a tricky and fragile point of our build-system.
44
45
46 {6 Explicit Projection}
47
48 For projecting complex data type in an external primitive for buildint a plugin,
49 you'll need to manipuate explicitely some projection helpers.
50 Cf the functor BslServerLibProjection.
51 *)
52
53 module type S = sig
54
55 (* ------------------------------------------------------------ *)
56 (**{6 Basic operations} *)
57 (* ------------------------------------------------------------ *)
58
59 (**
60 Compare specification.
61 For non record, Pervasives.compare
62 For records:
63 lexicographic on present fields.
64 in case of equality of vtables,
65 lexicographic on attached values.
66 e.g.
67 {[
68 { z = "yop" ; x = 0 } > { x = 42 ; y }
69 ]}
70
71 Simple record are handled correctly, as they were not optimized.
72 *)
73 val compare : 'a -> 'a -> int
74
75 (* ------------------------------------------------------------ *)
76 (**{6 Lazy records handling} *)
77 (* ------------------------------------------------------------ *)
78
79 (** The type of records *)
80 type ty_record
81
82 (** The type of embedded information *)
83 type 'a ty_info = [> ] as 'a
84
85 (** Place-holder value. Must be extensible (eg with lazy info) *)
86 val empty_record : ty_record
87
88 (** Returns [true] if the given record has embedded lazy-db-record data *)
89 val has_lazy_data : ty_record -> bool
90
91 (** Returns the embedded lazy-db-record value if any *)
92 val get_lazy_data_opt : ty_record -> ('a ty_info) option
93
94 (** Embeds the given data in a record if Some. With None, clears that data *)
95 val embed_lazy_data : ty_record -> ('a ty_info) option -> ty_record
96
97 (**
98 Embeds the given data (or clears if None) in a record as a side-effect
99 <!> with the flat compiler, that has no effect on simple record
100 *)
101 val inject_lazy_data : ty_record -> ('a ty_info) option -> unit
102
103 (* ------------------------------------------------------------ *)
104 (**{6 Manipulate records} *)
105 (* ------------------------------------------------------------ *)
106 (** The type of fields of records*)
107
108 type field
109
110 (** comparison between fields *)
111 val compare_field : field -> field -> int
112
113 (** Type of a value suitable to find the field_index, see val fields_indexes *)
114 type fields_indexes
115
116 (** Type of a field index, that can provide fast field access content, see vals dot_with_field_index and field_index *)
117 type field_index
118
119 (** Indexed field record, see val patterns_indexes *)
120 type patterns_indexes
121
122 (** Get a fields_indexes *)
123 val fields_indexes : field array -> fields_indexes
124
125 (** Get a field_index, can raise an exception if not existing in fields_indexes
126 e.g. can be used to describe any set of fields (record fields in a value or a pattern) *)
127 val field_index : fields_indexes -> field -> field_index
128
129 (** Access the field corresponding to a field index,
130 raise a runtime exception if the field_index is invalid
131 does not need to work with empty record *)
132 val dot_with_field_index : ty_record -> field_index -> 'a
133
134 (** index a sequence of record field set (like a pattern) to retrieve fastly the corresponding index given a record
135 e.g. can be used to implements construct fast pattern matching at runtime *)
136 val patterns_indexes : fields_indexes array -> patterns_indexes
137
138 (** comparison between record structure,
139 !!! has no obligation to work for empty record on purpose (speed) !!!
140 if the returned integer is -2 or -1 it is a comparison otherwise it is the index
141 generate a runtime error both record form are not in pattern_index
142 if one record only is in the pattern_index it is considered bigger than the other *)
143 val compare_structure : patterns_indexes -> ty_record -> ty_record -> int
144
145 (**
146 Fold a record. [fold_record folder record acc] parameter
147 [record] must be a record else behavior is not know (at best
148 you'll get a segfault). [folder] is a function like this :
149 [folder field value_of_field acc].
150 On lazy records, this leads to a force eval of each value.
151 *)
152 val fold_record : (field -> 'b -> 'acc -> 'acc ) -> 'a -> 'acc -> 'acc
153
154 (**
155 Fold two record. [fold_record folder record1 record2 acc]
156 parameter [record1] and [record2] must be a record and they must
157 be identical (same structure). Else behavior is not know (at
158 best you'll get a segfault). [folder] is a function like this :
159 [folder field value_of_field1 value_of_field2 acc].
160 Like [fold_record], this force eval lazy records.
161 *)
162 val fold_2_record : (field -> 'b -> 'b -> 'acc -> 'acc ) -> 'a -> 'a -> 'acc -> 'acc
163
164 (** Get the name of field. If field doesn't exists return [None] *)
165 val name_of_field : field -> string option
166
167 (** Get the field corresponding to a string. If given parameter
168 not corresponding to any record, return [None]. *)
169 val field_of_name : string -> field option
170
171 (**
172 If you write a plugin, you may want to use fields definition at toplevel.
173 This will create the field if it does not yet exists, without errors.
174 Do not use on dynamic fields, because doing so, you may potentially
175 fill the memory with untrusted input (e.g. fields names coming from a malicious client)
176
177 <!> Do never corrupt the string you use as argument of [static_field_of_name], it would
178 affect directly the shared field. (not copy of the input is done in case of a new field allocation)
179 *)
180 val static_field_of_name : string -> field
181 val static_name_of_field : field -> string
182
183
184 (* ------------------------------------------------------------ *)
185 (**{6 Construct records} *)
186 (* ------------------------------------------------------------ *)
187 (** Type used for construct a record. *)
188 type record_constructor
189
190 (** It's empty (initial) record constructor. *)
191 val empty_record_constructor : record_constructor
192
193 (** Add field and associated value to a record constructor. *)
194 val add_field : record_constructor -> field -> 'a -> record_constructor
195
196 (** Make a record from a record constructor. *)
197 val make_record : record_constructor -> ty_record
198
199 (** Make a simple record if the backend supports it, or a normal record. *)
200 val make_simple_record : field -> _
201
202 (** Get just one field of a record, if present *)
203 val dot : ty_record -> field -> 'a option
204
205 (** Assume dot would return [Some data] but optimized so that the option is never built.
206 This cause a runtime error if the field is not present. *)
207 val unsafe_dot : ty_record -> field -> 'a
208
978b7c4 @akoprow [fix] typo: occurence->occurrence, occured->occurred
akoprow authored
209 (** In sum types, sometimes you just want to check the occurrence of a field, without
fccc685 Initial open-source release
MLstate authored
210 accessing its data *)
211 val is_present : ty_record -> field -> bool
212
213 (* ------------------------------------------------------------ *)
214 (**{6 Exit functions} *)
215 (* ------------------------------------------------------------ *)
216
217 (** Specify the only function that should be run whenever exiting with do_exit
218 WARNING : it erased all previously specified function by at_exit
219 use get_exit, if you want to preserve previously specified function *)
220 val at_exit : (unit -> unit) -> unit
221
222 (** Return the last function registered by at_exit, to do composition in whatever order you want *)
223 val get_exit : unit -> (unit -> unit)
224
225 (** To exit the backend (may not really exit for testing backends,
226 e.g. qmltop) *)
227 val do_exit : int -> 'a
228
229 (* ------------------------------------------------------------ *)
230 (**{6 API for explicit utilisation of projections} *)
231 (* ------------------------------------------------------------ *)
232
233 (**
234 Low level manipulation of values.
235
236 This feature is needed for people which are manipulating radioactive
237 types and need to deal with a lot of projection between opa and the
238 backend language.
239
240 It is meant to bring more safety regarding to the interfaces of the bsl.
241
242 This is about the constructor opa[] of register directives.
243
244 {[
245 ##opa-type toto('a, 'b)
246 ##register foo : opa[float], opa[toto('a, 'b)], opa['a] -> opa[unit]
247 ]}
248 will produce the following interface
249 {[
250 type ('a, 'b) opa_toto
251 external wrap_opa_toto : ServerLib.ty_record -> ('a, 'b) opa_toto
252 external unwrap_opa_toto : ('a, 'b) opa_toto -> ServerLib.ty_record
253
254 val foo :
255 ServerLib.ty_float ->
256 ('a, 'b) opa_toto -> 'a -> ServerLib.ty_void
257 ]}
258
259 Alternative approach :
260
261 An automatisation is done by the bsl, using [CTrans].
262 The CTrans have choice to generate call to the instance of the ServerLib,
263 or generating inline code for optimization. (e.g. if the projection is
264 the identity, it does not generate anything.)
265 *)
266
267 (** {9 Constants} *)
268 (**
269 The implementation is free, it can be anything.
270 *)
271
272 (** *)
273 type ty_float
274 type ty_int
275 type ty_null
276 type ty_string
277
278 (** *)
279 val wrap_float : float -> ty_float
280 val unwrap_float : ty_float -> float
281
282 val wrap_int : int -> ty_int
283 val unwrap_int : ty_int -> int
284
285 val null : ty_null
286
287 val wrap_string : string -> ty_string
288 val unwrap_string : ty_string -> string
289
290 (**
291 In the implementation in any module implementing this interface:
292 {[
293 type ty_void = ty_record
294 type ty_bool
295 type ty_option
296 ]}
297 *)
298
299 type ty_void = ty_record
300
301 (**
302 Same than empty record.
303 wraping/unwraping is inlined in any implementation.
304 *)
305 val void : ty_void
306
307 (**
308 Booleans
309 *)
310
311 type ty_bool = ty_record
312
313 val wrap_bool : bool -> ty_bool
314 val unwrap_bool : ty_bool -> bool
315
316 val true_ : ty_bool
317 val false_ : ty_bool
318
319 (**
320 Options
321 *)
322
323 type 'a ty_option = ty_record
324 val wrap_option : 'a option -> 'a ty_option
325 val unwrap_option : 'a ty_option -> 'a option
326
327 val none : 'a ty_option
328 val some : 'a -> 'a ty_option
329
330 (** {9 Marshal} *)
331
332 (**
333 Marshaling lazy value causes runtime errors.
334 With this function, all pending lazy values contained
335 in the value.
336 Would loop on cyclic values.
337 *)
338 val deep_force_eval : 'a -> 'a
339
340 (**
341 Since the flat-v2, vtable and fields structure are shared.
342 If we use directly the module Marshal returns corrupted values.
343 We should inspect these values, and perform all the needed lookup
344 to return the same structural value, but with all shared structures.
345
346 For backend without sharing, this is the identity.
347 *)
348 val sharing_refresh : 'a -> 'a
349
350
351 end
Something went wrong with that request. Please try again.