Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Dynamically evaluating OCaml code
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: skaller <skaller@u...>
Subject: Re: [Caml-list] build tools - good vs. fast, both cheap
On Sat, 2004-04-17 at 02:06, Kenneth Knowles wrote:

> These are the approaches I can see out there:
> 
> (1) Monolithic automagical GNU Makefile
> (2) O'Caml script outputing make-agnostic Makefile
> (3) Command-line build-every-at-once ocaml tool
> (4) Roll your own Makefile, have the user edit it - often separated into a
>     Makefile.config.
> (5) Use autoconf (why, oh why?  it doesn't offer any O'Caml support)
> (6) Interscript? I don't really understand what it does and what the developer
>     must do.

I'm against make. It just isn't necessary. Make is for C developers,
not Ocaml package installation. To build a package it suffices
to run a sequence of commands in a fixed order.

To understand interscript .. what does it do?
The answer is the same as tar -zxvf, except that
'extracting' a file can execute arbitrary code.
Its that simple. Here's an example:

@head(1,"My program")
Its only a demo.

@select(tangler("sample.ml")
let f x = x + x
@for i in [1..10]:
  tangle("print_endline (f "+i+");")

@doc()
This demo prints 2,4, .. 20. The Python script
means: @head -- document heading level 1.
The @select(tangler("sample.ml")) .. means 
"write the following stuff to sample.ml"

The @ starts an arbitrary Python command.
The select, tangler, and head functions
are just interscript library functions,
nothing special. The tangle() functions
write a string to output.

The for loop prints out 

print_endline(f 1);
print_endline(f 2);
...
etc up to 10. It is just a standard Python construction,
nothing special. If you want to compile
the above program instantly, here is how to do it:

@os.system("ocamlc -c sample.ml")

Duh. It just calls Python's system function,
which is C's system function. It is more usual
to do this though:

@select(tangler("Makefile"))
all:
@tangle("\tocamlc -c sample.ml")

@doc()
and then after you run interscript you have
a makefile, and you can compile using 
the ordinary 'make' command. 

The point of all this is: you can do anything
you want. Its just Python script, with a little
control loop that copies lines to the weaver
for typesetting, the tangler to write a source
file, or executes them (if they start with @).

Oh yes, there is much more than that,
but this is the basic idea...

EXECISE: What does this do:

@os.system("ocaml sample.ml > sample.out")
@f = open("sample.out")
@for i in [1..10]:
  tangle(f.readline())
@doc()

If you want to see a more advanced use
of the executable facilities, examine
section 6.4 of the interscript implementation
listing at http://interscript.sf.net.

What you will see there is the full
Unicode data, and code tables for something like
30 other standard character sets -- there
are hundreds of pages of character tables,
and the whole of it is generated by about
a page of code which downloads and reads
the unicode.org data files.

Here is a real example from Felix compiler.
Have you ever got annoyed at copying
things in both mli and ml files??

@head(1,'Compile time exceptions')
@python('//')
exceptions = """
open Flx_ast
open Flx_types
exception SyntaxError of string
exception ParseError of string
exception LexError of string
exception TokenError of string
exception ClientError of range_srcref * string
exception ClientError2 of range_srcref * range_srcref * string
exception SystemError of range_srcref * string
exception Exit of int
exception Bad_recursion
exception Expr_recursion of expr_t
exception Free_fixpoint of btypecode_t 
exception Unresolved_return of range_srcref * string
"""
//
@h = tangler('src/flx_exceptions.ml')
@select(h)
@tangle(exceptions)
let clierr2 sr sr2 s = raise (ClientError2 (sr,sr2,s))
let clierr sr s = raise (ClientError (sr,s))
let syserr sr s = raise (SystemError (sr,s))
let catch s f = try f() with _ -> failwith s

@h = tangler('src/flx_exceptions.mli')
@select(h)
@tangle(exceptions)
val clierr: range_srcref -> string -> 'a
val clierr2: range_srcref -> range_srcref -> string -> 'a
val syserr: range_srcref -> string -> 'a
val catch: string -> (unit -> 'a) -> 'a



-- 
John Skaller, mailto:skaller@users.sf.net
voice: 061-2-9660-0850, 
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net



-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners