caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Converting variants with only constant constructors to integers
@ 2010-06-07 18:07 Török Edwin
  2010-06-07 18:25 ` [Caml-list] " W Dan Meyer
                   ` (2 more replies)
  0 siblings, 3 replies; 23+ messages in thread
From: Török Edwin @ 2010-06-07 18:07 UTC (permalink / raw)
  To: caml-list

Hi,

What is the recommended way to convert a variant that has only constant
constructors to an integer? (an integer that is unique for each constant
constructor, preferably sequential in the order in which they are declared).

I found the following two possibilities, but I am not sure if these are
guaranteed to return the same results for future versions of OCaml or not:

let int_of_constant_variant a : int = Hashtbl.hash a;;
let int_of_constant_variant a : int =
 let r = Obj.repr a in
  assert (Obj.is_int r);
  (Obj.magic r : int);;

for 'type t = A | C | B', both of these functions return 0,1, and 2 for
A,C, and B respectively.

Best regards,
--Edwin


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

* Re: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-07 18:07 Converting variants with only constant constructors to integers Török Edwin
@ 2010-06-07 18:25 ` W Dan Meyer
  2010-06-07 18:45   ` bluestorm
       [not found] ` <87sk4y7lc7.fsf@gmail.com>
  2010-06-07 18:48 ` David Allsopp
  2 siblings, 1 reply; 23+ messages in thread
From: W Dan Meyer @ 2010-06-07 18:25 UTC (permalink / raw)
  To: Török Edwin; +Cc: caml-list


Török Edwin <edwintorok@gmail.com> writes:

> What is the recommended way to convert a variant that has only constant
> constructors to an integer? (an integer that is unique for each constant
> constructor, preferably sequential in the order in which they are declared).

In the first play you'd need to tell us, why would you need this, and
then maybe there are other solutions to your problem.
Most likely Marshal module from stdlib, will full-fill your requirements.

I can imagine you could use an association list, function with pattern
matching, code generation tool (based on CamlP4), etc.

The later would be needed if you have varied data structure, that change
frequently or it is too big to maintain it with just pattern matching.

>
> I found the following two possibilities, but I am not sure if these are
> guaranteed to return the same results for future versions of OCaml or not:
>
> let int_of_constant_variant a : int = Hashtbl.hash a;;
> let int_of_constant_variant a : int =
>  let r = Obj.repr a in
>   assert (Obj.is_int r);
>   (Obj.magic r : int);;

There is no guarantee of these kind of unsafe casts at all (means using
Obj.magic). Especially Obj.magic should not be used in marshaling, but
most common patter is for type system tricks.

Wojciech


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

* Re: [Caml-list] Converting variants with only constant constructors to integers
       [not found]   ` <4C0D3B0F.4060502@gmail.com>
@ 2010-06-07 18:32     ` Török Edwin
  2010-06-07 18:50       ` W Dan Meyer
  0 siblings, 1 reply; 23+ messages in thread
From: Török Edwin @ 2010-06-07 18:32 UTC (permalink / raw)
  To: Wojciech Meyer; +Cc: caml-list

On 06/07/2010 09:31 PM, Török Edwin wrote:
> On 06/07/2010 09:23 PM, Wojciech Meyer wrote:
>> Török Edwin <edwintorok@gmail.com> writes:
>>
>>> What is the recommended way to convert a variant that has only constant
>>> constructors to an integer? (an integer that is unique for each constant
>>> constructor, preferably sequential in the order in which they are declared).
>>
>> In the first play you'd need to tell us, why would you need this
> 
> Yes, I probably should have started with that.
> I have some flags like:
> type myflags = Property1 | Property2 | Property3;;
> 
> I have something similar code in C, as an enum.
> I need to convert to convert OCaml lists of flags to an integer, that
> will ultimately be passed to a C function.
> 
> So [Property1; Property3] needs to become (1 << Property1) | (1 <<
> Property3). I want to do this conversion in OCaml code.
> 
> Important is that "Property1" from OCaml gets the same value as
> Property1 in the C enum.
> 
>> , and
>> then maybe there are other solutions to your problem.
>> Most likely Marshal module from stdlib, will full-fill your requirements.
> 
> If I only had OCaml code to deal with yes, but see above.
> 
>>
>> I can imagine you could use an association list, function with pattern
>> matching
> 
> I don't have too many flags, so I could write a simple pattern matching
> function to convert to int (even manually).
> I just thought there is a way to do this easily, and more general than that.
> 
>> , code generation tool (based on CamlP4), etc.
>>
>> The later would be needed if you have varied data structure, that change
>> frequently or it is too big to maintain it with just pattern matching.
>>
>>>
>>> I found the following two possibilities, but I am not sure if these are
>>> guaranteed to return the same results for future versions of OCaml or not:
>>>
>>> let int_of_constant_variant a : int = Hashtbl.hash a;;
>>> let int_of_constant_variant a : int =
>>>  let r = Obj.repr a in
>>>   assert (Obj.is_int r);
>>>   (Obj.magic r : int);;
>>
>> There is no guarantee of these kind of unsafe casts at all (means using
>> Obj.magic). Especially Obj.magic should not be used in marshaling, but
>> most common patter is for type system tricks.
> 
> How about the hash value? I guess no guarantees about that either.
> 
> Best regards,
> --Edwin


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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-07 18:25 ` [Caml-list] " W Dan Meyer
@ 2010-06-07 18:45   ` bluestorm
  0 siblings, 0 replies; 23+ messages in thread
From: bluestorm @ 2010-06-07 18:45 UTC (permalink / raw)
  To: W Dan Meyer; +Cc: Török Edwin, caml-list

[-- Attachment #1: Type: text/plain, Size: 692 bytes --]

2010/6/7 W Dan Meyer <wojciech.meyer@googlemail.com>
> I can imagine you could use an association list, function with pattern
> matching, code generation tool (based on CamlP4), etc.

I wrote a type-conv (
http://www.ocaml.info/home/ocaml_sources.html#type-conv ) generator for just
that a few years ago :
   http://bluestorm.info/camlp4/ty_enum_to_int.ml.html

Example use :

  type test = | A | B | C | D of bool with to_int


Generated functions :

  let test_to_int = function | A -> 0 | B -> 1 | C -> 2 | D _ -> 3

  let test_of_int = function
  | 0 -> A
  | 1 -> B
  | 2 -> C
  | 3 -> failwith "can't convert to a constructor with parameters: D"
  | _ -> invalid_argument "test_of_int"

[-- Attachment #2: Type: text/html, Size: 1027 bytes --]

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

* RE: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-07 18:07 Converting variants with only constant constructors to integers Török Edwin
  2010-06-07 18:25 ` [Caml-list] " W Dan Meyer
       [not found] ` <87sk4y7lc7.fsf@gmail.com>
@ 2010-06-07 18:48 ` David Allsopp
  2010-06-07 19:46   ` Török Edwin
  2 siblings, 1 reply; 23+ messages in thread
From: David Allsopp @ 2010-06-07 18:48 UTC (permalink / raw)
  To: 'Török Edwin', caml-list

Török Edwin wrote:
> What is the recommended way to convert a variant that has only constant
> constructors to an integer? (an integer that is unique for each constant
> constructor, preferably sequential in the order in which they are
> declared).

type foo = A | B;;
external int_of_foo : foo -> int = "%identity";;

Which is another way of saying Obj.magic - but %identity is an OCaml
primitive, where Obj.magic is part of a restricted module so there is a
small semantic difference in terms of future support. The internal
representation of variants won't change until at least OCaml 4.0.0 -
there're simply far too many C bindings out there! foo_of_int obviously
can't be done quite so trivially written although having checked that the
int represents a valid constructor you can then use %identity in the same
way.


David 


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

* Re: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-07 18:32     ` Török Edwin
@ 2010-06-07 18:50       ` W Dan Meyer
  0 siblings, 0 replies; 23+ messages in thread
From: W Dan Meyer @ 2010-06-07 18:50 UTC (permalink / raw)
  To: Török Edwin; +Cc: Wojciech Meyer, caml-list


Török Edwin <edwintorok@gmail.com> writes:

>
> Yes, I probably should have started with that.
> I have some flags like:
> type myflags = Property1 | Property2 | Property3;;

Hmm, you can take a look at lablgl sources, they use a lot this kind of
constructs.

Here is the answer:
CAMLprim value ml_glPushAttrib (value list)
{
    GLbitfield mask = 0;

    while (list != Val_int(0)) {
	switch (Field(list,0)) {
	case MLTAG_accum_buffer:mask |= GL_ACCUM_BUFFER_BIT; break;
	case MLTAG_color_buffer:mask |= GL_COLOR_BUFFER_BIT; break;
	case MLTAG_current:	mask |= GL_CURRENT_BIT; break;
	case MLTAG_depth_buffer:mask |= GL_DEPTH_BUFFER_BIT; break;
	case MLTAG_enable:	mask |= GL_ENABLE_BIT; break;
	case MLTAG_eval:	mask |= GL_EVAL_BIT; break;
	case MLTAG_fog:		mask |= GL_FOG_BIT; break;
	case MLTAG_hint:	mask |= GL_HINT_BIT; break;
	case MLTAG_lighting:	mask |= GL_LIGHTING_BIT; break;
	case MLTAG_line:	mask |= GL_LINE_BIT; break;
	case MLTAG_list:	mask |= GL_LIST_BIT; break;
	case MLTAG_pixel_mode:	mask |= GL_PIXEL_MODE_BIT; break;
	case MLTAG_point:	mask |= GL_POINT_BIT; break;
	case MLTAG_polygon:	mask |= GL_POLYGON_BIT; break;
	case MLTAG_polygon_stipple:mask |= GL_POLYGON_STIPPLE_BIT; break;
	case MLTAG_scissor:	mask |= GL_SCISSOR_BIT; break;
	case MLTAG_stencil_buffer:mask |= GL_STENCIL_BUFFER_BIT; break;
	case MLTAG_texture:	mask |= GL_TEXTURE_BIT; break;
	case MLTAG_transform:	mask |= GL_TRANSFORM_BIT; break;
	case MLTAG_viewport:	mask |= GL_VIEWPORT_BIT; break;
	}
	list = Field(list,1);
    }
    glPushAttrib (mask);
    return Val_unit;
}

where is the MLTAG is define like this:

struct record {
    value key; 
    GLenum data;
};

static struct record input_table[] = {
#include "gl_tags.c"
};

where:

    {MLTAG_color, GL_COLOR},
    {MLTAG_depth, GL_DEPTH},
    {MLTAG_accum, GL_ACCUM},
    {MLTAG_stencil, GL_STENCIL},
    {MLTAG_points, GL_POINTS},

where:

#define MLTAG_color	Val_int(-899911325)
#define MLTAG_depth	Val_int(-685117181)
(...)

aha!
-rwxr-xr-x 1 spec spec 86334 2010-05-31 13:51 var2switch
-rwxr-xr-x 1 spec spec 81183 2010-05-31 13:51 var2def

plus this:
gl_tags.var:
(* GLenum *)

color
depth
accum
stencil
points
lines
polygon
triangles
quads
line_strip
line_loop
triangle_strip
triangle_fan
quad_strip     

(...)

gives an answer: they are generated from OCaml code.

> Best regards,
> --Edwin

Wojciech


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

* Re: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-07 18:48 ` David Allsopp
@ 2010-06-07 19:46   ` Török Edwin
  2010-06-07 19:56     ` bluestorm
  0 siblings, 1 reply; 23+ messages in thread
From: Török Edwin @ 2010-06-07 19:46 UTC (permalink / raw)
  To: David Allsopp, bluestorm; +Cc: caml-list

On 06/07/2010 09:48 PM, David Allsopp wrote:
> Török Edwin wrote:
>> What is the recommended way to convert a variant that has only constant
>> constructors to an integer? (an integer that is unique for each constant
>> constructor, preferably sequential in the order in which they are
>> declared).
> 
> type foo = A | B;;
> external int_of_foo : foo -> int = "%identity";;
> 
> Which is another way of saying Obj.magic - but %identity is an OCaml
> primitive, where Obj.magic is part of a restricted module so there is a
> small semantic difference in terms of future support. The internal
> representation of variants won't change until at least OCaml 4.0.0 -
> there're simply far too many C bindings out there! foo_of_int obviously
> can't be done quite so trivially written although having checked that the
> int represents a valid constructor you can then use %identity in the same
> way.

Thanks, that "%identity" looks exactly what I wanted.
I don't need a foo_of_int right now.

On 06/07/2010 09:45 PM, bluestorm wrote:
> 2010/6/7 W Dan Meyer <wojciech.meyer@googlemail.com
> <mailto:wojciech.meyer@googlemail.com>>
>> I can imagine you could use an association list, function with pattern
>> matching, code generation tool (based on CamlP4), etc.
>
> I wrote a type-conv (
> http://www.ocaml.info/home/ocaml_sources.html#type-conv ) generator for
> just that a few years ago :
>    http://bluestorm.info/camlp4/ty_enum_to_int.ml.html
>
> Example use :
>
>   type test = | A | B | C | D of bool with to_int
>
>
> Generated functions :
>
>   let test_to_int = function | A -> 0 | B -> 1 | C -> 2 | D _ -> 3
>
>   let test_of_int = function
>   | 0 -> A
>   | 1 -> B
>   | 2 -> C
>   | 3 -> failwith "can't convert to a constructor with parameters: D"
>   | _ -> invalid_argument "test_of_int"
>

If I'll need a foo_of_int this sounds like a good solution, thanks.

Best regards,
--Edwin


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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-07 19:46   ` Török Edwin
@ 2010-06-07 19:56     ` bluestorm
  2010-06-07 22:51       ` W Dan Meyer
  2010-06-08 11:28       ` Kaustuv Chaudhuri
  0 siblings, 2 replies; 23+ messages in thread
From: bluestorm @ 2010-06-07 19:56 UTC (permalink / raw)
  To: Török Edwin; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 389 bytes --]

Beware that "%identity" is an unsafe feature that breaks all safety
guarantees if used badly.

If you were, for example, to change your definition of "foo" (in a way not
always representable as integers, such as adding a constructor with
parameters), int_of_foo would become incorrect. The compiler wouldn't warn
you, and you could get pretty bad failures (segfaults). You're on your own.

[-- Attachment #2: Type: text/html, Size: 436 bytes --]

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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-07 19:56     ` bluestorm
@ 2010-06-07 22:51       ` W Dan Meyer
  2010-06-08  7:42         ` David Allsopp
  2010-06-08 11:28       ` Kaustuv Chaudhuri
  1 sibling, 1 reply; 23+ messages in thread
From: W Dan Meyer @ 2010-06-07 22:51 UTC (permalink / raw)
  To: bluestorm; +Cc: Török Edwin, caml-list

bluestorm <bluestorm.dylc@gmail.com> writes:

> Beware that "%identity" is an unsafe feature that breaks all safety guarantees
> if used badly.

Yes %identity is another solution. Although as safe as Obj.magic.
Sorry about posting code in the previous post.

>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs


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

* RE: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-07 22:51       ` W Dan Meyer
@ 2010-06-08  7:42         ` David Allsopp
  2010-06-08  7:59           ` bluestorm
  0 siblings, 1 reply; 23+ messages in thread
From: David Allsopp @ 2010-06-08  7:42 UTC (permalink / raw)
  To: 'W Dan Meyer', 'bluestorm'; +Cc: caml-list

W Dan Meyer wrote:
> bluestorm <bluestorm.dylc@gmail.com> writes:
> 
> > Beware that "%identity" is an unsafe feature that breaks all safety
> > guarantees if used badly.
> 
> Yes %identity is another solution. Although as safe as Obj.magic.

It's a bit pedantic but the %identity *primitive* is not the evil thing -
what is evil about Obj.magic is that it has an illegal type, namely 'a ->
'b. %identity constrained to a type like foo -> int is a safe use of it
(obviously with the side-condition that foo only has constant constructors,
as noted - but that's a local check, i.e. in your code, not your callers').

Incidentally, the general function for getting a unique integer for a
variant type with non-constant constructors isn't that bad either:

let int_of_gen x =
  let x = Obj.repr x
  in
    if Obj.is_block x
    then -1 * Obj.tag x - 1
    else (Obj.magic x : int) 

Naturally, any specific use should constrain the type of this function
beyond 'a -> int


David


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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-08  7:42         ` David Allsopp
@ 2010-06-08  7:59           ` bluestorm
  2010-06-08  9:14             ` David Allsopp
  0 siblings, 1 reply; 23+ messages in thread
From: bluestorm @ 2010-06-08  7:59 UTC (permalink / raw)
  To: David Allsopp; +Cc: W Dan Meyer, caml-list

[-- Attachment #1: Type: text/plain, Size: 934 bytes --]

>
> Incidentally, the general function for getting a unique integer for a
> variant type with non-constant constructors isn't that bad either:
>
> let int_of_gen x =
>  let x = Obj.repr x
>  in
>    if Obj.is_block x
>    then -1 * Obj.tag x - 1
>    else (Obj.magic x : int)
>

I consider that version much better. You could also write it in a more
restrictive way :

 let to_int x =
   let repr = Obj.repr x in
   if Obj.is_int repr
   then (Obj.obj repr : int)
   else invalid_arg "to_int";;

The good point about those is that they check that the memory representation
is compatible before casting (while the "%identity" does not). They're
safer. Of course, they still break parametricity if used polymorphically, so
as you said type should be constrained.

I still would prefer the more direct pattern-matching definition : it may
require code generation not to be tedious, but the generated code is an
honourable OCaml citizen.

[-- Attachment #2: Type: text/html, Size: 1282 bytes --]

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

* RE: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-08  7:59           ` bluestorm
@ 2010-06-08  9:14             ` David Allsopp
  2010-06-08  9:36               ` Luc Maranget
  0 siblings, 1 reply; 23+ messages in thread
From: David Allsopp @ 2010-06-08  9:14 UTC (permalink / raw)
  To: 'bluestorm'; +Cc: 'W Dan Meyer', caml-list

Gabriel Scherer wrote:
> Incidentally, the general function for getting a unique integer for a
> variant type with non-constant constructors isn't that bad either:
>
> let int_of_gen x =
> let x = Obj.repr x
> in
>   if Obj.is_block x
>   then -1 * Obj.tag x - 1
>   else (Obj.magic x : int)
>
> I consider that version much better. You could also write it in a more
restrictive way :
>
> let to_int x =
>   let repr = Obj.repr x in
>   if Obj.is_int repr
>   then (Obj.obj repr : int)
>   else invalid_arg "to_int";;

(that doesn't quite do the same thing but I don't think that was your point)

My "problem" is that for each specific case where it's only constant
constructors, I can't help but feel guilty that code will execute for the
conversion of a value to the same value (%identity is a no-op most of the
time). It's not that everything has to be pointlessly micro-optimised, but
you know what I mean?

> The good point about those is that they check that the memory
representation is compatible 
> before casting (while the "%identity" does not). They're safer. Of course,
they still break 
> parametricity if used polymorphically, so as you said type should be
constrained.

> I still would prefer the more direct pattern-matching definition : it may
require code 
> generation not to be tedious, but the generated code is an honourable
OCaml citizen.

Of course, if you have the following:

type t = A | B | C
let int_of_t = function
  A -> 0
| B -> 1
| C -> 2

Then in fact I believe that the compiler already converts that to a
hashtable lookup instead of a sequence of jumps so it would be fairly
reasonable (and easy) to have the compiler spot that the match is exactly a
conversion to the tag value and so remove the match completely (and given
that the compiler already has two different strategies for match clauses,
it's not even that inconsistent). camlp4 of course solves the generation
problem (but there's no need to tell you that!!)


David


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

* Re: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-08  9:14             ` David Allsopp
@ 2010-06-08  9:36               ` Luc Maranget
  2010-06-08  9:45                 ` David Allsopp
  0 siblings, 1 reply; 23+ messages in thread
From: Luc Maranget @ 2010-06-08  9:36 UTC (permalink / raw)
  To: David Allsopp; +Cc: 'bluestorm', caml-list, 'W Dan Meyer'

> Of course, if you have the following:
> 
> type t = A | B | C
> let int_of_t = function
>   A -> 0
> | B -> 1
> | C -> 2
> 
> Then in fact I believe that the compiler already converts that to a
> hashtable lookup instead of a sequence of jumps..

The compiler does not convert the above code to 'hashtable lookup'.


--Luc

PS>

To have a look at produced code.
* put your (Caml) code in some file say a.ml;
* compile as ocamlopt -S a.ml
* look at a.s

You can also use various options, such as -dlambda or -dcmm, to
see intermediate stages of the compilation process.


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

* RE: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-08  9:36               ` Luc Maranget
@ 2010-06-08  9:45                 ` David Allsopp
  2010-06-08  9:51                   ` Luc Maranget
  2010-06-08 10:21                   ` Dario Teixeira
  0 siblings, 2 replies; 23+ messages in thread
From: David Allsopp @ 2010-06-08  9:45 UTC (permalink / raw)
  To: luc.maranget; +Cc: 'bluestorm', caml-list, 'W Dan Meyer'

Luc Maranget wrote:
> Of course, if you have the following:
> >
> > type t = A | B | C
> > let int_of_t = function
> >   A -> 0
> > | B -> 1
> > | C -> 2
> >
> > Then in fact I believe that the compiler already converts that to a
> > hashtable lookup instead of a sequence of jumps..
> 
> The compiler does not convert the above code to 'hashtable lookup'.

Is there a point where the compiler does do a table lookup for matches
rather than jumps or have I clearly just dreamt that? :o)


David


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

* Re: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-08  9:45                 ` David Allsopp
@ 2010-06-08  9:51                   ` Luc Maranget
  2010-06-08 10:21                     ` David Allsopp
  2010-06-08 10:21                   ` Dario Teixeira
  1 sibling, 1 reply; 23+ messages in thread
From: Luc Maranget @ 2010-06-08  9:51 UTC (permalink / raw)
  To: David Allsopp; +Cc: caml-list

> Luc Maranget wrote:
> > Of course, if you have the following:
> > >
> > > type t = A | B | C
> > > let int_of_t = function
> > >   A -> 0
> > > | B -> 1
> > > | C -> 2
> > >
> > > Then in fact I believe that the compiler already converts that to a
> > > hashtable lookup instead of a sequence of jumps..
> > 
> > The compiler does not convert the above code to 'hashtable lookup'.
> 
> Is there a point where the compiler does do a table lookup for matches
> rather than jumps or have I clearly just dreamt that? :o)
> 
> 
> David

As far as I know the compiler always output jumps for matches.

Those jumps can be conditional jumps, or indirect jumps.
For instance in the case of your code, ther will be two condional jumps
(ocamlopt)

With a bigger example, say
| A -> 0
...

| Z -> 25

It is likely that you get a table of addresses indexed by constructor
numbers.


-- 
Luc


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

* RE: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-08  9:45                 ` David Allsopp
  2010-06-08  9:51                   ` Luc Maranget
@ 2010-06-08 10:21                   ` Dario Teixeira
  1 sibling, 0 replies; 23+ messages in thread
From: Dario Teixeira @ 2010-06-08 10:21 UTC (permalink / raw)
  To: luc.maranget, David Allsopp; +Cc: 'W Dan Meyer', caml-list

Hi,

> > The compiler does not convert the above code to 'hashtable lookup'.
> 
> Is there a point where the compiler does do a table lookup
> for matches rather than jumps or have I clearly just dreamt that? :o)

I think Luc's objection was to the use of the word "hash" in "hashtable".
Using the word "hashtable" for an indexed lookup table is technically
correct if you consider the trivial hash function (the identity function);
this may be what David meant.  Nevertheless, in most people's minds an
hashtable conjures images of a non-trivial mapping, which I'm quite sure
is not what the compiler generates...

Cheers,
Dario Teixeira






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

* RE: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-08  9:51                   ` Luc Maranget
@ 2010-06-08 10:21                     ` David Allsopp
  0 siblings, 0 replies; 23+ messages in thread
From: David Allsopp @ 2010-06-08 10:21 UTC (permalink / raw)
  To: luc.maranget; +Cc: caml-list

Luc Maranget wrote:
> > Luc Maranget wrote:
> > > Of course, if you have the following:
> > > >
> > > > type t = A | B | C
> > > > let int_of_t = function
> > > >   A -> 0
> > > > | B -> 1
> > > > | C -> 2
> > > >
> > > > Then in fact I believe that the compiler already converts that to
> > > > a hashtable lookup instead of a sequence of jumps..
> > >
> > > The compiler does not convert the above code to 'hashtable lookup'.
> >
> > Is there a point where the compiler does do a table lookup for matches
> > rather than jumps or have I clearly just dreamt that? :o)
> >
> >
> > David
> 
> As far as I know the compiler always output jumps for matches.
> 
> Those jumps can be conditional jumps, or indirect jumps.
> For instance in the case of your code, ther will be two condional jumps
> (ocamlopt)
> 
> With a bigger example, say
> | A -> 0
> ...
> 
> | Z -> 25
> 
> It is likely that you get a table of addresses indexed by constructor
> numbers.

I think that's probably what I was getting muddled with - I didn't realise
that the compiler doesn't do that all the time for constant constructors,
though.


David


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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-07 19:56     ` bluestorm
  2010-06-07 22:51       ` W Dan Meyer
@ 2010-06-08 11:28       ` Kaustuv Chaudhuri
  2010-06-08 11:40         ` bluestorm
  1 sibling, 1 reply; 23+ messages in thread
From: Kaustuv Chaudhuri @ 2010-06-08 11:28 UTC (permalink / raw)
  To: caml-list caml-list; +Cc: bluestorm

2010/6/7 bluestorm <bluestorm.dylc@gmail.com>:
> If you were, for example, to change your definition of "foo" (in a way not
> always representable as integers, such as adding a constructor with
> parameters), int_of_foo would become incorrect. The compiler wouldn't warn
> you, and you could get pretty bad failures (segfaults). You're on your own.

%identity will never cause a seg fault.

  % ocaml
          Objective Caml version 3.12.0+dev25 (2010-05-20)

  # external intify : 'a -> int = "%identity" ;;
  external intify : 'a -> int = "%identity"
  # intify "hello, world" ;;
  - : int = 70165942419644
  # intify [10; 20] ;;
  - : int = 70165942402044
  # intify 4.2 ;;
  - : int = 70165942392140
  # intify 322L ;;
  - : int = 70165942379652
  # intify 322L ;;
  - : int = 70165942369800

Obviosly if you write code that depends on such values, then your code
is most likely broken:

  # let x = [10; 20] ;;
  val x : int list = [10; 20]
  # intify x ;;
  - : int = 70165942003824
  # Gc.compact () ;;
  - : unit = ()
  # intify x ;;
  - : int = 70165941843960

-- Kaustuv


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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-08 11:28       ` Kaustuv Chaudhuri
@ 2010-06-08 11:40         ` bluestorm
  2010-06-08 14:37           ` Jacques Garrigue
  0 siblings, 1 reply; 23+ messages in thread
From: bluestorm @ 2010-06-08 11:40 UTC (permalink / raw)
  To: Kaustuv Chaudhuri; +Cc: caml-list caml-list

[-- Attachment #1: Type: text/plain, Size: 739 bytes --]

You're right : that's true in the "int" case and I hadn't considered it.

But if you use the same trick for ('a -> float) or other types you can get a
segfault :

# external floatify : 'a -> float = "%identity";;
external floatify : 'a -> float = "%identity"
# floatify 0;;
Segmentation fault

Also there are other problems with "intify" that may be worse than segfaults
: your application running with nonsense data and failing at an arbitrary
later point. Though ocaml doesn't fail (in the current implementation, it
would be unwise to assume that the GC/runtime will never check this), you
get strange behavior with those integers-wich-are-not-integers :

# let x = intify (1,2);;
val x : int = 70246988845964
# x * 1 - x;;
- : int = 1

[-- Attachment #2: Type: text/html, Size: 1018 bytes --]

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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-08 11:40         ` bluestorm
@ 2010-06-08 14:37           ` Jacques Garrigue
  2010-06-08 18:22             ` Kaustuv Chaudhuri
  0 siblings, 1 reply; 23+ messages in thread
From: Jacques Garrigue @ 2010-06-08 14:37 UTC (permalink / raw)
  To: bluestorm; +Cc: Kaustuv Chaudhuri, caml-list caml-list

Of course intify can cause a segmentation fault!

# let arr = Array.of_list [intify 1.0; 0];;
Segmentation fault

You can even have one with Obj.repr.

# let arr = Array.of_list [Obj.repr 1.0; Obj.repr 1];;
Segmentation fault

Only use these things once you understand the details of internal
representations...

Jacques Garrigue


On Tue, Jun 8, 2010 at 8:40 PM, bluestorm <bluestorm.dylc@gmail.com> wrote:
> You're right : that's true in the "int" case and I hadn't considered it.
> But if you use the same trick for ('a -> float) or other types you can get a
> segfault :
> # external floatify : 'a -> float = "%identity";;
> external floatify : 'a -> float = "%identity"
> # floatify 0;;
> Segmentation fault
> Also there are other problems with "intify" that may be worse than segfaults
> : your application running with nonsense data and failing at an arbitrary
> later point. Though ocaml doesn't fail (in the current implementation, it
> would be unwise to assume that the GC/runtime will never check this), you
> get strange behavior with those integers-wich-are-not-integers :
> # let x = intify (1,2);;
> val x : int = 70246988845964
> # x * 1 - x;;
> - : int = 1


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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-08 14:37           ` Jacques Garrigue
@ 2010-06-08 18:22             ` Kaustuv Chaudhuri
  2010-06-09  1:34               ` Jacques Garrigue
  2010-08-23 14:36               ` Damien Doligez
  0 siblings, 2 replies; 23+ messages in thread
From: Kaustuv Chaudhuri @ 2010-06-08 18:22 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: bluestorm, caml-list caml-list

On Tue, Jun 8, 2010 at 4:37 PM, Jacques Garrigue
<garrigue@math.nagoya-u.ac.jp> wrote:
> Of course intify can cause a segmentation fault!
>
> # let arr = Array.of_list [intify 1.0; 0];;
> Segmentation fault

This may be splitting hairs, but the reason that fails is that
Array.of_list's ad hoc polymorphism heuristic assumes that if the
first element of the list is allocated, then all elements are
allocated. Merely changing the order works.

  # Array.of_list [Obj.repr 0 ; Obj.repr 1.0] ;;
  - : Obj.t array = [|<abstr>; <abstr>|]

Which one of Obj.repr of Array.of_list to blame, if that's the right
word, is not that relevant to any code a sane person might write.

-- Kaustuv


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

* Re: [Caml-list] Converting variants with only constant constructors to integers
  2010-06-08 18:22             ` Kaustuv Chaudhuri
@ 2010-06-09  1:34               ` Jacques Garrigue
  2010-08-23 14:36               ` Damien Doligez
  1 sibling, 0 replies; 23+ messages in thread
From: Jacques Garrigue @ 2010-06-09  1:34 UTC (permalink / raw)
  To: kaustuv.chaudhuri; +Cc: caml-list

From: Kaustuv Chaudhuri <kaustuv.chaudhuri@inria.fr>
> On Tue, Jun 8, 2010 at 4:37 PM, Jacques Garrigue
> <garrigue@math.nagoya-u.ac.jp> wrote:
>> Of course intify can cause a segmentation fault!
>>
>> # let arr = Array.of_list [intify 1.0; 0];;
>> Segmentation fault
> 
> This may be splitting hairs, but the reason that fails is that
> Array.of_list's ad hoc polymorphism heuristic assumes that if the
> first element of the list is allocated, then all elements are
> allocated. Merely changing the order works.
> 
>   # Array.of_list [Obj.repr 0 ; Obj.repr 1.0] ;;
>   - : Obj.t array = [|<abstr>; <abstr>|]
> 
> Which one of Obj.repr of Array.of_list to blame, if that's the right
> word, is not that relevant to any code a sane person might write.

No, this is not an heuristic, but a compilation method based on the
assumption that values of the same type have the same representation.
This is enforced by the compiler, but by using the Obj module, which
is out of the safe realm, you can break this invariant.
So, from the point of view of the ocaml specification, Obj.repr is
clearly to blame (and defined as unsafe to start with).

Jacques Garrigue


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

* Re: [Caml-list] Converting variants with only constant constructors  to integers
  2010-06-08 18:22             ` Kaustuv Chaudhuri
  2010-06-09  1:34               ` Jacques Garrigue
@ 2010-08-23 14:36               ` Damien Doligez
  1 sibling, 0 replies; 23+ messages in thread
From: Damien Doligez @ 2010-08-23 14:36 UTC (permalink / raw)
  To: Kaustuv Chaudhuri; +Cc: caml-list caml-list

Hi Kaustuv,

On 2010-06-08, at 20:22, Kaustuv Chaudhuri wrote:

>> Of course intify can cause a segmentation fault!
>> 
>> # let arr = Array.of_list [intify 1.0; 0];;
>> Segmentation fault
> 
> This may be splitting hairs, but the reason that fails is that
> Array.of_list's ad hoc polymorphism heuristic assumes that if the
> first element of the list is allocated, then all elements are
> allocated. Merely changing the order works.


Then again, good old addition has the same kind of problem with
intify.

$ ocaml
        Objective Caml version 3.12.0

# external intify : 'a -> int = "%identity";;
external intify : 'a -> int = "%identity"
# let x = 1 + intify (1, 2);;
val x : int = 2147734445
# Gc.minor ();;  
ocamlrun(11589) malloc: *** mmap(size=184834061894270976) failed (error code=12)
*** error: can't allocate region


-- Damien


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

end of thread, other threads:[~2010-08-23 14:36 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-07 18:07 Converting variants with only constant constructors to integers Török Edwin
2010-06-07 18:25 ` [Caml-list] " W Dan Meyer
2010-06-07 18:45   ` bluestorm
     [not found] ` <87sk4y7lc7.fsf@gmail.com>
     [not found]   ` <4C0D3B0F.4060502@gmail.com>
2010-06-07 18:32     ` Török Edwin
2010-06-07 18:50       ` W Dan Meyer
2010-06-07 18:48 ` David Allsopp
2010-06-07 19:46   ` Török Edwin
2010-06-07 19:56     ` bluestorm
2010-06-07 22:51       ` W Dan Meyer
2010-06-08  7:42         ` David Allsopp
2010-06-08  7:59           ` bluestorm
2010-06-08  9:14             ` David Allsopp
2010-06-08  9:36               ` Luc Maranget
2010-06-08  9:45                 ` David Allsopp
2010-06-08  9:51                   ` Luc Maranget
2010-06-08 10:21                     ` David Allsopp
2010-06-08 10:21                   ` Dario Teixeira
2010-06-08 11:28       ` Kaustuv Chaudhuri
2010-06-08 11:40         ` bluestorm
2010-06-08 14:37           ` Jacques Garrigue
2010-06-08 18:22             ` Kaustuv Chaudhuri
2010-06-09  1:34               ` Jacques Garrigue
2010-08-23 14:36               ` Damien Doligez

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