Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
* camlp4
@ 2008-01-18 17:08 Christian Sternagel
  2008-01-18 18:56 ` [Caml-list] camlp4 Nicolas Pouillard
  2008-01-18 19:30 ` Olivier Andrieu
  0 siblings, 2 replies; 16+ messages in thread
From: Christian Sternagel @ 2008-01-18 17:08 UTC (permalink / raw)
  To: caml-list

When using `camlp4o -parser Camlp4ListComprehension' as preprocessor,
is the resulting code the naive translation, like in,

 [(x, y) | x <- xs, even xs, y <- ys]

=>

 List.flatten (
  List.map (fun x -> List.map (fun y -> (x, y)) ys) (List.filter even xs)
 )

or is there an optimization in order to avoid appends and minimize the
number of cons?

cheers

christian


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-18 17:08 camlp4 Christian Sternagel
@ 2008-01-18 18:56 ` Nicolas Pouillard
  2008-01-18 19:30 ` Olivier Andrieu
  1 sibling, 0 replies; 16+ messages in thread
From: Nicolas Pouillard @ 2008-01-18 18:56 UTC (permalink / raw)
  To: caml-list

Excerpts from christian.sternagel's message of Fri Jan 18 18:08:52 +0100 2008:
> When using `camlp4o -parser Camlp4ListComprehension' as preprocessor,
> is the resulting code the naive translation, like in,
> 
>  [(x, y) | x <- xs, even xs, y <- ys]
> 
> =>
> 
>  List.flatten (
>   List.map (fun x -> List.map (fun y -> (x, y)) ys) (List.filter even xs)
>  )
> 
> or is there an optimization in order to avoid appends and minimize the
> number of cons?

There is only a few very local optimizations.

However  you  can  answer  to your question by asking camlp4 to translate your
code and pretty-print the result.

$ camlp4o -parser Camlp4ListComprehension -str '[(x, y) | x <- xs; even xs; y <- ys]'
List.concat
  (List.map (fun x -> List.map (fun y -> (x, y)) ys)
     (List.filter (fun x -> even xs) xs))

As you can see List.concat is still there.

Note  also  that  the  syntax is to use `;' to separate qualifiers (generators
and filters) instead of `,' as your example.

Best regards,

-- 
Nicolas Pouillard aka Ertai


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-18 17:08 camlp4 Christian Sternagel
  2008-01-18 18:56 ` [Caml-list] camlp4 Nicolas Pouillard
@ 2008-01-18 19:30 ` Olivier Andrieu
  2008-01-18 19:53   ` Nicolas Pouillard
  1 sibling, 1 reply; 16+ messages in thread
From: Olivier Andrieu @ 2008-01-18 19:30 UTC (permalink / raw)
  To: Christian Sternagel; +Cc: caml-list

On Jan 18, 2008 6:08 PM, Christian Sternagel
<Christian.Sternagel@uibk.ac.at> wrote:
> When using `camlp4o -parser Camlp4ListComprehension' as preprocessor,
> is the resulting code the naive translation, like in,
>
>  [(x, y) | x <- xs, even xs, y <- ys]
>
> =>
>
>  List.flatten (
>   List.map (fun x -> List.map (fun y -> (x, y)) ys) (List.filter even xs)
>  )
>
> or is there an optimization in order to avoid appends and minimize the
> number of cons?


FYI, my (old) syntax extension¹ for camlp4 <= 3.09 expands list
comprehensions to a combination of folds:

  [+ (x, y) | x <- xs | when even x | y <- ys]

=>

  List.fold_right
    (fun x __acc__ ->
       if even x then
         List.fold_right (fun y __acc__ -> (x, y) :: __acc__) ys __acc__
       else __acc__)
    xs []

Less cons operations, but it's not tail recursive.

