diff --git a/thesis.tex b/thesis.tex index 1c52352..68636b1 100644 --- a/thesis.tex +++ b/thesis.tex @@ -6087,15 +6087,15 @@ The signature of file creation and opening is unsurprisingly comprised of two operations. % \[ - \dec{FileCO} \defas \{\UCreate : \String \opto \Int; \UOpen : \String \opto \Option~\Int\} + \dec{FileCO} \defas \{\UCreate : \String \opto \Option~\Int; \UOpen : \String \opto \Option~\Int\} \] % The implementation of file creation and opening follows the same pattern as the implementation of reading and writing. As before, we implement a primitive routine for each operation that interacts -directly with the file system structure. We start with the -implementation of primitive file opening function as file creation -function depends on this function. +directly with the file system structure. We first implement the +primitive file opening function as the file creation function depends +on this function. % \[ \bl @@ -6103,18 +6103,93 @@ function depends on this function. \fopen\,\Record{fname;fs} \defas \lookup\,\Record{fname; fs.dir} \el \] +% +Opening a file in the file system simply corresponds to returning the +i-node index associated with the filename in the directory table. +The \UNIX{} file create command does one of two things depending on +the state of the file system. If the create command is provided with +the name of a file that is already present in the directory, then the +system truncates the file, and returns the file descriptor for the +file. Otherwise the system allocates a new empty file and returns its +file descriptor~\cite{RitchieT74}. To check whether a file already +exists in the directory we need a function $\dec{has}$ that given a +filename and the file system state returns whether there exists a file +with the given name. This function can be built completely generically +from the functions we already have at our disposal. +% +\[ + \bl + \dec{has} : \Record{\alpha;\List~\Record{\alpha;\beta}} \to \Bool\\ + \dec{has}\,\Record{k;xs} \defas \faild\,\Record{\False;(\lambda\Unit.\lookup\,\Record{k;xs};\True)} + \el +\] +% +The function $\dec{has}$ applies $\lookup$ under the failure handler +with default value $\False$. If $\lookup$ returns successfully then +its result is ignored, and the computation returns $\True$, otherwise +the computation returns the default value $\False$. +% +With this function we can implement the semantics of create. +% \[ \bl \fcreate : \Record{\String;\FileSystem} \to \Record{\Int;\FileSystem} \eff \{\Fail : \UnitType \opto \Zero\}\\ \fcreate\,\Record{fname;fs} \defas \ba[t]{@{}l} - \Let\;inode \revto \lookup\,\Record{ino; fs.ilist}\;\In\\ - \lookup\,\Record{inode.loc; fs.dreg} + \If\;\dec{has}\,\Record{fname;fs.dir}\;\Then\\ + \quad\bl + \Let\;ino \revto \fopen\,\Record{fname;fs}\;\In\\ + \Let\;inode \revto \lookup\,\Record{ino;fs}\;\In\\ + \Let\;dreg' \revto \modify\,\Record{inode.loc; \strlit{}; fs.dreg}\;\In\\ + \Record{ino;\Record{fs\;\With\;dreg = dreg'}} + \el\\ + \Else\\ + \quad\bl + \Let\;loc \revto fs.lnext \;\In\\ + \Let\;dreg \revto \Record{loc; \strlit{}} \cons fs.dreg\;\In\\ + \Let\;ino \revto fs.inext \;\In\\ + \Let\;inode \revto \Record{loc=loc;lno=1}\;\In\\ + \Let\;ilist \revto \Record{ino;inode} \cons fs.ilist \;\In\\ + \Let\;dir \revto \Record{fname; ino} \cons fs.dir \;\In\\ + \Record{ino;\Record{ + \bl + dir=dir;ilist=ilist;dreg=dreg;\\ + lnext=loc+1;inext=ino+1}} + \el + \el \el \el \] % +The $\Then$-branch accounts for the case where the filename $fname$ +already exists in the directory. First we retrieve the i-node for the +file to obtain its location in the data region such that we can +truncate the file contents. +% +The branch returns the i-node index along with the modified file +system. The $\Else$-branch allocates a new empty file. First we +allocate a location in the data region by copying the value of +$fs.lnext$ and consing the location and empty string onto +$fs.dreg$. The next three lines allocates the i-node for the file in a +similar fashion. The second to last line associates the filename with +the new i-node. The last line returns the identifier for the i-node +along with the modified file system, where the next location ($lnext$) +and next i-node identifier ($inext$) have been incremented. +% +It is worth noting that the effect signature of $\dec{has}$ mentions +$\Fail$ even though it will (most likely) never fail. It is present in +the effect row due to the use of $\lookup$ in the $\Then$-branch. This +application of $\lookup$ can only fail if the file system is in an +inconsistent state, where the index $ino$ has become stale. The +$\dec{f}$-family of functions have been carefully engineered to always +leave the file system in a consistent state. +% + +Now we can implement the semantics for the $\UCreate$ and $\UOpen$ +effectful operations. The implementation is similar to the +implementation of $\fileRW$. +% \[ \bl \fileAlloc : (\UnitType \to \alpha \eff \dec{FileCO}) \to \alpha \eff \State~\FileSystem\\ @@ -6125,10 +6200,10 @@ function depends on this function. \Return\;res &\mapsto& res\\ \OpCase{\UCreate}{fname}{resume} &\mapsto& \bl - \Let\;ino \revto \faild\,\Record{-1; \lambda\Unit.\\ + \Let\;ino \revto \faild\,\Record{\None; \lambda\Unit.\\ \quad\bl \Let\;\Record{ino;fs} = \fcreate\,\Record{\,fname;\Uget\,\Unit}\\ - \In\;\Uput~fs;\,ino} + \In\;\Uput~fs;\,\Some~ino} \el\\ \In\; resume\,ino \el\\ @@ -6143,25 +6218,25 @@ function depends on this function. \el \] % -There is no file close operation in \fsname{}, because it would be a no-op. -The composition of $\fileRW$ and $\fileAlloc$ give a semantics to file -i/o. -% -\[ - \bl - \fileIO : (\UnitType \to \alpha \eff \{\dec{FileCO};\dec{FileRW}\}) \to \alpha \eff \State~\FileSystem \\ - \fileIO~m \defas \dec{fileCO}\,(\lambda\Unit. \dec{fileRW}\,m) - \el -\] -% -The two handlers may as well be implemented as a single monolithic -handler, since they implement different operations, return the same -value, and make use of the same state cell. In practice a monolithic -handler may have better performance. However, a sufficient clever -compiler would be able to use the fusion technique of \citet{WuS15} to -fuse the two handlers into one, and thus allow modular composition -without remorse. + +% The composition of $\fileRW$ and $\fileAlloc$ give a semantics to file +% i/o. +% % +% \[ +% \bl +% \fileIO : (\UnitType \to \alpha \eff \{\dec{FileCO};\dec{FileRW}\}) \to \alpha \eff \State~\FileSystem \\ +% \fileIO~m \defas \dec{fileCO}\,(\lambda\Unit. \dec{fileRW}\,m) +% \el +% \] +% % +% The two handlers may as well be implemented as a single monolithic +% handler, since they implement different operations, return the same +% value, and make use of the same state cell. In practice a monolithic +% handler may have better performance. However, a sufficient clever +% compiler would be able to use the fusion technique of \citet{WuS15} to +% fuse the two handlers into one, and thus allow modular composition +% without remorse. \paragraph{Stream redirection} % @@ -6172,12 +6247,16 @@ without remorse. \redirect : \bl \Record{\UnitType \to \alpha \eff \{\Write : \Record{\Int;\String} \opto \UnitType\}; \String}\\ - \to \alpha \eff \{\UCreate : \String \opto \Int;\Write : \Record{\Int;\String} \opto \UnitType\} + \to \alpha \eff \{\UCreate : \String \opto \Option~\Int;\Exit : \Int \opto \Zero;\Write : \Record{\Int;\String} \opto \UnitType\} \el\\ m~\redirect~fname \defas \ba[t]{@{}l} - \Let\;ino \revto \Ucreate~fname\;\In\\ - \Handle\;m\,\Unit\;\With\\ + \Let\;ino \revto \Case\;\Do\;\UCreate~fname\;\{ + \ba[t]{@{~}l@{~}c@{~}l} + \None &\mapsto& \exit\,(-1)\\ + \Some~ino &\mapsto& ino\} + \ea\\ + \In\;\Handle\;m\,\Unit\;\With\\ ~\ba{@{~}l@{~}c@{~}l} \Return\;res &\mapsto& res\\ \OpCase{\Write}{\Record{\_;cs}}{resume} &\mapsto& resume\,(\Do\;\Write\,\Record{ino;cs}) @@ -6250,14 +6329,14 @@ We can now plug everything together. \Record{2; \ba[t]{@{}l@{}l} \texttt{"}&\texttt{To be, or not to be,\nl{}that is the question:\nl{}}\\ - &\texttt{Whether 'tis nobler in the mind to suffer\nl{}"}}; + &\texttt{Whether 'tis nobler in the mind to suffer\nl{}"}}, \ea\\ \Record{1; \ba[t]{@{}l@{}l} \texttt{"}&\texttt{UNIX is basically a simple operating system, }\\ - &\texttt{but you have to be a genius to understand the simplicity.\nl{"}}}; + &\texttt{but you have to be a genius to understand the simplicity.\nl{"}}}, \ea\\ - \Record{0; \strlit{}}]}} + \Record{0; \strlit{}}]; lnext=3; inext=3}}\\ \ea \ea \ea\\