12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273(**************************************************************************)(* *)(* OCaml *)(* *)(* Damien Doligez, projet Para, INRIA Rocquencourt *)(* *)(* Copyright 1997 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)(* Internals of forcing lazy values. *)type'at='alazy_texceptionUndefinedletraise_undefined=Obj.repr(fun()->raiseUndefined)externalmake_forward:Obj.t->Obj.t->unit="caml_obj_make_forward"(* Assume [blk] is a block with tag lazy *)letforce_lazy_block(blk:'arglazy_t)=letclosure=(Obj.obj(Obj.field(Obj.reprblk)0):unit->'arg)inObj.set_field(Obj.reprblk)0raise_undefined;tryletresult=closure()inmake_forward(Obj.reprblk)(Obj.reprresult);resultwithe->Obj.set_field(Obj.reprblk)0(Obj.repr(fun()->raisee));raisee(* Assume [blk] is a block with tag lazy *)letforce_val_lazy_block(blk:'arglazy_t)=letclosure=(Obj.obj(Obj.field(Obj.reprblk)0):unit->'arg)inObj.set_field(Obj.reprblk)0raise_undefined;letresult=closure()inmake_forward(Obj.reprblk)(Obj.reprresult);result(* [force] is not used, since [Lazy.force] is declared as a primitive
whose code inlines the tag tests of its argument, except when afl
instrumentation is turned on. *)letforce(lzv:'arglazy_t)=(* Using [Sys.opaque_identity] prevents two potential problems:
- If the value is known to have Forward_tag, then its tag could have
changed during GC, so that information must be forgotten (see GPR#713
and issue #7301)
- If the value is known to be immutable, then if the compiler
cannot prove that the last branch is not taken it will issue a
warning 59 (modification of an immutable value) *)letlzv=Sys.opaque_identitylzvinletx=Obj.reprlzvinlett=Obj.tagxinift=Obj.forward_tagthen(Obj.obj(Obj.fieldx0):'arg)elseift<>Obj.lazy_tagthen(Obj.objx:'arg)elseforce_lazy_blocklzvletforce_val(lzv:'arglazy_t)=letx=Obj.reprlzvinlett=Obj.tagxinift=Obj.forward_tagthen(Obj.obj(Obj.fieldx0):'arg)elseift<>Obj.lazy_tagthen(Obj.objx:'arg)elseforce_val_lazy_blocklzv