Commit 83c72a2e authored by Pietro Abate's avatar Pietro Abate

[r2005-01-03 15:10:20 by afrisch] Doc

Original author: afrisch
Date: 2005-01-03 15:10:21+00:00
parent b192be09
......@@ -11,11 +11,12 @@ Since 0.2.1
- better compilation of sequence capture variables
- punning in record/attribute expressions and values ({ x; y } -> {x=x;y=y})
- removed the warning "no caml interface"
- add "system: Latin1->Latin1", "exit: (0--255)->Empty"
- add "system" and "exit" built-in functions
- (e :? t) raises an exception when e doesn't have type t;
the exception is an explanation of why this is not the case.
- apps-cduce-cvs GODI package is updatable
- /* ... */ comments
- fix --stdin
......@@ -326,9 +326,12 @@ let compile src out_dir =
let compile_run src =
if not (Filename.check_suffix src ".cd")
then raise (InvalidInputFilename src);
let cu = Filename.chop_suffix (Filename.basename src) ".cd" in
let cu =
if src = "" then "<stdin>"
if not (Filename.check_suffix src ".cd")
then raise (InvalidInputFilename src)
else Filename.chop_suffix (Filename.basename src) ".cd" in
let id = (U.mk_latin1 cu) in
Librarian.compile !verbose cu id src; id
......@@ -151,18 +151,20 @@ let rec compile verbose name id src =
check_loop id;
protect_op "Compile external file";
let ic =
try open_in src
with Sys_error _ -> raise (CannotOpen src) in
if src = "" then stdin
try open_in src
with Sys_error _ -> raise (CannotOpen src) in
Location.push_source (`File src);
let input = Stream.of_channel ic in
let p =
try Parser.prog input
| Stdpp.Exc_located (_, (Location _ as e)) -> raise e
(* | Stdpp.Exc_located ((i,j), e) -> raise_loc i j e *)
| Stdpp.Exc_located ((i,j), e) -> raise_loc i.Lexing.pos_cnum j.Lexing.pos_cnum e
| Stdpp.Exc_located ((i,j), e) ->
raise_loc i.Lexing.pos_cnum j.Lexing.pos_cnum e
close_in ic;
if src <> "" then close_in ic;
let argv = ident ( "argv") in
during_compile := true;
C.enter id;
......@@ -361,6 +361,8 @@ EXTEND
| "let"; p = pat; "="; e = expr -> (false,p,e)
| "let"; p = pat; ":"; t = pat; "="; e = expr -> (false,p, Forget (e,t))
| "let"; p = pat; ":"; "?"; t = pat; "="; e = expr ->
(false,p, Check (e,t))
......@@ -91,6 +91,11 @@ let rec token = lexer
comment (L.lexeme_start lexbuf) lexbuf;
in_comment := false;
token lexbuf
| "/*" ->
in_comment := true;
tcomment (L.lexeme_start lexbuf) lexbuf;
in_comment := false;
token lexbuf
| eof ->
return lexbuf ("EOI","")
| _ ->
......@@ -113,6 +118,14 @@ and comment start = lexer
| _ ->
comment start lexbuf
and tcomment start = lexer
| "*/" ->
| eof ->
error start (start+2) "Unterminated comment"
| _ ->
tcomment start lexbuf
and string start double = lexer
| '"' | "'" ->
let d = L.latin1_lexeme_char lexbuf 0 = '"' in
open Operators
open Builtin_defs
open Ident
let len = 1024;;
let variant_type_ascii l =
(fun accu (l,t) ->
Types.cup accu
(Types.cons (Types.atom (Atoms.atom (Atoms.V.mk_ascii l))))
(Types.cons t)))
let run_process s =
let ic = Unix.open_process_in s in
let b = Buffer.create (1024*10) in
let buf = String.create len in
let rec aux () =
let i = input ic buf 0 len in
if i = 0 then () else (Buffer.add_string b (String.sub buf 0 i); aux ())
aux ();
let s = Value.string_latin1 (Buffer.contents b) in
s, Unix.close_process_in ic
let record_type_ascii l =
Types.record' (false,
( (fun (l,t) -> Value.label_ascii l, Types.cons t) l)))
module Reader = struct
let b = Buffer.create 10240
let buf = String.create 1024
let rec read_loop ic =
let i = input ic buf 0 (String.length buf) in
if i > 0 then (Buffer.add_string b (String.sub buf 0 i); read_loop ic)
let ic ic =
read_loop ic;
let s = Buffer.contents b in
Buffer.clear b;
let run_process cmd =
let (sout,sin,serr) as h = Unix.open_process_full cmd (Unix.environment()) in
close_out sin;
let sout = Reader.ic sout in
let serr = Reader.ic serr in
sout,serr, Unix.close_process_full h
let process_status = function
| Unix.WEXITED n ->
Value.Pair (Value.atom_ascii "exited", Value.ocaml2cduce_int n)
| Unix.WSTOPPED n ->
Value.Pair (Value.atom_ascii "stopped", Value.ocaml2cduce_int n)
| Unix.WSIGNALED n ->
Value.Pair (Value.atom_ascii "signaled", Value.ocaml2cduce_int n)
let system_out =
record_type_ascii [
"stdout", string_latin1;
"stderr", string_latin1;
"status", variant_type_ascii [
"exited", int;
"stopped", int;
"signaled", int
let () = register_fun "system" string_latin1 string_latin1
let () = register_fun "system" string_latin1 system_out
(fun v ->
Location.protect_op "system";
match run_process (Value.get_string_latin1 v) with
| s,Unix.WEXITED n ->
if (n = 0) then s
(Value.tagged_tuple "exited" [ Value.ocaml2cduce_int n; s ])
| s,Unix.WSTOPPED n ->
(Value.tagged_tuple "stopped" [ Value.ocaml2cduce_int n; s ])
| s,Unix.WSIGNALED n ->
(Value.tagged_tuple "signaled" [ Value.ocaml2cduce_int n; s ])
let cmd = Value.get_string_latin1 v in
let sout,serr,ps = run_process cmd in
Value.record_ascii [
"stdout", Value.string_latin1 sout;
"stderr", Value.string_latin1 serr;
"status", process_status ps
let () = register_fun "exit" byte_int Types.empty
......@@ -575,12 +575,17 @@ let label_ascii s =
let record l =
Record (LabelMap.from_list_disj l)
let record_ascii l =
record ( (fun (l,v) -> (label_ascii l, v)) l)
let get_field v l =
match v with
| Record fields -> LabelMap.assoc l fields
| _ -> raise Not_found
let get_field_ascii v l = get_field v (label_ascii l)
let abstract a v =
Abstract (a,Obj.repr v)
......@@ -57,7 +57,9 @@ val fold_sequence: ('a -> t -> 'a) -> 'a -> t -> 'a
val atom_ascii : string -> t
val label_ascii : string -> label
val record : (label * t) list -> t
val record_ascii : (string * t) list -> t
val get_field : t -> label -> t
val get_field_ascii : t -> string -> t
val get_variant : t -> string * t option
......@@ -29,6 +29,8 @@ The simplest way to compile and install CDuce is probably to
use the
<a href="">
GODI distribution</a>, and to select the <tt>apps-cduce</tt> package.
There is also a <tt>apps-cduce-cvs</tt> package which synchronize
itself with the CDuce CVS development tree.
......@@ -53,10 +55,9 @@ of the CVS tree.
In order to build CDuce from the current CVS tree, you need
to install <a href="#side">ulex</a>, and also attentively
read the instructions in the <a href="INSTALL">INSTALL</a> file included in the
Another way to follow the development in the CVS is to is the
<tt>apps-cduce-cvs</tt> <a
href=""> GODI</a> package.
......@@ -334,7 +334,9 @@ There are three kinds of operators on records:
<code>%%l%%</code> is the name of a label which must be
present in the result of the evaluation of <code>%%e%%</code>.
This construction is equivalent to: <code>match %%e%% with
{ %%l%% = x } -> x</code>.
{ %%l%% = x } -> x</code>. It is necessary to put
whitespace between the expression and the dot
when the expression is an identifier.
Record concatenation:
......@@ -363,6 +365,13 @@ Binary arithmetic operators on integers:
for projection and <em>not</em> for division.
The operator <code>+,-</code> and <code>*</code> are typed
using simple interval arithmetic. The operators <code>div</code>
and <code>mod</code> produce a warning at compile type if
the type of there second argument include the integer <code>0</code>.
<box title="Generic comparisons, if-then-else" link="comp">
......@@ -434,7 +443,19 @@ let %%p%% = (%%e%% : %%t%%) in %%...%%
Note that the upward coercion allows earlier detection of type errors,
better localization in the program, and more informative messages.
CDuce also have a dynamic type-check construction:
(%%e%% :? %%t%%)
let %%p%% :? %%t%% = %%e%% in %%...%%
If the value resulting from the evaluation of <code>%%e%%</code>
does not have type <code>%%t%%</code>, an exception
whose argument (of type <code>Latin1</code>) explains the reason
of the mismatch is raised.
<box title="XML-specific constructions" link="xml">
......@@ -644,6 +665,32 @@ argument is the filename and the second one is the string to dump.
<box title="System" link="sys">
<section title="Running external commands">
The predefined function <code>system</code> executes
an external command (passed to <code>/bin/sh</code>)
and returns its standard output and standard error
channels and its exit code. The type for <code>system</code>
Latin1 -> {| stdout = Latin1; stderr = Latin1;
status = (`exited,Int) | (`stopped,Int) | (`signaled,Int) |}
<section title="Running external commands">
The predefined function <code>exit</code> terminates
the current process. Its type is <code>0--255 -> Empty</code>.
The argument is the exit code.
<box title="Namespaces" link="ns">
......@@ -27,6 +27,9 @@ toplevel. See the <a href="#toplevel">Toplevel</a> section below.
cduce [OPTIONS ...] [ {{script}}.cd | --stdin ] [--arg ARGUMENT ...]
cduce [OPTIONS ...] --script {{script}}.cd [ ARGUMENT ...]
The command runs the script <code>{{script}}.cd</code>.
......@@ -109,22 +112,29 @@ and built-in optional features, and exit.
CDuce can be used for writing scripts. As usual it suffices to start
the script file by <code> #!%%install_dir%%/cduce</code> to call in a batch way
the CDuce interpreter. Here is an example of a script file that prints all the
titles of the filters of an Evolution mail client.
the script file by <code> #!%%install_dir%%/cduce</code> to call in a
batch way the CDuce interpreter. The <code>--script</code> option can
be used to avoid <code>--arg</code> when calling the script. Here is
an example of a script file that prints all the titles of the filters
of an Evolution mail client.
#!/usr/local/bin/cduce --script
type Filter = <filteroptions>[<ruleset> [(<rule>[<title>String _*])+]];;
let src : Latin1 =
match argv [] with
| [ f ] -> f
| _ -> raise "Invalid command line"
let filter : Filter =
match load_xml "/home/beppe/evolution/filters.xml" with
match load_xml src with
| x&Filter -> x
| _ -> raise "Not a filter document"
in print_xml(<filters>([filter]/<ruleset>_/<rule>_/<title>_)) ;;
print_xml(<filters>([filter]/<ruleset>_/<rule>_/<title>_)) ;;
......@@ -186,7 +196,7 @@ and global namespace default <code>namespace "%%...%%"</code>
<li>Schema declaration <code>schema %%name%% = "%%...%%"</code>
(see <local href="manual_schema">XML Schema</local>).</li>
<li>Give an alias for an external unit <code>using %%alias%% = "%%unit%%"</code>
<li>Alias for an external unit <code>using %%alias%% = "%%unit%%"</code>
or <code>using %%alias%% = %%unit%%</code>:
gives an alternative name for a pre-compiled unit. Values
and types from <code>%%unit%%.cdo</code> can be referred to either as
......@@ -198,6 +208,22 @@ or as <code>%%unit%%:%%ident%%</code>.
<box title="Comments" link="comment">
CDuce supports two style of comments: <code>(* ... *)</code>
and <code>/* ... */</code>. The first style allows the programmer
to put a piece a code apart. Nesting is allowed, and strings
within simple or double quotes are not searched for the end-marker
<code>*)</code>. In particular, simple quotes (and apostrophes)
have to be balanced inside a <code>(* ... *)</code> comment.
The other style <code>/* ... */</code> is more adapted to textual
comments. They cannot be nested and quotes are not treated
specially inside the comment.
<box title="Toplevel" link="toplevel">
......@@ -224,7 +250,7 @@ You can quit the toplevel with the toplevel directive
The toplevel directive <code>#dump_value</code> dump an XML-like
representation of the internal cduce representation of the resulting
representation of the internal CDuce representation of the resulting
value of an expression. It should not be considered a normative
representation for CDuce values.
......@@ -322,12 +322,21 @@ the integer itself.</li>
Grouping <code>(%%R%%)</code>. E.g.: <code>[ x::(Int Int) y ]</code>.
Tail predicate <code>/p</code>. The type/pattern <code>p</code>
applies to the current tail of the sequence (the subsequence
starting at the current position). E.g.:
<code>[ (Int /(x:=1) | /(x:=2)) _* ]</code> will bind
<code>x</code> to <code>1</code> if the sequence starts
with an integer and <code>2</code> otherwise.
Sequence types and patterns also accepts the <code>[ %%...%%; %%...%% ]</code>
notation. This is a convenient way to discard the tail of a sequence
in a pattern, e.g.: <code>[ x::Int* ; _ ]</code>.
in a pattern, e.g.: <code>[ x::Int* ; _ ]</code>, which
is equivalent to <code>[ x::Int* _* ]</code>.
......@@ -382,9 +391,15 @@ The syntax of a record expression is
<code>{ %%l1%% = %%e1%%; %%...%%; %%ln%% = %%en%% }</code>
where the <code>%%li%%</code> are label names (same lexical
conventions as for identifiers), and the <code>%%vi%%</code>
are expressions.
are expressions. When an expression <code>%%ei%%</code>
is simply a variable whose name match the field label
<code>%%li%%</code>, it is possible to omit it.
E.g.: <code>{ x; y = 10; z }</code>
is equivalent to <code>{ x = x; y = 10; z = z }</code>.
They are two kinds of record types. Open record types
are written <code>{ %%l1%% = %%t1%%; %%...%%; %%ln%% = %%tn%%
......@@ -418,7 +433,18 @@ value is not syntactically equal to this value.
The syntax is the same for patterns. Note that capture variables
cannot appear in an optional field.
cannot appear in an optional field. A common idiom is to bind
default values to replace missing optinal fields:<code>
({ x = a } | (a := 1)) &amp; { y = b }</code>. A special syntax
makes this idiom more convenient:
<code>{ x = a else (a:=1); y = b }</code>.
As for record expressions, when the pattern
is simply a capture variable whose name match the field label,
it is possible to omit it. E.g.: <code>{ x; y = b; z }</code>
is equivalent to <code>{ x = x; y = b; z = z }</code>.
......@@ -530,4 +556,12 @@ is only syntactic sugar for the type
<box title="OCaml abstract types" link="abstr">
The notation <code>!t</code> is used by the
<local href="manual_interfacewithocaml">CDuce/OCaml interface</local>
to denote the OCaml abstract type <code>t</code>.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment