caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] hash_variant anomalies
@ 2001-07-03  1:02 Miles Egan
  2001-07-03  2:18 ` Chris Quinn
  2001-07-03  7:42 ` Xavier Leroy
  0 siblings, 2 replies; 6+ messages in thread
From: Miles Egan @ 2001-07-03  1:02 UTC (permalink / raw)
  To: caml-list

The manual states:

<quote>
Like constructed terms, values of variant types are represented either as
integers (for variants without arguments), or as blocks (for variants with an
argument). Unlike constructed terms, variant constructors are not numbered
starting from 0, but identified by a hash value (a Caml integer), as computed by
the C function hash_variant (declared in <caml/mlvalues.h>): the hash value for
a variant constructor named, say, VConstr is hash_value("VConstr").

The variant value `VConstr is represented by hash_value("VConstr"). The variant
value `VConstr(v) is represented by a block of size 2 and tag 0, with field
number 0 containing hash_value("VConstr") and field number 1 containing v.
</quote>

This test program seems to indicate otherwise:

*** test.c ***
------------------------------------------------------------------
#include <stdio.h>
#include <caml/mlvalues.h>

void c_calc_variant(value variant)
{
    printf(
        "variant '%s' gives %d\n", 
        String_val(variant),
        hash_variant(String_val(variant)));
}

void c_print_variant(value variant)
{
    printf("variant is %d\n", variant);
}

*** test.ml ***
------------------------------------------------------------------
type t = YES | NO | MAYBE
type p = [`YES | `NO | `MAYBE]

external calc_variant: string -> unit = "c_calc_variant"
external print_variant: t -> unit = "c_print_variant"
external print_pvariant: p -> unit = "c_print_variant"

let _ =
  calc_variant "YES";
  print_variant YES;
  calc_variant "NO";
  print_variant NO;
  calc_variant "MAYBE";
  print_variant MAYBE;
  calc_variant "`YES";
  print_pvariant `YES;
  calc_variant "`NO";
  print_pvariant `NO;
  calc_variant "`MAYBE";
  print_variant MAYBE


when compiled (ocaml -c test.c; ocamlc -o test -custom test.o test.ml) gives
this:

<quote>
variant 'YES' gives 8882703
variant is 1
variant 'NO' gives 34947
variant is 3
variant 'MAYBE' gives 36345617
variant is 5
variant '`YES' gives 2138079567
variant is 8882703
variant '`NO' gives 9582915
variant is 34947
variant '`MAYBE' gives -961552815
variant is 5
</quote>

It seems that the polymorphic variants are indeed calculated with hash_variant.
The plain variants, however, are numbered incrementally starting at 1 and
stepping by two, which seems to contradict the manual.  Am I reading the manual
incorrectly?  

Also the manual states that both functions "hash_value" and "hash_variant" are
used to compute the value of variants, but mlvalues.h seems to declare only
"hash_variant".  Is there a "hash_value" function?  If so, where is it declared?

Last, the varcc utility supplied with lablgtk is quite handy when writing
bindings for c libraries with a lot of c constants.  Is there any prospect of
including it in the ocaml distribution?

--
miles
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


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

* Re: [Caml-list] hash_variant anomalies
  2001-07-03  1:02 [Caml-list] hash_variant anomalies Miles Egan
@ 2001-07-03  2:18 ` Chris Quinn
  2001-07-03  7:42 ` Xavier Leroy
  1 sibling, 0 replies; 6+ messages in thread
From: Chris Quinn @ 2001-07-03  2:18 UTC (permalink / raw)
  To: Miles Egan; +Cc: caml-list

The Caml runtime makes a basic distinction between memory pointers and everything else - pointers are mod 2 while everything else is shifted along 1 bit and has the lsb set to 1. This allows for operation of the garbage collector. Integers are in the 'everything else' camp so 0 maps to 1, 1 to 3 ...etc.
The macros Val_int(x) and Int_val(v) allow for conversion to and from caml integer values and appropriate use of these will correct the apparent anomaly.
-- 
Chris Quinn
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


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

* Re: [Caml-list] hash_variant anomalies
  2001-07-03  1:02 [Caml-list] hash_variant anomalies Miles Egan
  2001-07-03  2:18 ` Chris Quinn
@ 2001-07-03  7:42 ` Xavier Leroy
  2001-07-03 15:15   ` Miles Egan
  1 sibling, 1 reply; 6+ messages in thread
From: Xavier Leroy @ 2001-07-03  7:42 UTC (permalink / raw)
  To: Miles Egan; +Cc: caml-list

> [Question on tags for constant constructors and constant variant
> constructors]

> This test program seems to indicate otherwise:

No, no, it works as described in the manual, with two caveats:

1- The argument to hash_value() is the name of the variant constructor
without the leading ` (it's a syntactic marker, not part of the
constructor name), hence your test program should be:

> let _ =
>   calc_variant "YES";
>   print_variant YES;
>   calc_variant "NO";
>   print_variant NO;
>   calc_variant "MAYBE";
>   print_variant MAYBE;
>   calc_variant "YES";   <-- removed `
>   print_pvariant `YES;
>   calc_variant "NO";    <-- removed `
>   print_pvariant `NO;
>   calc_variant "MAYBE"; <-- removed `
>   print_pvariant `MAYBE  <-- there was a missing p and a missing `

With these corrections, I get:

variant 'YES' gives 8882703
variant is 1
variant 'NO' gives 34947
variant is 3
variant 'MAYBE' gives 36345617
variant is 5
variant 'YES' gives 8882703
variant is 8882703
variant 'NO' gives 34947
variant is 34947
variant 'MAYBE' gives 36345617
variant is 36345617

2- Owing to the Caml encoding of integers (integer N is represented by
the bit pattern for 2N+1), when the manual says that constant
constructors are numbered starting from 0, it really means that the
constant constructors are represented by the representation of 0, the
representation of 1, etc, that is, by 1, 3, etc.

In contrast, the return value of hash_value() is not a C integer but a
Caml value representing an already encoded integer.

> Also the manual states that both functions "hash_value" and
> "hash_variant" are used to compute the value of variants, but
> mlvalues.h seems to declare only "hash_variant".

Right, that's a typo in the manual: hash_variant() is the correct
function.

- Xavier Leroy
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


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

* Re: [Caml-list] hash_variant anomalies
  2001-07-03  7:42 ` Xavier Leroy
@ 2001-07-03 15:15   ` Miles Egan
  2001-07-04  0:19     ` Jacques Garrigue
  0 siblings, 1 reply; 6+ messages in thread
From: Miles Egan @ 2001-07-03 15:15 UTC (permalink / raw)
  To: caml-list

On Tue, Jul 03, 2001 at 09:42:10AM +0200, Xavier Leroy wrote:
> 2- Owing to the Caml encoding of integers (integer N is represented by
> the bit pattern for 2N+1), when the manual says that constant
> constructors are numbered starting from 0, it really means that the
> constant constructors are represented by the representation of 0, the
> representation of 1, etc, that is, by 1, 3, etc.

Ok.  That makes sense.  I think this language is a bit confusing:

"""
the hash value for a variant constructor named, say, VConstr is
hash_value("VConstr").

The variant value `VConstr is represented by hash_value("VConstr"). The variant
value `VConstr(v) is represented by a block of size 2 and tag 0, with field
number 0 containing hash_value("VConstr") and field number 1 containing v.
"""

What wasn't clear to me is that both sentences are referring to polymorphic
variants, when they seem to be comparing the properties of normal variants and
polymorphic variants.  Chapter 2 of the manual uses the term "variant" to refer to
both kinds of variants, so when I see a sentence describing a variant "VConstr"
and a variant "`VConstr" I assume it's referring to both types.

I guess the upshot of all this is that it's much easier to map polymorphic
variants to C constants because there's no easy way to calculate the integer
value of a normal variant without knowing it's position in the variant
declaration.  The integer value of a polymorphic variant can be computed
directly from its name alone.

Overall I have to say writing ocaml-c interfaces is pretty easy.  Mapping long
lists of c enums and defines to ocaml variants seems to be one of the more
tedious tasks.

-- 
miles
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


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

* Re: [Caml-list] hash_variant anomalies
  2001-07-03 15:15   ` Miles Egan
@ 2001-07-04  0:19     ` Jacques Garrigue
  2001-07-05  5:58       ` Miles Egan
  0 siblings, 1 reply; 6+ messages in thread
From: Jacques Garrigue @ 2001-07-04  0:19 UTC (permalink / raw)
  To: miles; +Cc: caml-list

> I guess the upshot of all this is that it's much easier to map
> polymorphic variants to C constants because there's no easy way to
> calculate the integer value of a normal variant without knowing it's
> position in the variant declaration.  The integer value of a
> polymorphic variant can be computed directly from its name alone.

Hard to say which is hardest: in both cases you must be careful to
synchronize your sources, and avoid typos. Polymorphic variants are
a bit stronger to ansynchronies, since they are by name.

> Overall I have to say writing ocaml-c interfaces is pretty easy.
> Mapping long lists of c enums and defines to ocaml variants seems to
> be one of the more tedious tasks.

Doesn't ocamlidl provide some help with standard variants?
For polymorphic variants, there is a tool called varcc in the lablgtk
distribution. There is no documentation, but examples and source code
should be informative enough. It generates efficient conversion tables
and macros between polymorphic variants and C enums.

Cheers,

Jacques Garrigue
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


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

* Re: [Caml-list] hash_variant anomalies
  2001-07-04  0:19     ` Jacques Garrigue
@ 2001-07-05  5:58       ` Miles Egan
  0 siblings, 0 replies; 6+ messages in thread
From: Miles Egan @ 2001-07-05  5:58 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list

On Wed, Jul 04, 2001 at 09:19:44AM +0900, Jacques Garrigue wrote:
> > Overall I have to say writing ocaml-c interfaces is pretty easy.
> > Mapping long lists of c enums and defines to ocaml variants seems to
> > be one of the more tedious tasks.
> 
> Doesn't ocamlidl provide some help with standard variants?
> For polymorphic variants, there is a tool called varcc in the lablgtk
> distribution. There is no documentation, but examples and source code
> should be informative enough. It generates efficient conversion tables
> and macros between polymorphic variants and C enums.

I've already taken the liberty of "borrowing" varcc for my little project,
thanks.  Very handy.  In my last message I suggested that varcc or a tool like
it might be included in the ocaml distribution.

-- 
miles
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


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

end of thread, other threads:[~2001-07-05  5:59 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-07-03  1:02 [Caml-list] hash_variant anomalies Miles Egan
2001-07-03  2:18 ` Chris Quinn
2001-07-03  7:42 ` Xavier Leroy
2001-07-03 15:15   ` Miles Egan
2001-07-04  0:19     ` Jacques Garrigue
2001-07-05  5:58       ` Miles Egan

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