% % 04-semantika-programov.tex % % Developed by Ondrej Jombik % Copyright (c) 2003-2005 Platon Group, http://platon.sk/ % Licensed under terms of GNU General Public License. % All rights reserved. % % Changelog: % 26/02/2003 - created % % $Platon: doc/ztp-zbierka/04-semantika-programov.tex,v 1.10 2007-08-06 04:56:50 nepto Exp $ \chapter{Sémantika programov} \section{Základy sémantiky} \begin{example} % /* loop(b, S_1, S_2) Uvažujme hypotetický iteratívny príkaz~$\cmd{loop}~(b, S_1, S_2)$ definovaný sémantickou rovnicou $$ \M\lb \cmd{loop}~(b, S_1, S_2) \rb ~=~ \UU\{\phi_i\} $$ kde $$ \begin{array}{rcc @{} c @{} l @{} l} \phi_0 & = & \lambda\sigma & ~\cdot~ & \perp & \\ \phi_{i+1} & = & \lambda\sigma & ~\cdot~ & \cmd{if}~ \W\lb b \rb\sigma & ~\cmd{then}~ \phi_i(\M\lb S_1 \rb\sigma) \\ & & & & & ~\cmd{else}~ \M\lb S_2 \rb\sigma \\ \end{array} $$ Na základe základných príkazov (priradenie, kompozícia, vetvenie a cyklus) definujte programový segment $S$ taký, že platí $$ \M\lb \cmd{loop}~(b, S_1, S_2) \rb ~=~ \M\lb S \rb $$ Tvrdenie dokážte. \end{example} % */ \begin{solution} % /* Analýzou sémantickej rovnice v~zadaní vieme vytvoriť programový segment~$S$ skladajúci sa z~častí $S_0$ a $S_2$. % $$ % \begin{array}{ll} % S: & % \left.\begin{array}{@{} l} % \cmd{while}~ b ~\cmd{do} \\ % ~~~~ S_1 \\ % \cmd{od} \\ % \end{array}\right\} S_0 \\ % & S_2; \\ % \end{array} % $$ $$ \begin{array}{ll @{~} l} S: & \cmd{while}~ b ~\cmd{do} & \multirow{3}{*}{$\left.\raisebox{4ex}{}\right\} S_0$} \\ & ~~~~ S_1 \\ & \cmd{od} \\ & S_2; \\ \end{array} $$ Teda pre programový subsegment~$S_0$ platí $$ \M\lb \cmd{while}~ b ~\cmd{do}~ S_1 ~\cmd{od} \rb ~=~ \UU\{\psi_i\} $$ kde $$ \begin{array}{rcc @{} c @{} l @{} l} \psi_0 & = & \lambda\sigma & ~\cdot~ & \perp & \\ \psi_{i+1} & = & \lambda\sigma & ~\cdot~ & \cmd{if}~ \W\lb b \rb\sigma & ~\cmd{then}~ \psi_i(\M\lb S_1 \rb\sigma) \\ & & & & & ~\cmd{else}~ \sigma \\ \end{array} $$ Keďže $\M\lb S_2 \rb\sigma^{'}$ potom pre programový segment~$S$ platí $$ \M\lb S_0; S_2 \rb\sigma ~=~ \lambda\sigma ~\cdot~ \M\lb S_2 \rb(\M\lb S_0 \rb\sigma) $$ Našli sme teda programový segment~$S$. Teraz musíme dokázať ekvivalenciu s~iteratívnym príkazom $\cmd{loop}~(b, S_1, S_2)$. $$ \begin{array}{lcl} \M\lb S \rb & = & \lambda\sigma ~\cdot~ \M\lb S_2 \rb(\M\lb S_0 \rb\sigma) \\ & = & \lambda\sigma ~\cdot~ \M\lb S_2 \rb(\M\lb \cmd{while}~ b ~\cmd{do}~ S_1 ~\cmd{od} \rb\sigma) \\ & = & \lambda\sigma ~\cdot~ \M\lb S_2 \rb(\UU\{\psi_i\}\sigma) \\ \end{array} $$ Čiže musíme dokázať nasledujúce tvrdenie. $$ \M\lb S_2 \rb(\UU\{\psi_i\}) ~=~ \UU\{\phi_i\} $$ Rovnosť rozložíme na dva možné prípady. \begin{enumerate} \item Nech $\UU\{\phi_i\} = \perp$. To znamená, že $\forall \phi_i = \perp$. Potom $\M\lb S_2 \rb(\UU\{\psi_i\}) = \perp$. Kedy bude $\phi_i$~$\perp$? Ak $i=0$ alebo $\forall i>0: \W\lb b \rb\sigma = true$. Rovnako to platí aj pri~$\psi$. Takže $\M\lb S_2 \rb\perp = \perp$. \item Nech $\UU\{\phi_i\} \ne \perp$. Potom $i\ne0$ resp. $i>0$. Určite $\exists k: k 2\} & \equiv & \cmd{if}~ x = 0\\ & & \cmd{then}~ 0\\ & & \cmd{else} \begin{array}[t]{l} \cmd{if} \perp = 0\\ \cmd{then}~ 0\\ \cmd{else}~(\cmd{if} \perp = 1 ~\cmd{then}~ 0 ~\cmd{else} \perp \cmd{fi})\\ \cmd{fi} \end{array}\\ & & \cmd{fi}\\ \tau^3\{x > 2\} & \equiv & \cmd{if}~ x = 0 ~\cmd{then}~ 0 ~\cmd{else} \perp \cmd{fi} \end{array} $$ Skúsme teraz $\tau^4$: $$ \begin{array}{lcl} \tau^4 & \equiv & \cmd{if}~ x = 0\\ & & \cmd{then}~ 0\\ & & \cmd{else}~(\cmd{if}~[\cmd{if}~ x = 1 ~\cmd{then}~ 0 ~\cmd{else}~ 0 ~\cmd{fi}] = 0 ~\cmd{then}~ 0 ~\cmd{else}~ 0 ~\cmd{fi})\\ & & \cmd{fi}\\ \tau^4 & \equiv & \cmd{if}~ x = 0 ~\cmd{then}~ 0 ~\cmd{else}~ 0 ~\cmd{fi} \end{array} $$ %Zdá sa, že to už je pevný bod. Overme to: % %$$ %\begin{array}{rcl} %f_P & \equiv & \cmd{if}~ x = 0 ~\cmd{then}~ 0 ~\cmd{else}~ (\cmd{if}~ [\cmd{if}~ x = 1 ~\cmd{then}~ 0 ~\cmd{else}~ 0 %~\cmd{fi}] = 0 ~\cmd{then}~ 0 ~\cmd{else}~ 0 ~\cmd{fi}) ~\cmd{fi} \equiv\\ %& \equiv & \cmd{if}~ x = 0 ~\cmd{then}~ 0 ~\cmd{else}~ 0 ~\cmd{fi} %\end{array} %$$ Vyzerá to tak, že pre $x \ge 0$ je to $0$, inak $\perp$. A to už je pevný bod $f_P$: $$ \begin{array}{rcl} f_P & \equiv & \cmd{if}~ x \ge 0 ~\cmd{then}~ 0 ~\cmd{else} \perp \cmd{fi} \end{array} $$ \end{solution} % */ \begin{example} % /* Uvažujme rovnakú funkciu $f$ ako v predchádzajúcom príklade. Nech $g(x)$ je jej pevný bod. Ukážte, že je silne ekvivalentný s~$f_P(x)$. \end{example} % */ \begin{solution} % /* Fixpointovou indukciou dokážeme, že pre $x \ge 0$: $$ f_P(x) \sqsubseteq g(x) $$ Označme $$ g(x) \equiv \cmd{if}~ x \ge 0 ~\cmd{then}~ 0 ~\cmd{else} \perp \cmd{fi} $$ Podľa fixpointovej indukcie stačí dokázať, že $\tau[g] \sqsubseteq g$, čiže: $$ \begin{array}{lcl} \left( \begin{array}{lcl} \cmd{if}~ x = 0\\ \cmd{then}~ 0\\ \cmd{else}~(\cmd{if}~[\cmd{if}~ x - 1 \ge 0 ~\cmd{then}~ 0 ~\cmd{else} \perp \cmd{fi}] \ge 0 ~\cmd{then}~ 0 ~\cmd{else} \perp \cmd{fi})\\ \cmd{fi} \end{array} \right) & \sqsubseteq & \left( \begin{array}{l} \cmd{if}~ x = 0\\ \cmd{then}~ 0\\ \cmd{else} \perp\\ \cmd{fi} \end{array} \right) \end{array} $$ Rozdelíme to na nasledujúce prípady: \begin{enumerate} \item $x = 0$ $$ \begin{array}{lcl} \tau[g](x) & = & 0\\ \tau[g](x) & = & g(x) \end{array} $$ \item $x - 1 \ge 0 \equiv x \ge 1$ $$ \begin{array}{lcl} \tau[g](x) & = & \cmd{if}~ x = 0\\ & & \cmd{then}~ 0\\ & & \cmd{else}~(\cmd{if}~ 0 \ge 0 ~\cmd{then}~ 0 ~\cmd{else} \perp \cmd{fi})\\ & & \cmd{fi}\\ \tau[g](x) & = & \cmd{if}~ x = 0 ~\cmd{then}~ 0 ~\cmd{else}~ 0 ~\cmd{fi}\\ \tau[g](x) & = & g(x) \end{array} $$ \end{enumerate} Teda platí $f_P \sqsubseteq g$. A navyše pre $x < 0$ platí $g(x) \sqsubseteq f_P(x)$, pretože $g(x) = \perp$. Celkovo platí $$ (g \sqsubseteq f_P) \land (f_P \sqsubseteq g) ~\Longrightarrow~ f_P \equiv g $$ Teda $g$ je najmenší pevný bod. \end{solution} % */ \begin{example} % /* Máme funkciu: $$ \phi(x): \cmd{if}~ x > 0 ~\cmd{then}~ \phi(\phi(x-1)) ~\cmd{else}~ x ~\cmd{fi} $$ pre $x \in \mathbb{N}$. Nájdite pevný bod tejto funkcie. \end{example} % */ \begin{solution} % /* Najskôr si rozpíšeme čo to vlastne robí: $$ \begin{array}[t]{rcl} \phi(0) & = & \cmd{if}~ 0 > 0 ~\cmd{then} \perp \cmd{else}~ 0 ~\cmd{fi}\\ & = & 0\\ \phi(1) & = & \cmd{if}~ 1 > 0 ~\cmd{then}~ \phi(0) ~\cmd{else}~ 1 ~\cmd{fi}~ =\\ & = & \cmd{if}~ 1 > 0 ~\cmd{then}~ 0 ~\cmd{else}~ 1 ~\cmd{fi}~ =\\ & = & 0\\ \phi(2) & = & \cmd{if}~ 2 > 0 ~\cmd{then}~ \phi(1) ~\cmd{else}~ 2 ~\cmd{fi}~ =\\ & = & \cmd{if}~ 2 > 0 ~\cmd{then}~ (\cmd{if}~ 1 > 0 ~\cmd{then}~ 0 ~\cmd{else}~ 1 ~\cmd{fi}) ~\cmd{else}~ 2 ~\cmd{fi}~ =\\ & = & \cmd{if}~ 2 > 0 ~\cmd{then}~ 0 ~\cmd{else}~ 2 ~\cmd{fi}~ =\\ & = & 0 \end{array} $$ Riešenie: $$ \begin{array}[t]{lcl} \tau^0 & \equiv & \Omega\\ \tau^1 & \equiv & \cmd{if}~ x > 0 ~\cmd{then} \perp \cmd{else}~ x ~\cmd{fi}\\ \tau^2 & \equiv & \cmd{if}~ x > 0\\ & & \cmd{then} \begin{array}[t]{l} \cmd{if}~[\cmd{if}~ x > 1 ~\cmd{then} \perp \cmd{else}~ x - 1 ~\cmd{fi}] > 0\\ \cmd{then} \perp\\ \cmd{else}~(\cmd{if}~ x > 1 ~\cmd{then} \perp \cmd{else}~ x - 1 ~\cmd{fi})\\ \cmd{fi} \end{array}\\ & & \cmd{else}~ ?\\ & & \cmd{fi}\\ \tau^2\{x > 1\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if} \perp > 0 ~\cmd{then} \perp \cmd{else} \perp \cmd{fi}) ~\cmd{else}~ x ~\cmd{fi}~ \equiv\\ & \equiv & \cmd{if}~ x > 0 ~\cmd{then} \perp \cmd{else}~ x ~\cmd{fi}~ \equiv\\ & \equiv & \tau^1\\ \tau^2\{x \le 1\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 1 ~\cmd{then} \perp \cmd{else}~ x - 1 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi}~ \equiv\\ & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 1 ~\cmd{else}~ x ~\cmd{fi} \end{array} $$ A teraz pre $\tau^3$: $$ \begin{array}[t]{lcl} \tau^3 &\equiv & \cmd{if}~ x > 0\\ & & \cmd{then} \begin{array}[t]{l} \cmd{if}~ [\cmd{if}~ x > 1 ~\cmd{then}~ x - 2 ~\cmd{else}~ x - 1 ~\cmd{fi}] > 0\\ \cmd{then}~ [\cmd{if}~ x > 1 ~\cmd{then}~ x - 2 ~\cmd{else}~ x - 1 ~\cmd{fi}] - 1\\ \cmd{else}~ (\cmd{if}~ x > 1 ~\cmd{then}~ x - 2 ~\cmd{else}~ x - 1 ~\cmd{fi})\\ \cmd{fi} \end{array}\\ & & \cmd{else}~ x\\ & & \cmd{fi}\\ \tau^3\{x > 1\} &\equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 2 ~\cmd{then}~ x - 3 ~\cmd{else}~ x - 2 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi}\\ \tau^3\{x \le 1\} &\equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 1 ~\cmd{then}~ x - 2 ~\cmd{else}~ x - 1 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi} \equiv\\ &\equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 2 ~\cmd{else}~ x ~\cmd{fi} \end{array} $$ Vznikli nám tri možnosti $\tau^3_1$, $\tau^3_2$ a $\tau^3_3$: $$ \begin{array}{lcl} \tau^3_1 & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 2 ~\cmd{then}~ x - 3 ~\cmd{else}~ x - 2 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi}\\ \tau^3_2\{x > 2\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 3 ~\cmd{else}~ x ~\cmd{fi} ~\equiv~ \tau^3_1\\ \tau^3_2\{x \le 2\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 2 ~\cmd{else}~ x ~\cmd{fi} ~\equiv~ \tau^3_1\\ \tau^3_3 & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 2 ~\cmd{else}~ x ~\cmd{fi} \end{array} $$ Vidíme, že prípad $\tau^3_2$ je totožný s~$\tau^3_1$. Takže ďalej nám stačí rozvinúť len možnosti $\tau^3_1$ a $\tau^3_3$. Začneme s možnosťou $\tau[\tau^3_3]$: $$ \begin{array}{lclcl} \tau^4 & \equiv & \tau[\tau^3_3] & \equiv & \cmd{if}~ x > 0\\ & & & & \cmd{then} \begin{array}[t]{l} \cmd{if}~ [\cmd{if}~ x > 1 ~\cmd{then}~ x - 3 ~\cmd{else}~ x - 1 ~\cmd{fi}] > 0\\ \cmd{then}~ [\cmd{if}~ x > 1 ~\cmd{then}~ x - 3 ~\cmd{else}~ x - 1 ~\cmd{fi}] - 2\\ \cmd{else}~ (\cmd{if}~ x > 1 ~\cmd{then}~ x - 3 ~\cmd{else}~ x - 1 ~\cmd{fi})\\ \cmd{fi} \end{array}\\ & & & & \cmd{else}~ x\\ & & & & \cmd{fi} \end{array} $$ Čiže konkrétne vyjadrené: $$ \begin{array}{lcl} \tau^4\{x > 1\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 3 ~\cmd{then}~ x - 5 ~\cmd{else}~ x - 3 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi}\\ \tau^4\{x > 1\}\{x > 3\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 5 ~\cmd{else}~ x ~\cmd{fi}\\ \tau^4\{x > 1\}\{x \le 3\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 3 ~\cmd{else}~ x ~\cmd{fi}\\ \tau^4\{x \le 1\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 1 ~\cmd{then}~ x - 3 ~\cmd{else}~ x - 1 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi}\\ & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 1 ~\cmd{else}~ x ~\cmd{fi} \end{array} $$ Pokračujeme s možnosťou $\tau[\tau^3_1]$: $$ \begin{array}{lclcl} \tau^4 & \equiv & \tau[\tau^3_1] & \equiv & \cmd{if}~ x > 0\\ & & & & \cmd{then} \begin{array}[t]{l} \cmd{if}~ [\cmd{if}~ x > 1 ~\cmd{then}~ x - 4 ~\cmd{else}~ x ~\cmd{fi}] > 0\\ \cmd{then}~ [\cmd{if}~ x > 1 ~\cmd{then}~ x - 4 ~\cmd{else}~ x ~\cmd{fi}] - 3\\ \cmd{else}~ (\cmd{if}~ x > 1 ~\cmd{then}~ x - 4 ~\cmd{else}~ x ~\cmd{fi})\\ \cmd{fi} \end{array}\\ & & & & \cmd{else}~ x\\ & & & & \cmd{fi} \end{array} $$ Aj toto konkrétne vyjadríme: $$ \begin{array}{lcl} \tau^4\{x > 1\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 4 ~\cmd{then}~ x - 7 ~\cmd{else}~ x - 4 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi}\\ \tau^4\{x > 1\}\{x > 4\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 7 ~\cmd{else}~ x ~\cmd{fi}\\ \tau^4\{x > 1\}\{x \le 4\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 4 ~\cmd{else}~ x ~\cmd{fi}\\ \tau^4\{x \le 1\} & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 0 ~\cmd{then}~ x - 3 ~\cmd{else}~ x ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi}\\ & \equiv & \cmd{if}~ x > 0 ~\cmd{then}~ x - 3 ~\cmd{else}~ x ~\cmd{fi} \end{array} $$ Takto postupne konštruujeme aproximácie. Evidentne vyzerajú dobre, v~každom kroku nám pribudne $+1$ v niektorej z nich. Aký je teda pevný bod? $$ f_P \equiv \cmd{if}~ x > 0 ~\cmd{then}~ 0 ~\cmd{else}~ x ~\cmd{fi} $$ Čiže $$ \begin{array}{cl} f_P: & \cmd{if}~ x > 0\\ & \cmd{then} \begin{array}[t]{l} \cmd{if}~ [\cmd{if}~ x > 1 ~\cmd{then}~ 0 ~\cmd{else}~ x - 1 ~\cmd{fi}] > 0\\ \cmd{then}~ 0\\ \cmd{else}~ (\cmd{if}~ x > 1 ~\cmd{then}~ 0 ~\cmd{else}~ x - 1 ~\cmd{fi})\\ \cmd{fi} \end{array}\\ & \cmd{else}~ x\\ & \cmd{fi} \end{array} $$ sa nám rozloží na tri prípady: \begin{enumerate} \item $ \begin{array}[t]{rcl} x > 1 & \Rightarrow & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ 0 > 0 ~\cmd{then}~ 0 ~\cmd{else}~ 0 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi} =\\ & = & \cmd{if}~ x > 0 ~\cmd{then}~ 0 ~\cmd{else}~ x ~\cmd{fi} \end{array} $ \item $ \begin{array}[t]{rcl} x = 1 & \Rightarrow & \cmd{if}~ x > 0 ~\cmd{then}~ (\cmd{if}~ x > 1 ~\cmd{then}~ 0 ~\cmd{else}~ x - 1 ~\cmd{fi}) ~\cmd{else}~ x ~\cmd{fi} =\\ & = & \cmd{if}~ x > 0 ~\cmd{then}~ 0 ~\cmd{else}~ x ~\cmd{fi} \end{array} $ \item $ \begin{array}[t]{rcl} x > 0 & \Rightarrow & \cmd{if}~ x > 0 ~\cmd{then}~ 0 ~\cmd{else}~ x ~\cmd{fi} =\\ & = & \cmd{if}~ x > 0 ~\cmd{then}~ 0 ~\cmd{else}~ x ~\cmd{fi} \end{array} $ \end{enumerate} Ukázali sme, že $f_P$ je pevný bod. %Je to ten posledný tretí prípad $0 - 1 = \perp$, pretože $x \in \mathbb{N}$. \end{solution} % */ \begin{example} % /* Uvažujme rovnakú funkciu $f$ ako v predchádzajúcom príklade. Nech $g(x)$ je jej pevný bod. Ukážte, že je silne ekvivalentný s~$f_P(x)$. \end{example} % */ \begin{solution} % /* Fixpointovou indukciou dokážeme, že pre $x \ge 0$: $$ f_P(x) \sqsubseteq g(x) $$ Označme $$ g(x) \equiv \cmd{if}~ x > 0 ~\cmd{then}~ 0 ~\cmd{else}~ x ~\cmd{fi} $$ Podľa fixpointovej indukcie stačí dokázať, že $\tau[g] \sqsubseteq g$, čiže: $$ \begin{array}{lcl} \left( \begin{array}{lcl} \cmd{if}~ x > 0\\ \cmd{then} \begin{array}[t]{l} \cmd{if}~[\cmd{if}~ x - 1 > 0 ~\cmd{then}~ 0 ~\cmd{else}~ x - 1 ~\cmd{fi}] > 0\\ \cmd{then}~ 0\\ \cmd{else}~ (\cmd{if}~ x - 1 > 0 ~\cmd{then}~ 0 ~\cmd{else}~ x - 1 ~\cmd{fi})\\ \cmd{fi} \end{array}\\ \cmd{else}~x\\ \cmd{fi} \end{array} \right) & \sqsubseteq & \left( \begin{array}{l} \cmd{if}~ x > 0\\ \cmd{then}~ 0\\ \cmd{else}~ x\\ \cmd{fi} \end{array} \right) \end{array} $$ Rozdelíme to na nasledujúce prípady: \begin{enumerate} \item $x = 0: \tau[g](x) = 0 = g(x)$ \item $x > 0: \tau[g](x) = 0 = g(x)$ \end{enumerate} Teda platí $f_P \sqsubseteq g$. A navyše pre $x < 0$ platí $g(x) = x$, potom musí $f(x) = x$ aby platilo $g \sqsubseteq f_P$. Celkovo platí $$ (g \sqsubseteq f_P) \land (f_P \sqsubseteq g) ~\Longrightarrow~ f_P \equiv g $$ Teda $g$ je najmenší pevný bod. \end{solution} % */ % vim: ts=4 tw=100 % vim600: fdl=0 fdm=marker fdc=0 fmr=/*,*/