.ml
contenant respectivement : la syntaxe abstraite
(syntax.ml), l'afficheur
(pprint.ml), l'analyse syntaxique
(alexsynt.ml) et l'évaluation des
instructions (eval.ml). Chaque début
de fichier contiendra l'ouverture des modules nécessaires à sa
compilation.
typeop_unr
=
OPPOSE
|
NON
;;
typeop_bin
=
PLUS
|
MOINS
|
MULT
|
DIV
|
MOD
|
EGAL
|
INF
|
INFEQ
|
SUP
|
SUPEQ
|
DIFF
|
ET
|
OU
;;
typeexpression
=
ExpInt
of
int
|
ExpVar
of
string
|
ExpStr
of
string
|
ExpUnr
of
op_unr
*
expression
|
ExpBin
of
expression
*
op_bin
*
expression
;;
typeinstruction
=
Rem
of
string
|
Goto
of
int
|
of
expression
|
Input
of
string
|
If
of
expression
*
int
|
Let
of
string
*
expression
;;
typeligne
=
{
num
:
int
;
inst
:
instruction
}
;;
typeprogram
=
ligne
list
;;
typephrase
=
Ligne
of
ligne
|
List
|
Run
|
End
;;
letpriority_ou
=
function
NON
->
1
|
OPPOSE
->
7
letpriority_ob
=
function
MULT
|
DIV
->
6
|
PLUS
|
MOINS
->
5
|
MOD
->
4
|
EGAL
|
INF
|
INFEQ
|
SUP
|
SUPEQ
|
DIFF
->
3
|
ET
|
OU
->
2
;;
letpp_opbin
=
function
PLUS
->
"+"
|
MULT
->
"*"
|
MOD
->
"%"
|
MOINS
->
"-"
|
DIV
->
"/"
|
EGAL
->
" = "
|
INF
->
" < "
|
INFEQ
->
" <= "
|
SUP
->
" > "
|
SUPEQ
->
" >= "
|
DIFF
->
" <> "
|
ET
->
" & "
|
OU
->
" | "
letpp_opunr
=
function
OPPOSE
->
"-"
|
NON
->
"!"
;;
openSyntax;;
letparenthese
x
=
"("
^
x
^
")"
;;
letpp_expression
=
let
rec
ppg
pr
=
function
ExpInt
n
->
(string_of_int
n)
|
ExpVar
v
->
v
|
ExpStr
s
->
"\""
^
s
^
"\""
|
ExpUnr
(op
,
e)->
let
res
=
(pp_opunr
op)
^
(ppg(priority_ou
op)
e)
in
if
pr
=
0
then
res
else
parenthese
res
|
ExpBin
(e1
,
op,
e2)->
let
pr2
=
priority_ob
op
in
let
res
=
(ppg
pr2
e1)
^
(pp_opbinop)
^
(ppdpr2
e2)
(* parenthèse si la priorite n'est pas supérieure *)
in
if
pr2
>=
pr
then
res
else
parenthese
res
and
ppd
pr
exp
=
match
exp
with
(* les sous-arbres droits ne diffèrent *)
(* que pour les opérateurs binaires *)
ExpBin
(e1
,
op,
e2)->
let
pr2
=
priority_ob
op
in
let
res
=
(ppg
pr2
e1)
^
(pp_opbinop)
^
(ppdpr2
e2)
in
if
pr2
>
pr
then
res
else
parenthese
res
|
_
->
ppg
pr
exp
in
ppg
0
;;
letpp_instruction
=
function
Rem
s
->
"REM "
^
s
|
Goto
n
->
"GOTO "
^
(string_of_int
n)
|
e
->
"PRINT "
^
(pp_expression
e)
|
Input
v
->
"INPUT "
^
v
|
If
(e
,
n)
->
"IF "
^
(pp_expressione)
^
" THEN "
^
(string_of_intn)
|
Let
(v
,
e)->
"LET "
^
v
^
" = "
^
(pp_expression
e)
;;
letpp_ligne
l
=
(string_of_int
l
.
num)
^
" "
^
(pp_instruction
l
.
inst)
;;
openSyntax;;
typelexeme
=
Lint
of
int
|
Lident
of
string
|
Lsymbol
of
string
|
Lstring
of
string
|
Lfin
;;
typechaine_lexer
=
{chaine
:
string;mutable
courant
:
int;taille
:
int}
;;
letinit_lex
s
=
{
chaine
=
s;courant
=
0
;
taille
=
String.lengths
}
;;
letavance
cl
=
cl
.
courant
<-
cl
.
courant+
1
;;
letavance_n
cl
n
=
cl
.
courant
<-
cl
.
courant+
n;;
letextrait
pred
cl
=
let
st
=
cl
.
chaineand
ct
=
cl
.
courantin
let
rec
ext
n
=
if
n
<
cl.
taille
&&
(pred
st
.[
n]
)then
ext
(n
+
1
)else
n
in
let
res
=
ext
ct
in
cl
.
courant
<-
res
;
String.sub
cl
.
chainect
(res
-
ct)
;;
letextrait_int
=
let
est_entier
=
function
'0'
..
'9'
->
true
|
_
->
false
in
function
cl
->
int_of_string
(extrait
est_entier
cl)
letextrait_ident
=
let
est_alpha_num
=
function
'a'
..
'z'
|
'A'
..
'Z'
|
'0'
..
'9'
|
'_'
->
true
|
_
->
false
in
extrait
est_alpha_num
;;
exceptionLexerErreur
;;
let
rec
lexer
cl
=
let
lexer_char
c
=
match
c
with
' '
|
'\t'
->
avance
cl
;
lexer
cl
|
'a'
..
'z'
|
'A'
..
'Z'
->
Lident
(extrait_ident
cl)
|
'0'
..
'9'
->
Lint
(extrait_int
cl)
|
'"'
->
avance
cl
;
let
res
=
Lstring
(extrait
((
<>
)
'"'
)cl)
in
avance
cl
;
res
|
'+'
|
'-'
|
'*'
|
'/'
|
'%'
|
'&'
|
'|'
|
'!'
|
'='
|
'('
|
')'
->
avance
cl;
Lsymbol
(String.make
1
c)
|
'<'
|
'>'
->
avance
cl;
if
cl
.
courant
>=
cl
.
taillethen
Lsymbol
(String.make
1
c)
else
let
cs
=
cl
.
chaine.[
cl.
courant]
in
(
match
(c
,
cs)with
(
'<'
,
'='
)->
avance
cl;
Lsymbol
"<="
|
(
'>'
,
'='
)->
avance
cl;
Lsymbol
">="
|
(
'<'
,
'>'
)->
avance
cl;
Lsymbol
"<>"
|
_
->
Lsymbol
(String.make
1
c)
)
|
_
->
raise
LexerErreur
in
if
cl
.
courant
>=
cl
.
taillethen
Lfin
else
lexer_char
cl
.
chaine.[
cl.
courant]
;;
typeexp_elem
=
Texp
of
expression
(* expression *)
|
Tbin
of
op_bin
(* opérateur binaire *)
|
Tunr
of
op_unr
(* opérateur unaire *)
|
Tpg
(* parenthèse gauche *)
;;
exceptionParseErreur
;;
letsymb_unr
=
function
"!"
->
NON
|
"-"
->
OPPOSE
|
_
->
raise
ParseErreur
letsymb_bin
=
function
"+"
->
PLUS
|
"-"
->
MOINS
|
"*"
->
MULT
|
"/"
->
DIV
|
"%"
->
MOD
|
"="
->
EGAL
|
"<"
->
INF
|
"<="
->
INFEQ
|
">"
->
SUP
|
">="
->
SUPEQ
|
"<>"
->
DIFF
|
"&"
->
ET
|
"|"
->
OU
|
_
->
raise
ParseErreur
lettsymb
s
=
try
Tbin
(symb_bin
s)
with
ParseErreur
->
Tunr
(symb_unr
s)
;;
letreduit
pr
=
function
(Texp
e)::(Tunr
op)::st
when
(priority_ou
op)
>=
pr
->
(Texp
(ExpUnr
(op
,
e)))::st
|
(Texp
e1)::(Tbin
op)::(Texp
e2)::st
when
(priority_ob
op)
>=
pr
->
(Texp
(ExpBin
(e2
,
op,
e1)))::st
|
_
->
raise
ParseErreur
;;
letrec
empile_ou_reduit
lex
stack
=
match
lex
,
stack
with
Lint
n
,
_
->
(Texp
(ExpInt
n))::stack
|
Lident
v
,
_
->
(Texp
(ExpVar
v))::stack
|
Lstring
s
,
_
->
(Texp
(ExpStr
s))::stack
|
Lsymbol
"("
,
_
->
Tpg::stack
|
Lsymbol
")"
,
(Texp
e)::Tpg::st
->
(Texp
e)::st
|
Lsymbol
")"
,
_
->
empile_ou_reduit
lex
(reduit
0
stack)
|
Lsymbol
s
,
_
->
let
symbole
=
if
s
<>
"-"
then
tsymb
s
(* lever l'ambiguïte du symbole ``-'' *)
(* suivant la pile (i.e dernier exp_elem empile) *)
else
match
stack
with
(Texp
_
)::_
->
Tbin
MOINS
|
_
->
Tunr
OPPOSE
in
(
match
symbole
with
Tunr
op
->
(Tunr
op)::stack
|
Tbin
op
->
(
try
empile_ou_reduit
lex
(reduit
(priority_ob
op)
stack
)
with
ParseErreur
->
(Tbin
op)::stack
)
|
_
->
raise
ParseErreur
)
|
_
,
_
->
raise
ParseErreur
;;
letrec
reduit_tout
=
function
|
[]
->
raise
ParseErreur
|
[
Texpx
]
->
x
|
st
->
reduit_tout
(reduit
0
st)
;;
letparse_exp
fin
cl
=
let
p
=
ref
0
in
let
rec
parse_un
stack
=
let
l
=
(
p
:=
cl.
courant;
lexer
cl)
in
if
not
(fin
l)
then
parse_un
(empile_ou_reduit
l
stack)
else
(
cl
.
courant
<-
!
p;
reduit_tout
stack
)
in
parse_un
[]
;;
letparse_inst
cl
=
match
lexer
cl
with
Lident
s
->
(
match
s
with
"REM"
->
Rem
(extrait
(fun
_
->
true)
cl)
|
"GOTO"
->
Goto
(match
lexer
cl
with
Lint
p
->
p
|
_
->
raise
ParseErreur)
|
"INPUT"
->
Input
(match
lexer
cl
with
Lident
v
->
v
|
_
->
raise
ParseErreur)
|
"PRINT"
->
(parse_exp
((
=
)Lfin)
cl)
|
"LET"
->
let
l2
=
lexer
cl
and
l3
=
lexer
cl
in
(
match
l2
,
l3with
(Lident
v
,
Lsymbol
"="
)->
Let
(v
,
parse_exp((
=
)Lfin)
cl)
|
_
->
raise
ParseErreur
)
|
"IF"
->
let
test
=
parse_exp
((
=
)(Lident
"THEN"
))cl
in
(
match
ignore
(lexer
cl)
;
lexer
cl
with
Lint
n
->
If
(test
,
n)
|
_
->
raise
ParseErreur
)
|
_
->
raise
ParseErreur
)
|
_
->
raise
ParseErreur
;;
letparse
str
=
let
cl
=
init_lex
str
in
match
lexer
cl
with
Lint
n
->
Ligne
{
num
=
n;
inst
=
parse_instcl
}
|
Lident
"LIST"
->
List
|
Lident
"RUN"
->
Run
|
Lident
"END"
->
End
|
_
->
raise
ParseErreur
;;
openSyntax;;
openPprint;;
openAlexsynt;;
typevaleur
=
Vint
of
int
|
Vstr
of
string
|
Vbool
of
bool
;;
typeenvironnement
=
(string
*
valeur)
list
;;
typeetat
=
{
ligne
:
int;
prog
:
program;
env
:
environnement}
;;
exceptionRunErreur
of
int
letrunerr
n
=
raise
(RunErreur
n)
;;
letrec
eval_exp
n
envt
expr
=
match
expr
with
ExpInt
p
->
Vint
p
|
ExpVar
v
->
(
try
List.assoc
v
envt
with
Not_found
->
runerr
n
)
|
ExpUnr
(OPPOSE
,
e)->
(
match
eval_exp
n
envt
e
with
Vint
p
->
Vint
(
-
p)
|
_
->
runerr
n
)
|
ExpUnr
(NON
,
e)->
(
match
eval_exp
n
envt
e
with
Vbool
p
->
Vbool
(not
p)
|
_
->
runerr
n
)
|
ExpStr
s
->
Vstr
s
|
ExpBin
(e1
,
op,
e2)
->
match
eval_exp
n
envt
e1
,
op
,
eval_exp
n
envt
e2
with
Vint
v1
,
PLUS
,
Vint
v2
->
Vint
(v1
+
v2)
|
Vint
v1
,
MOINS
,
Vint
v2
->
Vint
(v1
-
v2)
|
Vint
v1
,
MULT
,
Vint
v2
->
Vint
(v1
*
v2)
|
Vint
v1
,
DIV
,
Vint
v2
when
v2
<>
0
->
Vint
(v1
/
v2)
|
Vint
v1
,
MOD
,
Vint
v2
when
v2
<>
0
->
Vint
(v1
mod
v2)
|
Vint
v1
,
EGAL
,
Vint
v2
->
Vbool
(v1
=
v2)
|
Vint
v1
,
DIFF
,
Vint
v2
->
Vbool
(v1
<>
v2)
|
Vint
v1
,
INF
,
Vint
v2
->
Vbool
(v1
<
v2)
|
Vint
v1
,
SUP
,
Vint
v2
->
Vbool
(v1
>
v2)
|
Vint
v1
,
INFEQ
,
Vint
v2
->
Vbool
(v1
<=
v2)
|
Vint
v1
,
SUPEQ
,
Vint
v2
->
Vbool
(v1
>=
v2)
|
Vbool
v1
,
ET
,
Vbool
v2
->
Vbool
(v1
&&
v2)
|
Vbool
v1
,
OU
,
Vbool
v2
->
Vbool
(v1
||
v2)
|
Vstr
v1
,
PLUS
,
Vstr
v2
->
Vstr
(v1
^
v2)
|
_
,
_
,
_
->
runerr
n
;;
letrec
ajoute
v
e
env
=
match
env
with
[]
->
[
v,
e]
|
(w
,
f)::l->
if
w
=
vthen
(v
,
e)::lelse
(w
,
f)::(ajoutev
e
l)
;;
letrec
goto_ligne
n
prog
=
match
prog
with
[]
->
runerr
n
|
l::ll
->
if
l
.
num
=
n
then
prog
else
if
l
.
num<
nthen
goto_ligne
n
ll
else
runerr
n
;;
letprint_valeur
v
=
match
v
with
Vint
n
->
print_int
n
|
Vbool
true
->
print_string
"true"
|
Vbool
false
->
print_string
"false"
|
Vstr
s
->
print_string
s
;;
leteval_inst
etat
=
let
lc
,
ns
=
match
goto_ligne
etat
.
ligneetat
.
progwith
[]
->
failwith
"programme vide"
|
lc
::[]
->
lc
,-
1
|
lc::ls
::_
->
lc
,
ls.
num
in
match
lc
.
instwith
Rem
_
->
{
etat
with
ligne
=
ns}
|
e
->
print_valeur
(eval_exp
lc
.
numetat
.
enve)
;
print_newline
()
;
{
etat
with
ligne
=
ns}
|
Let(v
,
e)->
let
ev
=
eval_exp
lc
.
numetat
.
enve
in
{
etat
with
ligne
=
ns;env
=
ajoutev
ev
etat
.
env}
|
Goto
n
->
{
etat
with
ligne
=
n}
|
Input
v
->
let
x
=
try
read_int
()
with
Failure
"int_of_string"
->
0
in
{
etat
with
ligne
=
ns;
env
=
ajoutev
(Vint
x)
etat
.
env}
|
If
(t
,
n)->
match
eval_exp
lc
.
numetat
.
envt
with
Vbool
true
->
{
etat
with
ligne
=
n}
|
Vbool
false
->
{
etat
with
ligne
=
ns}
|
_
->
runerr
n
;;
letrec
run
etat
=
if
etat
.
ligne
=
-
1
then
etat
else
run
(eval_inst
etat)
;;
letrec
inserer
ligne
p
=
match
p
with
[]
->
[
ligne]
|
l::prog
->
if
l
.
num
<
ligne
.
numthen
l::(inserer
ligne
prog)
else
if
l
.
num=
ligne.
numthen
ligne::prog
else
ligne::l::prog
;;
letprint_prog
etat
=
let
print_ligne
x
=
print_string
(pp_ligne
x)
;
print_newline
()
in
print_newline
()
;
List.iter
print_ligne
etat
.
prog;
print_newline
()
;;
letpremiere_ligne
=
function
[]
->
0
|
i
::_
->
i
.
num
;;
exceptionFin
letune_commande
etat
=
print_string
"> "
;
flush
stdout
;
try
match
parse
(input_line
stdin)
with
Ligne
l
->
{
etat
with
prog
=
insererl
etat
.
prog}
|
List
->
(print_prog
etat
;
etat
)
|
Run
->
run
{etat
with
ligne
=
premiere_ligne
etat
.
prog}
|
End
->
raise
Fin
with
LexerErreur
->
print_string
"Illegal character\n"
;etat
|
ParseErreur
->
print_string
"syntax error\n"
;etat
|
RunErreur
n
->
print_string
"runtime error at line "
;
print_int
n
;
print_string
"\n"
;
etat
;;
letgo
()
=
try
print_string
"Mini-BASIC version 0.1\n\n"
;
let
rec
loop
etat
=
loop
(une_commande
etat)
in
loop
{
ligne
=
0
;prog
=[]
;env
=[]
}
withFin
->
print_string
"A bientôt...\n"
;;
$ ocamlc -c syntax.ml $ ocamlc -c pprint.ml $ ocamlc -c alexsynt.ml $ ocamlc -c eval.ml
openEval;;
go();;
$ ocamlmktop -o topbasic syntax.cmo pprint.cmo alexsynt.cmo eval.cmo mainbasic.mltest du toplevel :
$ topbasic Mini-BASIC version 0.1 > 10 PRINT "DONNER UN NOMBRE" > 20 INPUT X > 30 PRINT X > LIST 10 PRINT "DONNER UN NOMBRE" 20 INPUT X 30 PRINT X > RUN DONNER UN NOMBRE 44 44 > END A bientôt... Objective Caml version 2.04 #
$ ocamlc -custom -o basic.exe syntax.cmo pprint.cmo alexsynt.cmo eval.cmo mainbasic.mltest de l'exécutable autonome :
$ basic.exe Mini-BASIC version 0.1 > 10 PRINT "BONJOUR" > LIST 10 PRINT "BONJOUR" > RUN BONJOUR > END A bientôt... $
(***********************************************************************)
(* *)
(* Objective Caml *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* Automatique. Distributed only by permission. *)
(* *)
(***********************************************************************)
(* $Id: sort.mli,v 1.1 2000/01/21 09:40:00 emmanuel Exp $ *)
(* Module [Sort]: sorting and merging lists *)
vallist
:
('a
->
'a
->
bool)
->
'a
list
->
'a
list
(* Sort a list in increasing order according to an ordering predicate.
The predicate should return [true] if its first argument is
less than or equal to its second argument. *)
valarray
:
('a
->
'a
->
bool)
->
'a
array
->
unit
(* Sort an array in increasing order according to an
ordering predicate.
The predicate should return [true] if its first argument is
less than or equal to its second argument.
The array is sorted in place. *)
valmerge
:
('a
->
'a
->
bool)
->
'a
list
->
'a
list
->
'a
list
(* Merge two lists according to the given predicate.
Assuming the two argument lists are sorted according to the
predicate, [merge] returns a sorted list containing the elements
from the two lists. The behavior is undefined if the two
argument lists were not sorted. *)
(***********************************************************************)
(* *)
(* Objective Caml *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* Automatique. Distributed only by permission. *)
(* *)
(***********************************************************************)
(* $Id: sort.ml,v 1.1 2000/01/21 09:18:40 emmanuel Exp $ *)
(* Merging and sorting *)
openArray
letrec
merge
order
l1
l2
=
match
l1
with
[]
->
l2
|
h1
::
t1
->
match
l2
with
[]
->
l1
|
h2
::
t2
->
if
order
h1
h2
then
h1
::
merge
order
t1
l2
else
h2
::
merge
order
l1
t2
letlist
order
l
=
let
rec
initlist
=
function
[]
->
[]
|
[
e]
->
[[
e]]
|
e1::e2::rest
->
(if
order
e1
e2
then
[
e1;e2]
else
[
e2;e1]
)::
initlist
rest
in
let
rec
merge2
=
function
l1::l2::rest
->
merge
order
l1
l2
::
merge2
rest
|
x
->
x
in
let
rec
mergeall
=
function
[]
->
[]
|
[
l]
->
l
|
llist
->
mergeall
(merge2
llist)
in
mergeall(initlist
l)
letswap
arr
i
j
=
let
tmp
=
unsafe_get
arr
i
in
unsafe_set
arr
i
(unsafe_get
arr
j);
unsafe_set
arr
j
tmp
letarray
order
arr
=
let
rec
qsort
lo
hi
=
if
hi
<=
lo
then
()
else
if
hi
-
lo
<
5
then
begin
(* Use insertion sort *)
for
i
=
lo
+
1
to
hi
do
let
val_i
=
unsafe_get
arr
i
in
if
order
val_i
(unsafe_get
arr
(i
-
1
))then
begin
unsafe_set
arr
i
(unsafe_get
arr
(i
-
1
));
let
j
=
ref
(i
-
1
)in
while
!
j
>=
1
&&
order
val_i
(unsafe_get
arr
(
!
j
-
1
))do
unsafe_set
arr
!
j(unsafe_get
arr
(
!
j
-
1
));
decr
j
done;
unsafe_set
arr
!
jval_i
end
done
end
else
begin
let
mid
=
(lo
+
hi)
lsr
1
in
(* Select median value from among LO, MID, and HI *)
let
pivotpos
=
let
vlo
=
unsafe_get
arr
lo
and
vhi
=
unsafe_get
arr
hi
and
vmid
=
unsafe_get
arr
mid
in
if
order
vlo
vmid
then
if
order
vmid
vhi
then
mid
else
if
order
vlo
vhi
then
hi
else
lo
else
if
order
vhi
vmid
then
mid
else
if
order
vhi
vlo
then
hi
else
lo
in
swap
arr
pivotpos
hi;
let
pivot
=
unsafe_get
arr
hi
in
let
i
=
ref
lo
and
j
=
ref
hi
in
while
!
i
<
!
jdo
while
!
i
<
hi
&&
order
(unsafe_get
arr
!
i)pivot
do
incr
i
done;
while
!
j
>
lo
&&
order
pivot
(unsafe_get
arr
!
j)do
decr
j
done;
if
!
i
<
!
jthen
swap
arr
!
i
!
j
done;
swap
arr
!
ihi;
(* Recurse on larger half first *)
if
(
!
i
-
1
)
-
lo
>=
hi
-
(
!
i
+
1
)then
begin
qsort
lo
(
!
i
-
1
);qsort
(
!
i
+
1
)hi
end
else
begin
qsort
(
!
i
+
1
)hi;
qsort
lo
(
!
i
-
1
)
end
end
in
qsort
0
(Array.length
arr
-
1
)
letinterval
order
next
a
b
=
let
rec
aux
a
=
if
not
(order
a
b)
then
[
a]
else
a
::
aux
(next
a)
in
aux
a;;
letmain
()
=
let
il
=
Interval.interval
(
>
)(fun
x
->
x
-
1
)
5
0
0
0
0
2
0
and
il2
=
Interval.interval
(
<
)(fun
x
->
x
+
1
)
2
0
5
0
0
0
0
in
Sort.list
(
<
)il
,
Sort.list
(
>
)il2;;
main();;
ocamlc -custom -o trilbyte.exe sort.mli sort.ml interval.ml trilist.ml
ocamlopt -o trilopt.exe sort.mli sort.ml interval.ml trilist.ml
trilbyte.exe | trilopt.exe |
2,55 secondes (user) | 1,67 secondes (user) |
letmain
()
=
let
il
=
Array.of_list(Interval.interval
(
>
)(fun
x
->
x
-
1
)
5
0
0
0
0
2
0
)
and
il2
=
Array.of_list(Interval.interval
(
<
)(fun
x
->
x
+
1
)
2
0
5
0
0
0
0
)
in
Sort.array
(
<
)il
,
Sort.array
(
>
)il2;;
main();;
ocamlc -custom -o triabyte.exe sort.mli sort.ml interval.ml triarray.ml
ocamlopt -o triaoptu.exe sort.mli sort.ml interval.ml triarray.ml
triabyte.exe | triaopt.exe |
515 s | 106 s |