caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* How to raise_with_arg() a tuple?
@ 2005-07-07 18:05 Thomas Fischbacher
  2005-07-07 18:42 ` [Caml-list] " Olivier Andrieu
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Fischbacher @ 2005-07-07 18:05 UTC (permalink / raw)
  To: caml-list


Hello together,

I'd like to throw an exception from within C code which provides more 
information to Caml than just a string.

If I do it that way:

=== Caml ===

exception Test_exn of int * int

external test_raise_tuple: bool -> (int*int) = "caml_test_raise_tuple"

let _ = Callback.register_exception "ocaml_exn_test" (Test_exn (0,0));;

=== C ===

CAMLprim caml_test_raise_tuple(value x)
{
  CAMLparam1(x);
  int cx;

  cx=Int_val(x);
  fprintf(stderr,"DDD x=%d\n",cx);

  CAMLlocal1(ex);
  ex=alloc_tuple(2);

  Store_field(ex,0,Val_int(2));
  Store_field(ex,1,Val_int(4));

  if(cx)
    {
      raise_with_arg(*caml_named_value("ocaml_exn_test"), ex);
    }
  else
    {
      CAMLreturn(ex);
    }
}

======

...then just returning the tuple works as expected,
but throwing the tuple gives me crazy values - like 

Test_exn (67385386, 1408)

instead of

Test_exn (2,4).

Does anyone have an idea what is going on here, and how to repair this? 
Maybe I just missed something essential in the documentation. I tried to 
find an example in existing OCaml libraries where this is used, but 
somehow I was out of luck there so far... All I found about this 
issue is this bit of documentation in ocaml's byterun/memory.h:

===>
   Your function may raise an exception or return a [value] with the
   [CAMLreturn] macro.  Its argument is simply the [value] returned by
   your function.  Do NOT directly return a [value] with the [return]
   keyword.  If your function returns void, use [CAMLreturn0].
<===

...and the definition says:

===>
#define CAMLreturn(result) do{ \
  caml_local_roots = caml__frame; \
  return (result); \
}while(0)
<===

I tried a few obvious and non-obvious things related to what I see in 
there, but without success so far. So, how does one do that?

-- 
regards,               tf@cip.physik.uni-muenchen.de              (o_
 Thomas Fischbacher -  http://www.cip.physik.uni-muenchen.de/~tf  //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y)           V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1))                  (Debian GNU)


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

* Re: [Caml-list] How to raise_with_arg() a tuple?
  2005-07-07 18:05 How to raise_with_arg() a tuple? Thomas Fischbacher
@ 2005-07-07 18:42 ` Olivier Andrieu
  2005-07-08 15:55   ` Thomas Fischbacher
  0 siblings, 1 reply; 5+ messages in thread
From: Olivier Andrieu @ 2005-07-07 18:42 UTC (permalink / raw)
  To: Thomas Fischbacher; +Cc: caml-list

 Thomas Fischbacher [Thursday 7 July 2005] :
 >
 > 
 > Hello together,
 > 
 > I'd like to throw an exception from within C code which provides
 > more information to Caml than just a string.
 > 
 > If I do it that way:
 > 
 > === Caml ===
 > 
 > exception Test_exn of int * int

It's the usual gotcha with variant constructor that have multiple
arguments. The exception you defines has two arguments, whereas 

 exception Test_exn of (int * int)

has only one argument -- a tuple. It's not the same thing.

 > external test_raise_tuple: bool -> (int*int) = "caml_test_raise_tuple"
 > 
 > let _ = Callback.register_exception "ocaml_exn_test" (Test_exn (0,0));;
 > 
 > === C ===
 > 
 > CAMLprim caml_test_raise_tuple(value x)
 > {
 >   CAMLparam1(x);
 >   int cx;
 > 
 >   cx=Int_val(x);
 >   fprintf(stderr,"DDD x=%d\n",cx);
 > 
 >   CAMLlocal1(ex);
 >   ex=alloc_tuple(2);
 > 
 >   Store_field(ex,0,Val_int(2));
 >   Store_field(ex,1,Val_int(4));
 > 
 >   if(cx)
 >     {
 >       raise_with_arg(*caml_named_value("ocaml_exn_test"), ex);

here you are raising an exception with one tuple argument, this
doesn't match the exception you defined.

There's no function to directly create an exception value with
multiple argument, you have to do this (IIRC, not tested) :

  ex = alloc(3, 0);
  Store_field(ex, 0, *caml_named_value("ocaml_exn_test");
  Store_field(ex, 1, Val_int(2));
  Store_field(ex, 2, Val_int(4));
  caml_raise(ex);

 > ===>
 >  Your function may raise an exception or return a [value] with the
 >  [CAMLreturn] macro.  Its argument is simply the [value] returned by
 >  your function.  Do NOT directly return a [value] with the [return]
 >  keyword.  If your function returns void, use [CAMLreturn0].
 > <===

actually it's ok to raise exception directly (ie, not through
CAMLreturn), the runtime takes care of releasing the local GC roots.

-- 
   Olivier


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

* Re: [Caml-list] How to raise_with_arg() a tuple?
  2005-07-07 18:42 ` [Caml-list] " Olivier Andrieu
@ 2005-07-08 15:55   ` Thomas Fischbacher
  2005-07-08 16:24     ` Kenneth Knowles
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Fischbacher @ 2005-07-08 15:55 UTC (permalink / raw)
  To: Olivier Andrieu; +Cc: caml-list


On Thu, 7 Jul 2005, Olivier Andrieu wrote:

>  > exception Test_exn of int * int
> 
> It's the usual gotcha with variant constructor that have multiple
> arguments. The exception you defines has two arguments, whereas 
> 
>  exception Test_exn of (int * int)
> 
> has only one argument -- a tuple. It's not the same thing.

Oh dear. Indeed, if I just put parens around int * int, then everything is fine.

I don't know how other readers on the list think about this, but somehow 
I consider this a pretty bad tripwire. After all, I would not have 
expected behaviour like this:

# type foo =
 | Foo1 of int * int
 | Foo2 of (int * int)
;;
      type foo = Foo1 of int * int | Foo2 of (int * int)
# Foo1 (2,3);;
- : foo = Foo1 (2, 3)
# Foo2 (2,3);;
- : foo = Foo2 (2, 3)
# let x = (2,3) in Foo1 x;;
Characters 17-23:
  let x = (2,3) in Foo1 x;;
                   ^^^^^^
The constructor Foo1 expects 2 argument(s),
but is here applied to 1 argument(s)
# let x = (2,3) in Foo2 x;;
- : foo = Foo2 (2, 3)
# Foo1 2 3;;
Characters 7-8:
  Foo1 2 3;;
         ^
Syntax error

While it is certainly nice that there is an OCaml equivalent (I presume) 
of what would be written in Haskell as:

data Foo =
    Foo1 (Int,Int)
  | Foo2 Int Int
    deriving Show

Main> :load /tmp/1.hs
Main> Foo1 (2,3)
Foo1 (2,3)
Main> Foo2 2 3
Foo2 2 3

(I did not know about this so far!), the syntax used by ocaml certainly is 
quite misleading. As well, it seems to be a bit un-orthogonal here: after 
all, I cannot do this in OCaml (while it is allowed in Haskell, and might 
also be quite useful occasionally):

# Foo1 2;;
Characters 0-6:
  Foo1 2;;
  ^^^^^^
The constructor Foo1 expects 2 argument(s),
but is here applied to 1 argument(s)

Just as a further question, not to be meant as a suggestion or wishlist 
item: would it be conceivable that, at some point in the future, all the 
ocaml tools that operate on .ml files could accept different 
official "syntax variants" (say, the present one and a cleaned up syntax 
to be defined in the future), and dispatch between parsers via some 
command line argument or argv[0]? So that minor issues with the syntax 
could be repaired, should they turn out to be a problem.

> actually it's ok to raise exception directly (ie, not through
> CAMLreturn), the runtime takes care of releasing the local GC roots.

Many thanks again for your explanation.

-- 
regards,               tf@cip.physik.uni-muenchen.de              (o_
 Thomas Fischbacher -  http://www.cip.physik.uni-muenchen.de/~tf  //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y)           V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1))                  (Debian GNU)


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

* Re: [Caml-list] How to raise_with_arg() a tuple?
  2005-07-08 15:55   ` Thomas Fischbacher
@ 2005-07-08 16:24     ` Kenneth Knowles
  2005-07-08 16:58       ` Thomas Fischbacher
  0 siblings, 1 reply; 5+ messages in thread
From: Kenneth Knowles @ 2005-07-08 16:24 UTC (permalink / raw)
  To: Thomas Fischbacher; +Cc: caml-list

On Fri, Jul 08, 2005 at 05:55:38PM +0200, Thomas Fischbacher wrote:
> Just as a further question, not to be meant as a suggestion or wishlist 
> item: would it be conceivable that, at some point in the future, all the 
> ocaml tools that operate on .ml files could accept different 
> official "syntax variants" (say, the present one and a cleaned up syntax 
> to be defined in the future), and dispatch between parsers via some 
> command line argument or argv[0]? So that minor issues with the syntax 
> could be repaired, should they turn out to be a problem.

This exists, and is called camlp4.  I'm not sure which, if any, of the tools
that operate on .ml files doesn't "support" it via easy command line flags.

There is even a revised syntax shipped with camlp4 which has curried variant
constructors like Haskell.  Unfortunately, there's a lot of stuff in there I
disagree with, like extra bracketing of many constructs.

Here it is:

http://pauillac.inria.fr/caml/camlp4/manual/manual007.html

Forgive me if you already know of this and I misinterpreted your question.
 
- Kenn


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

* Re: [Caml-list] How to raise_with_arg() a tuple?
  2005-07-08 16:24     ` Kenneth Knowles
@ 2005-07-08 16:58       ` Thomas Fischbacher
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Fischbacher @ 2005-07-08 16:58 UTC (permalink / raw)
  To: Kenneth Knowles; +Cc: caml-list


On Fri, 8 Jul 2005, Kenneth Knowles wrote:

> This exists, and is called camlp4.  I'm not sure which, if any, of the tools
> that operate on .ml files doesn't "support" it via easy command line flags.
> 
> There is even a revised syntax shipped with camlp4 which has curried variant
> constructors like Haskell.  Unfortunately, there's a lot of stuff in there I
> disagree with, like extra bracketing of many constructs.

Many thanks for that tip! I really missed that so far - I knew about 
camlp4's existence, but just did not have an incentive to have a closer 
look. Well, now I have.

> http://pauillac.inria.fr/caml/camlp4/manual/manual007.html

I would say that I'd agree with ~85% of what's in there, so for me it's 
definitely an improvement. Thanks.

-- 
regards,               tf@cip.physik.uni-muenchen.de              (o_
 Thomas Fischbacher -  http://www.cip.physik.uni-muenchen.de/~tf  //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y)           V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1))                  (Debian GNU)


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

end of thread, other threads:[~2005-07-08 16:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-07-07 18:05 How to raise_with_arg() a tuple? Thomas Fischbacher
2005-07-07 18:42 ` [Caml-list] " Olivier Andrieu
2005-07-08 15:55   ` Thomas Fischbacher
2005-07-08 16:24     ` Kenneth Knowles
2005-07-08 16:58       ` Thomas Fischbacher

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).