--- /dev/null
+Language Design
+===============
+A central question is, what do we want our language to look like? Deciding to
+use haskell would be a first step, but that still leaves a lot of
+possibilities. However, why would we want to use Haskell?
+
+ * Lots of existing support: Language specification, compilers, libraries,
+ userbase. All of this reduces the workload to implement something.
+ * All of Haskell is usable in simulation / testing: When not compiling to
+ VHDL, but when doing functional tests, we can use all of Haskell's syntax,
+ libraries, functions, etc. even when we don't support all of it in our
+ compiler.
+ * Haskell is probably expressive enough to be able to express a lot of
+ different things and different approaches. By defining new (algebraic)
+ types and operators, we can extend this even further. Finally, we could
+ even use Template Haskell to do almost anything (The ForSyDe project uses
+ Template Haskell extensively).
+
+Typing
+------
+What kind of types will we be using in our programs? The base type should be
+some kind of bit type, but there are two main options for these:
+
+ * Use a single bit as a type. Calculations on these types represent the
+ calculations in a single time slice (ie, during one clock cycle). Any
+ state in the calculation is explicit, since the input state must be a
+ function argument and the output state part of the function's value.
+
+ Through the state values, these functions are closely tied to the clock
+ domain in use (or whatever other model is used for the time domain). Ie,
+ having different clock domains is non-trivial and will require
+ modification to the function.
+
+ Composition can be done by simply connection functions together. This does
+ require that the "state" of a function contains the states of each of the
+ function it calls. These are extracted from its state argument and passed
+ on to the callees, while the states returned are again inserted into the
+ resulting state of the outer function.
+
+ This approach is the closest to normal functional programming and shows
+ state very explicitly.
+
+ * Use a stream of bits as a type. Each value models a continuous (infinite)
+ stream of bits. Functions have streams as arguments and value and state
+ could probably be implicit in the calculation or could be made explicit
+ using delay elements (this is what Lava does).
+
+ The primitive operations all operate on streams, which seems the
+ fundamental difference between this and the previous approach.
+
+ This approach shows structure more explicitly when delay elements are
+ used, since the registers end up exactly there.
+
+It is probably possible to mix these approaches. In particular, the first
+approache eventually needs to do some I/O, which can be modeled as recursion
+over an infinite list of inputs resulting in an infinite list of outputs. This
+can be done at the top level always, but it is perhaps possible to move this
+recursion a bit downward and do composition based on stream functions instead
+of "single clock" functions. One problem that comes to mind is that one needs
+to guarantee that a function does not look into the future (ie, uses multiple
+input elements to generate one output element) and the state becomes a lot
+less explicit. This needs more thought.
+
+Implementation
+==============
+Assume we will want to translate a (subset of) haskell into something else.
+We will need to do parsing, typechecking, interpretation, etc. A few options
+for this are available:
+
+ * Doing everything manually, possibly using a parser generator.
+ Lot's of work. Requires us to write down the haskell grammar, create a
+ parser, do all kinds of funky type checking -> Too much work.
+ * Use the Language.Haskell library and write something in haskell. This
+ library contains a Lexer, Parser and AST, but still does not do any type
+ checking, desugaring and simplification. Still lots of work.
+ * Hack into an existing compiler. By writing a backend for an existing
+ compiler, we can save most of the haskell-specific work. This requires a
+ compiler that is modular enough to have its backend replaced by another
+ implementation. Also, the border between backend and frontend must be
+ suited for the work we would like to do. This approach would use the
+ original compiler's driver for the most part
+ * Use components from an existing compiler. By reusing selected components
+ and creating an own driver that uses these components, we can work with
+ the haskell source without doing all the work ourselves. This requires a
+ compiler that is very modular, so we can decide exactly which parts we
+ would like to use and which we don't need.
+
+After some looking around it seems GHC provides a consistent and (as of
+version 6.10) documented API into its internals This allows us to write
+
+ core <- compileToCoreSimplified "adder.hs"
+
+to compile the file `adder.hs` into a version in GHC's simplified CoreSyn
+representation. This is essentially an AST with type annotations, all
+syntactic sugar removed, redundant expressions simplified, etc. This seems to
+be a very useful form to work with. However, GHC provides other functions to
+access other parts of the compiler, so if we would like to access the source
+at another stage, or do some custom procesing in between, this is also
+possible (albeit a bit more complex than this).
+
+Problems
+--------
+Some problems encountered or expected when trying to do some initial
+translator hackup:
+
+ * Signal naming. In the generated VHDL the signals and ports need names.
+ These can of course be generated, but if we want to do some actual
+ debugging, we want useful signal names. For input ports generated from
+ function arguments, the binder name could perhaps be used, but that is not
+ always possible when patterns are more complex.
+
+ For output ports, a name could be deduced when the output value is always
+ computed in a where or let clause. However the simplification phase
+ removes these clauses where possible, so this information is lost.
+
+ Perhaps some way of explicitely labeling ports could be used.
+ * Type classes and universal qualification types are a powerful way of
+ making functions generic, which greatly increases their reusability.
+ However, this extra genericity makes the resulting Core representation
+ more complex. Since the actual types used are modeled as extra function
+ arguments, this shouldn't be too hard, but this is something that probably
+ needs implementation right away (because a lot of builtin haskell
+ constructs, such as tuples, use it).
+
+<!-- vim: set sw=2 sts=2 ts=8: -->