Sun May 2 12:33:37 EDT 2010

Compositional dataflow notation

The main problem scetched in the previous posts is the representation
of code right before it goes into the C code generator.  More

  * low-level machines have no "return <values>" statement, only
    assignment to shared/global resources (registers + memory).

  * embedding a DSL in haskell goes most smoothly if lambda
    abstractions and tuples are used for input and output

An impedance match is necessary here.  

The main problem in my current approach is that the `Function'
datastructure does not reflect this.  In fact the current "result = op
arg1 arg2" syntax for the SSA form hides this pattern.

So, what is the real problem?  Maybe the intermediate SSA form
construction needs to be built on top of a dataflow (multi in - multi
out) notation, such that at least dataflow networks can be composed:
i.e. composite networks can be added as primitives to a dataflow

Main principle: caller allocates storage space (provides variables).

When translating expression form (with or without let-sharing) to
explicit dataflow, nodes are created.

Question: how to combine data-flow composition (instantiation of code
over nodes) with expr->SSA conversion + common subexpression

What does `compileNodes' actually do?

*Term> :t compileNodes
  :: (Eq a) => [Term a] -> ([Term a], [(Term a1, Term a)])

It names intermediate nodes in a Term datastructure, reusing sharing
based on the `==' relation on the underlying type.

*Ai> compileNodes [(1 + var "a") * 2]
([r1],[(r0,(add 1 a)),(r1,(mul r0 2))])

It looks like this is the main place to start inserting external
nodes.  I.e. instead of having compileNodes return a list with
generated nodes that serve as a result (above this is [r1]) it might
be better to add binding there, or add some level of indirection which
decouples variable names and nodes.