Browse thread
my stupidity and non-tail calls
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Norman Ramsey <nr@e...> |
| Subject: | my stupidity and non-tail calls |
OK, I apologize for bothering everyone. My `tail calls' are actually
sitting inside `try ... with' blocks, so I recognize that these cannot be
optimized since they are in the scope of different handlers. I will
have to find a way to restructure my code. A great pity, since
I like it the way it is... suggestions are welcome.
For those who wished to see the offending code, I append it, or you
can visit http://www.eecs.harvard.edu/~nr/rsync.html.
Norman
let compress {size=size; blocks=blocks} infile =
let blocktab = mkBlockTable blocks in
let roll = Checksum.roll size in
let rec compressLoop instr' b q csum infile =
try (* first case: hit in the block table *)
match BTab.find_all blocktab csum
with [] -> raise Not_found
| candidates ->
let contents = Buffer.create size in
let () = Queue.iter (Buffer.add_char contents) q in
let fp = Fingerprint.string (Buffer.contents contents) in
let (blockNum, _) = List.find (fun (_, fp') -> fp = fp') candidates in
let instr' =
if Buffer.length b > 0 then STRING (Buffer.contents b) :: instr'
else instr' in
let instr' = BLOCK_NUMBERED blockNum :: instr' in
( Buffer.reset b
; Queue.clear q
; startCompressing instr' b q infile
)
with Not_found ->
try
let next = input_char infile in
let () = Queue.add next q in
let prev = Queue.take q in
let () = Buffer.add_char b prev in
let csum = roll csum prev next in
compressLoop instr' b q csum infile
(*********** not really a tail call ******)
with End_of_file ->
finishCompressing instr' b q
and finishCompressing instr' b q =
let () = Queue.iter (Buffer.add_char b) q in
List.rev (STRING (Buffer.contents b) :: instr')
and startCompressing instr' b q infile =
let rec fillAndSum csum k =
if k = 0 then csum
else
let c = input_char infile in
( Queue.add c q
; fillAndSum (Checksum.append csum c) (k-1)
) in
try
compressLoop instr' b q (fillAndSum (Checksum.string "") size) infile
with End_of_file ->
finishCompressing instr' b q in