[Caml-list] Define parser and printer consistently

2010-12-08 Thread Dawid Toton

I'm going to define a parser and a printer for a simple grammar.
Is there a way to define both of them in a single construct using some 
existing OCaml tool?


For example, I have a keyword "function". The usual parser would contain 
a mapping like:

"function" -> `Function
and the straightforward printer would do:
`Function -> "function"

What is the best way to combine these definitions, so that duplication 
would be minimized?
To be precise, avoiding duplication is not exactly what I need. I'm 
looking for something that would prevent making inconsistent changes to 
the parser and the printer.


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Re: help with regular expression

2010-12-06 Thread Dawid Toton

On 12/06/2010 12:43 PM, zaid khalid wrote:
> I want some help in writing regular expressions in Ocaml, as I know 
how to write it in informal way but in Ocaml syntax I can not. For 
example I want to write "a* | (aba)* ".

>
> Another question if I want the string to be matched against the 
regular expression to be matched as whole string not as substring what 
symbol I need to attach to the substring, i.e if I want only concrete 
strings accepted (like (" ", a , aa , aaa, aba, abaaba), but not ab or 
not abaa).

>

I also had problems with Str (regexp descriptions being unreadable, 
error-prone and hard to generate dynamically) and decided just to stop 
using Str.
I have a tiny module [1] made with clarity in mind. It is pure OCaml. It 
defines operators like $$ to be used in regexp construction. This way 
syntax of the expressions is checked at compile time. Also, it is 
trivial to build them at run time.
The whole "engine" is contained in a relatively short function 
HRegex.subwords_of_subexpressions, so I believe anybody can hack it 
without much effort.


I haven't measured performance of this implementation. I expect it to be 
slow when processing long strings. It's just OK for my needs so far. 
Anyway, the important part is the module interface. It expresses my 
point of view on this topic.


The code is available in a mercurial repository [2].

The exemple "a* | (aba)* " would become:

open HRegex.Operators

let rx = (!* !$ "a") +$ (!* !$ "aba")

Dawid

[1] 
http://hg.ocamlcore.org/cgi-bin/hgwebdir.cgi/hlibrary/hlibrary/raw-file/tip/HRegex.mli

[2] http://hg.ocamlcore.org/cgi-bin/hgwebdir.cgi/hlibrary/hlibrary

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Re: Smart ways to implement worker threads

2010-07-16 Thread Dawid Toton

> I find it odd that there is no Threaded_Queue module, a thread save
> version of Queue with 2 extra functions: (...)
>   
I use such a thread-safe queue a lot [1]. This is very simple yet
universal enough. Honestly I can hardly remember using more elaborate
constructs.

Dawid

[1] http://pfpleia.if.uj.edu.pl/projects/HLibrary/browser/HQueue.ml

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Re: Binding and evaluation order in module/type/value languages

2010-05-21 Thread Dawid Toton