[1] http://oandrieu.nerim.net/ocaml/#pa_compr
-- 
  Olivier


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-18 19:30 ` Olivier Andrieu
@ 2008-01-18 19:53   ` Nicolas Pouillard
  2008-01-19 15:09     ` Christian Sternagel
  0 siblings, 1 reply; 16+ messages in thread
From: Nicolas Pouillard @ 2008-01-18 19:53 UTC (permalink / raw)
  To: oandrieu; +Cc: christian.sternagel, caml-list

Excerpts from oandrieu's message of Fri Jan 18 20:30:59 +0100 2008:
> On Jan 18, 2008 6:08 PM, Christian Sternagel
> <Christian.Sternagel@uibk.ac.at> wrote:
> > When using `camlp4o -parser Camlp4ListComprehension' as preprocessor,
> > is the resulting code the naive translation, like in,
> >
> >  [(x, y) | x <- xs, even xs, y <- ys]
> >
> > =>
> >
> >  List.flatten (
> >   List.map (fun x -> List.map (fun y -> (x, y)) ys) (List.filter even xs)
> >  )
> >
> > or is there an optimization in order to avoid appends and minimize the
> > number of cons?
> 
> 
> FYI, my (old) syntax extension¹ for camlp4 <= 3.09 expands list
> comprehensions to a combination of folds:
> 
>   [+ (x, y) | x <- xs | when even x | y <- ys]
> 
> =>
> 
>   List.fold_right
>     (fun x __acc__ ->
>        if even x then
>          List.fold_right (fun y __acc__ -> (x, y) :: __acc__) ys __acc__
>        else __acc__)
>     xs []
> 
> Less cons operations, but it's not tail recursive.

Hum...  That's  nice and I could accept patches in that direction. However can
you  do  it  without  introducing  variables,  that's  always dangerous to add
variables because we should check that the user is not using the same.

> [1] http://oandrieu.nerim.net/ocaml/#pa_compr

-- 
Nicolas Pouillard aka Ertai


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-18 19:53   ` Nicolas Pouillard
@ 2008-01-19 15:09     ` Christian Sternagel
  2008-01-20 15:23       ` Nicolas Pouillard
  0 siblings, 1 reply; 16+ messages in thread
From: Christian Sternagel @ 2008-01-19 15:09 UTC (permalink / raw)
  To: caml-list

Quoting Nicolas Pouillard <nicolas.pouillard@gmail.com>:

> Excerpts from oandrieu's message of Fri Jan 18 20:30:59 +0100 2008:
> > On Jan 18, 2008 6:08 PM, Christian Sternagel
> > <Christian.Sternagel@uibk.ac.at> wrote:
> > > When using `camlp4o -parser Camlp4ListComprehension' as preprocessor,
> > > is the resulting code the naive translation, like in,
> > >
> > >  [(x, y) | x <- xs, even xs, y <- ys]
> > >
> > > =>
> > >
> > >  List.flatten (
> > >   List.map (fun x -> List.map (fun y -> (x, y)) ys) (List.filter even xs)
> > >  )
> > >
> > > or is there an optimization in order to avoid appends and minimize the
> > > number of cons?
> >
> >
> > FYI, my (old) syntax extension¹ for camlp4 <= 3.09 expands list
> > comprehensions to a combination of folds:
> >
> >   [+ (x, y) | x <- xs | when even x | y <- ys]
> >
> > =>
> >
> >   List.fold_right
> >     (fun x __acc__ ->
> >        if even x then
> >          List.fold_right (fun y __acc__ -> (x, y) :: __acc__) ys __acc__
> >        else __acc__)
> >     xs []
> >
> > Less cons operations, but it's not tail recursive.
>
> Hum...  That's  nice and I could accept patches in that direction. However
> can
> you  do  it  without  introducing  variables,  that's  always dangerous to
> add
> variables because we should check that the user is not using the same.
>
> > [1] http://oandrieu.nerim.net/ocaml/#pa_compr
>
> --
> Nicolas Pouillard aka Ertai
>
>
How about the transformation from Chapter 7 of [1] (by Philip Wadler)?
It should be similar to the `pseudo code':

type expr = ...;;
type patt = ...;;
type qualifier = Gen of patt * expr | Filt of expr;;
type compr = (expr * qualifier list);;
let rec expr = function
 | ...
 | (e, qs) -> transform [] (e, qs)
 | ...
and transform l = function
 | (e, []) -> expr e :: expr l
 | (e, Filt f :: qs) -> if expr f then transform l (e, qs) else expr l
 | (e, Gen (p, l1) :: qs) ->
  let rec h = function
   | [] -> expr l
   | u :: us -> (function p -> transform (h us) (e, qs) | _ -> h us) u
  in h (expr l1)
;;

(* where h, u, us are fresh variables not occurring in e, l1, l, or qs *)

Sorry I'm not yet familiar with camlp4 grammar extensions, but of course
above code would make use of them otherwise.

It is stated in [1] that the resulting code is optimal in that it
performs the minimum number of cons operations.

I'm not sure whether this isn't equivalent to oandrieu's code.

And I did ignore the hint that fresh variables make things
complicated :).

cheers

christian

[1] Simon P. Jones, 1987. The implementation of functional programming
languages. Available online at:
http://research.microsoft.com/~simonpj/papers/slpj-book-1987/index.htm


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-19 15:09     ` Christian Sternagel
@ 2008-01-20 15:23       ` Nicolas Pouillard
  2008-01-22 13:33         ` Christian Sternagel
  0 siblings, 1 reply; 16+ messages in thread
From: Nicolas Pouillard @ 2008-01-20 15:23 UTC (permalink / raw)
  To: christian.sternagel; +Cc: caml-list

Excerpts from christian.sternagel's message of Sat Jan 19 16:09:01 +0100 2008:
> Quoting Nicolas Pouillard <nicolas.pouillard@gmail.com>:
> 
> > Excerpts from oandrieu's message of Fri Jan 18 20:30:59 +0100 2008:
> > > On Jan 18, 2008 6:08 PM, Christian Sternagel
> > > <Christian.Sternagel@uibk.ac.at> wrote:
> > > > When using `camlp4o -parser Camlp4ListComprehension' as preprocessor,
> > > > is the resulting code the naive translation, like in,
> > > >
> > > >  [(x, y) | x <- xs, even xs, y <- ys]
> > > >
> > > > =>
> > > >
> > > >  List.flatten (
> > > >   List.map (fun x -> List.map (fun y -> (x, y)) ys) (List.filter even xs)
> > > >  )
> > > >
> > > > or is there an optimization in order to avoid appends and minimize the
> > > > number of cons?
> > >
> > >
> > > FYI, my (old) syntax extension¹ for camlp4 <= 3.09 expands list
> > > comprehensions to a combination of folds:
> > >
> > >   [+ (x, y) | x <- xs | when even x | y <- ys]
> > >
> > > =>
> > >
> > >   List.fold_right
> > >     (fun x __acc__ ->
> > >        if even x then
> > >          List.fold_right (fun y __acc__ -> (x, y) :: __acc__) ys __acc__
> > >        else __acc__)
> > >     xs []
> > >
> > > Less cons operations, but it's not tail recursive.
> >
> > Hum...  That's  nice and I could accept patches in that direction. However
> > can
> > you  do  it  without  introducing  variables,  that's  always dangerous to
> > add
> > variables because we should check that the user is not using the same.
> >
> > > [1] http://oandrieu.nerim.net/ocaml/#pa_compr
> >
> > --
> > Nicolas Pouillard aka Ertai
> >
> >
> How about the transformation from Chapter 7 of [1] (by Philip Wadler)?
> It should be similar to the `pseudo code':
> 
> type expr = ...;;
> type patt = ...;;
> type qualifier = Gen of patt * expr | Filt of expr;;
> type compr = (expr * qualifier list);;
> let rec expr = function
>  | ...
>  | (e, qs) -> transform [] (e, qs)
>  | ...
> and transform l = function
>  | (e, []) -> expr e :: expr l
>  | (e, Filt f :: qs) -> if expr f then transform l (e, qs) else expr l
>  | (e, Gen (p, l1) :: qs) ->
>   let rec h = function
>    | [] -> expr l
>    | u :: us -> (function p -> transform (h us) (e, qs) | _ -> h us) u
>   in h (expr l1)
> ;;
> 
> (* where h, u, us are fresh variables not occurring in e, l1, l, or qs *)
> 
> Sorry I'm not yet familiar with camlp4 grammar extensions, but of course
> above code would make use of them otherwise.

Yes this approach can be integrated with a camlp4 extension.

> It is stated in [1] that the resulting code is optimal in that it
> performs the minimum number of cons operations.

Nice.

> And I did ignore the hint that fresh variables make things
> complicated :).

Yes it can...

Best regards,

