Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: Virgile Prevosto <virgile.prevosto@m4x.org>
To: Thomas Gazagnaire <thomas.gazagnaire@irisa.fr>
Cc: Caml list <caml-list@yquem.inria.fr>
Subject: Re: [Caml-list] Re: instanciation of functor using command line
Date: Mon, 20 Aug 2007 18:41:59 +0200	[thread overview]
Message-ID: <20070820184159.3b569973@localhost> (raw)
In-Reply-To: <46C99CC3.7000508@irisa.fr>

[-- Attachment #1: Type: text/plain, Size: 698 bytes --]

Le lun 20 aoû 2007 15:53:07 CEST,
Thomas Gazagnaire <thomas.gazagnaire@irisa.fr> a écrit :

> Virgile Prevosto a écrit :
> > In fact, I've written something like that some time ago. If someone
> > is interested, I might try to find the code (and maybe adapt it to
> > 3.10).
> > 
> 
> I am interested :)

OK. After re-reading the code, I'm not completely sure that it'll do
exactly what you want, but it is attached to this mail, with a very
small example of the syntactic constructions it defines. It should
compile with ocaml 3.09.2
(ocamlc -c -pp "camlp4o pa_extend.cmo q_MLast.cmo -impl" -impl
   choose_module.ml4)

-- 
E tutto per oggi, a la prossima volta.
Virgile


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: choose_module.ml4 --]
[-- Type: text/x-ocaml; name=choose_module.ml4, Size: 5894 bytes --]

(* Copyright (c) 2004-2007, Virgile Prevosto
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * The names of its contributors may not be used to endorse or promote
 *       products derived from this software without specific prior
 *       written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *)

(** syntactic sugar to choose modules implementation according to some
    condition.
*)

(* incompatible with ocaml 3.10. Usage:
   ocamlc -pp camlp4o choose_module.cmo file.ml

   added expressions:

   choose_module M = match e with Foo when true -> M1 | _ -> Mdefault in M.x

   register_module "ident" M1,M2,M3 in choice
   select_module A from choice using e with F in A.x

   register and select use an intermediate file, choice.p4o, written by
   register and read by select. if e is equal to "ident", then A will be
   bound to F(M1,M2,M3)

*)

open Pcaml

let choices = Grammar.Entry.create Pcaml.gram "choices"

(* extension of file storing list of module choices. *)
let ext = ".p4o"

let open_path open_func f =
  if Sys.file_exists f then
    open_func f
  else
    let rec try_dir lst  =
      match lst with
          [] -> raise Not_found
        | a::l ->
            let fpath = Filename.concat a f in
              if Sys.file_exists fpath then
                open_func fpath
              else try_dir l
    in try_dir !Odyl_main.path

let open_in_path = open_path open_in_bin
let open_out_path = open_path open_out_bin

let make_one_choice a mod_expr exp =
  let _loc = Lexing.dummy_pos, Lexing.dummy_pos in
    <:expr<let module $uid:a$ = $mod_expr$ in $exp$>>

EXTEND
    expr: [[
            "choose_module"; a = UIDENT; "="; "match" ; cond = expr; "with";
            OPT "|"; l = LIST1 choices SEP "|";
            "in"; e = expr ->
              let new_l = List.map
                            (fun (patt,optwhen,expr) ->
                               (patt,optwhen, make_one_choice a expr e)) l
              in  <:expr< match $cond$ with [$list:new_l$] >>
          | "register_module"; opt=STRING; l=LIST1 module_expr SEP ","; "in";
                  store = LIDENT ->
                    let filename = store ^ ext in
                    let current_table =
                      try
                        let chan = open_in_path filename in
                        let res = Marshal.from_channel chan in
                          close_in chan; res
                      with Not_found | End_of_file -> Hashtbl.create 7
                    in
                      Hashtbl.replace current_table opt l;
                      let chan =
                        try open_out_path filename
                        with Not_found -> open_out_bin filename
                      in
                        Marshal.to_channel chan current_table [];
                        flush chan; close_out chan;
                        <:expr< $str:opt$ >>
          | "select_module"; a = UIDENT; "from"; store = LIDENT; "using";
                  choice = expr;
                  post_process = OPT ["with"; m = module_expr -> m];
                  "in"; e = expr ->
                    let apply f x = <:module_expr< $f$ $x$>> in
                    let create_mod_value l =
                      match post_process with
                          None -> List.hd l
                        | Some s -> List.fold_left apply s l
                    in
                    let selection =
                      try
                        let chan = open_in_path (store ^ ext) in
                        let res =
                          Marshal.from_channel chan
                        in close_in chan; res
                      with Not_found | End_of_file  ->
                        Hashtbl.create 1
                    in
                    let patts =
                      Hashtbl.fold
                        (fun patt -> fun mod_expr_list -> fun l ->
                           (<:patt<$str:patt$>>, None,
                            make_one_choice a
                              (create_mod_value mod_expr_list) e)
                           :: l)
                        selection [ <:patt< _ >>, None,
                                    <:expr< failwith
                                      ("not a valid option for selection of "
                                      ^ $str:store$)>>
                                  ]
                    in <:expr< match $choice$ with [$list:patts$]>>
]];

  choices: [[ p=patt; w = OPT ["when"; e = expr -> e]; "->"; m = module_expr ->
                (p,w,m)
            ]];
END

      parent reply	other threads:[~2007-08-20 16:42 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-08-13  0:38 Thomas Gazagnaire
2007-08-13  7:17 ` Sébastien Hinderer
2007-08-13  7:53   ` [Caml-list] " Jon Harrop
2007-08-20 13:49     ` Virgile Prevosto
     [not found]       ` <46C99CC3.7000508@irisa.fr>
2007-08-20 16:41         ` Virgile Prevosto [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070820184159.3b569973@localhost \
    --to=virgile.prevosto@m4x.org \
    --cc=caml-list@yquem.inria.fr \
    --cc=thomas.gazagnaire@irisa.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox