Previous week Up Next week

Hello

Here is the latest Caml Weekly News, for the week of August 27 to September 03, 2013.

  1. Ocamlnet-3.7.3
  2. OCaml 4.01.0 RC1
  3. Literate (sort-of) programming in OCaml
  4. Pippo: a pretty interesting pre-processor that uses OCaml
  5. Other Caml News

Ocamlnet-3.7.3

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2013-08/msg00171.html

Gerd Stolpmann announced:
Ocamlnet-3.7.3 is now available for download. Changes in this release:

 - Support for ocaml-4.01
 - New directives for ocamlrpcgen to control the language mapping better
 - Bug fixes here and there

Details about this release can be found on the project page:

http://projects.camlcity.org/projects/ocamlnet.html

See ChageLog for a detailed list of changes:

http://projects.camlcity.org/projects/dl/ocamlnet-3.7.3/ChangeLog

Gerd


PS. The versions 3.7.0 to 3.7.2 were release attempts but turned out as
buggy. Don't use them if you fetched one (they were visible for a short
period).
      

OCaml 4.01.0 RC1

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2013-09/msg00001.html

Damien Doligez announced:
The release of OCaml version 4.01.0 is imminent.  We have
created a release candidate for your testing pleasure.  Please
download the sources, compile, install, and test your favourite
software with it (or try it with OPAM).  Then let me know
whether it works for you.

We want to know about any show-stopping bugs, especially in the
compilation and installation phases.

This release candidate is available as source code at this
address: http://caml.inria.fr/pub/distrib/ocaml-4.01/

It will become the official release in one week unless a
show-stopping bug is discovered in the meantime.

Happy hacking,

-- Damien Doligez for the OCaml team.


OCaml 4.01.0:
-------------

(Changes that can break existing programs are marked with a "*")

Other libraries:
- Labltk: updated to Tcl/Tk 8.6.

Type system:
* Propagate type information towards pattern-matching, even in the presence of
  polymorphic variants (discarding only information about possibly-present
  constructors). As a result, matching against absent constructors is no longer
  allowed for exact and fixed polymorphic variant types.
* PR#6035: Reject multiple declarations of the same method or instance variable
  in an object

Compilers:
- PR#5861: raise an error when multiple private keywords are used in type
  declarations
- PR#5634: parsetree rewriter (-ppx flag)
- ocamldep now supports -absname
- PR#5768: On "unbound identifier" errors, use spell-checking to suggest names
  present in the environment
- ocamlc has a new option -dsource to visualize the parsetree
- tools/eqparsetree compares two parsetree ignoring location
- ocamlopt now uses clang as assembler on OS X if available, which enables
  CFI support for OS X.
- Added a new -short-paths option, which attempts to use the shortest
  representation for type constructors inside types, taking open modules
  into account. This can make types much more readable if your code
  uses lots of functors.
- PR#5986: added flag -compat-32 to ocamlc, ensuring that the generated
  bytecode executable can be loaded on 32-bit hosts.
- PR#5980: warning on open statements which shadow an existing identifier
  (if it is actually used in the scope of the open)
* warning 3 is extended to warn about other deprecated features:
  - ISO-latin1 characters in identifiers
  - uses of the (&) and (or) operators instead of (&&) and (||)
- Experimental OCAMLPARAM for ocamlc and ocamlopt
- PR#5571: incorrect ordinal number in error message
- PR#6073: add signature to Tstr_include

Standard library:
- PR#5899: expose a way to inspect the current call stack
  (Printexc.get_callstack)
- PR#5986: new flag Marshal.Compat_32 for the serialization functions
  (Marshal.to_*), forcing the output to be readable on 32-bit hosts.
- Add optimized composition operators |> and @@ in Pervasives

Other libraries:
- PR#5568: add O_CLOEXEC flag to Unix.openfile, so that the returned
  file descriptor is created in close-on-exec mode

Runtime system:
* PR#6019: more efficient implementation of caml_modify() and caml_initialize().
  The new implementations are less lenient than the old ones: now,
  the destination pointer of caml_modify() must point within the minor or
  major heaps, and the destination pointer of caml_initialize() must
  point within the major heap.

Internals:
- Moved debugger/envaux.ml to typing/envaux.ml to publish env_of_only_summary
  as part of compilerlibs, to be used on bin-annot files.
- The test suite can now be run without installing OCaml first.

Bug fixes:
- PR#3236: Document the fact that queues are not thread-safe
- PR#3468: (part 1) Sys_error documentation
- PR#3679: Warning display problems
- PR#3963: Graphics.wait_next_event in Win32 hangs if window closed
- PR#4079: Queue.copy is now tail-recursive
- PR#4138: Documentation for Unix.mkdir
- PR#4469: emacs mode: caml-set-compile-command is annoying with ocamlbuild
- PR#4485: Graphics: Keyboard events incorrectly delivered in native code
- PR#4502: ocamlbuild now reliably excludes the build-dir from hygiene check
- PR#4762: ?? is not used at all, but registered as a lexer token
- PR#4788: wrong error message when executable file is not found for backtrace
- PR#4812: otherlibs/unix: add extern int code_of_unix_error (value error);
- PR#4887: input_char after close_in crashes ocaml (msvc runtime)
- PR#4994: ocaml-mode doesn't work with xemacs21
- PR#5098: creating module values may lead to memory leaks
- PR#5102: ocamlbuild fails when using an unbound variable in rule dependency
* PR#5119: camlp4 now raises a specific exception when 'DELETE_RULE' fails,
  rather than raising 'Not_found'
- PR#5121: %( %) in Format module seems to be broken
- PR#5178: document in INSTALL how to build a 32-bit version under Linux x86-64
- PR#5212: Improve ocamlbuild error messages of _tags parser
- PR#5240: register exception printers for Unix.Unix_error and Dynlink.Error
- PR#5300: ocamlbuild: verbose parameter should implicitly set classic display
- PR#5327: (Windows) Unix.select blocks if same socket listed in first and
  third arguments
- PR#5343: ocaml -rectypes is unsound wrt module subtyping (was still unsound)
- PR#5350: missing return code checks in the runtime system
- PR#5468: ocamlbuild should preserve order of parametric tags
- PR#5551: Avoid repeated lookups for missing cmi files
- PR#5552: try to use camlp4.opt if it's possible
- PR#5580: missed opportunities for constant propagation
- PR#5611: avoid clashes betwen .cmo files and output files during linking
- PR#5662: typo in md5.c
- PR#5673: type equality in a polymorphic field
- PR#5674: Methods call are 2 times slower with 4.00 than with 3.12
- PR#5694: Exception raised by type checker
- PR#5695: remove warnings on sparc code emitter
- PR#5697: better location for warnings on statement expressions
- PR#5698: remove harcoded limit of 200000 labels in emitaux.ml
- PR#5702: bytecomp/bytelibrarian lib_sharedobjs was defined but never used
- PR#5708: catch Failure"int_of_string" in ocamldebug
- PR#5712: (9) new option -bin-annot is not documented
- PR#5731: instruction scheduling forgot to account for destroyed registers
- PR#5734: improved Win32 implementation of Unix.gettimeofday
- PR#5735: %apply and %revapply not first class citizens
- PR#5738: first class module patterns not handled by ocamldep
- PR#5739: Printf.printf "%F" (-.nan) returns -nan
- PR#5741: make pprintast.ml in compiler_libs
- PR#5747: 'unused open' warning not given when compiling with -annot
- PR#5752: missing dependencies at byte-code link with mlpack
- PR#5758: Compiler bug when matching on floats
- PR#5763: ocamlbuild does not give correct flags when running menhir
- PR#5765: ocamllex doesn't preserve line directives
- PR#5770: Syntax error messages involving unclosed parens are sometimes
  incorrect
- PR#5772: problem with marshaling of mutually-recursive functions
- PR#5775: several bug fixes for tools/pprintast.ml
- PR#5784: -dclambda option is ignored
- PR#5785: misbehaviour with abstracted structural type used as GADT index
- PR#5787: Bad behavior of 'Unused ...' warnings in the toplevel
- PR#5793: integer marshalling is inconsistent between architectures
- PR#5798: add ARM VFPv2 support for Raspbian (ocamlopt)
- PR#5802: Avoiding "let" as a value name
- PR#5805: Assert failure with warning 34 on pre-processed file
- PR#5806: ensure that backtrace tests are always run (testsuite)
- PR#5809: Generating .cmt files takes a long time, in case of type error
- PR#5810: error in switch printing when using -dclambda
- PR#5811: Untypeast produces singleton tuples for constructor patterns
  with only one argument
- PR#5813: GC not called when unmarshaling repeatedly in a tight loop (ocamlopt)
- PR#5814: read_cmt -annot does not report internal references
- PR#5815: Multiple exceptions in signatures gives an error
- PR#5816: read_cmt -annot does not work for partial .cmt files
- PR#5819: segfault when using [with] on large recursive record (ocamlopt)
- PR#5821: Wrong record field is reported as duplicate
- PR#5824: Generate more efficient code for immediate right shifts.
- PR#5825: Add a toplevel primitive to use source file wrapped with the
  coresponding module
- PR#5833: README.win32 can leave the wrong flexlink in the path
- PR#5835: nonoptional labeled arguments can be passed with '?'
- PR#5840: improved documentation for 'Unix.lseek'
- PR#5848: Assertion failure in type checker
- PR#5858: Assert failure during typing of class
- PR#5865: assert failure when reporting undefined field label
- PR#5872: Performance: Buffer.add_char is not inlined
- PR#5876: Uncaught exception with a typing error
- PR#5877: multiple "open" can become expensive in memory
- PR#5880: 'Genlex.make_lexer' documention mentions the wrong exception
- PR#5885: Incorrect rule for compiling C stubs when shared libraries are not
  supported.
- PR#5891: ocamlbuild: support rectypes tag for mlpack
- PR#5892: GADT exhaustiveness check is broken
- PR#5906: GADT exhaustiveness check is still broken
- PR#5907: Undetected cycle during typecheck causes exceptions
- PR#5910: Fix code generation bug for "mod 1" on ARM.
- PR#5911: Signature substitutions fail in submodules
- PR#5912: add configure option -no-cfi (for OSX 10.6.x with XCode 4.0.2)
- PR#5914: Functor breaks with an equivalent argument signature
- PR#5920, PR#5957: linking failure for big bytecodes on 32bit architectures
- PR#5928: Missing space between words in manual page for ocamlmktop
- PR#5930: ocamldep leaks temporary preprocessing files
- PR#5933: Linking is slow when there are functions with large arities
- PR#5934: integer shift by negative amount (in otherlibs/num)
- PR#5944: Bad typing performances of big variant type declaration
- PR#5945: Mix-up of Minor_heap_min and Minor_heap_max units
- PR#5948: GADT with polymorphic variants bug
- PR#5953: Unix.system does not handle EINTR
- PR#5965: disallow auto-reference to a recursive module in its definition
- PR#5973: Format module incorrectly parses format string
- PR#5974: better documentation for Str.regexp
- PR#5976: crash after recovering from two stack overflows (ocamlopt on MacOS X)
- PR#5977: Build failure on raspberry pi: "input_value: integer too large"
- PR#5981: Incompatibility check assumes abstracted types are injective
- PR#5982: caml_leave_blocking section and errno corruption
- PR#5985: Unexpected interaction between variance and GADTs
- PR#5986: Protect against marshaling 64-bit integers in bytecode
- PR#5988: missing from the documentation: -impl is a valid flag for ocamlopt
- PR#5989: Assumed inequalities involving private rows
- PR#5992: Crash when pattern-matching lazy values modifies the scrutinee
- PR#5993: Variance of private type abbreviations not checked for modules
- PR#5997: Non-compatibility assumed for concrete types with same constructor
- PR#6004: Type information does not flow to "inherit" parameters
- PR#6005: Type unsoundness with recursive modules
- PR#6010: Big_int.extract_big_int gives wrong results on negative arguments
- PR#6024: Format syntax for printing @ is incompatible with 3.12.1
- PR#6001: Reduce the memory used by compiling Camlp4
- PR#6031: Camomile problem with -with-frame-pointers
- PR#6032: better Random.self_init under Windows
- PR#6033: Matching.inline_lazy_force needs eta-expansion (command-line flags)
- PR#6046: testsuite picks up the wrong ocamlrun dlls
- PR#6056: Using 'match' prevents generalization of values
- PR#6058: 'ocamlbuild -use-ocamlfind -tag thread -package threads t.cma' fails
- PR#6060: ocamlbuild rules for -principal, -strict-sequence and -short-paths
- PR#6069: ocamldoc: lexing: empty token
- PR#6072: configure does not handle FreeBSD current (i.e. 10) correctly
- PR#6074: Wrong error message for failing Condition.broadcast
- PR#6084: Define caml_modify and caml_initialize as weak symbols to help
  with Netmulticore
- PR#6090: Module constraint + private type seems brocken in ocaml 4.01.0
- PR#6109: Typos in ocamlbuild error messages
- PR#6123: Assert failure when self escapes its class

Feature wishes:
- PR#5181: Merge common floating point constants in ocamlopt
- PR#5546: moving a function into an internal module slows down its use
- PR#5597: add instruction trace option 't' to OCAMLRUNPARAM
- PR#5676: IPv6 support under Windows
- PR#5721: configure -with-frame-pointers for Linux perf profiling
- PR#5722: toplevel: print full module path only for first record field
- PR#5762: Add primitives for fast access to bigarray dimensions
- PR#5769: Allow propagation of Sys.big_endian in native code
- PR#5771: Add primitives for reading 2, 4, 8 bytes in strings and bigarrays
- PR#5774: Add bswap primitives for amd64 and arm
- PR#5795: Generate sqrtsd opcode instead of external call to sqrt on amd64
- PR#5827: provide a dynamic command line parsing mechanism
- PR#5832: patch to improve "wrong file naming" error messages
- PR#5864: Add a find operation to Set
- PR#5886: Small changes to compile for Android
- PR#5902: -ppx based pre-processor executables accept arguments
- PR#6049: support for OpenBSD/macppc platform
- PR#6059: add -output-obj rules for ocamlbuild

Tools:
- OCamlbuild now features a bin_annot tag to generate .cmt files.
- OCamlbuild now features a strict_sequence tag to trigger the strict-sequence
  option.
- OCamlbuild now picks the non-core tools like ocamlfind and menhir from PATH
- PR#5884: Misc minor fixes and cleanup for emacs mode
- PR#6030: Improve performance of -annot
      
Anil Madhavapeddy then added:
For the OPAM users among you, I've added a 4.01.0 compiler switch
which will track the RC releases, and eventually become the official
release when it's out.

$ opam update
$ opam switch 4.01.0
$ eval `opam config env`
# ???
# profit

I've been running a full regression test of the entire OPAM database
on a variety of architectures and triaging the results.  If anyone
else is interested in helping submit patches to fix issues, then
please see:
https://github.com/OCamlPro/opam-repository/issues/1029

Note that the above link is a bit raw, since it also includes failures
from bugs in 4.00.1 packages too.  We've just been fixing everything
we can spot in preparation for testing the forthcoming OPAM 1.1 beta
on as stable a package database as possible.  I'm preparing a blog
post describing the most common failures we've seen to help package
authors avoid them in the future (warnings-as-errors, I'm looking at
you!)
      

Literate (sort-of) programming in OCaml

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2013-09/msg00002.html

Jonathan Protzenko asked:
I am currently writing a big, mostly textual document in format blah 
(blah being of a course a meta-variable). Are there any tools that 
would allow me to interleave OCaml code with the contents of my 
document?

More on my use-case. Creating this document requires me to perform 
various subtasks, such as:
- write a code snippet in the document,
- put the code snippet in a file,
- call an external program on the file,
- paste the output into the document.

Naturally, I wish to automate this. I could roll my own set of 
commands, and parse them with OCaml, but I would be re-creating a 
scripting language, and it seems to me that interleaving OCaml code 
within my document would be better. Here's what I have in mind:


blah blah blah blah blah blah blah blah blah blah blah blah blah blah 
blah blah
blah blah blah blah blah blah blah blah blah blah blah blah blah blah 
blah blah
blah ... we thus write the following code ... :

{%
  let code = "<sample code>" in
  output code
%}

blah blah blah ... after running the command blah ... the output is as 
follows ... blah

{%
  let f = write_into_temp_file code in
  let s = run_and_read "myprogram" [f] in
  output s
%}

blah blah blah blah blah blah blah blah blah blah blah blah blah blah 
blah blah ...


Are you aware of any tool that would allow me to achieve this?
      
Alain Frisch suggested:
I'm sure you can use sed to (I use '' for meta quotes):

  - Add ''print_string"'' in front of the file and ''";;'' at the end.
  - Replace ''{%'' with ''";;'' and ''%}'' with ''";; print_string"''

If you apply this transformation and call the toplevel on the result, 
you should get what you want, no?
      
Török Edwin suggested and Maxence Guesdon added:
> http://zoggy.github.io/stog/posts/ocaml-sessions.html

You can have a look at a huge usage of this in my ocaml introduction:
  http://form-ocaml.forge.ocamlcore.org/
The document:
  http://form-ocaml.forge.ocamlcore.org/intro_ocaml.html
The source code:
  http://forge.ocamlcore.org/scm/?group_id=228

You will need stog and stog-writing:
  http://zoggy.github.io/stog/
  http://zoggy.github.io/stog/stog-writing.html

> https://github.com/realworldocaml/scripts
      
Roberto Di Cosmo suggested:
for writing course notes, many of us used in the old times
a script (written in ... cough, cough .. Perl) that sort of
answered your needs.

I honestly do not remember who from the old Formel team wrote
it for CamlLight in the first place, and who adapted it to OCaml,
but you can see the old code in a message from Xavier in 1996 :-)

http://caml.inria.fr/pub/old_caml_site/caml-list-ar/0651.html

Here is the version I still use to produce course notes with a recent
OCaml and lstlistings environments (that knows how to highlight OCaml syntax).

One writes a source LaTeX file with environments like

\begin{caml_example}
let x = "this code will be executed, and printed out with toplevel output"
\end{caml_example}


\begin{caml_example*}
let x = "this code will be executed, and printed out without toplevel output"
\end{caml_example*}

\begin{caml_eval}
let x = "this code will be executed, but not printed out"
\end{caml_eval}

and passes it through ocaml-tex to get the LaTeX file with the results
properly inlined.

Ah, by the way, beware, this old code doew not do a very good job at identifying
phrases, so you need to use ;; all too often in the code.

Having a better (OCaml?) version with proper handling of all this would
certainly be nice.

--
Roberto


#!/usr/bin/perl
# ocaml-tex

$camllight = "TERM=dumb ocaml";
$camlbegin = "\\begin{lstlisting}[escapechar=§]\n";
$camlend = "\\end{lstlisting}\n";
$camlin = "";
$camloutstart = "§\\camloutbol §";
$camloutstop = "§\\camlouteol §";
$camlblank = "\n";

$linelen = 72;
$output = "";
$cut_at_blanks = 0;

while ($#ARGV >= 0) {
  $_ = $ARGV[0];
  last unless (/^-/);
  $linelen = $ARGV[1], shift, shift, next    if (/^-n$/);
  $output  = $ARGV[1], shift, shift, next    if (/^-o$/);
  $camllight = $ARGV[1], shift, shift, next    if (/^-caml$/);
  $cut_at_blanks = 1, shift, next            if (/^-w$/);
  printf STDERR ("Unknown option '%s', ignored\n", $_);
  shift;
}

# First pass: extract the Caml phrases to evaluate

open(ML, "> .input.ml") || die("Cannot create .input.ml : $!");

foreach $infile (@ARGV) {
  open(IN, $infile) || die("Cannot open $infile : $!");
  while(<IN>) {
    if (m/^\\begin{caml_(example|example\*|eval)}\s*$/) {
      while(<IN>) {
        last if m/^\\end{caml_(example|example\*|eval)}\s*$/;
        print ML $_;
      }
    }
  }
  close(IN);
}

close(ML);

# Feed the phrases to a Caml toplevel

open(TOPLEVEL, "$camllight 2>&1 < .input.ml |") ||
       die("Cannot start camllight : $!");

<TOPLEVEL>; <TOPLEVEL>;		# skip the banner
$lastread = <TOPLEVEL>;
$lastread =~ s/^# //;

# Second pass: shuffle the TeX source and the output of the toplevel

if ($output) {
  if ($output eq "-") {
    open(OUT, ">&STDOUT");
  } else {
    open(OUT, ">$output") || die("Cannot create $output: $!");
  }
}

foreach $infile (@ARGV) {
  open(IN, $infile) || die("Cannot open $infile: $!");
  if (! $output) {
    $outfile = $infile;
    $outfile =~ s/\.tex$//;
    open(OUT, "> $outfile.ml.tex") || die("Cannot create $outfile.ml.tex: $!");
  }
  while(<IN>) {
    if (m/^\\begin{caml_example(\*?)}\s*$/) {
      $omit_answer = $1;     # true if caml_example*, false if caml_example
      print OUT $camlbegin;
      $severalphrases = 0;
      while(<IN>) {
        last if m/\\end{caml_example\*?}\s*$/;
        print OUT $camlblank if ($severalphrases);
        while(1) {
          s/\\/\\\\/g;
          print OUT $camlin, $_;
          last if m/;; *$/;
          $_ = <IN>;
        }
	while ($lastread =~ s/^  //) { }
        while($lastread) {
          last if $lastread =~ s/^# //;
          print STDERR $lastread;
          if (! $omit_answer) {
            while (length($lastread) > $linelen) {
              if ($cut_at_blanks) {
                $cutpos = rindex($lastread, ' ', $linelen);
                if ($cutpos == -1) { $cutpos = $linelen; } else { $cutpos++; }
              } else {
                $cutpos = $linelen;
              }
              $line = substr($lastread, 0, $cutpos);
              $line =~ s/\\/\\\\/g;
              print OUT $camloutstart, $line, $camloutstop, "\n";
              $lastread = substr($lastread, $cutpos,
                                 length($lastread) - $cutpos);
            }
            $lastread =~ s/\\/\\\\/g;
            print OUT $camloutstart, $lastread, $camloutstop;
	  }
          $lastread = <TOPLEVEL>;
        }
        $severalphrases = 1;
      }
      print OUT $camlend;
    }
    elsif (m/^\\begin{caml_eval}\s*$/) {
      while(<IN>) {
        last if m/^\\end{caml_eval}\s*$/;
        if (m/;; *$/) {
	  while ($lastread =~ s/^#//) { }
	  while($lastread) {
	    last if $lastread =~ s/^#//;
	    print $lastread;
	    $lastread = <TOPLEVEL>;
	  }
        }
      }
    }
    else {
      print OUT $_;
    }
  }
  close(IN);
}

close(TOPLEVEL);
      
Ashish Agarwal suggested:
OCaml Labs is developing MPP (Meta Preprocessor) [1]. It will be used in a
new implementation of ocaml.org [2], which includes pages like 99 problems
[3] that are generated by running ocaml code through the toploop. In case
blah = Markdown, please also note the new Markdown library [4].

[1] https://github.com/pw374/MPP-language-blender
[2] http://lists.ocaml.org/pipermail/infrastructure/2013-July/000211.html
[3] http://ocaml.org/tutorials/99problems.html
[4] http://lists.ocaml.org/pipermail/infrastructure/2013-July/000223.html
      
Raphaël Proust suggested:
Current workflow I use involves:
- mkfile: a rule file for mk (Plan9's take on make, it has simple
escaping and a readable man page) to drive the whole thing,
- bar: a compiler for the language bar that includes a Latex pretty
printing mode
- inc/: a directory where I place all my code samples from language bar
- main.pdc: a pandoc file holding the source.

Extracts from the mkfile:
~~~~~~~
TARGET=main.pdf
SOURCE=${TARGET:%.pdf=%.pdc}

INCLUDES=`{cat $SOURCE | grep '\\input{.*\.tex}' | sed
's/^.*\\input{([^\$\\}]*\.tex)}.*$/\1/'}

$TARGET: $SOURCE $INCLUDES
        pandoc -o $TARGET $SOURCE

%.pp.tex: %.bar bar.byte
        OCAMLRUNPARAM=$OCAMLRUNOPT ./bar.byte -latex $stem.bar > $target

%.pp.annot.tex: %.bar bar.byte
        OCAMLRUNPARAM=$OCAMLRUNOPT ./bar.byte -latex -annot $stem.bar > $target
~~~~~~~

Extracts from bar.mli:
~~~~~~~
module type PRINTER = sig
  val t: annotations:bool -> t -> string
end
module LatexPP : PRINTER
~~~~~~~

Extracts from the main.pdc
~~~~~~~
The annotation process, blahblah. Thus the program $\input{inc/foo.pp.tex}$
is annotated in the following way: $\input{inc/foo.pp.annot.tex}$
~~~~~~~


Known bugs and shortcomings:
- sed works line-wise so the mkfile INCLUDES variable is not set
properly when there are several \input on the same line.
- the passing of argument (using two rules with and two file
extensions) is hackish and would not scale.


Less painful than copy-pasting things and easier to keep everything in
sync. It's also nice to be able to do things such as:
\begin{align*}
<some math>\input{inc/function-application.pp.tex}<more math>\\
<more math>\input{inc/function-declaration.pp.tex}<more math>\\
<more math>\input{inc/if-then-else.pp.tex}<more math>\\
<etc.>
\end{align*}
      
Simon Cruanes suggested:
You may also try https://www.lri.fr/~filliatr/ocamlweb/ .
      
oliver suggested:
Hmhhh, long, long ago I explored some of the good-old / classical
literate programming tools (well, to be detailed, I did not tried Web,
so it was not THE classical one, but later developments, influenced by
Knuth's Web.)

Some of these tools were limited to certain languages, but as far as I remember
at least one was able to work with any (???) language.
Or at least some tools were very flexible to work with many languages.

I have forgotten most of the names of the tools I used, possibly I tried
noweb and some others.

All had their advantages and also their limitations.

There was one (or two?) that looked so promising that I had planned to try it
(them) too, but I stopped with Literate Programming (LP) before I had the
motivation to try it/them.
  (Trying so many tools at some time has exhausted and demotivated me.
   Those I tried were not powerful/flexible enough, nevertheless needed their
   time to look at them. Tools should help in the work and help saving time,
   not eat the time...)

As far as I remember, and I'm not sure, FWEB and/or FunnelWeb was/were the
remaining tools that I had selected as the most prommising ones (but did not
tried them, as mentioned above, so I can't really vote for them).

(In/with R you can use Sweave, which allows to embed code and results from code
 like tables, and even to embedd created graphics into the document!)


An overview with links to some of the LP-tools can be found here:

  http://www.literateprogramming.com/tools.html


I remember that there were a lot more free tools, than mentioned there.

  I remember one really nice tool only for C-dialects, which did not have
  big functionality, but allowed to pretty print C-Code with real TeX-Comments
  inserted. And the syntax was very simple.
  But it was not allowing insertion of the results of the program,
  at least not directly. But via TeX/LaTeX-include/input--commands I think it was possible
  indirectly.

  But you look for more functionality, and want to pass back the results into
  your document. Something like Sweave.

Possibly FWEB or FunnelWEB are the tools, you should explore first.
(But be prepared to learn their syntax....)

Let me know, which tool you selected, and how your experience was with it.


Ciao,
   Oliver


P.S.: In a documenting-/reverse-engineering project I programmed my own
      literate programming tool(s), so that I could insert Text and
      graphviz-commands into the code-comments. The Perl-Tools did extract the
      text and the graphviz code, invoked graphviz and created a LaTeX-document
      that contained the Code, the documenting text and the Graphviz-graphics
      (e.g. for Flowcharts), and created a nice pdf-document, including the
      nice references, to open certain parts of the doc by clicking on the
      entries in the table of contents. :-)
      By organizing the document via includes/inputs, the document structure could be
      organized the way I wanted. (The laTeX-code was also created by the
      Perl-script(s).


P.P.S.: When using troff it's possible to write C code and it's documentation
        in troff (including PIC-macros :-)) in a way, that it can be C-compiled
        directly, without tangling-process, and the document can be set with
        troff without weaving-process. So, it's possible to have one C-file and
        pass it into C-compiler and troff without changes. :-) Very funny, to
        make this. But changing the order of sections is not possible. Real
        LP-tools IMHO should offer reordering of sections, but most of them
        don't.
      
Alan Schmitt suggested:
I'm using org-mode for this (http://orgmode.org/). The support for caml
uses a session, so when you evaluate / export code the previous code is
taken into account. I've used it for courses slides (exported to beamer)
and for caml exams (where the type of the expected answers is computed
from the correction, which is of course not exported).
      
Jonathan Protzenko replied and Alain Frisch added:
> Thanks for the numerous replies. There are a lot of good solutions in
> there, and the ones that looked closest to what I had in mind seem to be
> MPP and the rwo-run-toplevel script. Some questions about these two tools:
> - MPP seems to just have the built-in language. I couldn't find any
> example in the examples/ directory that used another language, such as
> OCaml. I guess that's because it's still in development?
> - rwo-run-toplevel seems closer to what I have in mind; if I could send
> all the ocaml parts to a top-level session, and put in my document what
> gets sent to stdout (not the toplevel reply, that is, not the "val f:
> int -> int" parts), that would be pretty much all I need.
> rwo-run-toplevel seems to perform a lot of work, though: what are all
> these rewrite rules?
> 
> Other solutions seemed interesting. The Perl script scared me a little
> bit; being no Perl hacker, I would have a hard time using it. The
> Markdown library does not seem to be an exact fit (I want the output of
> arbitrary OCaml commands to be put in the middle of my markdown.) Stog
> seems to be oriented towards reproducing an interactive toploop session,
> while I'm more interested in executing arbitrary commands. Alain's sed
> trick seems to be exactly what I need, I'm just a bit afraid if I ever
> need to change something, it'll be break. But in essence, yes, that's
> just all I need. Other proposals seemed a little bit too far away from
> what I had in mind.

Be careful with OCaml lexical convention though.  If you use e.g. " or \ 
in your text, you'll need also to escape them with sed.  Alternatively, 
you could use the new syntax for string literals ({foo|....|foo}) now 
available in trunk.
      
Philippe Wang also replied:
MPP currently has 2 things: the built-in language and its commands,
and the ability to bring OCaml as a pre-processor language.

With mpp -its (-its is an option to be less strict on trailing spaces
in commands) :

((x cmd ocamlopt foo.ml x))
will execute "ocamlopt foo.ml" in a shell and input its output.
Note that "x" is the name of the block. It could be FOO or 23NUI'è!çé
instead, so that one can write ((x cmd echo $((42+42)) x)) for
instance without being bothered by escaping stuff.
-> This is an example of the builtin commands.
To have the list of built-in commands: mpp -b

One may want to nest mpp commands. In this case, another pair of
tokens is used: {{ and }}.
so ((x cmd ocamlopt foo.ml x)) could be written {{x cmd ocamlopt
foo.ml x}} instead. In this precise case, there is absolutely no
difference. However, one can also write {{x cmd ocamlopt {{y get
filename y}} x}} or {{x cmd ocamlopt ((y get filename y)) x}}. But if
one write ((x ocamlopt ((y get filename y)) x)) then a shell will try
to run "ocamlopt ((y get filename y))", which is probably not what's
intended...

All tokens of the language provided by mpp are customisable on the
command line and live in mpp as well. mpp -so 42 will use "42" instead
of "((" to open blocks.
(( so TOTO)) will use TOTO to open blocks after this one, meaning that
to set the open token back to what it was, one could write TOTO so
(())

Well, it's up to the user to imagine how powerful it is.

Then, there is the ability to bring ocaml as a pre-processor language.
This is actually the main motivation for mpp.
Sometimes, you write something using a specific language and you just
wish you could easily use OCaml (or another language...) to preprocess
your file.
With mpp, the default tokens are {< and >} to embed ocaml.
This means that in any file, one can write ocaml and have its output.

Small example in markdown:

If you write this in the file e.md
```
# Number of the day
{< let foo = 42 >}
The number of the day is {< let () = Printf.printf "%d" foo >}.
```

And you run mpp -l ocaml over e.md (note the -l option), then you obtain
```
 let _ = print_string "# Number of the day\n\n"
 let foo = 42  let _ = print_string "\nThe number of the day is \n"
 let () = Printf.printf "%d" foo  let _ = print_string ".\n\n"
```
which is an ocaml programme that you can run to have your final document:

```
# Number of the day


The number of the day is
42.
```

You can see that the environment is shared. If you want different
environments, it's possible to run mpp several times with different
opening and closing tokens.

Of course, you may use ocaml as a preprocessor language in an ocaml
programme (instead of a markdown document), or any textual file
actually.

For the moment, ocaml is the only option supported by "mpp -l" but
I'll provide more language soon. (To provide a language X, one has to
write a "description" of how to convert a text file into an X
programme.)


I've not written much documentation for MPP yet because I've been
mainly working on OMD, a Markdown->HTML converted and Markdown parser
library in OCaml. Now I believe OMD is nearly done, so I'm getting
back to MPP soon...
      

Pippo: a pretty interesting pre-processor that uses OCaml

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2013-09/msg00015.html

Jonathan Protzenko announced:
Following yesterday's discussion, and using that as a pretext for 
writing my own tool, here's yet another pre-processor-sort-of.

https://github.com/protz/pippo

It requires OCaml 4.01.0rc1. The documentation for it is, of course, 
pre-processed using Pippo. It is distributed with a Makefile that 
allows you to recompile the documentation and thus play with the tool.

It works as described in yesterday's thread: anything found between {% 
and %} is fed to an OCaml interactive session. Therefore, the output of 
the OCaml commands is interleaved with the non-OCaml parts of the file. 
Basically, the tool allows you to script your documents easily.

The tool also contains a special "inject_value" facility, that allows 
you to make any OCaml value (constant, function) available in the 
top-level session. For instance, running:

  inject_value
    "__version"
    "unit -> unit"
    (fun () ->
      print_endline "This is pippo v0.1");

will allow you to write, in the to-be-pre-processed document :

{%
  __version ();
%}

For the record, the question (how do I use Toploop.setvalue) was asked 
a few years ago but left unanswered 
http://caml.inria.fr/pub/ml-archives/caml-list/2009/03/7e9085b8601142024108e254df9dfb1e.en.html. 
The OCaml maintainers should probably not look at the implementation, 
by the way.

Cheers,

~ jonathan

PS: My warmest thanks go to Thomas Braibant for helping me find a name 
with a pun (in French)
      

Other Caml News

From the ocamlcore planet blog:
Thanks to Alp Mestan, we now include in the Caml Weekly News the links to the
recent posts from the ocamlcore planet blog at http://planet.ocaml.org/.

A new open source app in Opa: Birdy:
  http://blog.opalang.org/2013/09/a-new-open-source-app-in-opa-birdy.html

Real World OCaml:
  http://gaiustech.wordpress.com/2013/08/30/real-world-ocaml/

ocurl 0.6.0 released:
  https://forge.ocamlcore.org/forum/forum.php?forum_id=884

Litiom 2.1 released:
  https://forge.ocamlcore.org/forum/forum.php?forum_id=883

The elements of an inductive type:
  http://math.andrej.com/2013/08/28/the-elements-of-an-inductive-type/
      

Old cwn

If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a look at the archive or the RSS feed of the archives.

If you also wish to receive it every week by mail, you may subscribe online.


Alan Schmitt