-- 
Nicolas Pouillard aka Ertai


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-20 15:23       ` Nicolas Pouillard
@ 2008-01-22 13:33         ` Christian Sternagel
  2008-01-22 13:42           ` Nicolas Pouillard
  0 siblings, 1 reply; 16+ messages in thread
From: Christian Sternagel @ 2008-01-22 13:33 UTC (permalink / raw)
  To: caml-list

> > How about the transformation from Chapter 7 of [1] (by Philip Wadler)?
> > It should be similar to the `pseudo code':
> > 
> > type expr = ...;;
> > type patt = ...;;
> > type qualifier = Gen of patt * expr | Filt of expr;;
> > type compr = (expr * qualifier list);;
> > let rec expr = function
> >  | ...
> >  | (e, qs) -> transform [] (e, qs)
> >  | ...
> > and transform l = function
> >  | (e, []) -> expr e :: expr l
> >  | (e, Filt f :: qs) -> if expr f then transform l (e, qs) else expr l
> >  | (e, Gen (p, l1) :: qs) ->
> >   let rec h = function
> >    | [] -> expr l
> >    | u :: us -> (function p -> transform (h us) (e, qs) | _ -> h us) u
> >   in h (expr l1)
> > ;;
> > 
> > (* where h, u, us are fresh variables not occurring in e, l1, l, or qs *)
> > 
> > Sorry I'm not yet familiar with camlp4 grammar extensions, but of course
> > above code would make use of them otherwise.
> 
> Yes this approach can be integrated with a camlp4 extension.
> 
> > It is stated in [1] that the resulting code is optimal in that it
> > performs the minimum number of cons operations.
> 
> Nice.
> 
> > And I did ignore the hint that fresh variables make things
> > complicated :).
> 
> Yes it can...
> 
> Best regards,
> 
> -- 
> Nicolas Pouillard aka Ertai
> 
I deduce that there is no standard way of introducing
`fresh' (w.r.t. the abstract syntax tree) variables
within a camlp4 syntax extension? Wouldn't that be nice? =)

Has anybody every implemented a solution to that problem?

cheers

christian


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-22 13:33         ` Christian Sternagel
@ 2008-01-22 13:42           ` Nicolas Pouillard
  2008-01-22 14:06             ` Loup Vaillant
  2008-01-22 16:43             ` Christian Sternagel
  0 siblings, 2 replies; 16+ messages in thread
From: Nicolas Pouillard @ 2008-01-22 13:42 UTC (permalink / raw)
  To: christian.sternagel; +Cc: caml-list

[-- Attachment #1: Type: multipart/signed, Size: 2257 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-22 13:42           ` Nicolas Pouillard
@ 2008-01-22 14:06             ` Loup Vaillant
  2008-01-22 14:26               ` Nicolas Pouillard
  2008-01-22 16:43             ` Christian Sternagel
  1 sibling, 1 reply; 16+ messages in thread
From: Loup Vaillant @ 2008-01-22 14:06 UTC (permalink / raw)
  To: Nicolas Pouillard; +Cc: christian. sternagel, caml-list

2008/1/22, Nicolas Pouillard <nicolas.pouillard@gmail.com>:
> Excerpts from christian.sternagel's message of Tue Jan 22 14:33:55 +0100
> > I deduce that there is no standard way of introducing
> > `fresh' (w.r.t. the abstract syntax tree) variables
> > within a camlp4 syntax extension? Wouldn't that be nice? =)
>
> That  would be nice, but doing it cleanly would require a large amount of work
> and user visible changes.

Hello,

I am personally interested in how we "do it cleanly" (not specifically
for Ocaml), but I didn't found much documentation nor papers on the
subject. Do anyone have some pointers about that?

Thanks,
Loup


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-22 14:06             ` Loup Vaillant
@ 2008-01-22 14:26               ` Nicolas Pouillard
  0 siblings, 0 replies; 16+ messages in thread
From: Nicolas Pouillard @ 2008-01-22 14:26 UTC (permalink / raw)
  To: loup.vaillant; +Cc: christian.sternagel, caml-list

[-- Attachment #1: Type: multipart/signed, Size: 1402 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-22 13:42           ` Nicolas Pouillard
  2008-01-22 14:06             ` Loup Vaillant
@ 2008-01-22 16:43             ` Christian Sternagel
  2008-01-22 18:20               ` Nicolas Pouillard
  1 sibling, 1 reply; 16+ messages in thread
From: Christian Sternagel @ 2008-01-22 16:43 UTC (permalink / raw)
  To: caml-list

I tried to implement the optimizations for list comprehensions
as stated in the book by simon peyton jones (1987). The problem
of using fresh variables I circumvented in an admittedly `ugly' way,
however (which is not fool proof since there could be programmers
that use variable names like __h__0, __h__1, ...).

The Starting point was the file Camlp4ListComprehension.ml from
camlp4.

Any comments are wellcome.

cheers

christian

Here is the code
-------------------------------------------------------------------------
open Camlp4;;

module Id = struct
 let name =    "ListComprehension";;
 let version = "$Id: ListComprehension";;
end

module Make (Syntax : Sig.Camlp4Syntax) = struct

open Sig;;
include Syntax;;

let rec safe_nth n = function
 | [] -> None
 | [(x,_)] -> if n = 1 then Some x else None
 | _ :: l -> safe_nth (n - 1) l
;;

let stream_peek_nth n s = safe_nth n (Stream.npeek n s);;

let lc_generator = Gram.Entry.of_parser "lc_generator" (fun s ->
 let rec skip_patt n = match stream_peek_nth n s with
  | Some (KEYWORD "<-") -> n
  | Some (KEYWORD ("[" | "[<")) -> skip_patt (ignore_upto "]" (n + 1) + 1)
  | Some (KEYWORD "(") -> skip_patt (ignore_upto ")" (n + 1) + 1)
  | Some (KEYWORD "{") -> skip_patt (ignore_upto "}" (n + 1) + 1)
  | Some (KEYWORD ("as" | "::" | ";" | "," | "_"))
  | Some (LIDENT _ | UIDENT _) -> skip_patt (n + 1)
  | Some _ | None -> raise Stream.Failure
 and ignore_upto end_kwd n = match stream_peek_nth n s with
  | Some (KEYWORD prm) when prm = end_kwd -> n 
  | Some (KEYWORD ("[" | "[<")) -> ignore_upto end_kwd (ignore_upto "]" (n + 1) + 1)
  | Some (KEYWORD "(") -> ignore_upto end_kwd (ignore_upto ")" (n + 1) + 1)
  | Some (KEYWORD "{") -> ignore_upto end_kwd (ignore_upto "}" (n + 1) + 1)
  | Some _ -> ignore_upto end_kwd (n + 1)
  | None -> raise Stream.Failure
 in skip_patt 1
);;

let var = ref 0;;
let fresh () = incr var; !var;;

let rec compr _loc e acc = function
 | [] -> <:expr< $e$::$acc$ >>
 | `filter b :: qs -> <:expr< if $b$ then $compr _loc e acc qs$ else $acc$ >>
 | `gen (p, l1) :: qs ->
 let h  = Format.sprintf "__h__%i" (fresh ()) in
 let u  = Format.sprintf "__u__%i" (fresh ()) in
 let us = Format.sprintf "__us__%i" (fresh ()) in
 <:expr<
  let rec $lid:h$ = function
   | [] -> $acc$
   | $lid:u$ :: $lid:us$ -> $if Ast.is_irrefut_patt p then
    <:expr< (fun $p$ -> $compr _loc e <:expr< ($lid:h$ $lid:us$) >> qs$) $lid:u$ >>
   else
    <:expr<
     (function $p$ ->
      $compr _loc e <:expr< ($lid:h$ $lid:us$) >> qs$ | _ -> $lid:h$ $lid:us$) $lid:u$
    >>
   $
  in $lid:h$ $l1$
 >>
 | _ -> <:expr< [] >>
;;

let list_comprehension = Gram.Entry.mk "list_comprehension";;

DELETE_RULE Gram expr: "["; sem_expr_for_list; "]" END;;

EXTEND Gram
 GLOBAL: expr list_comprehension;
 expr: LEVEL "simple" [
  [ "["; e = list_comprehension; "]" -> e]
 ];
 list_comprehension: [
  [ e = expr LEVEL "top"; ";"; mk = sem_expr_for_list ->
   <:expr< $e$::$mk <:expr< [] >>$ >>
  | e = expr LEVEL "top"; ";" -> <:expr< [$e$] >>
  | e = expr LEVEL "top"; "|"; l = LIST1 quantifier SEP ";" ->
   compr _loc e <:expr< [] >> l
  | e = expr LEVEL "top" -> <:expr< [$e$] >> ]
 ];
 quantifier: [
  [ lc_generator; p = patt; "<-"; e = expr LEVEL "top" -> `gen (p, e)
  | e = expr LEVEL "top" -> `filter e ]
 ];
END;;

end

let module M = Register.OCamlSyntaxExtension Id Make in ();;
-------------------------------------------------------------------------
On Tue, Jan 22, 2008 at 02:42:00PM +0100, Nicolas Pouillard wrote:
> Excerpts from christian.sternagel's message of Tue Jan 22 14:33:55 +0100 2008:
> > > > How about the transformation from Chapter 7 of [1] (by Philip Wadler)?
> > > > It should be similar to the `pseudo code':
> > > > 
> > > > type expr = ...;;
> > > > type patt = ...;;
> > > > type qualifier = Gen of patt * expr | Filt of expr;;
> > > > type compr = (expr * qualifier list);;
> > > > let rec expr = function
> > > >  | ...
> > > >  | (e, qs) -> transform [] (e, qs)
> > > >  | ...
> > > > and transform l = function
> > > >  | (e, []) -> expr e :: expr l
> > > >  | (e, Filt f :: qs) -> if expr f then transform l (e, qs) else expr l
> > > >  | (e, Gen (p, l1) :: qs) ->
> > > >   let rec h = function
> > > >    | [] -> expr l
> > > >    | u :: us -> (function p -> transform (h us) (e, qs) | _ -> h us) u
> > > >   in h (expr l1)
> > > > ;;
> > > > 
> > > > (* where h, u, us are fresh variables not occurring in e, l1, l, or qs *)
> > > > 
> > > > Sorry I'm not yet familiar with camlp4 grammar extensions, but of course
> > > > above code would make use of them otherwise.
> > > 
> > > Yes this approach can be integrated with a camlp4 extension.
> > > 
> > > > It is stated in [1] that the resulting code is optimal in that it
> > > > performs the minimum number of cons operations.
> > > 
> > > Nice.
> > > 
> > > > And I did ignore the hint that fresh variables make things
> > > > complicated :).
> > > 
> > > Yes it can...
> > > 
> > > Best regards,
> > > 
> > > -- 
> > > Nicolas Pouillard aka Ertai
> > > 
> > I deduce that there is no standard way of introducing
> > `fresh' (w.r.t. the abstract syntax tree) variables
> > within a camlp4 syntax extension? Wouldn't that be nice? =)
> > 
> 
> That  would be nice, but doing it cleanly would require a large amount of work
> and user visible changes.
> 
> -- 
> Nicolas Pouillard aka Ertai


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-22 16:43             ` Christian Sternagel
@ 2008-01-22 18:20               ` Nicolas Pouillard
  2008-01-24  9:01                 ` Christian Sternagel
  0 siblings, 1 reply; 16+ messages in thread
From: Nicolas Pouillard @ 2008-01-22 18:20 UTC (permalink / raw)
  To: christian.sternagel; +Cc: caml-list

[-- Attachment #1: Type: multipart/signed, Size: 6394 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Caml-list] camlp4
  2008-01-22 18:20               ` Nicolas Pouillard
@ 2008-01-24  9:01                 ` Christian Sternagel
  0 siblings, 0 replies; 16+ messages in thread
From: Christian Sternagel @ 2008-01-24  9:01 UTC (permalink / raw)
  To: caml-list

On Tue, Jan 22, 2008 at 07:20:55PM +0100, Nicolas Pouillard wrote:
> Excerpts from christian.sternagel's message of Tue Jan 22 17:43:20 +0100 2008:
> > I tried to implement the optimizations for list comprehensions
> > as stated in the book by simon peyton jones (1987). The problem
> > of using fresh variables I circumvented in an admittedly `ugly' way,
> > however (which is not fool proof since there could be programmers
> > that use variable names like __h__0, __h__1, ...).
> > 
> > The Starting point was the file Camlp4ListComprehension.ml from
> > camlp4.
> > 
> > Any comments are wellcome.
> 
> Nice  start,  however  can you make it more closer to the original code (as in
Yes. Here it is. The `fresh variable' problem, however,
is not really solved. Maybe, using some dedicated namespace
is indeed the easiest solution (hence I did that in my code).

cheers

christisn

@Ertai: sorry for the duplicate... the first time I forgot to
reply to the list.
--------------------------------------------------------------------------
open Camlp4;                                             (* -*- camlp4r -*- *)
(****************************************************************************)
(*                                                                          *)
(*                              Objective Caml                              *)
(*                                                                          *)
(*                            INRIA Rocquencourt                            *)
(*                                                                          *)
(*  Copyright  2007  Institut  National  de  Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed under   *)
(*  the terms of the GNU Library General Public License, with the special   *)
(*  exception on linking described in LICENSE at the top of the Objective   *)
(*  Caml source tree.                                                       *)
(*                                                                          *)
(****************************************************************************)

(* Authors:
 * - Nao Hirokawa: initial version
 * - Nicolas Pouillard: revised syntax version
 * - Christian Sternagel: optimization of Chapter 7 of
 *   [Simon Peyton Jones, 1987. The Implementation of
 *    Functional Programming Languages]
 *)


module Id = struct
  value name = "Camlp4ListComprenhsion";
  value version = "$Id: Camlp4ListComprehension.ml,v 1.1.2.1 2007/05/27 16:23:35 pouillar Exp $";
end;

module Make (Syntax : Sig.Camlp4Syntax) = struct
  open Sig;
  include Syntax;

  value rec loop n =
    fun
    [ [] -> None
    | [(x, _)] -> if n = 1 then Some x else None
    | [_ :: l] -> loop (n - 1) l ];

  value stream_peek_nth n strm = loop n (Stream.npeek n strm);

  (* usual trick *)
  value test_patt_lessminus =
    Gram.Entry.of_parser "test_patt_lessminus"
      (fun strm ->
        let rec skip_patt n =
          match stream_peek_nth n strm with
          [ Some (KEYWORD "<-") -> n
          | Some (KEYWORD ("[" | "[<")) ->
              skip_patt (ignore_upto "]" (n + 1) + 1)
          | Some (KEYWORD "(") -> 
              skip_patt (ignore_upto ")" (n + 1) + 1)
          | Some (KEYWORD "{") -> 
              skip_patt (ignore_upto "}" (n + 1) + 1)
          | Some (KEYWORD ("as" | "::" | "," | "_"))
          | Some (LIDENT _ | UIDENT _) -> skip_patt (n + 1)
          | Some _ | None -> raise Stream.Failure ]
        and ignore_upto end_kwd n =
          match stream_peek_nth n strm with
          [ Some (KEYWORD prm) when prm = end_kwd -> n 
          | Some (KEYWORD ("[" | "[<")) ->
              ignore_upto end_kwd (ignore_upto "]" (n + 1) + 1)
          | Some (KEYWORD "(") ->
              ignore_upto end_kwd (ignore_upto ")" (n + 1) + 1)
          | Some (KEYWORD "{") -> 
              ignore_upto end_kwd (ignore_upto "}" (n + 1) + 1)
          | Some _ -> ignore_upto end_kwd (n + 1)
          | None -> raise Stream.Failure ]
        in
        skip_patt 1);

  value index = ref 0;
  value var base =
   Format.sprintf
    "__camlp4_list_comprehension__%s__%i"
    base
    (incr index; !index);

  value compr _loc e qs =
   let rec transform _loc e acc =
    fun
    [ [] -> <:expr< [ $e$ :: $acc$ ] >>
    | [`cond b :: qs] ->
     <:expr< if $b$ then $transform _loc e acc qs$ else $acc$ >>
    | [`gen (p, l) :: qs] ->
     let h = var "h" and u = var "u" and us = var "us" in
     <:expr<
      let rec $lid:h$ = fun
      [ [] -> $acc$
      | [ $lid:u$ :: $lid:us$ ] ->
       $if Ast.is_irrefut_patt p then
        <:expr< (fun
         [ $p$ -> $transform _loc e <:expr< ($lid:h$ $lid:us$) >> qs$ ]
        ) $lid:u$
        >>
       else
        <:expr< (fun
         [ $p$ -> $transform _loc e <:expr< ($lid:h$ $lid:us$) >> qs$
         | _ -> $lid:h$ $lid:us$ ]
        ) $lid:us$
        >>
        $
       ]
     in $lid:h$ $l$ 
     >>
    | _ -> <:expr< [] >> ]
   in
   transform _loc e <:expr< [] >> qs;

  DELETE_RULE Gram expr: "["; sem_expr_for_list; "]" END;

  value is_revised =
    try do {
      DELETE_RULE Gram expr: "["; sem_expr_for_list; "::"; expr; "]" END;
      True
    } with [ Not_found -> False ];

  value comprehension_or_sem_expr_for_list =
    Gram.Entry.mk "comprehension_or_sem_expr_for_list";

  EXTEND Gram
    GLOBAL: expr comprehension_or_sem_expr_for_list;

    expr: LEVEL "simple"
      [ [ "["; e = comprehension_or_sem_expr_for_list; "]" -> e ] ]
    ;

    comprehension_or_sem_expr_for_list:
      [ [ e = expr LEVEL "top"; ";"; mk = sem_expr_for_list ->
            <:expr< [ $e$ :: $mk <:expr< [] >>$ ] >>
        | e = expr LEVEL "top"; ";" -> <:expr< [$e$] >>
        | e = expr LEVEL "top"; "|"; l = LIST1 item SEP ";" -> compr _loc e l
        | e = expr LEVEL "top" -> <:expr< [$e$] >> ] ]
    ;

    item: 
      [ [ test_patt_lessminus; 
          p = patt; "<-" ; e = expr LEVEL "top" -> `gen (p, e)
        | e = expr LEVEL "top" -> `cond e ] ]
    ;

  END;

  if is_revised then
    EXTEND Gram
      GLOBAL: expr comprehension_or_sem_expr_for_list;

      comprehension_or_sem_expr_for_list:
      [ [ e = expr LEVEL "top"; ";"; mk = sem_expr_for_list; "::"; last = expr ->
            <:expr< [ $e$ :: $mk last$ ] >>
        | e = expr LEVEL "top"; "::"; last = expr ->
            <:expr< [ $e$ :: $last$ ] >> ] ]
      ;
    END
  else ();

end;

let module M = Register.OCamlSyntaxExtension Id Make in ();
--------------------------------------------------------------------------
> 
> -- 
> Nicolas Pouillard aka Ertai


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: camlp4
  2010-02-06 13:37 ` [Caml-list] camlp4 Ed Keith
@ 2010-02-06 16:25   ` Chris Conway
  0 siblings, 0 replies; 16+ messages in thread
From: Chris Conway @ 2010-02-06 16:25 UTC (permalink / raw)
  To: caml-list

Ed Keith <e_d_k <at> yahoo.com> writes:
> I wrestled with this myself and finally decided to stick with camlp5 until
> there is documentation available for camlp4.

This nails it. I can't believe how many "eat your spinach" replies there 
have been to this question. There is no reason whatever to waste your time 
figuring out how to use campl4 (post-3.10) when there is a well documented 
and widely used alternative. camlp5 may not be the "official" INRIA-blessed 
standard, but it has a significant community behind it and is actively 
maintained.

-Chris 


^ permalink raw reply	[flat|nested] 16+ messages in thread

* camlp4
@ 2010-02-06  1:16 Andy Ray
  2010-02-06 13:37 ` [Caml-list] camlp4 Ed Keith
  0 siblings, 1 reply; 16+ messages in thread
From: Andy Ray @ 2010-02-06  1:16 UTC (permalink / raw)
  To: caml-list

Hi,

My project would really benefit from some simple camlp4 syntax
extensions, however, I am put off by the lack of a reference manual
for it.

At the moment I am tempted to go for camlp5 instead - not least
because I was able to work through it's manual and get some examples
working a while back.

The reality is I would prefer to use camlp4 as it appears to the
official ocaml supported way, but can't see how to get into it as a
beginner due to the lack of documentation (and that appears to have
been the case for quite some time now).  What should one do?

Cheers,
Andy


^ permalink raw reply	[flat|nested] 16+ messages in thread

* camlp4
@ 1997-01-14 12:47 Daniel de Rauglaudre
  0 siblings, 0 replies; 16+ messages in thread
From: Daniel de Rauglaudre @ 1997-01-14 12:47 UTC (permalink / raw)
  To: caml-list

We present the first distributed version of Camlp4 (0.4).

Camlp4 is a PreProcessorPrettyPrinter for Objective Caml. It offers
new syntactic library tools and the ability to change, extend and
redefine the concrete syntax of Objective Caml.

In the continuation of the work on "Chamau", but Camlp4 is compatible
with Objective Caml (the knowledge of Chamau is not necessary to use
Camlp4).

   Available by anonymous ftp at INRIA
	ftp.inria.fr (192.93.2.54)
   Directory lang/chamau.

   Or by the Web:
      ftp://ftp.inria.fr/lang/chamau/

   Files: README.camlp4, camlp4.tar.gz, camlp4-doc.ps.gz

--------------------------------------------------------------------------
 Daniel de RAUGLAUDRE

 Projet Cristal - INRIA Rocquencourt
 Tel: +33 (01) 39 63 53 51
 Email: daniel.de_rauglaudre@inria.fr
 Web: http://pauillac.inria.fr:80/~ddr/
--------------------------------------------------------------------------





^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2010-02-06 16:25 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-01-18 17:08 camlp4 Christian Sternagel
2008-01-18 18:56 ` [Caml-list] camlp4 Nicolas Pouillard
2008-01-18 19:30 ` Olivier Andrieu
2008-01-18 19:53   ` Nicolas Pouillard
2008-01-19 15:09     ` Christian Sternagel
2008-01-20 15:23       ` Nicolas Pouillard
2008-01-22 13:33         ` Christian Sternagel
2008-01-22 13:42           ` Nicolas Pouillard
2008-01-22 14:06             ` Loup Vaillant
2008-01-22 14:26               ` Nicolas Pouillard
2008-01-22 16:43             ` Christian Sternagel
2008-01-22 18:20               ` Nicolas Pouillard
2008-01-24  9:01                 ` Christian Sternagel
  -- strict thread matches above, loose matches on Subject: below --
2010-02-06  1:16 camlp4 Andy Ray
2010-02-06 13:37 ` [Caml-list] camlp4 Ed Keith
2010-02-06 16:25   ` camlp4 Chris Conway
1997-01-14 12:47 camlp4 Daniel de Rauglaudre

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox