From b9aea3fab982db87302a9202e38cd439a194ec60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hillerstr=C3=B6m?= Date: Mon, 3 Aug 2020 01:50:23 +0100 Subject: [PATCH] Tidy up HO translation. --- thesis.tex | 189 +++++++++++++++++++++++------------------------------ 1 file changed, 82 insertions(+), 107 deletions(-) diff --git a/thesis.tex b/thesis.tex index 1438642..a51feac 100644 --- a/thesis.tex +++ b/thesis.tex @@ -860,8 +860,9 @@ given term. The function computes the set of free variables bottom-up. Most cases are homomorphic on the syntax constructors. The interesting cases are those constructs which feature term binders: lambda abstraction, let -bindings, pair destructing, and case splitting. In each of those cases -we subtract the relevant binder(s) from the set of free variables. +bindings, pair deconstructing, and case splitting. In each of those +cases we subtract the relevant binder(s) from the set of free +variables. \subsection{Typing rules} \label{sec:base-language-type-rules} @@ -1007,7 +1008,7 @@ application $V\,A$ is well-typed whenever the abstractor term $V$ has the polymorphic type $\forall \alpha^K.C$ and the type $A$ has kind $K$. This rule makes use of type substitution. % -The \tylab{Split} rule handles typing of record destructing. When +The \tylab{Split} rule handles typing of record deconstructing. When splitting a record term $V$ on some label $\ell$ binding it to $x$ and the remainder to $y$. The label we wish to split on must be present with some type $A$, hence we require that @@ -1566,9 +1567,9 @@ effect handlers which are an alternative to deep effect handlers. % Programming with effect handlers is a dichotomy of \emph{performing} and \emph{handling} of effectful operations -- or alternatively a -dichotomy of \emph{constructing} and \emph{destructing}. An operation +dichotomy of \emph{constructing} and \emph{deconstructing}. An operation is a constructor of an effect without a predefined semantics. A -handler destructs effects by pattern-matching on their operations. By +handler deconstructs effects by pattern-matching on their operations. By matching on a particular operation, a handler instantiates the said operation with a particular semantics of its own choosing. The key ingredient to make this work in practice is \emph{delimited @@ -2534,28 +2535,12 @@ operation clauses extract and convert the current resumption stack into a function using the $\Res$, and $\hforward$ augments the current resumption stack with the current continuation pair. % -% Since we have only changed the representation of resumptions, the -% translation of top-level programs remains the same. \subsection{Higher-order translation for deep effect handlers} \label{sec:higher-order-uncurried-deep-handlers-cps} % \begin{figure} % -% \textbf{Static patterns and static lists} -% % -% \begin{syntax} -% \slab{Static patterns} &\sP& ::= & \sk \scons \sP \mid \sks \\ -% \slab{Static lists} &\VS& ::= & V \scons \VS \mid \reflect V \\ -% \end{syntax} -% % -% \textbf{Reification} -% % -% \begin{equations} -% \reify (V \scons \VS) &\defas& V \dcons \reify \VS \\ -% \reify \reflect V &\defas& V \\ -% \end{equations} -% \textbf{Values} % \begin{displaymath} @@ -2594,19 +2579,6 @@ resumption stack with the current continuation pair. \cps{-} &:& \HandlerCat \to \UCompCat\\ \cps{\{\Return \; x \mapsto N\}} &\defas& \dlam x\, ks.\Let\; (h \dcons ks') = ks \;\In\; \cps{N} \sapp \reflect ks' \\ -% \cps{\{(\ell \; p \; r \mapsto N_\ell)_{\ell \in \mathcal{L}}\}} -% &\defas& -% \bl -% \dlam z \, ks.\Case \;z\; \{ -% \bl -% (\ell~\Record{p, s} \mapsto \dLet\;r=\Fun\,s \;\dIn\; \cps{N_{\ell}} \sapp \reflect ks)_{\ell \in \mathcal{L}};\, -% y \mapsto \hforward \} \\ -% \el \\ -% \el \\ -% \hforward &\defas& \bl -% \dLet\; (k' \dcons h' \dcons ks') = ks \;\dIn\; \\ -% \Vmap\,(\dlam\Record{p, s}\,(k \dcons ks).k\,\Record{p, h' \dcons k' \dcons s}\,ks)\,y\,(h' \dcons ks') \\ -% \el\\ \cps{\{(\ell \; p \; r \mapsto N_\ell)_{\ell \in \mathcal{L}}\}} &\defas& \bl \dlam \Record{z,\Record{p,rs}}\,ks.\Case \;z\; \{ @@ -2666,15 +2638,6 @@ alternating lists of pure continuation functions and effect continuation functions. To ease notation we are going make use of pattern matching notation. The static meta language is generated by the following productions. -% Static constructs are marked in -% {\color{blue}$\overline{\text{static blue}}$}, and their redexes are -% reduced as part of the translation (at compile time). We make use of -% static lambda abstractions, pairs, and lists. Reflection of dynamic -% language values into the static language is written as $\reflect V$. -% % -% We use $\shk$ for variables representing statically known -% continuations (frame stacks), $\shf$ for variables representing pure -% frame stacks, and $\chi$ for variables representing handlers. % \begin{syntax} \slab{Static patterns} &\sP \in \SPatCat &::=& \sks \mid \sk \scons \sP\\ @@ -2682,8 +2645,8 @@ the following productions. \slab{Static computations} & \sM \in \SCompCat &::=& \sV \sapp \sW \mid \sV \dapp V \dapp W \end{syntax} % -The patterns comprise only static list destructing. We let $\sP$ range -over static patterns. +The patterns comprise only static list deconstructing. We let $\sP$ +range over static patterns. % The static values comprise dynamic values, reflected dynamic values, static lists, and static lambda abstractions. We let $\sV, \sW$ range @@ -2706,8 +2669,8 @@ Static computations are subject to the following equational axioms. The first equation is static $\beta$-equivalence, it states that applying a static lambda abstraction with binder $\sks$ and body $\sM$ to a static value $\sV$ is equal to substituting $\sV$ for $\sks$ in -$\sM$. The second equation allows us to apply a static list -component-wise. +$\sM$. The second equation provides a means for applying a static +lambda abstraction to a static list component-wise. % \dhil{What about $\eta$-equivalence?} @@ -2720,32 +2683,38 @@ $\reify \sV$ by induction on their structure. &\reify (\sV \scons \sW) \defas \reify \sV \dcons \reify \sW \ea \] - - +% +\dhil{Need to spell out that static pattern matching may induce dynamic (administrative) reductions} +% \paragraph{Higher-order translation} -The CPS translation is given in -Figure~\ref{fig:cps-higher-order-uncurried}. In essence, it is the -same as the CPS translation for deep and shallow handlers we described -in Section~\ref{sec:pure-as-stack}, albeit separated into static and -dynamic parts. A major difference that has a large cosmetic effect on -the presentation of the translation is that we maintain the invariant -that the statically known stack ($\sk$) always contains at least one -frame, consisting of a triple -$\sRecord{\reflect V_{fs}, \sRecord{\reflect V_{ret}, \reflect - V_{ops}}}$ of reflected dynamic pure frame stacks, return -handlers, and operation handlers. Maintaining this invariant ensures -that all translations are uniform in whether they appear statically -within the scope of a handler or not, and this simplifies our -correctness proof. To maintain the invariant, any place where a -dynamically known stack is passed in (as a continuation parameter -$k$), it is immediately decomposed using a dynamic language $\Let$ and -repackaged as a static value with reflected variable -names. Unfortunately, this does add some clutter to the translation -definition, as compared to the translations above. However, there is a -payoff in the removal of administrative reductions at run time. -% -\dhil{Rewrite the above.} % +The complete CPS translation is given in +Figure~\ref{fig:cps-higher-order-uncurried}. In essence, it is the +same as the refined first-order uncurried CPS translation, although +the notation is slightly more involved due to the separation of static +and dynamic parts. +% +The translation on values is mostly homomorphic on the syntax +constructors, except for $\lambda$- and $\Lambda$-abstractions which +are translated in the exact same way, because the target calculus has +no notion of types. As per usual continuation passing style practice, +the translation of a lambda abstraction yields a dynamic binary lambda +abstraction, where the second parameter is intended to be the +continuation parameter. However, the translation slightly diverge from +the usual practice in the translation of the body as the result of +$\cps{M}$ is applied statically, rather than dynamically, to the +(reflected) continuation parameter. +% +The reason is that the translation on computations is staged: for any +given computation term the translation yields a static function, which +can be applied to a static continuation to ultimately produce a +$\UCalc$-computation term. This staging is key to eliminating static +administrative redexes as any static function may perform static +computation by manipulating its provided static continuation, as is +for instance done in the translation of $\Let$. +% +\dhil{Spell out why this translation qualifies as `higher-order'.} + Let us again revisit the example from Section~\ref{sec:first-order-curried-cps} to see that the higher-order translation eliminates the static redex at translation time. @@ -2758,15 +2727,19 @@ translation eliminates the static redex at translation time. \end{equations} % In contrast with the previous translations, the image of this -translation admits only a single dynamic reduction. +translation admits only a single dynamic reduction (disregarding the +dynamic administrative reductions arising from continuation +construction and deconstruction). \subsubsection{Correctness} \label{sec:higher-order-cps-deep-handlers-correctness} -In order to prove the correctness of the higher-order uncurried CPS -translation (Theorem~\ref{thm:ho-simulation}), we first state several -auxiliary lemmas describing how translated terms behave. First, the -higher-order CPS translation commutes with substitution. +We establish the correctness of the higher-order uncurried CPS +translation via a simulation result in style of +Plotkin~\cite{Plotkin75} (Theorem~\ref{thm:ho-simulation}). However, +before we can state and prove this result, we first several auxiliary +lemmas describing how translated terms behave. First, the higher-order +CPS translation commutes with substitution. % \begin{lemma}[Substitution]\label{lem:ho-cps-subst} % @@ -2811,8 +2784,8 @@ It follows as a corollary that top-level substitution is well-behaved. Lemma~\ref{lem:ho-cps-subst}. \end{proof} % -In order to reason about the behaviour of the \semlab{Op} rule, -which is defined in terms of an evaluation context, we extend the CPS +In order to reason about the behaviour \semlab{Op} rule, which is +defined in terms of an evaluation context, we need to extend the CPS translation to evaluation contexts. % \begin{equations} @@ -2825,8 +2798,9 @@ translation to evaluation contexts. The following lemma is the characteristic property of the CPS translation on evaluation contexts. % -This allows us to focus on the computation contained within -an evaluation context. +It provides a means for decomposing an evaluation context, such that +we can focus on the computation contained within the evaluation +context. % \begin{lemma}[Decomposition] \label{lem:decomposition} @@ -2841,26 +2815,27 @@ an evaluation context. Proof by structural induction on the evaluation context $\EC$. \end{proof} % -Though we have eliminated the static administrative redexes, we are -still left with one form of administrative redex that cannot be -eliminated statically because it only appears at run-time. These arise -from pattern matching against a reified stack of continuations and are -given by the $\usemlab{SplitList}$ rule. +Even though we have eliminated the static administrative redexes, we +still need to account for the dynamic administrative redexes that +arise from pattern matching against a reified continuation. To +properly account for these administrative redexes it is convenient to +treat list pattern matching as a primitive in $\UCalc$, therefore we +introduce a new reduction rule $\usemlab{SplitList}$ in $\UCalc$. % \begin{reductions} \usemlab{SplitList} & \Let\; (k \dcons ks) = V \dcons W \;\In\; M &\reducesto& M[V/k, W/ks] \\ \end{reductions} % -This is isomorphic to the \usemlab{Split} rule, but we now treat lists -and \usemlab{SplitList} as distinct from pairs, unit, and -\usemlab{Split} in the higher-order translation so that we can -properly account for administrative reduction. +Note this rule is isomorphic to the \usemlab{Split} rule with lists +encoded as right nested pairs using unit to denote nil. % We write $\areducesto$ for the compatible closure of \usemlab{SplitList}. -By definition, $\reify \reflect V = V$, but we also need to reason -about the inverse composition. +We also need to be able to reason about the computational content of +reflection after reification. By definition we have that +$\reify \reflect V = V$, the following lemma lets us reason about the +inverse composition. % \begin{lemma}[Reflect after reify] \label{lem:reflect-after-reify} @@ -2917,10 +2892,10 @@ Follows from Lemmas~\ref{lem:decomposition}, \ref{lem:reflect-after-reify}, and \ref{lem:forwarding}. \end{proof} % -We now turn to our main result which is a simulation result in style -of Plotkin~\cite{Plotkin75}. The theorem shows that the only extra -behaviour exhibited by a translated term is the bureaucracy of -deconstructing the continuation stack. +Finally, we have the ingredients to state and prove the simulation +result. The following theorem shows that the only extra behaviour +exhibited by a translated term is the bureaucracy of deconstructing +the continuation stack. % \begin{theorem}[Simulation] \label{thm:ho-simulation} @@ -2933,18 +2908,18 @@ If $M \reducesto N$ then $\pcps{M} \reducesto^+ \areducesto^* \pcps{N}$. follows from Lemma~\ref{lem:handle-op}. \end{proof} % -In common with most CPS translations, full abstraction does not -hold. However, as our semantics is deterministic it is straightforward -to show a backward simulation result. -% -\begin{corollary}[Backwards simulation] -If $\pcps{M} \reducesto^+ \areducesto^* V$ then there exists $W$ such that -$M \reducesto^* W$ and $\pcps{W} = V$. -\end{corollary} -% -\begin{proof} - TODO\dots -\end{proof} +% In common with most CPS translations, full abstraction does not +% hold. However, as our semantics is deterministic it is straightforward +% to show a backward simulation result. +% % +% \begin{corollary}[Backwards simulation] +% If $\pcps{M} \reducesto^+ \areducesto^* V$ then there exists $W$ such that +% $M \reducesto^* W$ and $\pcps{W} = V$. +% \end{corollary} +% % +% \begin{proof} +% TODO\dots +% \end{proof} % \chapter{Abstract machine semantics}