> It is not clear that this will work at all.
> The semantics of ocaml (contrary to SML) is not defined in terms of
> type generativity.
>
>   
This is great eureka to me.
I thought that when the compiler refuses to unify some types it knows
that they are incompatible (as the error message says).
But now I think (as I currently understand non-generativity) that
sometimes the compiler simply doesn't know if some types are equal and
avoids unification of such types. The error message should be instead:
"Cannot unify the following types, because I don't have any proof that
they are equal (and I don't have looked for the proof really hard)..."

So in order to have not unifiable phantom types one has to kind of trick
the compiler and hide the fact that they are equal.

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Binding and evaluation order in module/type/value languages

2010-05-17 Thread Dawid Toton
Thinking about the discussion in the recent thread "Phantom types" [1],
I have created the following piece of code that aims to demonstrate
binding and evaluation order that takes effect in all three levels of OCaml.

My question is: what are the precise rules is the case of type language?
I have impression that it is lazy and memoized evaluation. But this my
guess looks suspicious.

I don't intend this question to be about inner working of the compiler,
but about the definition at the conceptual level.


(* 1. Module language; side effect = create fresh record type; test =
type equality test *)

module type T = sig type t end
module R (T:T) = struct type r = {lab : int} end

module TF = struct type t = float end
module TS = struct type t = string end
module R1 = R(TF)
module R2 = R(TF)
module R3 = R(TS)

let test12 (k : R1.r) (l : R2.r) = (k=l) (* pass => R1.r = R2.r *)
let test13 (k : R1.r) (l : R3.r) = (k=l) (* pass => R1.r = R3.r *)

(* Conclusion: RHS evaluated at the mapping definition point *)

(* 2. Type language; side effect = create fresh record type; test = type
equality test *)

type 't r = {lab : int}

type tf = float
type ts = string
type r1 = tf r
type r2 = tf r
type r3 = ts r

let test12 (k : r1) (l : r2) = (k=l) (* pass => r1 = r2 *)
let test13 (k : r1) (l : r3) = (k=l) (* fail => r1 ≠ r3 *)

(* Conclusion: RHS evaluated some time after the mapping is applied;
sort of memoization at the conceptual level *)

(* 3. Value language; side effect = create fresh int; test = value
equality test *)
let r t = Oo.id (object end)

let tf = 0.
let ts = "A"
let r1 = r tf
let r2 = r tf
let r3 = r ts

let test12 = assert (r1 = r2) (* fail => r1 ≠ r2 *)
let test13 = assert (r1 = r3) (* fail => r1 ≠ r3 *)

(* Conclusion: RHS evaluated exactly at the point of mapping application *)

Dawid

[1]
http://groups.google.com/group/fa.caml/browse_thread/thread/0df560ee78e0f75f#


___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Binding and evaluation order in module/type/value languages

2010-05-17 Thread Dawid Toton
Thinking about the discussion in the recent thread "Phantom types" [1],
I have created the following piece of code that aims to demonstrate
binding and evaluation order that takes effect in all three levels of OCaml.

My question is: what are the precise rules is the case of type language?
I have impression that it is lazy and memoized evaluation. But this my
guess looks suspicious.

I don't intend this question to be about inner working of the compiler,
but about the definition at the conceptual level.


(* 1. Module language; side effect = create fresh record type; test =
type equality test *)

module type T = sig type t end
module R (T:T) = struct type r = {lab : int} end

module TF = struct type t = float end
module TS = struct type t = string end
module R1 = R(TF)
module R2 = R(TF)
module R3 = R(TS)

let test12 (k : R1.r) (l : R2.r) = (k=l) (* pass => R1.r = R2.r *)
let test13 (k : R1.r) (l : R3.r) = (k=l) (* pass => R1.r = R3.r *)

(* Conclusion: RHS evaluated at the mapping definition point *)

(* 2. Type language; side effect = create fresh record type; test = type
equality test *)

type 't r = {lab : int}

type tf = float
type ts = string
type r1 = tf r
type r2 = tf r
type r3 = ts r

let test12 (k : r1) (l : r2) = (k=l) (* pass => r1 = r2 *)
let test13 (k : r1) (l : r3) = (k=l) (* fail => r1 ≠ r3 *)

(* Conclusion: RHS evaluated some time after the mapping is applied;
sort of memoization at the conceptual level *)

(* 3. Value language; side effect = create fresh int; test = value
equality test *)
let r t = Oo.id (object end)

let tf = 0.
let ts = "A"
let r1 = r tf
let r2 = r tf
let r3 = r ts

let test12 = assert (r1 = r2) (* fail => r1 ≠ r2 *)
let test13 = assert (r1 = r3) (* fail => r1 ≠ r3 *)

(* Conclusion: RHS evaluated exactly at the point of mapping application *)

Dawid

[1]
http://groups.google.com/group/fa.caml/browse_thread/thread/0df560ee78e0f75f#


___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Re: Phantom types

2010-05-17 Thread Dawid Toton

> type 'a t = {l: float}
>
> Any thoughts ?

I think the crucial question is when new record types are born. Here is
my opinion:

The "=" sign in the above type mapping definition is what I would call
"delayed binding". "Early binding" would be equivalent to

type tmp = {lab : float}
type 'a s = tmp

(evaluate the right-hand side first, then define the mapping).

The "early binding" creates only one record type, so lab becomes
ordinary record label.
In the given example of the "delayed binding" the t becomes a machine
producing new record types.
Hence, the identifier l is not an ordinary record label. It is shared by
whole family of record types. We can see it this way:

# type 'a t = { la : float } ;;
type 'a t = { la : float; }
# {la = 0.};;
- : 'a t = {la = 0.}

So OCaml interpreter doesn't know the exact type of the last expression,
but it is clever enough to give it a generalized type.
We can use la to construct records of incompatible types:

# type 'a t = { la : float } ;;
type 'a t = { la : float; }
# let yy = ({la = 0.} : int t) ;;
val yy : int t = {la = 0.}
# let xx = ({la = 0.} : string t);;
val xx : string t = {la = 0.}
# xx = yy;;
Error: This expression has type int t but an expression was expected of type
 string t


I suppose my jargon may be not mainstream, apologies.

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Extending Set - strange behavior of abstract type

2010-04-27 Thread Dawid Toton
I tried to extend the standard Set module with new operations. I got 
error messages about type incompatibilities (the Set.S.t as exposed by 
my implementation and Set.S.t used by functions from the original Set). 
I have reduced my code to the following small example:


module Set = struct
  module Make (Ord : Set.OrderedType) = struct
module Set = Set.Make(Ord)
include Set
  end
end

module OrdChar = struct type t = char let compare = compare end
module Raw1 = Set.Make (OrdChar)
module Raw2 = Set.Make (struct type t = char let compare = compare end)

let aaa (aa : Raw1.t) (bb : Raw1.Set.t) = (aa = bb)
let aaa (aa : Raw2.t) (bb : Raw2.Set.t) = (aa = bb)

Only the last line results in an error:
Error: This expression has type Raw2.Set.t but is here used with type Raw2.t

All the rest of the code compiles correctly. It means that types Raw1.t 
and Raw1.Set.t can be unified.


My question is: why these nearly identical statements results in 
different behavior of the type t?


I'd really prefer Raw1 and Raw2 to be identical.
I use ocaml 3.11.0.

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Re: Module type of a structure returned by functor

2010-04-26 Thread Dawid Toton
I've found that I have more fundamental problem. What is the exact 
meaning of the following line?


module type Foo = functor (X:X) -> sig val foo : X.t end

(1) Foo is not a functor, but it is a type of some functors that map 
modules to modules

(2) Foo is a mapping from modules to module types

Currently I think that it (1) is true and (2) is false. Let me know if 
I'm wrong.


It means that there is no easy way to get module type of what results 
from functor application. I think that the solution is to separately 
define signature of results of the functor and use "with type" clauses 
to recreate all result module types that are needed.


This is not very bad, but I'm still wondering if "module type of..." of 
3.12 will provide elegant solution for this.


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Module type of a structure returned by functor

2010-04-23 Thread Dawid Toton
1. The following piece of code contains illegal constructs. These are 
functor applications marked with (* ? *).

Basically, I need module type of what is produced by functor.
My first question is: what is the proper, "canonical" workaround 
for unavailability of applications marked (* ? *) ?


module type Big = sig type t type u end
module type Small = sig type t end

module type MakeEdge = functor (Big : Big) -> sig val foo : Big.t option end
module MakeEdge = functor (Big : Big) -> struct let foo = None end

module type Add_boilerplate = functor (Small:Small) -> sig type t end
module Add_boilerplate = functor (Small:Small) -> struct type t = 
Small.t type u = t end


module type ConvenientEdge = functor (Small:Small) -> MakeEdge 
(Add_boilerplate (Small)) (* ? *)
module ConvenientEdge = functor (Small:Small) -> MakeEdge 
(Add_boilerplate (Small))


module SmallX = struct type t = int end
module EdgeX = ConvenientEdge (SmallX)
module type EdgeX = ConvenientEdge (SmallX) (* ? *)

module Algorithm = functor (EdgeX : EdgeX) -> struct let doit = 
EdgeX.foo end



2. And the related question: why one can't do functor applications in 
module types as in above lines marked with (* ? *) ? Is there some 
theoretical reason?


3. Will the "module type of..." feature of 3.12 help with this? I can 
imagine e.g.:


module type EdgeX = (module type of (ConvenientEdge (SmallX)))


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] OCaml on AIX

