Version française
Home     About     Download     Resources     Contact us    
Browse thread
Wrapping sigsetjmps/siglongjmps in OCaml.
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Guillaume Yziquel <guillaume.yziquel@c...>
Subject: Wrapping sigsetjmps/siglongjmps in OCaml.
Hello.

I'm having some problems wrapping up the API for the R interpreter, 
namely because R seems to be using sigsetjmps and siglongjmps 
everywhere: that's how looping is implemented, for instance. (At least 
that's how I understand the source code).

So I was wondering: what's the "best" way to wrap up such jumps in OCaml 
code? It may be that the jumps would happen in one single C function. Or 
it may be, due to a rather restrictive API for R, that I may have to 
reimplement some C code entirely in OCaml. In which case, the jumps 
would go over OCaml code.

How would you deal with that?


Here's the LONGJMP:

SETJMP and LONGJMP are just macros to sigsetjmp and siglongjmp.

> /* jumpfun - jump to the named context */
> 
> static void jumpfun(RCNTXT * cptr, int mask, SEXP val)
> {
>     Rboolean savevis = R_Visible;
> 
>     /* run onexit/cend code for all contexts down to but not including
>        the jump target */
>     PROTECT(val);
>     R_run_onexits(cptr);
>     UNPROTECT(1);
>     R_Visible = savevis;
> 
>     R_ReturnedValue = val;
>     R_GlobalContext = cptr; /* this used to be set to
>                                cptr->nextcontext for non-toplevel
>                                jumps (with the context set back at the
>                                SETJMP for restarts).  Changing this to
>                                always using cptr as the new global
>                                context should simplify some code and
>                                perhaps allow loops to be handled with
>                                fewer SETJMP's.  LT */
>     R_restore_globals(R_GlobalContext);
> 
>     LONGJMP(cptr->cjmpbuf, mask);
> }

Here's the SETJMP

> SEXP applyClosure(SEXP call, SEXP op, SEXP arglist, SEXP rho, SEXP suppliedenv)
> {
>     SEXP body, formals, actuals, savedrho;
>     volatile  SEXP newrho;
>     SEXP f, a, tmp;
>     RCNTXT cntxt;
> 
>     /* formals = list of formal parameters */
>     /* actuals = values to be bound to formals */
>     /* arglist = the tagged list of arguments */
> 
>     formals = FORMALS(op);
>     body = BODY(op);
>     savedrho = CLOENV(op);
>
> [...]
>
>     /*  Set a longjmp target which will catch any explicit returns
>         from the function body.  */
> 
>     if ((SETJMP(cntxt.cjmpbuf))) {
>         if (R_ReturnedValue == R_RestartToken) {
>             cntxt.callflag = CTXT_RETURN;  /* turn restart off */
>             R_ReturnedValue = R_NilValue;  /* remove restart token */
>             PROTECT(tmp = eval(body, newrho));
>         }
>         else
>             PROTECT(tmp = R_ReturnedValue);
>     }
>     else {
>         PROTECT(tmp = eval(body, newrho));
>     }
> 
>     endcontext(&cntxt);
> 
>     if (RDEBUG(op)) {
>         Rprintf("exiting from: ");
>         PrintValueRec(call, rho);
>     }
>     UNPROTECT(3);
>     return (tmp);
> }

All the best,

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/