├── LICENSE ├── README.md ├── assemble.p ├── bin ├── forestfire ├── fourier ├── heatequation ├── householder ├── multiplication ├── nbody ├── pipeline ├── primality ├── salesperson ├── shortestpaths └── sorting ├── common.p ├── compile.p ├── examples ├── forestfire.sp ├── fourier.sp ├── heatequation.sp ├── householder.sp ├── multiplication.sp ├── nbody.sp ├── pipeline.sp ├── primality.sp ├── salesperson.sp ├── shortestpaths.sp └── sorting.sp ├── interpret.p ├── notes.tex ├── parse.p ├── readthis.tex ├── report.tex ├── scan.p ├── software.shar ├── sun3.user ├── sun4.user └── user.tex /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Christopher D. Long 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ```bash 2 | fpc -O3 -Miso -Fabaseunix interpret.p 3 | fpc -O3 -Miso compile.p 4 | ``` 5 | ``` 6 | ./compile 7 | source = examples/primality.sp 8 | code = bin/primality 9 | 10 | ./interpret 11 | code = bin/primality 12 | select files? no 13 | 14 | Primality testing: 15 | 10 digits, 2 trials, 2 pipeline nodes 16 | 17 | 1653701519(10) 18 | 0 composite votes, 2 prime votes 19 | 20 | 1653701518(10) 21 | 2 composite votes, 0 prime votes 22 | 23 | 0 s 24 | ``` 25 | -------------------------------------------------------------------------------- /assemble.p: -------------------------------------------------------------------------------- 1 | { SUPERPASCAL COMPILER 2 | ASSEMBLER 3 | 20 August 1993 4 | Copyright (c) 1993 Per Brinch Hansen } 5 | 6 | procedure assemble( 7 | optimizing: boolean; 8 | procedure get(var value: integer); 9 | procedure put(value: integer); 10 | procedure getreal(var value: real); 11 | procedure putreal(value: real); 12 | procedure getstring( 13 | var length: integer; 14 | var value: string); 15 | procedure putstring( 16 | length: integer; 17 | value: string); 18 | procedure getcase( 19 | var lineno, length: integer; 20 | var table: casetable); 21 | procedure putcase( 22 | lineno, length: integer; 23 | table: casetable); 24 | procedure rerun; 25 | procedure halt(kind: phrase)); 26 | type 27 | operations = set of minoperation 28 | ..maxoperation; 29 | assemblytable = 30 | array [1..maxlabel] of integer; 31 | var 32 | noarguments, oneargument, 33 | twoarguments, threearguments, 34 | fourarguments, fivearguments, 35 | jumps: operations; 36 | blockno, address, op, arg1, arg2, 37 | arg3, arg4, arg5: integer; 38 | realarg: real; 39 | stringarg: string; 40 | casearg: casetable; 41 | table: assemblytable; 42 | 43 | procedure nextinstruction; 44 | begin 45 | get(op); 46 | if op in noarguments then 47 | { skip } 48 | else if op in oneargument then 49 | get(arg1) 50 | else if op in twoarguments then 51 | begin 52 | get(arg1); get(arg2) 53 | end 54 | else if op in threearguments then 55 | begin 56 | get(arg1); get(arg2); 57 | get(arg3) 58 | end 59 | else if op in fourarguments then 60 | begin 61 | get(arg1); get(arg2); 62 | get(arg3); get(arg4) 63 | end 64 | else if op in fivearguments then 65 | begin 66 | get(arg1); get(arg2); 67 | get(arg3); get(arg4); 68 | get(arg5) 69 | end 70 | else if op = realconst2 then 71 | getreal(realarg) 72 | else if op = stringconst2 then 73 | getstring(arg1, stringarg) 74 | else { op = caseconst2 } 75 | getcase(arg1, arg2, 76 | casearg) 77 | end; 78 | 79 | procedure emit1(op: integer); 80 | begin 81 | put(op); 82 | address := address + 1 83 | end; 84 | 85 | procedure emit2( 86 | op, arg: integer); 87 | begin 88 | put(op); put(arg); 89 | address := address + 2 90 | end; 91 | 92 | procedure emit3( 93 | op, arg1, arg2: integer); 94 | begin 95 | put(op); put(arg1); 96 | put(arg2); 97 | address := address + 3 98 | end; 99 | 100 | procedure emit4( 101 | op, arg1, arg2, 102 | arg3: integer); 103 | begin 104 | put(op); put(arg1); 105 | put(arg2); put(arg3); 106 | address := address + 4 107 | end; 108 | 109 | procedure emit5( 110 | op, arg1, arg2, arg3, 111 | arg4: integer); 112 | begin 113 | put(op); put(arg1); 114 | put(arg2); put(arg3); 115 | put(arg4); 116 | address := address + 5 117 | end; 118 | 119 | procedure emit6( 120 | op, arg1, arg2, arg3, 121 | arg4, arg5: integer); 122 | begin 123 | put(op); put(arg1); 124 | put(arg2); put(arg3); 125 | put(arg4); put(arg5); 126 | address := address + 6 127 | end; 128 | 129 | procedure emit7( 130 | op, arg1, arg2, arg3, arg4, 131 | arg5, arg6: integer); 132 | begin 133 | put(op); put(arg1); 134 | put(arg2); put(arg3); 135 | put(arg4); put(arg5); 136 | put(arg6); 137 | address := address + 7 138 | end; 139 | 140 | procedure emitreal( 141 | value: real); 142 | begin 143 | put(realconst2); 144 | putreal(value); 145 | address := address + 3 146 | end; 147 | 148 | procedure emitstring( 149 | length: integer; 150 | value: string); 151 | begin 152 | put(stringconst2); 153 | putstring(length, value); 154 | address := 155 | address + length + 2 156 | end; 157 | 158 | procedure emitcase( 159 | lineno, length: integer; 160 | table: casetable); 161 | begin 162 | put(case2); 163 | putcase(lineno, length, 164 | table); 165 | address := 166 | address + 2*length + 3 167 | end; 168 | 169 | procedure newblock; 170 | begin 171 | if blockno = maxblock then 172 | halt(maxblock5); 173 | blockno := blockno + 1 174 | end; 175 | 176 | function optimize(condition: 177 | boolean): boolean; 178 | begin 179 | optimize := 180 | optimizing and condition 181 | end; 182 | 183 | function templength(labelno: 184 | integer): integer; 185 | begin 186 | { include block link 187 | (or process state) 188 | of length 4 (or 3) } 189 | templength := 190 | table[labelno] + 4 191 | end; 192 | 193 | function jumpdispl(labelno: 194 | integer): integer; 195 | begin 196 | jumpdispl := 197 | table[labelno] - address 198 | end; 199 | 200 | procedure assign( 201 | length: integer); 202 | begin 203 | if optimize(length = 1) 204 | then emit1(ordassign2) 205 | else if optimize(length = 2) 206 | then emit1(realassign2) 207 | else emit2(assign2, length); 208 | nextinstruction 209 | end; 210 | 211 | procedure casex( 212 | lineno, length: integer; 213 | table: casetable); 214 | var i: integer; 215 | begin 216 | for i := 1 to length do 217 | table[i].index := 218 | jumpdispl( 219 | table[i].index); 220 | emitcase(lineno, length, 221 | table); 222 | nextinstruction 223 | end; 224 | 225 | procedure defaddr(labelno: 226 | integer); 227 | begin 228 | table[labelno] := address; 229 | nextinstruction 230 | end; 231 | 232 | procedure defarg(labelno, 233 | value: integer); 234 | begin 235 | table[labelno] := value; 236 | nextinstruction 237 | end; 238 | 239 | procedure endprocess(exitlabel, 240 | lineno: integer); 241 | begin 242 | emit3(endprocess2, 243 | jumpdispl(exitlabel), 244 | lineno); 245 | nextinstruction 246 | end; 247 | 248 | procedure field(displ: integer); 249 | begin 250 | if optimize(displ = 0) 251 | then { empty } 252 | else emit2(field2, displ); 253 | nextinstruction 254 | end; 255 | 256 | procedure forall(templabel, 257 | endlabel, lineno: integer); 258 | begin 259 | newblock; 260 | emit5(forall2, blockno, 261 | templength(templabel), 262 | jumpdispl(endlabel), 263 | lineno); 264 | nextinstruction 265 | end; 266 | 267 | procedure jump(op, labelno: 268 | integer); 269 | begin 270 | { op in [do2, downto2, 271 | enddown2, endto2, 272 | goto2, to2] } 273 | emit2(op, 274 | jumpdispl(labelno)); 275 | nextinstruction 276 | end; 277 | 278 | procedure proccall(level, 279 | labelno: integer); 280 | var displ: integer; 281 | begin 282 | displ := jumpdispl(labelno); 283 | if optimize(level = 1) then 284 | emit2(globalcall2, displ) 285 | else 286 | emit3(proccall2, level, 287 | displ); 288 | nextinstruction 289 | end; 290 | 291 | procedure procedur(paramlength, 292 | varlabel, templabel, 293 | beginlabel, lineno: integer); 294 | begin 295 | newblock; 296 | emit7(procedure2, blockno, 297 | paramlength, 298 | table[varlabel], 299 | templength(templabel), 300 | jumpdispl(beginlabel), 301 | lineno); 302 | nextinstruction 303 | end; 304 | 305 | procedure process(templabel, 306 | endlabel, lineno: integer); 307 | begin 308 | newblock; 309 | emit5(process2, blockno, 310 | templength(templabel), 311 | jumpdispl(endlabel), 312 | lineno); 313 | nextinstruction 314 | end; 315 | 316 | procedure programx(varlabel, 317 | templabel, beginlabel, 318 | lineno: integer); 319 | begin 320 | newblock; 321 | emit6(program2, blockno, 322 | table[varlabel], 323 | templength(templabel), 324 | jumpdispl(beginlabel), 325 | lineno); 326 | nextinstruction 327 | end; 328 | 329 | procedure value(length: integer); 330 | begin 331 | if optimize(length = 1) 332 | then emit1(ordvalue2) 333 | else if optimize(length = 2) 334 | then emit1(realvalue2) 335 | else emit2(value2, length); 336 | nextinstruction 337 | end; 338 | 339 | procedure variable(level, displ: 340 | integer); 341 | begin 342 | if displ >= 0 then 343 | { include block link 344 | of length 4 } 345 | displ := displ + 4; 346 | nextinstruction; 347 | while optimize(op = field2) do 348 | begin 349 | displ := displ + arg1; 350 | nextinstruction 351 | end; 352 | if optimize(level = 0) then 353 | if (op = value2) and 354 | (arg1 = 1) then 355 | begin 356 | emit2(localvalue2, 357 | displ); 358 | nextinstruction 359 | end 360 | else if (op = value2) and 361 | (arg1 = 2) then 362 | begin 363 | emit2(localreal2, 364 | displ); 365 | nextinstruction 366 | end 367 | else emit2(localvar2, displ) 368 | else if optimize(level = 1) then 369 | if (op = value2) and 370 | (arg1 = 1) then 371 | begin 372 | emit2(globalvalue2, 373 | displ); 374 | nextinstruction 375 | end 376 | else emit2(globalvar2, displ) 377 | else 378 | emit3(variable2, level, displ) 379 | end; 380 | 381 | procedure copyinstruction; 382 | begin 383 | if op in noarguments 384 | then emit1(op) 385 | else if op in oneargument 386 | then emit2(op, arg1) 387 | else if op in twoarguments 388 | then emit3(op, arg1, arg2) 389 | else if op in threearguments 390 | then 391 | emit4(op, arg1, arg2, 392 | arg3) 393 | else if op in fourarguments 394 | then 395 | emit5(op, arg1, arg2, 396 | arg3, arg4) 397 | else if op in fivearguments 398 | then 399 | emit6(op, arg1, arg2, 400 | arg3, arg4, arg5) 401 | else if op = realconst2 402 | then emitreal(realarg) 403 | else { op = stringconst2 } 404 | emitstring(arg1, 405 | stringarg); 406 | nextinstruction 407 | end; 408 | 409 | procedure assemble; 410 | begin 411 | blockno := 0; 412 | address := 0; 413 | nextinstruction; 414 | while op <> endprog2 do 415 | if op = assign2 then 416 | assign(arg1) 417 | else if op = case2 then 418 | casex(arg1, arg2, casearg) 419 | else if op = defaddr2 then 420 | defaddr(arg1) 421 | else if op = defarg2 then 422 | defarg(arg1, arg2) 423 | else if op = endprocess2 then 424 | endprocess(arg1, arg2) 425 | else if op = field2 then 426 | field(arg1) 427 | else if op = forall2 then 428 | forall(arg1, arg2, arg3) 429 | else if op in jumps then 430 | jump(op, arg1) 431 | else if op = proccall2 then 432 | proccall(arg1, arg2) 433 | else if op = procedure2 then 434 | procedur(arg1, arg2, arg3, 435 | arg4, arg5) 436 | else if op = process2 then 437 | process(arg1, arg2, arg3) 438 | else if op = program2 then 439 | programx(arg1, arg2, arg3, 440 | arg4) 441 | else if op = value2 then 442 | value(arg1) 443 | else if op = variable2 then 444 | variable(arg1, arg2) 445 | else copyinstruction; 446 | emit1(endprog2) 447 | end; 448 | 449 | procedure initialize; 450 | var labelno: integer; 451 | begin 452 | noarguments := 453 | [and2, endio2, endproc2, 454 | endprog2, eqord2, eqreal2, 455 | eqstring2, float2, 456 | floatleft2, for2, grord2, 457 | grreal2, grstring2, lsord2, 458 | lsreal2, lsstring2, neord2, 459 | nereal2, nestring2, ngord2, 460 | ngreal2, ngstring2, nlord2, 461 | nlreal2, nlstring2, not2, 462 | odd2, or2, parallel2]; 463 | oneargument := 464 | [abs2, absint2, add2, 465 | addreal2, arctan2, assign2, 466 | assume2, checkio2, chr2, 467 | cos2, divide2, divreal2, 468 | do2, downto2, endall2, 469 | enddown2, endparallel2, 470 | endto2, eof2, eoln2, 471 | equal2, exp2, field2, 472 | goto2, ln2, minus2, 473 | minusreal2, modulo2, multiply2, 474 | multreal2, notequal2, open2, 475 | ordconst2, read2, readint2, 476 | readln2, readreal2, result2, 477 | round2, sin2, sqr2, 478 | sqrint2, sqrt2, subreal2, 479 | subtract2, to2, trunc2, 480 | value2, writeln2, defaddr2]; 481 | twoarguments := 482 | [endprocess2, pred2, 483 | proccall2, succ2, variable2, 484 | varparam2, write2, 485 | writebool2, writeint2, 486 | writestring2, defarg2]; 487 | threearguments := 488 | [forall2, process2, 489 | receive2, send2, 490 | writereal2]; 491 | fourarguments := 492 | [index2, program2]; 493 | fivearguments := 494 | [procedure2]; 495 | jumps := 496 | [do2, downto2, enddown2, 497 | endto2, goto2, to2]; 498 | for labelno := 1 to maxlabel 499 | do table[labelno] := 0 500 | end; 501 | 502 | begin 503 | initialize; assemble; 504 | rerun; assemble 505 | end; 506 | -------------------------------------------------------------------------------- /bin/forestfire: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/forestfire -------------------------------------------------------------------------------- /bin/fourier: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/fourier -------------------------------------------------------------------------------- /bin/heatequation: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/heatequation -------------------------------------------------------------------------------- /bin/householder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/householder -------------------------------------------------------------------------------- /bin/multiplication: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/multiplication -------------------------------------------------------------------------------- /bin/nbody: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/nbody -------------------------------------------------------------------------------- /bin/pipeline: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/pipeline -------------------------------------------------------------------------------- /bin/primality: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/primality -------------------------------------------------------------------------------- /bin/salesperson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/salesperson -------------------------------------------------------------------------------- /bin/shortestpaths: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/shortestpaths -------------------------------------------------------------------------------- /bin/sorting: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/bin/sorting -------------------------------------------------------------------------------- /common.p: -------------------------------------------------------------------------------- 1 | { SUPERPASCAL COMPILER AND INTERPRETER 2 | COMMON BLOCK 3 | 3 Novemver 1993 4 | Copyright (c) 1993 Per Brinch Hansen } 5 | 6 | const 7 | { compilation options } 8 | 9 | testoptions = false; 10 | restricted = true; 11 | 12 | { software limits } 13 | 14 | maxaddr = 100000; maxblock = 200; 15 | maxbuf = 10000; maxcase = 128; 16 | { maxchan was 10000 } 17 | maxchan = 1000000; maxchar = 10000; 18 | maxlabel = 1000; maxlevel = 10; 19 | maxphrase = 30; maxstring = 80; 20 | minreal = 1.0e-307; 21 | maxreal = 1.0e+307; 22 | 23 | { standard identifiers } 24 | 25 | minstandard = 1; 26 | maxstandard = 34; 27 | abs0 = 1; arctan0 = 2; 28 | boolean0 = 3; char0 = 4; 29 | chr0 = 5; cos0 = 6; 30 | eof0 = 7; eoln0 = 8; 31 | exp0 = 9; false0 = 10; 32 | integer0 = 11; ln0 = 12; 33 | maxint0 = 13; maxstring0 = 14; 34 | null0 = 15; odd0 = 16; 35 | open0 = 17; ord0 = 18; 36 | pred0 = 19; read0 = 20; 37 | readln0 = 21; real0 = 22; 38 | receive0 = 23; round0 = 24; 39 | send0 = 25; sin0 = 26; 40 | sqr0 = 27; sqrt0 = 28; 41 | string0 = 29; succ0 = 30; 42 | true0 = 31; trunc0 = 32; 43 | write0 = 33; writeln0 = 34; 44 | 45 | { tokens } 46 | 47 | mintoken = 0; maxtoken = 59; 48 | and1 = 0; array1 = 1; 49 | assume1 = 2; asterisk1 = 3; 50 | bar1 = 4; becomes1 = 5; 51 | begin1 = 6; case1 = 7; 52 | charconst1 = 8; colon1 = 9; 53 | comma1 = 10; const1 = 11; 54 | div1 = 12; do1 = 13; 55 | downto1 = 14; doubledot1 = 15; 56 | else1 = 16; end1 = 17; 57 | endtext1 = 18; equal1 = 19; 58 | for1 = 20; forall1 = 21; 59 | function1 = 22; greater1 = 23; 60 | identifier1 = 24; if1 = 25; 61 | intconst1 = 26; 62 | leftbracket1 = 27; 63 | leftparenthesis1 = 28; 64 | less1 = 29; minus1 = 30; 65 | mod1 = 31; newline1 = 32; 66 | not1 = 33; notequal1 = 34; 67 | notgreater1 = 35; notless1 = 36; 68 | of1 = 37; or1 = 38; 69 | parallel1 = 39; period1 = 40; 70 | plus1 = 41; procedure1 = 42; 71 | program1 = 43; realconst1 = 44; 72 | record1 = 45; repeat1 = 46; 73 | rightbracket1 = 47; 74 | rightparenthesis1 = 48; 75 | semicolon1 = 49; sic1 = 50; 76 | slash1 = 51; stringconst1 = 52; 77 | then1 = 53; to1 = 54; 78 | type1 = 55; until1 = 56; 79 | var1 = 57; while1 = 58; 80 | unknown1 = 59; 81 | 82 | { operation parts } 83 | 84 | minoperation = 0; 85 | maxoperation = 110; 86 | abs2 = 0; absint2 = 1; 87 | add2 = 2; addreal2 = 3; 88 | and2 = 4; arctan2 = 5; 89 | assign2 = 6; assume2 = 7; 90 | case2 = 8; checkio2 = 9; 91 | chr2 = 10; cos2 = 11; 92 | divide2 = 12; divreal2 = 13; 93 | do2 = 14; downto2 = 15; 94 | endall2 = 16; enddown2 = 17; 95 | endio2 = 18; endparallel2 = 19; 96 | endproc2 = 20; endprocess2 = 21; 97 | endprog2 = 22; endto2 = 23; 98 | eof2 = 24; eoln2 = 25; 99 | eqord2 = 26; eqreal2 = 27; 100 | eqstring2 = 28; equal2 = 29; 101 | exp2 = 30; field2 = 31; 102 | float2 = 32; floatleft2 = 33; 103 | for2 = 34; forall2 = 35; 104 | goto2 = 36; grord2 = 37; 105 | grreal2 = 38; grstring2 = 39; 106 | index2 = 40; ln2 = 41; 107 | lsord2 = 42; lsreal2 = 43; 108 | lsstring2 = 44; minus2 = 45; 109 | minusreal2 = 46; modulo2 = 47; 110 | multiply2 = 48; multreal2 = 49; 111 | neord2 = 50; nereal2 = 51; 112 | nestring2 = 52; ngord2 = 53; 113 | ngreal2 = 54; ngstring2 = 55; 114 | nlord2 = 56; nlreal2 = 57; 115 | nlstring2 = 58; not2 = 59; 116 | notequal2 = 60; odd2 = 61; 117 | open2 = 62; or2 = 63; 118 | ordconst2 = 64; parallel2 = 65; 119 | pred2 = 66; proccall2 = 67; 120 | procedure2 = 68; process2 = 69; 121 | program2 = 70; read2 = 71; 122 | readint2 = 72; readln2 = 73; 123 | readreal2 = 74; realconst2 = 75; 124 | receive2 = 76; result2 = 77; 125 | round2 = 78; send2 = 79; 126 | sin2 = 80; sqr2 = 81; 127 | sqrint2 = 82; sqrt2 = 83; 128 | stringconst2 = 84; 129 | subreal2 = 85; subtract2 = 86; 130 | succ2 = 87; to2 = 88; 131 | trunc2 = 89; value2 = 90; 132 | variable2 = 91; varparam2 = 92; 133 | write2 = 93; writebool2 = 94; 134 | writeint2 = 95; writeln2 = 96; 135 | writereal2 = 97; 136 | writestring2 = 98; 137 | globalcall2 = 99; 138 | globalvalue2 = 100; 139 | globalvar2 = 101; 140 | localreal2 = 102; 141 | localvalue2 = 103; 142 | localvar2 = 104; 143 | ordassign2 = 105; 144 | ordvalue2 = 106; 145 | realassign2 = 107; 146 | realvalue2 = 108; 147 | defaddr2 = 109; defarg2 = 110; 148 | 149 | { compile-time errors } 150 | 151 | ambiguous3 = 152 | 'ambiguous identifier '; 153 | block3 = 154 | 'function block error '; 155 | case3 = 156 | 'ambiguous case constant '; 157 | comment3 = 158 | 'incomplete comment '; 159 | forall3 = 160 | 'forall statement error '; 161 | kind3 = 162 | 'identifier kind error '; 163 | number3 = 164 | 'number error '; 165 | parallel3 = 166 | 'parallel statement error '; 167 | parameter3 = 168 | 'function parameter error '; 169 | procedure3 = 170 | 'procedure statement error '; 171 | range3 = 172 | 'index range error '; 173 | recursion3 = 174 | 'recursion error '; 175 | syntax3 = 176 | 'syntax error '; 177 | type3 = 178 | 'type error '; 179 | undefined3 = 180 | 'undefined identifier '; 181 | 182 | { run-time errors } 183 | 184 | assume4 = 185 | 'false assumption '; 186 | case4 = 187 | 'undefined case constant '; 188 | channel4 = 189 | 'undefined channel reference '; 190 | contention4 = 191 | 'channel contention '; 192 | deadlock4 = 193 | 'deadlock '; 194 | range4 = 195 | 'range error '; 196 | type4 = 197 | 'message type error '; 198 | 199 | { software failure } 200 | 201 | maxaddr5 = 202 | 'memory limit exceeded '; 203 | maxblock5 = 204 | 'block limit exceeded '; 205 | maxbuf5 = 206 | 'buffer limit exceeded '; 207 | maxcase5 = 208 | 'case limit exceeded '; 209 | maxchan5 = 210 | 'channel limit exceeded '; 211 | maxchar5 = 212 | 'character limit exceeded '; 213 | maxlabel5 = 214 | 'branch limit exceeded '; 215 | maxlevel5 = 216 | 'nesting limit exceeded '; 217 | maxstring5 = 218 | 'string limit exceeded '; 219 | 220 | { miscellaneous phrases } 221 | 222 | assembled = 223 | 'assembled '; 224 | errorfile = 225 | 'errors '; 226 | fileconflict = 227 | 'use different source and code '; 228 | keyboard = 229 | 'keyboard '; 230 | no = 231 | 'no '; 232 | parsed = 233 | 'parsed '; 234 | scanned = 235 | 'scanned '; 236 | screen = 237 | 'screen '; 238 | yes = 239 | 'yes '; 240 | 241 | { characters and ordinal values } 242 | 243 | apostrophe = '''' ; sp = ' '; 244 | etx = 3; del = 127; nl = 10; 245 | null = 0; 246 | 247 | type 248 | { common types } 249 | 250 | binary = file of integer; 251 | caserecord = 252 | record 253 | value, index: integer 254 | end; 255 | casetable = 256 | array [1..maxcase] of caserecord; 257 | phrase = 258 | packed array [1..maxphrase] of 259 | char; 260 | string = 261 | packed array [1..maxstring] of 262 | char; 263 | { a dual real is used with 264 | an undefined tag field to 265 | convert a real "a" to its 266 | binary representation by 267 | two integers "b" and "c" 268 | (or vice versa) } 269 | dualreal = 270 | record 271 | case split: boolean of 272 | false: (a: real); 273 | true: (b, c: integer) 274 | end; 275 | 276 | { phrase routines } 277 | 278 | function phraselength( 279 | value: phrase): integer; 280 | var i, j: integer; 281 | begin 282 | i := 0; j := maxphrase; 283 | while i < j do 284 | if value[j] = sp 285 | then j := j - 1 286 | else i := j; 287 | phraselength := i 288 | end; 289 | 290 | procedure writephrase( 291 | var outfile: text; 292 | value: phrase); 293 | begin 294 | write(outfile, value: 295 | phraselength(value)) 296 | end; 297 | 298 | procedure readphrase( 299 | var value: phrase); 300 | var ch: char; i: integer; 301 | begin 302 | repeat 303 | while eoln do readln; 304 | read(ch) 305 | until ch <> sp; 306 | value[1] := ch; 307 | for i := 2 to maxphrase do 308 | if not eoln 309 | then read(value[i]) 310 | else value[i] := sp; 311 | while not eoln do read(ch); 312 | readln 313 | end; 314 | 315 | procedure readboolean( 316 | var value: boolean); 317 | var word: phrase; 318 | begin 319 | readphrase(word); 320 | while (word <> yes) 321 | and (word <> no) do 322 | begin 323 | write( 324 | ' yes or no? '); 325 | readphrase(word) 326 | end; 327 | value := (word = yes) 328 | end; 329 | 330 | { string routines } 331 | 332 | function stringlength( 333 | value: string): integer; 334 | var i, j: integer; 335 | begin 336 | i := 0; j := maxstring; 337 | while i < j do 338 | if value[j] = chr(null) 339 | then j := j - 1 340 | else i := j; 341 | stringlength := i 342 | end; 343 | 344 | procedure writestring( 345 | var outfile: text; 346 | value: string; 347 | width: integer); 348 | var i, n: integer; 349 | begin 350 | //writeln('enter writestring'); 351 | //writeln(value:width); 352 | //writeln(width); 353 | n := stringlength(value); 354 | //writeln('n = ',n); 355 | if width > n then 356 | begin 357 | //writeln('width > n'); 358 | for i := 1 to width - n do 359 | write(outfile, sp); 360 | end 361 | else n := width; 362 | write(outfile, value:n); 363 | //writeln('exit writestring'); 364 | end; 365 | -------------------------------------------------------------------------------- /compile.p: -------------------------------------------------------------------------------- 1 | { SUPERPASCAL COMPILER 2 | MAIN PROGRAM 3 | 20 August 1993 4 | Copyright (c) 1993 Per Brinch Hansen } 5 | 6 | program main(input, output); 7 | {$include "common.p"} 8 | {$include "scan.p"} 9 | {$include "parse.p"} 10 | {$include "assemble.p"} 11 | 12 | procedure compile; 13 | label 1 { exit }; 14 | type 15 | table = 16 | array [1..maxbuf] of 17 | integer; 18 | buffer = 19 | record 20 | contents: table; 21 | length: integer 22 | end; 23 | var 24 | sourcename, codename: phrase; 25 | errors, source: text; 26 | code: binary; 27 | inpbuf, outbuf: buffer; 28 | compiled, endline, lineok, 29 | optimizing, testing: boolean; 30 | lineno, pass: integer; 31 | 32 | procedure error(kind: phrase); 33 | var n: integer; 34 | begin 35 | if lineok then 36 | begin 37 | if compiled then 38 | begin 39 | compiled := false; 40 | writeln 41 | end; 42 | n := phraselength(kind); 43 | writeln(errors, 44 | 'line ', lineno:4, sp, 45 | kind:n); 46 | writeln( 47 | 'line ', lineno:4, sp, 48 | kind:n); 49 | lineok := false 50 | end 51 | end; 52 | 53 | procedure halt(kind: phrase); 54 | var n: integer; 55 | begin 56 | if compiled then 57 | begin 58 | compiled := false; 59 | writeln 60 | end; 61 | n := phraselength(kind); 62 | writeln(errors, 63 | 'line ', lineno:4, sp, 64 | kind:n); 65 | writeln( 66 | 'line ', lineno:4, sp, 67 | kind:n); 68 | goto 1 69 | end; 70 | 71 | procedure newline(no: integer); 72 | begin 73 | lineno := no; 74 | lineok := true 75 | end; 76 | 77 | procedure accept(var ch: char); 78 | begin 79 | if eof(source) then 80 | begin 81 | lineno := lineno + 1; 82 | ch := chr(etx) 83 | end 84 | else 85 | begin 86 | if endline then 87 | begin 88 | lineno := lineno + 1; 89 | endline := false; 90 | lineok := true; 91 | if testing then 92 | write(lineno:4, sp) 93 | end; 94 | if eoln(source) then 95 | begin 96 | readln(source); 97 | ch := chr(nl); 98 | endline := true; 99 | if testing then 100 | writeln 101 | end 102 | else 103 | begin 104 | read(source, ch); 105 | if testing then 106 | write(ch) 107 | end 108 | end 109 | end; 110 | 111 | procedure put(value: integer); 112 | begin 113 | if outbuf.length = maxbuf 114 | then halt(maxbuf5); 115 | outbuf.length := 116 | outbuf.length + 1; 117 | outbuf.contents[ 118 | outbuf.length] := value 119 | end; 120 | 121 | procedure get( 122 | var value: integer); 123 | begin 124 | inpbuf.length := 125 | inpbuf.length + 1; 126 | value := inpbuf.contents[ 127 | inpbuf.length]; 128 | if testing then 129 | writeln(pass:1, sp, 130 | value:12) 131 | end; 132 | 133 | procedure getreal( 134 | var value: real); 135 | var dual: dualreal; 136 | begin 137 | dual.split := true; 138 | get(dual.b); 139 | get(dual.c); 140 | dual.split := false; 141 | value := dual.a 142 | end; 143 | 144 | procedure putreal(value: real); 145 | var dual: dualreal; 146 | begin 147 | dual.split := false; 148 | dual.a := value; 149 | dual.split := true; 150 | put(dual.b); 151 | put(dual.c) 152 | end; 153 | 154 | procedure getstring( 155 | var length: integer; 156 | var value: string); 157 | var c, i: integer; 158 | begin 159 | get(length); 160 | for i := 1 to length do 161 | begin 162 | get(c); 163 | value[i] := chr(c) 164 | end; 165 | for i := length + 1 166 | to maxstring do 167 | value[i] := chr(null) 168 | end; 169 | 170 | procedure putstring( 171 | length: integer; 172 | value: string); 173 | var i: integer; 174 | begin 175 | put(length); 176 | for i := 1 to length do 177 | put(ord(value[i])) 178 | end; 179 | 180 | procedure getcase( 181 | var lineno, length: integer; 182 | var table: casetable); 183 | var i: integer; 184 | begin 185 | get(lineno); get(length); 186 | for i := 1 to length do 187 | begin 188 | get(table[i].value); 189 | get(table[i].index) 190 | end 191 | end; 192 | 193 | procedure putcase( 194 | lineno, length: integer; 195 | table: casetable); 196 | var i: integer; 197 | begin 198 | put(lineno); put(length); 199 | for i := 1 to length do 200 | begin 201 | put(table[i].value); 202 | put(table[i].index) 203 | end 204 | end; 205 | 206 | function checksum: integer; 207 | const n = 8191; 208 | var i, sum, x: integer; 209 | begin 210 | sum := 0; 211 | for i := 1 to outbuf.length do 212 | begin 213 | x := outbuf.contents[i]; 214 | sum := 215 | (sum + x mod n) mod n 216 | end; 217 | checksum := sum 218 | end; 219 | 220 | procedure testoutput( 221 | kind: phrase); 222 | const 223 | max = 5 { symbols/line }; 224 | var i, n: integer; 225 | log: text; 226 | begin 227 | if testing then 228 | begin 229 | { nonstandard rewrite } 230 | assign(log, copy(kind,1,phraselength(kind))); 231 | rewrite (log); 232 | writephrase(log, 233 | sourcename); 234 | write(log, sp); 235 | writephrase(log, kind); 236 | writeln(log); 237 | n := outbuf.length; 238 | for i := 1 to 239 | outbuf.length do 240 | begin 241 | if i mod max = 1 242 | then 243 | writeln(log); 244 | write(log, outbuf. 245 | contents[i]:12) 246 | end; 247 | writeln(log); 248 | writeln(log); 249 | writeln(log, 250 | 'check sum = ', 251 | checksum:4); 252 | writeln 253 | end 254 | end; 255 | 256 | procedure codeoutput; 257 | var i: integer; 258 | begin 259 | { nonstandard rewrite } 260 | assign(code, copy(codename,1,phraselength(codename))); 261 | rewrite(code); 262 | for i := 1 to outbuf.length do 263 | write(code, 264 | outbuf.contents[i]) 265 | end; 266 | 267 | procedure rerun; 268 | begin 269 | inpbuf.length := 0; 270 | outbuf.length := 0 271 | end; 272 | 273 | procedure firstpass; 274 | begin 275 | write(' source = '); 276 | readphrase(sourcename); 277 | write(' code = '); 278 | readphrase(codename); 279 | if testoptions then 280 | begin 281 | write( 282 | ' test output? '); 283 | readboolean(testing); 284 | write( 285 | ' optimize? '); 286 | readboolean(optimizing); 287 | if testing then writeln 288 | end 289 | else 290 | begin 291 | testing := false; 292 | optimizing := true 293 | end; 294 | compiled := true; 295 | lineno := 0; 296 | { nonstandard rewrite } 297 | assign(errors, copy(errorfile,1,phraselength(errorfile))); 298 | // assign(errors, errorfile); 299 | rewrite(errors); 300 | writephrase(errors, 301 | sourcename); 302 | writeln(errors); 303 | writeln(errors); 304 | { if sourcename = codename 305 | then halt(fileconflict); } 306 | { nonstandard reset } 307 | //writeln(sourcename); 308 | assign(source, copy(sourcename,1,phraselength(sourcename))); 309 | // assign(source, sourcename); 310 | reset(source); 311 | //writeln(sourcename); 312 | pass := 1; 313 | outbuf.length := 0; 314 | endline := true; 315 | lineno := 0 316 | end; 317 | 318 | procedure nextpass; 319 | begin 320 | pass := pass + 1; 321 | { swap buffers } 322 | inpbuf := outbuf; 323 | inpbuf.length := 0; 324 | outbuf.length := 0 325 | end; 326 | 327 | procedure exit; 328 | begin 329 | if compiled then 330 | writeln(errors, 331 | 'no errors found') 332 | else writeln 333 | end; 334 | 335 | begin 336 | firstpass; 337 | scan(lineno, accept, put, 338 | putreal, putstring, 339 | error, halt); 340 | if compiled then 341 | begin 342 | testoutput(scanned); 343 | nextpass; 344 | parse(newline, get, put, 345 | getreal, putreal, 346 | getstring, putstring, 347 | putcase, error, halt); 348 | if compiled then 349 | begin 350 | testoutput(parsed); 351 | nextpass; 352 | assemble(optimizing, 353 | get, put, getreal, 354 | putreal, getstring, 355 | putstring, getcase, 356 | putcase, rerun, 357 | halt); 358 | if compiled then 359 | begin 360 | testoutput( 361 | assembled); 362 | codeoutput 363 | end 364 | end 365 | end; 366 | 1: exit 367 | end { compile }; 368 | 369 | begin compile end. 370 | -------------------------------------------------------------------------------- /examples/forestfire.sp: -------------------------------------------------------------------------------- 1 | program forestfire(input, output); 2 | const 3 | n = 20 { n x n interior grid elements, n = q*m }; 4 | q = 2 { q x q processor nodes }; 5 | m = 10 { m x m interior subgrid elements, m even }; 6 | m1 = 11 { m+1 }; 7 | steps = n; 8 | pa = 0.30 { Prob(alive) }; 9 | pb = 0.01 { Prob(burning) }; 10 | 11 | type 12 | state = (alive, burning, dead); 13 | row = array [1..n] of state; 14 | grid = array [1..n] of row; 15 | 16 | procedure fire(var u: grid; u1, u2, u3, u4, u5: state; steps: integer); 17 | type 18 | subrow = array [0..m1] of state; 19 | subgrid = array [0..m1] of subrow; 20 | channel = *(state); 21 | 22 | procedure node(qi, qj, steps: integer; up, down, left, right: channel); 23 | var u: subgrid; k: integer; seed: real; 24 | 25 | procedure copy(no: integer; inp, out: channel); 26 | var k: integer; uk: state; 27 | begin 28 | for k := 1 to no do 29 | begin 30 | receive(inp, uk); 31 | send(out, uk) 32 | end 33 | end; 34 | 35 | procedure output(qi, qj: integer; inp, out: channel; var u: subgrid); 36 | var i, j: integer; 37 | begin 38 | for i := 1 to m do 39 | begin 40 | for j := 1 to m do 41 | send(out, u[i,j]); 42 | copy((q - qj)*m, inp, out) 43 | end; 44 | copy((q - qi)*m*n, inp, out) 45 | end; 46 | 47 | procedure phase1(qi, qj, b: integer; up, down, left, right: channel; var u: subgrid); 48 | var k, last: integer; 49 | begin 50 | k := 2 - b; 51 | last := m - b; 52 | while k <= last do 53 | begin 54 | { 1 <= k <= m } 55 | [sic] parallel 56 | if qi > 1 then 57 | receive(up, u[0,k])| 58 | if qi < q then 59 | send(down, u[m,k])| 60 | if qj > 1 then 61 | receive(left, u[k,0])| 62 | if qj < q then 63 | send(right, u[k,m]) 64 | end; 65 | k := k + 2 66 | end 67 | end; 68 | 69 | procedure phase2(qi, qj, b: integer; up, down, left, right: channel; var u: subgrid); 70 | var k, last: integer; 71 | begin 72 | k := b + 1; 73 | last := m + b - 1; 74 | while k <= last do 75 | begin 76 | { 1 <= k <= m } 77 | [sic] parallel 78 | if qi > 1 then 79 | send(up, u[1,k])| 80 | if qi < q then 81 | receive(down, u[m+1,k])| 82 | if qj > 1 then 83 | send(left, u[k,1])| 84 | if qj < q then 85 | receive(right, u[k,m+1]) 86 | end; 87 | k := k + 2 88 | end 89 | end; 90 | 91 | procedure exchange(qi, qj, b: integer; up, down, left, right: channel; var u: subgrid); 92 | begin 93 | phase1(qi, qj, b, up, down, left, right, u); 94 | phase2(qi, qj, b, up, down, left, right, u) 95 | end; 96 | 97 | function initial(i, j: integer): state; 98 | begin 99 | if i = 0 then 100 | initial := u1 101 | else if i = n + 1 then 102 | initial := u2 103 | else if j = n + 1 then 104 | initial := u3 105 | else if j = 0 then 106 | initial := u4 107 | else 108 | initial := u5 109 | end; 110 | 111 | procedure random(var no: real); 112 | { 0 <= no <= 1 } 113 | const a = 16807.0; m = 2147483647.0; 114 | var temp: real; 115 | begin 116 | temp := a*seed; 117 | seed := temp - m*trunc(temp/m); 118 | no := seed/m 119 | end; 120 | 121 | procedure nextstate(var u: subgrid; i, j: integer); 122 | { 1 <= i <= m, 1 <=j <=m} 123 | var x: real; 124 | begin 125 | case u[i,j] of 126 | alive: 127 | if 128 | (u[i-1,j] = burning) or 129 | (u[i+1,j] = burning) or 130 | (u[i,j+1] = burning) or 131 | (u[i,j-1] = burning) 132 | then u[i,j]:= burning 133 | else 134 | begin 135 | random(x); 136 | if x <= pb then 137 | u[i,j] := burning 138 | end; 139 | burning: 140 | u[i,j] := dead; 141 | dead: 142 | begin 143 | random(x); 144 | if x <= pa then 145 | u[i,j] := alive 146 | end 147 | end 148 | end; 149 | 150 | procedure newgrid(qi, qj : integer; var u: subgrid); 151 | var i, i0, j, j0: integer; 152 | begin 153 | i0 := (qi - 1)*m; 154 | j0 := (qj - 1)*m; 155 | for i := 0 to m + 1 do 156 | for j := 0 to m + 1 do 157 | u[i,j] := initial(i0+i, j0+j) 158 | end; 159 | 160 | procedure relax(qi, qj: integer; up, down, left, right: channel; var u: subgrid); 161 | var b, i, j, k: integer; 162 | begin 163 | for b := 0 to 1 do 164 | begin 165 | exchange(qi, qj, 1 - b, up, down, left, right, u); 166 | for i := 1 to m do 167 | begin 168 | k := (i + b) mod 2; 169 | j := 2 - k; 170 | while j <= m - k do 171 | begin 172 | nextstate(u, i, j); 173 | j := j + 2 174 | end 175 | end 176 | end 177 | end; 178 | 179 | begin 180 | seed := 1.0; 181 | newgrid(qi, qj, u); 182 | for k := 1 to steps do 183 | relax(qi, qj, up, down,left, right, u); 184 | output(qi,qj, right, left, u) 185 | end { node }; 186 | 187 | procedure master(right: channel; var u: grid); 188 | var i, j: integer; 189 | begin 190 | for i := 1 to n do 191 | for j := 1 to n do 192 | receive(right, u[i,j]) 193 | end; 194 | 195 | procedure simulate(steps: integer; var u: grid); 196 | type 197 | line = array [1..q] of channel; 198 | matrix = array [0..q] of line; 199 | var h, v: matrix; i, j: integer; 200 | begin 201 | open(h[0,q]); 202 | for i := 1 to q do 203 | for j := 1 to q do 204 | open(h[i,j]); 205 | for i := 0 to q do 206 | for j := 1 to q do 207 | open(v[i,j]); 208 | parallel 209 | master(h[0,q], u)| 210 | forall j := 1 to q do 211 | node(j, 1, steps, v[j-1,1], v[j,1], h[j-1,q] , h[j,1])| 212 | forall i := 1 to q do 213 | forall j := 2 to q do 214 | node(i, j, steps, v[i-1,j], v[i,j], h[i,j-1], h[i,j]) 215 | end 216 | end; 217 | 218 | begin simulate(steps, u) end { fire }; 219 | 220 | procedure run; 221 | var u: grid; 222 | 223 | procedure display(var u: grid); 224 | var i, j: integer; 225 | begin 226 | for i := 1 to n do 227 | begin 228 | for j := 1 to n do 229 | case u[i,j] of 230 | alive: write('+ '); 231 | burning: write('* '); 232 | dead: write(' ') 233 | end; 234 | writeln 235 | end 236 | end; 237 | 238 | begin 239 | fire(u, dead, dead, dead, dead, alive, steps); 240 | display(u) 241 | end { run }; 242 | 243 | begin 244 | writeln('Forest fire matrix:', ' n = ', n:1, ', p = ', q*q:1); 245 | writeln; run 246 | end. 247 | -------------------------------------------------------------------------------- /examples/fourier.sp: -------------------------------------------------------------------------------- 1 | program fourier(input, output); 2 | const 3 | d = 2 { tree depth: log(p+l)-l }; 4 | p = 7 { tree nodes: 2**(d+l)-l }; 5 | n = 128 { items: 2power>=2**d }; 6 | type 7 | complex = record re, im: real end; 8 | table = array [1..n] of complex; 9 | 10 | { complex arithmetic } 11 | function pair (re, im: real): complex; 12 | var a: complex; 13 | begin 14 | a.re := re; 15 | a.im := im; 16 | pair := a 17 | end; 18 | 19 | function sum(a, b: complex): complex; 20 | begin 21 | a.re := a.re + b.re; 22 | a.im := a.im + b.im; 23 | sum := a 24 | end; 25 | 26 | function difference(a, b: complex): complex; 27 | begin 28 | a.re := a.re - b.re; 29 | a.im := a.im - b.im; 30 | difference := a 31 | end; 32 | 33 | function product (a, b: complex): complex; 34 | var c: complex; 35 | begin 36 | c.re := a.re*b.re - a.im*b.im; 37 | c.im := a.re*b.im + a.im*b.re; 38 | product := c 39 | end; 40 | 41 | { discrete fourier transform } 42 | procedure dft(var a: table); 43 | type channel = *(complex, integer); 44 | var bottom: channel; 45 | 46 | procedure permute(var a: table); 47 | type map = array [1..n] of integer; 48 | var rev: map; half, incr, size, j, k: integer; aj: complex; 49 | begin 50 | rev[1] := 1; 51 | half := n div 2; 52 | size := 1; 53 | while size <= half do 54 | begin 55 | incr := half div size; 56 | for j := 1 to size do 57 | rev[j + size] := rev[j] + incr; 58 | size := 2*size 59 | end; 60 | for j := 1 to n do 61 | begin 62 | k := rev[j]; 63 | if j < k then 64 | begin 65 | aj := a[j]; 66 | a[j] := a[k]; 67 | a[k] := aj 68 | end 69 | end 70 | end; 71 | 72 | procedure combine(var a: table; first, last: integer); 73 | const pi = 3.1415926536; 74 | var even, half, odd, j: integer; w, wj, x: complex; 75 | begin 76 | half := (last - first + 1) div 2; 77 | w := pair(cos(pi/half), sin(pi/half)); 78 | wj := pair(1, 0); 79 | for j := 0 to half - 1 do 80 | begin 81 | even := first + j; 82 | odd := even + half; 83 | x := product (wj, a[odd]); 84 | a[odd] := difference(a[even], x); 85 | a[even] := sum (a[even], x); 86 | wj := product (wj, w) 87 | end 88 | end; 89 | 90 | procedure fft(var a: table; first, last: integer); 91 | var size, k, m: integer; 92 | begin 93 | m := last - first + 1; 94 | size := 2; 95 | while size <= m do 96 | begin 97 | k := first + size - 1; 98 | while k <= last do 99 | begin 100 | combine(a, k - size + 1, k); 101 | k := k + size 102 | end; 103 | size := 2*size 104 | end 105 | end; 106 | 107 | procedure leaf(bottom: channel); 108 | var a: table; first, last, i: integer; 109 | begin 110 | receive(bottom, first, last); 111 | for i := first to last do 112 | receive(bottom, a[i]); 113 | fft(a, first, last); 114 | for i := first to last do 115 | send(bottom, a[i]) 116 | end; 117 | 118 | procedure root(bottom, left, right: channel); 119 | var a: table; first, last, middle, middle2, i: integer; 120 | begin 121 | receive(bottom, first, last); 122 | for i := first to last do 123 | receive(bottom, a[i]); 124 | middle := (first + last) div 2; 125 | send (left, first, middle); 126 | for i := first to middle do 127 | send(left, a[i]); 128 | middle2 := middle + 1; 129 | send(right, middle2, last); 130 | for i := middle2 to last do 131 | send (right, a[i]); 132 | for i := first to middle do 133 | receive (left, a[i]); 134 | for i := middle2 to last do 135 | receive (right, a[i]); 136 | combine(a, first, last); 137 | for i := first to last do 138 | send(bottom, a[i]) 139 | end; 140 | 141 | procedure tree(depth: integer; bottom: channel); 142 | var left, right: channel; 143 | begin 144 | if depth > 0 then 145 | begin 146 | open (left, right); 147 | parallel 148 | tree(depth - 1, left)| 149 | tree(depth - 1, right)| 150 | root(bottom, left, right) 151 | end 152 | end 153 | else 154 | leaf(bottom) 155 | end; 156 | 157 | procedure master(var a: table; bottom: channel); 158 | var i: integer; 159 | begin 160 | send(bottom, 1, n); 161 | for i := 1 to n do 162 | send(bottom, a[i]); 163 | for i := 1 to n do 164 | receive(bottom, a[i]) 165 | end; 166 | 167 | begin 168 | permute(a); 169 | open(bottom); 170 | parallel 171 | tree(d, bottom)| 172 | master(a, bottom) 173 | end 174 | end { dft}; 175 | 176 | procedure run; 177 | var a: table; seed: real; 178 | 179 | procedure random(var value: real); 180 | { 0 <= value <= 1 } 181 | const a = 16807.0; m = 2147483647.0; 182 | var temp: real; 183 | begin 184 | temp := a*seed; 185 | seed := temp - m*trunc(temp/m); 186 | value := seed/m 187 | end; 188 | 189 | procedure initialize (var a: table); 190 | var i: integer; re: real; 191 | begin 192 | seed := 1.0; 193 | for i := 1 to n do 194 | begin 195 | random(re); 196 | a[i] := pair(re, 0) 197 | end 198 | end; 199 | 200 | procedure display(a: table); 201 | const m = 4 { items/line }; 202 | var i, j, k: integer; aij: complex; 203 | begin 204 | k := n div m; 205 | for i := 0 to k - 1 do 206 | begin 207 | for j := 1 to m do 208 | begin 209 | aij :=a[i*m + j]; 210 | write(aij.re:8, ' ', aij.im:8, ', ') 211 | end; 212 | writeln 213 | end; 214 | writeln 215 | end; 216 | 217 | begin 218 | initialize(a); 219 | dft(a); 220 | display(a) 221 | end { run }; 222 | begin 223 | writeln('FFT tree:', ' n = ', n:1, ', p = ', p:1); 224 | writeln; 225 | run 226 | end. 227 | -------------------------------------------------------------------------------- /examples/heatequation.sp: -------------------------------------------------------------------------------- 1 | program heatequation(input, output); 2 | const 3 | n = 20 { n x n interior grid elements, n = q*m }; 4 | q = 2 { q x q processor nodes }; 5 | m = 10 { m x m interior subgrid elements, m even }; 6 | m1 = 11 { m+1 }; 7 | steps = n; 8 | type 9 | row = array [1..n] of real; 10 | grid = array [1..n] of row; 11 | 12 | procedure laplace(var u: grid; u1, u2, u3, u4, u5: real; steps: integer); 13 | type 14 | subrow = array [0..m1] of real; 15 | subgrid = array [0..m1] of subrow; 16 | channel = *(real); 17 | 18 | procedure node(qi, qj, steps: integer; up, down, left, right: channel); 19 | const pi = 3.14159265358979; 20 | var u: subgrid; k: integer; fopt: real; 21 | 22 | procedure copy(no: integer; inp, out: channel); 23 | var k: integer; uk: real; 24 | begin 25 | for k := 1 to no do 26 | begin 27 | receive(inp, uk); 28 | send(out, uk) 29 | end 30 | end; 31 | 32 | procedure output(qi, qj: integer; inp, out: channel; var u: subgrid); 33 | var i, j: integer; 34 | begin 35 | for i := 1 to m do 36 | begin 37 | for j := 1 to m do 38 | send(out, u[i,j]); 39 | copy((q - qj)*m, inp, out) 40 | end; 41 | copy((q - qi)*m*n, inp, out) 42 | end; 43 | 44 | procedure phase1(qi, qj, b: integer; up, down, left, right: channel; var u: subgrid); 45 | var k, last: integer; 46 | begin 47 | k := 2 - b; 48 | last := m - b; 49 | while k <= last do 50 | begin 51 | { 1 <= k <= m } 52 | [sic] parallel 53 | if qi > 1 then 54 | receive(up, u[0,k])| 55 | if qi < q then 56 | send(down, u[m,k])| 57 | if qj > 1 then 58 | receive(left, u[k,0])| 59 | if qj < q then 60 | send(right, u[k,m]) 61 | end; 62 | k := k + 2 63 | end 64 | end; 65 | 66 | procedure phase2(qi, qj, b: integer; up, down, left, right: channel; var u: subgrid); 67 | var k, last: integer; 68 | begin 69 | k := b + 1; 70 | last := m + b - 1; 71 | while k <= last do 72 | begin 73 | { 1 <= k <= m } 74 | [sic] parallel 75 | if qi > 1 then 76 | send(up, u[1,k])| 77 | if qi < q then 78 | receive(down, u[m+1,k])| 79 | if qj > 1 then 80 | send(left, u[k,1])| 81 | if qj < q then 82 | receive(right, u[k,m+1]) 83 | end; 84 | k := k + 2 85 | end 86 | end; 87 | 88 | procedure exchange(qi, qj, b: integer; up, down, left, right: channel; var u: subgrid); 89 | begin 90 | phase1(qi, qj, b, up, down, left, right, u); 91 | phase2(qi, qj, b, up, down, left, right, u) 92 | end; 93 | 94 | function initial(i, j: integer): real; 95 | begin 96 | if i = 0 then 97 | initial := u1 98 | else if i = n + 1 then 99 | initial := u2 100 | else if j = n + 1 then 101 | initial := u3 102 | else if j = 0 then 103 | initial := u4 104 | else 105 | initial := u5 106 | end; 107 | 108 | procedure nextstate(var u: subgrid; i, j: integer); 109 | { 1 <= i <= m, 1 <= j <= m} 110 | var res: real; 111 | begin 112 | res := (u[i-1,j] + u[i+1,j] + u[i,j+1] + u[i,j-1])/4.0 - u[i,j]; 113 | u[i,j] := u[i,j] + fopt*res 114 | end; 115 | 116 | procedure newgrid(qi, qj: integer; var u: subgrid); 117 | var i, i0, j, j0: integer; 118 | begin 119 | i0 := (qi - 1)*m; 120 | j0 := (qj - 1)*m; 121 | for i := 0 to m + 1 do 122 | for j:= 0 to m + 1 do 123 | u[i,j] := initial(i0+i, j0+j) 124 | end; 125 | 126 | procedure relax(qi, qj: integer; up, down, left, right: channel; var u: subgrid); 127 | var b, i, j, k: integer; 128 | begin 129 | for b := 0 to 1 do 130 | begin 131 | exchange(qi, qj, 1 - b, up, down, left, right, u); 132 | for i := 1 to m do 133 | begin 134 | k := (i + b) mod 2; 135 | j := 2 - k; 136 | while j <= m - k do 137 | begin 138 | nextstate(u, i, j); 139 | j := j + 2 140 | end 141 | end 142 | end 143 | end; 144 | 145 | begin 146 | fopt := 2.0 - 2.0*pi/n; 147 | newgrid(qi, qj, u); 148 | for k := 1 to steps do 149 | relax(qi, qj, up, down, left, right, u); 150 | output(qi, qj, right, left, u) 151 | end { node }; 152 | 153 | procedure master(right: channel; var u: grid); 154 | var i, j: integer; 155 | begin 156 | for i := 1 to n do 157 | for j := 1 to n do 158 | receive(right, u[i,j]) 159 | end; 160 | 161 | procedure simulate(steps: integer; var u: grid); 162 | type 163 | line = array [1..q] of channel; 164 | matrix = array [0..q] of line; 165 | var h, v: matrix; i, j: integer; 166 | begin 167 | open(h[0,q]); 168 | for i := 1 to q do 169 | for j := 1 to q do 170 | open(h[i,j]); 171 | for i := 0 to q do 172 | for j := 1 to q do 173 | open(v[i,j]); 174 | parallel 175 | master(h[0,q], u)| 176 | forall j := 1 to q do 177 | node(j, 1, steps, v[j-1,1], v[j,1], h[j-1,q], h[j,1])| 178 | forall i := 1 to q do 179 | forall j := 2 to q do 180 | node(i, j, steps, v[i-1,j], v[i,j], h[i,j-1], h[i,j]) 181 | end 182 | end; 183 | 184 | begin simulate(steps, u) end { laplace }; 185 | 186 | procedure run; 187 | var u: grid; 188 | 189 | procedure display(var u: grid); 190 | var i, j: integer; 191 | begin 192 | for i := 1 to n do 193 | begin 194 | for j := 1 to n do 195 | write(round(u[i,j]):2, ' '); 196 | writeln 197 | end 198 | end; 199 | 200 | begin 201 | laplace(u, 0.0, 100.0, 100.0, 0.0, 50.0, steps); 202 | display(u) 203 | end{run}; 204 | 205 | begin 206 | writeln('Laplace matrix:', ' n = ', n:1, ', p = ',q*q:1); 207 | writeln; run 208 | end. 209 | -------------------------------------------------------------------------------- /examples/householder.sp: -------------------------------------------------------------------------------- 1 | program householder (input, output); 2 | const 3 | n = 50 { equations }; 4 | p = 3 { pipeline nodes }; 5 | qmin = 16 { (n - 1) div p steps/node }; 6 | type 7 | column = array [1..n] of real; 8 | matrix = array [1..n] of column; 9 | 10 | procedure reduce(var a: matrix; var b: column); 11 | 12 | type channel = *(column); 13 | 14 | function product(i: integer; a, b: column): real; { the scalar product of elements i..n of a and b } 15 | var ab: real; k: integer; 16 | begin 17 | ab := 0.0; 18 | for k := i to n do 19 | ab := ab + a[k]*b[k]; 20 | product := ab 21 | end; 22 | 23 | procedure eliminate(i: integer; var ai, vi: column); 24 | var anorm, dii, fi, wii: real; k: integer; 25 | begin 26 | anorm := sqrt(product(i, ai, ai)); 27 | if (ai[i] > 0.0) 28 | then dii := -anorm 29 | else dii := anorm; 30 | wii := ai[i] - dii; 31 | fi := sqrt(-2.0*wii*dii); 32 | vi[i] := wii/fi; 33 | ai[i] := dii; 34 | for k := i + 1 to n do 35 | begin 36 | vi[k] := ai[k]/fi; 37 | ai[k] := 0.0 38 | end 39 | end; 40 | 41 | procedure transform(i: integer; var aj, vi: column); 42 | var fi: real; k: integer; 43 | begin 44 | fi := 2.0*product(i, vi, aj); 45 | for k := i to n do 46 | aj[k] := aj[k] - fi*vi[k] 47 | end; 48 | 49 | procedure node(r, s: integer; left, right: channel); 50 | type block = array [0..qmin] of column; 51 | var a, v: block; aj, b: column; i, j: integer; 52 | begin 53 | { 1 <= r <= s <= n - 1 } 54 | receive(left, b); 55 | for i := 0 to s - r do 56 | begin 57 | receive(left, a[i]); 58 | for j := 0 to i - 1 do 59 | transform(j + r, a[i], v[j]); 60 | eliminate(i + r, a[i], v[i]); 61 | transform(i + r, b, v[i]) 62 | end; 63 | send(right, b); 64 | for j := s + 1 to n do 65 | begin 66 | receive (left, aj); 67 | for i := 0 to s - r do 68 | transform(i + r, aj, v[i]); 69 | send(right, aj) 70 | end; 71 | for i := s - r downto 0 do 72 | send(right, a[i]); 73 | for j := r - 1 downto 1 do 74 | begin 75 | receive(left, aj); 76 | send (right, aj) 77 | end 78 | end; 79 | 80 | procedure master(var a: matrix; var b: column; left, right: channel); 81 | var i: integer; 82 | begin 83 | send(left, b); 84 | for i := 1 to n do 85 | send(left, a[i]); 86 | receive (right, b); 87 | for i := n downto 1 do 88 | receive (right, a[i]) 89 | end; 90 | 91 | procedure ring(var a: matrix; var b: column); 92 | type net = array [0..p] of channel; 93 | var k, long, qmax: integer; c: net; 94 | begin 95 | qmax := qmin + 1; 96 | long := (n - 1) mod p; 97 | for k := 0 to p do open(c[k]); 98 | parallel 99 | master(a, b, c[0], c[p])| 100 | forall k := 1 to long do 101 | node((k - 1)*qmax + 1, k*qmax, c[k-1], c[k])| 102 | forall k := long + 1 to p do 103 | node((k - 1)*qmin + long + 1, k*qmin + long, c[k-1], c[k]) 104 | end 105 | end; 106 | 107 | begin ring(a, b) end { reduce }; 108 | 109 | procedure substitute(var a: matrix; var b, x: column); 110 | var i, j: integer; 111 | begin 112 | for i := n downto 1 do 113 | begin 114 | x[i] := b[i]/a[i,i]; 115 | for j := i - 1 downto 1 do 116 | b[j] := b[j] - a[i,j]*x[i] 117 | end 118 | end; 119 | 120 | procedure run; 121 | var a: matrix; b, x: column; 122 | 123 | procedure initialize(var a: matrix; var b: column); 124 | var i, j, s: integer; 125 | begin 126 | s := (n + 1)*(n + 2) div 2; 127 | for i := 1 to n do 128 | begin 129 | for j := 1 to n - i do 130 | a[i,j] := 1.0; 131 | a[i,n-i+1] := 2.0; 132 | for j := n - i + 2 to n do 133 | a[i,j] := 1.0; 134 | b[i] := s - i 135 | end 136 | end; 137 | 138 | procedure display(x: column); 139 | const m = 10 { items/line }; 140 | var i, j, k: integer; 141 | begin 142 | k := n div m; 143 | for i := 0 to k - 1 do 144 | begin 145 | for j := 1 to m do 146 | write(x[i*m+j]:6:1); 147 | writeln 148 | end; 149 | for j := 1 to n mod m do 150 | write(x[k*m+j]:6:1); 151 | writeln 152 | end; 153 | 154 | begin 155 | initialize (a, b); 156 | reduce(a, b); 157 | substitute(a, b, x); 158 | display (x) 159 | end; 160 | 161 | begin 162 | writeln('Householder pipeline:',' n = ', n:1, ', p = ', p:1); 163 | writeln; 164 | run 165 | end. 166 | 167 | 168 | -------------------------------------------------------------------------------- /examples/multiplication.sp: -------------------------------------------------------------------------------- 1 | program multiplication(input, output); 2 | const 3 | n = 20 { n x n matrices }; 4 | p = 3 { pipeline nodes }; 5 | qmin = 6 { n div p }; 6 | type 7 | vector = array [1..n] of real; 8 | matrix = array [1..n] of vector; 9 | 10 | procedure multiply(var a, b, c: matrix); 11 | { c := a*b } 12 | type channel = *(vector); 13 | 14 | function f(ai, bj: vector): real; 15 | var cij: real; k: integer; 16 | begin 17 | cij := 0.0; 18 | for k := 1 to n do 19 | cij := cij + ai[k]*bj[k]; 20 | f := cij 21 | end; 22 | 23 | procedure node(r, s: integer; left, right: channel); 24 | type 25 | block = array [0..qmin] of vector; 26 | var a, c: block; i, j: integer; 27 | ai, bj, ci: vector; 28 | begin 29 | { 1 <= r <= s <= n } 30 | for i := 0 to s - r do 31 | receive(left, a[i]); 32 | for i := s + 1 to n do 33 | begin 34 | receive(left, ai); 35 | send(right, ai) 36 | end; 37 | for j := 1 to n do 38 | begin 39 | receive(left, bj); 40 | if s < n then 41 | send(right, bj); 42 | for i := 0 to s - r do 43 | c[i,j] := f(a[i], bj) 44 | end; 45 | for i := 1 to r - 1 do 46 | begin 47 | receive(left, ci); 48 | send(right, ci) 49 | end; 50 | for i := 0 to s - r do 51 | send(right, c[i]) 52 | end; 53 | 54 | procedure master(var a, b, c: matrix; left, right: channel); 55 | var i, j: integer; bj: vector; 56 | begin 57 | for i := 1 to n do 58 | send(left, a[i]); 59 | for j := 1 to n do 60 | begin 61 | for i := 1 to n do 62 | bj[i] := b[i,j]; 63 | send (left, bj) 64 | end; 65 | for i := 1 to n do 66 | receive (right, c[i]) 67 | end; 68 | 69 | procedure ring(var a, b, c: matrix); 70 | type net = array [0..p] of channel; 71 | var k, long, qmax: integer; d: net; 72 | begin 73 | qmax := qmin + 1; 74 | long := n mod p; 75 | for k := 0 to p do 76 | open(d[k]); 77 | parallel 78 | master(a, b, c, d[0], d[p])| 79 | forall k := 1 to long do 80 | node((k - 1)*qmax + 1, k*qmax, d[k-1], d[k])| 81 | forall k := long + 1 to p do 82 | node((k - 1)*qmin + long + 1, k*qmin + long, d[k-1], d[k]) 83 | end 84 | end; 85 | 86 | begin ring(a, b, c) end { multiply }; 87 | 88 | procedure transpose(var a, b: matrix); 89 | { b := aT } var i, j: integer; 90 | begin 91 | for i := 1 to n do 92 | for j := 1 to n do 93 | b[i,j] := a[j,i] 94 | end; 95 | 96 | procedure run; 97 | var a, b, c: matrix; 98 | 99 | procedure initialize(var a, b: matrix); 100 | var i, j: integer; 101 | begin 102 | for i := 1 to n do 103 | begin 104 | for j := 1 to i do 105 | a[i,j] := 1.0; 106 | for j := i + 1 to n do 107 | a[i,j] := 0.0 108 | end; 109 | transpose(a, b) 110 | end; 111 | 112 | procedure display(var c: matrix); 113 | var i, j: integer; 114 | begin 115 | for i := 1 to n do 116 | begin 117 | for j := 1 to n do 118 | write(round(c[i,j]):3); 119 | writeln 120 | end 121 | end; 122 | 123 | begin 124 | initialize(a, b); 125 | multiply(a, b, c); 126 | display(c) 127 | end { run }; 128 | 129 | begin 130 | writeln('Matrix multiplication:'); 131 | writeln('n = ', n:1, ', p = ', p:1); 132 | writeln; 133 | run 134 | end. 135 | -------------------------------------------------------------------------------- /examples/nbody.sp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/examples/nbody.sp -------------------------------------------------------------------------------- /examples/pipeline.sp: -------------------------------------------------------------------------------- 1 | program pipeline; 2 | 3 | const 4 | len = 100; 5 | 6 | type 7 | channel = *(integer); 8 | 9 | var 10 | left, right: channel; 11 | value: integer; 12 | 13 | procedure node(i: integer; left, right: channel); 14 | var value: integer; 15 | begin 16 | receive(left, value); 17 | send(right, value+1) 18 | end; 19 | 20 | procedure create(left, right: channel); 21 | type row = array [0..len] of channel; 22 | var c: row; i: integer; 23 | begin 24 | c[0] := left; 25 | c[len] := right; 26 | for i := 1 to len-1 do 27 | open(c[i]); 28 | forall i := 1 to len do 29 | node(i, c[i-1], c[i]) 30 | end; 31 | 32 | begin 33 | open(left, right); 34 | 35 | parallel 36 | send(left, 0) | 37 | create(left, right) | 38 | receive(right, value) 39 | end; 40 | 41 | writeln('The resulting value is ', value) 42 | end. 43 | -------------------------------------------------------------------------------- /examples/primality.sp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octonion/superpascal/3822f4a13159057ce4f7ddf44405519460f9b9f2/examples/primality.sp -------------------------------------------------------------------------------- /examples/salesperson.sp: -------------------------------------------------------------------------------- 1 | program salesperson(input, output); 2 | const 3 | s = 4 { s*s square, s even }; 4 | n = 16 { s*s cities }; 5 | m = 2 { trials, m mod p = 0 }; 6 | p = 2 { pipeline nodes }; 7 | type 8 | city = record x, y: real end; 9 | tour = array [1..n] of city; 10 | table = array [1..m] of tour; 11 | 12 | function distance(p, q: city): real; 13 | var dx, dy: real; 14 | begin 15 | dx := q.x - p.x; 16 | dy := q.y - p.y; 17 | distance := sqrt(dx*dx + dy*dy) 18 | end; 19 | 20 | procedure solve(a: tour; var b: tour; trial: integer); 21 | { 1 <= trial <= m } 22 | var seed: real; index: integer; 23 | 24 | procedure random(var value: real); 25 | { 0 <= value <= 1 } 26 | const a = 16807.0; m = 2147483647.0; 27 | var temp: real; 28 | begin 29 | temp := a*seed; 30 | seed := temp - m*trunc(temp/m); 31 | value := seed/m 32 | end; 33 | 34 | procedure generate(var i, j: integer); 35 | { 1 <= ij <= n } 36 | var x: real; 37 | begin 38 | random(x); 39 | i := trunc(x*n) + 1; 40 | j := index; 41 | index := index mod n + 1 42 | end; 43 | 44 | procedure select (var a: tour; var si, j: integer; var dE: real); 45 | var i, sj: integer; 46 | begin 47 | generate(i, j); 48 | si := i mod n + 1; 49 | sj := j mod n + 1; 50 | if i <> j then 51 | dE := distance(a[i], a[j]) + distance(a[si], a[sj]) - distance(a[i], a[si]) - distance(a[j], a[sj]) 52 | else 53 | dE := 0.0 54 | end; 55 | 56 | function accept (dE, T: real): boolean; 57 | begin 58 | accept := dE < T 59 | end; 60 | 61 | procedure swap(var a: tour; i, j: integer); 62 | var ai: city; 63 | begin 64 | ai := a[i]; 65 | a[i] := a[j]; 66 | a[j] := ai 67 | end; 68 | 69 | procedure change(var a: tour; i, j: integer); 70 | var k, nij: integer; 71 | begin 72 | nij := (j - i + n) mod n + 1; 73 | for k := 1 to nij div 2 do 74 | swap (a,(i + k - 2) mod n + 1, (j - k + n) mod n + 1) 75 | end; 76 | 77 | procedure search(var a: tour; T: real; attempts, changes: integer); 78 | var i, j, na, nc: integer; dE: real; 79 | begin 80 | na := 0; 81 | nc := 0; 82 | while (na < attempts) and (nc < changes) do 83 | begin 84 | select (a, i, j, dE); 85 | if accept(dE, T) then 86 | begin 87 | change(a, i, j); 88 | nc := nc + 1 89 | end; 90 | na := na + 1 91 | end 92 | end; 93 | 94 | procedure anneal(var a: tour; Tmax, alpha: real; steps, attempts, changes: integer); 95 | var T: real; k: integer; 96 | begin 97 | T := Tmax; 98 | for k := 1 to steps do 99 | begin 100 | search(a, T, attempts, changes); 101 | T := alpha*T 102 | end 103 | end; 104 | 105 | procedure permute(var a: tour; changes: integer); 106 | var i, j, k: integer; 107 | begin 108 | for k := 1 to changes do 109 | begin 110 | generate(i, j); 111 | swap(a, i, j) 112 | end 113 | end; 114 | 115 | begin 116 | seed := trial; 117 | index := trial; 118 | b := a; 119 | permute(b, n); 120 | anneal(b, sqrt(n), 0.95, trunc(20.0*ln(n)), 100*n, 10*n) 121 | end { solve }; 122 | 123 | procedure compute(a: tour; var b: table); 124 | type channel = *(tour); 125 | 126 | procedure master(a: tour; var b: table; left, right: channel); 127 | var trial: integer; 128 | begin 129 | send(left, a); 130 | for trial := 1 to m do 131 | receive(right, b[trial]) 132 | end; 133 | 134 | procedure node(i: integer; left, right: channel); 135 | { 1 <= i <= p } 136 | var a, b: tour; j, k, q, trial: integer; 137 | begin 138 | receive(left, a); 139 | if i < p then 140 | send(right, a); 141 | q := m div p; 142 | for j := 1 to q do 143 | begin 144 | trial := (i - 1)*q + j; 145 | solve(a, b, trial); 146 | send(right, b); 147 | for k := 1 to i - 1 do 148 | begin 149 | receive(left, b); 150 | send(right, b) 151 | end 152 | end 153 | end; 154 | 155 | procedure ring(a: tour; var b: table); 156 | type net = array [0..p] of channel; 157 | var c: net; i: integer; 158 | begin 159 | for i := 0 to p do 160 | open(c[i]); 161 | parallel 162 | master(a, b, c[0], c [p])| 163 | forall i := 1 to p do 164 | node(i, c[i-1], c[i]) 165 | end 166 | end; 167 | 168 | begin ring(a, b) end { compute }; 169 | 170 | procedure run; 171 | var a: tour; b: table; 172 | 173 | procedure initialize(var a: tour); 174 | { grid of s*s cities } 175 | var i, j, k: integer; 176 | begin 177 | for i := 1 to s do 178 | for j := 1 to s do 179 | begin 180 | k := (i - 1)*s + j; 181 | a[k].x := i; 182 | a[k].y := j 183 | end 184 | end; 185 | 186 | function length(a: tour): real; 187 | var i: integer; sum: real; 188 | begin 189 | sum := distance(a[n], a[1]); 190 | for i := 1 to n - 1 do 191 | sum := sum + distance(a[i], a[i+1]); 192 | length := sum 193 | end; 194 | 195 | function shortest(b: table): tour; 196 | var Ek, Emin: real; 197 | k, min: integer; 198 | begin 199 | min := 1; 200 | Emin := length(b[min]); 201 | for k := 2 to m do 202 | begin 203 | Ek := length(b[k]); 204 | if Emin > Ek then 205 | begin 206 | min := k; 207 | Emin := Ek 208 | end 209 | end; 210 | shortest := b[min] 211 | end; 212 | 213 | procedure summarize(var b: table); 214 | var a: tour; i: integer; 215 | begin 216 | a := shortest(b); 217 | for i := 1 to n do 218 | writeln(a[i].x:11, ' ', a[i].y:11); 219 | writeln(length(a)) 220 | end; 221 | 222 | begin 223 | initialize(a); 224 | compute(a, b); 225 | summarize(b) 226 | end { run }; 227 | 228 | begin 229 | writeln('Traveling salesperson: ', n:1, ' cities, ', m:1, ' trials, ', p:1, ' pipeline nodes'); 230 | writeln; 231 | run 232 | end. 233 | -------------------------------------------------------------------------------- /examples/shortestpaths.sp: -------------------------------------------------------------------------------- 1 | program shortestpaths(input, output); 2 | const 3 | n = 20 { n x n matrices }; 4 | p = 3 { pipeline nodes }; 5 | qmin = 6 { n div p }; 6 | infinity = 1.0e300; 7 | type 8 | vector = array [1..n] of real; 9 | matrix = array [1..n] of vector; 10 | 11 | procedure multiply(var a, b, c: matrix); 12 | { c := a*b } 13 | type channel = *(vector); 14 | 15 | function min(a, b: real): real; 16 | begin 17 | if a <= b then 18 | min := a 19 | else 20 | min := b 21 | end; 22 | 23 | function sum(a, b: real): real; 24 | begin 25 | if (a < infinity) and (b < infinity) then 26 | sum := a + b 27 | else 28 | sum := infinity 29 | end; 30 | 31 | function f(ai, bj: vector): real; 32 | var cij: real; k: integer; 33 | begin 34 | cij := infinity; 35 | for k := 1 to n do 36 | cij := min(cij, sum(ai[k],bj[k])); 37 | f := cij 38 | end; 39 | 40 | procedure node(r, s: integer; left, right: channel); 41 | type block = array [0..qmin] of vector; 42 | var a, c: block; i, j: integer; ai, bj, ci: vector; 43 | begin 44 | { 1 <= r <= s <= n } 45 | for i := 0 to s - r do 46 | receive(left, a[i]); 47 | for i := s + 1 to n do 48 | begin 49 | receive (left, ai); 50 | send(right, ai) 51 | end; 52 | for j := 1 to n do 53 | begin 54 | receive(left, bj); 55 | if s < n then 56 | send (right, bj); 57 | for i := 0 to s - r do 58 | c[i,j] := f(a[i], bj) 59 | end; 60 | for i := 1 to r - 1 do 61 | begin 62 | receive(left, ci); 63 | send(right, ci) 64 | end; 65 | for i := 0 to s - r do 66 | send (right, c[i]) 67 | end; 68 | 69 | procedure master(var a, b, c: matrix; left, right: channel); 70 | var i, j: integer; bj: vector; 71 | begin 72 | for i := 1 to n do 73 | send(left, a[i]); 74 | for j := 1 to n do 75 | begin 76 | for i := 1 to n do 77 | bj[i] := b[i,j]; 78 | send (left, bj) 79 | end; 80 | for i := 1 to n do 81 | receive (right, c[i]) 82 | end; 83 | 84 | procedure ring(var a, b, c: matrix); 85 | type net = array [0..p] of channel; 86 | var k, long, qmax: integer; d: net; 87 | begin 88 | qmax := qmin + 1; 89 | long := n mod p; 90 | for k := 0 to p do 91 | open(d[k]); 92 | parallel 93 | master(a, b, c, d[0], d[p])| 94 | forall k := 1 to long do 95 | node((k - 1)*qmax + 1, k*qmax, d[k-1], d[k])| 96 | forall k := long + 1 to p do 97 | node((k - 1)*qmin + long + 1, k*qmin + long, d[k-1], d[k]) 98 | end 99 | end; 100 | 101 | begin ring(a, b, c) end { multiply }; 102 | 103 | procedure square(var a: matrix); 104 | { a := a*a } 105 | var b, c: matrix; 106 | begin 107 | c := a; 108 | b := a; 109 | multiply(c, b, a) 110 | end; 111 | 112 | procedure allpaths(var a, d: matrix); 113 | var m: integer; 114 | begin 115 | d := a; 116 | m := 1; 117 | while m < n - 1 do 118 | begin 119 | square(d); 120 | m := 2*m 121 | end 122 | end; 123 | 124 | procedure run; 125 | var a, d: matrix; 126 | 127 | procedure initialize (var w: matrix); 128 | var i, j: integer; 129 | begin 130 | for i := 1 to n do 131 | for j := 1 to n do 132 | w[i,j] := infinity; 133 | for i := 1 to n do 134 | w[i,i] := 0.0; 135 | for i := 1 to n - 1 do 136 | w[i,i+1] := 1.0 137 | end; 138 | 139 | procedure display(var a: matrix); 140 | var i, j: integer; aij: real; 141 | begin 142 | for i := 1 to n do 143 | begin 144 | for j := 1 to n do 145 | begin 146 | aij := a[i,j]; 147 | if aij < infinity then 148 | write(round(aij):3) 149 | else 150 | write(' -') 151 | end; 152 | writeln 153 | end; 154 | writeln 155 | end; 156 | 157 | begin 158 | initialize(a); 159 | allpaths(a, d); 160 | display(d) 161 | end { run }; 162 | 163 | begin 164 | writeln('Shortest paths:'); 165 | writeln('n = ', n:1, ', p = 1', p:1); 166 | writeln; 167 | run 168 | end. 169 | -------------------------------------------------------------------------------- /examples/sorting.sp: -------------------------------------------------------------------------------- 1 | program sorting(input, output); 2 | const 3 | d = 2 { tree depth: log(p+l)-l }; 4 | p = 7 { tree nodes: 2**(d+l)-1 }; 5 | n = 500 { items: >=2**d }; 6 | type table = array [1..n] of integer; 7 | 8 | procedure sort(var a: table); 9 | type channel = *(integer); 10 | var bottom: channel; 11 | 12 | procedure partition(var a: table; var i, j: integer; first, last: integer); 13 | var ai, key: integer; 14 | begin 15 | i := first; 16 | j := last; 17 | key := a[(i+j) div 2]; 18 | while i <= j do 19 | begin 20 | while a[i] < key do 21 | i := i + 1; 22 | while key < a[j] do 23 | j := j - 1; 24 | if i <= j then 25 | begin 26 | ai := a[i]; 27 | a[i] := a[j]; 28 | a[j]:=ai; 29 | i := i + 1; 30 | j := j - 1 31 | end 32 | end 33 | end; 34 | 35 | procedure find(var a: table; first, last, middle: integer); 36 | var left, right, i, j: integer; 37 | begin 38 | left := first; 39 | right := last; 40 | while left < right do 41 | begin 42 | partition(a, i, j, left, right); 43 | if middle <= j then 44 | right := j 45 | else if i <= middle then 46 | left := i 47 | else 48 | left := right 49 | end 50 | end; 51 | 52 | procedure quicksort(var a: table; first, last: integer); 53 | var i, j: integer; 54 | begin 55 | if first < last then 56 | begin 57 | partition(a, i, j, first, last); 58 | quicksort(a, first, j); 59 | quicksort(a, i, last) 60 | end 61 | end; 62 | 63 | procedure leaf(bottom: channel); 64 | var a: table; first, last, i: integer; 65 | begin 66 | receive(bottom, first, last); 67 | for i := first to last do 68 | receive(bottom, a[i]); 69 | quicksort (a, first, last); 70 | for i := first to last do 71 | send(bottom, a[i]) 72 | end; 73 | 74 | procedure root(bottom, left, right: channel); 75 | var a: table; first, last, middle, middle2, i: integer; 76 | begin 77 | receive(bottom, first, last); 78 | for i := first to last do 79 | receive(bottom, a[i]); 80 | middle := (first + last) div 2; 81 | find(a, first, last, middle); 82 | send(left, first, middle); 83 | for i := first to middle do 84 | send(left, a[i]); 85 | middle2 := middle + 1; 86 | send(right, middle2, last); 87 | for i := middle2 to last do 88 | send(right, a[i]); 89 | for i := first to middle do 90 | receive(left, a[i]); 91 | for i := middle2 to last do 92 | receive(right, a[i]); 93 | for i := first to last do 94 | send(bottom, a[i]) 95 | end; 96 | 97 | procedure tree(depth: integer; bottom: channel); 98 | var left, right: channel; 99 | begin 100 | if depth > 0 then 101 | begin 102 | open(left, right); 103 | parallel 104 | tree(depth - 1, left)| 105 | tree(depth - 1, right)| 106 | root(bottom, left, right) 107 | end 108 | end 109 | else 110 | leaf(bottom) 111 | end; 112 | 113 | procedure master(var a: table; bottom: channel); 114 | var i: integer; 115 | begin 116 | send(bottom, 1, n); 117 | for i := 1 to n do 118 | send(bottom, a[i]); 119 | for i := 1 to n do 120 | receive(bottom, a[i]) 121 | end; 122 | 123 | begin 124 | open(bottom); 125 | parallel 126 | tree(d, bottom)| 127 | master(a, bottom) 128 | end 129 | end { sort }; 130 | 131 | procedure run; 132 | var a: table; seed: real; 133 | 134 | procedure random(var value: integer); 135 | { 0 <= value <= max-1 } 136 | const max = 10000; a = 16807.0; 137 | m = 2147483647.0; 138 | var temp: real; 139 | begin 140 | temp := a*seed; 141 | seed := temp - m*trunc(temp/m); 142 | value := trunc((seed/m)*max) 143 | end; 144 | 145 | procedure initialize (var a: table); 146 | var i: integer; 147 | begin 148 | seed := 1.0; 149 | for i := 1 to n do 150 | random(a[i]) 151 | end; 152 | 153 | procedure display(a: table); 154 | const m = 11 { items/line }; 155 | var i, j, k: integer; 156 | begin 157 | k := n div m; 158 | for i := 0 to k - 1 do 159 | begin 160 | for j := 1 to m do 161 | write(a[i*m+j]:5); 162 | writeln 163 | end; 164 | for j := 1 to n mod m do 165 | write(a[k*m+j]:5); 166 | writeln 167 | end; 168 | 169 | begin 170 | initialize(a); 171 | sort(a); 172 | display(a) 173 | end { run }; 174 | 175 | begin 176 | writeln('Quicksort tree:',' n = ', n:1, ', p = ', p:1); 177 | writeln; 178 | run 179 | end. 180 | -------------------------------------------------------------------------------- /notes.tex: -------------------------------------------------------------------------------- 1 | % THE SUPERPASCAL SOFTWARE NOTES 2 | % PER BRINCH HANSEN 3 | % School of Computer and Information Science 4 | % Syracuse University, Syracuse, NY 13244, USA 5 | % 29 October 1993 6 | % Copyright(c) 1993 Per Brinch Hansen 7 | 8 | % LATEX PREAMBLE 9 | \documentstyle[twoside,11pt]{article} 10 | \pagestyle{myheadings} 11 | \setlength{\topmargin}{7mm} 12 | \setlength{\textheight}{200mm} 13 | \setlength{\textwidth}{140mm} 14 | \setlength{\oddsidemargin}{14mm} 15 | \setlength{\evensidemargin}{12mm} 16 | \newcommand{\acknowledgements} 17 | {\section*{Acknowledgements} 18 | \addcontentsline{toc}{section} 19 | {Acknowledgements} 20 | } 21 | \newcommand{\blank} 22 | {\mbox{\hspace{1.8em}}} 23 | \newcommand{\blankline} 24 | {\medskip} 25 | \newcommand{\Copyright} 26 | {Copyright {\copyright}} 27 | \newcommand{\entry} 28 | {\bibitem{}} 29 | \newcommand{\example} 30 | {{\it Example:}} 31 | \newcommand{\examples} 32 | {{\it Examples:}} 33 | \newcommand{\mytitle}[3] 34 | % [title,month,year] 35 | {\markboth{Per Brinch Hansen}{#1} 36 | \thispagestyle{empty} 37 | \begin{center} 38 | {\Large\bf #1}\\ 39 | % TITLE 40 | \blankline 41 | PER BRINCH HANSEN 42 | \footnote{ 43 | \Copyright #3 % Year 44 | Per Brinch Hansen. All rights reserved.}\\ 45 | \blankline 46 | {\it 47 | School of Computer and Information Science \\ 48 | Syracuse University, Syracuse, NY 13244, USA\\ 49 | } 50 | \blankline 51 | #2 #3\\ 52 | % Month Year 53 | \end{center} 54 | } 55 | \newcommand{\Superpascal} 56 | {\it SuperPascal} 57 | \newenvironment{grammar} 58 | {\begin{small}} 59 | {\end{small}} 60 | \newenvironment{myabstract} 61 | {\begin{rm} 62 | \noindent{\bf Abstract:}} 63 | {\end{rm}} 64 | \newenvironment{mybibliography}[1] 65 | % [widestlabel] 66 | {\begin{small} 67 | \begin{thebibliography}{#1} 68 | \addcontentsline{toc} 69 | {section}{References}} 70 | { \end{thebibliography} 71 | \end{small}} 72 | \newenvironment{mykeywords} 73 | {\begin{small} 74 | \noindent{\bf Key Words:}} 75 | {\end{small}} 76 | \newenvironment{mytabular}[1] 77 | % [columns] 78 | {\begin{small} 79 | \begin{center} 80 | \begin{tabular}{#1}} 81 | { \end{tabular} 82 | \end{center} 83 | \end{small}} 84 | \newenvironment{program}[1] 85 | % [width] 86 | {\begin{center} 87 | \begin{minipage}{#1}} 88 | { \end{minipage} 89 | \end{center}} 90 | % Program Indentation 91 | \newcommand{\PA} 92 | {\noindent} 93 | \newcommand{\PB} 94 | {\mbox{\hspace{1em}}} 95 | \newcommand{\PC} 96 | {\mbox{\hspace{2em}}} 97 | \newcommand{\PD} 98 | {\mbox{\hspace{3em}}} 99 | \newcommand{\PE} 100 | {\mbox{\hspace{4em}}} 101 | 102 | % DOCUMENT TEXT 103 | \begin{document} 104 | 105 | \mytitle{The SuperPascal Software Notes} 106 | {November}{1993} 107 | 108 | \begin{myabstract} 109 | These notes describe the {\Superpascal} software, define 110 | the terms and conditions for its use, and explain how 111 | you compile the {\Superpascal} compiler and interpreter. 112 | \end{myabstract} 113 | 114 | 115 | \section{Definitions} 116 | 117 | \subsection{Software} 118 | 119 | The {\it SuperPascal} software (hereafter {\it Software}) is 120 | educational software written by Per Brinch Hansen (hereafter 121 | {\it PBH}). The {\it Software} consists of the {\it Manuals}, 122 | {\it Programs}, and {\it Scripts} for the programming 123 | language {\Superpascal} invented by {\it PBH}. The {\it 124 | Software} is stored as text in 11 files (hereafter {\it Files}). 125 | 126 | 127 | \subsection{Manuals} 128 | 129 | The {\it Manuals}, written by {\it PBH}, are stored as {\LaTeX} 130 | text in 3 {\it Files}: 131 | 132 | \begin{itemize} 133 | \item 134 | {\it report.tex:} ``The programming language SuperPascal'' 135 | [Brinch Hansen 1993a]. 136 | \item 137 | {\it user.tex:} ``The SuperPascal user manual'' [Brinch 138 | Hansen 1993b]. 139 | \item 140 | {\it notes.tex:} ``The SuperPascal software notes'' [The 141 | present notes]. 142 | \end{itemize} 143 | 144 | 145 | \subsection{Programs} 146 | 147 | The {\it Programs}, written by {\it PBH}, are a {\Superpascal} 148 | compiler and interpreter (hereafter {\it Compiler} and {\it 149 | Interpreter}). The {\it Programs} are based on the Pascal 150 | compiler and interpreter described and listed in [Brinch 151 | Hansen 1985]. The {\it Programs} are written in Pascal for 152 | Sun3 and Sun4 workstations running Unix. 153 | 154 | The {\it Programs} are stored as Pascal text in 6 {\it Files} 155 | (hereafter {\it Program Files}): 156 | 157 | \begin{itemize} 158 | \item 159 | {\it common.p:} The common declarations used by the 160 | {\it Compiler} and {\it Interpreter}. 161 | \item 162 | {\it scan.p:} The {\it Compiler} procedure that performs 163 | lexical analysis. 164 | \item 165 | {\it parse.p:} The {\it Compiler} procedure that performs 166 | syntax, scope, and type analysis. 167 | \item 168 | {\it assemble.p:} The {\it Compiler} procedure that 169 | assembles interpreted code. 170 | \item 171 | {\it compile.p:} The {\it Compiler} program. 172 | \item 173 | {\it interpret.p:} The {\it Interpreter} program. 174 | \end{itemize} 175 | 176 | 177 | \subsection{Scripts} 178 | 179 | The {\it Scripts} are Unix shell scripts stored as text in 2 180 | {\it Files}: 181 | 182 | \begin{itemize} 183 | \item 184 | {\it sun3.user:} A shell script for compilation of the 185 | {\it Programs} on a Sun3 workstation under Unix. 186 | \item 187 | {\it sun4.user:} A shell script for compilation of the 188 | {\it Programs} on a Sun4 workstation under Unix. 189 | \end{itemize} 190 | 191 | 192 | \section{Terms and Conditions} 193 | 194 | \begin{it} 195 | THE MANUALS ARE COPYRIGHTED BY PBH. THE PROGRAMS ARE IN THE 196 | PUBLIC DOMAIN. YOU CAN OBTAIN THE SOFTWARE BY ANONYMOUS FTP. 197 | THE SOFTWARE IS NOT GUARANTEED FOR A PARTICULAR PURPOSE. PBH 198 | SUPPLIES THE SOFTWARE ``AS IS'' WITHOUT ANY WARRANTIES OR 199 | REPRESENTATIONS AND DOES NOT ACCEPT ANY LIABILITIES WITH 200 | RESPECT TO THE SOFTWARE. 201 | YOU (THE USER) ARE RESPONSIBLE FOR SELECTING THE SOFTWARE, AND 202 | FOR THE USE AND RESULTS OBTAINED FROM THE SOFTWARE. YOUR USE 203 | OF THE SOFTWARE INDICATES YOUR ACCEPTANCE OF THESE TERMS AND 204 | CONDITIONS. 205 | \end{it} 206 | 207 | 208 | \section{Software Limits} 209 | 210 | The {\it Program File common.p} (hereafter {\it Common 211 | Declarations}) defines common constants, types, functions, and 212 | procedures used by the {\it Programs}. The limits of software 213 | arrays are defined by common constants (hereafter {\it Software 214 | Limits}). If the {\it Software Limits} are too small for 215 | compilation or execution of a user program, these limits must 216 | be increased by editing the {\it Common Declarations} and 217 | recompiling the {\it Programs}. 218 | 219 | 220 | \section{Include Commands} 221 | 222 | The {\it Program File compile.p} contains the following {\it 223 | include commands}: 224 | 225 | \begin{program}{10.0em} 226 | {\PA}{\#}include "common.p" \\ 227 | {\PA}{\#}include "scan.p" \\ 228 | {\PA}{\#}include "parse.p" \\ 229 | {\PA}{\#}include "assemble.p"\\ 230 | \end{program} 231 | 232 | These commands ensure that Pascal compilation of the {\it 233 | Compiler} also includes the {\it Common Declarations} and 234 | the {\it Compiler} procedures. 235 | 236 | The {\it Program File interpret.p} contains the {\it 237 | include} command: 238 | 239 | \begin{center} 240 | {\#}include "common.p" 241 | \end{center} 242 | 243 | This command ensures that Pascal compilation of the 244 | {\it Interpreter} also includes the {\it Common 245 | Declarations}. 246 | 247 | 248 | \section{Nonstandard Pascal} 249 | 250 | The {\it Programs} use the following nonstandard 251 | statements, which are Sun extensions of Pascal [Sun 252 | Microsystems 1986]: 253 | 254 | \begin{mytabular}{lll} 255 | \hline 256 | Program File & Procedure & Nonstandard statement \\ 257 | \hline 258 | compile.p & testoutput & rewrite(log, kind) \\ 259 | compile.p & codeoutput & rewrite(code, codename) \\ 260 | compile.p & firstpass & rewrite(errors, errorfile)\\ 261 | compile.p & firstpass & reset(source, sourcename) \\ 262 | interpret.p & readtime & t := clock \\ 263 | interpret.p & openoutput & rewrite(outfile, outname) \\ 264 | interpret.p & openinput & reset(inpfile, inpname) \\ 265 | interpret.p & start & reset(codefile, codename) \\ 266 | \hline 267 | \end{mytabular} 268 | 269 | The rest of the {\it Program Files} conform to {\it ISO 270 | Level 1 Standard Pascal} [British Standards Institute 1982]. 271 | 272 | 273 | \section{Program Compilation} 274 | 275 | When you have obtained the {\it Files}, the first step is 276 | is to compile the {\it Programs}. 277 | 278 | On a {\it Sun3} you compile the {\it Programs} by typing the 279 | Unix command: 280 | 281 | \begin{center} 282 | csh sun3.user 283 | \end{center} 284 | 285 | The {\it Script sun3.user} contains the Unix commands: 286 | 287 | \begin{program}{16.7em} 288 | {\PA}echo Compiling Sun3 SuperPascal \\ 289 | {\PA}pc --s --H --O --f68881 --o sc compile.p \\ 290 | {\PA}pc --s --H --O --f68881 --o sr interpret.p\\ 291 | \end{program} 292 | 293 | The {\it Programs} are compiled with the following Sun3 294 | options: 295 | 296 | \begin{itemize} 297 | \item 298 | {\it --s:} Check the Pascal standard. 299 | \item 300 | {\it --H:} Check pointers (but not subranges). 301 | \item 302 | {\it --O:} Optimize the code. 303 | \item 304 | {\it --f68881:} Generate code for the Motorola 68881 305 | floating-point processor. 306 | \end{itemize} 307 | 308 | On a {\it Sun4} you compile the {\it Programs} by typing 309 | the Unix command: 310 | 311 | \begin{center} 312 | csh sun4.user 313 | \end{center} 314 | 315 | The {\it Script sun4.user} contains the Unix commands: 316 | 317 | \begin{program}{15.7em} 318 | {\PA}echo Compiling Sun4 SuperPascal \\ 319 | {\PA}pc --s --H --O --cg89 --o sc compile.p \\ 320 | {\PA}pc --s --H --O --cg89 --o sr interpret.p\\ 321 | \end{program} 322 | 323 | The {\it Programs} are compiled with the following Sun4 324 | options: 325 | 326 | \begin{itemize} 327 | \item 328 | {\it --s:} Check the Pascal standard. 329 | \item 330 | {\it --H:} Check pointers (but not subranges). 331 | \item 332 | {\it --O:} Optimize the code. 333 | \item 334 | {\it --cg89:} Generate code for any Sun4. 335 | \end{itemize} 336 | 337 | The {\it --s} option causes the Sun Pascal compilers to 338 | display warning mesages about the nonstandard Pascal 339 | statements used in the {\it Programs}. 340 | 341 | A compilation of the {\it Programs} takes 3--5 minutes 342 | and produces two {\it Executable Files} [Brinch Hansen 343 | 1993b]: 344 | 345 | \begin{itemize} 346 | \item 347 | {\it sc:} An executable {\it Compiler}. 348 | \item 349 | {\it sr:} An executable {\it Interpreter}. 350 | \end{itemize} 351 | 352 | If you are not using {\Superpascal} on a Sun3 or Sun4, try 353 | the following if the {\it Programs} cannot be compiled 354 | directly: 355 | 356 | \begin{itemize} 357 | \item 358 | Change or omit the compilation options in the {\it 359 | Scripts}. 360 | \item 361 | Change or omit the nonstandard statements in the 362 | {\it Program Files}. 363 | \item 364 | Include the {\it Common Declarations} in each of the 365 | other {\it Program Files}. These {\it Program Files} 366 | can then be compiled separately and linked together. 367 | \end{itemize} 368 | 369 | 370 | \begin{mybibliography}{5} 371 | \entry 372 | Brinch Hansen, P. (1985) {\it Brinch Hansen on Pascal 373 | Compilers.} Prentice-Hall, Englewood Cliffs, NJ. 374 | \entry 375 | Brinch Hansen, P. (1993a) The programming language 376 | SuperPascal. School of Computer and Information Science, 377 | Syracuse University, Syracuse, NY. 378 | \entry 379 | Brinch Hansen, P. (1993b) The SuperPascal user manual. 380 | School of Computer and Information Science, Syracuse 381 | University, Syracuse, NY. 382 | \entry 383 | British Standards Institute (1982) {\it Specification 384 | for Computer Programming Language Pascal.} BS 6192. 385 | \entry 386 | Sun Microsystems (1986) {\it Pascal Programmer's Guide.} 387 | Mountain View, CA. 388 | \end{mybibliography} 389 | 390 | \end{document} 391 | -------------------------------------------------------------------------------- /readthis.tex: -------------------------------------------------------------------------------- 1 | % ANONYMOUS FTP OF THE SUPERPASCAL SOFTWARE 2 | % PER BRINCH HANSEN 3 | % School of Computer and Information Science 4 | % Syracuse University, Syracuse, NY 13244, USA 5 | % 29 October 1993 6 | % Copyright(c) 1993 Per Brinch Hansen 7 | 8 | % LATEX PREAMBLE 9 | \documentstyle[twoside,11pt]{article} 10 | \pagestyle{myheadings} 11 | \setlength{\topmargin}{7mm} 12 | \setlength{\textheight}{200mm} 13 | \setlength{\textwidth}{140mm} 14 | \setlength{\oddsidemargin}{14mm} 15 | \setlength{\evensidemargin}{12mm} 16 | \newcommand{\acknowledgements} 17 | {\section*{Acknowledgements} 18 | \addcontentsline{toc}{section} 19 | {Acknowledgements} 20 | } 21 | \newcommand{\blank} 22 | {\mbox{\hspace{1.8em}}} 23 | \newcommand{\blankline} 24 | {\medskip} 25 | \newcommand{\Copyright} 26 | {Copyright {\copyright}} 27 | \newcommand{\entry} 28 | {\bibitem{}} 29 | \newcommand{\example} 30 | {{\it Example:}} 31 | \newcommand{\examples} 32 | {{\it Examples:}} 33 | \newcommand{\mytitle}[3] 34 | % [title,month,year] 35 | {\markboth{PER BRINCH HANSEN}{#1} 36 | \thispagestyle{empty} 37 | \begin{center} 38 | {\Large\bf #1}\\ 39 | % TITLE 40 | \blankline 41 | PER BRINCH HANSEN\\ 42 | \blankline 43 | {\it 44 | School of Computer and Information Science \\ 45 | Syracuse University, Syracuse, NY 13244, USA\\ 46 | } 47 | \blankline 48 | #2 #3\\ 49 | % Month Year 50 | \end{center} 51 | } 52 | \newcommand{\Superpascal} 53 | {\it SuperPascal} 54 | \newenvironment{grammar} 55 | {\begin{small}} 56 | {\end{small}} 57 | \newenvironment{myabstract} 58 | {\begin{rm} 59 | \noindent{\bf Abstract:}} 60 | {\end{rm}} 61 | \newenvironment{mybibliography}[1] 62 | % [widestlabel] 63 | {\begin{small} 64 | \begin{thebibliography}{#1} 65 | \addcontentsline{toc} 66 | {section}{References}} 67 | { \end{thebibliography} 68 | \end{small}} 69 | \newenvironment{mykeywords} 70 | {\begin{small} 71 | \noindent{\bf Key Words:}} 72 | {\end{small}} 73 | \newenvironment{mytabular}[1] 74 | % [columns] 75 | {\begin{small} 76 | \begin{center} 77 | \begin{tabular}{#1}} 78 | { \end{tabular} 79 | \end{center} 80 | \end{small}} 81 | \newenvironment{program}[1] 82 | % [width] 83 | {\begin{center} 84 | \begin{minipage}{#1}} 85 | { \end{minipage} 86 | \end{center}} 87 | % Program Indentation 88 | \newcommand{\PA} 89 | {\noindent} 90 | \newcommand{\PB} 91 | {\mbox{\hspace{1em}}} 92 | \newcommand{\PC} 93 | {\mbox{\hspace{2em}}} 94 | \newcommand{\PD} 95 | {\mbox{\hspace{3em}}} 96 | \newcommand{\PE} 97 | {\mbox{\hspace{4em}}} 98 | 99 | % DOCUMENT TEXT 100 | \begin{document} 101 | 102 | \mytitle{ANONYMOUS FTP OF THE SUPERPASCAL SOFTWARE} 103 | {November}{1993} 104 | 105 | \noindent 106 | These instructions describe the {\Superpascal} software, 107 | define the terms and conditions for its use, and explain how 108 | you obtain the software by anonymous FTP. 109 | 110 | \begin{center} 111 | {\bf DEFINITIONS} 112 | \end{center} 113 | 114 | \noindent 115 | The {\it SuperPascal} software (hereafter {\it Software}) is 116 | educational software written by Per Brinch Hansen (hereafter 117 | {\it PBH}). The {\it Software} consists of the {\it Manuals}, 118 | {\it Programs}, and {\it Scripts} for the programming 119 | language {\Superpascal} invented by {\it PBH}. The {\it 120 | Software} is stored as text in 11 files (hereafter {\it 121 | Files}). 122 | 123 | The {\it Manuals}, written by {\it PBH}, are stored as {\LaTeX} 124 | text in 3 {\it Files}: 125 | 126 | \begin{itemize} 127 | \item 128 | {\it report.tex:} ``The programming language SuperPascal.'' 129 | \item 130 | {\it user.tex:} ``The SuperPascal user manual.'' 131 | \item 132 | {\it notes.tex:} ``The SuperPascal software notes.'' 133 | \end{itemize} 134 | 135 | The {\it Programs}, written by {\it PBH}, are a {\Superpascal} 136 | compiler and interpreter (hereafter {\it Compiler} and {\it 137 | Interpreter}). The {\it Programs} are written in Pascal for 138 | Sun3 and Sun4 workstations running Unix. The {\it Programs} 139 | are stored as Pascal text in 6 {\it Files}: 140 | 141 | \begin{itemize} 142 | \item 143 | {\it common.p:} The common declarations used by the 144 | {\it Compiler} and {\it Interpreter}. 145 | \item 146 | {\it scan.p:} The {\it Compiler} procedure that performs 147 | lexical analysis. 148 | \item 149 | {\it parse.p:} The {\it Compiler} procedure that performs 150 | syntax, scope, and type analysis. 151 | \item 152 | {\it assemble.p:} The {\it Compiler} procedure that 153 | assembles interpreted code. 154 | \item 155 | {\it compile.p:} The {\it Compiler} program. 156 | \item 157 | {\it interpret.p:} The {\it Interpreter} program. 158 | \end{itemize} 159 | 160 | The {\it Scripts} are Unix shell scripts stored as text in 2 161 | {\it Files}: 162 | 163 | \begin{itemize} 164 | \item 165 | {\it sun3.user:} A shell script for compilation of the 166 | {\it Programs} on a Sun3 workstation under Unix. 167 | \item 168 | {\it sun4.user:} A shell script for compilation of the 169 | {\it Programs} on a Sun4 workstation under Unix. 170 | \end{itemize} 171 | 172 | \begin{center} 173 | {\bf TERMS AND CONDITIONS} 174 | \end{center} 175 | 176 | \begin{it} 177 | \noindent 178 | THE MANUALS ARE COPYRIGHTED BY PBH. THE PROGRAMS ARE IN THE 179 | PUBLIC DOMAIN. YOU CAN OBTAIN THE SOFTWARE BY ANONYMOUS FTP. 180 | THE SOFTWARE IS NOT GUARANTEED FOR A PARTICULAR PURPOSE. PBH 181 | SUPPLIES THE SOFTWARE ``AS IS'' WITHOUT ANY WARRANTIES OR 182 | REPRESENTATIONS AND DOES NOT ACCEPT ANY LIABILITIES WITH 183 | RESPECT TO THE SOFTWARE. 184 | YOU (THE USER) ARE RESPONSIBLE FOR SELECTING THE SOFTWARE, AND 185 | FOR THE USE AND RESULTS OBTAINED FROM THE SOFTWARE. YOUR USE 186 | OF THE SOFTWARE INDICATES YOUR ACCEPTANCE OF THESE TERMS AND 187 | CONDITIONS. 188 | \end{it} 189 | 190 | \begin{center} 191 | {\bf FILE TRANSFER PROCEDURE} 192 | \end{center} 193 | 194 | \noindent 195 | To obtain the software, use anonymous FTP from the directory 196 | {\it pbh@top.cis.syr.edu}. If your local machine runs Unix, 197 | follow these steps to copy the files: 198 | 199 | \blankline 200 | 201 | Create an empty directory on your local machine by typing 202 | 203 | \begin{center} 204 | mkdir clone 205 | \end{center} 206 | 207 | Enter the local directory by typing 208 | 209 | \begin{center} 210 | cd clone 211 | \end{center} 212 | 213 | Select the remote machine by typing 214 | 215 | \begin{center} 216 | ftp top.cis.syr.edu 217 | \end{center} 218 | 219 | When prompted for your name, type 220 | 221 | \begin{center} 222 | anonymous 223 | \end{center} 224 | 225 | When prompted for your password, type your 226 | 227 | \begin{center} 228 | $<$e-mail address$>$ 229 | \end{center} 230 | 231 | Enter the remote ftp directory by typing 232 | 233 | \begin{center} 234 | cd pbh 235 | \end{center} 236 | 237 | Copy a shell archive that contains the {\it Files} by 238 | typing 239 | 240 | \begin{center} 241 | get software.shar 242 | \end{center} 243 | 244 | Leave the remote machine by typing 245 | 246 | \begin{center} 247 | bye 248 | \end{center} 249 | 250 | Split the archive into {\it Files} by typing 251 | 252 | \begin{center} 253 | sh software.shar 254 | \end{center} 255 | 256 | Your local directory should now contain the Files. 257 | 258 | \begin{center} 259 | {\bf HOW TO GET STARTED} 260 | \end{center} 261 | 262 | \noindent 263 | Transform the {\LaTeX} files into PostScript files and 264 | print the {\it Manuals}. Read ``The SuperPascal software 265 | notes" which explain how you compile the {\it Programs} 266 | on Sun3 and Sun4 workstations. Compile the {\it Programs} 267 | into two executable files: 268 | 269 | \begin{program}{14.1em} 270 | {\PA}sc{\blank}An executable {\it Compiler}. \\ 271 | {\PA}sr{\blank}An executable {\it Interpreter}.\\ 272 | \end{program} 273 | 274 | Then read "The programming language SuperPascal" and "The 275 | SuperPascal user manual." 276 | 277 | \end{document} 278 | -------------------------------------------------------------------------------- /report.tex: -------------------------------------------------------------------------------- 1 | % THE PROGRAMMING LANGUAGE SUPERPASCAL 2 | % PER BRINCH HANSEN 3 | % School of Computer and Information Science 4 | % Syracuse University, Syracuse, NY 13244, USA 5 | % 10 November 1993 6 | % Copyright(c) 1993 Per Brinch Hansen 7 | 8 | % LATEX PREAMBLE 9 | % For 11pt, 1em = 3.83mm 10 | \documentstyle[twoside,11pt]{article} 11 | \pagestyle{myheadings} 12 | \setlength{\topmargin}{7mm} 13 | \setlength{\textheight}{200mm} 14 | \setlength{\textwidth}{140mm} 15 | \setlength{\oddsidemargin}{14mm} 16 | \setlength{\evensidemargin}{12mm} 17 | \newcommand{\acknowledgements} 18 | {\section*{Acknowledgements} 19 | \addcontentsline{toc}{section} 20 | {Acknowledgements} 21 | } 22 | \newcommand{\blank} 23 | {\mbox{\hspace{1.8em}}} 24 | \newcommand{\blankline} 25 | {\medskip} 26 | \newcommand{\Copyright} 27 | {Copyright {\copyright}} 28 | \newcommand{\entry} 29 | {\bibitem{}} 30 | \newcommand{\example} 31 | {{\it Example:}} 32 | \newcommand{\examples} 33 | {{\it Examples:}} 34 | \newcommand{\mytitle}[3] 35 | % [title,month,year] 36 | {\markboth{Per Brinch Hansen}{#1} 37 | \thispagestyle{empty} 38 | \begin{center} 39 | {\Large\bf #1}\\ 40 | % TITLE 41 | \blankline 42 | PER BRINCH HANSEN 43 | \footnote{ 44 | \Copyright #3 % Year 45 | Per Brinch Hansen. All rights reserved.}\\ 46 | \blankline 47 | {\it 48 | School of Computer and Information Science \\ 49 | Syracuse University, Syracuse, NY 13244, USA\\ 50 | } 51 | \blankline 52 | #2 #3\\ 53 | % Month Year 54 | \end{center} 55 | } 56 | \newcommand{\Superpascal} 57 | {\it SuperPascal} 58 | \newenvironment{grammar} 59 | {\begin{small}} 60 | {\end{small}} 61 | \newenvironment{myabstract} 62 | {\begin{rm} 63 | \noindent{\bf Abstract:}} 64 | {\end{rm}} 65 | \newenvironment{mybibliography}[1] 66 | % [widestlabel] 67 | {\begin{small} 68 | \begin{thebibliography}{#1} 69 | \addcontentsline{toc} 70 | {section}{References}} 71 | { \end{thebibliography} 72 | \end{small}} 73 | \newenvironment{mykeywords} 74 | {\begin{small} 75 | \noindent{\bf Key Words:}} 76 | {\end{small}} 77 | \newenvironment{mytabular}[1] 78 | % [columns] 79 | {\begin{small} 80 | \begin{center} 81 | \begin{tabular}{#1}} 82 | { \end{tabular} 83 | \end{center} 84 | \end{small}} 85 | \newenvironment{program}[1] 86 | % [width] 87 | {\begin{center} 88 | \begin{minipage}{#1}} 89 | { \end{minipage} 90 | \end{center}} 91 | % Program Tokens 92 | \newcommand{\token}[1] 93 | {{\bf#1}} 94 | \newcommand{\And} 95 | {\token{and}} 96 | \newcommand{\Array} 97 | {\token{array}} 98 | \newcommand{\Assume} 99 | {\token{assume}} 100 | \newcommand{\Begin} 101 | {\token{begin}} 102 | \newcommand{\Case} 103 | {\token{case}} 104 | \newcommand{\Const} 105 | {\token{const}} 106 | \newcommand{\Div} 107 | {\token{div}} 108 | \newcommand{\Do} 109 | {\token{do}} 110 | \newcommand{\Downto} 111 | {\token{downto}} 112 | \newcommand{\Else} 113 | {\token{else}} 114 | \newcommand{\End} 115 | {\token{end}} 116 | \newcommand{\For} 117 | {\token{for}} 118 | \newcommand{\Forall} 119 | {\token{forall}} 120 | \newcommand{\Function} 121 | {\token{function}} 122 | \newcommand{\If} 123 | {\token{if}} 124 | \newcommand{\Mod} 125 | {\token{mod}} 126 | \newcommand{\Not} 127 | {\token{not}} 128 | \newcommand{\Of} 129 | {\token{of}} 130 | \newcommand{\Or} 131 | {\token{or}} 132 | \newcommand{\Parallel} 133 | {\token{parallel}} 134 | \newcommand{\Procedure} 135 | {\token{procedure}} 136 | \newcommand{\Program} 137 | {\token{program}} 138 | \newcommand{\Record} 139 | {\token{record}} 140 | \newcommand{\Repeat} 141 | {\token{repeat}} 142 | \newcommand{\Sic} 143 | {\token{sic}} 144 | \newcommand{\Then} 145 | {\token{then}} 146 | \newcommand{\To} 147 | {\token{to}} 148 | \newcommand{\Type} 149 | {\token{type}} 150 | \newcommand{\Until} 151 | {\token{until}} 152 | \newcommand{\Var} 153 | {\token{var}} 154 | \newcommand{\While} 155 | {\token{while}} 156 | % Program Indentation 157 | \newcommand{\PA} 158 | {\noindent} 159 | \newcommand{\PB} 160 | {\mbox{\hspace{1em}}} 161 | \newcommand{\PC} 162 | {\mbox{\hspace{2em}}} 163 | \newcommand{\PD} 164 | {\mbox{\hspace{3em}}} 165 | \newcommand{\PE} 166 | {\mbox{\hspace{4em}}} 167 | % Grammar Indentation 168 | \newcommand{\GA} 169 | {\noindent} 170 | \newcommand{\GB} 171 | {\mbox{\hspace{1.6em}}} 172 | \newcommand{\GC} 173 | {\mbox{\hspace{3.2em}}} 174 | \newcommand{\GD} 175 | {\mbox{\hspace{4.8em}}} 176 | \hyphenation{ 177 | syn-chron-ous 178 | } 179 | % DOCUMENT TEXT 180 | \begin{document} 181 | 182 | \mytitle 183 | {The Programming Language SuperPascal} 184 | {November}{1993} 185 | 186 | \begin{myabstract} 187 | This paper defines {\Superpascal}---a secure programming 188 | language for publication of parallel scientific 189 | algorithms. {\Superpascal} extends a subset of IEEE Standard 190 | Pascal with deterministic statements for parallel 191 | processes and synchronous message communication. A parallel 192 | statement denotes parallel execution of a fixed number of 193 | statements. A {\it forall} statement denotes parallel execution 194 | of the same statement by a dynamic number of processes. 195 | Recursive procedures may be combined with parallel and {\it 196 | forall} statements to define recursive parallel processes. 197 | Parallel processes communicate by sending typed messages 198 | through channels created dynamically. {\Superpascal} omits 199 | ambiguous and insecure features of Pascal. Restrictions on 200 | the use of variables enable a single-pass compiler to check 201 | that parallel processes are disjoint, even if the processes 202 | use procedures with global variables. 203 | \end{myabstract} 204 | 205 | \blankline 206 | 207 | \begin{mykeywords} 208 | Programming languages, Parallel programming, Recursive 209 | parallelism, Synchronous communication, SuperPascal. 210 | \end{mykeywords} 211 | 212 | %\tableofcontents 213 | 214 | 215 | \section{Introduction} 216 | 217 | This paper defines {\Superpascal}---a secure programming 218 | language for publication of parallel scientific algorithms. 219 | {\Superpascal} extends a subset of IEEE Standard Pascal with 220 | deterministic statements for parallel processes and 221 | synchronous message communication. A parallel statement 222 | denotes parallel execution of a fixed number of statements. 223 | A {\it forall} statement denotes parallel execution of the 224 | same statement by a dynamic number of processes. Recursive 225 | procedures may be combined with parallel and {\it forall} 226 | statements to define recursive parallel processes. Parallel 227 | processes communicate by sending typed message through 228 | channels created dynamically. {\Superpascal} omits ambiguous 229 | and insecure features of Pascal. Restrictions on the use of 230 | variables enable a single-pass compiler to check that 231 | parallel processes are disjoint, even if the processes use 232 | procedures with global variables. 233 | 234 | This paper defines the parallel features of {\Superpascal} 235 | using the terminology and syntax notation of the Standard 236 | Pascal report [IEEE 1983]. Brinch Hansen [1993a] 237 | illustrates {\Superpascal} by examples. The syntactic 238 | checking of parallel statements is discussed further in 239 | [Brinch Hansen 1993b]. 240 | 241 | A {\it portable implementation} of {\Superpascal} has been 242 | developed on a Sun workstation under Unix. It consists of 243 | a compiler and an interpreter written in Pascal. To obtain 244 | the {\Superpascal} software, use anonymous FTP from the 245 | directory {\it pbh} at {\it top.cis.syr.edu}. 246 | 247 | 248 | \section{Processes and Variables} 249 | 250 | \begin{grammar} 251 | {\GA}command = \\ 252 | {\GB}variable-access $|$ expression $|$ 253 | statement $|$ statement-sequence . 254 | \end{grammar} 255 | 256 | The evaluation or execution of a {\it command} is called a 257 | {\it process}. A structured process is a sequential or 258 | parallel composition of processes. The components of a 259 | parallel composition are called {\it parallel processes}. 260 | They proceed independently at unpredictable speeds until all 261 | of them have terminated. 262 | 263 | In a program text an {\it entire variable} is a syntactic 264 | entity that has an identifier, a type, and a scope. 265 | 266 | During program execution a {\it block} is activated when a 267 | process evaluates a function designator or executes a 268 | procedure statement or program. Every activation of a block 269 | $B$ creates a new instance of every variable that is local 270 | to $B$. When an activation terminates, the corresponding 271 | variable instances cease to exist. 272 | 273 | During recursive and parallel activations of a block, 274 | multiple instances of the local variables exist. Each 275 | variable instance is a dynamic entity that has a location, a 276 | current value, and a finite lifetime in memory. 277 | 278 | The distinction between a {\it variable} as a syntactic 279 | entity in the program text and a class of dynamic entities 280 | in memory is usually clear from the context. Where it is 281 | necessary, this paper distinguishes between {\it syntactic 282 | variables} and {\it variable instances}. 283 | 284 | Parallel processes are said to be {\it disjoint} if they 285 | satisfy the following condition: Any variable instance that 286 | is assigned a value by one of the processes is not 287 | accessed by any of the other processes. In other words, any 288 | variable instance that is accessed by more than one process 289 | is not assigned a value by any of the processes. 290 | 291 | 292 | \section{Type Definitions} 293 | 294 | Every type has an identifier. Two types are the same if they 295 | have the same identifier and the same scope. 296 | 297 | \blankline 298 | 299 | \examples 300 | 301 | \blankline 302 | 303 | The following types are used in the examples of this paper: 304 | 305 | \begin{program}{20.4em} 306 | {\PA}{\Type} \\ 307 | {\PB}vector = {\Record} x, y: real {\End}; \\ 308 | {\PB}body = {\Record} m: real; r, v, f: vector {\End};\\ 309 | {\PB}system = {\Array} [1..n] {\Of} body; \\ 310 | {\PB}channel = $*$(body); \\ 311 | {\PB}net = {\Array} [0..p] {\Of} channel; \\ 312 | {\PB}mixed = $*$(body, integer); \\ 313 | {\PB}two = {\Array} [0..1] {\Of} mixed; \\ 314 | {\PB}four = {\Array} [0..1] {\Of} two; 315 | \end{program} 316 | 317 | 318 | \subsection{Channel Types} 319 | 320 | Processes communicate by means of values called {\it 321 | messages} transmitted through entities called {\it 322 | channels}. A {\it communication} takes place when one 323 | process is ready to {\it output} a message of some type 324 | through a channel and another process is ready to {\it 325 | input} a message of the same type through the same channel. 326 | 327 | Processes create channels dynamically and access them by 328 | means of values known as {\it channel references}. The type 329 | of a channel reference is called a {\it channel type}. 330 | \blankline 331 | \begin{grammar} 332 | {\GA}channel-type = \\ 333 | {\GB}``$*$'' ``('' message-type-list ``)'' . \\ 334 | {\GA}message-type-list = \\ 335 | {\GB}type-identifier \{ ``,'' type-identifier \} .\\ 336 | \end{grammar} 337 | 338 | A channel type 339 | 340 | \begin{center} 341 | $*(T_1,T_2,\ldots,T_n)$ 342 | \end{center} 343 | 344 | \noindent 345 | denotes an unordered set of channel references created 346 | dynamically. Each channel reference denotes a distinct 347 | channel which can transmit messages of distinct types 348 | $T_1,T_2,\ldots,T_n$ only (the {\it message types}). 349 | 350 | A type definition cannot be of the recursive form: 351 | 352 | \begin{center} 353 | $T = *(\ldots,T,\ldots)$ 354 | \end{center} 355 | 356 | \examples 357 | 358 | \begin{program}{6.9em} 359 | {\PA}$*$(body) \\ 360 | {\PA}$*$(body, integer) 361 | \end{program} 362 | 363 | 364 | \section{Variables} 365 | 366 | \subsection{Entire Variables} 367 | 368 | An {\it entire variable} is a variable denoted by one of the 369 | following kinds of identifiers: 370 | 371 | \begin{enumerate} 372 | \item 373 | A variable identifier introduced by a variable declaration 374 | or a {\it forall} statement. 375 | \item 376 | A function identifier that occurs as the left part of an 377 | assignment statement in the statement part of the 378 | corresponding function block. 379 | \end{enumerate} 380 | 381 | \examples 382 | 383 | \blankline 384 | 385 | The following entire variables are used in the examples of 386 | this paper: 387 | 388 | \begin{program}{8.9em} 389 | {\PA}{\Var} \\ 390 | {\PB}inp, out: channel;\\ 391 | {\PB}c: net; \\ 392 | {\PB}a: system; \\ 393 | {\PB}ai, aj: body; \\ 394 | {\PB}left: mixed; \\ 395 | {\PB}top: four; \\ 396 | {\PB}i, j, k: integer; 397 | \end{program} 398 | 399 | A {\it variable context} is associated with each command 400 | $C$. This context consists of two sets of entire variables 401 | called the {\it target} and {\it expression variables} of 402 | $C$. If the process denoted by $C$ may assign a value to an 403 | entire variable $v$ (or one of its components), then $v$ is 404 | a target variable of $C$. If the process may use the value 405 | of $v$ (or one of its components) as an operand, then $v$ is 406 | an expression variable of $C$. 407 | 408 | 409 | \subsection{Block Parameters} 410 | 411 | Consider a procedure or function block $B$ with a statement 412 | part $S$. An {\it implicit parameter} of $B$ is an entire 413 | variable $v$ that is global to $B$ and is part of the 414 | variable context of $S$. If $v$ is a target variable of $S$, 415 | then $v$ is an {\it implicit variable parameter} of $B$. If 416 | $v$ is an expression variable of $S$, then $v$ is an {\it 417 | implicit value parameter} of $B$. 418 | 419 | A {\it function} block cannot use formal variable parameters 420 | or implicit variable parameters. 421 | 422 | A {\it recursive procedure} or {\it function} block cannot 423 | use implicit parameters. 424 | 425 | 426 | \subsection{Target Variables} 427 | 428 | An entire variable $v$ is a target variable of a command $C$ 429 | in the following cases: 430 | 431 | \begin{enumerate} 432 | \item 433 | The variable identifier $v$ occurs in an assignment 434 | statement $C$ that denotes assignment to $v$ (or one of 435 | its components). 436 | \item 437 | The variable identifier $v$ occurs in a {\it for} 438 | statement $C$ that uses $v$ as the control variable. 439 | \item 440 | The variable identifier $v$ occurs in a procedure 441 | statement $C$ that uses $v$ (or one of its components) as 442 | an actual variable parameter. 443 | \item 444 | The variable $v$ is an implicit variable parameter of a 445 | procedure block $B$, and $C$ is a procedure statement that 446 | denotes activation of $B$. 447 | \item 448 | The variable $v$ is a target variable of a command $D$, 449 | and $C$ is a structured command that contains $D$. 450 | \end{enumerate} 451 | 452 | 453 | \subsection{Expression Variables} 454 | 455 | An entire variable $v$ is an expression variable of a 456 | command $C$ in the following cases: 457 | 458 | \begin{enumerate} 459 | \item 460 | The variable identifier $v$ occurs in an expression $C$ 461 | that uses $v$ (or one of its components) as an operand. 462 | \item 463 | The variable identifier $v$ occurs in the element 464 | statement $C$ of a {\it forall} statement that introduces 465 | $v$ as the index variable. 466 | \item 467 | The variable $v$ is an implicit value parameter of a 468 | function block $B$, and $C$ is a function designator that 469 | denotes activation of $B$. 470 | \item 471 | The variable $v$ is an implicit value parameter of a 472 | procedure block $B$, and $C$ is a procedure statement that 473 | denotes activation of $B$. 474 | \item 475 | The variable $v$ is an expression variable of a command 476 | $D$, and $C$ is a structured command that contains $D$. 477 | \end{enumerate} 478 | 479 | 480 | \subsection{Channel Variables} 481 | 482 | A {\it channel variable} is a variable of a channel type. 483 | The value of a channel variable is undefined unless a 484 | channel reference has been assigned to the variable. 485 | 486 | \blankline 487 | 488 | \begin{grammar} 489 | {\GA}channel-variable-access = \\ 490 | {\GB}variable-access . \\ 491 | \end{grammar} 492 | 493 | \examples 494 | 495 | \begin{program}{2.9em} 496 | {\PA}inp \\ 497 | {\PA}c[0] \\ 498 | {\PA}top[i,j] 499 | \end{program} 500 | 501 | 502 | \section{Expressions} 503 | 504 | \subsection{Channel Expressions} 505 | 506 | \begin{grammar} 507 | {\GA}channel-expression =\\ 508 | {\GB}expression . \\ 509 | \end{grammar} 510 | 511 | A channel expression is an expression of a channel type. The 512 | expression is said to be {\it well-defined} if it denotes a 513 | channel; otherwise, it is {\it undefined}. 514 | 515 | \blankline 516 | 517 | \examples 518 | 519 | \begin{program}{2.4em} 520 | {\PA}out \\ 521 | {\PA}c[k$-$1] 522 | \end{program} 523 | 524 | 525 | \subsection{Relational Operators} 526 | 527 | If $x$ and $y$ are well-defined channel expressions of the 528 | same type, the following expressions denote boolean values: 529 | 530 | \begin{center} 531 | x = y{\blank}x $<>$ y 532 | \end{center} 533 | 534 | The value of x = y is true if $x$ and $y$ denote the same 535 | channel, and is false otherwise. The value of x $<>$ y is 536 | the same as the value of 537 | 538 | \begin{center} 539 | {\Not} (x = y) 540 | \end{center} 541 | 542 | \example 543 | 544 | \begin{center} 545 | left = top[i,j] 546 | \end{center} 547 | 548 | 549 | \section{Message Communication} 550 | 551 | The required procedures for message communication are 552 | 553 | \begin{center} 554 | open{\blank}send{\blank}receive 555 | \end{center} 556 | 557 | 558 | \subsection{The Procedure Open} 559 | 560 | \begin{grammar} 561 | {\GA}open-statement = \\ 562 | {\GB}``{\it open}'' ``('' open-parameters ``)'' .\\ 563 | {\GA}open-parameters = \\ 564 | {\GB}open-parameter \{ ``,'' open-parameter \} . \\ 565 | {\GA}open-parameter = \\ 566 | {\GB}channel-variable-access . \\ 567 | \end{grammar} 568 | 569 | If $v$ is a channel variable, the statement 570 | 571 | \begin{center} 572 | open(v) 573 | \end{center} 574 | 575 | \noindent 576 | denotes creation of a new channel. 577 | 578 | The {\it open} statement is executed by creating a new 579 | channel and assigning the corresponding reference to the 580 | channel variable $v$. The channel reference is of the same 581 | type as the channel variable. The channel exists until the 582 | program execution terminates. 583 | 584 | The abbreviation 585 | 586 | \begin{center} 587 | open($v_1,v_2,\ldots,v_n$) 588 | \end{center} 589 | 590 | \noindent 591 | is equivalent to 592 | 593 | \begin{center} 594 | {\Begin} open($v_1$); open($v_2,\ldots,v_n$) {\End} 595 | \end{center} 596 | 597 | \examples 598 | 599 | \begin{program}{6.3em} 600 | {\PA}open(c[k]) \\ 601 | {\PA}open(inp, out) 602 | \end{program} 603 | 604 | 605 | \subsection{The Procedures Send and Receive} 606 | 607 | \begin{grammar} 608 | {\GA}send-statement = \\ 609 | {\GB}``{\it send}'' ``('' send-parameters ``)'' . \\ 610 | {\GA}send-parameters = \\ 611 | {\GB}channel-expression ``,'' output-expression-list . \\ 612 | {\GA}output-expression-list = \\ 613 | {\GB}output-expression \{ ``,'' output-expression \} . \\ 614 | {\GA}output-expression = \\ 615 | {\GB}expression . \\ 616 | {\GA}receive-statement = \\ 617 | {\GB}``{\it receive}'' ``('' receive-parameters ``)'' . \\ 618 | {\GA}receive-parameters = \\ 619 | {\GB}channel-expression ``,'' input-variable-list . \\ 620 | {\GA}input-variable-list = \\ 621 | {\GB}input-variable-access \{ ``,'' input-variable-access \} .\\ 622 | {\GA}input-variable-access = \\ 623 | {\GB}variable-access . \\ 624 | \end{grammar} 625 | 626 | The statement 627 | 628 | \begin{center} 629 | send(b, e) 630 | \end{center} 631 | 632 | \noindent 633 | denotes output of the value of an expression $e$ through 634 | the channel denoted by an expression $b$. The expression 635 | $b$ must be of a channel type $T$, and the type of the 636 | expression $e$ must be a message type of $T$. 637 | 638 | The statement 639 | 640 | \begin{center} 641 | receive(c, v) 642 | \end{center} 643 | 644 | \noindent 645 | denotes input of the value of a variable $v$ through the 646 | channel denoted by an expression $c$. The expression $c$ 647 | must be of a channel type $T$, and the type of the variable 648 | $v$ must be a message type of $T$. 649 | 650 | The {\it send} and {\it receive} operations defined by the 651 | above statements are said to {\it match} if they satisfy the 652 | following conditions: 653 | 654 | \begin{enumerate} 655 | \item 656 | The channel expressions $b$ and $c$ are of the same type 657 | $T$ and denote the same channel. 658 | \item 659 | The output expression $e$ and the input variable $v$ are 660 | of the same type, which is a message type of $T$. 661 | \end{enumerate} 662 | 663 | The execution of a {\it send} operation delays a process 664 | until another process is ready to execute a matching {\it 665 | receive} operation (and vice versa). If and when this 666 | happens, a {\it communication} takes place as follows: 667 | 668 | \begin{enumerate} 669 | \item 670 | The sending process obtains a value by evaluating the 671 | output expression $e$. 672 | \item 673 | The receiving process assigns the value to the input 674 | variable $v$. 675 | \end{enumerate} 676 | 677 | After the communication, the sending and receiving processes 678 | proceed independently. 679 | 680 | \blankline 681 | 682 | {\it Communication Errors:} 683 | 684 | \begin{enumerate} 685 | \item 686 | {\it Undefined channel reference}: A channel expression 687 | does not denote a channel. 688 | \item 689 | {\it Channel contention}: Two parallel processes both 690 | attempt to send (or receive) through the same channel at 691 | the same time. 692 | \item 693 | {\it Message type error}: Two parallel processes attempt 694 | to communicate through the same channel, but the output 695 | expression and the input variable are of different message 696 | types. 697 | \end{enumerate} 698 | 699 | The abbreviation 700 | 701 | \begin{center} 702 | send($b,e_1,e_2,\ldots,e_n$) 703 | \end{center} 704 | 705 | \noindent 706 | is equivalent to 707 | 708 | \begin{center} 709 | {\Begin} send($b,e_1$); send($b,e_2,\ldots,e_n$) {\End} 710 | \end{center} 711 | 712 | The abbreviation 713 | 714 | \begin{center} 715 | receive($c,v_1,v_2,\ldots,v_n$) 716 | \end{center} 717 | 718 | \noindent 719 | is equivalent to 720 | 721 | \begin{center} 722 | {\Begin} receive($c,v_1$); receive($c,v_2,\ldots,v_n$) {\End} 723 | \end{center} 724 | 725 | \examples 726 | 727 | \begin{program}{8.1em} 728 | {\PA}send(out, ai) \\ 729 | {\PA}receive(inp, aj) \\ 730 | {\PA}send(top[i,j], 2, ai) 731 | \end{program} 732 | 733 | 734 | \section{Statements} 735 | 736 | \subsection{Assignment Statements} 737 | 738 | If $x$ is a channel variable access and $y$ is a 739 | well-defined channel expression of the same type, the effect 740 | of the assignment statement 741 | 742 | \begin{center} 743 | x := y 744 | \end{center} 745 | 746 | \noindent 747 | is to make the values of $x$ and $y$ denote the same 748 | channel. 749 | 750 | \blankline 751 | 752 | \example 753 | 754 | \begin{center} 755 | left := top[i,j] 756 | \end{center} 757 | 758 | 759 | \subsection{Procedure Statements} 760 | 761 | The {\it restricted actual parameters} of a procedure 762 | statement are the explicit variable parameters that occur in 763 | the actual parameter list and the implicit parameters of the 764 | corresponding procedure block. 765 | 766 | \blankline 767 | 768 | {\it Restriction}: The restricted actual parameters of a 769 | procedure statement must be distinct entire variables (or 770 | components of such variables). 771 | 772 | \blankline 773 | 774 | A procedure statement cannot occur in the statement part of 775 | a function block. This rule also applies to a procedure 776 | statement that denotes activation of a required procedure. 777 | 778 | 779 | \subsection{Parallel Statements} 780 | 781 | \begin{grammar} 782 | {\GA}parallel-statement = \\ 783 | {\GB}``{\Parallel}'' process-statement-list ``{\End}'' .\\ 784 | {\GA}process-statement-list = \\ 785 | {\GB}process-statement \{ ``$|$'' process-statement \} .\\ 786 | {\GA}process-statement = \\ 787 | {\GB}statement-sequence . \\ 788 | \end{grammar} 789 | 790 | A {\it parallel} statement denotes parallel processes. Each 791 | process is denoted by a separate process statement. 792 | 793 | The effect of a parallel statement is to execute the process 794 | statements as parallel processes until all of them have 795 | terminated. 796 | 797 | \blankline 798 | 799 | {\it Restriction}: In a parallel statement, a target 800 | variable of one process statement cannot be a target or 801 | expression variable of another process statement. 802 | 803 | \blankline 804 | 805 | \example 806 | 807 | \begin{program}{13.6em} 808 | {\PA}{\Parallel} \\ 809 | {\PB}source(a, c[0]); sink(a, c[p])$|$\\ 810 | {\PB}{\Forall} k := 1 {\To} p {\Do} \\ 811 | {\PC}node(k, c[k$-$1], c[k]) \\ 812 | {\PA}{\End} 813 | \end{program} 814 | 815 | 816 | \subsection{Forall Statements} 817 | 818 | \begin{grammar} 819 | {\GA}forall-statement = \\ 820 | {\GB}``{\Forall}'' index-variable-declaration ``{\Do}''\\ 821 | {\GC}element-statement . \\ 822 | {\GA}index-variable-declaration = \\ 823 | {\GB}variable-identifier ``:='' process-index-range . \\ 824 | {\GA}process-index-range = \\ 825 | {\GB}expression ``{\To}'' expression . \\ 826 | {\GA}element-statement = \\ 827 | {\GB}statement . \\ 828 | \end{grammar} 829 | 830 | The statement 831 | 832 | \begin{center} 833 | {\Forall} $i$ := $e_1$ {\To} $e_2$ {\Do} $S$ 834 | \end{center} 835 | 836 | \noindent 837 | denotes a (possibly empty) array of parallel processes, 838 | called {\it element processes}, and a corresponding range of 839 | values, called {\it process indices}. The lower and upper 840 | bounds of the process index range are denoted by two 841 | expressions, $e_1$ and $e_2$, of the same simple type (the 842 | {\it index type}). Every index value corresponds to a 843 | separate element process defined by an {\it index variable 844 | i} and an {\it element statement S}. 845 | 846 | The {\it index variable declaration} 847 | 848 | \begin{center} 849 | $i$ := $e_1$ {\To} $e_2$ 850 | \end{center} 851 | 852 | \noindent 853 | introduces the index variable $i$ which is local to the 854 | element statement $S$. 855 | 856 | A {\it forall} statement is executed as follows: 857 | 858 | \begin{enumerate} 859 | \item 860 | The expressions $e_1$ and $e_2$ are evaluated. If 861 | $e_1 > e_2$, the execution of the {\it forall} statement 862 | terminates; otherwise, step 2 takes place. 863 | \item 864 | $e_2-e_1+1$ element processes run in parallel until all of 865 | them have terminated. Each element process creates a local 866 | instance of the index variable $i$, assigns the 867 | corresponding process index to the variable, and executes 868 | the element statement $S$. When an element process 869 | terminates, its local instance of the index variable 870 | ceases to exist. 871 | \end{enumerate} 872 | 873 | {\it Restriction}: In a {\it forall} statement, the element 874 | statement cannot use target variables. 875 | 876 | \blankline 877 | 878 | \examples 879 | 880 | \begin{program}{11.8em} 881 | {\PA}{\Forall} k := 1 {\To} p {\Do} \\ 882 | {\PB}node(k, c[k$-$1], c[k]) \\ 883 | {\PA} \\ 884 | {\PA}{\Forall} i := 0 {\To} 1 {\Do} \\ 885 | {\PB}{\Forall} j := 0 {\To} 1 {\Do}\\ 886 | {\PC}quadtree(i, j, top[i,j]) 887 | \end{program} 888 | 889 | 890 | \subsection{Unrestricted Statements} 891 | 892 | \begin{grammar} 893 | {\GA}unrestricted-statement = \\ 894 | {\GB}sic-clause statement . \\ 895 | {\GA}sic-clause = \\ 896 | {\GB}``['' ``{\Sic}'' ``]'' .\\ 897 | \end{grammar} 898 | 899 | A statement $S$ is said to be {\it unrestricted} in the 900 | following cases: 901 | 902 | \begin{enumerate} 903 | \item 904 | The statement $S$ is prefixed by a {\it sic} clause. 905 | \item 906 | The statement $S$ is a component of an unrestricted 907 | statement. 908 | \end{enumerate} 909 | 910 | All other statements are said to be {\it restricted}. 911 | 912 | Restricted statements must satisfy the rules labeled as 913 | {\it restrictions} in this paper. These rules restrict the 914 | use of entire variables in procedure statements, parallel 915 | statements, and {\it forall} statements to make it possible 916 | to check the disjointness of parallel processes during 917 | single-pass compilation (see 7.2, 7.3 and 7.4). 918 | 919 | The same rules do {\it not} apply to unrestricted 920 | statements. Consequently, the programmer must prove that 921 | each unrestricted statement preserves the disjointness of 922 | parallel processes; otherwise, the semantics of unrestricted 923 | statements are beyond the scope of this paper. 924 | 925 | \blankline 926 | 927 | \examples 928 | 929 | \begin{program}{14.9em} 930 | {\PA}[{\Sic}] \{ i $<>$ j \} \\ 931 | {\PB}swap(a[i], a[j]) \\ 932 | {\PA} \\ 933 | {\PA}[{\Sic}] \{ i $<>$ j \} \\ 934 | {\PB}{\Parallel} a[i] := ai$|$a[j] := aj {\End}\\ 935 | {\PA} \\ 936 | {\PA}[{\Sic}] \{ disjoint elements a[i] \} \\ 937 | {\PB}{\Forall} i := 1 {\To} n {\Do} a[i] := ai 938 | \end{program} 939 | 940 | 941 | \subsection{Assume Statements} 942 | 943 | \begin{grammar} 944 | {\GA}assume-statement = \\ 945 | {\GB}``{\Assume}'' assumption .\\ 946 | {\GA}assumption = \\ 947 | {\GB}expression . \\ 948 | \end{grammar} 949 | 950 | The effect of an {\it assume} statement is to test an 951 | assumption denoted by a boolean expression. If the 952 | assumption is true, the test terminates; otherwise, program 953 | execution stops. 954 | 955 | \blankline 956 | 957 | \example 958 | 959 | \begin{center} 960 | {\Assume} i $<>$ j 961 | \end{center} 962 | 963 | 964 | \section{SuperPascal versus Pascal} 965 | 966 | The following summarizes the differences between 967 | {\Superpascal} and Pascal. 968 | 969 | 970 | \subsection{Added Features} 971 | 972 | Table~1 lists the {\Superpascal} features that were added 973 | to Pascal. 974 | 975 | \begin{table}[p] 976 | \caption{Added features} 977 | \begin{mytabular}{ll} 978 | \hline 979 | Language & Required \\ 980 | concepts & identifiers\\ 981 | \hline 982 | channel types & null \\ 983 | structured function types & maxstring \\ 984 | parallel statements & string \\ 985 | forall statements & open \\ 986 | unrestricted statements & send \\ 987 | assume statements & receive \\ 988 | \hline 989 | \end{mytabular} 990 | \end{table} 991 | 992 | 993 | \subsection{Excluded Features} 994 | 995 | Table~2 lists the Pascal features that were excluded from 996 | {\Superpascal}. 997 | 998 | \begin{table}[p] 999 | \caption{Excluded features} 1000 | \begin{mytabular}{ll} 1001 | \hline 1002 | Language & Required \\ 1003 | concepts & identifiers\\ 1004 | \hline 1005 | labels & text \\ 1006 | subrange types & input \\ 1007 | record variants & output \\ 1008 | empty field lists & page \\ 1009 | set types & reset \\ 1010 | file types & get \\ 1011 | pointer types & rewrite \\ 1012 | packed types & put \\ 1013 | nameless types & new \\ 1014 | renamed types & dispose \\ 1015 | functions with side-effects & pack \\ 1016 | functional parameters & unpack \\ 1017 | procedural parameters & \\ 1018 | forward declarations & \\ 1019 | goto statements & \\ 1020 | with statements & \\ 1021 | \hline 1022 | \end{mytabular} 1023 | \end{table} 1024 | 1025 | 1026 | \subsection{Minor Differences} 1027 | 1028 | {\Superpascal} differs from Pascal in the following details: 1029 | 1030 | \begin{enumerate} 1031 | \item 1032 | {\it Program parameters} are comments only. 1033 | \item 1034 | A multi-dimensional {\it array type} is defined in terms 1035 | of one-dimensional array types. 1036 | \item 1037 | The required type {\it string} is the only string type: 1038 | 1039 | \begin{center} 1040 | string = {\Array} [1..maxstring] {\Of} char 1041 | \end{center} 1042 | 1043 | \noindent 1044 | A character string with $n$ string elements denotes a 1045 | string of $n$ characters followed by maxstring$-n$ {\it 1046 | null} characters, where 1047 | 1048 | \begin{center} 1049 | $2\,{\leq}\,n\,{\leq}$ maxstring{\blank} 1050 | maxstring = 80{\blank}null = chr(0)\\ 1051 | \end{center} 1052 | 1053 | \noindent 1054 | The default length $n$ of a write parameter of type string 1055 | is the number of characters (if any) which precede the 1056 | first null character (if any), where 1057 | $0\,{\leq}\,n\,{\leq}$ maxstring. 1058 | \item 1059 | The required textfile {\it input} is the only input file. 1060 | The file identifier is omitted from {\it eof} and {\it 1061 | eoln} function designators and {\it read} and {\it readln} 1062 | statements. The input file is an implicit value parameter 1063 | of the eof and eoln functions and is an implicit variable 1064 | parameter of the read and readln procedures (see 4.2). 1065 | \item 1066 | The required textfile {\it output} is the only output 1067 | file. The file identifier is omitted from {\it write} and 1068 | {\it writeln} statements. The output file is an implicit 1069 | variable parameter of the write and writeln procedures 1070 | (see 4.2). 1071 | \end{enumerate} 1072 | 1073 | 1074 | \subsection{Required Identifiers} 1075 | 1076 | Table 3 lists the required identifiers of {\Superpascal}. 1077 | 1078 | \begin{table}[htb] 1079 | \caption{Required identifiers} 1080 | \begin{mytabular}{lll} 1081 | \hline 1082 | abs & maxint & round \\ 1083 | arctan & maxstring & send \\ 1084 | boolean & null & sin \\ 1085 | char & odd & sqr \\ 1086 | chr & open & sqrt \\ 1087 | cos & ord & string \\ 1088 | eof & pred & succ \\ 1089 | eoln & read & true \\ 1090 | exp & readln & trunc \\ 1091 | false & real & write \\ 1092 | integer & receive & writeln\\ 1093 | ln & & \\ 1094 | \hline 1095 | \end{mytabular} 1096 | \end{table} 1097 | 1098 | 1099 | \subsection{Syntax Summary} 1100 | 1101 | The following grammar defines the complete syntax of 1102 | {\Superpascal}. 1103 | 1104 | \blankline 1105 | 1106 | \begin{grammar} 1107 | {\GA}program = \\ 1108 | {\GB}program-heading ``;'' program-block ``.'' . \\ 1109 | {\GA}program-heading = \\ 1110 | {\GB}``{\Program}'' program-identifier 1111 | [ ``('' program-parameters ``)'' ] . \\ 1112 | {\GA}program-parameters = \\ 1113 | {\GB}parameter-identifier 1114 | \{ ``,'' parameter-identifier \} . \\ 1115 | {\GA}program-block = \\ 1116 | {\GB}block . \\ 1117 | {\GA}block = \\ 1118 | {\GB}[ constant-definitions ] 1119 | [ type-definitions ] \\ 1120 | {\GC}[ variable-declarations ] 1121 | [ routine-declarations ] \\ 1122 | {\GD}statement-part . \\ 1123 | {\GA}constant-definitions = \\ 1124 | {\GB}``{\Const}'' constant-definition ``;'' 1125 | \{ constant-definition ``;'' \} . \\ 1126 | {\GA}constant-definition = \\ 1127 | {\GB}constant-identifier ``='' constant . \\ 1128 | {\GA}constant = \\ 1129 | {\GB}[ sign ] unsigned-constant . \\ 1130 | {\GA}sign = \\ 1131 | {\GB}``+'' $|$ ``$-$'' . \\ 1132 | {\GA}type-definitions = \\ 1133 | {\GB}``{\Type}'' type-definition ``;'' 1134 | \{ type-definition ``;'' \} . \\ 1135 | {\GA}type-definition = \\ 1136 | {\GB}type-identifier ``='' new-type . \\ 1137 | {\GA}new-type = \\ 1138 | {\GB}enumerated-type $|$ array-type $|$ 1139 | record-type $|$ channel-type . \\ 1140 | {\GA}enumerated-type = \\ 1141 | {\GB}``('' constant-identifier-list ``)'' . \\ 1142 | {\GA}constant-identifier-list = \\ 1143 | {\GB}constant-identifier 1144 | \{ ``,'' constant-identifier \} . \\ 1145 | {\GA}array-type = \\ 1146 | {\GB}``{\Array}'' index-range ``{\Of}'' 1147 | type-identifier . \\ 1148 | {\GA}index-range = \\ 1149 | {\GB}``['' constant ``..'' constant ``]'' . \\ 1150 | {\GA}record-type = \\ 1151 | {\GB}``{\Record}'' field-list ``{\End}'' . \\ 1152 | {\GA}field-list = \\ 1153 | {\GB}record-section 1154 | \{ ``;'' record-section \} [ ``;'' ] . \\ 1155 | {\GA}record-section = \\ 1156 | {\GB}field-identifier-list ``:'' type-identifier . \\ 1157 | {\GA}field-identifier-list = \\ 1158 | {\GB}field-identifier 1159 | \{ ``,'' field-identifier \} . \\ 1160 | {\GA}channel-type = \\ 1161 | {\GB}``$*$'' ``('' message-type-list ``)'' . \\ 1162 | {\GA}message-type-list = \\ 1163 | {\GB}type-identifier \{ ``,'' type-identifier \} . \\ 1164 | {\GA}variable-declarations = \\ 1165 | {\GB}``{\Var}'' variable-declaration ``;'' 1166 | \{ variable-declaration ``;'' \} . \\ 1167 | {\GA}variable-declaration = \\ 1168 | {\GB}variable-identifier-list ``:'' type-identifier . \\ 1169 | {\GA}variable-identifier-list = \\ 1170 | {\GB}variable-identifier 1171 | \{ ``,'' variable-identifier \} . \\ 1172 | {\GA}routine-declarations = \\ 1173 | {\GB}routine-declaration ``;'' 1174 | \{ routine-declaration ``;'' \} . \\ 1175 | {\GA}routine-declaration = \\ 1176 | {\GB}function-declaration $|$ procedure-declaration . \\ 1177 | {\GA}function-declaration = \\ 1178 | {\GB}function-heading ``;'' function-block . \\ 1179 | {\GA}function-heading = \\ 1180 | {\GB}``{\Function}'' function-identifier 1181 | [ formal-parameter-list ] \\ 1182 | {\GC}``:'' type-identifier . \\ 1183 | {\GA}formal-parameter-list = \\ 1184 | {\GB}``('' formal-parameters ``)'' . \\ 1185 | {\GA}formal-parameters = \\ 1186 | {\GB}formal-parameter-section 1187 | \{ ``;'' formal-parameter-section \} . \\ 1188 | {\GA}formal-parameter-section = \\ 1189 | {\GB}[ ``{\Var}'' ] variable-declaration . \\ 1190 | {\GA}function-block = \\ 1191 | {\GB}block . \\ 1192 | {\GA}procedure-declaration = \\ 1193 | {\GB}procedure-heading ``;'' procedure-block . \\ 1194 | {\GA}procedure-heading = \\ 1195 | {\GB}``{\Procedure}'' procedure-identifier 1196 | [ formal-parameter-list ] . \\ 1197 | {\GA}procedure-block = \\ 1198 | {\GB}block . \\ 1199 | {\GA}statement-part = \\ 1200 | {\GB}compound-statement . \\ 1201 | {\GA}compound-statement = \\ 1202 | {\GB}``{\Begin}'' statement-sequence ``{\End}'' . \\ 1203 | {\GA}statement-sequence = \\ 1204 | {\GB}statement \{ ``;'' statement \} . \\ 1205 | {\GA}statement = \\ 1206 | {\GB}empty-statement $|$ assignment-statement $|$ \\ 1207 | {\GB}procedure-statement $|$ if-statement $|$ \\ 1208 | {\GB}while-statement $|$ repeat-statement $|$ \\ 1209 | {\GB}for-statement $|$ case-statement $|$ \\ 1210 | {\GB}compound-statement $|$ parallel-statement $|$ \\ 1211 | {\GB}forall-statement $|$ unrestricted-statement $|$ \\ 1212 | {\GB}assume-statement . \\ 1213 | {\GA}empty-statement = . \\ 1214 | {\GA}assignment-statement = \\ 1215 | {\GB}left-part ``:='' expression . \\ 1216 | {\GA}left-part = \\ 1217 | {\GB}variable-access $|$ function-identifier . \\ 1218 | {\GA}procedure-statement = \\ 1219 | {\GB}procedure-identifier [ actual-parameter-list ] . \\ 1220 | {\GA}actual-parameter-list = \\ 1221 | {\GB}``('' actual-parameters ``)'' . \\ 1222 | {\GA}actual-parameters = \\ 1223 | {\GB}actual-parameter \{ ``,'' actual-parameter \} . \\ 1224 | {\GA}actual-parameter = \\ 1225 | {\GB}expression $|$ variable-access $|$ 1226 | write-parameter . \\ 1227 | {\GA}write-parameter = \\ 1228 | {\GB}expression 1229 | [ ``:'' expression [ ``:'' expression ] ] . \\ 1230 | {\GA}if-statement = \\ 1231 | {\GB}``{\If}'' expression ``{\Then}'' statement \\ 1232 | {\GC}[ ``{\Else}'' statement ] . \\ 1233 | {\GA}while-statement = \\ 1234 | {\GB}``{\While}'' expression ``{\Do}'' statement . \\ 1235 | {\GA}repeat-statement = \\ 1236 | {\GB}``{\Repeat}'' statement-sequence 1237 | ``{\Until}'' expression . \\ 1238 | {\GA}for-statement = \\ 1239 | {\GB}``{\For}'' control-variable ``:='' expression \\ 1240 | {\GC}( ``{\To}'' $|$ ``{\Downto}'' ) expression 1241 | ``{\Do}'' statement . \\ 1242 | {\GA}control-variable = \\ 1243 | {\GB}entire-variable . \\ 1244 | {\GA}case-statement = \\ 1245 | {\GB}``{\Case}'' expression ``{\Of}'' 1246 | case-list ``{\End}'' . \\ 1247 | {\GA}case-list = \\ 1248 | {\GB}case-list-element \{ ``;'' case-list-element \} 1249 | [ ``;'' ] . \\ 1250 | {\GA}case-list-element = \\ 1251 | {\GB}case-constant \{ ``,'' case-constant \} 1252 | ``:'' statement . \\ 1253 | {\GA}case-constant = \\ 1254 | {\GB}constant . \\ 1255 | {\GA}parallel-statement = \\ 1256 | {\GB}``{\Parallel}'' process-statement-list 1257 | ``{\End}'' . \\ 1258 | {\GA}process-statement-list = \\ 1259 | {\GB}process-statement 1260 | \{ ``$|$'' process-statement \} . \\ 1261 | {\GA}process-statement = \\ 1262 | {\GB}statement-sequence . \\ 1263 | {\GA}forall-statement = \\ 1264 | {\GB}``{\Forall}'' index-variable-declaration 1265 | ``{\Do}'' \\ 1266 | {\GC}element-statement . \\ 1267 | {\GA}index-variable-declaration = \\ 1268 | {\GB}variable-identifier ``:='' process-index-range . \\ 1269 | {\GA}process-index-range = \\ 1270 | {\GB}expression ``{\To}'' expression . \\ 1271 | {\GA}element-statement = \\ 1272 | {\GB}statement . \\ 1273 | {\GA}unrestricted-statement = \\ 1274 | {\GB}``['' ``{\Sic}'' ``]'' statement . \\ 1275 | {\GA}assume-statement = \\ 1276 | {\GB}``{\Assume}'' expression . \\ 1277 | {\GA}expression = \\ 1278 | {\GB}simple-expression \\ 1279 | {\GC}[ relational-operator simple-expression ] . \\ 1280 | {\GA}relational-operator = \\ 1281 | {\GB}``$<$'' $|$ ``='' $|$ ``$>$'' $|$ 1282 | ``$<=$'' $|$ ``$<>$'' $|$ ``$>=$'' . \\ 1283 | {\GA}simple-expression = \\ 1284 | {\GB}[ sign ] term \{ adding-operator term \} . \\ 1285 | {\GA}adding-operator = \\ 1286 | {\GB}``+'' $|$ ``$-$'' $|$ ``{\Or}'' . \\ 1287 | {\GA}term = \\ 1288 | {\GB}factor \{ multiplying-operator factor \} . \\ 1289 | {\GA}multiplying-operator = \\ 1290 | {\GB}``$*$'' $|$ ``/'' $|$ ``{\Div}'' $|$ 1291 | ``{\Mod}'' $|$ ``{\And}'' . \\ 1292 | {\GA}factor = \\ 1293 | {\GB}function-designator $|$ variable-access $|$ \\ 1294 | {\GB}unsigned-constant $|$ ``('' expression ``)'' $|$ \\ 1295 | {\GB}``{\Not}'' factor . \\ 1296 | {\GA}function-designator = \\ 1297 | {\GB}function-identifier [ actual-parameter-list ] . \\ 1298 | {\GA}variable-access = \\ 1299 | {\GB}entire-variable \{ component-selector \} . \\ 1300 | {\GA}entire-variable = \\ 1301 | {\GB}variable-identifier . \\ 1302 | {\GA}component-selector = \\ 1303 | {\GB}field-selector $|$ indexed-selector . \\ 1304 | {\GA}field-selector = \\ 1305 | {\GB}``.'' field-identifier . \\ 1306 | {\GA}indexed-selector = \\ 1307 | {\GB}``['' index-expressions ``]'' . \\ 1308 | {\GA}index-expressions = \\ 1309 | {\GB}expression \{ ``,'' expression \} . \\ 1310 | {\GA}unsigned-constant = \\ 1311 | {\GB}character-string $|$ unsigned-real $|$ \\ 1312 | {\GB}unsigned-integer $|$ constant-identifier . \\ 1313 | {\GA}character-string = \\ 1314 | {\GB}``\,'\,'' string-elements ``\,'\,'' . \\ 1315 | {\GA}string-elements = \\ 1316 | {\GB}string-element \{ string-element \} . \\ 1317 | {\GA}string-element = \\ 1318 | {\GB}string-character $|$ apostrophe-image . \\ 1319 | {\GA}apostrophe-image = \\ 1320 | {\GB}``\,''\,'' . \\ 1321 | {\GA}unsigned-real = \\ 1322 | {\GB}unsigned-integer real-option . \\ 1323 | {\GA}real-option = \\ 1324 | {\GB}``.'' fractional-part [ scaling-part ] $|$ 1325 | scaling-part . \\ 1326 | {\GA}fractional-part = \\ 1327 | {\GB}digit-sequence . \\ 1328 | {\GA}scaling-part = \\ 1329 | {\GB}``e'' scale-factor . \\ 1330 | {\GA}scale-factor = \\ 1331 | {\GB}[ sign ] unsigned-integer . \\ 1332 | {\GA}unsigned-integer = \\ 1333 | {\GB}digit-sequence . \\ 1334 | {\GA}digit-sequence = \\ 1335 | {\GB}digit \{ digit \} . \\ 1336 | {\GA}identifier = \\ 1337 | {\GB}letter \{ letter $|$ digit \} . \\ 1338 | \end{grammar} 1339 | 1340 | 1341 | \acknowledgements 1342 | 1343 | I thank Jonathan Greenfield and Peter O'Hearn for their 1344 | helpful comments. 1345 | 1346 | 1347 | \begin{mybibliography}{3} 1348 | \entry 1349 | IEEE (1983). {\it IEEE Standard Pascal Computer 1350 | Programming Language}. Institute of Electrical and 1351 | Electronics Engineers, New York, NY. 1352 | \entry 1353 | Brinch Hansen, P. (1993a) SuperPascal---a publication 1354 | language for parallel scientific computing. School of 1355 | Computer and Information Science, Syracuse University, 1356 | Syracuse, NY. 1357 | \entry 1358 | Brinch Hansen, P. (1993b) Interference control in 1359 | SuperPascal---a block-structured parallel language. 1360 | School of Computer and Information Science, Syracuse 1361 | Syracuse University, Syracuse, NY. 1362 | \end{mybibliography} 1363 | 1364 | \end{document} 1365 | -------------------------------------------------------------------------------- /scan.p: -------------------------------------------------------------------------------- 1 | { SUPERPASCAL COMPILER 2 | SCANNER 3 | 28 October 1993 4 | Copyright (c) 1993 Per Brinch Hansen } 5 | 6 | procedure scan(var lineno: integer; 7 | procedure accept(var value: char); 8 | procedure put(value: integer); 9 | procedure putreal(value: real); 10 | procedure putstring( 11 | length: integer; 12 | value: string); 13 | procedure error(kind: phrase); 14 | procedure halt(kind: phrase)); 15 | const 16 | maxkey = 631; maxshort = 10; 17 | type 18 | charset = set of char; 19 | short = 20 | packed array [1..maxshort] of 21 | char; 22 | spellingtable = 23 | array [1..maxchar] of char; 24 | wordpointer = ^ wordrecord; 25 | wordrecord = 26 | record 27 | nextword: wordpointer; 28 | symbol: boolean; 29 | index, length, lastchar: 30 | integer 31 | end; 32 | hashtable = 33 | array [1..maxkey] of wordpointer; 34 | var 35 | ch: char; afterperiod: boolean; 36 | alphanumeric, capitalletters, 37 | digits, endcomment, endline, 38 | invisible, letters, radix, 39 | separators, smallletters: charset; 40 | spelling: spellingtable; 41 | characters, identifiers: integer; 42 | hash: hashtable; 43 | nulstring: string; 44 | 45 | { INPUT } 46 | 47 | procedure nextchar; 48 | var skipped: boolean; 49 | begin 50 | repeat 51 | accept(ch); 52 | if (ch < chr(null)) 53 | or (ch > chr(del)) 54 | then 55 | skipped := true 56 | else 57 | skipped := ch in invisible 58 | until not skipped 59 | end; 60 | 61 | { OUTPUT } 62 | 63 | procedure emit1(sym: integer); 64 | begin put(sym) end; 65 | 66 | procedure emit2( 67 | sym, arg: integer); 68 | begin 69 | put(sym); put(arg) 70 | end; 71 | 72 | procedure emitreal(value: real); 73 | begin 74 | put(realconst1); 75 | putreal(value) 76 | end; 77 | 78 | procedure emitstring( 79 | length: integer; 80 | value: string); 81 | begin 82 | put(stringconst1); 83 | putstring(length, value) 84 | end; 85 | 86 | { WORD SYMBOLS AND IDENTIFIERS } 87 | 88 | function key(text: string; 89 | length: integer): integer; 90 | const w = 32641 { 32768 - 127 }; 91 | n = maxkey; 92 | var i, sum: integer; 93 | begin 94 | sum := 0; i := 1; 95 | while i <= length do 96 | begin 97 | sum := (sum + ord(text[i])) 98 | mod w; 99 | i := i + 1 100 | end; 101 | key := sum mod n + 1 102 | end; 103 | 104 | procedure insert( 105 | symbol: boolean; text: string; 106 | length, index, keyno: integer); 107 | var pointer: wordpointer; 108 | m, n: integer; 109 | begin 110 | { insert word in 111 | spelling table } 112 | characters := 113 | characters + length; 114 | if characters > maxchar then 115 | halt(maxchar5); 116 | m := length; 117 | n := characters - m; 118 | while m > 0 do 119 | begin 120 | spelling[m + n] := text[m]; 121 | m := m - 1 122 | end; 123 | { insert word in a word list } 124 | new(pointer); 125 | pointer^.nextword := 126 | hash[keyno]; 127 | pointer^.symbol := symbol; 128 | pointer^.index := index; 129 | pointer^.length := length; 130 | pointer^.lastchar := 131 | characters; 132 | hash[keyno] := pointer 133 | end; 134 | 135 | function found(text: string; 136 | length: integer; 137 | pointer: wordpointer): boolean; 138 | var same: boolean; m, n: integer; 139 | begin 140 | if pointer^.length = length then 141 | begin 142 | same := true; m := length; 143 | n := pointer^.lastchar - m; 144 | while same and (m > 0) do 145 | begin 146 | same := text[m] = 147 | spelling[m + n]; 148 | m := m - 1 149 | end 150 | end 151 | else same := false; 152 | found := same 153 | end; 154 | 155 | procedure declare( 156 | shorttext: short; 157 | index: integer; 158 | symbol: boolean); 159 | var i, length: integer; 160 | text: string; 161 | begin 162 | length := maxshort; 163 | while shorttext[length] = sp 164 | do length := length - 1; 165 | for i := 1 to length do 166 | text[i] := shorttext[i]; 167 | insert(symbol, text, length, 168 | index, key(text, length)) 169 | end; 170 | 171 | procedure search( 172 | text: string; 173 | length: integer; 174 | var symbol: boolean; 175 | var index: integer); 176 | var keyno: integer; 177 | pointer: wordpointer; 178 | done: boolean; 179 | begin 180 | keyno := key(text, length); 181 | pointer := hash[keyno]; 182 | done := false; 183 | while not done do 184 | if pointer = nil then 185 | begin 186 | symbol := false; 187 | identifiers := 188 | identifiers + 1; 189 | index := identifiers; 190 | insert(false, text, 191 | length, index, keyno); 192 | done := true 193 | end 194 | else if 195 | found(text, length, pointer) 196 | then 197 | begin 198 | symbol := pointer^.symbol; 199 | index := pointer^.index; 200 | done := true 201 | end 202 | else 203 | pointer := pointer^.nextword 204 | end; 205 | 206 | { WordSymbol = 207 | "and" | "array" | "assume" | 208 | "begin" | "case" | "const" | 209 | "div" | "do" | "downto" | 210 | "else" | "end" | "for" | 211 | "forall" | "function" | "if" | 212 | "mod" | "not" | "of" | "or" | 213 | "parallel" | "procedure" | 214 | "program" | "record" | 215 | "repeat" | "sic" | "then" | 216 | "to" | "type" | "until" | 217 | "var" | "while" . 218 | UnusedWord = 219 | "file" | "goto" | "in" | 220 | "label" | "nil" | "packed" | 221 | "set" | "with" . } 222 | 223 | procedure initialize; 224 | var i: integer; 225 | begin 226 | digits := ['0'..'9']; 227 | capitalletters := ['A'..'Z']; 228 | smallletters := ['a'..'z']; 229 | letters := 230 | capitalletters + smallletters; 231 | alphanumeric := letters + digits; 232 | endcomment := ['}', chr(etx)]; 233 | endline := [chr(nl), chr(etx)]; 234 | invisible := 235 | [chr(0)..chr(31), chr(127)] 236 | - [chr(nl), chr(etx)]; 237 | radix := ['e', 'E']; 238 | separators := [sp, chr(nl), '{']; 239 | for i := 1 to maxkey do 240 | hash[i] := nil; 241 | for i := 1 to maxstring do 242 | nulstring[i] := chr(null); 243 | characters := 0; 244 | { insert word symbols } 245 | declare('and ', and1, 246 | true); 247 | declare('array ', array1, 248 | true); 249 | declare('assume ', assume1, 250 | true); 251 | declare('begin ', begin1, 252 | true); 253 | declare('case ', case1, 254 | true); 255 | declare('const ', const1, 256 | true); 257 | declare('div ', div1, 258 | true); 259 | declare('do ', do1, 260 | true); 261 | declare('downto ', downto1, 262 | true); 263 | declare('else ', else1, 264 | true); 265 | declare('end ', end1, 266 | true); 267 | declare('file ', unknown1, 268 | true); 269 | declare('for ', for1, 270 | true); 271 | declare('forall ', forall1, 272 | true); 273 | declare('function ', function1, 274 | true); 275 | declare('goto ', unknown1, 276 | true); 277 | declare('if ', if1, 278 | true); 279 | declare('in ', unknown1, 280 | true); 281 | declare('label ', unknown1, 282 | true); 283 | declare('mod ', mod1, 284 | true); 285 | declare('nil ', unknown1, 286 | true); 287 | declare('not ', not1, 288 | true); 289 | declare('of ', of1, 290 | true); 291 | declare('or ', or1, 292 | true); 293 | declare('packed ', unknown1, 294 | true); 295 | declare('parallel ', parallel1, 296 | true); 297 | declare('procedure ', procedure1, 298 | true); 299 | declare('program ', program1, 300 | true); 301 | declare('record ', record1, 302 | true); 303 | declare('repeat ', repeat1, 304 | true); 305 | declare('set ', unknown1, 306 | true); 307 | declare('sic ', sic1, 308 | true); 309 | declare('then ', then1, 310 | true); 311 | declare('to ', to1, 312 | true); 313 | declare('type ', type1, 314 | true); 315 | declare('until ', until1, 316 | true); 317 | declare('var ', var1, 318 | true); 319 | declare('while ', while1, 320 | true); 321 | declare('with ', unknown1, 322 | true); 323 | { insert standard identifiers } 324 | declare('abs ', abs0, 325 | false); 326 | declare('arctan ', arctan0, 327 | false); 328 | declare('boolean ', boolean0, 329 | false); 330 | declare('char ', char0, 331 | false); 332 | declare('chr ', chr0, 333 | false); 334 | declare('cos ', cos0, 335 | false); 336 | declare('eof ', eof0, 337 | false); 338 | declare('eoln ', eoln0, 339 | false); 340 | declare('exp ', exp0, 341 | false); 342 | declare('false ', false0, 343 | false); 344 | declare('integer ', integer0, 345 | false); 346 | declare('ln ', ln0, 347 | false); 348 | declare('maxint ', maxint0, 349 | false); 350 | declare('maxstring ', maxstring0, 351 | false); 352 | declare('null ', null0, 353 | false); 354 | declare('odd ', odd0, 355 | false); 356 | declare('open ', open0, 357 | false); 358 | declare('ord ', ord0, 359 | false); 360 | declare('pred ', pred0, 361 | false); 362 | declare('read ', read0, 363 | false); 364 | declare('readln ', readln0, 365 | false); 366 | declare('real ', real0, 367 | false); 368 | declare('receive ', receive0, 369 | false); 370 | declare('round ', round0, 371 | false); 372 | declare('send ', send0, 373 | false); 374 | declare('sin ', sin0, 375 | false); 376 | declare('sqr ', sqr0, 377 | false); 378 | declare('sqrt ', sqrt0, 379 | false); 380 | declare('string ', string0, 381 | false); 382 | declare('succ ', succ0, 383 | false); 384 | declare('true ', true0, 385 | false); 386 | declare('trunc ', trunc0, 387 | false); 388 | declare('write ', write0, 389 | false); 390 | declare('writeln ', writeln0, 391 | false); 392 | identifiers := maxstandard; 393 | afterperiod := false 394 | end; 395 | 396 | { LEXICAL ANALYSIS } 397 | 398 | { Comment = 399 | LeftBrace [ CommentElement ]* 400 | RightBrace . 401 | CommentElement = 402 | GraphicCharacter | NewLine | 403 | Comment . } 404 | 405 | procedure comment; 406 | begin 407 | (* ch = '{' *) nextchar; 408 | while not (ch in endcomment) do 409 | if ch = '{' then comment 410 | else 411 | begin 412 | if ch = chr(nl) then 413 | begin 414 | nextchar; 415 | emit2(newline1, lineno) 416 | end 417 | else nextchar 418 | end; 419 | if ch = '}' then nextchar 420 | else error(comment3) 421 | end; 422 | 423 | { Word = 424 | WordSymbol | Identifier . 425 | Identifier = 426 | Letter [ Letter | Digit ]* . } 427 | 428 | procedure word; 429 | var symbol: boolean; text: string; 430 | length, index: integer; 431 | begin 432 | { ch in letters } 433 | length := 0; 434 | while ch in alphanumeric do 435 | begin 436 | { convert a capital letter 437 | (if any) to lower case } 438 | if ch in capitalletters then 439 | ch := chr(ord(ch) + 440 | ord('a') - ord('A')); 441 | if length = maxstring then 442 | halt(maxstring5); 443 | length := length + 1; 444 | text[length] := ch; 445 | nextchar; 446 | end; 447 | search(text, length, symbol, 448 | index); 449 | if symbol then emit1(index) 450 | else emit2(identifier1, index) 451 | end; 452 | 453 | function scaled(r: real; 454 | s: integer): real; 455 | { scaled(r,s) = r*(10**s) } 456 | var max, min: real; 457 | begin 458 | max := maxreal / 10.0; 459 | while s > 0 do 460 | begin 461 | if r <= max then 462 | r := r * 10.0 463 | else error(number3); 464 | s := s - 1 465 | end; 466 | min := 10.0 * minreal; 467 | while s < 0 do 468 | begin 469 | if r >= min then 470 | r := r / 10.0 471 | else r := 0.0; 472 | s := s + 1 473 | end; 474 | scaled := r 475 | end; 476 | 477 | { DigitSequence = 478 | Digit [ Digit ]* . } 479 | 480 | procedure digitsequence( 481 | var r: real; 482 | var n: integer); 483 | { r := digitsequence; 484 | n := length(r) } 485 | var d: real; 486 | begin 487 | r := 0.0; n := 0; 488 | if ch in digits then 489 | while ch in digits do 490 | begin 491 | d := ord(ch) - ord('0'); 492 | r := 10.0 * r + d; 493 | n := n + 1; 494 | nextchar 495 | end 496 | else error(number3) 497 | end; 498 | 499 | { UnsignedScaleFactor = 500 | DigitSequence . } 501 | 502 | procedure unsignedscalefactor( 503 | var s: integer); 504 | { s := scalefactor } 505 | var r: real; n: integer; 506 | begin 507 | digitsequence(r, n); 508 | if r > maxint then 509 | begin 510 | error(number3); 511 | s := 0 512 | end 513 | else s := trunc(r) 514 | end; 515 | 516 | { ScaleFactor = 517 | [ Sign ] 518 | UnsignedScaleFactor . 519 | Sign = 520 | "+" | "-" . } 521 | 522 | procedure scalefactor( 523 | var s: integer); 524 | { s := scalefactor } 525 | begin 526 | if ch = '+' then 527 | begin 528 | nextchar; 529 | unsignedscalefactor(s) 530 | end 531 | else if ch = '-' then 532 | begin 533 | nextchar; 534 | unsignedscalefactor(s); 535 | s := - s 536 | end 537 | else unsignedscalefactor(s) 538 | end; 539 | 540 | { UnsignedInteger = 541 | DigitSequence . } 542 | 543 | procedure unsignedinteger( 544 | r: real); 545 | var i: integer; 546 | begin 547 | if r > maxint then 548 | begin 549 | error(number3); 550 | i := 0 551 | end 552 | else i := trunc(r); 553 | emit2(intconst1, i) 554 | end; 555 | 556 | { UnsignedNumber = 557 | UnsignedReal | 558 | UnsignedInteger . 559 | UnsignedReal = 560 | IntegerPart RealOption . 561 | IntegerPart = 562 | DigitSequence . 563 | RealOption = 564 | "." FractionalPart 565 | [ ScalingPart ] | 566 | ScalingPart . 567 | FractionalPart = 568 | DigitSequence . 569 | ScalingPart = 570 | Radix ScaleFactor . 571 | Radix = 572 | "e" | "E" . } 573 | 574 | procedure unsignednumber; 575 | var i, f, r: real; 576 | s, n: integer; 577 | begin 578 | digitsequence(i, n); 579 | if ch = '.' then 580 | begin 581 | nextchar; 582 | if ch = '.' then 583 | begin 584 | { input = i.. 585 | and ch = '.' } 586 | unsignedinteger(i); 587 | afterperiod := true 588 | end 589 | else 590 | begin 591 | digitsequence(f, n); 592 | r := i + scaled(f, -n); 593 | { r = i.f } 594 | if ch in radix then 595 | begin 596 | nextchar; 597 | scalefactor(s); 598 | r := scaled(r, s) 599 | {r = i.f*(10**s) } 600 | end; 601 | emitreal(r) 602 | end 603 | end 604 | else if ch in radix then 605 | begin 606 | nextchar; 607 | scalefactor(s); 608 | r := scaled(i, s); 609 | { r = i*(10**s) } 610 | emitreal(r) 611 | end 612 | else unsignedinteger(i) 613 | end; 614 | 615 | { StringElement = 616 | StringCharacter | 617 | ApostropheImage . 618 | ApostropheImage = 619 | "''" . } 620 | 621 | procedure stringelement( 622 | var text: string; 623 | var length: integer); 624 | begin 625 | if length = maxstring then 626 | halt(maxstring5); 627 | length := length + 1; 628 | text[length] := ch; 629 | nextchar 630 | end; 631 | 632 | { CharacterString = 633 | "'" StringElements "'" . 634 | StringElements = 635 | StringElement 636 | [ StringElement ]* . } 637 | 638 | procedure characterstring; 639 | type state = 640 | (extend, accept, reject); 641 | var length: integer; s: state; 642 | text: string; 643 | begin 644 | { ch = apostrophe } 645 | text := nulstring; 646 | length := 0; 647 | nextchar; s := extend; 648 | while s = extend do 649 | if ch in endline then 650 | s := reject 651 | else if ch = apostrophe then 652 | begin 653 | nextchar; 654 | if ch = apostrophe then 655 | stringelement(text, 656 | length) 657 | else s := accept 658 | end 659 | else 660 | stringelement(text, length); 661 | if (s = accept) and (length > 0) 662 | then 663 | if length = 1 then 664 | emit2(charconst1, 665 | ord(text[1])) 666 | else 667 | emitstring(length, text) 668 | else emit1(unknown1) 669 | end; 670 | 671 | { TokenField = 672 | [ Separator ]* Token . 673 | Token = 674 | Literal | Identifier | 675 | SpecialSymbol | UnknownToken | 676 | EndText . 677 | Literal = 678 | UnsignedNumber | 679 | CharacterString . 680 | SpecialSymbol = 681 | "(" | ")" | "*" | "+" | "," | 682 | "-" | "." | "/" | ":" | ";" | 683 | "<" | "=" | ">" | "[" | "]" | 684 | ".." | ":=" | "<=" | "<>" | 685 | ">=" | "|" | WordSymbol . 686 | UnknownToken = 687 | UnusedWord | UnusedCharacter . 688 | UnusedCharacter = 689 | "!" | """ | "#" | "$" | "%" | 690 | "&" | "?" | "@" | "\" | "^" | 691 | "_" | "`" | "~" . } 692 | 693 | procedure nexttoken; 694 | begin 695 | while ch in separators do 696 | if ch = sp then nextchar 697 | else if ch = chr(nl) then 698 | begin 699 | nextchar; 700 | emit2(newline1, lineno) 701 | end 702 | else (* ch = '{' *) comment; 703 | if ch in letters then word 704 | else if ch in digits then 705 | unsignednumber 706 | else if ch = apostrophe then 707 | characterstring 708 | else if ch = '+' then 709 | begin 710 | emit1(plus1); 711 | nextchar 712 | end 713 | else if ch = '-' then 714 | begin 715 | emit1(minus1); 716 | nextchar 717 | end 718 | else if ch = '*' then 719 | begin 720 | emit1(asterisk1); 721 | nextchar; 722 | end 723 | else if ch = '/' then 724 | begin 725 | emit1(slash1); 726 | nextchar 727 | end 728 | else if ch = '<' then 729 | begin 730 | nextchar; 731 | if ch = '=' then 732 | begin 733 | emit1(notgreater1); 734 | nextchar 735 | end 736 | else if ch = '>' then 737 | begin 738 | emit1(notequal1); 739 | nextchar 740 | end 741 | else emit1(less1) 742 | end 743 | else if ch = '=' then 744 | begin 745 | emit1(equal1); 746 | nextchar 747 | end 748 | else if ch = '>' then 749 | begin 750 | nextchar; 751 | if ch = '=' then 752 | begin 753 | emit1(notless1); 754 | nextchar 755 | end 756 | else emit1(greater1) 757 | end 758 | else if ch = ':' then 759 | begin 760 | nextchar; 761 | if ch = '=' then 762 | begin 763 | emit1(becomes1); 764 | nextchar 765 | end 766 | else emit1(colon1) 767 | end 768 | else if ch = '(' then 769 | begin 770 | emit1(leftparenthesis1); 771 | nextchar 772 | end 773 | else if ch = ')' then 774 | begin 775 | emit1(rightparenthesis1); 776 | nextchar 777 | end 778 | else if ch = '[' then 779 | begin 780 | emit1(leftbracket1); 781 | nextchar 782 | end 783 | else if ch = ']' then 784 | begin 785 | emit1(rightbracket1); 786 | nextchar 787 | end 788 | else if ch = ',' then 789 | begin 790 | emit1(comma1); 791 | nextchar 792 | end 793 | else if ch = '.' then 794 | if afterperiod then 795 | begin 796 | emit1(doubledot1); 797 | nextchar; 798 | afterperiod := false 799 | end 800 | else 801 | begin 802 | nextchar; 803 | if ch = '.' then 804 | begin 805 | emit1(doubledot1); 806 | nextchar 807 | end 808 | else emit1(period1) 809 | end 810 | else if ch = ';' then 811 | begin 812 | emit1(semicolon1); 813 | nextchar 814 | end 815 | else if ch = '|' then 816 | begin 817 | emit1(bar1); 818 | nextchar 819 | end 820 | else if ch <> chr(etx) then 821 | begin 822 | emit1(unknown1); 823 | nextchar 824 | end 825 | end; 826 | 827 | { Program = 828 | TokenField [ TokenField ]* . } 829 | 830 | begin 831 | initialize; nextchar; 832 | emit2(newline1, lineno); 833 | while ch <> chr(etx) do 834 | nexttoken; 835 | emit1(endtext1) 836 | end; 837 | -------------------------------------------------------------------------------- /sun3.user: -------------------------------------------------------------------------------- 1 | echo Compiling Sun3 SuperPascal: 2 | pc -s -H -O -f68881 -o sc compile.p 3 | pc -s -H -O -f68881 -o sr interpret.p 4 | -------------------------------------------------------------------------------- /sun4.user: -------------------------------------------------------------------------------- 1 | echo Compiling Sun4 SuperPascal: 2 | pc -s -H -O -cg89 -o sc compile.p 3 | pc -s -H -O -cg89 -o sr interpret.p 4 | -------------------------------------------------------------------------------- /user.tex: -------------------------------------------------------------------------------- 1 | % THE SUPERPASCAL USER MANUAL 2 | % PER BRINCH HANSEN 3 | % School of Computer and Information Science 4 | % Syracuse University, Syracuse, NY 13244, USA 5 | % 28 October 1993 6 | % Copyright(c) 1993 Per Brinch Hansen 7 | 8 | % LATEX PREAMBLE 9 | \documentstyle[twoside,11pt]{article} 10 | \pagestyle{myheadings} 11 | \setlength{\topmargin}{7mm} 12 | \setlength{\textheight}{200mm} 13 | \setlength{\textwidth}{140mm} 14 | \setlength{\oddsidemargin}{14mm} 15 | \setlength{\evensidemargin}{12mm} 16 | \newcommand{\acknowledgements} 17 | {\section*{Acknowledgements} 18 | \addcontentsline{toc}{section} 19 | {Acknowledgements} 20 | } 21 | \newcommand{\blank} 22 | {\mbox{\hspace{1.8em}}} 23 | \newcommand{\blankline} 24 | {\medskip} 25 | \newcommand{\Copyright} 26 | {Copyright {\copyright}} 27 | \newcommand{\entry} 28 | {\bibitem{}} 29 | \newcommand{\example} 30 | {{\it Example:}} 31 | \newcommand{\examples} 32 | {{\it Examples:}} 33 | \newcommand{\mytitle}[3] 34 | % [title,month,year] 35 | {\markboth{Per Brinch Hansen}{#1} 36 | \thispagestyle{empty} 37 | \begin{center} 38 | {\Large\bf #1}\\ 39 | % TITLE 40 | \blankline 41 | PER BRINCH HANSEN 42 | \footnote{ 43 | \Copyright #3 % Year 44 | Per Brinch Hansen. All rights reserved.}\\ 45 | \blankline 46 | {\it 47 | School of Computer and Information Science \\ 48 | Syracuse University, Syracuse, NY 13244, USA\\ 49 | } 50 | \blankline 51 | #2 #3\\ 52 | % Month Year 53 | \end{center} 54 | } 55 | \newcommand{\Superpascal} 56 | {\it SuperPascal} 57 | \newenvironment{grammar} 58 | {\begin{small}} 59 | {\end{small}} 60 | \newenvironment{myabstract} 61 | {\begin{rm} 62 | \noindent{\bf Abstract:}} 63 | {\end{rm}} 64 | \newenvironment{mybibliography}[1] 65 | % [widestlabel] 66 | {\begin{small} 67 | \begin{thebibliography}{#1} 68 | \addcontentsline{toc} 69 | {section}{References}} 70 | { \end{thebibliography} 71 | \end{small}} 72 | \newenvironment{mykeywords} 73 | {\begin{small} 74 | \noindent{\bf Key Words:}} 75 | {\end{small}} 76 | \newenvironment{mytabular}[1] 77 | % [columns] 78 | {\begin{small} 79 | \begin{center} 80 | \begin{tabular}{#1}} 81 | { \end{tabular} 82 | \end{center} 83 | \end{small}} 84 | \newenvironment{program}[1] 85 | % [width] 86 | {\begin{center} 87 | \begin{minipage}{#1}} 88 | { \end{minipage} 89 | \end{center}} 90 | % Program Indentation 91 | \newcommand{\PA} 92 | {\noindent} 93 | \newcommand{\PB} 94 | {\mbox{\hspace{1em}}} 95 | \newcommand{\PC} 96 | {\mbox{\hspace{2em}}} 97 | \newcommand{\PD} 98 | {\mbox{\hspace{3em}}} 99 | \newcommand{\PE} 100 | {\mbox{\hspace{4em}}} 101 | 102 | % DOCUMENT TEXT 103 | \begin{document} 104 | 105 | \mytitle{The SuperPascal User Manual} 106 | {November}{1993} 107 | 108 | \begin{myabstract} 109 | This report explains how you compile and run {\Superpascal} 110 | programs [Brinch Hansen 1993a]. 111 | \end{myabstract} 112 | 113 | 114 | \section{Command Aliases} 115 | 116 | If you are using {\Superpascal} under Unix, please define the 117 | following command aliases in the file .{\it cshrc} in your 118 | home directory: 119 | 120 | \begin{program}{23.5em} 121 | {\PA}alias sc $<${\it path name of an executable compiler sc}$>$ \\ 122 | {\PA}alias sr $<${\it path name of an executable interpreter sr}$>$\\ 123 | \end{program} 124 | 125 | 126 | \section{Program Compilation} 127 | 128 | You compile a {\Superpascal} program by typing the command 129 | 130 | \begin{center} 131 | {\it sc} 132 | \end{center} 133 | 134 | \noindent 135 | followed by a return. When the message 136 | 137 | \begin{center} 138 | source = 139 | \end{center} 140 | 141 | \noindent 142 | appears, type the name of a program textfile followed by a 143 | return. After the message 144 | 145 | \begin{center} 146 | code = 147 | \end{center} 148 | 149 | \noindent 150 | type the name of a new program codefile followed by a 151 | return. 152 | 153 | \blankline 154 | 155 | \example 156 | 157 | \begin{program}{10.5em} 158 | {\PA}{\it sc} \\ 159 | {\PB}source = {\it sortprogram}\\ 160 | {\PB}code = {\it sortcode} \\ 161 | \end{program} 162 | 163 | If the compiler finds errors in a program text, the errors 164 | are reported both on the screen and in the textfile {\it 165 | errors}, but no program code is output. 166 | 167 | 168 | \section{Program Execution} 169 | 170 | You run a compiled {\Superpascal} program by typing the 171 | command 172 | 173 | \begin{center} 174 | {\it sr} 175 | \end{center} 176 | 177 | \noindent 178 | followed by a return. When the message 179 | 180 | \begin{center} 181 | code = 182 | \end{center} 183 | 184 | \noindent 185 | appears, type the name of a program codefile followed by a 186 | return. After the message 187 | 188 | \begin{center} 189 | select files? 190 | \end{center} 191 | 192 | \noindent 193 | you have a choice: 194 | 195 | \blankline 196 | 197 | 1.~If you type {\it no} followed by a return, the program 198 | will be executed with text input from the {\it keyboard} 199 | and text output on the {\it screen}. 200 | 201 | \blankline 202 | 203 | 2.~If you type {\it yes} followed by a return, you will 204 | first be asked to name the input file: 205 | 206 | \begin{center} 207 | input = 208 | \end{center} 209 | 210 | \noindent 211 | Type the name of an existing textfile or the word {\it 212 | keyboard} followed by a return. Finally, you will be asked 213 | to name the output: 214 | 215 | \begin{center} 216 | output = 217 | \end{center} 218 | 219 | \noindent 220 | Type the name of a new textfile or the word {\it screen} 221 | followed by a return. 222 | 223 | \blankline 224 | 225 | \examples 226 | 227 | \begin{program}{8.1em} 228 | {\PA}{\it sr} \\ 229 | {\PB}code = {\it sortcode} \\ 230 | {\PB}select files? {\it no} \\ 231 | {\PA} \\ 232 | {\PA}{\it sr} \\ 233 | {\PB}code = {\it sortcode} \\ 234 | {\PB}select files? {\it yes}\\ 235 | {\PB}input = {\it testdata} \\ 236 | {\PB}output = {\it screen} \\ 237 | \end{program} 238 | 239 | 240 | \section{Compile-time Errors} 241 | 242 | During compilation, the following program errors are 243 | reported: 244 | 245 | \begin{itemize} 246 | \item 247 | {\it Ambiguous case constant:} Two case constants denote 248 | the same value. 249 | \item 250 | {\it Ambiguous identifier:} A program, a function 251 | declaration, a procedure declaration, or a record type 252 | introduces two named entities with the same identifier. 253 | \item 254 | {\it Forall statement error:} In a restricted {\it forall} 255 | statement, the element statement uses a target variable. 256 | \item 257 | {\it Function block error:} A procedure statement occurs 258 | in the statement part of a function block. 259 | \item 260 | {\it Function parameter error:} A function uses an 261 | explicit or implicit variable parameter. 262 | \item 263 | {\it Identifier kind error:} A named entity of the wrong 264 | kind is used in some context. (Constants, types, fields, 265 | variables, functions and procedures are different kinds of 266 | named entities.) 267 | \item 268 | {\it Incomplete comment:} The closing delimiter \} of a 269 | comment is missing. 270 | \item 271 | {\it Index range error:} The index range of an array type 272 | has a lower bound that exceeds the upper bound. 273 | \item 274 | {\it Number error:} A constant denotes a number outside 275 | the range of integers or reals. 276 | \item 277 | {\it Parallel statement error:} In a restricted parallel 278 | statement, a target variable of one process statement is 279 | also a target or an expression variable of another process 280 | statement. 281 | \item 282 | {\it Procedure statement error:} In a restricted procedure 283 | statement, an entire variable is used more than once as a 284 | restricted actual parameter. 285 | \item 286 | {\it Recursion error:} A recursive function or procedure 287 | uses an implicit parameter. 288 | \item 289 | {\it Syntax error:} The program syntax is incorrect. 290 | \item 291 | {\it Type error:} The type of an operand is incompatible 292 | with its use. 293 | \item 294 | {\it Undefined identifier:} An identifier is used without 295 | being defined. 296 | \end{itemize} 297 | 298 | 299 | \section{Run-time Errors} 300 | 301 | During program execution, the following program errors are 302 | reported: 303 | 304 | \begin{itemize} 305 | \item 306 | {\it Channel contention:} Two processes both attemp to 307 | send or receive through the same channel. 308 | \item 309 | {\it Deadlock:} Every process is delayed by a send or 310 | receive operation, but none of these operations match. 311 | \item 312 | {\it False assumption:} An assume statement denotes a 313 | false assumption. 314 | \item 315 | {\it Message type error}: Two processes attempt to 316 | communicate through the same channel, but the output 317 | expression and the input variable are of different message 318 | types. 319 | \item 320 | {\it Range error:} The value of an index expression or a 321 | {\it chr, pred,} or {\it succ} function designator is out 322 | of range. 323 | \item 324 | {\it Undefined case constant:} A case expression does not 325 | denote a case constant. 326 | \item 327 | {\it Undefined channel reference:} A channel expression 328 | does not denote a channel. 329 | \end{itemize} 330 | 331 | 332 | \section{Software Limits} 333 | 334 | If a program is too large to be compiled or run, the software 335 | displays one of the following messages and stops. Each 336 | message indicates that the limit of a particular software 337 | array type has been exceeded: 338 | 339 | \begin{itemize} 340 | \item 341 | {\it Block limit exceeded:} The total number of blocks 342 | defined by the program and its function declarations, 343 | procedure declarations, {\it forall} statements, and 344 | process statements exceeds the limit {\it maxblock}. 345 | \item 346 | {\it Branch limit exceeded:} The total number of branches 347 | denoted by all statements in the program exceeds the limit 348 | {\it maxlabel}. 349 | \item 350 | {\it Buffer limit exceeded:} The size of the compiled code 351 | exceeds the limit {\it maxbuf}. 352 | \item 353 | {\it Case limit exceeded:} The number of case constants 354 | exceeds the limit {\it maxcase}. 355 | \item 356 | {\it Channel limit exceeded:} The number of channels 357 | opened exceeds the limit {\it maxchan}. 358 | \item 359 | {\it Character limit exceeded:} The total number of 360 | characters in all word symbols and identifiers exceeds the 361 | limit {\it maxchar}. 362 | \item 363 | {\it Memory limit exceeded:} The program execution exceeds 364 | the limit {\it maxaddr}. 365 | \item 366 | {\it Nesting limit exceeded:} The level of nesting of the 367 | program and its function declarations, procedure 368 | declarations, parallel statements, and {\it forall} 369 | statements exceeds the limit {\it maxlevel}. 370 | \item 371 | {\it String limit exceeded:} The number of characters in a 372 | word symbol, an identifier, or a character string exceeds 373 | the limit {\it maxstring}. 374 | \end{itemize} 375 | 376 | The standard {\it software limits} are: 377 | 378 | \begin{mytabular}{llrllr} 379 | maxaddr & = & 100000 & maxchar & = & 10000 \\ 380 | maxblock & = & 200 & maxlabel & = & 1000 \\ 381 | maxbuf & = & 10000 & maxlevel & = & 10 \\ 382 | maxcase & = & 128 & maxstring & = & 80 \\ 383 | maxchan & = & 10000 & & & \\ 384 | \end{mytabular} 385 | 386 | If these limits are too small for compilation or execution of 387 | a program, the limits must be increased by editing a common 388 | declaration file and recompiling both the compiler and the 389 | interpreter [Brinch Hansen 1993b]. 390 | 391 | \begin{mybibliography}{2} 392 | \entry 393 | Brinch Hansen, P. (1993a) The programming language 394 | SuperPascal. School of Computer and Information Science, 395 | Syracuse University, Syracuse, NY. 396 | \entry 397 | Brinch Hansen, P. (1993b) The SuperPascal software notes. 398 | School of Computer and Information Science, Syracuse 399 | University, Syracuse, NY. 400 | \end{mybibliography} 401 | 402 | \end{document} 403 | --------------------------------------------------------------------------------