summaryrefslogtreecommitdiffstats
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/lazy.ml37
-rw-r--r--stdlib/obj.ml4
-rw-r--r--stdlib/obj.mli3
3 files changed, 30 insertions, 14 deletions
diff --git a/stdlib/lazy.ml b/stdlib/lazy.ml
index 2af10859e..84158b257 100644
--- a/stdlib/lazy.ml
+++ b/stdlib/lazy.ml
@@ -30,11 +30,16 @@
type [unit -> 'a] that computes the value.
2. A block of size 1 with tag [forward_tag]. Its field is the value
of type ['a] that was computed.
- 3. Anything else. This has type ['a] and is the value that was computed.
+ 3. Anything else except a float. This has type ['a] and is the value
+ that was computed.
Exceptions are stored in format (1).
The GC will magically change things from (2) to (3) according to its
fancy.
+ We cannot use representation (3) for a [float Lazy.t] because
+ [make_array] assumes that only a [float] value can have tag
+ [Double_tag].
+
We have to use the built-in type constructor [lazy_t] to
let the compiler implement the special typing and compilation
rules for the [lazy] keyword.
@@ -45,21 +50,21 @@ exception Undefined;;
let raise_undefined = Obj.repr (fun () -> raise Undefined);;
-external is_forward : Obj.t -> bool = "lazy_is_forward";;
external follow_forward : Obj.t -> 'a = "lazy_follow_forward";;
+external make_forward : 'a -> 'a lazy_t = "lazy_make_forward";;
let force (l : 'arg t) =
let x = Obj.repr l in
- if is_forward x then (follow_forward x : 'arg)
- else if Obj.is_int x then (Obj.obj x : 'arg)
- else if Obj.tag x <> Obj.lazy_tag then (Obj.obj x : 'arg)
+ let t = Obj.tag x in
+ if t = Obj.forward_tag then (follow_forward x : 'arg)
+ else if t <> Obj.lazy_tag then (Obj.obj x : 'arg)
else begin
let closure = (Obj.obj (Obj.field x 0) : unit -> 'arg) in
Obj.set_field x 0 raise_undefined;
try
let result = closure () in
Obj.set_field x 0 (Obj.repr result); (* do set_field BEFORE set_tag *)
- Obj.set_tag x (Obj.forward_tag);
+ Obj.set_tag x Obj.forward_tag;
result
with e ->
Obj.set_field x 0 (Obj.repr (fun () -> raise e));
@@ -69,9 +74,9 @@ let force (l : 'arg t) =
let force_val (l : 'arg t) =
let x = Obj.repr l in
- if is_forward x then (follow_forward x : 'arg)
- else if Obj.is_int x then (Obj.obj x : 'arg)
- else if Obj.tag x <> Obj.lazy_tag then (Obj.obj x : 'arg)
+ let t = Obj.tag x in
+ if t = Obj.forward_tag then (follow_forward x : 'arg)
+ else if t <> Obj.lazy_tag then (Obj.obj x : 'arg)
else begin
let closure = (Obj.obj (Obj.field x 0) : unit -> 'arg) in
Obj.set_field x 0 raise_undefined;
@@ -88,9 +93,13 @@ let lazy_from_fun (f : unit -> 'arg) =
(Obj.obj x : 'arg t)
;;
-let lazy_from_val (v : 'arg) = (Obj.magic v : 'arg t);;
-
-let lazy_is_val (l : 'arg t) =
- let x = Obj.repr l in
- is_forward x || Obj.is_int x || Obj.tag x <> Obj.lazy_tag
+let lazy_from_val (v : 'arg) =
+ let t = Obj.tag (Obj.repr v) in
+ if t = Obj.forward_tag || t = Obj.lazy_tag || t = Obj.double_tag then begin
+ make_forward v
+ end else begin
+ (Obj.magic v : 'arg t)
+ end
;;
+
+let lazy_is_val (l : 'arg t) = Obj.tag (Obj.repr l) <> Obj.lazy_tag;;
diff --git a/stdlib/obj.ml b/stdlib/obj.ml
index 42df136f7..94e2e711d 100644
--- a/stdlib/obj.ml
+++ b/stdlib/obj.ml
@@ -50,3 +50,7 @@ let double_tag = 253
let double_array_tag = 254
let custom_tag = 255
let final_tag = custom_tag
+
+
+let int_tag = 1000
+let out_of_heap_tag = 1001
diff --git a/stdlib/obj.mli b/stdlib/obj.mli
index 68670f51d..dd0a667aa 100644
--- a/stdlib/obj.mli
+++ b/stdlib/obj.mli
@@ -47,6 +47,9 @@ val double_array_tag : int
val custom_tag : int
val final_tag : int (* DEPRECATED *)
+val int_tag : int
+val out_of_heap_tag : int
+
(** The following two functions are deprecated. Use module {!Marshal}
instead. *)