Thu Jan 17 00:30:05 CET 2013
siso abstraction in Scheme
When sticking to a pure functional representation, code generation is
straightforward: it is just SSA eval. The real problem is
manipulation of state and metadata such as inputs/outputs, and
construction of composition operators such that state machines can be
chained without manual state manips.
COMPOSITION IS THE KEY!
In Haskell, the cool part here was the use of '.'
What I really want however is a way to use ordinary `let' forms to
connect the inputs and outputs of state machines, but have the state
be handled separately.
(define op (i1 i2 ...) (o1 o2 ...)
(let ((x (big-stateful-filter i1)))
What I really want is something like Haskell arrow 'proc' notation.
How to distill the basic "state multiplication" approach used in dspm?
The problem seems to be that state size is type information, so it's
probably best to look at this problem at expansion time. The main
problem is the "inference" of the state type.
Using arrows it's simple, because arrow notation orders the
compositions, such that we only need to implement binary composition
operations. Does it make sense to do something similar for Scheme?
Conclusion: using an arrow approach might be a good idea: it reuses a
standard pattern, and allows composition to be limited to binary
( A nasty question: what's the advantage over using straight up OO
stateful approach? Lexically this approach here uses less code: all
constructors are inferred from the body of the code, and all state
updates can be done behind the scenes. The whole class/instance
distinction disappears from view. )
To make this work in Scheme, some information needs to be attached to
compile-time representation in order to expand
(let* (... (x (fn y)) ...) ...)
(lambda ((... si ...) in)
(let-values* (... ((so x) (fn si y)) ...) ...)
(values (... so ...) out))
This doesn't seem like a big deal really. Because the let* form is
linear, all state variables appear in order. This might give a huge
benefit for cache management since all references are predictable.
For a real application, state memory will probably dominate necessary
intermediate storage.. Also it might even make it possible to split
loops to trade off between state size and intermediate coupling size.
Next: how to attach I/O size to a name at compile time?