have a direct hardware interpretation.
\section{Normal form}
- The transformations described here have a well-defined goal: To bring the
+ The transformations described here have a well-defined goal: to bring the
program in a well-defined form that is directly translatable to
\VHDL, while fully preserving the semantics of the program. We refer
to this form as the \emph{normal form} of the program. The formal
EBNF-like description captures most of the intended structure (and
generates a subset of \GHC's core format).
- There are two things missing: Cast expressions are sometimes
+ There are two things missing: cast expressions are sometimes
allowed by the prototype, but not specified here and the below
definition allows uses of state that cannot be translated to \VHDL\
properly. These two problems are discussed in
The type of this expression is \lam{Word}, so it does not match \lam{a -> b}
and the transformation does not apply. Next, we have two options for the
- next expression to look at: The function position and argument position of
+ next expression to look at: the function position and argument position of
the application. The expression in the argument position is \lam{b}, which
has type \lam{Word}, so the transformation does not apply. The expression in
the function position is:
function position (which makes the second condition false). In the same
way the transformation does not apply to both components of this
expression (\lam{case opcode of Low -> (+); High -> (-)} and \lam{a}), so
- we will skip to the components of the case expression: The scrutinee and
+ we will skip to the components of the case expression: the scrutinee and
both alternatives. Since the opcode is not a function, it does not apply
here.
A \emph{hardware representable} (or just \emph{representable}) type or value
is (a value of) a type that we can generate a signal for in hardware. For
example, a bit, a vector of bits, a 32 bit unsigned word, etc. Values that are
- not runtime representable notably include (but are not limited to): Types,
+ not runtime representable notably include (but are not limited to): types,
dictionaries, functions.
\defref{representable}
\stoplambda
This is obviously not what was supposed to happen! The root of this problem is
- the reuse of binders: Identical binders can be bound in different,
+ the reuse of binders: identical binders can be bound in different,
but overlapping scopes. Any variable reference in those
overlapping scopes then refers to the variable bound in the inner
(smallest) scope. There is not way to refer to the variable in the
outer scope. This effect is usually referred to as
- \emph{shadowing}: When a binder is bound in a scope where the
+ \emph{shadowing}: when a binder is bound in a scope where the
binder already had a value, the inner binding is said to
\emph{shadow} the outer binding. In the example above, the \lam{c}
binder was bound outside of the expression and in the inner lambda
\transexample{unusedlet}{Unused let binding removal}{from}{to}
\subsubsection{Empty let removal}
- This transformation is simple: It removes recursive lets that have no bindings
+ This transformation is simple: it removes recursive lets that have no bindings
(which usually occurs when unused let binding removal removes the last
binding from it).
This transformation makes all non-recursive lets recursive. In the
end, we want a single recursive let in our normalized program, so all
non-recursive lets can be converted. This also makes other
- transformations simpler: They only need to be specified for recursive
+ transformations simpler: they only need to be specified for recursive
let expressions (and simply will not apply to non-recursive let
expressions until this transformation has been applied).
values used in our expression representable. There are two main
transformations that are applied to \emph{all} unrepresentable let
bindings and function arguments. These are meant to address three
- different kinds of unrepresentable values: Polymorphic values,
+ different kinds of unrepresentable values: polymorphic values,
higher-order values and literals. The transformation are described
- generically: They apply to all non-representable values. However,
+ generically: they apply to all non-representable values. However,
non-representable values that do not fall into one of these three
categories will be moved around by these transformations but are
unlikely to completely disappear. They usually mean the program was not
take care of exactly this.
There is one case where polymorphism cannot be completely
- removed: Built-in functions are still allowed to be polymorphic
+ removed: built-in functions are still allowed to be polymorphic
(Since we have no function body that we could properly
specialize). However, the code that generates \VHDL\ for built-in
functions knows how to handle this, so this is not a problem.
\hs{Bool} Haskell type, which is just an enumerated type.
There is, however, a second type of literal that does not have a
- representable type: Integer literals. Cλash supports using integer
+ representable type: integer literals. Cλash supports using integer
literals for all three integer types supported (\hs{SizedWord},
\hs{SizedInt} and \hs{RangedWord}). This is implemented using
Haskell's \hs{Num} type class, which offers a \hs{fromInteger} method
in y + z
\stoplambda
- Looking at this, we could imagine an alternative approach: Create a
+ Looking at this, we could imagine an alternative approach: create a
transformation that removes let bindings that bind identical values.
In the above expression, the \lam{y} and \lam{z} variables could be
merged together, resulting in the more efficient expression:
expanding some expression.
\item[q:soundness] Is our system \emph{sound}? Since our transformations
continuously modify the expression, there is an obvious risk that the final
- normal form will not be equivalent to the original program: Its meaning could
+ normal form will not be equivalent to the original program: its meaning could
have changed.
\item[q:completeness] Is our system \emph{complete}? Since we have a complex
system of transformations, there is an obvious risk that some expressions will
not end up in our intended normal form, because we forgot some transformation.
- In other words: Does our transformation system result in our intended normal
+ In other words: does our transformation system result in our intended normal
form for all possible inputs?
\item[q:determinism] Is our system \emph{deterministic}? Since we have defined
no particular order in which the transformation should be applied, there is an
\emph{different} normal forms. They might still both be intended normal forms
(if our system is \emph{complete}) and describe correct hardware (if our
system is \emph{sound}), so this property is less important than the previous
- three: The translator would still function properly without it.
+ three: the translator would still function properly without it.
\stopitemize
Unfortunately, the final transformation system has only been
Since each of the transformations can be applied to any
subexpression as well, there is a constraint on our meaning
- definition: The meaning of an expression should depend only on the
+ definition: the meaning of an expression should depend only on the
meaning of subexpressions, not on the expressions themselves. For
example, the meaning of the application in \lam{f (let x = 4 in
x)} should be the same as the meaning of the application in \lam{f
Fortunately, we can also prove the complement (which is
equivalent, since $A \subseteq B \Leftrightarrow \overline{B}
- \subseteq \overline{A}$): Show that the set of nodes not in
+ \subseteq \overline{A}$): show that the set of nodes not in
intended normal form is a subset of the set of nodes not in normal
form. In other words, show that for every expression that is not
in intended normal form, that there is at least one transformation