[clean-list] Re: Strict lists kill me...

John van Groningen johnvg@cs.kun.nl
Mon, 1 Dec 2003 16:19:22 +0100


Jerzy Karczmarczuk writes:
>More on it...
>
>Reminder: I sent a triple-version program which generates
>a co-recursive stream - a sampled sinusoid. This needed
>lazy lists. With normal lists it works, with head-strict
>[!Real] lists it produces rubbish, with unboxed [#Real]
>it finds a spine black-hole...

The compiler generates incorrect code for a strict or unboxed
list constructor on a cycle that is in a strict context or
in a lazy context with an already evaluated head (or tail for
tail strict lists).

In this case
> z =: [# 0.0 : v]
in function oscils or oscilu.

In the case of a strict (boxed) list an incorrect label is generated
for the constructor, which causes pattern matching on the constructor
to fail. For an unboxed list an incorrect stack offset is generated
for the tail of the constructor.

An improved backend.dll for windows is available at:

http://www.cs.kun.nl/~clean/download/Clean21/windows/backend.zip

This dll is stored in the directory Tools/Clean System 2.1.0.

Or replace lines 3077-3079 in codegen2.c with:
									GenFillR (strict_cons_lab_p,a_size,b_size,*asp_p-update_node_id->nid_a_index,0,0,node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill,True);
								else
									GenFillh (node->node_arity==2 ? &cons_lab : strict_cons_lab_p,a_size,*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill);

and recompile the compiler, backend.dll or CleanCompilerLib, depending on
the platform.

>So I tested another example.
>
>prefx :: [#Real]
>prefx =: ... some filling, e.g. random numbers. No problemo Baby
>
>strm =: prefx ++| z
>  where z = 0.5 *> (strm + Tl strm)
>
>This time it works without complaining. So, scratching my head
>I replaced

Yes, because there is no contructor on a cycle.

>oscilu =: (z,v,r) where
> z =: [# 0.0 : v]
> v =: [# sin 0.01 : r]
> r =: (2.0*cos 0.01)*>v - z
>
>which generated the spine loop error message, by:
>
>oscilu =: (z,v,r) where
> z =: [# 0.0] ++| v
> v =: [# sin 0.01] ++| r
> r =: (2.0*cos 0.01)*>v - z
>
>i.e., I did thing which I tell my students *never to do*.
>And miracle happened, it works.

This works because [# 0.0] is no longer on a cycle.

>So, it seems that the pattern [# x : l] does something awful.
>But what, and who is to blame?

See my explanation above.

By the way, the oscil functions are now CAFs because you use =:, this will
probably introduce a space leak. And for better performance you may want
to define ZipWith as a macro:

ZipWith op l1 l2 :== ZipWith l1 l2
where
	ZipWith [|a:as] [|b:bs] = [|(op a b) : ZipWith as bs]
	ZipWith as bs		= [|]

Or instead enable fusion by passing :: -fusion as a compiler flag.

Regards,

John van Groningen