1
0
mirror of https://github.com/dhil/phd-dissertation synced 2026-03-13 02:58:26 +00:00

Parameterised semantics

This commit is contained in:
2021-02-04 15:04:41 +00:00
parent 86269f6de2
commit 9fdcf19ee5

View File

@@ -7498,7 +7498,10 @@ being handled. Semantically, parameterised handlers are defined as
folds with state threading over computation trees. folds with state threading over computation trees.
We take the deep handler calculus $\HCalc$ as our starting point and We take the deep handler calculus $\HCalc$ as our starting point and
extend it with parameterised handlers to yield the calculus $\HPCalc$. extend it with parameterised handlers to yield the calculus
$\HPCalc$. The parameterised handler extension interacts nicely with
shallow handlers, and as such it can be added to $\SCalc$ with low
effort.
\subsection{Syntax and static semantics} \subsection{Syntax and static semantics}
In addition to a computation, a parameterised handler also take a In addition to a computation, a parameterised handler also take a
@@ -7506,21 +7509,31 @@ value as argument. This argument is the initial value of the state
cell embedded inside the handler. cell embedded inside the handler.
% %
\begin{syntax} \begin{syntax}
\slab{Handler\textrm{ }types} & F &::=& \cdots \mid \Record{C; A} \Rightarrow^\param D\\ \slab{Handler\textrm{ }types} & F &::=& \cdots \mid \Record{C; A} \Rightarrow^\param D\\
\slab{Computations} & M,N &::=& \cdots \mid \ParamHandle\; M \;\With\; H^\param(W)\\ \slab{Computations} & M,N &::=& \cdots \mid \ParamHandle\; M \;\With\; H^\param(W)\\
\slab{Parameterised\textrm{ }definitions} & H^\param &::=& q^A.~H \slab{Parameterised\textrm{ }definitions} & H^\param &::=& q^A.~H
\end{syntax} \end{syntax}
% %
Figure~\ref{fig:param-syntax} extends the syntax of The syntactic category of handler types $F$ is extended with a new
$\HCalc$ with parameterised handlers. Syntactically a parameterised kind of handler arrow for parameterised handlers. The left hand side
handler is new binding form $(q^A.~H)$, where $q$ is the name of the of the arrow is a pair, whose first component denotes the type of the
parameter, whose type is $A$. The name is bound in the ordinary input computation and the second component denotes the type of the
handler definition $H$. The elimination form handler parameter. The right hand side denotes the return type of the
($\ParamHandle\; M\;\With\;H^\param(W)$) is similar to the form for handler.
ordinary deep handlers, except that the parameterised handler %
definition is applied to a value $W$, which is the initial value of The computations category is extended with a new application form for
the parameter $q$. handlers, which runs a computation $M$ under a parameterised handler
$H$ applied to the value $W$.
%
Finally, a new category is added for parameterised handler
definitions. A parameterised handler definition is a new binding form
$(q^A.~H)$, where $q$ is the name of the parameter, whose type is $A$,
and $H$ is an ordinary handler definition $H$. The parameter $q$ is
accessible in the $\Return$ and operation clauses of $H$.
As with ordinary deep handlers and shallow handlers, there are two
typing rules: one for handler application and another for handler
definitions.
% %
\begin{mathpar} \begin{mathpar}
% Handle % Handle
@@ -7532,7 +7545,18 @@ the parameter $q$.
\typ{\Gamma}{H^\param : \Record{C; A} \Harrow^\param D} \typ{\Gamma}{H^\param : \Record{C; A} \Harrow^\param D}
} }
{\Gamma \vdash \ParamHandle \; M \; \With\; H^\param(W) : D} {\Gamma \vdash \ParamHandle \; M \; \With\; H^\param(W) : D}
\end{mathpar}
%
The $\tylab{Handle^\param}$ rule is similar to the $\tylab{Handle}$
and $\tylab{Handle^\dagger}$ rules, except that it has to account for
the parameter $W$, whose type has to be compatible with the second
component of the domain type of the handler definition $H^\param$.
%
The typing rule for parameterised handler definitions adapts the
corresponding typing rule $\tylab{Handler}$ for ordinary deep handlers
with the addition of a parameter.
%
\begin{mathpar}
% Parameterised handler % Parameterised handler
\inferrule*[Lab=\tylab{Handler^\param}] \inferrule*[Lab=\tylab{Handler^\param}]
{{\bl {{\bl
@@ -7546,54 +7570,63 @@ the parameter $q$.
{\typ{\Delta;\Gamma}{(q^{A'} . H) : \Record{C;A'} \Harrow^\param D}} {\typ{\Delta;\Gamma}{(q^{A'} . H) : \Record{C;A'} \Harrow^\param D}}
\end{mathpar} \end{mathpar}
%% %%
We require two additional rules to type parameterised handlers. The The key differences between the \tylab{Handler} and
rules are given in Figure~\ref{fig:param-static-semantics}. The main \tylab{Handler^\param} rules are that in the latter the return and
differences between the \tylab{Handler} and \tylab{Handler^\param} are operation cases are typed with respect to the parameter $q$, and that
that in the latter the return and operation cases are typed with resumptions $r_i$ have type $\Record{B_\ell;A'} \to D$, that is a
respect to the parameter $q$, and that resumptions $r$ have type parameterised resumption is a binary function, where the first
$\Record{B_\ell;A'} \to D$, that is they accept a pair as argument is the interpretation of an operation and the second argument
input. is the (updated) handler state. The return type of $r_i$ is the same
as the return type of the handler, meaning that an invocation of $r_i$
is guarded in the same way as an invocation of an ordinary deep
resumption.
\subsection{Dynamic semantics} \subsection{Dynamic semantics}
Operationally, a parameterised resumption uses the first component as The two reduction rules for parameterised handlers adapt the reduction
the return value of the operation, and the second component as the rules for ordinary deep handlers with a parameter.
updated value of the handler parameter $q$.
% %
This operational behaviour is formalised by following reduction rule \begin{reductions}
$\semlab{Op^\param}$. \semlab{Ret^\param} &
\ParamHandle \; (\Return \; V) \; \With \; (q.H)(W) &\reducesto& N[V/x,W/q],\\
\multicolumn{4}{@{}r@{}}{
\hfill\text{where } \hret = \{ \Return \; x \mapsto N \}} \\
\semlab{Op^\param} &
\ParamHandle \; \EC[\Do \; \ell \, V] \; \With \; (q.H)(W)
&\reducesto& N[V/p,W/q,R/r],\\
\multicolumn{4}{@{}r@{}}{
\hfill\ba[t]{@{~}r@{~}l}
\text{where}& R = \lambda\Record{y;q'}.\ParamHandle\;\EC[\Return \; y]\;\With\;(q.H)(q')\\
\text{and} &\hell = \{ \OpCase{\ell}{p}{r} \mapsto N \}\\
\text{and} &\ell \notin \BL(\EC)
\ea
}
\end{reductions}
% %
\[ The rule $\semlab{Ret^\param}$ handles the return value of a
\ba{@{~}l@{~}l} computation. Just like the rule $\semlab{Ret}$ the return value $V$ is
&\ParamHandle \; \EC[\Do \; \ell \; V] \; \With \; (q.~H)(W)\\ substituted for the binder $x$ in the return case body
\reducesto& $N$. Furthermore the value $W$ is substituted for the handler
N[V/p,W/q,\lambda \Record{y;q'}.\Handle \; \EC[\Return \; y] \; \With \; (q.~H)(q')/r]\\ parameter $q$ in $N$, meaning the handler parameter is accessible in
& \text{ where } \ell \notin BL(\EC) \text{ and } \hell = \{ \OpCase{\ell}{p}{r} \mapsto N \} the return case.
\ea
\] The $\semlab{Op^\param}$ handles an operation invocation. Both the
% operation payload $V$ and handler argument $W$ are accessible inside
The parameter value $W$ is substituted for the parameter name $q$ into the case body $N$. As with ordinary deep handlers, the resumption
the operation case body $N$. As with ordinary deep handlers, the rewraps its handler, but with the slight twist that the parameterised
resumption rewraps its handler, but with the slight twist that the handler definition is applied to the updated parameter value $q'$
parameterised handler definition is applied to the updated parameter rather than the original value $W$. This achieves the effect of state
value $q'$ rather than the original value $W$. The reduction rule for passing as the value of $q'$ becomes available upon the next
handling the return of a computation is as follows. activation of the handler.
%
\[
\ParamHandle \, (\Return \; V) \; \With \; (q.~H)(W) \reducesto N[V/x,W/q], \text{where } \hret = \{ \Return \; x \mapsto N \}
\]
%
Both the return value $V$ and the parameter value $W$ are substituted
into the return case body $N$ for their respective binders.
\subsection{Process synchronisation} \subsection{Process synchronisation}
\[ \[
\Co \defas \{\UFork : \UnitType \opto \Int; \Wait : \Int \opto \UnitType; \Interrupt : \UnitType \opto \UnitType;\} \Co \defas \{\UFork : \UnitType \opto \Int; \Wait : \Int \opto \UnitType; \Interrupt : \UnitType \opto \UnitType\}
\] \]
\[ \[
\ba{@{~}l@{~}l@{~}c@{~}l} \ba{@{~}l@{~}l@{~}c@{~}l}
\Proc &\alpha~\varepsilon &\defas& \Sstate \to \alpha \eff \varepsilon\\ \Proc &\alpha~\varepsilon &\defas& \Sstate \to \List~\alpha \eff \varepsilon\\
\Pstate &\alpha~\varepsilon &\defas& [\Ready:\Proc~\alpha~\varepsilon;\Blocked:\Record{\Int;\Proc~\alpha~\varepsilon}]\\ \Pstate &\alpha~\varepsilon &\defas& [\Ready:\Proc~\alpha~\varepsilon;\Blocked:\Record{\Int;\Proc~\alpha~\varepsilon}]\\
\Sstate &\alpha~\varepsilon &\defas& \Record{q:\List\,\Record{\Int;\Pstate~\alpha~\varepsilon};done:\List~\alpha;pid:\Int;pnext:\Int}\\ \Sstate &\alpha~\varepsilon &\defas& \Record{q:\List\,\Record{\Int;\Pstate~\alpha~\varepsilon};done:\List~\alpha;pid:\Int;pnext:\Int}\\
\ea \ea
@@ -7642,12 +7675,6 @@ into the return case body $N$ for their respective binders.
\Let\;st' \revto \Record{st\;\With\;q = q'; pnext = pid + 1}\;\In\\ \Let\;st' \revto \Record{st\;\With\;q = q'; pnext = pid + 1}\;\In\\
resume\,\Record{pid;st'} resume\,\Record{pid;st'}
\el\\ \el\\
\OpCase{\Interrupt}{\Unit}{resume} \mapsto\\
\quad\bl
\Let\;resume' \revto \lambda st.resume\,\Record{\Unit;st}\;\In\\
\Let\;q' \revto st.q \concat [\Record{st.pid;\Ready~resume'}]\;\In\\
\runNext~\Record{st \;\With\; q = q'}
\el\\
\OpCase{\Wait}{pid}{resume} \mapsto\\ \OpCase{\Wait}{pid}{resume} \mapsto\\
\quad\bl \quad\bl
\Let\;resume' \revto \lambda st.resume~\Record{\Unit;st}\;\In\\ \Let\;resume' \revto \lambda st.resume~\Record{\Unit;st}\;\In\\
@@ -7658,12 +7685,19 @@ into the return case body $N$ for their respective binders.
\Else\;st.q \concat [\Record{st.pid;\Ready~resume'}] \Else\;st.q \concat [\Record{st.pid;\Ready~resume'}]
\el\\ \el\\
\In\;\runNext\,\Record{st\;\With\;q = q'} \In\;\runNext\,\Record{st\;\With\;q = q'}
\el\\
\OpCase{\Interrupt}{\Unit}{resume} \mapsto\\
\quad\bl
\Let\;resume' \revto \lambda st.resume\,\Record{\Unit;st}\;\In\\
\Let\;q' \revto st.q \concat [\Record{st.pid;\Ready~resume'}]\;\In\\
\runNext~\Record{st \;\With\; q = q'}
\el \el
\el \el
\el \el
\el \el
\] \]
%
%
\[ \[
\bl \bl
\timesharee : (\UnitType \to \alpha \eff \Co) \to \List~\alpha\\ \timesharee : (\UnitType \to \alpha \eff \Co) \to \List~\alpha\\
@@ -7674,7 +7708,21 @@ into the return case body $N$ for their respective binders.
\el \el
\el \el
\] \]
%
%
\[
\bl
\init : (\Unit \to \alpha \eff \varepsilon) \to \alpha \eff \{\Co;\Exit : \Int \opto \ZeroType;\varepsilon\}\\
\init~main \defas
\bl
\Let\;pid \revto \Do\;\UFork~\Unit\;\In\\
\If\;pid = 0\\
\Then\;main\,\Unit\\
\Else\;\Do\;\Wait~pid; \exit~1
\el
\el
\]
%
% %
\[ \[
\ba{@{~}l@{~}l} \ba{@{~}l@{~}l}
@@ -7708,10 +7756,10 @@ into the return case body $N$ for their respective binders.
\ba[t]{@{}l} \ba[t]{@{}l}
\Record{0; \Record{0;
\ba[t]{@{}l@{}l} \ba[t]{@{}l@{}l}
\texttt{"}&\texttt{UNIX is basically a simple operating system, but }\\ \texttt{"}&\texttt{To be, or not to be,\nl{}that is the question:\nl{}}\\
&\texttt{you have to be a genius to understand the simplicity.\nl}\\ &\texttt{Whether 'tis nobler in the mind to suffer\nl{}}\\
&\texttt{To be, or not to be,\nl{}that is the question:\nl{}}\\ &\texttt{UNIX is basically a simple operating system, but }\\
&\texttt{Whether 'tis nobler in the mind to suffer\nl{}"}}]; &\texttt{you have to be a genius to understand the simplicity.\nl"}}];
\ea\\ \ea\\
lnext=1; inext=1}}\\ lnext=1; inext=1}}\\
\ea \ea