059ba43c99482828c059de70e1943be972680bd5
[matthijs/master-project/report.git] / Chapters / Normalization.tex
1 \chapter{Normalization}
2
3 % A helper to print a single example in the half the page width. The example
4 % text should be in a buffer whose name is given in an argument.
5 %
6 % The align=right option really does left-alignment, but without the program
7 % will end up on a single line. The strut=no option prevents a bunch of empty
8 % space at the start of the frame.
9 \define[1]\example{
10   \framed[offset=1mm,align=right,strut=no]{
11     \setuptyping[option=LAM,style=sans,before=,after=]
12     \typebuffer[#1]
13     \setuptyping[option=none,style=\tttf]
14   }
15 }
16
17
18 % A transformation example
19 \definefloat[example][examples]
20 \setupcaption[example][location=top] % Put captions on top
21
22 \define[3]\transexample{
23   \placeexample[here]{#1}
24   \startcombination[2*1]
25     {\example{#2}}{Original program}
26     {\example{#3}}{Transformed program}
27   \stopcombination
28 }
29 %
30 %\define[3]\transexampleh{
31 %%  \placeexample[here]{#1}
32 %%  \startcombination[1*2]
33 %%    {\example{#2}}{Original program}
34 %%    {\example{#3}}{Transformed program}
35 %%  \stopcombination
36 %}
37
38 The first step in the core to VHDL translation process, is normalization. We
39 aim to bring the core description into a simpler form, which we can
40 subsequently translate into VHDL easily. This normal form is needed because
41 the full core language is more expressive than VHDL in some areas and because
42 core can describe expressions that do not have a direct hardware
43 interpretation.
44
45 TODO: Describe core properties not supported in VHDL, and describe how the
46 VHDL we want to generate should look like.
47
48 \section{Goal}
49 The transformations described here have a well-defined goal: To bring the
50 program in a well-defined form that is directly translatable to hardware,
51 while fully preserving the semantics of the program.
52
53 This {\em normal form} is again a Core program, but with a very specific
54 structure. A function in normal form has nested lambda's at the top, which
55 produce a let expression. This let expression binds every function application
56 in the function and produces a simple identifier. Every bound value in
57 the let expression is either a simple function application or a case
58 expression to extract a single element from a tuple returned by a
59 function.
60
61 An example of a program in canonical form would be:
62
63 \startlambda
64   -- All arguments are an inital lambda
65   λa.λd.λsp.
66   -- There are nested let expressions at top level
67   let
68     -- Unpack the state by coercion
69     s = sp :: (Word, Word)
70     -- Extract both registers from the state
71     r1 = case s of (fst, snd) -> fst
72     r2 = case s of (fst, snd) -> snd
73     -- Calling some other user-defined function.
74     d' = foo d
75     -- Conditional connections
76     out = case a of
77       High -> r1
78       Low -> r2
79     r1' = case a of
80       High -> d
81       Low -> r1
82     r2' = case a of
83       High -> r2
84       Low -> d
85     -- Packing a tuple
86     s' = (,) r1' r2'
87     -- Packing the state by coercion
88     sp' = s' :: State (Word, Word)
89     -- Pack our return value
90     res = (,) sp' out
91   in
92     -- The actual result
93     res
94 \stoplambda
95
96 \startlambda
97 \italic{normal} = \italic{lambda}
98 \italic{lambda} = λvar.\italic{lambda} (representable(typeof(var)))
99                 | \italic{toplet} 
100 \italic{toplet} = let \italic{binding} in \italic{toplet} 
101                 | letrec [\italic{binding}] in \italic{toplet}
102                 | var (representable(typeof(var)), fvar(var))
103 \italic{binding} = var = \italic{rhs} (representable(typeof(rhs)))
104                  -- State packing and unpacking by coercion
105                  | var0 = var1 :: State ty (fvar(var1))
106                  | var0 = var1 :: ty (var0 :: State ty) (fvar(var1))
107 \italic{rhs} = userapp
108              | builtinapp
109              -- Extractor case
110              | case var of C a0 ... an -> ai (fvar(var))
111              -- Selector case
112              | case var of (fvar(var))
113                 DEFAULT -> var0 (fvar(var0))
114                 C w0 ... wn -> resvar (\forall{}i, wi \neq resvar, fvar(resvar))
115 \italic{userapp} = \italic{userfunc}
116                  | \italic{userapp} {userarg}
117 \italic{userfunc} = var (tvar(var))
118 \italic{userarg} = var (fvar(var))
119 \italic{builtinapp} = \italic{builtinfunc}
120                     | \italic{builtinapp} \italic{builtinarg}
121 \italic{builtinfunc} = var (bvar(var))
122 \italic{builtinarg} = \italic{coreexpr}
123 \stoplambda
124
125 -- TODO: Define tvar, fvar, typeof, representable
126 -- TODO: Limit builtinarg further
127
128 -- TODO: There can still be other casts around (which the code can handle,
129 e.g., ignore), which still need to be documented here.
130
131 -- TODO: Note about the selector case. It just supports Bit and Bool
132 currently, perhaps it should be generalized in the normal form?
133
134 When looking at such a program from a hardware perspective, the top level
135 lambda's define the input ports. The value produced by the let expression is
136 the output port. Most function applications bound by the let expression
137 define a component instantiation, where the input and output ports are mapped
138 to local signals or arguments. Some of the others use a builtin
139 construction (\eg the \lam{case} statement) or call a builtin function
140 (\eg \lam{add} or \lam{sub}). For these, a hardcoded VHDL translation is
141 available.
142
143 \subsection{Normal definition}
144 Formally, the normal form is a core program obeying the following
145 constraints. TODO: Update this section, this is probably not completely
146 accurate or relevant anymore.
147
148 \startitemize[R,inmargin]
149 %\item All top level binds must have the form $\expr{\bind{fun}{lamexpr}}$.
150 %$fun$ is an identifier that will be bound as a global identifier.
151 %\item A $lamexpr$ has the form $\expr{\lam{arg}{lamexpr}}$ or
152 %$\expr{letexpr}$. $arg$ is an identifier which will be bound as an $argument$.
153 %\item[letexpr] A $letexpr$ has the form $\expr{\letexpr{letbinds}{retexpr}}$.
154 %\item $letbinds$ is a list with elements of the form
155 %$\expr{\bind{res}{appexpr}}$ or $\expr{\bind{res}{builtinexpr}}$, where $res$ is
156 %an identifier that will be bound as local identifier. The type of the bound
157 %value must be a $hardware\;type$.
158 %\item[builtinexpr] A $builtinexpr$ is an expression that can be mapped to an
159 %equivalent VHDL expression. Since there are many supported forms for this,
160 %these are defined in a separate table.
161 %\item An $appexpr$ has the form $\expr{fun}$ or $\expr{\app{appexpr}{x}}$,
162 %where $fun$ is a global identifier and $x$ is a local identifier.
163 %\item[retexpr] A $retexpr$ has the form $\expr{x}$ or $\expr{tupexpr}$, where $x$ is a local identifier that is bound as an $argument$ or $result$.  A $retexpr$ must
164 %be of a $hardware\;type$.
165 %\item A $tupexpr$ has the form $\expr{con}$ or $\expr{\app{tupexpr}{x}}$,
166 %where $con$ is a tuple constructor ({\em e.g.} $(,)$ or $(,,,)$) and $x$ is
167 %a local identifier.
168 %\item A $hardware\;type$ is a type that can be directly translated to
169 %hardware. This includes the types $Bit$, $SizedWord$, tuples containing
170 %elements of $hardware\;type$s, and will include others. This explicitely
171 %excludes function types.
172 \stopitemize
173
174 TODO: Say something about uniqueness of identifiers
175
176 \subsection{Builtin expressions}
177 A $builtinexpr$, as defined at \in[builtinexpr] can have any of the following forms.
178
179 \startitemize[m,inmargin]
180 %\item
181 %$tuple\_extract=\expr{\case{t}{\alt{\app{con}{x_0\;x_1\;..\;x_n}}{x_i}}}$,
182 %where $t$ can be any local identifier, $con$ is a tuple constructor ({\em
183 %e.g.} $(,)$ or $(,,,)$), $x_0$ to $x_n$ can be any identifier, and $x_i$ can
184 %be any of $x_0$ to $x_n$. A case expression must have a $hardware\;type$.
185 %\item TODO: Many more!
186 \stopitemize
187
188 \section{Transform passes}
189
190 In this section we describe the actual transforms. Here we're using
191 the core language in a notation that resembles lambda calculus.
192
193 Each of these transforms is meant to be applied to every (sub)expression
194 in a program, for as long as it applies. Only when none of the
195 expressions can be applied anymore, the program is in normal form. We
196 hope to be able to prove that this form will obey all of the constraints
197 defined above, but this has yet to happen (though it seems likely that
198 it will).
199
200 Each of the transforms will be described informally first, explaining
201 the need for and goal of the transform. Then, a formal definition is
202 given, using a familiar syntax from the world of logic. Each transform
203 is specified as a number of conditions (above the horizontal line) and a
204 number of conclusions (below the horizontal line). The details of using
205 this notation are still a bit fuzzy, so comments are welcom.
206
207 TODO: Formally describe the "apply to every (sub)expression" in terms of
208 rules with full transformations in the conditions.
209
210 \subsection{η-abstraction}
211 This transformation makes sure that all arguments of a function-typed
212 expression are named, by introducing lambda expressions. When combined with
213 β-reduction and function inlining below, all function-typed expressions should
214 be lambda abstractions or global identifiers.
215
216 \starttrans
217 E                 \lam{E :: * -> *}
218 --------------    \lam{E} is not the first argument of an application.
219 λx.E x            \lam{E} is not a lambda abstraction.
220                   \lam{x} is a variable that does not occur free in \lam{E}.
221 \stoptrans
222
223 \startbuffer[from]
224 foo = λa -> case a of 
225   True -> λb.mul b b
226   False -> id
227 \stopbuffer
228
229 \startbuffer[to]
230 foo = λa.λx -> (case a of 
231     True -> λb.mul b b
232     False -> λy.id y) x
233 \stopbuffer
234
235 \transexample{η-abstraction}{from}{to}
236
237 \subsection{Extended β-reduction}
238 This transformation is meant to propagate application expressions downwards
239 into expressions as far as possible. In lambda calculus, this reduction
240 is known as β-reduction, but it is of course only defined for
241 applications of lambda abstractions. We extend this reduction to also
242 work for the rest of core (case and let expressions).
243
244 For let expressions:
245 \starttrans
246 let binds in E) M
247 -----------------
248 let binds in E M
249 \stoptrans
250
251 For case statements:
252 \starttrans
253 (case x of
254   p1 -> E1
255   \vdots
256   pn -> En) M
257 -----------------
258 case x of
259   p1 -> E1 M
260   \vdots
261   pn -> En M
262 \stoptrans
263
264 For lambda expressions:
265 \starttrans
266 (λx.E) M
267 -----------------
268 E[M/x]
269 \stoptrans
270
271 % And an example
272 \startbuffer[from]
273 ( let a = (case x of 
274             True -> id
275             False -> neg
276           ) 1
277       b = (let y = 3 in add y) 2
278   in
279     (λz.add 1 z)
280 ) 3
281 \stopbuffer
282
283 \startbuffer[to]
284 let a = case x of 
285            True -> id 1
286            False -> neg 1
287     b = let y = 3 in add y 2
288 in
289   add 1 3
290 \stopbuffer
291
292 \transexample{Extended β-reduction}{from}{to}
293
294 \subsection{Let derecursification}
295 This transformation is meant to make lets non-recursive whenever possible.
296 This might allow other optimizations to do their work better. TODO: Why is
297 this needed exactly?
298
299 \subsection{Let flattening}
300 This transformation puts nested lets in the same scope, by lifting the
301 binding(s) of the inner let into a new let around the outer let. Eventually,
302 this will cause all let bindings to appear in the same scope (they will all be
303 in scope for the function return value).
304
305 Note that this transformation does not try to be smart when faced with
306 recursive lets, it will just leave the lets recursive (possibly joining a
307 recursive and non-recursive let into a single recursive let). The let
308 rederursification transformation will do this instead.
309
310 \starttrans
311 letnonrec x = (let bindings in M) in N
312 ------------------------------------------
313 let bindings in (letnonrec x = M) in N
314 \stoptrans
315
316 \starttrans
317 letrec 
318   \vdots
319   x = (let bindings in M)
320   \vdots
321 in
322   N
323 ------------------------------------------
324 letrec
325   \vdots
326   bindings
327   x = M
328   \vdots
329 in
330   N
331 \stoptrans
332
333 \startbuffer[from]
334 let
335   a = letrec
336     x = 1
337     y = 2
338   in
339     x + y
340 in
341   letrec
342     b = let c = 3 in a + c
343     d = 4
344   in
345     d + b
346 \stopbuffer
347 \startbuffer[to]
348 letrec
349   x = 1
350   y = 2
351 in
352   let
353     a = x + y
354   in
355     letrec
356       c = 3
357       b = a + c
358       d = 4
359     in
360       d + b
361 \stopbuffer
362
363 \transexample{Let flattening}{from}{to}
364
365 \subsection{Empty let removal}
366 This transformation is simple: It removes recursive lets that have no bindings
367 (which usually occurs when let derecursification removes the last binding from
368 it).
369
370 \starttrans
371 letrec in M
372 --------------
373 M
374 \stoptrans
375
376 \subsection{Simple let binding removal}
377 This transformation inlines simple let bindings (\eg a = b).
378
379 This transformation is not needed to get into normal form, but makes the
380 resulting VHDL a lot shorter.
381
382 \starttrans
383 letnonrec
384   a = b
385 in
386   M
387 -----------------
388 M[b/a]
389 \stoptrans
390
391 \starttrans
392 letrec
393   \vdots
394   a = b
395   \vdots
396 in
397   M
398 -----------------
399 let
400   \vdots
401   \vdots
402 in
403   M[b/a]
404 \stoptrans
405
406 \subsection{Unused let binding removal}
407 This transformation removes let bindings that are never used. Usually,
408 the desugarer introduces some unused let bindings.
409
410 This normalization pass should really be unneeded to get into normal form
411 (since ununsed bindings are not forbidden by the normal form), but in practice
412 the desugarer or simplifier emits some unused bindings that cannot be
413 normalized (e.g., calls to a \type{PatError} (TODO: Check this name)). Also,
414 this transformation makes the resulting VHDL a lot shorter.
415
416 \starttrans
417 let a = E in M
418 ----------------------------    \lam{a} does not occur free in \lam{M}
419 M
420 \stoptrans
421
422 \starttrans
423 letrec
424   \vdots
425   a = E
426   \vdots
427 in
428   M
429 ----------------------------    \lam{a} does not occur free in \lam{M}
430 letrec
431   \vdots
432   \vdots
433 in
434   M
435 \stoptrans
436
437 \subsection{Non-representable binding inlining}
438 This transform inlines let bindings of a funtion type. TODO: This should
439 be generelized to anything that is non representable at runtime, or
440 something like that.
441
442 \subsection{Scrutinee simplification}
443 This transform ensures that the scrutinee of a case expression is always
444 a simple variable reference.
445
446 \subsection{Case simplification}
447
448 \subsection{Case removal}
449 This transform removes any case statements with a single alternative and
450 only wild binders.
451
452 \subsection{Argument simplification}
453 The transforms in this section deal with simplifying application
454 arguments into normal form. The goal here is to:
455
456 \startitemize
457  \item Make all arguments of user-defined functions (\eg, of which
458  we have a function body) simple variable references of a runtime
459  representable type.
460  \item Make all arguments of builtin functions either:
461    \startitemize
462     \item A type argument.
463     \item A dictionary argument.
464     \item A type level expression.
465     \item A variable reference of a runtime representable type.
466     \item A variable reference or partial application of a function type.
467    \stopitemize
468 \stopitemize
469
470 When looking at the arguments of a user-defined function, we can
471 divide them into two categories:
472 \startitemize
473   \item Arguments with a runtime representable type (\eg bits or vectors).
474
475         These arguments can be preserved in the program, since they can
476         be translated to input ports later on.  However, since we can
477         only connect signals to input ports, these arguments must be
478         reduced to simple variables (for which signals will be
479         produced). This is taken care of by the argument extraction
480         transform.
481   \item Non-runtime representable typed arguments.
482         
483         These arguments cannot be preserved in the program, since we
484         cannot represent them as input or output ports in the resulting
485         VHDL. To remove them, we create a specialized version of the
486         called function with these arguments filled in. This is done by
487         the argument propagation transform.
488 \stopitemize
489
490 When looking at the arguments of a builtin function, we can divide them
491 into categories: 
492
493 \startitemize
494   \item Arguments with a runtime representable type.
495         
496         As we have seen with user-defined functions, these arguments can
497         always be reduced to a simple variable reference, by the
498         argument extraction transform. Performing this transform for
499         builtin functions as well, means that the translation of builtin
500         functions can be limited to signal references, instead of
501         needing to support all possible expressions.
502
503   \item Arguments with a function type.
504         
505         These arguments are functions passed to higher order builtins,
506         like \lam{map} and \lam{foldl}. Since implementing these
507         functions for arbitrary function-typed expressions (\eg, lambda
508         expressions) is rather comlex, we reduce these arguments to
509         (partial applications of) global functions.
510         
511         We can still support arbitrary expressions from the user code,
512         by creating a new global function containing that expression.
513         This way, we can simply replace the argument with a reference to
514         that new function. However, since the expression can contain any
515         number of free variables we also have to include partial
516         applications in our normal form.
517
518         This category of arguments is handled by the function extraction
519         transform.
520   \item Other unrepresentable arguments.
521         
522         These arguments can take a few different forms:
523         \startdesc{Type arguments}
524           In the core language, type arguments can only take a single
525           form: A type wrapped in the Type constructor. Also, there is
526           nothing that can be done with type expressions, except for
527           applying functions to them, so we can simply leave type
528           arguments as they are.
529         \stopdesc
530         \startdesc{Dictionary arguments}
531           In the core language, dictionary arguments are used to find
532           operations operating on one of the type arguments (mostly for
533           finding class methods). Since we will not actually evaluatie
534           the function body for builtin functions and can generate
535           code for builtin functions by just looking at the type
536           arguments, these arguments can be ignored and left as they
537           are.
538         \stopdesc
539         \startdesc{Type level arguments}
540           Sometimes, we want to pass a value to a builtin function, but
541           we need to know the value at compile time. Additionally, the
542           value has an impact on the type of the function. This is
543           encoded using type-level values, where the actual value of the
544           argument is not important, but the type encodes some integer,
545           for example. Since the value is not important, the actual form
546           of the expression does not matter either and we can leave
547           these arguments as they are.
548         \stopdesc
549         \startdesc{Other arguments}
550           Technically, there is still a wide array of arguments that can
551           be passed, but does not fall into any of the above categories.
552           However, none of the supported builtin functions requires such
553           an argument. This leaves use with passing unsupported types to
554           a function, such as calling \lam{head} on a list of functions.
555
556           In these cases, it would be impossible to generate hardware
557           for such a function call anyway, so we can ignore these
558           arguments.
559
560           The only way to generate hardware for builtin functions with
561           arguments like these, is to expand the function call into an
562           equivalent core expression (\eg, expand map into a series of
563           function applications). But for now, we choose to simply not
564           support expressions like these.
565         \stopdesc
566
567         From the above, we can conclude that we can simply ignore these
568         other unrepresentable arguments and focus on the first two
569         categories instead.
570 \stopitemize
571
572 \subsubsection{Argument extraction}
573 This transform deals with arguments to functions that
574 are of a runtime representable type. 
575
576 TODO: It seems we can map an expression to a port, not only a signal.
577 Perhaps this makes this transformation not needed?
578 TODO: Say something about dataconstructors (without arguments, like True
579 or False), which are variable references of a runtime representable
580 type, but do not result in a signal.
581
582 To reduce a complex expression to a simple variable reference, we create
583 a new let expression around the application, which binds the complex
584 expression to a new variable. The original function is then applied to
585 this variable.
586
587 %\transform{Argument extract}
588 %{
589 %\lam{Y} is of a hardware representable type
590 %
591 %\lam{Y} is not a variable referene
592 %
593 %\conclusion
594 %
595 %\trans{X Y}{let z = Y in X z}
596 %}
597
598 \subsubsection{Function extraction}
599 This transform deals with function-typed arguments to builtin functions.
600 Since these arguments cannot be propagated, we choose to extract them
601 into a new global function instead.
602
603 Any free variables occuring in the extracted arguments will become
604 parameters to the new global function. The original argument is replaced
605 with a reference to the new function, applied to any free variables from
606 the original argument.
607
608 %\transform{Function extraction}
609 %{
610 %\lam{X} is a (partial application of) a builtin function
611 %
612 %\lam{Y} is not an application
613 %
614 %\lam{Y} is not a variable reference
615 %
616 %\conclusion
617 %
618 %\lam{f0 ... fm} = free local vars of \lam{Y}
619 %
620 %\lam{y} is a new global variable
621 %
622 %\lam{y = λf0 ... fn.Y}
623 %
624 %\trans{X Y}{X (y f0 ... fn)}
625 %}
626
627 \subsubsection{Argument propagation}
628 This transform deals with arguments to user-defined functions that are
629 not representable at runtime. This means these arguments cannot be
630 preserved in the final form and most be {\em propagated}.
631
632 Propagation means to create a specialized version of the called
633 function, with the propagated argument already filled in. As a simple
634 example, in the following program:
635
636 \startlambda
637 f = λa.λb.a + b
638 inc = λa.f a 1
639 \stoplambda
640
641 we could {\em propagate} the constant argument 1, with the following
642 result:
643
644 \startlambda
645 f' = λa.a + 1
646 inc = λa.f' a
647 \stoplambda
648
649 Special care must be taken when the to-be-propagated expression has any
650 free variables. If this is the case, the original argument should not be
651 removed alltogether, but replaced by all the free variables of the
652 expression. In this way, the original expression can still be evaluated
653 inside the new function. Also, this brings us closer to our goal: All
654 these free variables will be simple variable references.
655
656 To prevent us from propagating the same argument over and over, a simple
657 local variable reference is not propagated (since is has exactly one
658 free variable, itself, we would only replace that argument with itself).
659
660 This shows that any free local variables that are not runtime representable
661 cannot be brought into normal form by this transform. We rely on an
662 inlining transformation to replace such a variable with an expression we
663 can propagate again.
664
665 TODO: Move these definitions somewhere sensible.
666
667 Definition: A global variable is any variable that is bound at the
668 top level of a program. A local variable is any other variable.
669
670 Definition: A hardware representable type is a type that we can generate
671 a signal for in hardware. For example, a bit, a vector of bits, a 32 bit
672 unsigned word, etc. Types that are not runtime representable notably
673 include (but are not limited to): Types, dictionaries, functions.
674
675 Definition: A builtin function is a function for which a builtin
676 hardware translation is available, because its actual definition is not
677 translatable. A user-defined function is any other function.
678
679 \starttrans
680 x = E
681 ~
682 x Y0 ... Yi ... Yn                               \lam{Yi} is not of a runtime representable type
683 ---------------------------------------------    \lam{Yi} is not a local variable reference
684 x' = λy0 ... yi-1 f0 ... fm yi+1 ... yn .        \lam{f0 ... fm} = free local vars of \lam{Y_i}
685       E y0 ... yi-1 Yi yi+1 ... yn   
686 ~
687 x' y0 ... yi-1 f0 ...  fm Yi+1 ... Yn
688 \stoptrans
689
690 \subsection{Cast propagation / simplification}
691 This transform pushes casts down into the expression as far as possible.
692
693 \subsection{Return value simplification}
694 Currently implemented using lambda simplification, let simplification, and
695 top simplification. Should change.
696
697 \subsection{Example sequence}
698
699 This section lists an example expression, with a sequence of transforms
700 applied to it. The exact transforms given here probably don't exactly
701 match the transforms given above anymore, but perhaps this can clarify
702 the big picture a bit.
703
704 TODO: Update or remove this section.
705
706 \startlambda
707   λx.
708     let s = foo x
709     in
710       case s of
711         (a, b) ->
712           case a of
713             High -> add
714             Low -> let
715               op' = case b of
716                 High -> sub
717                 Low  -> λc.λd.c
718               in
719                 λc.λd.op' d c
720 \stoplambda
721
722 After top-level η-abstraction:
723
724 \startlambda
725   λx.λc.λd.
726     (let s = foo x
727     in
728       case s of
729         (a, b) ->
730           case a of
731             High -> add
732             Low -> let
733               op' = case b of
734                 High -> sub
735                 Low  -> λc.λd.c
736               in
737                 λc.λd.op' d c
738     ) c d
739 \stoplambda
740
741 After (extended) β-reduction:
742
743 \startlambda
744   λx.λc.λd.
745     let s = foo x
746     in
747       case s of
748         (a, b) ->
749           case a of
750             High -> add c d
751             Low -> let
752               op' = case b of
753                 High -> sub
754                 Low  -> λc.λd.c
755               in
756                 op' d c
757 \stoplambda
758
759 After return value extraction:
760
761 \startlambda
762   λx.λc.λd.
763     let s = foo x
764         r = case s of
765               (a, b) ->
766                 case a of
767                   High -> add c d
768                   Low -> let
769                     op' = case b of
770                       High -> sub
771                       Low  -> λc.λd.c
772                     in
773                       op' d c
774     in
775       r
776 \stoplambda
777
778 Scrutinee simplification does not apply.
779
780 After case binder wildening:
781
782 \startlambda
783   λx.λc.λd.
784     let s = foo x
785         a = case s of (a, _) -> a
786         b = case s of (_, b) -> b
787         r = case s of (_, _) ->
788               case a of
789                 High -> add c d
790                 Low -> let op' = case b of
791                              High -> sub
792                              Low  -> λc.λd.c
793                        in
794                          op' d c
795     in
796       r
797 \stoplambda
798
799 After case value simplification
800
801 \startlambda
802   λx.λc.λd.
803     let s = foo x
804         a = case s of (a, _) -> a
805         b = case s of (_, b) -> b
806         r = case s of (_, _) -> r'
807         rh = add c d
808         rl = let rll = λc.λd.c
809                  op' = case b of
810                    High -> sub
811                    Low  -> rll
812              in
813                op' d c
814         r' = case a of
815                High -> rh
816                Low -> rl
817     in
818       r
819 \stoplambda
820
821 After let flattening:
822
823 \startlambda
824   λx.λc.λd.
825     let s = foo x
826         a = case s of (a, _) -> a
827         b = case s of (_, b) -> b
828         r = case s of (_, _) -> r'
829         rh = add c d
830         rl = op' d c
831         rll = λc.λd.c
832         op' = case b of
833           High -> sub
834           Low  -> rll
835         r' = case a of
836                High -> rh
837                Low -> rl
838     in
839       r
840 \stoplambda
841
842 After function inlining:
843
844 \startlambda
845   λx.λc.λd.
846     let s = foo x
847         a = case s of (a, _) -> a
848         b = case s of (_, b) -> b
849         r = case s of (_, _) -> r'
850         rh = add c d
851         rl = (case b of
852           High -> sub
853           Low  -> λc.λd.c) d c
854         r' = case a of
855           High -> rh
856           Low -> rl
857     in
858       r
859 \stoplambda
860
861 After (extended) β-reduction again:
862
863 \startlambda
864   λx.λc.λd.
865     let s = foo x
866         a = case s of (a, _) -> a
867         b = case s of (_, b) -> b
868         r = case s of (_, _) -> r'
869         rh = add c d
870         rl = case b of
871           High -> sub d c
872           Low  -> d
873         r' = case a of
874           High -> rh
875           Low -> rl
876     in
877       r
878 \stoplambda
879
880 After case value simplification again:
881
882 \startlambda
883   λx.λc.λd.
884     let s = foo x
885         a = case s of (a, _) -> a
886         b = case s of (_, b) -> b
887         r = case s of (_, _) -> r'
888         rh = add c d
889         rlh = sub d c
890         rl = case b of
891           High -> rlh
892           Low  -> d
893         r' = case a of
894           High -> rh
895           Low -> rl
896     in
897       r
898 \stoplambda
899
900 After case removal:
901
902 \startlambda
903   λx.λc.λd.
904     let s = foo x
905         a = case s of (a, _) -> a
906         b = case s of (_, b) -> b
907         r = r'
908         rh = add c d
909         rlh = sub d c
910         rl = case b of
911           High -> rlh
912           Low  -> d
913         r' = case a of
914           High -> rh
915           Low -> rl
916     in
917       r
918 \stoplambda
919
920 After let bind removal:
921
922 \startlambda
923   λx.λc.λd.
924     let s = foo x
925         a = case s of (a, _) -> a
926         b = case s of (_, b) -> b
927         rh = add c d
928         rlh = sub d c
929         rl = case b of
930           High -> rlh
931           Low  -> d
932         r' = case a of
933           High -> rh
934           Low -> rl
935     in
936       r'
937 \stoplambda
938
939 Application simplification is not applicable.