caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Daniel de Rauglaudre <daniel.de_rauglaudre@inria.fr>
To: caml-list@inria.fr
Subject: Re: [Caml-list] record labels of record scope using camlp4
Date: Mon, 14 Jan 2002 11:01:49 +0100	[thread overview]
Message-ID: <20020114110149.B6175@verdot.inria.fr> (raw)
In-Reply-To: <000101c19ccc$ffe8e8c0$0b01a8c0@mit.edu>; from jehenrik@yahoo.com on Mon, Jan 14, 2002 at 02:28:02AM -0500

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

Hi,

On Mon, Jan 14, 2002 at 02:28:02AM -0500, Jeff Henrikson wrote:

> First bad news: the code runs great in the toplevel, but that's
> because camlp4 extends grammars interactively there.  Apparently in
> batch compilation, any EXTEND construct only takes effect at the end
> of the file, not at the end of a statement.

It works in batch mode, but syntax extensions must be given to camlp4
as cmo or cma files. Find attached your program and its two examples.
First compile your extension by:
      ocamlc -pp camlp4o -I +camlp4 -c my_extension.ml

And your two examples by:
      ocamlc -pp camlp4o -c my_file.ml
      ocamlc -pp camlp4o -c my_file2.ml

You can also pretty print the corresponding pure OCaml code, to see
what the syntax extension did, by:
      camlp4o pr_o.cmo my_file.ml
      camlp4o pr_o.cmo my_file2.ml

-- 
Daniel de RAUGLAUDRE
daniel.de_rauglaudre@inria.fr
http://cristal.inria.fr/~ddr/

[-- Attachment #2: my_extension.ml --]
[-- Type: text/plain, Size: 2423 bytes --]

#load "q_MLast.cmo";;
#load "pa_extend.cmo";;

open Pcaml;;

let loc = (0,0);;        (* toploop only *)

let prepend_id name labels =
  let helper2 v =
    match v with
    <:patt<$lid:x$>> ->
      let y = name ^ "_" ^ x in
      <:patt<$lid:y$>>
  | _ -> v in
  let helper1 = fun
    (patt,expr) -> (helper2 patt,expr) in
  List.map helper1 labels;;



let make_record_constructor name =
  let lname = String.uncapitalize name in
  let uname = String.capitalize name in
  let lbl_expr_list =
    (Obj.magic (Grammar.Entry.find expr "lbl_expr_list") :
       (MLast.patt * MLast.expr) list Grammar.Entry.e) in
  let lbl_patt_list =
    (Obj.magic (Grammar.Entry.find patt "lbl_patt_list") :
       (MLast.patt * MLast.patt) list Grammar.Entry.e) in
  EXTEND
    expr: LEVEL "simple"
    [ [ $uname$; "{"; memb = LIST1 lbl_expr_list SEP ";" ; "}" ->
          (let memb0= prepend_id lname (List.hd memb) in
          <:expr<{$list:memb0$}>>) ] ];
    patt: LEVEL "simple"
    [ [ $uname$; "{"; memb = LIST1 lbl_patt_list SEP ";" ; "}" ->
          (let memb0= prepend_id lname (List.hd memb) in
          <:patt<{$list:memb0$}>>) ] ];
  END;
;;

(* test:
make_record_constructor "bogus";;

type bogus = {bogus_foo:string;bogus_bar:string};;

Bogus{foo="happy";bar="sad"};;
*)

let type_declaration =
    (Obj.magic (Grammar.Entry.find str_item "type_declaration") :
       MLast.type_decl Grammar.Entry.e);;
let type_parameters =
    (Obj.magic (Grammar.Entry.find type_declaration "type_parameters") :
       ((string * (bool * bool)) list) Grammar.Entry.e);;
let type_patt =
    (Obj.magic (Grammar.Entry.find type_declaration "type_patt") :
       (MLast.loc * string) Grammar.Entry.e);;
let type_kind =
    (Obj.magic (Grammar.Entry.find type_declaration "type_kind") :
        MLast.ctyp Grammar.Entry.e);;
let constrain =
    (Obj.magic (Grammar.Entry.find type_declaration "constrain") :
        ((MLast.ctyp * MLast.ctyp)) Grammar.Entry.e);;


let prepend_id_t name tk =
  let helper = fun
    (loc,s,b,t) -> (loc,name ^ "_" ^ s,b,t) in
  match tk with
    <:ctyp< { $list:ldl$ }>> ->
      let ldl2 = List.map helper ldl in <:ctyp< { $list:ldl2$ }>>
  | _ -> tk;;



EXTEND
  type_declaration:
    [ [ tpl = type_parameters; n = type_patt; "="; "LOCAL"; tk = type_kind;
        cl = LIST0 constrain ->
	  match n with (loc,s) ->
	    make_record_constructor s;
	    (n, tpl, prepend_id_t s tk,  cl) ] ]
  ;
END;;

[-- Attachment #3: my_file.ml --]
[-- Type: text/plain, Size: 194 bytes --]

#load "./my_extension.cmo";;

(* example: *)
type person = LOCAL {name:string; addr: string};;
let p = Person{name="Joe";addr="1 Broadway Ave"};;
match p with
  Person{name=n;addr=a} -> (n,a);;

[-- Attachment #4: my_file2.ml --]
[-- Type: text/plain, Size: 186 bytes --]

#load "./my_extension.cmo";;

(* this sort of thing works too: *)
type person = LOCAL {name:string; addr:string; friends:plist}
and plist = Plist_person of (person * plist) | List_End;;

  reply	other threads:[~2002-01-14 10:01 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-01-14  7:28 Jeff Henrikson
2002-01-14 10:01 ` Daniel de Rauglaudre [this message]
2002-01-14 12:15 ` Alain Frisch
2002-01-17 18:06   ` Didier Remy
2002-01-17 19:58     ` Alain Frisch
2002-01-18  6:58       ` Jacques Garrigue

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=20020114110149.B6175@verdot.inria.fr \
    --to=daniel.de_rauglaudre@inria.fr \
    --cc=caml-list@inria.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;
as well as URLs for NNTP newsgroup(s).