2010-01-27 Thread Dawid Toton

Christoph Bauer pisze:

Please try:

$ cd asmrun
$ cpp -DSYS_aix power-aix.S > power-aix.s
$ as -u  power-aix.s
$ cd ..
$ make opt

Christoph Bauer

  
Apparently I can go directly without preprocessor (and cpp I have on the 
AIX machine doesn't like asm syntax):


$ cp power-aix.S power-aix.s
$ as -u -o power-aix.o power-aix.s
$ cd ..
$ gmake opt

So I get working native code.
The remaining problem is that camlp4 crashes on some Unix call when 
preprocessing. I solved it by preprocessing all the code on another machine.


Thank you for your help.

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] Bytecode run on AIX - "unknown C primitive" error

2010-01-20 Thread Dawid Toton



unfortunatly I haven't a solution for the bytecode stuff. I only use
ocaml with native compiled code. This works very well.
  
Native code would also be sufficient (to save me from translating lot of 
code to C).


The problem is that the assembler available on AIX doesn't unserstand 
power-aix.S:


as  -o power-aix.o power-aix.S
Assembler:
power-aix.S: line 103: 1252-023 The symbol .caml_garbage_collection is 
not defined.

power-aix.S: line 103: 1252-087 The target of the branch instruction
   must be a relocatable or external expression.
power-aix.S: line 457: 1252-023 The symbol caml_young_limit is not defined.
power-aix.S: line 457: 1252-040 The specified expression is not valid.
   Make sure that all symbols are defined.
   Check the rules on symbols used in an arithmetic expression
   concerning relocation.
.. (many similar messages)

How have you obtained running ocamlopt?

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Bytecode run on AIX - "unknown C primitive" error

2010-01-19 Thread Dawid Toton

I have installed part of this OCaml port
http://home.arcor.de/chr_bauer/ocaml-aix.html
on a computer running on AIX. It seems that everything built correctly 
except ocamlopt. So I have ocamlrun and standard library and this should 
be enough for bytecode to run.


I have to build the bytecode on a different machine (because it's 
difficult to do on AIX). I believe this shouldn't induce any problems.


Trivial bytecode executes correctly regardless where it is created.

I set LIBPATH to point to ocaml/stublibs and try running some bytecode 
uning Unix module. This results in:

Fatal error: unknown C primitive `unix_getsockopt_bool'

If I compile simple "let _ = Unix.sleep 1" on the target machine, I get 
bytecode that causes ocamlrun to crash with:

Illegal instruction (core dumped)

Does anybody have an idea for workaround? Some understanding what's 
going on?


I'm using AIX 5.3

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Linking mutually dependent modules for fun

2009-10-16 Thread Dawid Toton

I often get into trouble of cyclic dependencies when writing in OCaml.
Perhaps, I'm still not enough mentally shifted from poor languages (for
which circular design is quite natural).

Of course OCaml has many tools to deal with this: functors (which, once
introduced, spread like a disease), type variables and generalization
(which sometimes deadly collide with the functorial way) and ugly global
ref cells (which smell).

Why not try some Pascal style then? ;)
The following is what I got when studying OCaml's linking issues:

A.mli: val flip : unit -> unit
A.ml: let flip () = print_string "1"; B.flop ()  let _ = flip ()
B.mli: val flop : unit -> unit
B.ml: let flop () = print_string "0"; A.flip ()
C.ml: let _ = print_endline "C"

Compile:
ocamlopt -c -S A.ml
ocamlopt -c -S B.ml

The resulting .o depends on existing cmx files, so we can reach fixpoint
 by doing it once more:
ocamlopt -c -S A.ml

The new compiled A happens to work with uinitialized B.
Then use some helper module:
ocamlopt -c -S C.ml
ocamlopt -dstartup -ccopt --verbose C.cmx

Modify a.startup.s to call camlA_entry instead of camlC__entry.
as -o startup.o a.out.startup.s

Verbose gcc invocation gave us proper linking command.
Replace
...std_exit.o C.o /./stdlib.a ...
with just
...std_exit.o A.o B.o /./stdlib.a ...

And go!

OK, I must admit that I don't know how to get startup code that would
work in general. This one had wrong memory maps and no initialization of
B... anyway it works. :)

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Re: Incremental linking

2009-10-16 Thread Dawid Toton


Yes.  "ocamlopt -pack" actually calls "ld -r" underneath to
consolidate several compilation units in a single .cmx/.o file.
"ld -r" will resolve references between these compilation units.


I tried with this switch and indeed I can link a toy program by
arbitrary intermediate steps. It works OK and is good news to me.

Since today I thought that I have no way to generate the startup code
quickly, but I came to the following solution:
ocamlopt -o prog -dstartup --cc echo A.cmx B.cx C.cmx D.cmx
as -o prog.startup.o prog.startup.s

This way I have all the technical pieces working. Now I have to think
how to automate this. :)



Generally speaking, I'm somewhat surprised that linking time is an
issue for Dawid.  Modern Unix linkers are quite fast, and the
additional link-time work that OCaml does is small.  Let us know if
you manage to narrow the problem.


My interest in this comes from combination of few facts: all my
calculations are done on a not very fresh machine, my code is a big tree
of small modules and I normally work this way:
1. modify some module (usually at leaf position)
2. recompile everything to native code
3. run, look at the results and go to 1.

I need therefore fast recompilation and fast linking (to stay focused on
the work). I'm about to solve the problem of ocamlbuild spending all its
time looking at unmodified modules. Then I wanted to make sure that it
will be possible to mitigate the second bottleneck.

This is why I'm happy to be able to do incremental linking.

It's helpful that the ocamlopt itself is very fast.

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Incremental linking

2009-09-29 Thread Dawid Toton

I have lot of modules and they are compiled to native code.
So I have .cmx and .o files and want to link them faster.

Is is possible to make linking an associative operation acting on modules?

I would like to do something like the following:
Knowing the correct partial order of modules (that compiler requires) I
can create a tree that preserves that order. Leafs are modules. Other
nodes of the tree correspond to a result of linking all descendant
modules. Modules that are frequently recompiled are placed closer to the
root. This way I expect to execute less linking operations during
development.

Documentation of ld says that files produced with --relocatable can be
used as intermediate partially linked files. Can something like this be
done with object code produced by ocamlopt?
I don't know ocaml-specific details of linking, so maybe I overlook some
obvoius obstacle?

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Incremental linking

2009-09-29 Thread Dawid Toton

I have lot of modules and they are compiled to native code.
So I have .cmx and .o files and want to link them faster.

Is is possible to make linking an associative operation acting on modules?

I would like to do something like the following:
Knowing the correct partial order of modules (that compiler requires) I 
can create a tree that preserves that order. Leafs are modules. Other 
nodes of the tree correspond to a result of linking all descendant 
modules. Modules that are frequently recompiled are placed closer to the 
root. This way I expect to execute less linking operations during 
development.


Documentation of ld says that files produced with --relocatable can be 
used as intermediate partially linked files. Can something like this be 
done with object code produced by ocamlopt?
I don't know ocaml-specific details of linking, so maybe I overlook some 
obvoius obstacle?


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Broken dumps from memprof patch?

2009-06-08 Thread Dawid Toton
I have compiled MinGW port of the comopiler (3.10) with memprof patch 
applied.

I can produce heap dumps, but heapstats tool fails to load it.

I had to change major_gc.c, the line:
#include 
is replaced by a stub:
int getpid() {return 8;}

I had to tag all files in hp dir as precious (using hp/_tags file).

Surprisingly I get no linking error with boot/stdlib.cma when doing the 
first step:

make -f Makefile.nt world

Gc.dump_heap successfully created a file while running bytecode.
I had to remove labltk from OTHERLIBRARIES (in config/Makefile), 
otherwise bootstrap step results in:


File "shell.ml", line 78, characters 15-27:
Unbound value Mutex.create

I got three executables: heapstats.exe, heapstats.opt and hp2ps.exe in 
root dir of the sources. 'make -f Makefile.nt install installopt' didn't 
install them.


At first, threads.cmxa and friends were not built, because my make 
(using normal Cygwin) was unable to resolve a symbolic link (thread.ml 
to thread_posix.ml). I made a copy instead and it compiled.


Trying to run heapstats on a fresh dump file (from toplevel loop) 
results in (the first line is my debug output):


globals_map length = 469785344
Fatal error: exception Invalid_argument("String.create")
Raised at file "hp/hPLoadHeap.ml", line 88, characters 20-37

The file is 320kB only, it can't contain 470MB of globals_map.
Should I assume that bytecode produces broken heap dumps?

Loading of a dump produced from native code went further:

$ heapstats.opt -heap heap.dump.8.0
globals_map length = 115
info list element length = 1721
info list element length = 193024
Fatal error: exception End_of_file
Raised at file "pervasives.ml", line 302, characters 15-26
Called from file "hp/hPLoadHeap.ml", line 118, characters 4-30
Called from file "hp/hPLoadHeap.ml", line 121, characters 14-21
Called from file "hp/hPLoadHeap.ml", line 173, characters 18-43
Called from file "hp/hPMain.ml", line 20, characters 16-38
Called from file "arg.ml", line 146, characters 12-33
Called from file "arg.ml", line 197, characters 8-27
Called from file "arg.ml", line 211, characters 4-32
Called from file "hp/hPMain.ml", line 10, characters 2-1023

Any ideas?

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Re: Memory leak & slowdown

2009-06-05 Thread Dawid Toton


The overall memory usage grows significantly over time, but I don't know 
why. After it consumes several MB extra, it slows considerably and 
becomes unusable, so I have to fix this.


I'm still unable to figure out what is the allocated memory, but I 
discovered few things:


* there is available (somewhat hidden) version of memprof patch that 
works with 3.10.0:

  http://www.pps.jussieu.fr/~smimram/docs/ocaml-3.10.0-memprof.patch
* It seems that I can't use gprof with OCaml programs in Windows


I can roughly remember I had memory leaks some time ago if I allocated 
big arrays in expose event handler (with lablgtk2) - still have to 
verify this.


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Re: Memory leak & slowdown

2009-06-05 Thread Dawid Toton




You might want to instrument the [caml_]register_global_root function
and see how often it gets called.


Is it possible to enable profiling in the compiler in Windows or Cygwin 
environment? Cygwin has gprof, but OCaml's configure script says 'no 
profiling'.


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Memory leak & slowdown

2009-06-05 Thread Dawid Toton
I have an OCaml program using GTK running on Windows, using multiple 
threads.


The overall memory usage grows significantly over time, but I don't know 
why. After it consumes several MB extra, it slows considerably and 
becomes unusable, so I have to fix this.


Is it possible that this is related to GC compaction being turned off? 
Additional calls to Gc.compact seemingly don't help.


The memory usage grows only when the main processing loop is working. 
After the function exists, the memory is not freed. Moreover, if I start 
it again, it 'reuses' the leaked memory. The second execution of the 
loop takes more memory only after it takes more time than the previous one.


This made me thinking that it's just some container growing but not 
shrinking. So I checked my toplevel values with the objsize library, but 
I managed to trace down only a fraction of the allocated memory and the 
sizes I get don't grow.


How to do memory profiling?

The program can have about 10MB of useful data and 200MB of something I 
don't know. How to check what is this?


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] (Not) corrupt output of printf

2009-01-23 Thread Dawid Toton



Weird ... I was going to suggeest it was because you weren't flushing
the output after each print statement.  


This raises important question:
Let's see the output as a sequence of bytes (there's no time).
Assuming that the process exits normally and incompatible printing 
functions are not mixed:
is there a guarantee (in OCaml library) that the flush operation doesn't 
affect the output?


For me it's obvious that the output shouldn't depend on the presence of 
flush operations. If otherwise - needs to be explicitly stated.


(Of course I'm not considering the one special flush action done when 
closing a stream, but it's tied to the closing function.)


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] (Not) corrupt output of printf

2009-01-23 Thread Dawid Toton

This was actually a bug in GNOME Terminal... sorry for the noise.

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Corrupt output of printf

2009-01-22 Thread Dawid Toton

I have a program, which output is produced only with Printf.printf .
This inner part is executed by another one (outer) using Unix.system . 
The outer executable uses print_endline before and after the inner is run.


From time to time the output of the inner program is corrupt.

Printf.printf seemingly devours parts of single lines, as in these 
examples (all lines should have the same structure):


156 In: 5.483000, 1.50, 1.76
157 Sb: 5.008000, 1.494000, 1.50
158 In: 4.498000, 1.494000, 0.75
159160 Sb: 5.003000, 1.503000, 0.508000

Another one:

138 In: 5.00, 0.00, 0.253000
139 In: 5.001000, 1.000140 Sb: 5.50, 0.00, 0.00
141 Sb: 5.50, 1.00, 0.00

This isn't easily reproducible as it happens rarely; subsequent runs are OK.

Could anybody find a possible cause of this behavior?

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] What is a future of ocaml?

2009-01-14 Thread Dawid Toton
Few days ago I spent some time googling for any info in the subject and 
found nothing (except assigned feature requests in the tracer).


Would be great to know what should be expected about OCaml in a long term.
I understand that there's no manpower to push the core compiler forward 
faster. But it would be a solace to know that there are at least some 
optimistic plans with a broader horizon.


(say, following is a collection of dreams :))

Is there any hope for a grand 'OCaml 4' release that would iron out the 
last ugly spots left in the language with some breaking changes?


E.g.:
Have immutable strings for everyday use and mutable byte arrays as buffers?

Full support for revised syntax? (Error messages, documentation...)

Make modules practically first-class by devising some standard way of 
automatic module to record conversion?


Make record fields acting as projection functions?

Could anybody explain why it's impossible to have type classes in OCaml?
We have few very special operators like (=), is there any chance to make 
them less magic and work out anything that would satisfy basic needs for 
overloading?


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] Toplevel - loading dependencies

2009-01-09 Thread Dawid Toton

in case you're doing so this way:
ocamlc -o my.cma mod1.ml mod2.ml mod3.ml mod4.ml

this will recompile everything,
but you can use in your makefile:
(...)
then you don't recompile everything, only the modified module



Yes, with ocamlbuild I need not to recompile everything, but it's slow 
traversing even nothing-to-be-done tree:


Finished, 432 targets (411 cached) in 00:00:08.

It takes already 8 seconds if nothing is touched.

If I edit few files, it's worse:

Finished, 432 targets (256 cached) in 00:00:49.

I'm looking for alternatives.

That's why I try with scripting: keep core libraries compiled and run 
outermost parts with an interpreter.


Another idea is to change ocamlbuild to work dynamically: keep the 
dependency tree in memory and update it from time to time, watching 
files on disk.


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] Toplevel - load cmo from given location

2009-01-09 Thread Dawid Toton



The problem is that it gives "Unbound module Enum" while no error about loading the 
cmo&cmi is shown.


The #directory instruction is needed to find the .cmi.


I see, so there are 2 problems:
* why the failure to load cmi is silent in this case?
* why the toplevel fails to check for cmi where the cmo is located? This 
looks as incorrect behaviour (the reference manual doesn't mention any 
exceptional rules for the #load directive).


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Toplevel - loading dependencies

2009-01-09 Thread Dawid Toton

Another problem with loading modules in the toplevel:
I need to use the module A. So I write:
#load "A.cmo"
to get a messsage "Reference to undefined global B"
So I prepend a line:
#load B.cmo
and get another "undefined global". Then it repeats prohibitively many 
times.

This is resolving dependencies by hand, one by one.

The solution would be to have a special version of cmo that knows 
locations of all other cmo's it depends on.


In special cases I could use cma archives, but this is only applicable 
when there is well defined and stable set of modules I need.
But in practice the modules I use in ocaml scripts are constantly 
evolving. It leads to having multiple cma aggregates and maintaining 
their building description. Again, lots of work.


If I put everything into one big cma, then I have to recompile it every 
small change. It takes so long time, that it would make no sense to use 
the interpreter at all.


Could I ask ocamlbuild to produce proper loading preamble for my scripts?

What is the right solution?

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Toplevel - load cmo from given location

2009-01-09 Thread Dawid Toton

I've noticed stange behaviour:

The following works OK (using #directory directive):

#!/usr/bin/ocamlrun ocaml
#directory "/home/dt2/Calc1/CalcEngine/src/_build/extlib/"
#load "enum.cmo"
open Enum

But this version not (using the full path directly):

#!/usr/bin/ocamlrun ocaml
#load "/home/dt2/Calc1/CalcEngine/src/_build/extlib/enum.cmo"
open Enum

The problem is that it gives "Unbound module Enum" while no error about 
loading the cmo&cmi is shown.

So:
* if it finds correctly the enum.cmi: why "open Enum" doesn't work?
* if the cmi is not found, why I see no message like "*Cannot find file 
*/home/dt2/Calc1/CalcEngine/src/_build/extlib/enum.cmi*" - as chapter 
9.4 of docs suggests? Does the toplevel check for the cmi in the same 
location as cmo? *

(I tested this with the cmi file existing there as built by ocamlbuild)

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Portable hash

2008-11-13 Thread Dawid Toton
I'm looking for a way to calculate hashes of values of variuos types. It 
has to be:

1. proper function (i.e. x=y => (hash x)=(hash y) )
2. and should not change with a platform or compiler version.
3. It'd also help to have practically no collisions.

For some time I needed not to move data across machines and what I have 
been (wrongly) using for this so far is:

let hash x =  Digest.string (Marshal.to_string x [])

Recently I realized that it's incorrect as Marshal.to_string is not pure 
function and doesn't satisfy my first requirement. Indeed in some very 
rare cases I got different results from the same value. Only the 3rd 
point is satisfied very well.


I have to change my function before I run into problems and I'm considering:
1) Small hashes:

let hash x =  |Hashtbl.hash_param large_int large_int x

Does anybody know what are properies of | |Hashtbl.hash_param? I mean: 
is the implementation stable? Can I have good distribution when all the 
data is examined (large parameters)?


Unfortunately it returns int of platform-dependent length (and even 
platform-depentent less significant bits of result?). How hard would it 
be to tailor it to, say, work always with 31 bits?

||
2) To serialize values with Sexp:

let hash to_sexp x = Digest.string (string_of_sexp (to_sexp x))
|
|This way I have the stablility because I can just keep implementation 
of Sexp untouched. But the performance is going to be even worse than 
with my original solution.|


Has anybody solved already this (or similar) problem?

Dawid Toton

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] Quantifier in the type

2008-10-17 Thread Dawid Toton

Hope this helps,


Exactly what I wanted to know! Thanks!
Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] Quantifier in the type

2008-10-16 Thread Dawid Toton

Thanks for your answer; now I'll try to sate my point in a clear way,
since you misunderstood all my questions.


I put 'a in the interface:
val fu : 'a -> 'a
and int in the implementation:
let fu x = x + 1


this interface doesn't reflect the implementation, ocaml will reject it in any 
way


OK, it's all about this rejection, e.g. what does precisely mean 'to
reflect the implementation'.




So I have universal quantification: for any type 'a function fu can
consume the argument.


No it is not universal, imagine all the types that a user can create, you 
cannot handle them all (except maybe with the Obj module, but it's another 
question)


I wanted this my sentence to be about the declatation in mli interface.
My point is: the type in the declaration in mli implicitly contains
universal quantifier.



  So my implementation doesn't comply with that
universal quatification. And the message I get is following:

Values do not match: val fu : int -> int is not included in val fu : 'a
-> 'a


Yes it doesn't match at all, the type of the implementation is int, nothing 
else.


The error message uses plural: 'Value*s* do not match'.
So this raises few questions:
1) Is (fun x -> x + 1) a value?
2) Is (x + 1) a value?
3) Is the whole line " val fu : 'a -> 'a " a value?
4) How many values are in my example?

We have to find at least two, to understand the error message!

An my conlcusion is that this is just silly, unimportant mistake:


So the declaration of value in mli file is called simply a 'value'. Is
it intentional?


It is just the word in the English language to designate this thing.


What do you mean saying 'this thing'?
The point is: *which thing*?


I thought that value and it's declaration are separate notions?


Are they separate in OCaml or not?
(Of course, everybody knows they have to be separate, that's why I'm
asking about the word 'value'.)


a value is handle by a identifier and has a type
  let ident = some_value in
here ident and some_value are of some type


So - according to your point of view - in my example there is only one
value, which has identifier 'fu' and its type would be " 'a -> 'a " if
the implementation was corrent.
But, you remember, the error message was about *two* values.





My reading of " val fu : 'a -> 'a " is:
 some partiular value vvv that belongs to set of values that satisfy
"forall 'a : (vvv can be used with ('a -> 'a) type)"



But if I write
let (bar : 'a -> 'a ) = (fun x -> x + 1)
I create a value that belongs to set "exists 'a : (vvv can be used with
('a -> 'a) type)"
So it's the other quantifier.



I think that the quantifier has to be part of type, since a type is set
of values (and the quantifier plays important role when describing some
of such sets).
So my question is: since we see the same string " 'a -> 'a " that refers
to different types in different contexts, what are the rules? How is
type definition in OCaml translated to a type?


type definition in OCaml are translated to actual types by inference.
(fun x -> x + 1) will be easily infered to (int -> int)


My question was what are the rules for putting universal and
existential quantifers into types. So we have some type definition:
'a -> ('b -> 'c)
How is it translated to a type?

I have an idea that this piece of code can sometimes be not a type
definition, but rather part of type equation.
Let's take my previous example:
let (bar : 'a -> 'a ) = ...

This " 'a -> 'a " whould not define any type (so the problem of
quantifiers would be irrelevant here), but RHS of some type equation.
Still I'm not sure about what does this RHS contais (precisely).

So: was I wrong thinking that existnetial quantifier is involved in this
example?

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] Quantifier in the type

2008-10-15 Thread Dawid Toton

Just an elementary question.

I put 'a in the interface:
val fu : 'a -> 'a
and int in the implementation:
let fu x = x + 1

So I have universal quantification: for any type 'a function fu can 
consume the argument. So my implementation doesn't comply with that 
universal quatification. And the message I get is following:


Values do not match: val fu : int -> int is not included in val fu : 'a 
-> 'a


So the declaration of value in mli file is called simply a 'value'. Is 
it intentional?

I thought that value and it's declaration are separate notions?

My reading of " val fu : 'a -> 'a " is:
some partiular value vvv that belongs to set of values that satisfy  
"forall 'a : (vvv can be used with ('a -> 'a) type)"


But if I write
let (bar : 'a -> 'a ) = (fun x -> x + 1)
I create a value that belongs to set "exists 'a : (vvv can be used with 
('a -> 'a) type)"

So it's the other quantifier.

I think that the quantifier has to be part of type, since a type is set 
of values (and the quantifier plays important role when describing some 
of such sets).
So my question is: since we see the same string " 'a -> 'a " that refers 
to different types in different contexts, what are the rules? How is 
type definition in OCaml translated to a type?


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] 'Compiler' module

2008-10-06 Thread Dawid Toton


Given that the sole objective of run-time compilation is performance and 
Python is vastly slower than OCaml, why are you the envy of Python's Compiler 
(to interpreted bytecode) module?




From my point of view this is more about manipulating code at runtime
and evaluating it (actually I'm not interested about performance).


I think (as Zheng implied) you want asynchronous workflows from F#. Note that 
these also handle cleanup of resources.


From what is currently available on web I see that it's equivalent to
my current stop-gap solution using monads:
(async {blah blah}) in F# can be translated to (lazy (blah blah)) in
OCaml and Async.Run just uses some threads to do Lazy.force. Am I
missing some difference?



For a decent editor, you will need a lot more than that. I would certainly 
love to have such a thing but you also need access to the type checking phase 
to throwback type errors and having the data available in an efficient and 
accessible form would certainly be preferable.




I see no reason for hypothetical Compiler.eval function couldn't give me
full information about all errors.

As for availability of resulting data: this is not obvious at the
conceptual level.

One possibile solution is to decide that the host invoking Compiler.eval
has to treat resulting values as of abstract type. They might be subject
to marshalling and so on.

The other way is to have a module for manipulating data which type is
known at runtime. Then Compiler.eval would return value of type
TypedData.t = (Type.t, TypedData.abstract_type)

The second approach would make the whole Compiler-module-thing more useful.

Anyway, this is somewhat another story. RTTI would allow us to have
clean implementation of marshalling. We could have (at no performance
cost) Type.typeof operator that acts only on values of concrete type
(if only camlp4 knew types...).

I believe you can lex and parse OCaml using Camlp4 and then invoke the OCaml 
compiler with -dtypes to get the results of type checking. However, the 
latter is extremely inefficient. You really want the ability to restart the 
compiler from the end of the previous definition each time a file is edited.


I hope the first dirty solution would be to use compiled modules as the
context carrier. In case of a simple editor I'd have many tiny modules
that correspond to compiled chunks of evolvong code.
It would scale not so bad: compiler would have to load (log n) modules
for n chunks processed. But I have no idea what would be the practical
performance.

Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] 'Compiler' module (was: embedding ocaml into a windows app: need gcc?)

2008-10-03 Thread Dawid Toton



I would like an OCaml support library that can compile and execute
similar to JaveScript engines, but we don't have that in any practical
form.



I also need this and I'm thinking about something like this:

module type Compiler =
sig
 val parse : Context.t -> string -> (Context.t * AST.t)
 val get_type : Context.t -> AST.t -> Type.t;
 val eval : Context.t -> AST.t -> Context.t * (Type.t * 
MarshalledValueOrSomething.t)

end

Is it really so hard to have it in OCaml? I'm envy of Python's Compiler 
module.


It could solve some of my problems, in particular for my 'parallel-like' 
evaluation ( 
http://www.nabble.com/'Nondeterministic'-evaluation-wrt-exceptions-td18653998.html 
). After some experimentation I know that I need type information during 
code transformation. I want to create a sort of interpreter.


That Compiler module would also enable me to have an editor with 
graphical representation of results intermixed with code (like 
Mathematica's notebook).


Where to look for suitable pieces of code? AFAIK camlp4 modules can't 
tell me type of anything. Should I start digging in OCaml compiler sources?


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


Re: [Caml-list] 'Nondeterministic' evaluation wrt exceptions

2008-07-25 Thread Dawid Toton

Thank you all for quick answers!

Let me show an example of what I exactly mean. I start with a code:

1: let a = heavy 1
2: let b = heavy 2
3: let c = report (a + b)
4: let d = heavy 4
5: let e = heavy d

Then I want to translate it automatically so that three applications of
heavy are evaluated (lines 1, 2, 4). The addition a + b won't be
evaluated untill a and b are successfully returned.

It's easier to get only two heavy operations started at once:

0: type 'a future_t = 'a Lazy.t
1: let a = future heavy 1
2: let b = future heavy 2
3: let c = report ((force a) + (force b))
4: let d = future heavy 4
5: let e = future heavy (force d)

Computation of c hangs or throws an exception. Hence lines 4 an 5 are
not executed. So I think I need some more invasive transformarion:

0: type 'a future_t = 'a Lazy.t
1: let a = future heavy 1
2: let b = future heavy 2
3: let c = lazy (report (force a) + (force b))
4: let d = future heavy 4
5: let e = future heavy (force d)
6: let _ = force c

In this case we have a problem: line 5 throws an exception, so report in
line 3 is not executed even if first two heavy operations are finished.
The function report could even contain some other heavy operations that
need to be started as soon as possible.

So I can conctruct a tree of deferred computations, but probably I can't
force it to do as much as possible. Forcing is governed by total order.
Let's consider:

7: let f = foo (force c) (force e)

If one of arguments fails first, the other is not forced. This is bad.

So I go to the original idea: thread the exception across everything.
Wrap with variant instead of Lazy.t.

0: type 'a lifted_t = Exception | Value 'a
1: let a = start heavy 1
2: let b = start heavy 2
3: let c = bind2 (fun a b -> return (report (a+b))) a b
4: let d = start heavy 4
5: let e = bind1 (fun d -> start heavy d) d
7: let f = bind2 (fun c e -> return (foo c e)) c e

Function 'start' starts calculation and returns Exception or returns
Value result if it's available.
bindX functions evaluate the function passed as a parameter if all
arguments are Values.

Is is easy to lift every heavy call to 'start heavy arg arg arg ...' -
since in any case I have to distinguish heavy functions manually.
I need to decide about granularity of bindX incrustation. I can have
some modules marked as 'nondeterministic' and leave the other ones
untouched.
I could wrap into lifted_t all single values in 'nondeterministic'
modules. This would mean placing bindX for every integer addition, every
string concatenation...

I need rules: where should I place bindX and return in the original
code. At the moment I don't know.

I have looked at the Lwt library - as far as I understand in my case the
idea boils down to threading something across all expressions.

Dawid


___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


[Caml-list] 'Nondeterministic' evaluation wrt exceptions

2008-07-25 Thread Dawid Toton

Let's look at my OCaml program as a poset of function applications.
Some its elements throw exceptions.
I need to evaluate all applications except of those that 'Follow' 
exception-throwing ones.

This 'Follow' corresponds to the ordering in my poset.
Unfortunately standard tools allow only to do this with 'Follow' 
corresponding to some total order.
Could you give me some advice how to evaluate really all applications 
that precede throwing an exception?


--
Full story

I have many similar programs that do calculations for me. Some steps are 
very computationally heavy. Every such function do_heavy_thing starts 
another process (on other computer) and throws an exception that means 
"the result will be available later". Everything that relies on this 
result of do_heavy_thing cannot be evaluated. And it won't be because I 
don't catch the exception.


So I run my programs repeatedly. I correct and extend them while 
heavy_thing is done somewhere else (usually for few days).
do_heavy_thing checks for the result. If it's finished at the moment of 
execution, it downloads the data and returns. Then the data undergoes 
some cheap transformations and some next do_heavy_thing function can be 
called.


Every time I execute the program I get some more useful output and 
"Fatal error: exception ..." message. So far this scheme worked very well.


This is basically breaking the calculation at some point with respect to 
a total order (the order of source code). Some calculations should be 
done in parallel, since there are many of them. I solved this problem 
with run_many adapter: firstly collect a list of heavy calculations, 
then execute them as a one node in the total order of evaluation.


Currently I hit the following problem: my new programs (call them 
'Calcs') are too complex to apply the evasion with run_many. So my 
latest calculations are done one-by-one. This is so bad, that I can 
spend several days in order to solve this in a systematical way.


These Calcs are managed by other set of OCaml tools. I have complete 
control over all the code. The tools already do tiny changes to Calcs 
with simple string operations, not real syntax extension. I hope some 
witty preprocessor can help.


I have no idea what code the syntax extension should produce. My first 
guess is to wrap everything in

type 'a wrapped = Exception | Value 'a
and make all aplications evaluated. But this seems to be a big headache. 
Maybe this is well-known, already solved problem? Any ideas?


Dawid

___
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs