Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 460 lines (365 sloc) 11.699 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 (**
20 Complete QmlFlat Server-side library.
21
22 Implementation of server-side operations for the QmlFlat compiler.
23
24 @author Mathieu Barbin
25 @author David Rajchenbach-Teller
26 @author Esther Baruk (modifications)
27 *)
28
29 (**
30 Runtime error on server due to a type error.
31 Such an exception can possibly escape this module.
32 A runtimerror happens never alone, a message has been printed
33 on stderr before raising the exception.
34 *)
35 exception RuntimeError
36
37 (** Print a message and raise exception [RuntimeError]. *)
38 val runtime_error : string -> 'a
39
40
41 (** {6 Field} *)
42
43 (**
44 Field are shared strings.
45 *)
46
47 module Field :
48 sig
49 (**
50 An opaque type for fields
51 *)
52 type t
53
54 (**
55 Physicall identity.
56 *)
57 val equal : t -> t -> bool
58
59 (**
60 Returns -1, 0 or 1
61 *)
62 val compare : t -> t -> int
63
64 (**
65 Returns true if and only if a < b.
66 More effecient than compare.
67 *)
68 val lt : t -> t -> bool
69
70 (**
71 Returns true if and only if a > b
72 More effecient than compare.
73 *)
74 val gt : t -> t -> bool
75
76 (**
77 Side effect on a private Hashtbl.
78 Beware, we are trusting the input string for efficiency
79 purpose. Do not corrupt it !!
80 *)
81 val register : string -> t
82
83 (**
84 Without side effect.
85 *)
86 val field_of_name : string -> t option
87 val name_of_field : t -> string option
88
89 (**
90 <!> Beware, we are giving you the shared field.
91 Do not perform side effect on the name.
92 (if we get scared, we can return a copy)
93 *)
94 external name : t -> string = "%identity"
95 end
96
97 (*
98 (**
99 Return the name of a field. Used for error reporting.
100
101 If this function returns [None], you are in trouble because
102 this means that your field does not exist.
103 *)
104 val name_of_field: field -> string option
105
106 (**
107 Declare a new field, and store it in the global table.
108 After a call to :
109 {[
110 let field = declare_field "field"
111 ]}
112 any call to [name_of_field field] returns Some "field"
113 *)
114 val register_field : string -> field
115 val register_fields : string list -> unit
116
117 *)
118
119 (** {6 Field Access} *)
120
121 module FieldAccess :
122 sig
123 (**
124 An opaque information which may be used
125 to accelerate several consecutive searches,
126 provided that you have ordered your searches by increasing [field].
127 *)
128 type t
129
130 (**
131 An opaque type for cache field_access
132 Value of this type are mutable and modified when searching fields
133 This type was also called hint in the code and function names
134 *)
135 type cache
136
137 (**
138 A safe value for [field_access] which you can use to initialize e.g. caches.
139 *)
140 val default : t
141 val start_from : t
142 val make_cache : unit -> cache
143 end
144
145 (** {6 VTable} *)
146
147 (**
148 A virtual table is a sorted array of field.
149 So that the stability of the sorted property can be
150 ensured by typing, the type is private.
151 Check related to this property are limited to a few constructors.
152 *)
153
154 module VTable :
155 sig
156 (**
157 An opaque type for each vtable of record.
158 *)
159 type t
160
161 (**
162 Create a vtable. The array should be sorted by [Field.compare].
163 Unicity of fields is required in a vtable.
164
165 [vtable] are shared between records, this is an invariant.
166 There is a runtime cache of vtables, based on string array hashing.
167
168 In the llvm compiler, the structure is an index in a vtable map.
169 In the flat, this is a [vtable].
170 *)
171 val register : string array -> t
172
173 (**
174 Dynamically, you may use to allow the creation of new VTable,
175 by using [register], or not, by using [shared], which return
176 [None] if no such VTable was already known.
177 *)
178 val shared : string array -> t option
179
180 (**
181 <!> Do not corrupt the vtable.
182 *)
183 external export : t -> Field.t array = "%identity"
184
185 (**
186 Safe function which does not segfault on any object.
187 Tell if the object is a vtable
188 *)
189 val check : Obj.t -> bool
190 end
191
192 (** {6 Records} *)
193
194 (**
195 1) Complex records:
196
197 The contents of a complex record.
198 It contains :
199 - as first element : the vtable
200 - as second element : a prospective information
201 - as remaining elements : the record values.
202 You must be absolutely certain that the values are {e not packed}.
203 This representation causes no more problems with floats because the first element
204 of the array is a field array (the vtable).
205
206 About lazy values :
207 We don't consider it because lazy and non-lazy values are the same at runtime, encapsulated
208 in a value of type Obj.t.
209
210 2) Empty record
211
212 This is a complex record, with a empty vtable.
213 We ensure that the value empty is shared. This is an invariant.
214
215 3) Simple record
216
217 Record with one uniq field of type void are optimized, and represented directly by the field.
218 *)
219 type flat_record = Obj.t array
220
221 module Complex :
222 sig
223 type t
224
225 (** {6 Getters} *)
226
227 val get_value : int -> t -> 'a
228 val get_info : t -> Obj.t
229 external get_vtable : t -> VTable.t = "%field0"
230
231 (** {6 Constructors} *)
232
233 (**
234 Initialize a complex record with a set of already evaluated field values
235 *)
236 external init_from_evaluated : flat_record -> t = "%identity"
237
238 (** return a fresh record, sharing data *)
239 val update_info : t -> Obj.t -> t
240
241 (** side effect, modification in place *)
242 val inject_info : t -> Obj.t -> unit
243 end
244
245 type record = Complex.t (**An opaque type for records. *)
246
247 (**
248 An unwrap for matching record with arrays.
249 *)
250 external unwrap_record : record -> _ array = "%identity"
251
252 (**
253 Runtime check
254 *)
255 val is_record : Obj.t -> bool
256 val is_simple : record -> bool
257
258 (**
259 Exported for ServerLib. Probably possible to fix.
260 *)
261 val val_shift : int
262
263 val init_from_list : (Field.t * 'a) list -> record
264 (**
265 Sharing of simple record
266
267 Construct a trivial record such as [{foo}].
268
269 Performance note:
270 Two trivial records are structurally equal
271 if and only if they are physically equal.
272 This performance note is preserved thanks to the string sharing
273 ensured by the systematic use of Field, VTable, and Simple modules.
274 *)
275 module Simple :
276 sig
277 val register : string -> record
278 end
279
280 (**
281 {7 Operations on records}
282 *)
283
284 (**
285 The shared empty record.
286 *)
287 val empty : record
288 val shared_void : Obj.t
289
290 (**
291 Ignore a value, return [void], i.e. the shared empty record.
292 *)
293 val void_of_unit : unit -> record
294
295 (**
296 Return [true] if the record is empty, [false] otherwise.
297 For this purpose, check for physical equality with [empty].
298 *)
299 val is_empty : record -> bool
300
301 (**
302 Bool are shared
303 *)
304 val true_ : record
305 val false_ : record
306
307 (**
308 returns either the shared [true_] or [false_]
309 *)
310 val wrap_bool : bool -> record
311
312 (**
313 test for physically equality with [true_]
314 *)
315 val unwrap_bool : record -> bool
316
317 (**
318 Helpers for option projection.
319 *)
320
321 (**
322 none is shared
323 *)
324 val none : record
325
326 (**
327 <!> the 'a should be an opa value
328 *)
329 val some : 'a -> record
330
331 (**
332 unwrapping option
333 *)
334 val unwrap_option : record -> 'a option
335 val wrap_option : 'a option -> record
336
337 (**
338 Returns the number of fields in this record.
339 Invariant: if the number is 0, the record is the shared empty record.
340
341 If the record is empty, this is 0.
342 If the record is simple, this is 1.
343 Otherwise, this is the length of the vtable of the Complex record,
344 *)
345 val number_of_fields : record -> int
346
347 (**
348 Info attached to a complex record.
349 *)
350 type 'a info constraint 'a = [> ]
351
352 (**
353 Get the information attached to a record.
354
355 @return [None] if no information has been attached to a record, [Some x] if the record
356 has been initialized with an argument [info].
357 *)
358 val get_record_info: record -> 'a info option
359
360 (**
361 Depending on the given flat_record:
362 -return the shared empty record
363 -build a simple record
364 -build a complex record
365
366 The given record may contain lazy values.
367 <!> If your record is simple, info is ignored.
368 <!> If your record has only 1 field, and contain
369 a lazy value, it is evaluated right-away.
370 *)
371 val safe_init : flat_record -> record
372
373 (**
374 Optimized version for potential simple record.
375 Called with an array of size 3 (1 data only).
376 If the data is empty, this build a shared simple record
377 if not, keep the record as is. (the vtable should be the
378 correct shared one)
379 *)
380 val may_be_simple : flat_record -> record
381
382 (**
383 Initialize a record with a given array containing a array of fields [vtable], an additional information
384 [info] (see below) and a sequence of values.
385
386 The arguments need to respect the following:
387 - the order of fields in [vtable] {e must} match the order of values
388 - the fields of [vtable] {e must} be sorted by increasing order
389 - there {e must} be no duplicate field in [vtable]
390 - you {e must} never overwrite [vtable] or the values yourself
391 - values {e must} spread from index 2 to the end of the array
392 - if you are using [unsafe_init_lazy], the record {e must} be something that does not
393 evaluate to the empty record or to a record of size 1 with one field of type [void].
394 - if you are using [unsafe_init_lazy], the evaluation function {e must} never raise an
395 exception.
396
397 In addition:
398 - [vtable] should necessarly be shared between records with the same vtable, so
399 as to limit memory usage and improve cache-consistency.
400
401 This initialization is in O(1).
402
403 Initialization can be either eager, with [unsafe_init], or lazy, with [unsafe_init_lazy].
404
405 Additional information [info] for special-purpose records can be provided as option value at
406 index 1. This information may be recovered by [get_record_info] but may also lost by record extension.
407
408 This function must stay external and be a call to identity, else it blows up compilation time with
409 ocamlopt.opt.
410 *)
411
412 external unsafe_init_static : flat_record -> record = "%identity"
413
414 (**
415 Extend a record with some other fields * value.
416 [extend a b] adds all the fields of [b] to [a].
417 If a field appears both in [a] and [b], the value
418 of [b] is kept.
419 The array given as extension should be sorted by field, and field
420 should be uniq in this array.
421 *)
422 val extend_with_array : record -> (Field.t * Obj.t) array -> record
423
424 (**
425 Access a given field in a record.
426 Behavior is unspecified if the record doesn't have this field.
427 *)
428 val dot : Field.t -> record -> 'a
429
430 (**
431 As [dot] but returns [Some x] in case of success,
432 [None] in case of failure.
433 *)
434 val dot_opt : Field.t -> record -> 'a option
435
436 (**
437 The following behave as [search_field] et al,
438 except they also take as argument a cache, which
439 hopefully contains the index of the field in the record.
440 If the cache value doesn't point to the index, it is simply discarded,
441 and updated for the next search
442 *)
443
444 val dot_with_cache :
445 FieldAccess.cache -> Field.t -> record -> 'a
446
447 (**
448 [unsafe_get n r] returns the value of the [n]th field of record [r].
449 The record should be valid.
450 The index is the index of the vtable, starting from 0.
451 *)
452 val unsafe_get : int -> record -> 'a
453
454 (** {6 Compiler Interface} *)
455
456 (**
457 CF module Flat_Common.FlatServerLib, which reproduces the hieararchy
458 of primitives, for code generation.
459 *)
Something went wrong with that request. Please try again.