Skip to content
Snippets Groups Projects
Commit 6676a195 authored by Ralf Jung's avatar Ralf Jung
Browse files

document HeapLang syntax and operational semantics

parent 56e9d264
No related branches found
No related tags found
No related merge requests found
......@@ -107,8 +107,6 @@ Inductive expr :=
| InjL (e : expr)
| InjR (e : expr)
| Case (e0 : expr) (e1 : expr) (e2 : expr)
(* Concurrency *)
| Fork (e : expr)
(* Heap *)
| AllocN (e1 e2 : expr) (* array length (positive number), initial value *)
| Free (e : expr)
......@@ -117,6 +115,8 @@ Inductive expr :=
| CmpXchg (e0 : expr) (e1 : expr) (e2 : expr) (* Compare-exchange *)
| Xchg (e0 : expr) (e1 : expr) (* exchange *)
| FAA (e1 : expr) (e2 : expr) (* Fetch-and-add *)
(* Concurrency *)
| Fork (e : expr)
(* Prophecy *)
| NewProph
| Resolve (e0 : expr) (e1 : expr) (e2 : expr) (* wrapped expr, proph, val *)
......@@ -243,7 +243,6 @@ Proof.
| InjR e, InjR e' => cast_if (decide (e = e'))
| Case e0 e1 e2, Case e0' e1' e2' =>
cast_if_and3 (decide (e0 = e0')) (decide (e1 = e1')) (decide (e2 = e2'))
| Fork e, Fork e' => cast_if (decide (e = e'))
| AllocN e1 e2, AllocN e1' e2' =>
cast_if_and (decide (e1 = e1')) (decide (e2 = e2'))
| Free e, Free e' =>
......@@ -257,6 +256,7 @@ Proof.
cast_if_and (decide (e0 = e0')) (decide (e1 = e1'))
| FAA e1 e2, FAA e1' e2' =>
cast_if_and (decide (e1 = e1')) (decide (e2 = e2'))
| Fork e, Fork e' => cast_if (decide (e = e'))
| NewProph, NewProph => left _
| Resolve e0 e1 e2, Resolve e0' e1' e2' =>
cast_if_and3 (decide (e0 = e0')) (decide (e1 = e1')) (decide (e2 = e2'))
......@@ -410,6 +410,11 @@ Canonical Structure valO := leibnizO val.
Canonical Structure exprO := leibnizO expr.
(** Evaluation contexts *)
(** Note that [ResolveLCtx] is not by itself an evaluation context item: we do
not reduce directly under Resolve's first argument. We only reduce things nested
further down. Once no nested contexts exist any more, the expression must take
exactly one more step to a value, and Resolve then (atomically) also uses that
value for prophecy resolution. *)
Inductive ectx_item :=
| AppLCtx (v2 : val)
| AppRCtx (e1 : expr)
......@@ -498,7 +503,6 @@ Fixpoint subst (x : string) (v : val) (e : expr) : expr :=
| InjL e => InjL (subst x v e)
| InjR e => InjR (subst x v e)
| Case e0 e1 e2 => Case (subst x v e0) (subst x v e1) (subst x v e2)
| Fork e => Fork (subst x v e)
| AllocN e1 e2 => AllocN (subst x v e1) (subst x v e2)
| Free e => Free (subst x v e)
| Load e => Load (subst x v e)
......@@ -506,6 +510,7 @@ Fixpoint subst (x : string) (v : val) (e : expr) : expr :=
| Store e1 e2 => Store (subst x v e1) (subst x v e2)
| CmpXchg e0 e1 e2 => CmpXchg (subst x v e0) (subst x v e1) (subst x v e2)
| FAA e1 e2 => FAA (subst x v e1) (subst x v e2)
| Fork e => Fork (subst x v e)
| NewProph => NewProph
| Resolve ex e1 e2 => Resolve (subst x v ex) (subst x v e1) (subst x v e2)
end.
......@@ -661,8 +666,6 @@ Inductive head_step : expr → state → list observation → expr → state →
head_step (Case (Val $ InjLV v) e1 e2) σ [] (App e1 (Val v)) σ []
| CaseRS v e1 e2 σ :
head_step (Case (Val $ InjRV v) e1 e2) σ [] (App e2 (Val v)) σ []
| ForkS e σ:
head_step (Fork e) σ [] (Val $ LitV LitUnit) σ [e]
| AllocNS n v σ l :
(0 < n)%Z
( i, (0 i)%Z (i < n)%Z σ.(heap) !! (l + i) = None)
......@@ -707,6 +710,8 @@ Inductive head_step : expr → state → list observation → expr → state →
[]
(Val $ LitV $ LitInt i1) (state_upd_heap <[l:=Some $ LitV (LitInt (i1 + i2))]>σ)
[]
| ForkS e σ:
head_step (Fork e) σ [] (Val $ LitV LitUnit) σ [e]
| NewProphS σ p :
p σ.(used_proph_id)
head_step NewProph σ
......
......@@ -749,15 +749,15 @@ Section interpret_ok.
(repeat case_match; subst; try errored;
success;
eauto using state_wf_upd).
- constructor; intros.
simpl.
apply state_wf_holds; auto.
- match goal with
| H: interp_alloc _ _ = (_, _) |- _ => invc H
end.
apply state_wf_init_alloc; eauto.
lia.
- apply state_wf_same_dom; eauto.
- constructor; intros.
simpl.
apply state_wf_holds; auto.
Qed.
Local Hint Resolve interpret_wf : core.
......@@ -792,13 +792,6 @@ Section interpret_ok.
lazymatch goal with
| |- context[Case (Val ?v)] => destruct v; try errored; step_atomic; eauto
end.
- (* Fork *)
eapply rtc_once. exists [].
lazymatch goal with
| |- context[Fork ?e] => eapply (step_atomic _ _ _ _ [e] []); simpl; eauto
end.
apply head_prim_step; simpl.
eauto using head_step.
- (* AllocN *)
lazymatch goal with
| H: interp_alloc _ _ = _ |- _ => invc H
......@@ -806,6 +799,13 @@ Section interpret_ok.
eapply atomic_step. constructor; auto; intros.
simpl. apply state_wf_holds; eauto.
simpl; lia.
- (* Fork *)
eapply rtc_once. exists [].
lazymatch goal with
| |- context[Fork ?e] => eapply (step_atomic _ _ _ _ [e] []); simpl; eauto
end.
apply head_prim_step; simpl.
eauto using head_step.
Qed.
(** * Theory for expressions that are stuck after some execution steps. *)
......
......@@ -3849,3 +3849,20 @@ year = {2013}
volume = {20},
year = {1955}
}
@article{iris:prophecy,
author = {Ralf Jung and
Rodolphe Lepigre and
Gaurav Parthasarathy and
Marianna Rapoport and
Amin Timany and
Derek Dreyer and
Bart Jacobs},
title = {The future is ours: prophecy variables in separation logic},
journal = {{PACMPL}},
volume = {4},
number = {{POPL}},
doi = {10.1145/3371113},
pages = {45:1--45:32},
year = {2020}
}
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\ProvidesPackage{heaplang}
\RequirePackage{marvosym}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% CONCRETE LANGUAGE SYNTAX AND SEMANTICS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\textlang}[1]{\texttt{#1}}
\newcommand{\ProphId}{\textdom{ProphId}}
\newcommand{\langkw}[1]{\textlang{\bfseries #1}}
\newcommand{\langv}[1]{\ensuremath{\mathit{#1}}} % Yes, this makes language-level variables look like logic-level variables. but we still distinguish locally bound variables from global definitions.
\newcommand{\lvar}{\langv{\var}}
\newcommand{\lvarB}{\langv{\varB}}
\newcommand{\lvarC}{\langv{\varC}}
\newcommand{\lvarF}{\langv{f}}
\newcommand{\loc}{\ell}
\newcommand{\prophid}{p}
\newcommand{\stateHeap}{\textproj{heap}}
\newcommand{\stateProphs}{\textproj{prophs}}
\newcommand\exprForm{{\langkw{e}}}
\newcommand\valForm{{\langkw{v}}}
\def\Let#1=#2in{\langkw{let} \spac #1 \mathrel{=} #2 \spac \langkw{in} \spac}
\def\If#1then{\langkw{if} \spac #1 \spac \langkw{then} \spac}
\def\Else{\spac\langkw{else} \spac}
\def\Ref(#1){\langkw{ref}(#1)}
\def\Rec#1(#2)={\langkw{rec}\spac{#1}({#2}) \mathrel{=} }
\def\RecE#1(#2)={\langkw{rec}_\exprForm\spac{#1}({#2}) \mathrel{=} }
\def\RecV#1(#2)={\langkw{rec}_\valForm\spac{#1}({#2}) \mathrel{=} }
\def\Skip{\langkw{skip}}
\def\Assert{\langkw{assert}}
\def\Inl{\langkw{inl}}
\def\Inr{\langkw{inr}}
\def\Fst{\langkw{fst}}
\def\Snd{\langkw{snd}}
\def\True{\langkw{true}}
\def\False{\langkw{false}}
\def\NewProph{\langkw{newproph}}
\def\ResolveWith#1at#2to#3{\langkw{resolve}\spac\langkw{with}\spac#1\spac\langkw{at}\spac#2\spac\langkw{to}\spac#3}
\def\Resolve#1to#2{\langkw{resolve}\spac#1\spac\langkw{to}\spac#2}
\def\MatchCore#1with#2|#3end{\langkw{match}\spac#1\spac\langkw{with}\spac#2\mid#3\spac\langkw{end}}
\def\Match#1with#2=>#3|#4=>#5end{\langkw{match}\spac#1\spac\langkw{with}\spac#2\Ra#3\mid#4\Ra#5\spac\langkw{end}}
\def\MatchML#1with#2=>#3|#4=>#5end#6{{\arraycolsep=1.4pt\begin{array}[t]{rll}%
\multicolumn{3}{l}{\langkw{match}\spac#1\spac\langkw{with}}\\%
&#2&\Ra#3\\|&#4&\Ra#5\\%
\multicolumn{3}{l}{\langkw{end}#6}%
\end{array}}}
\def\MatchMLL#1with#2=>#3|#4=>#5|#6=>#7end#8{{\arraycolsep=1.4pt\begin{array}[t]{rll}%
\multicolumn{3}{l}{\langkw{match}\spac#1\spac\langkw{with}}\\%
&#2&\Ra#3\\|&#4&\Ra#5\\|&#6&\Ra#7\\%
\multicolumn{3}{l}{\langkw{end}#8}%
\end{array}}}
\def\MatchS#1with#2=>#3end{
\langkw{match}\spac#1\spac\langkw{with}\spac#2\Ra#3\spac\langkw{end}}
\newcommand\Alloc{\langkw{Alloc}}
\newcommand\Free{\langkw{Free}}
\newcommand\CAS{\langkw{CAS}}
\newcommand\CmpXchg{\langkw{CmpXchg}}
\newcommand\Xchg{\langkw{Xchg}}
\newcommand\FAA{\langkw{FAA}}
\newcommand\deref{\mathop{!}}
\let\gets\leftarrow
\newcommand*\Fork[1]{\langkw{fork}\spac\set{#1}}
\newcommand{\fold}{\langkw{fold}\spac}
\newcommand{\unfold}{\langkw{unfold}\spac}
\newcommand{\HLOp}{\circledcirc}
\newcommand{\Ptradd}{\mathop{+_{\langkw{l}}}}
\newcommand{\TT}{()}
\newcommand*\poison{\text{\Biohazard}}
\newcommand\valeq{\cong}
\newcommand\valne{\ncong}
\newcommand\litCompareSafe{\textlog{lit\_compare\_safe}}
\newcommand\valCompareSafe{\textlog{val\_compare\_safe}}
\section{HeapLang}
\label{sec:heaplang}
So far, we have treated the programming language we work on entirely generically.
In this section we present the default language that ships with Iris, HeapLang.
HeapLang is an ML-like languages with a higher-order heap, unstructured concurrency, some common atomic operations, and prophecy variables.
It is an instance of the language interface (\Sref{sec:language}), so we only define a per-thread small-step operational semantics---the thread-pool semantics are given in in \Sref{sec:language:concurrent}.
\subsection{HeapLang syntax and operational semantics}
The grammar of HeapLang, and in particular its set \Expr{} of \emph{expressions} and \Val{} of \emph{values}, is defined as follows:
\begin{align*}
\val,\valB \in \Val \bnfdef{}&
z \mid
\True \mid \False \mid
\TT \mid
\poison \mid
\loc \mid
\prophid \mid {}& (z \in \integer, \loc \in \Loc, \prophid \in \ProphId) \\&
\RecV\lvarF(\lvar)= \expr \mid
(\val,\valB)_\valForm \mid
\Inl(\val)_\valForm \mid
\Inr(\val)_\valForm \\
\expr \in \Expr \bnfdef{}&
\val \mid
\lvar \mid
\RecE\lvarF(\lvar)= \expr \mid
\expr_1(\expr_2) \mid
{}\\ &
\HLOp_1 \expr \mid
\expr_1 \HLOp_2 \expr_2 \mid
\If \expr then \expr_1 \Else \expr_2 \mid
{}\\ &
(\expr_1,\expr_2)_\exprForm \mid
\Fst(\expr) \mid
\Snd(\expr) \mid
{}\\ &
\Inl(\expr)_\exprForm \mid
\Inr(\expr)_\exprForm \mid
\MatchCore \expr with \expr_1 | \expr_2 end \mid
{}\\ &
\Alloc(\expr_1,\expr_2) \mid
\Free(\expr) \mid
\deref \expr \mid
\expr_1 \gets \expr_2 \mid
\CmpXchg(\expr_1, \expr_2, \expr_3) \mid
\Xchg(\expr_1, \expr_2) \mid
\FAA(\expr_1, \expr_2) \mid
\kern-30ex{}\\ &
\Fork \expr \mid
\NewProph \mid
\ResolveWith \expr_1 at \expr_2 to \expr_3 \\
\HLOp_1 \bnfdef{}& - \mid \ldots ~~\text{(list incomplete)} \\
\HLOp_2 \bnfdef{}& + \mid - \mid \Ptradd \mid \mathop{=} \mid \ldots ~~\text{(list incomplete)}
\end{align*}
(Note that \langkw{match} contains a literal $|$ that is not part of the BNF but part of HeapLang syntax.)
Recursive abstractions, pairs, and the injections exist both as a value form and an expression form.
The expression forms will reduce to the value form once all their arguments are values.
Conceptually, one can think of that as corresponding to ``boxing'' that most functional language implementations do.
We will leave away the disambiguating subscript when it is clear from the context or does not matter.
All of this lets us define $\ofval$ as simply applying the value injection (the very first syntactic form of $\Expr$), which makes a lot of things in Coq much simpler.
$\toval$ is defined recursively in the obvious way.
For our set of states and observations, we pick
\begin{align*}
\loc \ni \Loc \eqdef{}& \integer \\
\prophid \ni \ProphId \eqdef{}& \integer \\
\sigma \ni \State \eqdef{}& \record{\begin{aligned}
\stateHeap:{}& \Loc \fpfn \Val,\\
\stateProphs:{}& \pset{\ProphId}
\end{aligned}} \\
\obs \ni \Obs \eqdef{}& \ProphId \times (\Val \times \Val)
\end{align*}
The HeapLang operational semantics is defined via the use of \emph{evaluation contexts}:
\begin{align*}
\lctx \in \Lctx \bnfdef{}&
\bullet \mid \Lctx_{>} \\
\lctx_{>} \in \Lctx_{>} \bnfdef{}&
\expr(\lctx) \mid
\lctx (\val) \mid
{}\\ &
\HLOp_1 \lctx \mid
\expr \HLOp_2 \lctx \mid
\lctx \HLOp_2 \val \mid
\If \lctx then \expr_1 \Else \expr_2 \mid
{}\\ &
(\expr, \lctx) \mid
(\lctx, \val) \mid
\Fst(\lctx) \mid
\Snd(\lctx) \mid
{}\\ &
\Inl(\lctx) \mid
\Inr(\lctx) \mid
\MatchCore \lctx with \expr_1 | \expr_2 end \mid
{}\\ &
\Alloc(\expr, \lctx) \mid
\Alloc(\lctx, \val) \mid
\Free(\lctx) \mid
\deref \lctx \mid
\expr \gets \lctx \mid
\lctx \gets \val \mid
{}\\ &
\CmpXchg(\expr_1, \expr_2, \lctx) \mid
\CmpXchg(\expr_1, \lctx, \val_3) \mid
\CmpXchg(\lctx, \val_2, \val_3) \mid
{}\\ &
\Xchg(\expr, \lctx) \mid
\Xchg(\lctx, \val) \mid
\FAA(\expr, \lctx) \mid
\FAA(\lctx, \val) \mid
{}\\ &
\ResolveWith \expr_1 at \expr_2 to \lctx \mid
\ResolveWith \expr_1 at \lctx to \val_3 \mid
{}\\ &
\ResolveWith \lctx_{>} at \val_2 to \val_3
\end{align*}
Note that we use right-to-left evaluation order.
This means in a curried function call $f(x)(y)$, we know syntactically the arguments will all evaluate before $f$ gets to do anything, which makes specifying curried calls a lot easier.
The \langkw{resolve} evaluation context for the leftmost expression (the nested expression that executes atomically together with the prophecy resolution) is special: it must not be empty; only further nested evaluation contexts are allowed.
\langkw{resolve} takes care of reducing the expression once the nested contexts are taken care of, and at that point it requires the expression to reduce to a value in exactly one step.
Hence we define $\Lctx_{>}$ for non-empty evaluation contexts.
For more details on prophecy variables, see \cite{iris:prophecy}.
This lets us define the primitive reduction relation in terms of a ``head step'' reduction; see \figref{fig:heaplang-reduction-pure} and \figref{fig:heaplang-reduction-impure}.
Comparison (both for $\CmpXchg$ and the binary comparison operator) is a bit tricky and uses a helper judgment (\figref{fig:heaplang-valeq}).
Basically, two values can only be compared if at least one of them is ``compare-safe''.
Compare-safe values are basic literals (integers, Booleans, locations, unit) as well as $\Inl$ and $\Inr$ of those literals.
The intention of this is to forbid directly comparing large values such as pairs, which could not be done in a single atomic step on a real machine.
\begin{figure}[p]
\judgment[Per-thread reduction]{\expr_1, \state_1 \step [\vec\obs] \expr_2, \state_2, \vec\expr}
\begin{mathpar}
\infer
{\expr_1, \state_1 \hstep [\vec\obs] \expr_2, \state_2, \vec\expr}
{\fillctx\lctx[\expr_1], \state_1 \step[\vec\obs] \fillctx\lctx[\expr_2], \state_2, \vec\expr}
\end{mathpar}
\judgment[``Head'' reduction (pure)]{\expr_1, \state_1 \hstep [\vec\obs] \expr_2, \state_2, \vec\expr}
\newcommand\alignheader{\kern-30ex}
\begin{align*}
&\alignheader\textbf{``Boxing'' reductions} \\
(\RecE\lvarF(\lvar)= \expr, \state) \hstep[\nil]{}&
(\RecV\lvarF(\lvar)= \expr, \state, \nil) \\
((\val_1, \val_2)_\exprForm, \state) \hstep[\nil]{}&
((\val_1, \val_2)_\valForm, \state, \nil) \\
(\Inl(\val)_\exprForm, \state) \hstep[\nil]{}&
(\Inl(\val)_\valForm, \state, \nil) \\
(\Inr(\val)_\exprForm, \state) \hstep[\nil]{}&
(\Inr(\val)_\valForm, \state, \nil) \\
&\alignheader\textbf{Pure reductions} \\
((\RecV\lvarF(\lvar)= \expr)(\val), \state) \hstep[\nil]{}&
(\subst {\subst \expr \lvarF {(\Rec\lvarF(\lvar)= \expr)}} \lvar \val, \state, \nil) \\
(-_{\HLOp} z, \state) \hstep[\nil]{}&
(-z, \state, \nil) \\
(z_1 +_{\HLOp} z_2, \state) \hstep[\nil]{}&
(z_1 + z_2, \state, \nil) \\
(z_1 -_{\HLOp} z_2, \state) \hstep[\nil]{}&
(z_1 - z_2, \state, \nil) \\
(\loc \Ptradd z, \state) \hstep[\nil]{}&
(\loc + z, \state, \nil) \\
(\val_1 =_{\HLOp} \val_2, \state) \hstep[\nil]{}&
(\True, \state, \nil)
&&\text{if $\val_1 \valeq \val_2$} \\
(\val_1 =_{\HLOp} \val_2, \state) \hstep[\nil]{}&
(\False, \state, \nil)
&&\text{if $\val_1 \valne \val_2$} \\
(\If \True then \expr_1 \Else \expr_2, \state) \hstep[\nil]{}&
(\expr_1, \state, \nil) \\
(\If \False then \expr_1 \Else \expr_2, \state) \hstep[\nil]{}&
(\expr_2, \state, \nil) \\
(\Fst((\val_1, \val_2)_\valForm), \state) \hstep[\nil]{}&
(\val_1, \state, \nil) \\
(\Snd((\val_1, \val_2)_\valForm), \state) \hstep[\nil]{}&
(\val_2, \state, \nil) \\
(\MatchCore \Inl(\val)_\valForm with \expr_1 | \expr_2 end, \state) \hstep[\nil]{}&
(\expr_1(\val), \state, \nil) \\
(\MatchCore \Inr(\val)_\valForm with \expr_1 | \expr_2 end, \state) \hstep[\nil]{}&
(\expr_2(\val), \state, \nil)
\end{align*}
\caption{HeapLang pure and boxed reduction rules. \\ \small
The $\HLOp$ subscript indicates that this is the HeapLang operator, not the mathematical operator.}
\label{fig:heaplang-reduction-pure}
\end{figure}
\begin{figure}
\judgment[``Head'' reduction (impure)]{\expr_1, \state_1 \hstep [\vec\obs] \expr_2, \state_2, \vec\expr}
\newcommand\alignheader{\kern-30ex}
\begin{align*}
&\alignheader\textbf{Heap reductions} \\
(\Alloc(z, \val), \state) \hstep[\nil]{}&
(\loc, \mapinsert {[\loc,\loc+z)} \val {\state:\stateHeap}, \nil)
&&\text{if $z>0$ and \(\All i<z. \state.\stateHeap(\loc+i) = \bot\)} \\
(\Free(\loc), \state) \hstep[\nil]{}&
((), \mapinsert \loc \bot {\state:\stateHeap}, \nil) &&\text{if $\state.\stateHeap(l) = \val$} \\
(\deref\loc, \state) \hstep[\nil]{}&
(\val, \state, \nil) &&\text{if $\state.\stateHeap(l) = \val$} \\
(\loc\gets\valB, \state) \hstep[\nil]{}&
(\TT, \mapinsert \loc \valB {\state:\stateHeap}, \nil) &&\text{if $\state.\stateHeap(l) = \val$} \\
(\CmpXchg(\loc,\valB_1,\valB_2), \state) \hstep[\nil]{}&
((\val, \True), \mapinsert\loc{\valB_2}{\state:\stateHeap}, \nil)
&&\text{if $\state.\stateHeap(l) = \val$ and $\val \valeq \valB_1$} \\
(\CmpXchg(\loc,\valB_1,\valB_2), \state) \hstep[\nil]{}&
((\val, \False), \state, \nil)
&&\text{if $\state.\stateHeap(l) = \val$ and $\val \valne \valB_1$} \\
(\Xchg(\loc, \valB) \hstep[\nil]{}&
(\val, \mapinsert \loc \valB {\state:\stateHeap}, \nil) &&\text{if $\state.\stateHeap(l) = \val$} \\
(\FAA(\loc, z_2) \hstep[\nil]{}&
(z_1, \mapinsert \loc {z_1+z_2} {\state:\stateHeap}, \nil) &&\text{if $\state.\stateHeap(l) = z_1$} \\
&\alignheader\textbf{Special reductions} \\
(\Fork\expr, \state) \hstep[\nil]{}&
(\TT, \state, \expr) \\
(\NewProph, \state) \hstep[\nil]{}&
(\prophid, \state:\stateProphs \uplus \set{\prophid}, \nil)
&&\text{if $\prophid \notin \state.\stateProphs$}
\end{align*}
\begin{mathpar}
\infer
{(\expr, \state) \hstep[\vec\obs] (\val, \state', \vec\expr')}
{(\ResolveWith \expr at \prophid to \valB, \state) \hstep[\vec\obs \dplus [(\prophid, (\val, \valB))]] (\val, \state', \vec\expr')}
\end{mathpar}
\caption{HeapLang impure reduction rules. \\ \small
Here, $\state:\stateHeap$ denotes $\sigma$ with the $\stateHeap$ field updated as indicated.
$[\loc,\loc+z)$ in the $\Alloc$ rule indicates that we update all locations in this (left-closed, right-open) interval.}
\label{fig:heaplang-reduction-impure}
\end{figure}
\begin{figure}
\judgment[Value (in)equality]{\val \valeq \valB, \val \valne \valB}
\begin{align*}
\val \valeq \valB \eqdef{}& \val = \valB \land (\valCompareSafe(\val) \lor \valCompareSafe(\valB)) \\
\val \valne \valB \eqdef{}& \val \ne \valB \land (\valCompareSafe(\val) \lor \valCompareSafe(\valB))
\end{align*}
\begin{mathpar}
\axiom{\litCompareSafe(z)}
\axiom{\litCompareSafe(\True)}
\axiom{\litCompareSafe(\False)}
\axiom{\litCompareSafe(\loc)}
\axiom{\litCompareSafe(\TT)}
\\
\infer
{\litCompareSafe(\val)}
{\valCompareSafe(\val)}
\infer
{\litCompareSafe(\val)}
{\valCompareSafe(\Inl(\val))}
\infer
{\litCompareSafe(\val)}
{\valCompareSafe(\Inr(\val))}
\end{mathpar}
\caption{HeapLang value comparison judgment.}
\label{fig:heaplang-valeq}
\end{figure}
\subsection{Syntactic sugar}
We recover many of the common language operations as syntactic sugar.
\begin{align*}
\Lam \lvar. \expr \eqdef{}& \Rec\any(\lvar)= \expr \\
\Let \lvar = \expr in \expr' \eqdef{}& (\Lam \lvar. \expr')(\expr) \\
\expr; \expr' \eqdef{}& \Let \any = \expr in \expr' \\
\Skip \eqdef{}& \TT; \TT \\
\Ref(\expr) \eqdef{}& \Alloc(1,\expr) \\
\CAS(\expr_1, \expr_2, \expr_3) \eqdef{}& \Snd(\CmpXchg(\expr_1, \expr_2, \expr_3)) \\
\Resolve \expr_1 to \expr_2 \eqdef{}& \ResolveWith \Skip at \expr_1 to \expr_2
\end{align*}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "iris"
%%% End:
......@@ -31,6 +31,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\nat}{\mathbb{N}}
\newcommand{\integer}{\mathbb{Z}}
\DeclareMathOperator*{\Sep}{\scalerel*{\ast}{\sum}} % big-star
\newcommand*{\disj}[1][]{\mathrel{\#_{#1}}}
......
......@@ -27,7 +27,7 @@
This document describes formally the Iris program logic.
Every result in this document has been fully verified in Coq.
The latest versions of this document and the Coq formalization can be found in the git repository at \url{https://gitlab.mpi-sws.org/iris/iris}.
For further information, visit the Iris project website at \url{http://plv.mpi-sws.org/iris/}.
For further information, visit the Iris project website at \url{https://iris-project.org}.
\end{abstract}
\clearpage\begingroup
......@@ -69,6 +69,9 @@ For a list of changes in Iris since then, please consult our changelog at \url{h
\input{paradoxes}
\endgroup
\clearpage\begingroup
\input{heaplang}
\endgroup
\clearpage\begingroup
\printbibliography
\endgroup
......
......@@ -46,6 +46,7 @@ Otherwise, we need strong atomicity.
\end{defn}
\subsection{Concurrent Language}
\label{sec:language:concurrent}
For any language $\Lang$, we define the corresponding thread-pool semantics.
......
......@@ -18,6 +18,7 @@
\usepackage{\basedir pftools}
\usepackage{\basedir iris}
\usepackage{\basedir heaplang}
\usepackage{xcolor} % for print version
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment