ocaml/ocaml — pull request #69 by Octachron (2014-05-25 15:05:45+00:00)
Title: Simplify the definition and use of custom index operators

This patch simplifies the definition and use of custom index operator, i.e the
operators used to access or modify the value of an array-like structure at an given index.

First, a new syntax for index operators is introduced.
Six "core parenthesis operators" are added
- .() ,
- .[] ,
- .{}, .{,}, .{,,}, .{,..,}.

The .{,}/.{,,}/.{,,,} operators are defined for compatibility with the
Bigarray syntax extension (more about it later).
Each core index operator is available in a safe/unsafe and access/assignment
versions. For instance, .() is declined in
- .() : safe index operator
- .()! : unsafe index operator
- .()<- : safe indexed assignment operator
- .()!<- : unsafe indexed assignment operator

Expressions of the form array.(index), string.(index) and bigarray1.{index} are
now desugared to one of these new index operators. The safe or unsafe index
operator are chosen in function of the presence or absence of the
"unsafe" compiler option.

In order to keep the compatibility with existing code,
the .() and .[] index operators are defined inside the pervasives modules
to be equal to their standard equivalent.

# Compatibility issues with bigarray
The bigarray .{} operators can be desugared to 4 different operators to
respect the original bigarray syntax extension.

More precisely, the index operator used in the desugaring changes if the
index is a n-tuple. Depending on the arity of the tuple, the index operator
used is either:
- 1-tuple => .{} : arity 2 [ +1 for assignment ] operator
- 2-tuple => .{,} : arity 3 [ +1 for assignment ] operator
- 3-tuple => .{,,} : arity 4 [ +1 for assignment ] operator
- 4 and more tuples => .{,..,} : arity 2 [ +1 for assignment]
operator, the tuple is passed as an array.

The bigarray module have been updated to use these new operators. However,
since these operators are not defined inside pervasives, this change **will
break** existing code using bigarrays without opening the Bigarray module.
At least one test in the test suite has been updated due to this
incompatibility.

An other possibility to deal with this incompatibility issue
would be to hide the new desugar transform of .{} behind a compiler switch.
A possible advantage of this compiler switch option is that it would
allow to fusion all four .{} operator. Then, the bigarrays custom .{} index
operators could be implemented at the Bigarray.Array{n} level rather than
the Bigarray level.

# Example of code
```ocaml
type z = Zero
type 'a succ=Succ
type (_,_) nat = Z : ('a,'a) nat | S : ('a,'b) nat -> ('a, 'b succ) nat

type 'dim vector = ((z,'dim) nat * float array )

let rec to_int: type inf sup. (inf,sup) nat -> int =
function Z -> 0 | S n -> 1 + to_int n

exception Wrong_dimension
let from_array : type dim. (z,dim succ) nat -> float array -> dim vector =
fun (S nat) array -> if (Array.length array=1+to_int nat) then
(nat, array)
else
raise Wrong_dimension

let ( .{} ) : 'dim vector -> ('mid,'dim) nat -> 'float =
fun (dim,v) nat -> Array.unsafe_get v (to_int nat)

let ( .{} <- ) : 'dim vector -> ('mid,'dim) nat -> float -> unit =
fun (dim,v ) nat x -> Array.unsafe_set v (to_int nat) x

let ( .{}! )= (.{} )
let ( .{}! <- )= ( .{}<- )

let a = from_array (S (S Z)) [|1.;2.|]

let x = a.{Z}
let () = a.{S Z} <- 11.
```