181 lines
5.6 KiB
Plaintext
181 lines
5.6 KiB
Plaintext
#########################################################################
|
|
# #
|
|
# OCaml #
|
|
# #
|
|
# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt #
|
|
# #
|
|
# Copyright 2010 Institut National de Recherche en Informatique et #
|
|
# en Automatique. All rights reserved. This file is distributed #
|
|
# under the terms of the Q Public License version 1.0. #
|
|
# #
|
|
#########################################################################
|
|
|
|
=== Initial setup ===
|
|
make clean
|
|
./build/distclean.sh
|
|
./configure -prefix `pwd`/_install
|
|
./build/fastworld.sh
|
|
# Go to "Bootstrap camlp4"
|
|
|
|
=== Install the bootstrapping camlp4 processor ===
|
|
./build/install.sh
|
|
|
|
=== Build camlp4 ===
|
|
# This step is not needed right after a "./build/world.sh byte"
|
|
./build/camlp4-byte-only.sh
|
|
|
|
=== Bootstrap camlp4 ===
|
|
# First "Build camlp4"
|
|
# Then "Install the bootstrapping camlp4 processor"
|
|
# Indeed the following bootstrapping script
|
|
# does use the installed version!
|
|
./build/camlp4-bootstrap.sh
|
|
# If the fixpoint not is reached yet
|
|
# Go to "Bootstrap camlp4"
|
|
# Otherwise
|
|
# Have a look at the changes in
|
|
# camlp4/boot it may be a good idea to commit them
|
|
|
|
=== Generate Camlp4Ast.ml ===
|
|
# First "Install the bootstrapping camlp4 processor"
|
|
# Indeed the following bootstrapping script
|
|
# does use the installed version!
|
|
./build/camlp4-mkCamlp4Ast.sh
|
|
|
|
=== Case study "let open M in e" ===
|
|
|
|
Open the revised parser
|
|
Camlp4Parsers/Camlp4OCamlRevisedParser.ml
|
|
|
|
Look for similar constructs, indeed rules
|
|
that start by the same prefix should in
|
|
the same entry. It is simpler to stick
|
|
them close to each other.
|
|
|
|
[ "let"; r = opt_rec; ...
|
|
| "let"; "module"; m = a_UIDENT; ...
|
|
|
|
So we naturally add something like
|
|
|
|
| "let"; "open"; ...
|
|
|
|
Then have a look to the "open" construct:
|
|
|
|
| "open"; i = module_longident ->
|
|
|
|
So we need a module_longident, it becomes:
|
|
|
|
| "let"; "open"; i = module_longident; "in"; e = SELF ->
|
|
|
|
Then we leave a dummy action but very close to what we want
|
|
in the end:
|
|
|
|
| "let"; "open"; i = module_longident; "in"; e = SELF ->
|
|
<:expr< open_in $id:i$ $e$ >>
|
|
|
|
Here it is just calling a (non-existing) function called open_in.
|
|
|
|
Check that there is no other place where we have to duplicate this
|
|
rule (yuk!). In our case it is! The sequence entry have the "let"
|
|
rules again.
|
|
|
|
Then go into Camlp4Parsers/Camlp4OCamlParser.ml and look for other
|
|
occurences.
|
|
|
|
When copy/pasting the rule take care of SELF occurences, you may
|
|
have to replace it by expr and expr LEVEL ";" in our case.
|
|
|
|
The return type of the production might be different from expr in
|
|
our case an action become <:str_item<...>> instead of <:expr<...>
|
|
|
|
Watch the DELETE_RULE as well, in our case I'm searching for the
|
|
literal string "let" in the source:
|
|
|
|
DELETE_RULE Gram expr: "let"; "open"; module_longident; "in"; SELF END;
|
|
|
|
Then build and bootstrap.
|
|
|
|
Then you can at last extend the AST, go in:
|
|
|
|
Camlp4/Camlp4Ast.partial.ml
|
|
|
|
And add the "open in" constructor (at the end).
|
|
|
|
(* let open i in e *)
|
|
| ExOpI of loc and ident and expr
|
|
|
|
Then "Generate Camlp4Ast.ml" and build.
|
|
|
|
We get a single warning in Camlp4/Struct/Camlp4Ast2OCamlAst.ml but
|
|
don't fix it now. Notice that you may need to disable '-warn-error'
|
|
in order to be able to successfully compile, despite of the warning.
|
|
|
|
Then I hacked the camlp4/boot/camlp4boot.ml to generate:
|
|
Ast.ExOpI(_loc, i, e)
|
|
instead of
|
|
Ast.ExApp(_loc .... "open_in" ... i ... e ...)
|
|
|
|
Build. Bootstrap once and build again.
|
|
|
|
Then change the parsers again and replace the
|
|
open_in $id:i$ $e$
|
|
by
|
|
let open $i$ in $e$
|
|
|
|
Then change the Parsetree generation in
|
|
Camlp4/Struct/Camlp4Ast2OCamlAst.ml
|
|
|
|
| <:expr@loc< let open $i$ in $e$ >> ->
|
|
mkexp loc (Pexp_open (long_uident i) (expr e))
|
|
|
|
Change the pretty-printers as well (drawing inspiration in
|
|
"let module" in this case):
|
|
|
|
In Camlp4/Printers/OCaml.ml:
|
|
| <:expr< let open $i$ in $e$ >> ->
|
|
pp f "@[<2>let open %a@]@ @[<2>in@ %a@]"
|
|
o#ident i o#reset_semi#expr e
|
|
And at the end of #simple_expr:
|
|
<:expr< let open $_$ in $_$ >>
|
|
|
|
Have a look in Camlp4/Printers/OCamlr.ml as well.
|
|
|
|
=== Second case study "with t := ..." ===
|
|
|
|
1/ Change the revised parser first.
|
|
Add new parsing rules for := but keep the old actions for now.
|
|
|
|
2/ Change Camlp4Ast.partial.ml, add:
|
|
(* type t := t *)
|
|
| WcTyS of loc and ctyp and ctyp
|
|
(* module i := i *)
|
|
| WcMoS of loc and ident and ident
|
|
|
|
3/ "Generate Camlp4Ast.ml" and build.
|
|
|
|
4/ Change the generated camlp4/boot/camlp4boot.ml:
|
|
Look for ":=" and change occurences of
|
|
WcMod by WcMoS and WcTyp by WcTyS
|
|
|
|
5/ Build (DO NOT bootstrap)
|
|
"Install the bootstrapping camlp4 processor"
|
|
|
|
6/ Change the required files:
|
|
Camlp4/Printers/OCaml.ml:
|
|
just copy/paste&adapt what is done for
|
|
"... with type t = u" and
|
|
"... with module M = N"
|
|
Camlp4/Struct/Camlp4Ast2OCamlAst.ml:
|
|
I've factored out a common part under
|
|
another function and then copy/pasted.
|
|
Camlp4Parsers/Camlp4OCamlRevisedParser.ml:
|
|
Change the <:with_constr< type $...$ = $...$ >>
|
|
we've introduced earlier by replacing the '='
|
|
by ':='.
|
|
Camlp4Parsers/Camlp4OCamlParser.ml:
|
|
Copy paste what we have done in Camlp4OCamlRevisedParser
|
|
and but we need to call opt_private_ctyp instead of
|
|
ctyp (just like the "type =" construct).
|
|
|
|
7/ Build & Bootstrap
|