From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id B15687FD02 for ; Wed, 6 May 2015 11:50:15 +0200 (CEST) Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of oleg@okmij.org) identity=pra; client-ip=66.39.3.115; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="oleg@okmij.org"; x-sender="oleg@okmij.org"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of oleg@okmij.org designates 66.39.3.115 as permitted sender) identity=mailfrom; client-ip=66.39.3.115; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="oleg@okmij.org"; x-sender="oleg@okmij.org"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@www1.g3.pair.com) identity=helo; client-ip=66.39.3.115; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="oleg@okmij.org"; x-sender="postmaster@www1.g3.pair.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0AZAgAv40lVZ3MDJ0JchwrKdgKBKDwQAQEBAQEBAREUD1aEIQIEJ00FGyETIR0rFIgxxE0BAQEHAgEfizmFBQeDF4EWBYskkVgBgSSGTopzg1OENCKCdgEBAQ X-IPAS-Result: A0AZAgAv40lVZ3MDJ0JchwrKdgKBKDwQAQEBAQEBAREUD1aEIQIEJ00FGyETIR0rFIgxxE0BAQEHAgEfizmFBQeDF4EWBYskkVgBgSSGTopzg1OENCKCdgEBAQ X-IronPort-AV: E=Sophos;i="5.13,379,1427752800"; d="scan'208";a="114712032" Received: from www1.g3.pair.com ([66.39.3.115]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/ADH-AES256-SHA; 06 May 2015 11:50:14 +0200 Received: by www1.g3.pair.com (Postfix, from userid 9370) id 91063C382B; Wed, 6 May 2015 05:50:12 -0400 (EDT) From: oleg@okmij.org To: omeragacan@gmail.com CC: caml-list@inria.fr In-reply-to: Message-Id: <20150506095012.91063C382B@www1.g3.pair.com> Date: Wed, 6 May 2015 05:50:12 -0400 (EDT) Subject: Re: [Caml-list] Problems with printing MetaOCaml generated code Leo has given an excellent explanation. I merely wish to stress two subtle points, which are worth repeating. If we restrict ourselves to two stages for the sake of explanation, a cross-stage persistent identifier is the one that is bound outside the brackets but used within. What will appear in the generated code depends on whether that identifier is ``global'' or not. If it is global, the name of that identifier will appear. If it is local, MetaOCaml will try to lift the corresponding value one way or another. I should stress the special meaning of the ``global identifier''. In the discussions about CSP, a global identifier is a top-level identifier *in a different compilation unit*. Emphatically, the top-level identifier in the current compilation unit is *not* considered a global identifier. Therefore, if you write let foo = fun x -> x .. you will see the CSP - : int code = .<(* CSP foo *) 1>. rather than the expected ... The reason top-level identifiers in the current module are not considered global is because they may be re-defined -- even at a different type. For example, the above program may continue with let foo = true If the generated code were .., which particular foo it would refer to? BTW, the global references generated by OCaml proper (which one may refer too) do not have disambiguating timestamps. If you examine the object file generated by OCaml, you will see just 'foo'. MetaOCaml-specific processing is done definition-by-definition. When MetaOCaml typechecker sees 'foo', it has no knowledge if that identifier will be later redefined. Suppose the identifier x is not global, and and it appears within brackets, for example . x>. You can read this expression as if it were . .~(lift_it x)>. where 'lift_it' is one of the lifting function that MetaOCaml chooses for you. For example, if x is of the type int, then lift_it is essentially string_of_int. If x is not one of the few types MetaOCaml knows a priori how to lift (or if x is polymorphic and so its exact type cannot be determined), then lift_it is chosen to be a dynquote, a function that examines the run-time representation of the value and tries to do something intelligent. Since the type information is erased by that time (or was not available to start with, if x was polymorphic), we cannot distinguish the integer 0 from None from [] or from the first 0-ary constructor of any data type. All of them are represented internally as 0. That's why you see Obj.magic 0 in the generated code. Of course MetaOCaml serialization can be improved. What I'd like to stress is that you don't have to wait for the improvement. You can always, instead of . x>. write . .~(mylift x)>. where mylift : t -> t code is *your* function that does whatever _you_ like it to do at that particular type t (it should still produce something of the type (t code)). If some particular mylift functions turn out popular, they can be added to MetaOCaml, to save everyone trouble writing them. And I generally agree with Leo that this implicit lifting is baroque. At present I'm not sure if requiring the explicit lifting is too much of a burden. I'm sure that with modular implicits, it won't be.