| 1 | \part{Semantics}
|
|---|
| 2 | \label{part:semantics}
|
|---|
| 3 |
|
|---|
| 4 | \chapter{CIVL Model Syntax}
|
|---|
| 5 |
|
|---|
| 6 | \section{Notation and terminology}
|
|---|
| 7 | \label{sec:notation}
|
|---|
| 8 |
|
|---|
| 9 | Let $\B=\{\true,\false\}$ (the set of boolean values). Let
|
|---|
| 10 | $\N=\{0,1,2,\ldots\}$ (the set of natural numbers).
|
|---|
| 11 |
|
|---|
| 12 | Given a node $u$ in a tree, we let $\ancestors(u)$ denote the set of
|
|---|
| 13 | all ancestors of $u$, including $u$. We let $\descendants(u)$ denote
|
|---|
| 14 | the set of all descendants of $u$, including $u$.
|
|---|
| 15 |
|
|---|
| 16 | For any set $S$, let $S^*$ denote the set of all finite sequences of
|
|---|
| 17 | elements of $S$. The length of a sequence $\xi\in S^*$ is denoted
|
|---|
| 18 | $\len(\xi)$.
|
|---|
| 19 |
|
|---|
| 20 | % This is a lie:
|
|---|
| 21 | % The elements of the sequence are indexed from $0$ to
|
|---|
| 22 | % $\len(\xi)-1$.
|
|---|
| 23 |
|
|---|
| 24 | \section{Definition of Context}
|
|---|
| 25 | \label{sec:context}
|
|---|
| 26 |
|
|---|
| 27 | \begin{definition}
|
|---|
| 28 | A \emph{CIVL type system} is a tuple comprising the following
|
|---|
| 29 | components:
|
|---|
| 30 | \begin{enumerate}
|
|---|
| 31 | \item a set $\Type$ (the set of \emph{types}),
|
|---|
| 32 | \item a type $\bool\in\Type$ (the \emph{boolean type}),
|
|---|
| 33 | \item a type $\proc\in\Type$ (the \emph{process-reference type}),
|
|---|
| 34 | \item a set $\Var$ (the set of all \emph{typed variables}),
|
|---|
| 35 | \item a function $\vtype\colon \Var\ra\Type$ (which gives the
|
|---|
| 36 | type of each variable),
|
|---|
| 37 | \item a set $\Val$ (the set of all \emph{values}),
|
|---|
| 38 | \item a function which assigns to each $t\in\Type$ a subset
|
|---|
| 39 | $\Val_t\subseteq\Val$ (the set of values of type $t$)
|
|---|
| 40 | and which satisfies $\Val_{\bool}=\B$ and $\Val_{\proc}=\N$,
|
|---|
| 41 | \item a function which assigns to each $t\in\Type$ a value
|
|---|
| 42 | $\default_t\in\Val_t$.
|
|---|
| 43 | \end{enumerate}
|
|---|
| 44 | \end{definition}
|
|---|
| 45 |
|
|---|
| 46 | The default value will be used to give an initial value to any
|
|---|
| 47 | variable. It could represent something like ``an undefined value of
|
|---|
| 48 | type $t$'' or a reasonable initial value ($0$ for integers, etc.),
|
|---|
| 49 | depending on the language one is modeling.
|
|---|
| 50 |
|
|---|
| 51 | \begin{definition}
|
|---|
| 52 | Given a CIVL type system, a \emph{valuation} in that system is a
|
|---|
| 53 | function $\eta\colon\Var\ra\Val$ with the property that for any
|
|---|
| 54 | $v\in\Var$, $\eta(v)\in\Val_{\vtype(v)}$.
|
|---|
| 55 | \end{definition}
|
|---|
| 56 |
|
|---|
| 57 | Given a CIVL type system, we let $\Eval$ denote the set of all
|
|---|
| 58 | valuations in that system.
|
|---|
| 59 |
|
|---|
| 60 | \begin{definition}
|
|---|
| 61 | Given a CIVL type system, A \emph{CIVL expression system} for that
|
|---|
| 62 | type system is a tuple comprising the following components:
|
|---|
| 63 | \begin{enumerate}
|
|---|
| 64 | \item a set $\Expr$ (the set of all \emph{typed expressions} over
|
|---|
| 65 | $\Var$),
|
|---|
| 66 | \item a function $\etype\colon\Expr\ra\Type$ (giving the type
|
|---|
| 67 | of each expression),
|
|---|
| 68 | \item a function
|
|---|
| 69 | $\eval\colon\Expr\times\Eval\ra\Val$ (the \emph{evaluation
|
|---|
| 70 | function}), satisyfing
|
|---|
| 71 | \begin{itemize}
|
|---|
| 72 | \item for any $e\in\Expr$ and $\eta\in\Eval$,
|
|---|
| 73 | $\eval(e,\eta)\in\Val_{\etype(e)}$,
|
|---|
| 74 | \end{itemize}
|
|---|
| 75 | \item a function which associates to any $V\subseteq\Var$, a
|
|---|
| 76 | subset $\Expr(V)\subseteq\Expr$ (the set of
|
|---|
| 77 | \emph{expressions which involve only variables in $V$}) satisfying
|
|---|
| 78 | the following:
|
|---|
| 79 | \begin{itemize}
|
|---|
| 80 | \item for any $V\subseteq\Var$ and $\eta,\eta'\in\Eval$, if
|
|---|
| 81 | $\eta(v)=\eta'(v)$ for all $v\in V$, then for any $e\in\Expr(V)$,
|
|---|
| 82 | $\eval(e,\eta)=\eval(e,\eta')$
|
|---|
| 83 | \end{itemize}
|
|---|
| 84 | \end{enumerate}
|
|---|
| 85 | \end{definition}
|
|---|
| 86 |
|
|---|
| 87 | \begin{definition}
|
|---|
| 88 | A \emph{CIVL context} is a CIVL type system together with
|
|---|
| 89 | a CIVL expression system for that type system.
|
|---|
| 90 | \end{definition}
|
|---|
| 91 |
|
|---|
| 92 | \begin{figure}
|
|---|
| 93 | \notationtable
|
|---|
| 94 | \caption{Table of Notation Used to Define CIVL Model Syntax}
|
|---|
| 95 | \label{fig:notation}
|
|---|
| 96 | \end{figure}
|
|---|
| 97 |
|
|---|
| 98 | \section{Lexical scopes}
|
|---|
| 99 | \label{sec:scopes}
|
|---|
| 100 |
|
|---|
| 101 | \begin{definition}
|
|---|
| 102 | Given a CIVL context $\mathcal{C}$, a \emph{lexical scope system}
|
|---|
| 103 | over $\mathcal{C}$ is a tuple
|
|---|
| 104 | \[
|
|---|
| 105 | (\Sigma,\rootscope,\sparent,\vars)
|
|---|
| 106 | \]
|
|---|
| 107 | consisting of
|
|---|
| 108 | \begin{enumerate}
|
|---|
| 109 | \item a set $\Sigma$ (the set of \emph{static scopes}),
|
|---|
| 110 | \item a scope $\rootscope\in\Sigma$ (the \emph{root scope}),
|
|---|
| 111 | \item a function
|
|---|
| 112 | $\sparent\colon\Sigma\setminus\{\rootscope\}\rightarrow
|
|---|
| 113 | \Sigma$ such that
|
|---|
| 114 | \[\{(\sparent(\sigma),\sigma)\mid \sigma\in\Sigma\setminus\{\rootscope\}\}\]
|
|---|
| 115 | gives $\Sigma$ the structure of a rooted tree with root $\rootscope$,
|
|---|
| 116 | \item a function $\vars\colon\Sigma\rightarrow 2^{\Var}$
|
|---|
| 117 | (specifying the variables \emph{declared} in each scope) satisfying
|
|---|
| 118 | \begin{itemize}
|
|---|
| 119 | \item $\sigma\neq\tau\implies \vars(\sigma)\cap \vars(\tau)=\emptyset$.
|
|---|
| 120 | \end{itemize}
|
|---|
| 121 | \end{enumerate}
|
|---|
| 122 | \end{definition}
|
|---|
| 123 |
|
|---|
| 124 | \begin{definition}
|
|---|
| 125 | Given a CIVL context and scope $\sigma\in\Sigma$,
|
|---|
| 126 | the set of \emph{visible variables} in $\sigma$
|
|---|
| 127 | is $\bigcup_{\sigma'\in\ancestors(\sigma)}\vars(\sigma')$.
|
|---|
| 128 | \end{definition}
|
|---|
| 129 |
|
|---|
| 130 | One way this notion will be used: expressions used in a scope $\sigma$
|
|---|
| 131 | can only involve variables visible in $\sigma$.
|
|---|
| 132 |
|
|---|
| 133 | \section{Functions}
|
|---|
| 134 | \label{sec:functions}
|
|---|
| 135 |
|
|---|
| 136 | Fix a CIVL context $\mathcal{C}$ and lexical scope system
|
|---|
| 137 | \[\Lambda=(\Sigma,\rootscope,\sparent,\vars)\] over $\mathcal{C}$.
|
|---|
| 138 |
|
|---|
| 139 | We introduce a new type symbol $\void$, as in C, to use as the return
|
|---|
| 140 | type for a function that does not return a value. Let
|
|---|
| 141 | $\Type'=\Type\cup\{\void\}$.
|
|---|
| 142 |
|
|---|
| 143 | \begin{definition}
|
|---|
| 144 | A \emph{function prototype} for $\Lambda$ is a tuple
|
|---|
| 145 | $(\sigma, t, \xi)$ consisting of
|
|---|
| 146 | \begin{enumerate}
|
|---|
| 147 | \item a scope $\sigma\in\Sigma\setminus\{\rootscope\}$
|
|---|
| 148 | (the \emph{function scope}),
|
|---|
| 149 | \item a type $t\in\Type'$ (the \emph{return type}),
|
|---|
| 150 | \item a finite sequence $\xi=v_1v_2\cdots v_n\in\vars(\sigma)^*$
|
|---|
| 151 | consisting of variables declared in the function scope
|
|---|
| 152 | (the \emph{formal parameters}).
|
|---|
| 153 | \end{enumerate}
|
|---|
| 154 | \end{definition}
|
|---|
| 155 |
|
|---|
| 156 | \begin{definition}
|
|---|
| 157 | A \emph{CIVL function prototype system} consists of
|
|---|
| 158 | \begin{enumerate}
|
|---|
| 159 | \item a set $\Func$ (the \emph{function symbols}),
|
|---|
| 160 | \item a function which assigns to each $f\in\Func$ a
|
|---|
| 161 | function prototype, denoted
|
|---|
| 162 | \[
|
|---|
| 163 | (\fscope(f), \returntype(f), \params(f)),
|
|---|
| 164 | \]
|
|---|
| 165 | and satisfying
|
|---|
| 166 | \begin{itemize}
|
|---|
| 167 | \item for any $\sigma\in\Sigma$, there is at most
|
|---|
| 168 | one $f\in\Func$ such that $\sigma=\fscope(f)$, and
|
|---|
| 169 | \end{itemize}
|
|---|
| 170 | \item a \emph{root function} $f_0$ with $\fscope(f_0)=\rootscope$
|
|---|
| 171 | and which is the only function with root scope.
|
|---|
| 172 | \end{enumerate}
|
|---|
| 173 | \end{definition}
|
|---|
| 174 |
|
|---|
| 175 |
|
|---|
| 176 | \begin{definition}
|
|---|
| 177 | Given a CIVL function prototype system, and function symbol
|
|---|
| 178 | $f\in\Func\setminus\{f_0\}$, the \emph{declaration scope} of $f$ is
|
|---|
| 179 | the scope $\sigma=\sparent(\fscope(f))$. We also write \emph{$f$ is
|
|---|
| 180 | declared in $\sigma$.}
|
|---|
| 181 | \end{definition}
|
|---|
| 182 |
|
|---|
| 183 | Note the root function $f_0$ has no declaration scope.
|
|---|
| 184 |
|
|---|
| 185 | Just as every scope has a set of visible variables, there is also
|
|---|
| 186 | a set of visible functions:
|
|---|
| 187 | \begin{definition}
|
|---|
| 188 | The functions \emph{visible at scope $\sigma$} are
|
|---|
| 189 | those declared in $\sigma$ or an ancestor of $\sigma$.
|
|---|
| 190 | \end{definition}
|
|---|
| 191 | We will see that the variables and functions visible at $\sigma$ are
|
|---|
| 192 | the only variables and functions that can be referred to by statements
|
|---|
| 193 | and expressions used within $\sigma$.
|
|---|
| 194 |
|
|---|
| 195 | Note that only certain scopes are function scopes. There can be
|
|---|
| 196 | additional scopes (intuitively corresponding to block scopes in a
|
|---|
| 197 | source program). Every scope, however, must ``belong to'' exactly one
|
|---|
| 198 | function. The precise definition is as follows:
|
|---|
| 199 | \begin{definition}
|
|---|
| 200 | \label{def:func}
|
|---|
| 201 | Given a CIVL function prototype system, define
|
|---|
| 202 | \[
|
|---|
| 203 | \func \colon \Sigma \ra \Func
|
|---|
| 204 | \]
|
|---|
| 205 | by
|
|---|
| 206 | \[
|
|---|
| 207 | \func(\sigma)=
|
|---|
| 208 | \begin{cases}
|
|---|
| 209 | f & \text{if $\sigma=\fscope(f)$ for some $f\in\Func$}\\
|
|---|
| 210 | \func(\sparent(\sigma)) & \text{otherwise.}
|
|---|
| 211 | \end{cases}
|
|---|
| 212 | \]
|
|---|
| 213 | We say \emph{$\sigma$ belongs to $f$} when $\func(\sigma)=f$.
|
|---|
| 214 | \end{definition}
|
|---|
| 215 | Note that the recursion in Definition \ref{def:func} must stop as the
|
|---|
| 216 | root scope belongs to the root function and the scopes form a tree.
|
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 | \section{Statements}
|
|---|
| 220 |
|
|---|
| 221 | Fix a CIVL function prototype system. A \emph{CIVL statement} is
|
|---|
| 222 | defined to be a tuple of one of the forms described below.
|
|---|
| 223 | In each case, we give any restritions on the components of the tuple
|
|---|
| 224 | and a brief intuition on the statement's semantics. The precise
|
|---|
| 225 | semantics will be described in \S\ref{sec:semantics}.
|
|---|
| 226 |
|
|---|
| 227 | \begin{enumerate}
|
|---|
| 228 | \item $\langle\code{parassign},V_1,V_2,\psi\rangle$
|
|---|
| 229 | \begin{itemize}
|
|---|
| 230 | \item $V_1,V_2\subseteq\Var$
|
|---|
| 231 | \item $\psi\colon V_2\ra\Expr(V_1)$ satisfying
|
|---|
| 232 | $\etype(\psi(v))=\vtype(v)$ for all $v\in V_2$
|
|---|
| 233 | \item \emph{meaning}: parallel assignment, i.e., the assignment of new
|
|---|
| 234 | values to any or all of the variables in $V_2$. For each variable
|
|---|
| 235 | in $V_2$ an expression is given which will be evaluated in the old
|
|---|
| 236 | state to compute the new value for that variable. $V_1$ contains
|
|---|
| 237 | all the variables that may be used in those expressions. Hence
|
|---|
| 238 | $V_1$ is the ``read set'' and $V_2$ is the ``write set'' for the
|
|---|
| 239 | parallel assignment.
|
|---|
| 240 | \end{itemize}
|
|---|
| 241 | \item $\langle\code{assign},v,e\rangle$
|
|---|
| 242 | \begin{itemize}
|
|---|
| 243 | \item $v\in\Var$, $e\in\Expr$, $\etype(e)=\vtype(v)$
|
|---|
| 244 | \item \emph{meaning}: simple assignment: evaluate an expression $e$ and
|
|---|
| 245 | assign result to variable $v$. It is a special case of
|
|---|
| 246 | \code{parassign} but is provided for convenience.
|
|---|
| 247 | \end{itemize}
|
|---|
| 248 | \item $\langle\code{call},y,f,e_1,\ldots,e_n\rangle$
|
|---|
| 249 | \begin{itemize}
|
|---|
| 250 | \item $y\in\Var$, $f\in\Func$, $e_1,\ldots,e_n\in\Expr$
|
|---|
| 251 | \item $n=\numparams(f)$
|
|---|
| 252 | \item $\etype(e_i)=\vtype(v_i)$, where $\params(f)=v_1\cdots v_n$
|
|---|
| 253 | \item $\returntype(f)=\vtype(y)$
|
|---|
| 254 | \item \emph{meaning}: evaluate expressions $e_1,\ldots,e_n$; push
|
|---|
| 255 | frame on call stack and move control to guarded transition system
|
|---|
| 256 | (see \S\ref{sec:gts}) for function $f$; when $f$ returns, pop
|
|---|
| 257 | stack and store returned result in $y$
|
|---|
| 258 | \end{itemize}
|
|---|
| 259 | \item $\langle\code{call},f,e_1,\ldots,e_n\rangle$
|
|---|
| 260 | \begin{itemize}
|
|---|
| 261 | \item $f\in\Func$, $e_1,\ldots,e_n\in\Expr$
|
|---|
| 262 | \item $n=\numparams(f)$
|
|---|
| 263 | \item $\etype(e_i)=\vtype(v_i)$, where $\params(f)=v_1\cdots v_n$
|
|---|
| 264 | \item \emph{meaning}: like above, but return type may be \code{void}
|
|---|
| 265 | or returned value could just be ignored
|
|---|
| 266 | \end{itemize}
|
|---|
| 267 | \item $\langle\code{fork},p,f,e_1,\ldots,e_n\rangle$
|
|---|
| 268 | \begin{itemize}
|
|---|
| 269 | \item $p\in\Var$, $f\in\Func$, $e_1,\ldots,e_n\in\Expr$
|
|---|
| 270 | \item $n=\numparams(f)$
|
|---|
| 271 | \item $\etype(e_i)=\vtype(v_i)$, where $\params(f)=v_1\cdots v_n$
|
|---|
| 272 | \item $\returntype(f)=\void$
|
|---|
| 273 | \item $\vtype(p)=\proc$
|
|---|
| 274 | \item \emph{meaning}: evaluate expressions $e_1,\ldots,e_n$;
|
|---|
| 275 | create new process and invoke function $f$ in it;
|
|---|
| 276 | return, immediately, a reference to the new process and store
|
|---|
| 277 | that reference in $p$
|
|---|
| 278 | \end{itemize}
|
|---|
| 279 | \item $\langle\code{join},e\rangle$
|
|---|
| 280 | \begin{itemize}
|
|---|
| 281 | \item $e\in\Expr$
|
|---|
| 282 | \item $\etype(e)=\proc$
|
|---|
| 283 | \item \emph{meaning}: evaluate $e$ and wait for the referenced process to terminate
|
|---|
| 284 | \end{itemize}
|
|---|
| 285 | \item $\langle\code{return},e\rangle$
|
|---|
| 286 | \begin{itemize}
|
|---|
| 287 | \item $e\in\Expr$
|
|---|
| 288 | \item \emph{meaning}: evaluate $e$, pop the call stack and return
|
|---|
| 289 | control, along with the value, to caller
|
|---|
| 290 | \end{itemize}
|
|---|
| 291 | \item $\langle\code{return}\rangle$
|
|---|
| 292 | \begin{itemize}
|
|---|
| 293 | \item \emph{meaning}: pop the call stack and return control to caller;
|
|---|
| 294 | only to be used in functions returning \code{void}
|
|---|
| 295 | \end{itemize}
|
|---|
| 296 | \item $\langle\code{write},e\rangle$
|
|---|
| 297 | \begin{itemize}
|
|---|
| 298 | \item $e\in\Expr$
|
|---|
| 299 | \item \emph{meaning}: evaluate $e$ and send result to output
|
|---|
| 300 | \end{itemize}
|
|---|
| 301 | \item $\langle\code{noop}\rangle$
|
|---|
| 302 | \begin{itemize}
|
|---|
| 303 | \item \emph{meaning}: does nothing
|
|---|
| 304 | \end{itemize}
|
|---|
| 305 | \item $\langle\code{assert}, e\rangle$
|
|---|
| 306 | \begin{itemize}
|
|---|
| 307 | \item $e\in\Expr$, $\vtype(e)=\bool$
|
|---|
| 308 | \item \emph{meaning}: evaluate $e$; if result is false, stop
|
|---|
| 309 | execution and report error
|
|---|
| 310 | \end{itemize}
|
|---|
| 311 | \item $\langle\code{assume}, e\rangle$
|
|---|
| 312 | \begin{itemize}
|
|---|
| 313 | \item $e\in\Expr$, $\vtype(e)=\bool$
|
|---|
| 314 | \item \emph{meaning}: assume $e$ holds (i.e., if $e$ does not hold,
|
|---|
| 315 | the execution sequence is not a real execution)
|
|---|
| 316 | \end{itemize}
|
|---|
| 317 | \end{enumerate}
|
|---|
| 318 |
|
|---|
| 319 | \section{Remarks}
|
|---|
| 320 |
|
|---|
| 321 | The system described is sufficiently general to model pointers. There
|
|---|
| 322 | can be (one or more) pointer types and corresponding values. The
|
|---|
| 323 | parallel assignment statement can be used to model statements like
|
|---|
| 324 | C's \texttt{*p=e;}. In the worst case (if no information is known
|
|---|
| 325 | about where \texttt{p} could point), one can let $V_2=\Var$.
|
|---|
| 326 | Similarly, expressions that involve \texttt{*p} as a right-hand
|
|---|
| 327 | side subexpression can always take $V_1=\Var$.
|
|---|
| 328 |
|
|---|
| 329 | Heaps can also be modeled. A heap type may be defined and a variable
|
|---|
| 330 | of that type declared. Expressions to modify and read from the heap
|
|---|
| 331 | can be defined, as can pointers into the heap.
|
|---|
| 332 |
|
|---|
| 333 |
|
|---|
| 334 | \section{Transition system representation of functions}
|
|---|
| 335 | \label{sec:gts}
|
|---|
| 336 |
|
|---|
| 337 | \begin{definition}
|
|---|
| 338 | Given a CIVL function prototype system and $f\in\Func$,
|
|---|
| 339 | a \emph{guarded transition system} for $f$
|
|---|
| 340 | is a tuple $(\Loc,\lscope,\start, T)$, where
|
|---|
| 341 | \begin{itemize}
|
|---|
| 342 | \item $\Loc$ is a set (the set of \emph{locations}),
|
|---|
| 343 | \item $\lscope\colon\Loc\ra\Sigma$ is a function which associates
|
|---|
| 344 | to each $l\in\Loc$ a scope $\lscope(l)\in\Sigma$ belonging to $f$,
|
|---|
| 345 | \item $\start\in\Loc$ (the \emph{start location}),
|
|---|
| 346 | \item $T$ is a set of \emph{guarded transitions}, each of which has
|
|---|
| 347 | the form $\langle l,g,s,l'\rangle$, where
|
|---|
| 348 | \begin{itemize}
|
|---|
| 349 | \item $l,l'\in\Loc$ (the \emph{source} and \emph{target}
|
|---|
| 350 | locations)
|
|---|
| 351 | \item $g\in\Expr(V)$, where $V$ is the set of variables visible at
|
|---|
| 352 | $\lscope(l)$, and $\etype(g)=\bool$ ($g$ is called the
|
|---|
| 353 | \emph{guard}),
|
|---|
| 354 | \item $s$ is a statment all of whose constituent variables,
|
|---|
| 355 | expressions, and function symbols are visible at $\lscope(l)$.
|
|---|
| 356 | \end{itemize}
|
|---|
| 357 | \end{itemize}
|
|---|
| 358 | Furthermore, if the guarded transition system contains a statement
|
|---|
| 359 | of the form $\langle\code{return}\rangle$ then
|
|---|
| 360 | $\returntype(f)=\void$. If it contains a statement of the form
|
|---|
| 361 | $\langle\code{return},e\rangle$ then
|
|---|
| 362 | \[
|
|---|
| 363 | \etype(e)=\returntype(f).
|
|---|
| 364 | \]
|
|---|
| 365 | \end{definition}
|
|---|
| 366 |
|
|---|
| 367 | \begin{definition}
|
|---|
| 368 | Given a CIVL prototype system, a \emph{CIVL model} $M$ for that
|
|---|
| 369 | system assigns, to each $f\in\Func$, a guarded transition system
|
|---|
| 370 | \[(\Loc_f,\lscope_f, \start_f,T_f)\] for $f$. Moreover, if $f\neq f'$
|
|---|
| 371 | then
|
|---|
| 372 | $\Loc_f\cap\Loc_{f'}=\emptyset$.
|
|---|
| 373 | \end{definition}
|
|---|
| 374 |
|
|---|
| 375 | \begin{definition}
|
|---|
| 376 | Given a CIVL model $M$, let $\Loc=\bigcup_{f\in\Func}\Loc_f$.
|
|---|
| 377 | \end{definition}
|
|---|
| 378 |
|
|---|
| 379 | \chapter{CIVL Model Semantics}
|
|---|
| 380 | \label{sec:semantics}
|
|---|
| 381 |
|
|---|
| 382 | \section{State}
|
|---|
| 383 | \label{sec:state}
|
|---|
| 384 |
|
|---|
| 385 | Fix a CIVL model $M$. Recall that a valuation is a type-respecting
|
|---|
| 386 | function from $\Var$ to $\Val$. Given a subset $V\subseteq\Var$ of
|
|---|
| 387 | variables, we define a \emph{valuation on $V$} to be a type-respecting
|
|---|
| 388 | function from $V$ to $\Val$. Let $\Eval(V)$ denote the set of all
|
|---|
| 389 | valuations on $V$. Note that $\Eval(\Var)=\Eval$.
|
|---|
| 390 |
|
|---|
| 391 | \begin{definition}
|
|---|
| 392 | \label{def:state}
|
|---|
| 393 | A \emph{state} of a CIVL model $M$ is a tuple
|
|---|
| 394 | \[
|
|---|
| 395 | s=(\Delta, \droot, \dparent, \static, \deval, P, \stack),
|
|---|
| 396 | \]
|
|---|
| 397 | where
|
|---|
| 398 | \begin{enumerate}
|
|---|
| 399 | \item $\Delta$ is a finite set (the set of \emph{dynamic scopes} in
|
|---|
| 400 | $s$),
|
|---|
| 401 | \item $\droot\in\Delta$ (the \emph{root dynamic scope}),
|
|---|
| 402 | \item $\dparent\colon \Delta\setminus\{\droot\}\ra\Delta$
|
|---|
| 403 | is a function such that the set
|
|---|
| 404 | \[
|
|---|
| 405 | \{(\dparent(\delta),\delta)\mid \delta\in
|
|---|
| 406 | \Delta\setminus\{\droot\}\}
|
|---|
| 407 | \]
|
|---|
| 408 | gives $\Delta$ the structure of a rooted tree with root $\droot$,
|
|---|
| 409 | \item $\static\colon\Delta\ra\Sigma$,
|
|---|
| 410 | \item $\static(\droot)=\rootscope$ and $\droot$ is the only
|
|---|
| 411 | $\delta\in\Delta$ satisfying $\static(\delta)=\rootscope$,
|
|---|
| 412 | \item $\static(\dparent(\delta))=\sparent(\static(\delta))$ for any
|
|---|
| 413 | $\delta\in\Delta$,
|
|---|
| 414 | \item $\deval$ is a function that assigns to each $\delta\in\Delta$
|
|---|
| 415 | a valuation $\deval(\delta)\in\Eval(\vars(\static(\delta)))$,
|
|---|
| 416 | \item $P$ (the set of \emph{process IDs} in $s$)
|
|---|
| 417 | is a finite subset of $\Val_{\proc}$, and
|
|---|
| 418 | \item $\stack\colon P\ra \Frame^*$, where
|
|---|
| 419 | \[
|
|---|
| 420 | \Frame=\{(\delta,l)\in\Delta\times\Loc\mid\lscope(l)=\static(\delta)\}.
|
|---|
| 421 | \]
|
|---|
| 422 | \end{enumerate}
|
|---|
| 423 | Let $\State$ denote the set of all states of $M$.
|
|---|
| 424 | \end{definition}
|
|---|
| 425 |
|
|---|
| 426 | % say entrance and exit from scopes does not have to be "structured".
|
|---|
| 427 |
|
|---|
| 428 | Remarks:
|
|---|
| 429 | \begin{enumerate}
|
|---|
| 430 | \item We will also refer to dynamic scopes as \emph{dyscopes}.
|
|---|
| 431 | \item The elements of $\Delta$ contain no intrinsic information.
|
|---|
| 432 | Instead, all of the information concerning dyscopes is encoded
|
|---|
| 433 | in the functions that take elements of $\Delta$ as arguments. Hence
|
|---|
| 434 | we might just as well call the elements of $\Delta$ ``dynamic scope
|
|---|
| 435 | IDs'' (just as we call the elements of $P$ ``process IDs''). One
|
|---|
| 436 | could use natural numbers for the dyscopes, just as one does
|
|---|
| 437 | for processes.
|
|---|
| 438 | \item The reason for using some form of ID for dyscopes and
|
|---|
| 439 | processes, rather than just incorporating the data in the
|
|---|
| 440 | appropriate part of the state, is that both kinds of objects may be
|
|---|
| 441 | shared. There can be several components of the state that refer to
|
|---|
| 442 | the same dyscope $d$: e.g., $d$ could have several children,
|
|---|
| 443 | each of which has a parent reference to $d$, as well as a reference
|
|---|
| 444 | from a frame. A process can be referred to by any number of
|
|---|
| 445 | variables of type $\proc$.
|
|---|
| 446 | \item If $\sigma=\static(\delta)$, we say that \emph{$\delta$ is an
|
|---|
| 447 | instance of $\sigma$} or \emph{$\sigma$ is the static scope
|
|---|
| 448 | associated to $\delta$}. In general, a static scope can have any
|
|---|
| 449 | number (including 0) of dynamic instances. The exception is the root
|
|---|
| 450 | scope $\rootscope$, which must have exactly one instance ($\droot$).
|
|---|
| 451 | \item A valuation $\deval(\delta)$ assigns a value to each variable in
|
|---|
| 452 | the static scope associated to $\delta$. The function $\deval$
|
|---|
| 453 | thereby encodes the value of all variables ``in scope'' in state
|
|---|
| 454 | $s$.
|
|---|
| 455 | \item The sequence $\stack(p)$ encodes the state of the call stack of
|
|---|
| 456 | process $p$. The elements of the sequence are called
|
|---|
| 457 | \emph{activation frames}. The first frame in the sequence, i.e.,
|
|---|
| 458 | the frame in position $0$, is the bottom of the stack; the last
|
|---|
| 459 | frame is the top of the stack.
|
|---|
| 460 | \item Each frame refers to a dyscope $\delta$ and a
|
|---|
| 461 | location in the static scope associated to $\delta$.
|
|---|
| 462 | \end{enumerate}
|
|---|
| 463 |
|
|---|
| 464 |
|
|---|
| 465 | \begin{definition}
|
|---|
| 466 | A dyscope $\delta\in\Delta$ is a \emph{function node}
|
|---|
| 467 | if $\static(\delta)$ is the function scope of some function.
|
|---|
| 468 | \end{definition}
|
|---|
| 469 |
|
|---|
| 470 | \begin{definition}
|
|---|
| 471 | Given any $\delta\in\Delta$, $\fnode(\delta)\in\Delta$ is defined as
|
|---|
| 472 | follows: if $\delta$ is a function node, then
|
|---|
| 473 | $\fnode(\delta)=\delta$, else
|
|---|
| 474 | $\fnode(\delta)=\fnode(\dparent(\delta))$. We call $\fnode(\delta)$
|
|---|
| 475 | the \emph{function node associated to $\delta$}.
|
|---|
| 476 | \end{definition}
|
|---|
| 477 |
|
|---|
| 478 | The relation $\{(\delta,\delta')\mid \fnode(\delta)=\fnode(\delta')\}$
|
|---|
| 479 | is an equivalence relation $\sim$ on $\Delta$. Let
|
|---|
| 480 | $\bar{\Delta}=\Delta/\sim$ and write $[\delta]$ for the equivalence
|
|---|
| 481 | class containing $\delta$.
|
|---|
| 482 |
|
|---|
| 483 | The set of activation frames in a state $s$ may be identified with the
|
|---|
| 484 | set
|
|---|
| 485 | \[
|
|---|
| 486 | AF(s)=\bigcup_{p\in P}\{p\}\times\{0,\ldots,\len(\stack(p))-1\}
|
|---|
| 487 | \]
|
|---|
| 488 | Namely, $(p,i)$ corresponds to the $i^{\text{th}}$ entry in the call
|
|---|
| 489 | stack $\stack(p)$ (where the elements of the stacks are indexed from
|
|---|
| 490 | $0$).
|
|---|
| 491 |
|
|---|
| 492 | Define $\Psi\colon AF(s)\ra \bar{\Delta}$ as follows: given $(p,i)$,
|
|---|
| 493 | let $(\delta,l)$ be the corresponding frame; set $\Psi(p,i)=[\delta]$.
|
|---|
| 494 |
|
|---|
| 495 | % \begin{definition}
|
|---|
| 496 | % A state $s$ is \emph{well-formed} if all of the following hold:
|
|---|
| 497 | % \begin{enumerate}
|
|---|
| 498 | % \item for any $\delta\in\Delta$, at most one child of $\delta$ is not
|
|---|
| 499 | % a function node,
|
|---|
| 500 | % \item the function $\Psi$ is a one-to-one correspondence,
|
|---|
| 501 | % \item any $\delta$ occurring in the top frame of a call stack
|
|---|
| 502 | % is a leaf node.
|
|---|
| 503 | % \end{enumerate}
|
|---|
| 504 | % \end{definition}
|
|---|
| 505 |
|
|---|
| 506 |
|
|---|
| 507 | \section{Jump protocol}
|
|---|
| 508 | \label{sec:jump}
|
|---|
| 509 |
|
|---|
| 510 | % can only jump if \delta is a leaf node.
|
|---|
| 511 | % also no other frame can point to a dyscope between \delta
|
|---|
| 512 | % and the dyscope corresponding to the function scope
|
|---|
| 513 |
|
|---|
| 514 | % in any state, a "region" of the dyscope tree can have at
|
|---|
| 515 | % most one (exactly one?) stack frame pointing into it.
|
|---|
| 516 |
|
|---|
| 517 | % a region in a chain of nodes starting from a dyanmic scope corresonding
|
|---|
| 518 | % to a function scopes and leading down until you reach another
|
|---|
| 519 | % function scope.
|
|---|
| 520 |
|
|---|
| 521 | % whenever you have more than one child in the dynamic tree, all but
|
|---|
| 522 | % 0 or 1 children must be a function scope
|
|---|
| 523 |
|
|---|
| 524 | % every dyscope is owned by at most one frame
|
|---|
| 525 |
|
|---|
| 526 | % can a frame point only to a leaf node? No, but all of its children
|
|---|
| 527 | % must be function nodes
|
|---|
| 528 |
|
|---|
| 529 | % to find out which frame owns which dyscopes:
|
|---|
| 530 |
|
|---|
| 531 | % approach 1: start from a frame. frame owns the node it points to.
|
|---|
| 532 | % move up parents until you hit a function scope and stop.
|
|---|
| 533 | % that is that frame's region. No other frame can point into its
|
|---|
| 534 | % region. Proof: true in initial state, invariant under
|
|---|
| 535 | % call and fork.
|
|---|
| 536 |
|
|---|
| 537 | % invariant: every leaf node in the dyscope tree is pointed
|
|---|
| 538 | % to by the top frame of the call stack of some process
|
|---|
| 539 |
|
|---|
| 540 | % Define a \emph{well-formed state}:
|
|---|
| 541 |
|
|---|
| 542 | % every dyscope node has at most one child which is not a function node
|
|---|
| 543 |
|
|---|
| 544 | % 1-1 correspondence between leaf nodes and top frames of stacks.
|
|---|
| 545 |
|
|---|
| 546 | % Define regions in the dyscope tree. (each region contains one
|
|---|
| 547 | % function node)
|
|---|
| 548 |
|
|---|
| 549 |
|
|---|
| 550 | \newcommand{\lub}{\sigma_{\upsty{lub}}}
|
|---|
| 551 |
|
|---|
| 552 | \begin{figure}[t]
|
|---|
| 553 | \begin{algorithm}[H]
|
|---|
| 554 | \Procedure{$\upsty{jump}(s\colon\State, p\colon\Val_{\proc},
|
|---|
| 555 | l'\colon\Loc)\colon\State$}{%
|
|---|
| 556 | let $(\Delta, \droot, \dparent, \static, \deval, P, \stack)=s$\;
|
|---|
| 557 | let $\delta$ be the dyscope of the last frame on $\stack(p)$\;
|
|---|
| 558 | let $\sigma=\static(\delta)$\;
|
|---|
| 559 | let $\sigma'=\lscope(l')$\;
|
|---|
| 560 | let $\lub$ be the least upper bound of $\sigma$ and
|
|---|
| 561 | $\sigma'$ in the tree $\Sigma$\;
|
|---|
| 562 | let $m$ be the minimum integer such that
|
|---|
| 563 | $\sparent^m(\sigma)=\lub$\;
|
|---|
| 564 | let $\delta_{\upsty{lub}}=\dparent^m(\delta)$\;
|
|---|
| 565 | let $n$ be the minimum integer such that
|
|---|
| 566 | $\sparent^{n}(\sigma')=\lub$\;
|
|---|
| 567 | let $\delta_0,\ldots,\delta_{n-1}$ be $n$ distinct objects not in $\Delta$\;
|
|---|
| 568 | let
|
|---|
| 569 | \( \displaystyle
|
|---|
| 570 | \Delta'=\Delta
|
|---|
| 571 | \cup \{ \delta_0,\ldots,\delta_{n-1} \}
|
|---|
| 572 | %\setminus \{ \dparent^j(\delta)\mid 0\leq j<m\}
|
|---|
| 573 | \)\;
|
|---|
| 574 | define $\dparent'\colon\Delta'\setminus\{\droot\}\ra\Delta'$ by
|
|---|
| 575 | \(
|
|---|
| 576 | \dparent'(\delta')=
|
|---|
| 577 | \begin{cases}
|
|---|
| 578 | \dparent(\delta') & \text{if $\delta'\in\Delta$}\\
|
|---|
| 579 | \delta_{i+1} & \text{if $\delta'=\delta_{i}$ for some $0\leq i<n-1$}\\
|
|---|
| 580 | \delta_{\upsty{lub}} & \text{if $n\geq 1$ and $\delta'=\delta_{n-1}$}
|
|---|
| 581 | \end{cases}
|
|---|
| 582 | \)\;
|
|---|
| 583 | define $\static'\colon\Delta'\ra\Sigma$ by
|
|---|
| 584 | \(
|
|---|
| 585 | \static'(\delta')=
|
|---|
| 586 | \begin{cases}
|
|---|
| 587 | \static(\delta') & \text{if $\delta'\in\Delta$}\\
|
|---|
| 588 | \sparent^i(\sigma') & \text{if $\delta'=\delta_i$ for some $0\leq i<n$}
|
|---|
| 589 | \end{cases}
|
|---|
| 590 | \)\;
|
|---|
| 591 | for $\delta'\in\Delta'$ and $v\in\vars(\static(\delta'))$,
|
|---|
| 592 | let
|
|---|
| 593 | \(
|
|---|
| 594 | \deval'(\delta')(v) =
|
|---|
| 595 | \begin{cases}
|
|---|
| 596 | \deval(\delta')(v) & \text{if $\delta'\in\Delta$}\\
|
|---|
| 597 | \default_t & \text{otherwise}
|
|---|
| 598 | \end{cases}
|
|---|
| 599 | \)\;
|
|---|
| 600 | define $\stack'$ to be the same as $\stack$ except that
|
|---|
| 601 | the last frame on $\stack'(p)$ is replaced with
|
|---|
| 602 | $(\delta_0,l')$ if $n\geq 1$, or with $(\delta_{\upsty{lub}},l')$
|
|---|
| 603 | if $n=0$\;
|
|---|
| 604 | let $s'=(\Delta',\droot,\dparent',\static',\deval',P,\stack')$\;
|
|---|
| 605 | return the result of removing all unreachable dyscopes from $s'$\;
|
|---|
| 606 | }
|
|---|
| 607 | \end{algorithm}
|
|---|
| 608 | \caption{Jump protocol: how the state changes when control moves
|
|---|
| 609 | to a new location within a function. The procedure may only
|
|---|
| 610 | be called if $\func(\sigma)=\func(\sigma')$, i.e., the jump
|
|---|
| 611 | is contained within one function.}
|
|---|
| 612 | \label{fig:jump}
|
|---|
| 613 | \end{figure}
|
|---|
| 614 |
|
|---|
| 615 | When control moves from one location to another within a function's
|
|---|
| 616 | transition system, dyscopes may be added, because you can jump out of
|
|---|
| 617 | scope nests and into new scope nests. The motivating idea is that you
|
|---|
| 618 | have to move up the dyscope tree every time you move past a right
|
|---|
| 619 | curly brace (i.e., leave a scope) and then push on a new scope for
|
|---|
| 620 | each left curly brace you move past. So there is a sequence of upward
|
|---|
| 621 | moves followed by a sequence of pushes to get to the new
|
|---|
| 622 | location. (And either or both sequences could be empty.) At the end,
|
|---|
| 623 | if any dyscopes become unreachable, they are removed from the state.
|
|---|
| 624 |
|
|---|
| 625 | Note however, that we do not assume that scopes are associated to
|
|---|
| 626 | locations in a nice lexical pattern (or any pattern at all). The
|
|---|
| 627 | protocol described here works for any arbitrary assignment of scopes
|
|---|
| 628 | to locations.
|
|---|
| 629 |
|
|---|
| 630 | The precise protocol is described in Figure \ref{fig:jump}. The
|
|---|
| 631 | algorithm shown there takes as input a well-formed state, a process
|
|---|
| 632 | ID, and a location $l'$ for the function that $p$ is currently in.
|
|---|
| 633 | Say the current dyscope for $p$ is $\delta$, and $l'$ is in
|
|---|
| 634 | static scope $\sigma'$. Let $\sigma=\static(\delta)$. Hence the
|
|---|
| 635 | current static scope is $\sigma$ and the new static scope will be $\sigma'$.
|
|---|
| 636 |
|
|---|
| 637 | First, you have to find the \emph{least upper bound} $\lub$ of
|
|---|
| 638 | $\sigma$ and $\sigma'$ in the static scope tree. (Hence $\lub$ is a
|
|---|
| 639 | common anecestor of $\sigma$ and $\sigma'$, and if $\sigma''$ is any
|
|---|
| 640 | common ancestor of $\sigma$ and $\sigma'$ then $\sigma''$ is an
|
|---|
| 641 | ancestor or equal to $\lub$.) Note that the least upper bound must
|
|---|
| 642 | exist since the function scope is a common ancestor of $\sigma$ and
|
|---|
| 643 | $\sigma'$. There is a chain of static scopes from $\sigma$ up to
|
|---|
| 644 | $\lub$ and a corresponding chain
|
|---|
| 645 | $\delta,\dparent(\delta),\ldots,\dparent^m(\delta)$ in the dynamic
|
|---|
| 646 | scope tree. Let $\delta_{\upsty{lub}}=\dparent^m(\delta)$. This
|
|---|
| 647 | will become the least upper bound of $\delta$ and the new dynamic
|
|---|
| 648 | scope corresponding to $\sigma'$ that will be added to the state.
|
|---|
| 649 |
|
|---|
| 650 | Next you add new dyscopes corresponding to the chain of static
|
|---|
| 651 | scopes leading from $\lub$ down to $\sigma'$. The variables in the
|
|---|
| 652 | new scopes are assigned the default values for their respective types.
|
|---|
| 653 | The $\dparent$, $\static$, and $\deval$ maps are adjusted
|
|---|
| 654 | accordingly. Finally, the stack is modified by replacing the last
|
|---|
| 655 | activation frame with a frame referring to the (possibly) new dynamic
|
|---|
| 656 | scope and new location $l'$.
|
|---|
| 657 |
|
|---|
| 658 | This protocol is executed every time control moves from one location
|
|---|
| 659 | to another.
|
|---|
| 660 |
|
|---|
| 661 | Note that in CIVL all jumps stay within a function. There is no
|
|---|
| 662 | way to jump from one function to another (without returning).
|
|---|
| 663 |
|
|---|
| 664 | A small variation is the protocol for moving to the start location of
|
|---|
| 665 | a function when the function is first pushed on the stack. Since the
|
|---|
| 666 | start location is not necessarily in the function scope (it may be a
|
|---|
| 667 | proper descendant of that scope), you have to execute the second half
|
|---|
| 668 | of the protocol to push a sequence of scopes from the function scope
|
|---|
| 669 | to the scope of the start location.
|
|---|
| 670 |
|
|---|
| 671 | \section{Initial State}
|
|---|
| 672 |
|
|---|
| 673 | The \emph{initial state} for $M$ is obtained by creating one process
|
|---|
| 674 | (let $P=\{0\}$) and having it call the root function $f_0$.
|
|---|
| 675 | Hence start with the state $s$ in which $P=\{0\}$, $\ldots$.
|
|---|
| 676 | The initial state is $\upsty{jump}(s,0,\start_{f_0})$.
|
|---|
| 677 |
|
|---|
| 678 | \section{Transitions}
|
|---|
| 679 |
|
|---|
| 680 | The transitions follow the usual ``interleaving'' semantics. Given a
|
|---|
| 681 | state $\sigma$, one defines the set of enabled transitions in $\sigma$
|
|---|
| 682 | as follows. Let $p\in P$. Look at the last frame $(d,l)$ of
|
|---|
| 683 | $\stack(p)$ (i.e., the top of the call stack), assuming the stack is
|
|---|
| 684 | nonempty. Look at all guarded transitions emanating from $l$. For each
|
|---|
| 685 | such transition, evaluate the guard using the valuation formed by
|
|---|
| 686 | taking the union of the valuations of all ancestors of $d$ (including
|
|---|
| 687 | $d$). In other words, follow the standard ``lexical scoping'' protocol
|
|---|
| 688 | to determine the value of any variable that could occur at this point.
|
|---|
| 689 | Those transitions whose guard evaluates to $\emph{true}$ are enabled.
|
|---|
| 690 |
|
|---|
| 691 | For each enabled transition, a new state is generated by executing
|
|---|
| 692 | the transition's statement. For the most part, the semantics are obvious,
|
|---|
| 693 | but there are a few details that are a bit subtle.
|
|---|
| 694 |
|
|---|
| 695 | \section{Calls and Spawns}
|
|---|
| 696 |
|
|---|
| 697 | Both calls and forks of a function $f$ entail the creation of a new
|
|---|
| 698 | frame. First, a new dyscope $d$ corresponding to $\fscope(f)$ is
|
|---|
| 699 | created. To find out where to stick that new scope in the dynamic
|
|---|
| 700 | scope tree, proceed as follows: begin in the dyscope for the
|
|---|
| 701 | process invoking the fork or call and start moving up its parent
|
|---|
| 702 | sequence until you reach the first dyscope $d'$ whose associated
|
|---|
| 703 | static scope is the defining scope of $f$. (You must reach such a
|
|---|
| 704 | scope, or else $f$ would not be visible, and the model would have a
|
|---|
| 705 | syntax error!) Insert $d$ right under $d'$, i.e.,
|
|---|
| 706 | $\dparent(d)=d'$. This preserves the required correspondence between
|
|---|
| 707 | static scopes and dyscopes. Now you move to the start location,
|
|---|
| 708 | using the jump protocol, which may involve the creation of additional
|
|---|
| 709 | dyscopes under $d$. The new frame references the last dynamic
|
|---|
| 710 | scope you created, and the location is the start location of $f$.
|
|---|
| 711 | Variables are given their initial values in all the newly created
|
|---|
| 712 | dyscopes (however that is done).
|
|---|
| 713 |
|
|---|
| 714 | All of that is the same whether the statement is a fork or call. The
|
|---|
| 715 | only difference is what happens next: for a call, the new frame is
|
|---|
| 716 | pushed onto the calling process' call stack. For a fork, a new process
|
|---|
| 717 | is ``created'', i.e., you pick a natural number not in $P$ and
|
|---|
| 718 | add it to $P$, and push the frame onto the new stack. To be totally
|
|---|
| 719 | deterministic, you could pick the least natural number not in $P$.
|
|---|
| 720 |
|
|---|
| 721 | \section{Garbage collection}
|
|---|
| 722 |
|
|---|
| 723 | In a state $s$, a dyscope is unreachable if there is no path
|
|---|
| 724 | from a frame in a call stack to that dyscope (following the
|
|---|
| 725 | $\dparent$ edges). You can remove all unreachable dyscopes.
|
|---|
| 726 |
|
|---|
| 727 | If a process has terminated (has empty stack) and \emph{there are no
|
|---|
| 728 | references to that process} in the state, you can just remove the process
|
|---|
| 729 | from the state.
|
|---|
| 730 |
|
|---|
| 731 | In any state, you can renumber the processes (and update the
|
|---|
| 732 | references accordingly) however you want, to get rid of gaps, put them
|
|---|
| 733 | in a canonic order, etc.
|
|---|
| 734 |
|
|---|