open Camlp4.PreCast
let unique =
let n = ref 0 in
fun () -> incr n; "__pa_memo" ^ string_of_int !n
EXTEND Gram
GLOBAL: Syntax.expr;
Syntax.expr: LEVEL "top" [
[ "memo"; OPT "|"; pel = LIST1 match_case SEP "|" ->
let tbl = unique () in
let x = unique () in
let result = unique () in
<:expr<
let $lid:tbl$ = Hashtbl.create 100 in
fun $lid:x$ ->
try Hashtbl.find $lid:tbl$ $lid:x$
with [ Not_found ->
let $lid:result$ = match $lid:x$ with [ $list:pel$ ] in
do { Hashtbl.replace $lid:tbl$ $lid:x$ $lid:result$;
$lid:result$ } ]
>> ]
];
match_case: [
[ p = Syntax.patt;
w = OPT [ "when"; e = Syntax.expr -> e ];
"->"; e = Syntax.expr ->
match w with
None -> <:match_case< $p$ -> $e$ >>
| Some x -> <:match_case< $p$ when $x$ -> $e$ >> ]
];
END