Local definitions and sequences

From Gallium

Jump to: navigation, search

As part of the revised syntax an improvement as been made in order to facilitate the usage of local definition inside sequences.

In the 3.10 version of Camlp4 we have changed a little this syntactic sugar in order to have a clearer specification.

Since this problem is mainly due to historical changes, let's see a part of the evolution of sequences in Caml syntaxes.


Contents

1. The OCaml syntax for sequences and local bindings

Roughly, here is the OCaml syntax for local definitions and sequences.

expr, e ::= ...
          | let x = se1 in se2

seq_expr, se ::=
               | e
               | e;
               | e; se

An example:

let x = 42 in
print_int x;
let y = f x in
print_int y;
let z = g x y in
print_int z;
z

TODO: explain problems induced by this syntax...

2. The Revised syntax for sequences.

In order to fix this syntax about sequences, `do' blocks have been introduced.

expr, e ::= ...
          | let x = e1 in e2
          | do { seq }

sequence, seq ::=
                | e
                | e; seq

This makes sequences well delimited with non ambiguous scopes.

Our example updated:

let x = 42 in
do {
  print_int x;
  let y = f x in
  do {
    print_int y;
    let z = g x y in
    do {
      print_int z;
      z
    }
  }
}

As one can see it, this leads to nested blocks that can becomes very nasty.

Here one don't catch the essence of sequences, that is needed for imperative programming. One can claim that once with turn into a more imperative style one can keep this style as much as possible for sub-expressions of it.

This idea leads to a second change of the syntax.

3. The Revised syntax of sequences with local definitions.

The idea is to allow local definitions without leaving the sequence mode. To do so one introduce another local definition syntax using a semicolon instead of the `in' keyword.

One can rewrite our example as:

do {
  let x = 42;
  print_int x;
  let y = f x;
  print_int y;
  let z = g x y;
  print_int z;
  z
}

With the following idea what will be the meaning of `do { let x = 42 in print_int x; x }'?

The outcome is this error message "Unbound value x", that says that the last `x' is not in the scope of the `x' you defined. This seems obvious and clear however that another implementation that one can found in Camlp4 before 3.10.

4. Before 3.10

expr, e ::= ...
          | let x = e1 in e2
          | do { seq }

sequence, seq ::=
                | let x = e (in|;) seq
                | e
                | e; seq

I don't know why it was done that way in Camlp4, perhaps because the Camlp4 can be hard to control and can require manual inlining in order to do his left factorization.

The bad thing here, is that we've changed the scope of a local definition depending of it's context. For instance the previous example (do { let x = 42 in print_int x; x }) is accepted.

5. Starting from 3.10

The decision has been taken to fix the scope of local definitions inside sequences. The resulting grammar is something like:

expr, e ::= ...
          | let x = e1 in e2
          | do { seq }

sequence, seq ::=
                | let x = e1 in e2             (* This inlining is to allow left-factorization *)
                | let x = e ; seq
                | e
                | e; seq

The restriction imposed by this change is that some programs are no longer accepted by Camlp4. However one can consider that these programs are possible misunderstandings of scopes definition and should be re-wrote using either the `let-;' sugar or using more `do' blocks.

Personal tools
Espace privé