123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237(* OCaml promise library
* http://www.ocsigen.org/lwt
* Copyright (C) 2009 Jérémie Dimino
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, with linking exceptions;
* either version 2.1 of the License, or (at your option) any later
* version. See COPYING file for details.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*)openCamlp4.PreCastopen!Syntax(* Generate the catching function from a macth-case.
The main work of this functions is to add a case:
{[
| exn -> fail exn
]}
when there is not already one. *)letgen_catchmc=(* Does the match case have a rule of the form "| e -> ..." ? *)letrecdefault_case=function|<:match_case<$a$|$b$>>->default_casea||default_caseb|<:match_case<$patt$->$_$>>->catch_allpatt|_->falseandcatch_all=function|<:patt<_>>|<:patt<$lid:_$>>->true|<:patt<$p$as$_$>>->catch_allp|_->falseinifdefault_casemcthenmcelselet_loc=Ast.loc_of_match_casemcin<:match_case<$mc$|exn->Lwt.failexn>>letgen_bindingl=letrecauxn=function|[]->assertfalse|[(_loc,_p,e)]-><:binding<$lid:"__pa_lwt_"^string_of_intn$=$e$>>|(_loc,_p,e)::l-><:binding<$lid:"__pa_lwt_"^string_of_intn$=$e$and$aux(n+1)l$>>inaux0lletgen_bindle=letrecauxn=function|[]->e|(_loc,p,_e)::l->if!Pa_lwt_options.debugthen<:expr<Lwt.backtrace_bind(funexn->tryraiseexnwithexn->exn)$lid:"__pa_lwt_"^string_of_intn$(fun$p$->$aux(n+1)l$)>>else<:expr<Lwt.bind$lid:"__pa_lwt_"^string_of_intn$(fun$p$->$aux(n+1)l$)>>inaux0lletgen_top_bind_locl=letrecauxnvars=function|[]-><:expr<Lwt.return($tup:Ast.exCom_of_list(List.revvars)$)>>|(_loc,_p,_e)::l->letid="__pa_lwt_"^string_of_intninif!Pa_lwt_options.debugthen<:expr<Lwt.backtrace_bind(funexn->tryraiseexnwithexn->exn)$lid:id$(fun$lid:id$->$aux(n+1)(<:expr<$lid:id$>>::vars)l$)>>else<:expr<Lwt.bind$lid:id$(fun$lid:id$->$aux(n+1)(<:expr<$lid:id$>>::vars)l$)>>inaux0[]lEXTENDGramGLOBAL:exprstr_item;cases:[["with";c=match_case->Some(gen_catchc)|->None]];finally:[["finally";f=sequence->Somef|->None]];letb_binding:[[b1=SELF;"and";b2=SELF->b1@b2|p=patt;"=";e=expr->[(_loc,p,e)]]];for_scheme:[["=";s=sequence;"to";e=sequence->`CountTo(s,e)|"=";s=sequence;"downto";e=sequence->`CountDownTo(s,e)|"in";e=sequence->`IterOver(e)]];expr:LEVEL"top"[["try_lwt";e=exprLEVEL";";c=cases;f=finally->beginmatchc,fwith|None,None->if!Pa_lwt_options.debugthen<:expr<Lwt.backtrace_catch(funexn->tryraiseexnwithexn->exn)(fun()->$e$)Lwt.fail>>else<:expr<Lwt.catch(fun()->$e$)Lwt.fail>>|Somec,None->if!Pa_lwt_options.debugthen<:expr<Lwt.backtrace_catch(funexn->tryraiseexnwithexn->exn)(fun()->$e$)(function$c$)>>else<:expr<Lwt.catch(fun()->$e$)(function$c$)>>|None,Somef->if!Pa_lwt_options.debugthen<:expr<Lwt.backtrace_finalize(funexn->tryraiseexnwithexn->exn)(fun()->$e$)(fun()->(begin$f$end))>>else<:expr<Lwt.finalize(fun()->$e$)(fun()->(begin$f$end))>>|Somec,Somef->if!Pa_lwt_options.debugthen<:expr<Lwt.backtrace_try_bind(funexn->tryraiseexnwithexn->exn)(fun()->$e$)(fun__pa_lwt_x->Lwt.backtrace_bind(funexn->tryraiseexnwithexn->exn)(begin$f$end)(fun()->Lwt.return__pa_lwt_x))(fun__pa_lwt_e->Lwt.backtrace_bind(funexn->tryraiseexnwithexn->exn)(begin$f$end)(fun()->match__pa_lwt_ewith$c$))>>else<:expr<Lwt.try_bind(fun()->$e$)(fun__pa_lwt_x->Lwt.bind(begin$f$end)(fun()->Lwt.return__pa_lwt_x))(fun__pa_lwt_e->Lwt.bind(begin$f$end)(fun()->match__pa_lwt_ewith$c$))>>end|"lwt";l=letb_binding;"in";e=exprLEVEL";"-><:expr<let$gen_bindingl$in$gen_bindle$>>|"for_lwt";p=patt;scheme=for_scheme;"do";seq=do_sequence->(matchp,schemewith|<:patt<$lid:id$>>,`CountTo(s,e)-><:expr<let__pa_lwt_max=$e$inletrec__pa_lwt_loop$lid:id$=if$lid:id$>__pa_lwt_maxthenLwt.return()elseLwt.bind(begin$seq$end)(fun()->__pa_lwt_loop($lid:id$+1))in__pa_lwt_loop$s$>>|<:patt<$lid:id$>>,`CountDownTo(s,e)-><:expr<let__pa_lwt_min=$e$inletrec__pa_lwt_loop$lid:id$=if$lid:id$<__pa_lwt_minthenLwt.return()elseLwt.bind(begin$seq$end)(fun()->__pa_lwt_loop($lid:id$-1))in__pa_lwt_loop$s$>>|p,`IterOver(e)-><:expr<Lwt_stream.iter_s(fun$p$->$seq$)$e$>>|_->Loc.raise_loc(Failure"syntax error"))|"raise_lwt";e=SELF->if!Pa_lwt_options.debugthen<:expr<Lwt.fail(tryraise$e$withexn->exn)>>else<:expr<Lwt.fail$e$>>|"assert_lwt";e=SELF-><:expr<tryLwt.return(assert$e$)withexn->Lwt.failexn>>|"while_lwt";cond=sequence;"do";body=sequence;"done"-><:expr<letrec__pa_lwt_loop()=if$cond$thenLwt.bind(begin$body$end)__pa_lwt_loopelseLwt.return()in__pa_lwt_loop()>>|"match_lwt";e=sequence;"with";c=match_case-><:expr<Lwt.bind(begin$e$end)(function$c$)>>]];str_item:[["lwt";l=letb_binding->beginmatchlwith|[(_loc,p,e)]-><:str_item<let$p$=Lwt_main.run$e$>>|_-><:str_item<let$tup:Ast.paCom_of_list(List.map(fun(_loc,p,_e)->p)l)$=Lwt_main.runbeginlet$gen_bindingl$in$gen_top_bind_locl$end>>end|"lwt";l=letb_binding;"in";e=expr-><:str_item<let()=Lwt_main.run(let$gen_bindingl$in$gen_bindle$)>>]];END(* Replace the anonymous bind [x >> y] by [x >>= fun _ -> y] or [x >>= fun () ->
y] if the strict sequence flag is used. *)letmap_anonymous_bind=objectinheritAst.mapassupermethod!expre=matchsuper#exprewith|<:expr@_loc<$lid:f$$a$$b$>>whenf=">>"->if!Pa_lwt_options.strict_sequencethen<:expr<Lwt.bind$a$(fun()->$b$)>>else<:expr<Lwt.bind$a$(fun_->$b$)>>|e->eendlet_=AstFilters.register_str_item_filtermap_anonymous_bind#str_item;AstFilters.register_topphrase_filtermap_anonymous_bind#str_item