├── README.md ├── doc ├── algorithm.sty ├── algorithmicx.sty ├── algpseudocode.sty ├── clp_report.bib ├── clp_report.pdf ├── clp_report.tex ├── listings.dtx └── pl2clp2.pl └── src └── type.pl /README.md: -------------------------------------------------------------------------------- 1 | hm_prolog 2 | ========= 3 | 4 | A Hindley-Milner type inference implementation in Prolog 5 | -------------------------------------------------------------------------------- /doc/algorithm.sty: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%% ALGORITHMS STYLE %%%%%%%%%%% 2 | % This style defines an environment for algorithms with the following 3 | % features: 4 | % 5 | % 1) Defines an Theorem like environment (not exactly one) for 6 | % algorithms called ``algorithm''. 7 | % \begin{algorithm}{NAME} ... \end{algorithm} 8 | % NAME is the NAME of the algorithm. 9 | % Algorithms are numbered using a counter called ``algorithm''. 10 | % 11 | % 2) Inside this environment, the following commands are defined. 12 | % 13 | % \= Put the small left arrow commonly used for assignment. 14 | % 15 | % \invariant{INVARIANT} Use to describe invariants, put its parameter 16 | % between ``{}'' in math mode. 17 | % 18 | % \begin{Block} ... \end{Block} Environment use to start a indented 19 | % block of instructions \end{Block} put 20 | % an ``end'' to close the block. 21 | % 22 | % \nextBlock{SEPARATOR} Inside a Block, it allows to put a separator 23 | % of parts of the indented block. Usefull for 24 | % constructions like ``IF..THEN..ELSE..END'' 25 | % i.e. If cond then 26 | % \begin{Block} 27 | % then part 28 | % \nextBlock{else} 29 | % else part 30 | % \end{Block} 31 | % 32 | % 3) \Blockindent and \algorithmindent are length that specify the 33 | % indentention of Blocks and of the algorithm resp. 34 | % 35 | % 4) Instructions are separated by ``\\'', ``\par'' or by leaving a 36 | % blank line. Before an ``\end{Block}'' a ``\\'' can't be used. 37 | % 38 | % 39 | % Created by Jose Alberto Fernandez R. 40 | % e-mail: alberto@cs.umd.edu 41 | % 42 | 43 | % 44 | \newcounter{algorithm} 45 | \newtheorem{Alg@orithm}[algorithm]{Algorithm} 46 | % Invariants 47 | \newcommand{\inv@ariant}[1]{\mbox{$\{#1\}$}} 48 | % Steps environment 49 | \newenvironment{ste@ps}[1]{ 50 | \begin{list}{} 51 | {\setlength\labelsep{0in} 52 | \addtolength\partopsep\topsep 53 | \addtolength\partopsep\parsep 54 | \setlength\parsep{0in} 55 | \setlength\topsep{0in} 56 | \setlength\itemsep{0in} 57 | \setlength\labelwidth{0in} 58 | \setlength\rightmargin{0in} 59 | \setlength\leftmargin{#1}} 60 | }{ 61 | \end{list} 62 | } 63 | 64 | % Block environment 65 | % Indentation of the Block 66 | \newlength{\Blockindent} 67 | % NextBlock command 68 | \newcommand{\next@Block}[1]{ 69 | \end{ste@ps} 70 | #1 71 | \begin{ste@ps}{\Blockindent} 72 | \item 73 | } 74 | 75 | \newenvironment{Blo@ck}{ 76 | \let\nextBlock\next@Block 77 | \begin{ste@ps}{\Blockindent} 78 | \item 79 | }{ 80 | \end{ste@ps} 81 | end 82 | } 83 | % Algorithm environment 84 | % Assign command 85 | \newcommand{\ass@ign}{\mbox{$\leftarrow$}} 86 | % Indentation of the algorithm 87 | \newlength{\algorithmindent} 88 | % Algorithm definition 89 | \newenvironment{algorithm}[1]{ 90 | \let\=\ass@ign 91 | \let\invariant\inv@ariant 92 | \let\Block\Blo@ck 93 | \let\endBlock\endBlo@ck 94 | \begin{Alg@orithm} #1 95 | \rm\par 96 | \begin{ste@ps}{\algorithmindent} 97 | \item 98 | }{ 99 | \end{ste@ps} 100 | \bf end 101 | \end{Alg@orithm} 102 | } 103 | 104 | % Setting default indentation 105 | \setlength{\algorithmindent}{1em} 106 | \setlength{\Blockindent}{2em} 107 | 108 | % End of algorithm.sty 109 | -------------------------------------------------------------------------------- /doc/algorithmicx.sty: -------------------------------------------------------------------------------- 1 | % ALGORITHMIC STYLE -- Released 27 APR 2005 2 | % for LaTeX version 2e 3 | % 4 | % Copyright Szasz Janos 5 | % E-mail szaszjanos@users.sourceforge.net 6 | % 7 | % 8 | % *** INITIALISING *** 9 | % 10 | % 11 | \NeedsTeXFormat{LaTeX2e} 12 | \ProvidesPackage{algorithmicx}[2005/04/27 v1.2 Algorithmicx] 13 | \RequirePackage{ifthen} 14 | \typeout{Document Style algorithmicx 1.2 - a greatly improved `algorithmic' style} 15 | % 16 | \newcounter{ALG@line} 17 | \newcounter{ALG@rem} 18 | \newcounter{ALG@nested} 19 | \newlength{\ALG@tlm} 20 | \newlength{\ALG@thistlm} 21 | \newcounter{ALG@Lnr}% the number of defined languages 22 | \setcounter{ALG@Lnr}{0} 23 | \newcounter{ALG@blocknr}% the number of defined blocks 24 | \setcounter{ALG@blocknr}{0} 25 | \newcounter{ALG@storecount}% number of stored but not restored algorithmic environments 26 | \setcounter{ALG@storecount}{0} 27 | \newcounter{ALG@tmpcounter}% only to decrement things 28 | \newlength\ALG@tmplength% 29 | %\def\algorithmicnoindent{-\ALG@tlm} 30 | % \def\algbackskipbegin{\hskip\ALG@ctlm} 31 | %\def\algbackskip{\hskip-\ALG@thistlm} 32 | %\def\algbackskipend{\hskip-\ALG@tlm} 33 | \def\ALG@defaultindent{\algorithmicindent} 34 | % 35 | % conditional states 36 | % 37 | \def\ALG@newcondstate#1% 38 | {% 39 | \expandafter\edef\csname ALG@x@#1\endcsname% 40 | {\expandafter\noexpand\csname @@ALG@x@#1\endcsname}% 41 | }% 42 | \ALG@newcondstate{notext}% 43 | \ALG@newcondstate{default}% 44 | % 45 | % 46 | % *** ALGORITHMIC *** 47 | % 48 | % 49 | \newcommand\ALG@beginblock[1]% #1 - indentation 50 | {% 51 | \ALG@thistlm\ALG@tlm% 52 | \addtolength\ALG@tlm{#1}% 53 | \addtocounter{ALG@nested}{1}% 54 | \setlength\ALG@tmplength{#1}% 55 | \expandafter\edef\csname ALG@ind@\theALG@nested\endcsname{\the\ALG@tmplength}% 56 | }% 57 | \newcommand\ALG@endblock% 58 | {% 59 | \addtolength\ALG@tlm{-\csname ALG@ind@\theALG@nested\endcsname}% 60 | \addtocounter{ALG@nested}{-1}% 61 | \ALG@thistlm\ALG@tlm% 62 | }% 63 | % 64 | % algorithmic environment 65 | % 66 | \def\ALG@step% 67 | {% 68 | \addtocounter{ALG@line}{1}% 69 | \addtocounter{ALG@rem}{1}% 70 | \ifthenelse{\equal{\arabic{ALG@rem}}{\ALG@numberfreq}}% 71 | {\setcounter{ALG@rem}{0}\alglinenumber{\arabic{ALG@line}}}% 72 | {}% 73 | }% 74 | \newenvironment{algorithmic}[1][0]% 75 | {% 76 | \edef\ALG@numberfreq{#1}% 77 | \def\@currentlabel{\theALG@line}% 78 | % 79 | \setcounter{ALG@line}{0}% 80 | \setcounter{ALG@rem}{0}% 81 | % 82 | \let\\\algbreak% 83 | % 84 | \expandafter\edef\csname ALG@currentblock@\theALG@nested\endcsname{0}% 85 | \expandafter\let\csname ALG@currentlifetime@\theALG@nested\endcsname\relax% 86 | % 87 | \begin{list}% 88 | {\ALG@step}% 89 | {% 90 | \rightmargin\z@% 91 | \itemsep\z@ \itemindent\z@ \listparindent2em% 92 | \partopsep\z@ \parskip\z@ \parsep\z@% 93 | \labelsep 0.5em \topsep 0.2em%\skip 1.2em 94 | \ifthenelse{\equal{#1}{0}}% 95 | {\labelwidth 0.5em}% 96 | {\labelwidth 1.2em}% 97 | \leftmargin\labelwidth \addtolength{\leftmargin}{\labelsep}% Ok. the perfect leftmargin :-)) 98 | \ALG@tlm\z@% 99 | }% 100 | \setcounter{ALG@nested}{0}% 101 | \ALG@beginalgorithmic% 102 | }% 103 | {% end{algorithmic} 104 | % check if all blocks are closed 105 | \ALG@closeloops% 106 | \expandafter\ifnum\csname ALG@currentblock@\theALG@nested\endcsname=0\relax% 107 | \else% 108 | \PackageError{algorithmicx}{Some blocks are not closed!!!}{}% 109 | \fi% 110 | \ALG@endalgorithmic% 111 | \end{list}% 112 | }% 113 | % 114 | % 115 | % *** Functional core *** 116 | % 117 | % 118 | \def\ALG@makeentity#1% execute the entity (#1) 119 | {% 120 | \def\ALG@thisentity{#1}% 121 | \expandafter\ifx\csname ALG@b@\ALG@L @#1@0\endcsname\relax% 122 | \let\ALG@makenobeginrepeat\ALG@makenobegin\ALG@makenobeginrepeat% this entitie ends or continues blocks 123 | \else% 124 | \let\ALG@makebeginrepeat\ALG@makebegin\ALG@makebeginrepeat% this entitie can open blocks 125 | \fi% 126 | \ALG@entitiecommand% 127 | }% 128 | % 129 | \def\ALG@makebegin% executes an entitie that can open blocks 130 | {% 131 | \expandafter\let\expandafter\ALG@thislifetime\csname ALG@currentlifetime@\theALG@nested\endcsname% 132 | \ifx\ALG@thislifetime\relax% 133 | \let\ALG@makebeginrepeat\ALG@doentity% in infinite block I can open my block 134 | \else% 135 | \ifnum\ALG@thislifetime>0\relax% 136 | \ifnum\ALG@thislifetime>65534\else% 137 | \setcounter{ALG@tmpcounter}{\ALG@thislifetime}% the block has 'space' for another included block 138 | \addtocounter{ALG@tmpcounter}{-1}% 139 | \expandafter\edef\csname ALG@currentlifetime@\theALG@nested\endcsname{\arabic{ALG@tmpcounter}}% 140 | \fi% 141 | \let\ALG@makebeginrepeat\ALG@doentity% 142 | \else% the block needs to be closed 143 | \expandafter\ifx\csname ALG@b@\ALG@L @\ALG@thisentity @\csname ALG@currentblock@\theALG@nested\endcsname\endcsname\relax% 144 | \ALG@closebyforce% I can not close this block, continue after it is closed by force 145 | % \ALG@makebegin% 146 | \else% 147 | % the block would be closed automatically, but this entitie can close it, so let's do it with the entity 148 | \let\ALG@makebeginrepeat\ALG@doentity% 149 | \fi% 150 | \fi% 151 | \fi% 152 | \ALG@makebeginrepeat% 153 | }% 154 | % 155 | \def\ALG@makenobegin% executes an entitie that can not open blocks 156 | {% 157 | \expandafter\ifx\csname ALG@currentlifetime@\theALG@nested\endcsname\relax% 158 | \let\ALG@makenobeginrepeat\ALG@doentity% an infinite block must be broken 159 | \else% 160 | \expandafter\ifx\csname ALG@b@\ALG@L @\ALG@thisentity @\csname ALG@currentblock@\theALG@nested\endcsname\endcsname\relax% 161 | \ALG@closebyforce% the block must be ended by force, 162 | \else% 163 | \let\ALG@makenobeginrepeat\ALG@doentity% I can continue / end this block, let's do it 164 | \fi% 165 | \fi% 166 | \ALG@makenobeginrepeat% 167 | }% 168 | % 169 | \def\ALG@dobegin% 170 | {% 171 | \ALG@beginblock{\csname ALG@i@\ALG@L @\ALG@thisentity @\ALG@thisblock\endcsname}% 172 | \expandafter\edef\csname ALG@currentblock@\theALG@nested\endcsname{\csname ALG@b@\ALG@L @\ALG@thisentity @\ALG@thisblock\endcsname}% 173 | \expandafter\ifx\csname ALG@c@\ALG@L @\ALG@thisentity @\ALG@thisblock\endcsname\relax% 174 | \expandafter\let\csname ALG@currentlifetime@\theALG@nested\endcsname\relax% 175 | \else% 176 | \expandafter\edef\csname ALG@currentlifetime@\theALG@nested\endcsname{\csname ALG@c@\ALG@L @\ALG@thisentity @\ALG@thisblock\endcsname}% 177 | \fi% 178 | }% 179 | % 180 | \def\ALG@doend% 181 | {% 182 | \ALG@endblock% 183 | }% 184 | % 185 | \def\ALG@doentity% the number of the closed block, the entitie 186 | {% 187 | \edef\ALG@thisblock{\csname ALG@currentblock@\theALG@nested\endcsname}% 188 | \expandafter\ifx\csname ALG@b@\ALG@L @\ALG@thisentity @\ALG@thisblock\endcsname\relax% 189 | \def\ALG@thisblock{0}% 190 | \fi% 191 | \ALG@getentitytext% 192 | \ifnum\ALG@thisblock=0\else\ALG@doend\fi% 193 | \ifx\ALG@text\ALG@x@notext% 194 | \item[]\nointerlineskip%\vskip-\prevdepth\nointerlineskip% bug: if there are no text and no lines, then this is wrong 195 | \else% 196 | \item% 197 | \fi% 198 | \noindent\hskip\ALG@tlm% 199 | \expandafter\ifnum0=\csname ALG@b@\ALG@L @\ALG@thisentity @\ALG@thisblock\endcsname\else% 200 | \ALG@dobegin% 201 | \fi% 202 | \def\ALG@entitiecommand{\ALG@displayentity}% 203 | }% 204 | % 205 | \def\ALG@getentitytext% 206 | {% 207 | \expandafter\let\expandafter\ALG@text\csname ALG@t@\ALG@L @\ALG@thisentity @\ALG@thisblock\endcsname% 208 | \ifx\ALG@text\ALG@x@default% 209 | % block specific - default 210 | \expandafter\let\expandafter\ALG@text\csname ALG@t@\ALG@L @\ALG@thisentity\endcsname% 211 | \ifx\ALG@text\ALG@x@default% 212 | % block specific - default, language specific - default 213 | \def\ALG@text{\ALG@deftext{\ALG@thisentity}}% 214 | \fi% 215 | \fi% 216 | }% 217 | % 218 | \def\ALG@deftext{\csname ALG@deftext@\ALG@L\endcsname}% 219 | % 220 | \def\ALG@displayentity% 221 | {% 222 | \ifx\ALG@text\ALG@x@notext% 223 | \let\ALG@text\relax% 224 | \fi 225 | \ALG@text% 226 | }% 227 | % 228 | \def\ALG@closebyforce% 229 | {% 230 | \ALG@endblock% 231 | }% 232 | % 233 | \def\ALG@closeloops% closes all finite blocks 234 | {% 235 | \expandafter\ifx\csname ALG@currentlifetime@\theALG@nested\endcsname\relax% 236 | \else% only if it is finite 237 | \ALG@closebyforce% the block must be ended by force, 238 | \ALG@closeloops% the command still runs 239 | \fi% 240 | }% 241 | % 242 | % 243 | % *** Low level block/entitie defining commands *** 244 | % 245 | % 246 | \def\ALG@bl@{0}% the BIG block 247 | \let\ALG@bl@@\ALG@bl@% the BIG block 248 | % 249 | % Create a block 250 | % 251 | \def\ALG@createblock#1% create the block #1, if it does not exists 252 | {% 253 | \@ifundefined{ALG@bl@\ALG@Ld @#1}% needs to be created? 254 | {% 255 | \addtocounter{ALG@blocknr}{1}% increment the block counter 256 | \expandafter\edef\csname ALG@bl@\ALG@Ld @#1\endcsname{\arabic{ALG@blocknr}}% set the block number 257 | }% 258 | {}% 259 | }% 260 | % 261 | % Get the block number 262 | % 263 | \def\ALG@getblocknumber#1{\csname ALG@bl@\ALG@Ld @#1\endcsname}% 264 | % 265 | % Create an entitie 266 | % 267 | \def\ALG@createentitie#1% create the entitie #1, if it does not exists 268 | {% 269 | \expandafter\ALG@edefcmd\csname #1\endcsname{\noexpand\ALG@makeentity{#1}}% 270 | \@ifundefined{ALG@t@\ALG@Ld @#1}% the entity text is defined in this language? 271 | {% 272 | \expandafter\let\csname ALG@t@\ALG@Ld @#1\endcsname\ALG@x@default% 273 | }% 274 | {}% 275 | }% 276 | % 277 | \def\ALG@createtext#1#2% #1 = closed block; #2 = entitie; creates \ALG@t@#2@#1 278 | {% 279 | \expandafter\let\csname ALG@t@\ALG@Ld @#2@#1\endcsname\ALG@x@default% 280 | }% 281 | % 282 | % End and Continue block 283 | % 284 | \def\ALG@endandcontinueblock#1#2#3#4#5% #1 = new block; #2 = old block; #3 = entitie; #4 = credits; #5 = indent 285 | {% 286 | \ifthenelse{\equal{#3}{}}{}% execute only if the entity is not empty 287 | {% 288 | \ALG@createentitie{#3}% create the entitie 289 | \ALG@createblock{#2}% create the old block, if needed 290 | \ifthenelse{\equal{#1}{}}% whe need to open a new block? 291 | {\expandafter\edef\csname ALG@b@\ALG@Ld @#3@\ALG@getblocknumber{#2}\endcsname{0}}% no, just close the old one 292 | {% yes, 293 | \ALG@createblock{#1}% create the block 294 | \expandafter\edef\csname ALG@b@\ALG@Ld @#3@\ALG@getblocknumber{#2}\endcsname{\ALG@getblocknumber{#1}}% ending the old block opens a new one 295 | \ifthenelse{\equal{#4}{}}% infinite or finite credits? 296 | {\expandafter\let\csname ALG@c@\ALG@Ld @#3@\ALG@getblocknumber{#2}\endcsname\relax}% infinite credits 297 | {\expandafter\edef\csname ALG@c@\ALG@Ld @#3@\ALG@getblocknumber{#2}\endcsname{#4}}% finite credits 298 | \ifthenelse{\equal{#5}{}}% default or specified indentation 299 | {\expandafter\let\csname ALG@i@\ALG@Ld @#3@\ALG@getblocknumber{#2}\endcsname\ALG@defaultindent}% default indentation 300 | {\expandafter\edef\csname ALG@i@\ALG@Ld @#3@\ALG@getblocknumber{#2}\endcsname{#5}}% indentation is specified 301 | }% 302 | \ALG@createtext{\ALG@getblocknumber{#2}}{#3}% 303 | }% 304 | }% 305 | % 306 | % macros used in declarations 307 | % 308 | \def\ALG@p@endtext@E{\algrenewtext{\ALG@v@end}}% 309 | \def\ALG@p@endtext@xE{\algrenewtext[\ALG@v@newblock]{\ALG@v@end}}% 310 | \def\ALG@p@endtext@nE{\algnotext{\ALG@v@end}}% 311 | \def\ALG@p@endtext@xnE{\algnotext[\ALG@v@newblock]{\ALG@v@end}}% 312 | \def\ALG@p@endtext@{}% 313 | % starttext defines are more compex -- care must be taken for the optional parameters 314 | \def\ALG@p@starttext@S{\ALG@p@s@process{\algrenewtext}}% 315 | \def\ALG@p@starttext@C{\ALG@p@s@process{\algrenewtext}}% 316 | \def\ALG@p@starttext@xC{\ALG@p@s@process{\algrenewtext[\ALG@v@oldblock]}}% 317 | \def\ALG@p@s@process#1% 318 | {% 319 | \ifthenelse{\equal{\ALG@v@start}{}}% 320 | {\ALG@p@endtext}% 321 | {\@ifnextchar{[}{\ALG@p@s@getparamcount{#1}}{\ALG@p@s@simple{#1}}}% 322 | }% 323 | \def\ALG@p@s@getparamcount#1[#2]% 324 | {% 325 | \@ifnextchar{[}{\ALG@p@s@getdefparam{#1}{#2}}{\ALG@p@s@param{#1}{#2}}% 326 | }% 327 | \def\ALG@p@s@getdefparam#1#2[#3]% 328 | {% 329 | \ALG@p@s@defparam{#1}{#2}{#3}% 330 | }% 331 | \def\ALG@p@s@simple#1#2{#1{\ALG@v@start}{#2}\ALG@p@endtext}% 332 | \def\ALG@p@s@param#1#2#3{#1{\ALG@v@start}[#2]{#3}\ALG@p@endtext}% 333 | \def\ALG@p@s@defparam#1#2#3#4{#1{\ALG@v@start}[#2][#3]{#4}\ALG@p@endtext}% 334 | % the rest of the crew 335 | \def\ALG@p@starttext@nS{\algnotext{\ALG@v@start}\ALG@p@endtext}% 336 | \def\ALG@p@starttext@nC{\algnotext{\ALG@v@start}\ALG@p@endtext}% 337 | \def\ALG@p@starttext@xnC{\algnotext[\ALG@v@oldblock]{\ALG@v@start}\ALG@p@endtext}% 338 | \def\ALG@p@starttext@{\ALG@p@endtext}% 339 | \def\ALG@p@indent@def#1{\def\ALG@v@indent{#1}\ALG@p@setup}% 340 | \def\ALG@p@indent@{\def\ALG@v@indent{}\ALG@p@setup}% 341 | \def\ALG@p@credits@def#1{\def\ALG@v@credits{#1}\ALG@p@indent}% 342 | \def\ALG@p@credits@{\ALG@p@indent}% 343 | \def\ALG@p@end@def#1{\def\ALG@v@end{#1}\ALG@p@credits}% 344 | \def\ALG@p@end@{\def\ALG@v@end{}\ALG@p@credits}% 345 | \def\ALG@p@start@def#1{\def\ALG@v@start{#1}\ALG@p@end}% 346 | \def\ALG@p@start@{\def\ALG@v@start{}\ALG@p@end}% 347 | \def\ALG@p@oldblock@def#1{\def\ALG@v@oldblock{#1}\ALG@p@start}% 348 | \def\ALG@p@oldblock@{\def\ALG@v@oldblock{}\ALG@p@start}% 349 | \newcommand\ALG@p@newblock[1][]{\def\ALG@v@newblock{#1}\ALG@p@oldblock}% 350 | \def\ALG@p@setup% 351 | {% 352 | \ifthenelse{\equal{\ALG@v@newblock}{}}% 353 | {% 354 | \ifthenelse{\equal{\ALG@v@start}{}}% 355 | {% 356 | \PackageError{algorithmicx}{Block or starting entitie must be specified!!!}{}% 357 | }% 358 | {% 359 | \let\ALG@v@newblock\ALG@v@start% 360 | }% 361 | }% 362 | {% 363 | }% 364 | \ALG@endandcontinueblock% 365 | {\ALG@v@newblock}{\ALG@v@oldblock}{\ALG@v@start}% 366 | {\ALG@v@credits}{\ALG@v@indent}% 367 | \ALG@endandcontinueblock% 368 | {}{\ALG@v@newblock}{\ALG@v@end}% 369 | {}{}% 370 | \ALG@p@starttext% 371 | }% 372 | % 373 | % param handling 374 | % 375 | \newcommand\ALG@p@def[2][def]% 376 | {% 377 | \expandafter\let\csname ALG@p@#2\expandafter\endcsname\csname ALG@p@#2@#1\endcsname% 378 | }% 379 | \def\ALG@p@undef{\ALG@p@def[]}% 380 | % 381 | \def\ALG@p@ons{\ALG@p@def{start}}% 382 | \def\ALG@p@onS{\ALG@p@def{start}\ALG@p@def[S]{starttext}}% 383 | \def\ALG@p@onc{\ALG@p@def{oldblock}\ALG@p@def{start}}% 384 | \def\ALG@p@onC{\ALG@p@def{oldblock}\ALG@p@def{start}\ALG@p@def[C]{starttext}}% 385 | \def\ALG@p@one{\ALG@p@def{end}}% 386 | \def\ALG@p@onE{\ALG@p@def{end}\ALG@p@def[E]{endtext}}% 387 | \def\ALG@p@onxC{\ALG@p@def{oldblock}\ALG@p@def{start}\ALG@p@def[xC]{starttext}}% 388 | \def\ALG@p@onxE{\ALG@p@def{end}\ALG@p@def[xE]{endtext}}% 389 | \def\ALG@p@onnS{\ALG@p@def{start}\ALG@p@def[nS]{starttext}}% 390 | \def\ALG@p@onnC{\ALG@p@def{oldblock}\ALG@p@def{start}\ALG@p@def[nC]{starttext}}% 391 | \def\ALG@p@onnE{\ALG@p@def{end}\ALG@p@def[nE]{endtext}}% 392 | \def\ALG@p@onxnC{\ALG@p@def{oldblock}\ALG@p@def{start}\ALG@p@def[xnC]{starttext}}% 393 | \def\ALG@p@onxnE{\ALG@p@def{end}\ALG@p@def[xnE]{endtext}}% 394 | \def\ALG@p@onb{\def\ALG@v@credits{}}% 395 | \def\ALG@p@onl{\def\ALG@v@credits{1}}% 396 | \def\ALG@p@onL{\ALG@p@def{credits}}% 397 | \def\ALG@p@oni{\ALG@p@def{indent}}% 398 | % 399 | \def\ALG@p@main#1% 400 | {% 401 | \@ifundefined{ALG@ps@\ALG@p@state @#1}% 402 | {% 403 | \csname ALG@ps@\ALG@p@state @other\endcsname{#1}% 404 | }% 405 | {% 406 | \csname ALG@ps@\ALG@p@state @#1\endcsname% 407 | }% 408 | \ALG@p@rec% 409 | }% 410 | % STATE : <> 411 | \expandafter\def\csname ALG@ps@@]\endcsname{\let\ALG@p@rec\relax}% 412 | \def\ALG@ps@@s{\ALG@p@ons}% 413 | \def\ALG@ps@@S{\ALG@p@onS}% 414 | \def\ALG@ps@@c{\ALG@p@onc}% 415 | \def\ALG@ps@@C{\ALG@p@onC}% 416 | \def\ALG@ps@@e{\ALG@p@one}% 417 | \def\ALG@ps@@E{\ALG@p@onE}% 418 | \def\ALG@ps@@N{\typeout{algdef: 'N' obsoloted, use 'nE'.}\ALG@p@onnE}% 419 | \def\ALG@ps@@b{\ALG@p@onb}% 420 | \def\ALG@ps@@l{\ALG@p@onl}% 421 | \def\ALG@ps@@L{\ALG@p@onL}% 422 | \def\ALG@ps@@i{\ALG@p@oni}% 423 | \def\ALG@ps@@x{\def\ALG@p@state{x}}% 424 | \def\ALG@ps@@n{\def\ALG@p@state{n}}% 425 | \def\ALG@ps@@other#1{\typeout{algdef: Ignoring unknown token #1}}% 426 | % STATE : x 427 | \def\ALG@ps@x@C{\def\ALG@p@state{}\ALG@p@onxC}% 428 | \def\ALG@ps@x@E{\def\ALG@p@state{}\ALG@p@onxE}% 429 | \def\ALG@ps@x@N{\def\ALG@p@state{}\typeout{algdef: 'xN' obsoloted, use 'xnE'.}\ALG@p@onxnE}% 430 | \def\ALG@ps@x@n{\def\ALG@p@state{xn}}% 431 | \def\ALG@ps@x@other#1% 432 | {% 433 | \typeout{algdef: Ignoring 'x' before '#1'.}% 434 | \def\ALG@p@state{}% 435 | \def\ALG@p@rec{\let\ALG@p@rec\ALG@p@main\ALG@p@rec#1}% 436 | }% 437 | % STATE : n 438 | \def\ALG@ps@n@S{\def\ALG@p@state{}\ALG@p@onnS}% 439 | \def\ALG@ps@n@C{\def\ALG@p@state{}\ALG@p@onnC}% 440 | \def\ALG@ps@n@E{\def\ALG@p@state{}\ALG@p@onnE}% 441 | \def\ALG@ps@n@x{\def\ALG@p@state{nx}}% 442 | \def\ALG@ps@n@other#1% 443 | {% 444 | \typeout{algdef: Ignoring 'n' before '#1'.}% 445 | \def\ALG@p@state{}% 446 | \def\ALG@p@rec{\let\ALG@p@rec\ALG@p@main\ALG@p@rec#1}% 447 | }% 448 | % STATE : xn 449 | \def\ALG@ps@xn@C{\def\ALG@p@state{}\ALG@p@onxnC}% 450 | \def\ALG@ps@xn@E{\def\ALG@p@state{}\ALG@p@onxnE}% 451 | \def\ALG@ps@xn@x{\typeout{algdef: Ignoring 'x' after 'xn'.}}% 452 | \def\ALG@ps@xn@n{\typeout{algdef: Ignoring 'n' after 'xn'.}}% 453 | \def\ALG@ps@xn@other#1% 454 | {% 455 | \typeout{algdef: Ignoring 'xn' before '#1'.}% 456 | \def\ALG@p@state{}% 457 | \def\ALG@p@rec{\let\ALG@p@rec\ALG@p@main\ALG@p@rec#1}% 458 | }% 459 | % STATE : nx 460 | \def\ALG@ps@nx@C{\def\ALG@p@state{}\ALG@p@onxnC}% 461 | \def\ALG@ps@nx@E{\def\ALG@p@state{}\ALG@p@onxnE}% 462 | \def\ALG@ps@nx@x{\typeout{algdef: Ignoring 'x' after 'nx'.}}% 463 | \def\ALG@ps@nx@n{\typeout{algdef: Ignoring 'n' after 'nx'.}}% 464 | \def\ALG@ps@nx@other#1% 465 | {% 466 | \typeout{algdef: Ignoring 'nx' before '#1'.}% 467 | \def\ALG@p@state{}% 468 | \def\ALG@p@rec{\let\ALG@p@rec\ALG@p@main\ALG@p@rec#1}% 469 | }% 470 | % 471 | % 472 | % *** User level block/entitie commands *** 473 | % 474 | % 475 | % 476 | % algdef{switches}... -- the king of all definitions in the algorithmicx package 477 | % 478 | \newcommand\algdef[1]% 479 | {% 480 | \ALG@p@undef{oldblock}% 481 | \ALG@p@undef{start}% 482 | \ALG@p@undef{end}% 483 | \def\ALG@v@credits{}% 484 | \ALG@p@undef{credits}% 485 | \ALG@p@undef{indent}% 486 | \ALG@p@undef{starttext}% 487 | \ALG@p@undef{endtext}% 488 | \def\ALG@p@state{}% 489 | \let\ALG@p@rec\ALG@p@main% 490 | \ALG@p@rec#1]% 491 | \ALG@p@newblock% 492 | }% 493 | % 494 | % a lot of other macros are provided for convenience 495 | % 496 | \def\algblock{\algdef{se}}% 497 | \def\algcblock{\algdef{ce}}% 498 | \def\algloop{\algdef{sl}}% 499 | \def\algcloop{\algdef{cl}}% 500 | \def\algsetblock{\algdef{seLi}}% 501 | \def\algsetcblock{\algdef{ceLi}}% 502 | \def\algblockx{\algdef{SxE}}% 503 | \def\algblockdefx{\algdef{SE}}% 504 | \def\algcblockx{\algdef{CxE}}% 505 | \def\algcblockdefx{\algdef{CE}}% 506 | \def\algsetblockx{\algdef{SxELi}}% 507 | \def\algsetblockdefx{\algdef{SELi}}% 508 | \def\algsetcblockx{\algdef{CxELi}}% 509 | \def\algsetcblockdefx{\algdef{CELi}}% 510 | \def\algloopdefx{\algdef{Sl}}% 511 | \def\algcloopx{\algdef{xCl}}% 512 | \def\algcloopdefx{\algdef{Cl}}% 513 | % algloopx is not correct, use algloopdefx 514 | % 515 | % Text output commands 516 | % 517 | \newcommand\algrenewtext[2][]% [block]{entity} 518 | {% 519 | \ifthenelse{\equal{#2}{}}{}% 520 | {% 521 | \ifthenelse{\equal{#1}{}}% 522 | {% 523 | \expandafter\let\csname ALG@t@\ALG@Ld @#2\endcsname\relax% 524 | \expandafter\newcommand\csname ALG@t@\ALG@Ld @#2\endcsname% 525 | }% 526 | {% 527 | \expandafter\let\csname ALG@t@\ALG@Ld @#2@\ALG@getblocknumber{#1}\endcsname\relax% 528 | \expandafter\newcommand\csname ALG@t@\ALG@Ld @#2@\ALG@getblocknumber{#1}\endcsname% 529 | }% 530 | }% 531 | }% 532 | % 533 | \def\ALG@letentitytext#1#2% [block]{entity} 534 | {% 535 | \ifthenelse{\equal{#2}{}}{}% 536 | {% 537 | \ifthenelse{\equal{#1}{}}% 538 | {% 539 | \expandafter\let\csname ALG@t@\ALG@Ld @#2\endcsname% 540 | }% 541 | {% 542 | \expandafter\let\csname ALG@t@\ALG@Ld @#2@\ALG@getblocknumber{#1}\endcsname% 543 | }% 544 | }% 545 | }% 546 | % 547 | \newcommand\algnotext[2][]% [block]{entity} 548 | {% 549 | \ALG@letentitytext{#1}{#2}\ALG@x@notext% 550 | }% 551 | % 552 | \newcommand\algdefaulttext[2][]% [block]{entity} 553 | {% 554 | \ALG@letentitytext{#1}{#2}\ALG@x@default% 555 | }% 556 | % 557 | \def\ALG@notext*{\algnotext}% 558 | \def\algtext{\@ifnextchar{*}{\ALG@notext}{\algrenewtext}}% 559 | % 560 | % 561 | % *** LANGUAGE SWITCHING *** 562 | % 563 | % 564 | % 565 | \newcommand\algnewlanguage[1]% 566 | {% 567 | \@ifundefined{ALG@L@#1}% needs to be created? 568 | {}% 569 | {% 570 | \PackageError{algorithmicx}{Language '#1' already defined!}{}% 571 | }% 572 | \addtocounter{ALG@Lnr}{1}% increment the language counter 573 | \expandafter\edef\csname ALG@L@#1\endcsname{\arabic{ALG@Lnr}}% set the language number 574 | \edef\ALG@Ld{\csname ALG@L@#1\endcsname}% 575 | \expandafter\let\csname ALG@bl@\ALG@Ld @\endcsname\ALG@bl@% the BIG block 576 | \expandafter\let\csname ALG@bl@\ALG@Ld @@\endcsname\ALG@bl@% the BIG block 577 | \algdef{SL}[STATE]{State}{0}{}% 578 | \expandafter\def\csname ALG@deftext@\ALG@Ld\endcsname{\textbf}% 579 | \algnewcommand\algorithmiccomment[1]{\hfill\(\triangleright\) ##1}% 580 | \algnewcommand\algorithmicindent{1.5em}% 581 | \algnewcommand\alglinenumber[1]{\footnotesize ##1:}% 582 | \algnewcommand\ALG@beginalgorithmic\relax% for user overrides 583 | \algnewcommand\ALG@endalgorithmic\relax% for user overrides 584 | }% 585 | % 586 | \newcommand\algsetlanguage[1]% 587 | {% 588 | \@ifundefined{ALG@L@#1}% needs to be created? 589 | {% 590 | \PackageError{algorithmicx}{Language '#1' is not yet defined!}{}% 591 | }{}% 592 | \edef\ALG@L{\csname ALG@L@#1\endcsname}% 593 | }% 594 | % 595 | \newcommand\algdeflanguage[1]% 596 | {% 597 | \@ifundefined{ALG@L@#1}% needs to be created? 598 | {% 599 | \PackageError{algorithmicx}{Language '#1' is not yet defined!}{}% 600 | }{}% 601 | \edef\ALG@Ld{\csname ALG@L@#1\endcsname}% 602 | }% 603 | % 604 | \newcommand\alglanguage[1]% 605 | {% 606 | \algdeflanguage{#1}% 607 | \algsetlanguage{#1}% 608 | }% 609 | % 610 | % 611 | % *** Defining language dependent stuff *** 612 | % 613 | % 614 | \def\ALG@eatoneparam#1{}% 615 | \def\ALG@defbasecmd#1#2% 616 | {% 617 | \edef\ALG@tmp{\expandafter\ALG@eatoneparam\string #2}% 618 | \@ifundefined\ALG@tmp{\edef #2{\noexpand\csname ALG@cmd@\noexpand\ALG@L @\ALG@tmp\endcsname}}{}% 619 | \expandafter#1\csname ALG@cmd@\ALG@Ld @\ALG@tmp\endcsname% 620 | }% 621 | \newcommand\algnewcommand{\ALG@defbasecmd\newcommand}% 622 | \newcommand\algrenewcommand{\ALG@defbasecmd\renewcommand}% 623 | \def\ALG@letcmd{\ALG@defbasecmd\let}% 624 | \def\ALG@defcmd{\ALG@defbasecmd\def}% 625 | \def\ALG@edefcmd{\ALG@defbasecmd\edef}% 626 | % 627 | % 628 | % *** OTHERS *** 629 | % 630 | % 631 | \def\BState{\State \algbackskip}% 632 | \def\Statex{\item[]}% an empty line 633 | \newcommand\algrenewcomment{\algrenewcommand\algorithmiccomment}% 634 | \def\Comment{\algorithmiccomment}% 635 | \def\algref#1#2{\ref{#1}.\ref{#2}}% 636 | \algnewlanguage{default}% 637 | \algsetlanguage{default}% 638 | % 639 | % 640 | % *** Line breaks *** 641 | % 642 | % 643 | \newcommand\algbreak% for multiline parameters !!! needs fix 644 | {% 645 | \item% 646 | % \hskip\ALG@parindent%!!! not yet implemented 647 | % \hskip-\algorithmicindent% 648 | }% 649 | % 650 | \def\ALG@noputindents% 651 | {% 652 | \hskip\ALG@tlm% 653 | }% 654 | % 655 | % 656 | % *** algorithm store / restore *** 657 | % 658 | % 659 | % store 660 | % 661 | \ALG@newcondstate{mustrestore}% 662 | \def\algstore% 663 | {% 664 | \renewcommand\ALG@beginblock% 665 | {% 666 | \PackageError{algorithmicx}{The environment must be closed after store!}{}% 667 | }% 668 | \@ifstar{\ALG@starstore}{\ALG@nostarstore}% 669 | }% 670 | \def\ALG@nostarstore#1% save all infos into #1 and terminate the algorithmic block 671 | {% 672 | \addtocounter{ALG@storecount}{1}% 673 | \expandafter\global\expandafter\let\csname ALG@save@mustrestore@#1\endcsname\ALG@x@mustrestore% 674 | \ALG@starstore{#1}% 675 | }% 676 | \def\ALG@starstore#1% 677 | {% 678 | \@ifundefined{ALG@save@line@#1}{}% 679 | {\PackageError{algorithmicx}{This save name '#1' is already used!}{}}% 680 | \def\ALG@savename{#1}% 681 | \expandafter\xdef\csname ALG@save@totalnr@\ALG@savename\endcsname{\theALG@nested}% 682 | \expandafter\xdef\csname ALG@save@line@\ALG@savename\endcsname{\theALG@line}% 683 | \expandafter\xdef\csname ALG@save@numberfreq@\ALG@savename\endcsname{\ALG@numberfreq}% 684 | \expandafter\xdef\csname ALG@save@rem@\ALG@savename\endcsname{\theALG@rem}% 685 | \let\ALG@storerepeat\ALG@store% 686 | \ALG@storerepeat% 687 | }% 688 | \def\ALG@store% simply terminate all open blocks 689 | {% 690 | \ifnum\theALG@nested=0\let\ALG@storerepeat\relax% 691 | \else% 692 | \expandafter\xdef\csname ALG@save@currentblock@\ALG@savename @\theALG@nested\endcsname% 693 | {\csname ALG@currentblock@\theALG@nested\endcsname}% 694 | \expandafter\ifx\csname ALG@currentlifetime@\theALG@nested\endcsname\relax% 695 | \else% 696 | \expandafter\xdef\csname ALG@save@currentlifetime@\ALG@savename @\theALG@nested\endcsname% 697 | {\csname ALG@currentlifetime@\theALG@nested\endcsname}% 698 | \fi% 699 | \expandafter\xdef\csname ALG@save@ind@\ALG@savename @\theALG@nested\endcsname% 700 | {\csname ALG@ind@\theALG@nested\endcsname}% 701 | \ALG@closebyforce% 702 | \fi% 703 | \ALG@storerepeat% 704 | }% 705 | % 706 | % restore 707 | % 708 | \def\algrestore% 709 | {% 710 | \@ifstar{\ALG@starrestore}{\ALG@nostarrestore}% 711 | }% 712 | \def\ALG@starrestore% 713 | {% 714 | \let\ALG@restorerem\relax% 715 | \let\ALG@restorereprem\relax% 716 | \ALG@restoremain% 717 | }% 718 | \def\ALG@nostarrestore% 719 | {% 720 | \let\ALG@restorerem\ALG@restoreremovesave% 721 | \let\ALG@restorereprem\ALG@restorerepremovesave% 722 | \ALG@restoremain% 723 | }% 724 | \def\ALG@restoreremovesave% 725 | {% 726 | \expandafter\global\expandafter\let\csname ALG@save@totalnr@\ALG@savename\endcsname\relax% 727 | \expandafter\global\expandafter\let\csname ALG@save@line@\ALG@savename\endcsname\relax% 728 | \expandafter\global\expandafter\let\csname ALG@save@rem@\ALG@savename\endcsname\relax% 729 | \expandafter\global\expandafter\let\csname ALG@save@totalnr@\ALG@savename\endcsname\relax% 730 | \expandafter\global\expandafter\let\csname ALG@save@numberfreq@\ALG@savename\endcsname\relax% 731 | }% 732 | \def\ALG@restorerepremovesave% 733 | {% 734 | \expandafter\global\expandafter\let\csname ALG@save@currentblock@\ALG@savename @\theALG@tmpcounter\endcsname\relax% 735 | \expandafter\global\expandafter\let\csname ALG@save@currentlifetime@\ALG@savename @\theALG@tmpcounter\endcsname\relax% 736 | \expandafter\global\expandafter\let\csname ALG@save@currentlifetime@\ALG@savename @\theALG@tmpcounter\endcsname\relax% 737 | \expandafter\global\expandafter\let\csname ALG@save@ind@\ALG@savename @\theALG@tmpcounter\endcsname\relax% 738 | }% 739 | \def\ALG@restoremain#1% restore all infos from #1 in an open algorithmic block 740 | {% 741 | \ifnum\theALG@line=0% 742 | \else\PackageError{algorithmicx}{Restore might be used only at the beginning of the environment!}{}% 743 | \fi% 744 | \def\ALG@savename{#1}% 745 | \expandafter\ifx\csname ALG@save@totalnr@\ALG@savename\endcsname\relax% 746 | \PackageError{algorithmicx}{Save '\ALG@savename'\space not defined!!!}{}% 747 | \fi% 748 | \@ifundefined{ALG@save@mustrestore@\ALG@savename}{}% 749 | {% 750 | \addtocounter{ALG@storecount}{-1}% 751 | \expandafter\global\expandafter\let\csname ALG@save@mustrestore@\ALG@savename\endcsname\relax% 752 | }% 753 | \setcounter{ALG@line}{\csname ALG@save@line@\ALG@savename\endcsname}% 754 | \edef\ALG@numberfreq{\csname ALG@save@numberfreq@\ALG@savename\endcsname}% 755 | \setcounter{ALG@rem}{\csname ALG@save@rem@\ALG@savename\endcsname}% 756 | \setcounter{ALG@tmpcounter}{\csname ALG@save@totalnr@\ALG@savename\endcsname}% 757 | \setcounter{ALG@nested}{0}% 758 | \ALG@restorerem% 759 | \let\ALG@restorerepeat\ALG@restore% 760 | \ALG@restorerepeat% 761 | }% 762 | \def\ALG@restore% 763 | {% 764 | \ifnum\theALG@tmpcounter>0% 765 | \expandafter\edef\csname ALG@currentblock@\theALG@tmpcounter\endcsname% 766 | {\csname ALG@save@currentblock@\ALG@savename @\theALG@tmpcounter\endcsname}% 767 | \expandafter\ifx\csname ALG@save@currentlifetime@\ALG@savename @\theALG@tmpcounter\endcsname\relax% 768 | \expandafter\let\csname ALG@currentlifetime@\theALG@tmpcounter\endcsname\relax% 769 | \else% 770 | \expandafter\edef\csname ALG@currentlifetime@\theALG@tmpcounter\endcsname% 771 | {\csname ALG@save@currentlifetime@\ALG@savename @\theALG@tmpcounter\endcsname}% 772 | \fi% 773 | % 774 | \ALG@beginblock{\csname ALG@save@ind@\ALG@savename @\theALG@tmpcounter\endcsname}% 775 | \ALG@restorereprem% 776 | \addtocounter{ALG@tmpcounter}{-1}% 777 | \else\let\ALG@restorerepeat\relax% 778 | \fi% 779 | \ALG@restorerepeat% 780 | }% 781 | \AtEndDocument% 782 | {% 783 | \ifnum\theALG@storecount>0\relax% 784 | \PackageError{algorithmicx}{Some stored algorithms are not restored!}{}% 785 | \fi% 786 | }% 787 | -------------------------------------------------------------------------------- /doc/algpseudocode.sty: -------------------------------------------------------------------------------- 1 | % PSEUDOCODE ALGORITHMIC STYLE -- Released 27 APR 2005 2 | % for LaTeX version 2e 3 | % 4 | % Copyright Szasz Janos 5 | % E-mail szaszjanos@users.sourceforge.net 6 | % Based on Peter Williams's algorithmic.sty 7 | % 8 | \NeedsTeXFormat{LaTeX2e}% 9 | \ProvidesPackage{algpseudocode}% 10 | \RequirePackage{ifthen}% 11 | \RequirePackage{algorithmicx}% 12 | \typeout{Document Style - pseudocode environments for use with the `algorithmicx' style}% 13 | % 14 | \def\ALG@noend{f}% 15 | \newboolean{ALG@compatible}% 16 | \setboolean{ALG@compatible}{false}% 17 | % 18 | \DeclareOption{noend}{\def\ALG@noend{t}}% 19 | \DeclareOption{end}{\def\ALG@noend{f}}% 20 | \DeclareOption{compatible}{\typeout{For compatibility mode use algcompatible.sty!!!}\setboolean{ALG@compatible}{true}}% 21 | \DeclareOption{noncompatible}{\setboolean{ALG@noncompatible}{false}}% 22 | \ProcessOptions% 23 | % 24 | % *** DECLARATIONS *** 25 | % 26 | \algnewlanguage{pseudocode}% 27 | \alglanguage{pseudocode}% 28 | % 29 | % *** KEYWORDS *** 30 | % 31 | \algnewcommand\algorithmicend{\textbf{end}} 32 | \algnewcommand\algorithmicdo{\textbf{do}} 33 | \algnewcommand\algorithmicwhile{\textbf{while}} 34 | \algnewcommand\algorithmicfor{\textbf{for}} 35 | \algnewcommand\algorithmicforall{\textbf{for all}} 36 | \algnewcommand\algorithmicloop{\textbf{loop}} 37 | \algnewcommand\algorithmicrepeat{\textbf{repeat}} 38 | \algnewcommand\algorithmicuntil{\textbf{until}} 39 | \algnewcommand\algorithmicprocedure{\textbf{procedure}} 40 | \algnewcommand\algorithmicfunction{\textbf{function}} 41 | \algnewcommand\algorithmicif{\textbf{if}} 42 | \algnewcommand\algorithmicthen{\textbf{then}} 43 | \algnewcommand\algorithmicelse{\textbf{else}} 44 | \algnewcommand\algorithmicrequire{\textbf{Require:}} 45 | \algnewcommand\algorithmicensure{\textbf{Ensure:}} 46 | \algnewcommand\algorithmicreturn{\textbf{return}} 47 | \algnewcommand\textproc{\textsc} 48 | % 49 | % *** DECLARED LOOPS *** 50 | % 51 | \algdef{SE}[WHILE]{While}{EndWhile}[1]{\algorithmicwhile\ #1\ \algorithmicdo}{\algorithmicend\ \algorithmicwhile}% 52 | \algdef{SE}[FOR]{For}{EndFor}[1]{\algorithmicfor\ #1\ \algorithmicdo}{\algorithmicend\ \algorithmicfor}% 53 | \algdef{S}[FOR]{ForAll}[1]{\algorithmicforall\ #1\ \algorithmicdo}% 54 | \algdef{SE}[LOOP]{Loop}{EndLoop}{\algorithmicloop}{\algorithmicend\ \algorithmicloop}% 55 | \algdef{SE}[REPEAT]{Repeat}{Until}{\algorithmicrepeat}[1]{\algorithmicuntil\ #1}% 56 | \algdef{SE}[IF]{If}{EndIf}[1]{\algorithmicif\ #1\ \algorithmicthen}{\algorithmicend\ \algorithmicif}% 57 | \algdef{C}[IF]{IF}{ElsIf}[1]{\algorithmicelse\ \algorithmicif\ #1\ \algorithmicthen}% 58 | \algdef{Ce}[ELSE]{IF}{Else}{EndIf}{\algorithmicelse}% 59 | \algdef{SE}[PROCEDURE]{Procedure}{EndProcedure}% 60 | [2]{\algorithmicprocedure\ \textproc{#1}\ifthenelse{\equal{#2}{}}{}{(#2)}}% 61 | {\algorithmicend\ \algorithmicprocedure}% 62 | \algdef{SE}[FUNCTION]{Function}{EndFunction}% 63 | [2]{\algorithmicfunction\ \textproc{#1}\ifthenelse{\equal{#2}{}}{}{(#2)}}% 64 | {\algorithmicend\ \algorithmicfunction}% 65 | % 66 | \ifthenelse{\equal{\ALG@noend}{t}}% 67 | {% 68 | \algtext*{EndWhile}% 69 | \algtext*{EndFor}% 70 | \algtext*{EndLoop}% 71 | \algtext*{EndIf}% 72 | \algtext*{EndProcedure}% 73 | \algtext*{EndFunction}% 74 | }{}% 75 | % 76 | % *** OTHER DECLARATIONS *** 77 | % 78 | \algnewcommand\Require{\item[\algorithmicrequire]}% 79 | \algnewcommand\Ensure{\item[\algorithmicensure]}% 80 | \algnewcommand\Return{\algorithmicreturn{} }% 81 | \algnewcommand\Call[2]{\textproc{#1}\ifthenelse{\equal{#2}{}}{}{(#2)}}% 82 | % 83 | % 84 | % 85 | \ifthenelse{\boolean{ALG@compatible}}% 86 | {% 87 | \ifthenelse{\equal{\ALG@noend}{t}}% 88 | {\RequirePackage[noend]{algcompatible}}% 89 | {\RequirePackage{algcompatible}}% 90 | }% 91 | {}% 92 | % 93 | -------------------------------------------------------------------------------- /doc/clp_report.bib: -------------------------------------------------------------------------------- 1 | @article{pettorossi1994transformation, 2 | title={Transformation of logic programs: Foundations and techniques}, 3 | author={Pettorossi, Alberto and Proietti, Maurizio}, 4 | journal={The Journal of Logic Programming}, 5 | volume={19}, 6 | pages={261--320}, 7 | year={1994}, 8 | publisher={Elsevier} 9 | } 10 | @article{burstall1977transformation, 11 | title={A transformation system for developing recursive programs}, 12 | author={Burstall, Rod M and Darlington, John}, 13 | journal={Journal of the ACM (JACM)}, 14 | volume={24}, 15 | number={1}, 16 | pages={44--67}, 17 | year={1977}, 18 | publisher={ACM} 19 | } 20 | @article{mycroft1984polymorphic, 21 | title={A polymorphic type system for Prolog}, 22 | author={Mycroft, Alan and O'Keefe, Richard A}, 23 | journal={Artificial intelligence}, 24 | volume={23}, 25 | number={3}, 26 | pages={295--307}, 27 | year={1984}, 28 | publisher={Elsevier} 29 | } 30 | @incollection{schrijvers2008towards, 31 | title={Towards typed prolog}, 32 | author={Schrijvers, Tom and Costa, V{\'\i}tor Santos and Wielemaker, Jan and Demoen, Bart}, 33 | booktitle={Logic Programming}, 34 | pages={693--697}, 35 | year={2008}, 36 | publisher={Springer} 37 | } 38 | @article{barbuti1992bottom, 39 | title={A bottom-up polymorphic type inference in logic programming}, 40 | author={Barbuti, Roberto and Giacobazzi, Roberto}, 41 | journal={Science of computer programming}, 42 | volume={19}, 43 | number={3}, 44 | pages={281--313}, 45 | year={1992}, 46 | publisher={Elsevier} 47 | } 48 | @inproceedings{hadjichristodoulou2012gradual, 49 | title={A Gradual Polymorphic Type System with Subtyping for Prolog}, 50 | author={Hadjichristodoulou, Spyros}, 51 | booktitle={LIPIcs-Leibniz International Proceedings in Informatics}, 52 | volume={17}, 53 | year={2012}, 54 | organization={Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik} 55 | } 56 | @inproceedings{ponsini2012refining, 57 | title={Refining abstract interpretation based value analysis with constraint programming techniques}, 58 | author={Ponsini, Olivier and Michel, Claude and Rueher, Michel}, 59 | booktitle={Principles and Practice of Constraint Programming}, 60 | pages={593--607}, 61 | year={2012}, 62 | organization={Springer} 63 | } 64 | @inproceedings{holmer1990fast, 65 | title={Fast Prolog with an extended general purpose architecture}, 66 | author={Holmer, Bruce K and Sano, Barton and Carlton, Michael and Van Roy, Peter and Haygood, Ralph and Bush, William R and Despain, Alvin M and Pendleton, Joan M and Dobry, Tep}, 67 | booktitle={ACM SIGARCH Computer Architecture News}, 68 | volume={18}, 69 | number={2SI}, 70 | pages={282--291}, 71 | year={1990}, 72 | organization={ACM} 73 | } -------------------------------------------------------------------------------- /doc/clp_report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bertas/hm_prolog/35c480665c8b33c4cbb6fc6614e14430775e3041/doc/clp_report.pdf -------------------------------------------------------------------------------- /doc/clp_report.tex: -------------------------------------------------------------------------------- 1 | \title{Towards a Transformation from Prolog to Constraint Prolog Programs} 2 | \author{ 3 | Yu Fu \\ 4 | College of Information Sciences and Technology\\ 5 | The Pennsylvania State University\\ 6 | University Park, PA 16802, USA 7 | } 8 | \date{\today} 9 | 10 | \documentclass[12pt]{article} 11 | 12 | \usepackage{algorithm} 13 | \usepackage{algpseudocode} 14 | \usepackage{color} 15 | \usepackage{listings} 16 | 17 | \begin{document} 18 | \maketitle 19 | 20 | \lstset{ % 21 | language=Prolog, % choose the language of the code 22 | basicstyle=\footnotesize, % the size of the fonts that are used for the code 23 | numbers=left, % where to put the line-numbers 24 | numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers 25 | stepnumber=1, % the step between two line-numbers. If it is 1 each line will be numbered 26 | numbersep=5pt, % how far the line-numbers are from the code 27 | backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color} 28 | showspaces=false, % show spaces adding particular underscores 29 | showstringspaces=false, % underline spaces within strings 30 | showtabs=false, % show tabs within strings adding particular underscores 31 | frame=single, % adds a frame around the code 32 | tabsize=2, % sets default tabsize to 2 spaces 33 | captionpos=b, % sets the caption-position to bottom 34 | breaklines=true, % sets automatic line breaking 35 | breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace 36 | escapeinside={\%*}{*)} % if you want to add a comment within your code 37 | } 38 | 39 | 40 | \begin{abstract} 41 | 42 | Constraint Logic Programming (CLP) has great potential in the field of software analysis and testing; however, there is barely any research on how to transform programs written in C or Java into programs written in CLP. Combined with current progress on translating C programs into Prolog programs, this research project proposed and implemented a Prolog-to-CLP translator to exploit its "untapped" potentials; This research also attempted to build a type inference system to facilitate the construction of the translator. 43 | \end{abstract} 44 | 45 | \section{Introduction} 46 | 47 | Constraint Logic Programming (CLP) can be viewed as an integration of constraint satisfaction to the concept of logic programming. Just like logic programs, CLP programs are highly declarative, with rules and facts to describe a certain situation; it also depends on the interpreter to automatically query the information base to prove a specified goal. However, in CLP the variables are not necessarily restricted to specific values, as they may also be within a constrained domain. As a result, the result of a CLP execution could be assigning target variables a set of possible values rather than a single one. CLP works by firstly collecting all the constraints into the \emph{constraint store}, where they are all presumed to be satisfiable; at the end of one execution, \emph{labeling} is often used to check the satisfiability or partial satisfiability of the variables within the \emph{constraint store} and to find a satisfying assignment to all the variables in the goal. 48 | 49 | CLP could be applied into the field of software testing and program analysis. To begin with, we propose to use CLP to improve the current con-colic testing for more efficient coverage of all the execution paths in a program. Specifically, the original program shall be transformed to the corresponding CLP program, then the CLP goals would be queried until all the possible execution paths are uncovered, and finally concrete test cases with respect to each particular execution path would be generated by deploying a constraint solver upon the path constraints. By taking advantage of the inherent backtracking mechanisms offered by CLP, we don't need to bother implementing a full-fledged con-colic testing system; Moreover, by using the APIs provided by the CLP interpreter, it is more convenient to monitor and tune the execution details during the test process; Last but not the least, such testing tool can be quite versatile as long as programs in other languages are transformed into CLP in advance. 50 | 51 | We also see the possibility of extending CLP to the field of program analysis. One of the most dominant techniques in the field -- abstract interpretation is flawed, although significantly lowering the complexity of program states, because the huge gap between the abstract semantics and the original program often leads to unsatisfactory result. As pointed out by Ponsini, abstract interpretation often fails to consider the constraints between variables when mapping thee into abstract domains, especially when handling conditional statements and non-linear expressions. However, by using CLP as the intermediate language for abstract interpretation, we can take advantage of its more uniformed syntax and an array of existing CLP analyzers to generate a safer approximation of the semantics of the original program, while maintaining the constraints between variables in the original program. 52 | 53 | One major obstacle when trying to integrate CLP into software analysis and testing is to translate a program written in a common programming language such as C and Java into a program in CLP, which can be treated as a two-step process: first translating a C/Java program into the corresponding Prolog program, then translating the derived Prolog program into a CLP program. Considering that there has already been work on the transformation from C into Prolog programs, our object is to propose and implement a Prolog-to-CLP translator to attempt its usage in software testing. 54 | 55 | There is not an official Prolog distribution to stick to, so I have chosen SWI-Prolog, one of the most popular and robust open-source Prolog distribution with CLP support as well. Specifically, current stable SWI-Prolog (version 6.6.6) provides the following three libraries for extended ability to process CLP: library(clpb)--Constraint Logic Programming over Boolean Variables, library(clpfd)--Constraint Logic Programming over Finite Domains, and library(clpqr)--Constraint Logic Programming over Rationals and Reals. Although these libraries are similar to some extent, there are still differences w.r.t. specific pre-defined predicates, hereby we choose SWI-Prolog with library(clpfd) as our target CLP program because it is sufficient for most software testing needs while keeping up an acceptable performance. 56 | 57 | \paragraph{Outline} 58 | The remainder of this article is organized as follows. 59 | Section~\ref{previous work} gives account of previous work. 60 | Section~\ref{methodology} reviews the approaches in the transformation of Prolog into CLP programs. 61 | Our new and exciting results are described in Section~\ref{results}. 62 | Finally, Section~\ref{challenges} laid out the future challenges to resolve. 63 | 64 | \section{Previous work}\label{previous work} 65 | There has been a myriad of research with regard to the optimization of Prolog programs. In the \cite{pettorossi1994transformation}, the authors reviewed some of the major techniques often used for the transformation of logic programs, which is based on the use of two elementary transformation rules: \emph{unfolding} and \emph{folding} originally introduced for the transformation of functional rules \cite{burstall1977transformation}. Loosely, unfolding can be viewed as replacing a goal in the body of a clause by its definition, while folding corresponds to recognizing that goals in the body of a clause are an instance of a definition, unfolding and folding are inverse as an unfolding step followed by the corresponding folding step would produce the initial program. By introducing a set of theorems, the authors justified that such unfolding/folding based transformation is indeed semantics-preserving. Finally, considering the inverses within transformation rules, in order to avoid producing futile transformations (namely, equal to the initial programs), the authors concluded some transformation strategies to guide the transformation towards producing more efficient programs. Partial evaluation, another major program transformation method, is also based on repetitive unfolding procedures. 66 | 67 | Although folding and unfolding has long been the mainstream in the realm of logic program transformation, it does not necessarily fit our purposes, mainly due to the fact that Prolog and CLP are different in a lot of ways. Considering that there are many Prolog implementations, we choose SWI-Prolog because it is well supported by many external libraries and extensions, including library(clpfd), which we use as our target constraint Prolog programs. The library(clpfd) was developed as an extension to provide SWI-Prolog with the ability to model and solve various combinatorial problems such as planning, scheduling and allocation tasks. Based on the conventional SWI-Prolog grammar, new predicates for the definition and resolution of finite domain constraints are introduced. Specifically, library(clpfd) use the following set of arithmetic constraints: $Exp1\#>=Exp2$, $Exp1\#=Exp2$, whose meanings are rather self-explanatory. Another often used constraint predicate is $?Var in +Domain$, which means that $Var$ is an element of $Domain$, which can be a single integer, an integer domain bounded by lower and upper limit, or the union of two domains. As for the enumeration of constraints, library(clpfd) deploys the $labeling(+Options, +Vars)$ predicate, which systematically tries out values for the finite domain variables $Var$ until all of them are ground, while $Options$ contain a list of options that allow for extra control over the search process. There are still some new predicates introduced by library(clpfd) but these are the most basic ones. 68 | 69 | One critical step in our transformation to constraint Prolog programs is to add domain declarations for finite domain variables; it is not hard to distinguish between variables and atoms in Prolog thanks to the predicates $var(@Term)$ and $nonvar(@Term)$, yet how to determine whether the variable would bound to a finite domain or not is a challenge due to the fact that vanilla Prolog is a typeless language. As a result, there is no existent predicates in the original Prolog program to help us determine the type of each variable: for unbounded variables, they could be of any type, so it is futile to try getting its type; for bounded variables, we can use $integer(@Term)$ to tell whether it is bound to an integer; the tricky part is those variables that are implicitly bound, which requires a closer examination rather than the naïve $integer(@Term)$ predicate to tell which type it is bound to. Obviously it will not work (dynamic type checking error) if we simply add domain declarations for each variable in the program regardless of their type, so we need to apply type inference in the process of program transformation to locate all the variables that are (or going to) bound to an finite domain. 70 | 71 | One of the first contributions in this field is a polymorphic type system proposed by Mycroft and O'Keefe \cite{mycroft1984polymorphic}, here \emph{polymorphic} denotes the ability to include type variables in the type structures. In this Prolog system, the user need to declare types as restrictions upon the arguments of predicates and terms, and a static type checker would examine if these restrictions are followed. A recent effort was modeled after the Mycroft-O'Keefe type system to gradually introduce types in Prolog (Specifically, SWI-Prolog and YAP) using a type-checking library\cite{schrijvers2008towards}, which achieved a somewhat "on-demand" type system, i.e. runtime type checks are only performed when typed predicates (i.e. predicates whose type signature has already been provided) are invoked, therefore simplifying the migration from untyped code to typed code. Another branch of research, however, focuses on building a type inference system for existed Prolog code, one example was the bottom-up polymorphic type system developed by Barbuti and Giacobazzi \cite{barbuti1992bottom}, which opted for a fixed-point bottom-up abstract interpretation technique to infer types for Horn-Clause based logic programs. Although this system also supports user defined type signatures, they are not necessary as the system is able to infer types for predicates. 72 | 73 | The most recent endeavor in the area is the Gradual Polymorphic Type System with Subtyping for Prolog proposed by Spyros Hadjichristodoulou \cite{hadjichristodoulou2012gradual}, which works as a preprocessor of the original source code to provide both type checking and inference functionalities for XSB-Prolog programs. It ported the type-checking library from \cite{schrijvers2008towards} to work on XSB-Prolog, allowing user to provide type signatures and to invoke the correspondent type-checking library with a complier flag. Its type-inference was also based on the approach of \cite{burstall1977transformation} while adopting the same notations for declaring types in \cite{mycroft1984polymorphic}, which would infer predicates with no pre-defined type signatures. Compared with previous type systems, Hadjichristodoulou's system extended the Mycroft-O'Keefe to allow for the definition of predicates with different types with the introduction of simple-fixed subtyping rules between primitive types that each program can have: for instance, by concluding integer, atom and float as the subtypes of atomic, the user definition of fact $p(20)$ and $p(value)$ will conclude the type $p(atomic)$ for $p/1$ instead of failing; moreover, instead of the "cut-off" method to avoid infinite growth of a predicate type in \cite{barbuti1992bottom}, Hadjichristodoulou suggested using $unify\_with\_occurs\_check$ and concluded that the predicate is ill-typed when its two clauses give types that cannot be unified the occurs check. 74 | 75 | \section{Methodology}\label{methodology} 76 | 77 | One crucial task is to implement the transformation from Prolog code into Constraint Logic Prolog code, i.e. SWI-Prolog code to SWI-Prolog code under the library(cfd). Up till now, we haven't yet incorporated a type inference system to aid transformation, therefore its capabilities are limited. For our initial trial, our methodology is demonstrated in the pseudocode below: 78 | 79 | \begin{algorithm} 80 | \caption{Transformation from Prolog to CLP} 81 | \label{algo1} 82 | \begin{algorithmic}[1] 83 | \Procedure{Transform}{$P$} 84 | \Comment{$P$ is the original Prolog program} 85 | \For {each clause p$_i$ in $P$} 86 | \State transform\_clause p$_i$ to c$_i$ 87 | \Comment{c$_i$ is the corresponding CLP clause} 88 | \State add clause c$_i$ to $C$ 89 | \EndFor 90 | \State Return $C$ 91 | \Comment{$C$ is the transformed CLP program} 92 | \EndProcedure 93 | \end{algorithmic} 94 | \end{algorithm} 95 | 96 | As shown in algorithm \ref{algo1}, the main idea of transformation is quite straightforward: we first read in each clause of the original Prolog program with a simple iteration of the $read\_file/3$ predicate came as the API provided by SWI-Prolog until it has reached the end of the input stream (also supported by the $at_end_of_stream/1$ predicate from SWI-Prolog), then transform each clause of the original program into the corresponding CLP clause before building up the new CLP program. Because of the grammar difference between Prolog and SWI-Prolog, the most difficult part lies within the transformation of each individual clauses: 97 | 98 | \begin{algorithm} 99 | \caption{Transformation of Prolog clause to CLP clause} 100 | \label{algo2} 101 | \begin{algorithmic}[1] 102 | \Procedure{Transform\_clause}{$p$} 103 | \Comment{$p$ is the original Prolog clause} 104 | \State $read\_clause(p, Variablelist, \_)$ 105 | \State $sortout(Variablelist)$ 106 | \State $insert\_definition(p, Variablelist, p')$ 107 | \State $convert\_expressions(p', c)$ 108 | \State Return $c$ 109 | \Comment{$c$ is the transformed CLP clause} 110 | \EndProcedure 111 | \end{algorithmic} 112 | \end{algorithm} 113 | 114 | As further demonstrated in algorithm \ref{algo2}, the transformation of each Prolog clause can be divided into three steps: first, it is necessary to identify the list of variables in the original clause, which could be extracted using the $read\_clause/3$ predicate provided by SWI-Prolog; after we have sorted out the variable list, i.e. get rid of repetitive ones, we add the finite domain declarations for each variable in the beginning of the clause body: 115 | \begin{equation}\label{eq1} 116 | Head(V_1, ..., V_n) :- V_1\,in\,inf..sup, ..., V_n\,in\,inf..sup, Body. 117 | \end{equation} 118 | Note that here $Head$ and $Body$ both symbolize the corresponding part within each Prolog clause, while $V_1, V_2, ... ,V_n$ stand for the processed variable list extracted from $read\_clause/3$ . We find that here all the variables are sloppily treated as singular finite domain variables, which is often the case, and would lead to the problem demonstrated in the section \ref{results}. 119 | 120 | The $convert\_expression$ procedure is rather self-explanatory: all the arithmetic expressions would be transformed to its constraint logic programming format, for instance, $Exp1=, #>). 88 | transfer(\=, #\=). 89 | transfer(=<, #=<). 90 | transfer(>=, #>=). 91 | transfer(=:=, #=:=). 92 | transfer(=/=, #=/=). 93 | transfer(is, #=). 94 | transfer(X, X). 95 | -------------------------------------------------------------------------------- /src/type.pl: -------------------------------------------------------------------------------- 1 | /** 2 | * this is a prolog file 3 | */ 4 | 5 | nat(o). 6 | nat(s(N)) :- nat(N). 7 | 8 | bool(true). 9 | bool(false). 10 | 11 | type(A, nat) :- nat(A), !. 12 | type(A, bool) :- bool(A), !. 13 | type(id, arrow(A, A)) :- !. 14 | type(add, arrow(nat, arrow(nat, nat))) :- !. 15 | type(not, arrow(bool, bool)) :- !. 16 | type(const, arrow(A, arrow(_, A))). 17 | 18 | type(app(F, P), R) :- 19 | type(F, arrow(A, B)), 20 | var(A), 21 | type(P, A), 22 | R = B, 23 | !. 24 | 25 | type(app(F, P), R) :- 26 | type(F, arrow(A, B)), 27 | atom(A), 28 | get_type(types, A, TypeA), 29 | % type already exists in environment 30 | !, 31 | type(P, TypeA), 32 | type_in_env(B, R), 33 | !. 34 | 35 | type(app(F, P), R) :- 36 | type(F, arrow(A, B)), 37 | atom(A), 38 | % type doesn't exist in environment 39 | type(P, TypeP), 40 | add_type(types, A, TypeP), 41 | type_in_env(B, R), 42 | !. 43 | 44 | init_state(Name) :- 45 | empty_assoc(A), 46 | nb_setval(Name, A). 47 | 48 | add_type(SName, TermName, Type) :- 49 | nb_getval(SName, State), 50 | get_assoc(TermName, State, Type). 51 | 52 | type_in_env(T, T1) :- get_type(types, T, T1). 53 | type_in_env(T, T). 54 | 55 | type() 56 | --------------------------------------------------------------------------------