1 "";;010B8CEF872E4CAE653DCBA950DA8437DE154147ADBAE6B1F9D5B2BB0806 2 ""{ Logiweb, a system for electronic distribution of mathematics 3 Copyright (C) 2004-2009 Klaus Grue 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed IN the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 021111307 USA 18 19 Contact: Klaus Grue, DIKU, Universitetsparken 1, DK2100 Copenhagen, 20 Denmark, grue@diku.dk, http://logiweb.eu/, http://www.diku.dk/~grue/ 21 22 Logiweb is a system for distribution of mathematical definitions, 23 lemmas, and proofs. For more on Logiweb, consult http://logiweb.eu/. 24 ""} 25 26 ""P lgc 27 28 ""R base 29 30 ""D 0 31 late define " as " end define 32 lgc-get-events ( " ) 33 lgc-set-events ( " , " ) 34 lgc-clr-events ( " ) 35 lgc-push-event ( " , " ) 36 lgc-do-events ( " ) 37 lgc-exec ( " ) 38 lgc-exec-events ( " , " ) 39 lgc-main 40 lgc-config-1 ( " ) 41 lgc-config-2 ( " , " ) 42 lgc-config-3 ( " , " ) 43 lgc-config-4 ( " ) 44 lgc-config-5 ( " , " ) 45 lgc-config-6 ( " , " ) 46 lgc-tilde-expand ( " , " ) 47 lgc-default-leap 48 lgc-default-options 49 lgc-process-argv ( " , " ) 50 lgc-argv-short-to-long 51 lgc-process-short-argv ( " , " , " , " ) 52 lgc-split-long-arg ( " ) 53 lgc-argv-downcase ( " ) 54 lgc-argv-downcase1 ( " ) 55 lgc-argv-downcase2 ( " ) 56 lgc-process-long-argv ( " , " ) 57 lgc-process-assignment ( " , " , " , " ) 58 lgc-process-env ( " , " ) 59 lgc-process-lines ( " , " ) 60 lgc-file2lines ( " ) 61 lgc-file2lines1 ( " , " , " ) 62 lgc-add-line-to-lines ( " , " ) 63 lgc-process-file ( " , " ) 64 lgc-process-parameters ( " ) 65 lgc-process-query ( " ) 66 lgc-help 67 lgc-help2 68 lgc-help3 69 lgc-version 70 lgc-license 71 lgc-options ( " ) 72 lgc-options1 ( " , " ) 73 lgc-options2 ( " , " ) 74 lgc-option ( " ) 75 lgc-seconds-per-minute 76 lgc-seconds-per-day 77 lgc-minutes-per-hour 78 lgc-hours-per-day 79 lgc-days-per-month 80 lgc-days-per-dimester 81 lgc-days-per-quimester 82 lgc-days-per-year 83 lgc-days-per-olympiad 84 lgc-days-per-century 85 lgc-days-per-Gregorian 86 lgc-months-per-dimester 87 lgc-months-per-quimester 88 lgc-months-per-year 89 lgc-month-of-march 90 lgc-years-per-olympiad 91 lgc-years-per-century 92 lgc-years-per-Gregorian 93 lgc-grd-of-mjd0 94 lgc-grd2day ( " ) 95 lgc-day-of-mjd0 96 lgc-grd2mjd ( " ) 97 lgc-limited-floor ( " , " , " ) 98 lgc-mjd-of-grd-0-03-01 99 lgc-mjd2grd ( " ) 100 lgc-parse-prefix ( " , " ) 101 lgc-prefix-grd 102 lgc-prefix-hyphen 103 lgc-parse-leap ( " ) 104 lgc-convert-leap ( " ) 105 lgc-check-leap ( " ) 106 lgc-initial-leap 107 lgc-add-leap ( " ) 108 lgc-add-leap1 ( " , " , " ) 109 lgc-process-leap ( " ) 110 lgc-ref2lgt ( " ) 111 lgc-lgt2vt ( " ) 112 lgc-lgt2mjdtai ( " ) 113 lgc-lgt2mjdtai2vt ( " ) 114 lgc-lgt2utc ( " , " , " ) 115 lgc-lgt2grdutc ( " , " ) 116 lgc-lgt2grdutc2vt ( " , " ) 117 lgc-lgt2grdutc2v ( " , " ) 118 lgc-unix2lgt ( " , " ) 119 lgc-lgt-of-unix 120 lgc-unix2lgt1 ( " , " , " , " , " ) 121 test-leaps 122 test-leapstate 123 test-leapstate2 124 test-leapstate3 125 lgc-lex-1 ( " ) 126 lgc-lex-2 ( " , " ) 127 lgc-lex-3 ( " , " ) 128 lgc-lex-4 ( " , " ) 129 lgc-lex-source ( " , " ) 130 lgc-lex-position ( " , " ) 131 lgc-lex-newline ( " , " ) 132 lgc-lex-comment1 ( " ) 133 lgc-lex-comment2 ( " , " , " ) 134 lgc-lex-comment3 ( " ) 135 lgc-lex-comment4 ( " , " , " , " ) 136 lgc-lex-escape1 ( " ) 137 lgc-lex-escape2 ( " , " ) 138 lgc-lex-escape3 ( " , " ) 139 lgc-lex-collect ( " ) 140 lgc-lex-collect1 ( " , " , " ) 141 lgc-lex-left-trim ( " ) 142 lgc-lex-right-trim ( " ) 143 lgc-lex-trim ( " ) 144 lgc-lex-reverse-contract ( " ) 145 lgc-lex-reverse-contract1 ( " , " ) 146 lgc-lex-contract ( " ) 147 lgc-lex-reverse-contract* ( " ) 148 lgc-lex-contract* ( " ) 149 lgc-lex-reverse-trim-contract ( " ) 150 lgc-lex-trim-contract ( " ) 151 lgc-lex-space ( " ) 152 lgc-lex-page ( " , " , " , " ) 153 lgc-lex-page1 ( " , " , " , " ) 154 lgc-lex-ref ( " , " , " , " ) 155 lgc-lex-ref1 ( " , " , " , " ) 156 lgc-lex-def ( " ) 157 lgc-lex-def0 ( " , " , " , " , " ) 158 lgc-lex-def1 ( " , " , " ) 159 lgc-lex-def2 ( " , " , " , " , " ) 160 lgc-lex-string ( " , " , " , " ) 161 lgc-lex-hex ( " , " , " , " , " ) 162 lgc-lex-hex1 ( " , " , " , " , " , " ) 163 lgc-lex-extract-body ( " ) 164 lgc-lex-extract-body1 ( " , " ) 165 lgc-lex-extract-other ( " , " ) 166 lgc-lex-extract-page ( " , " ) 167 lgc-lex-extract-ref ( " , " ) 168 lgc-lex-extract-def ( " , " ) 169 lgc-lex-extract-include ( " , " ) 170 lgc-include-1 ( " ) 171 lgc-include-2 ( " , " ) 172 lgc-load-1 ( " ) 173 lgc-load-fetch0 ( " , " ) 174 lgc-load-setpath ( " ) 175 lgc-progress-fetch ( " , " , " ) 176 lgc-heads ( " ) 177 lgc-load-fetch ( " ) 178 lgc-load-fetch-name ( " ) 179 lgc-load-fetch-ref ( " , " ) 180 lgc-load-fetch-ref1 ( " , " ) 181 lgc-file-prefix 182 lgc-http-prefix 183 lgc-//-prefix 184 lgc-lgw-prefix 185 lgc-name-prefix 186 lgw-suffix 187 lgr-suffix 188 lgu-suffix 189 lgc-load-fetch-path ( " , " ) 190 lgc-load-fetch-file ( " , " ) 191 lgc-tilde-expand1 ( " , " ) 192 lgc-cwd-expand ( " , " ) 193 lgc-load-fetch-http ( " , " ) 194 lgc-prefix ( " , " ) 195 lgc-char-split ( " , " ) 196 lgc-char-split1 ( " , " , " ) 197 lgc-replace-colon ( " , " ) 198 lgc-replace-colon1 ( " , " ) 199 lgc-file-suffix ( " ) 200 lgc-load-fetch-ref-failed ( " , " ) 201 lgc-load-no-colon ( " ) 202 lgc-wrong-suffix ( " , " ) 203 lgc-wrong-lgu-suffix ( " , " ) 204 lgc-load-malformed-url ( " , " ) 205 lgc-load-malformed-lgu ( " , " ) 206 lgc-load-malformed-page ( " ) 207 lgc-load-wrong-page ( " ) 208 lgc-load-receive ( " , " ) 209 lgc-load-received-nothing ( " ) 210 lgc-load-receive-lgw ( " , " ) 211 lgc-load-receive-lgw1 ( " , " ) 212 lgc-logiweb-version 213 lgc-wrong-ref ( " , " , " ) 214 lgc-load-receive-lgr ( " , " ) 215 lgc-load-receive-lgu ( " , " ) 216 lgc-trim-newline ( " ) 217 lgc-load-codify ( " ) 218 lgc-load-codify1 ( " , " ) 219 lgc-load-codify-lgw ( " , " ) 220 lgc-load-codify-lgr ( " , " ) 221 lgc-load-render ( " , " ) 222 lgc-load-render1 ( " , " ) 223 lgc-load-codify-closure ( " , " ) 224 lgc-parse-int ( " ) 225 lgc-parse-int1 ( " , " ) 226 lgc-atoi ( " , " ) 227 lgc-itoa ( " ) 228 lgc-itoa1 ( " , " ) 229 lgc-ctoa ( " , " ) 230 lgc-ordinal-suffix ( " ) 231 lgc-ordinal ( " ) 232 lgc-max-messages 233 lgc-add-message ( " , " , " , " ) 234 lgc-throw-message ( " , " , " ) 235 lgc-die ( " ) 236 lgc-report-messages ( " ) 237 lgc-report-messages1 ( " , " , " ) 238 lgc-report-messages2 ( " , " , " ) 239 lgc-position ( " , " , " , " ) 240 lgc-position-1 ( " , " , " , " , " ) 241 lgc-max-lines 242 lgc-max-chars 243 lgc-report-message3 ( " , " ) 244 lgc-split ( " , " , " ) 245 lgc-split1 ( " , " ) 246 lgc-char-start1 247 lgc-char-start2 248 lgc-char-start ( " ) 249 lgc-size-limit ( " , " , " , " ) 250 lgc-error ( " , " , " ) 251 lgc-simple-error ( " , " ) 252 lgc-progress ( " , " , " ) 253 lgc-print ( " , " ) 254 lgc-EOF 255 lgc-esc-. 256 lgc-esc-- 257 lgc-esc-! 258 lgc-esc-# 259 lgc-esc-$ 260 lgc-esc-left 261 lgc-esc-right 262 lgc-esc-brace 263 lgc-esc-B 264 lgc-esc-C 265 lgc-esc-D 266 lgc-esc-N 267 lgc-esc-P 268 lgc-esc-R 269 lgc-esc-S 270 lgc-esc-f 271 lgc-esc-n 272 lgc-esc-r 273 lgc-esc-t 274 lgc-esc-x 275 lgc-left-trim ( " ) 276 lgc-right-trim ( " ) 277 lgc-trim ( " ) 278 lgc-reverse-contract ( " ) 279 lgc-reverse-contract1 ( " , " ) 280 lgc-contract ( " ) 281 lgc-contract* ( " ) 282 lgc-trim-contract ( " ) 283 lgc-panic ( " ) 284 lgc-splice ( " , " ) 285 lgw-parse-string ( " ) 286 lgw-parse-string1 ( " , " , " ) 287 lgw-parse-bibliography ( " ) 288 lgw-parse-bibliography1 ( " , " ) 289 lgw-parse-dictionary ( " ) 290 lgw-parse-dictionary1 ( " , " ) 291 lgw-trisect ( " ) 292 lgw-codify ( " , " , " ) 293 lgw-codify1 ( " , " , " , " ) 294 lgw-codify-unpack ( " , " ) 295 lgw-codify-unpacker ( " , " ) 296 lgw-codify-unpack1 ( " , " ) 297 lgw-make-dict ( " , " ) 298 lgw-make-dict1 ( " , " , " , " , " ) 299 lgw-make-dict2 ( " , " , " , " , " ) 300 lgw-parse-tree ( " , " , " ) 301 lgw-parse-tree* ( " , " , " , " , " , " ) 302 lgw-parse-tree-string ( " , " ) 303 lgw-codify-initialize ( " , " ) 304 lgw-codify-expand ( " , " ) 305 lgw-codify-expand1 ( " , " ) 306 lgw-codify-harvest ( " , " , " , " ) 307 lgw-codify-harvest* ( " , " , " , " ) 308 lgw-proclaim-array 309 lgw-codify-proclaim ( " , " , " ) 310 lgw-tree2aspect ( " , " ) 311 lgw-codify-define ( " , " , " , " ) 312 lgc-node2ref ( " ) 313 lgc-node2idx ( " ) 314 lgc-node2charge ( " ) 315 lgc-node2open ( " ) 316 lgc-node2closed ( " ) 317 lgc-node2name ( " ) 318 lgc-node2binary ( " ) 319 lgc-node2relref ( " ) 320 lgc-grammar ( " ) 321 lgc-grammar1 ( " , " ) 322 lgc-grammar-init 323 lgc-grammar-init1 ( " , " ) 324 lgc-grammar-add-bib ( " , " , " , " ) 325 lgc-grammar-add-ref ( " , " , " , " ) 326 lgc-grammar-add-dictionary ( " , " , " , " , " ) 327 lgc-grammar-add-construct ( " , " , " , " , " ) 328 lgc-grammar-add-construct1 ( " , " , " , " , " , " ) 329 lgc-card2septet* ( " ) 330 lgc-aritysymbol2vt ( " , " , " , " ) 331 lgc-aritysymbol2vt1 ( " , " , " , " ) 332 lgc-grammar-valid-construct ( " , " ) 333 lgc-def2charge ( " ) 334 lgc-grammar-get-charge ( " , " , " ) 335 lgc-grammar-default-construct ( " , " , " ) 336 lgc-grammar-default-arglist ( " ) 337 lgc-grammar-default-arglist1 ( " ) 338 lgc-grammar-add-def ( " ) 339 lgc-grammar-def-construct ( " , " , " , " ) 340 lgc-arity ( " ) 341 lgc-grammar-add-defs* ( " , " , " ) 342 lgc-grammar-add-defs ( " , " , " ) 343 lgc-grammar-def-construct* ( " , " , " , " ) 344 lgc-parse-charge ( " , " ) 345 lgc-parse-charge1 ( " , " ) 346 lgc-parse-charge2 ( " ) 347 lgc-charge2vector* ( " ) 348 lgc-charge2vector*1 ( " ) 349 lgc-grammar-get-tuple ( " , " ) 350 lgc-charge ( " , " ) 351 lgc-charge1 ( " , " , " ) 352 lgc-charge2 ( " , " , " , " ) 353 lgc-charge-right ( " , " , " , " , " ) 354 lgc-charge-right1 ( " , " ) 355 lgc-charge-brace ( " , " , " , " , " ) 356 lgc-charge-brace0 ( " ) 357 lgc-charge-brace1 ( " , " , " , " ) 358 lgc-less-charge ( " , " ) 359 lgc-charge-left ( " ) 360 lgc-charge-left1 ( " , " , " ) 361 lgc-charge-string ( " , " ) 362 lgc-charge-string1 ( " , " , " ) 363 lgc-string2bytes ( " , " ) 364 lgc-charge-bytes ( " , " ) 365 lgc-charge-binary ( " , " , " ) 366 lgc-charge-text ( " , " , " ) 367 lgc-charge-text1 ( " , " , " ) 368 lgc-host-newline ( " ) 369 lgc-get-newline ( " , " ) 370 lgc-add-newline ( " , " ) 371 lgc-add-headline ( " , " , " ) 372 lgc-charge-source ( " , " ) 373 lgc-headline 374 lgc-parse-headline ( " ) 375 lgc-parse-headline1 ( " , " ) 376 lgc-charge-name ( " , " , " ) 377 lgc-charge-charge ( " , " , " ) 378 lgc-charge-auto ( " , " , " , " ) 379 lgc-charge-name-find ( " , " , " , " ) 380 lgc-charge-name2binary ( " , " ) 381 lgc-charge-best-node ( " ) 382 lgc-charge-auto1 ( " , " , " , " , " , " ) 383 lgc-vectorize ( " , " ) 384 lgc-add-dict ( " , " ) 385 lgc-add-bib ( " , " ) 386 lgc-ref2vector* ( " ) 387 lgc-ref-version 388 lgc-hex2card ( " ) 389 lgc-mixed2vector* ( " ) 390 lgc-add-ref ( " , " ) 391 lgc-add-ref1 ( " , " ) 392 lgc-parse1 ( " , " ) 393 lgc-parse2 ( " ) 394 lgc-parse3 ( " ) 395 lgc-parse4 ( " , " ) 396 lgc-parse5 ( " ) 397 lgc-parse6 ( " , " ) 398 lgc-parse ( " , " ) 399 lgc-parse-any ( " , " , " , " , " , " ) 400 lgc-parse-left ( " , " , " , " , " , " ) 401 lgc-parse-right ( " , " , " , " , " , " ) 402 lgc-parse-brace ( " , " , " , " , " , " ) 403 lgc-parse-token ( " , " , " , " , " ) 404 lgc-parse-best ( " , " , " ) 405 lgc-parse-no-interpretations ( " , " ) 406 lgc-parse-no-inter1 ( " ) 407 lgc-shortest ( " ) 408 lgc-shortest1 ( " ) 409 lgc-shortest2 ( " ) 410 lgc-parse-ambiguous ( " , " ) 411 lgc-parse-ambiguous1 ( " , " , " ) 412 lgc-parse-ambiguous2 ( " ) 413 lgc-parse-ambiguous3 ( " ) 414 lgc-parse-ambiguous4 ( " , " ) 415 lgc-parse-ambiguous-construct ( " , " ) 416 lgc-parse-cannot-trisect ( " ) 417 lgc-proclaim-error ( " , " ) 418 lgc-parse-codify-lgw ( " , " ) 419 lgc-rendering-no-colon ( " ) 420 lgc-tree2vector* ( " , " ) 421 lgc-string2vt ( " ) 422 lgc-string2vt1 ( " ) 423 lgc-symbol2vt ( " , " , " ) 424 lgc-symbol2vt1 ( " , " , " ) 425 lgc-tree2vt ( " , " ) 426 lgc-tree2vt0 ( " , " , " , " ) 427 lgc-open 428 lgc-close 429 lgc-tree*2vt ( " , " , " , " ) 430 lgc-tree2vt1 ( " , " ) 431 lgc-ref2vt ( " , " ) 432 tree2vt ( " , " ) 433 tree*2vt ( " , " ) 434 lgc-vector*2html ( " ) 435 lgc-html-open ( " ) 436 lgc-html-close ( " ) 437 lgc-tree2html ( " , " ) 438 lgc-html-begin ( " ) 439 lgc-html-end ( " ) 440 lgc-html-tag ( " ) 441 lgc-html-br 442 lgc-html-wrap ( " , " ) 443 lgc-html-title ( " ) 444 lgc-html-h2 ( " ) 445 lgc-html-h3 ( " ) 446 lgc-html-h4 ( " ) 447 lgc-html-p ( " ) 448 lgc-html-it ( " ) 449 lgc-html-tt ( " ) 450 lgc-html-ptt ( " ) 451 lgc-html-string ( " ) 452 lgc-html-arg ( " , " ) 453 lgc-html-favicon ( " ) 454 lgc-html-utf8 455 lgc-html-head ( " ) 456 lgc-html-icon 457 lgc-html-href ( " , " ) 458 lgc-html-name ( " , " ) 459 lgc-html-named-h3 ( " , " ) 460 lgc-html-address ( " ) 461 lgc-html-body ( " , " , " ) 462 lgc-html-page ( " , " , " ) 463 lgc-html-help 464 lgc-render ( " , " ) 465 lgc-render-verify ( " , " ) 466 lgc-render-add-slash ( " ) 467 lgc-render-dirname ( " , " ) 468 lgc-render-dir ( " , " ) 469 lgc-lgs-suffix 470 lgc-page-name ( " ) 471 lgc-page-name1 ( " , " ) 472 lgc-render-link ( " , " ) 473 lgc-render-link1 ( " , " , " , " ) 474 lgc-render-vector ( " , " ) 475 lgc-render-ref ( " , " ) 476 lgc-render-source ( " , " ) 477 lgc-render-source1 ( " ) 478 lgc-render-tdiagnose ( " , " , " ) 479 lgc-render-pdiagnose ( " , " ) 480 lgc-render-icons ( " , " ) 481 lgc-logiweb.png 482 lgc-logiweb.ico 483 lgc-logiweb.eps 484 lgc-render-index ( " , " , " ) 485 lgc-render-extract ( " , " , " , " ) 486 lgc-render-extract-toc 487 lgc-render-extract-date ( " , " ) 488 lgc-render-bib ( " , " ) 489 lgc-render-ref-link ( " , " ) 490 lgc-render-bib1 ( " , " , " , " ) 491 lgc-render-def ( " , " ) 492 lgc-render-def1 ( " , " , " , " ) 493 lgc-render-def2 ( " , " , " , " ) 494 lgc-render-def-sym* ( " , " , " , " ) 495 lgc-render-def-sym ( " , " , " , " ) 496 lgc-render-def-string ( " , " , " ) 497 lgc-render-def-sym1 ( " , " , " ) 498 lgc-render-def-sym2 ( " , " , " ) 499 lgc-render-def-sym3 ( " , " ) 500 lgc-render-charge ( " , " ) 501 lgc-collect-charge ( " , " , " ) 502 lgc-collect-charge1 ( " , " , " ) 503 lgc-collect-charge2 ( " , " , " , " ) 504 lgc-collect-charge3 ( " , " , " , " ) 505 lgc-collect-charge4 ( " , " , " ) 506 lgc-render-charge0 ( " , " , " , " ) 507 lgc-render-charge1 ( " , " , " , " , " ) 508 lgc-render-charge2 ( " , " , " , " ) 509 lgc-render-charge-bib ( " , " , " ) 510 lgc-render-charge-self ( " , " , " ) 511 lgc-render-hdiagnose ( " , " , " , " , " ) 512 lgc-render-correct 513 lgc-render-hdiagnose1 ( " ) 514 lgc-render-dump ( " , " ) 515 lgc-render-user ( " , " ) 516 lgc-render-user0 ( " ) 517 lgc-render-noevent 518 lgc-render-user1 ( " , " , " ) 519 lgc-render-user2 ( " , " ) 520 lgc-render-response ( " , " ) 521 lgc-goodbye ( " ) 522 lgc-render-file ( " , " , " , " ) 523 lgc-render-file-exec ( " , " , " , " ) 524 lgc-render-text ( " , " , " , " ) 525 lgc-render-text-exec ( " , " , " , " ) 526 lgc-render-add-lf ( " ) 527 lgc-render-lgwam ( " , " , " , " ) 528 lgc-render-invoke ( " , " , " , " ) 529 lgc-render-path ( " ) 530 lgc-render-path1 ( " ) 531 lgc-render-path-dot ( " ) 532 lgc-render-path-slash ( " ) 533 lgc-render-refuse ( " , " ) 534 lgc-render-events ( " , " , " ) 535 lgc-render-event0 ( " ) 536 lgc-render-event ( " , " , " ) 537 lgc-render-expand ( " , " ) 538 lgc-render-expand1 ( " , " , " ) 539 lgc-render-default ( " , " , " ) 540 lgc-render-body ( " , " , " ) 541 lgc-render-diagnose ( " , " , " ) 542 lgc-render-diagnose1 ( " , " , " , " ) 543 lgc-render-pdftitle ( " ) 544 lgc-render-pdftitle1 ( " ) 545 lgc-render-exec ( " , " , " ) 546 lgc-render-exec1 ( " , " , " , " ) 547 lgc-render-exec2 ( " , " , " , " , " ) 548 lgc-render-exec-arg ( " , " ) 549 lgc-gdef ( " , " ) 550 lgc-only-letters ( " ) 551 lgc-gdef-ref ( " , " ) 552 lgc-gdef-bib ( " , " ) 553 lgc-break ( " ) 554 lgc-break1 ( " ) 555 lgc-render-lgwinclude ( " , " , " ) 556 lgc-index ( " , " , " ) 557 lgc-const2val ( " , " ) 558 lgc-render-compile ( " , " , " ) 559 lgc-render-compile1 ( " , " , " ) 560 lgc-render-compile* ( " , " , " ) 561 lgc-render-eval ( " , " , " , " ) 562 lgc-render-eval* ( " , " , " , " ) 563 lgc-render-use 564 lgc-render-use1 ( " ) 565 lgc-render-compile-use ( " , " , " , " ) 566 lgc-render-compile-use1 ( " , " , " , " ) 567 lgc-understood ( " ) 568 lgc-render-show 569 lgc-render-show1 ( " ) 570 lgc-render-compile-show ( " , " , " , " ) 571 lgc-render-compile-show1 ( " , " , " ) 572 lgc-render-name ( " , " , " ) 573 lgc-render-name1 ( " , " ) 574 lgc-render-name2 ( " , " ) 575 lgc-render-string ( " ) 576 lgc-render-string0 ( " ) 577 lgc-render-string1 ( " , " , " ) 578 lgc-render-string2 ( " , " ) 579 lgc-render-array 580 selfref 581 baseref 582 lgw-trisect-self 583 lgw-trisect-base 584 lgw-codify-self 585 lgw-codify-base 586 lgc-test ( " ) 587 588 ""B 589 page ( ""N , ""C ) 590 title "Compiler" 591 bib " 592 @techreport{appendix, 593 author = {Klaus Grue}, 594 year = {2008}, 595 title = {Compiler - appendix}, 596 institution={Logiweb}, 597 note = 598 {\href{\lgwBlockRelay \lgwBlockThis /page/appendix.pdf}{% 599 \lgwBreakRelay \lgwBreakThis /page/appendix.pdf}}} 600 " 601 main text " 602 \title{Compiler} 603 \author{Klaus Grue} 604 \maketitle 605 \tableofcontents 606 607 608 609 \section{The lgc compiler}\nocite{appendix}"[ " 610 611 \subsection{Frontend language} 612 613 The Logiweb compiler (lgc) comprises a \emph{frontend}, a \emph{codifier}, and a \emph{renderer}. 614 615 The frontend takes a Logiweb \emph{source} file as input. Source files typically have extension .lgs; they are human readable and human editable files expressed in the Logiweb \emph{frontend language}. 616 617 The frontend produces a Logiweb \intro{vector} file as output. Vector files typically have extension .lgw; they are compact, binary files suited for transmission over the Internet. We shall refer to the contents of a vector file as a Logiweb \emph{vector}, regardless of whether the vector is retrieved from a file, retrieved over a network, or is passed in memory from the frontend. 618 619 The codifier takes a vector as input and produces a Logiweb \emph{rack} file as output. Rack files typically have extension .lgr; they are big, binary files suited for storing in the local file system. A file or memory structure which allows to look up racks given their references is termed a Logiweb \emph{cache}. We shall refer to the contents of a rack file as a Logiweb \emph{rack}, regardless of how it is retrieved. 620 621 The renderer takes a rack as input and produces a Logiweb \emph{rendering} as output. A rendering is a directory structure of interlinked html, pdf, and other files suited for viewing in a browser. 622 623 Any Logiweb compiler must contain a frontend, a codifier, and a renderer. Furthermore, the codifier of any Logiweb compiler must do exactly as the codifier defined in the following. The frontend and renderer, however, are replacable. 624 625 As an example, one may design a language different from the Logiweb frontend language and write a frontend for that language. One could even imagine a wysiwyg Logiweb frontend. The only requirement to a frontend is that it must produce a Logiweb vector as output. 626 627 Any backend should take a Logiweb rack as input and produce some sort of rendering as output. 628 629 630 631 \subsection{File extensions} 632 633 The Logiweb compiler uses the following file extensions: 634 635 \begin{description} 636 637 \item[.lgw] Logiweb vector (lgw for LoGiWeb). 638 639 \item[.lgs] Logiweb source text (s for source). 640 641 \item[.lgr] Logiweb rack (r for rack). 642 643 \item[.lgu] Indirection (u for URL). 644 645 \item[.lgp] Reserved for Logiweb reference (p for pointer). 646 647 \item[.lgo] Reserved for link to Logiweb rendering (o for output). 648 649 \end{description} 650 651 652 653 \subsection{Files} 654 655 \begin{description} 656 657 \item[/etc/logiweb/lgc.conf] Default location for site configuration file. 658 659 \item[\$HOME/.logiweb/lgc.conf] Default location for a user configuration file. 660 661 \item[\$HOME/.logiweb/logiweb/] Default location for output and racks. 662 663 \item[/usr/bin/lgwam] Default location of Logiweb abstract machine. 664 665 \item[/usr/bin/lgc] Default location of Logiweb compiler. 666 667 \item[/usr/man] Default location of Logiweb man pages. 668 669 \end{description} 670 671 672 673 \subsection{General functions} 674 675 \begin{statements} 676 677 \item "[[ macro define late define u as v end define as eager define u as v end define end define ]]" 678 679 \end{statements} 680 681 682 683 \subsection{Event handling functions} 684 685 \begin{statements} 686 687 \item "[[ late define lgc-get-events ( s ) as s [[ !"events" ]] end define ]]" 688 689 Return the list of events to be executed. The list is in reverse order. 690 691 \item "[[ late define lgc-set-events ( s , E ) as s [[ !"events" -> E ]] end define ]]" 692 693 Set the list of events to the list "[[ E ]]". 694 695 \item "[[ late define lgc-clr-events ( s ) as lgc-set-events ( s , true ) end define ]]" 696 697 Clear the list of events. 698 699 \item "[[ late define lgc-push-event ( s , e ) as push ( s , !"events" , e ) end define ]]" 700 701 Add an event "[[ e ]]" to list "[[ E ]]" of events. When executed, "[[ e ]]" will be executed after the events in "[[ E ]]". 702 703 \item "[[ late define lgc-do-events ( s ) as newline reverse ( lgc-get-events ( s ) ) end define ]]" 704 705 Push the event "[[ e ]]" onto the list of events, then reverse the list. 706 707 \item "[[ macro define lgc-exec ( f ) as exec request ( true , map ( \ s . \ x . f ) apply lgc-clr-events ( s ) maptag ) end define ]]" 708 709 Forge an execute event for invoking "[[ f ]]". 710 711 \item "[[ macro define lgc-exec-events ( s , f ) as newline 712 713 reverse ( lgc-exec ( f ) :: lgc-get-events ( s ) ) end define ]]" 714 715 Push an execute event onto the list of events, then reverse the list. 716 717 \end{statements} 718 719 720 721 \subsection{State machine} 722 723 At top level, lgc is a state machine with the following states: 724 725 \begin{verbatim} 726 lgc-config-1 ( x ) 727 lgc-config-2 ( x , s ) 728 lgc-config-3 ( x , s ) 729 lgc-config-5 ( x , s ) 730 lgc-config-6 ( x , s ) 731 lgc-lex-2 ( x , s ) 732 lgc-lex-3 ( x , s ) 733 lgc-include-2 ( x , s ) 734 lgc-load-receive ( x , s ) 735 lgc-load-codify1 ( x , s ) 736 lgc-grammar1 ( x , s ) 737 lgc-parse1 ( x , s ) 738 lgc-parse-codify-lgw ( x , s ) 739 lgc-parse6 ( x , s ) 740 lgc-render ( x , s ) 741 lgc-render-verify ( x , s ) 742 lgc-render-dump ( x , s ) 743 lgc-render-user ( x , s ) 744 lgc-render-user2 ( x , s ) 745 \end{verbatim} 746 747 748 749 \subsection{Machine} 750 751 The following statements define the main program of the Logiweb compiler. 752 753 \begin{statements} 754 755 \item "[[ define "execute" of "lgc" as newline 756 757 << lgc-main ,, !"siteconfig=/etc/logiweb/lgc.conf" >> end define ]]" 758 759 Dump the lgc compiler "[[ lgc-main ]]" under the name of lgc and with the given compiled in default. 760 761 \item "[[ late define lgc-main as map ( \ x . lgc-config-1 ( x ) ) end define ]]" 762 763 As the first activity, read configuration files. 764 765 \end{statements} 766 767 768 769 \subsection{State entries} 770 771 During parameter processing, the compiler builds up a state "[[ s ]]" with the following entries: 772 773 \begin{itemize} 774 775 \item "[[ s [[ !"init" ]] ]]" The initial event containing command line arguments, environment variables, and compiled in defaults. 776 777 \item "[[ s [[ !"nsiteconfig" ]] ]]" Tilde expanded name of site configuration file. 778 779 \item "[[ s [[ !"siteconfig" ]] ]]" Contents of site configuration file (if any). 780 781 \item "[[ s [[ !"nuserconfig" ]] ]]" Tilde expanded name of user configuration file. 782 783 \item "[[ s [[ !"userconfig" ]] ]]" Contents of user configuration file (if any). 784 785 \item "[[ s [[ !"parameters" ]] ]]" Array of all parameters. 786 787 \item "[[ s [[ !"verbose" ]] ]]" Verbosity level as a cardinal. 788 789 \end{itemize} 790 791 The array "[[ t ]]" of parameters has the following entries: 792 793 \begin{itemize} 794 795 \item "[[ t [[ !"source" ]] ]]" The name of the source file. 796 797 \item "[[ t [[ !"leap" ]] ]]" List of leap second definitions like "[[ !"GRD-1972-06-30+1" ]]" which indicates that Gregorian Date 1972-06-30 ended with one, positive leap second. 798 799 \item "[[ t [[ !"siteconfig" ]] ]]" The location of the site configuration file. Not tilde-expanded. 800 801 \item "[[ t [[ !"userconfig" ]] ]]" The location of the user configuration file. Not tilde-expanded. 802 803 \item "[[ t [[ !"path" ]] ]]" List of locations to look up pages given their reference. As an example, an item of value "[[ !"~/.logiweb/logiweb/:/rack.lgr" ]]" makes the compiler look in the given location under the users home catalog where the rightmost colon is replaced by the reference of the page in mixed endian hexadecimal. 804 805 \item "[[ t [[ !"namepath" ]] ]]" List of locations to look up pages given their name. The rightmost colon is replaced by the name of the referenced page when translating "[[ !""-""!""!R" ]]" directives. 806 807 \item "[[ t [[ !"rendering" ]] ]]" Location of rendering output and racks. The rightmost colon is replaced by the reference of the page. 808 809 \item "[[ t [[ !"link" ]] ]]" List of locations for storing links to the rendering output. The rightmost colon is replaced by the name of the source file of the page (with the suffix removed, if any). 810 811 \item "[[ t [[ !"newline" ]] ]]" Host newline (CR, LF, CRLF, or LFCR). 812 813 \item "[[ t [[ !"script" ]] ]]" Script headline. 814 815 \item "[[ t [[ !"verbose" ]] ]]" Verbosity, c.f.\ Section \ref{sec:VerbosityLevels}. 816 817 \item "[[ t [[ !"options" ]] ]]" When unequal to "[[ !"no" ]]": print the values of all options to standard output and exit. 818 819 \item "[[ t [[ !"help" ]] ]]" When unequal to "[[ !"no" ]]": print help message one to standard output and exit. 820 821 \item "[[ t [[ !"help2" ]] ]]" When unequal to "[[ !"no" ]]": print help message two to standard output and exit. 822 823 \item "[[ t [[ !"help3" ]] ]]" When unequal to "[[ !"no" ]]": print help message three to standard output and exit. 824 825 \item "[[ t [[ !"version" ]] ]]" When unequal to "[[ !"no" ]]": print version to standard output and exit. 826 827 \item "[[ t [[ !"license" ]] ]]" When unequal to "[[ !"no" ]]": print license information to standard output and exit. 828 829 \end{itemize} 830 831 832 833 \subsection{Reading of configuration files} 834 835 Parameters are collected from the following sources: 836 837 \begin{itemize} 838 839 \item Static defaults which are defined in the code. 840 841 \item Dynamic defaults like siteconfig=/etc/logiweb/lgc.conf which are in the code but are easy to modify after compilation. 842 843 \item Parameters defined in a site configuration file. 844 845 \item Parameters defined in a user configuration file. 846 847 \item Environment variables. 848 849 \item Command line parameters. 850 851 \end{itemize} 852 853 The sources are shown in order of precedence in the sense that command line parameters override environment variables and so on. 854 855 All parameters can be defined in any of the locations. As an exception, however, the location of the site configuration file cannot be defined in the site or user configuration file and the location of the user configuration file cannot be defined in the user configuration file. 856 857 Each parameter is equal to a list of values. Environment variables merely allow to define one-element lists. All other sources allow to set a parameter to a one-element list or to add an element at the beginning or end of the current list. 858 859 Configuration files may contain lines like the following: 860 861 \begin{verbatim} 862 # This is a comment 863 uuu=xxx 864 vvv+yyy 865 www++zzz 866 \end{verbatim} 867 868 The lines above set parameter uuu to xxx, adds yyy in front of vvv, and adds zzz at the end of www. 869 870 Command lines may contain arguments like the following: 871 872 \begin{verbatim} 873 --uuu=xxx --vvv+yyy --www++zzz 874 \end{verbatim} 875 876 The command line arguments above have the same effect as the configuration file above. 877 878 Command line parameters typically have short forms. If u, v, and w are the short forms of uuu, vvv, and www, then one may write: 879 880 \begin{verbatim} 881 -u xxx +v yyy ++w zzz 882 \end{verbatim} 883 884 The two given command lines have the same effect. 885 886 Configuration files and command line parametes are processed in the reading direction. As an example, \verb/--vvv+aaa --vvv+bbb/ adds first aaa and then bbb in front of vvv so that bbb ends up occurring in front of aaa. 887 888 Dynamic defaults, environment variables, and command line arguments are embedded in the parameter "[[ x ]]" of "[[ lgc-config-1 ( x ) ]]" below. The functions in the following read in the site and user configuration files. 889 890 \begin{statements} 891 892 \item "[[ late define lgc-config-1 ( x ) as newline 893 894 let s = true [[ !"init" -> x ]] in newline 895 896 let t = lgc-process-parameters ( s ) in newline 897 898 let n = lgc-tilde-expand ( t [[ !"siteconfig" ]] head , t ) in newline 899 900 let s = s [[ !"nsiteconfig" -> n ]] in << tight newline 901 902 extend request ( lgcio ( true ) , lgcio-interface ) ,, tight newline 903 904 unixTime ,, tight newline 905 906 fileGetCwd ,, tight newline 907 908 fileType ( n ) ,, tight newline 909 910 lgc-exec ( lgc-config-2 ( x , s ) ) >> end define ]]" 911 912 Ask if the site configuration file exists. 913 914 \item "[[ late define lgc-config-2 ( x , s ) as newline 915 916 let << true ,, << true ,, f >> ,, << true ,, d >> ,, u >> = x in newline 917 918 let s = s [[ !"time" -> parse-unixTime ( u ) ]] in newline 919 920 let s = s [[ !"cwd" -> d ]] in newline 921 922 if f head != 258 then lgc-config-4 ( s ) else << tight newline 923 924 fileRead ( s [[ !"nsiteconfig" ]] ) ,, tight newline 925 926 lgc-exec ( lgc-config-3 ( x , s ) ) >> end define ]]" 927 928 If the site configuration file exists, read it. Otherwise, pretend that the site configuration file is empty and go on to the user configuration file. 929 930 \item "[[ late define lgc-config-3 ( x , s ) as newline 931 932 let << true ,, << true ,, f >> >> = x in newline 933 934 let s = s [[ !"siteconfig" -> f ]] in lgc-config-4 ( s ) end define ]]" 935 936 Store the site configuration file and go on to the user configuration file. 937 938 \item "[[ late define lgc-config-4 ( s ) as newline 939 940 let t = lgc-process-parameters ( s ) in newline 941 942 let n = lgc-tilde-expand ( t [[ !"userconfig" ]] head , t ) in newline 943 944 let s = s [[ !"nuserconfig" -> n ]] in << tight newline 945 946 fileType ( n ) ,, tight newline 947 948 lgc-exec ( lgc-config-5 ( x , s ) ) >> end define ]]" 949 950 Ask if the user configuration file exists. 951 952 \item "[[ late define lgc-config-5 ( x , s ) as newline 953 954 let << true ,, << true ,, f >> >> = x in newline 955 956 if f head != 258 then lgc-process-query ( s ) else << tight newline 957 958 fileRead ( s [[ !"nuserconfig" ]] ) ,, tight newline 959 960 lgc-exec ( lgc-config-6 ( x , s ) ) >> end define ]]" 961 962 If the user configuration file exists, read it. Otherwise, pretend that the user configuration file is empty and go on to query processing. 963 964 \item "[[ late define lgc-config-6 ( x , s ) as newline 965 966 let << true ,, << true ,, f >> >> = x in newline 967 968 let s = s [[ !"userconfig" -> f ]] in lgc-process-query ( s ) end define ]]" 969 970 Store the site configuration file and go on to query processing. 971 972 \item "[[ late define lgc-tilde-expand ( n , t ) as newline 973 974 if n then true else newline 975 976 if vector-head ( n ) != "~" - NULL then n else newline 977 978 t [[ "home" ]] :: vector-tail ( n ) end define ]]" 979 980 \end{statements} 981 982 983 984 \subsection{Parameter processing} 985 986 This section defines "[[ lgc-process-parameters ( s ) ]]" which converts a state "[[ s ]]" into an array which maps parameter names to parameter value lists. The state "[[ s ]]" must contain an initial event and may contain a site and a user configuration file. 987 988 \begin{statements} 989 990 \item "[[ late define lgc-default-leap as << tight newline 991 992 !"GRD-2008-12-31+1" ,, tight newline 993 994 !"GRD-2005-12-31+1" ,, tight newline 995 996 !"GRD-1998-12-31+1" ,, tight newline 997 998 !"GRD-1997-06-30+1" ,, tight newline 999 1000 !"GRD-1995-12-31+1" ,, tight newline 1001 1002 !"GRD-1994-06-30+1" ,, tight newline 1003 1004 !"GRD-1993-06-30+1" ,, tight newline 1005 1006 !"GRD-1992-06-30+1" ,, tight newline 1007 1008 !"GRD-1990-12-31+1" ,, tight newline 1009 1010 !"GRD-1989-12-31+1" ,, tight newline 1011 1012 !"GRD-1987-12-31+1" ,, tight newline 1013 1014 !"GRD-1985-06-30+1" ,, tight newline 1015 1016 !"GRD-1983-06-30+1" ,, tight newline 1017 1018 !"GRD-1982-06-30+1" ,, tight newline 1019 1020 !"GRD-1981-06-30+1" ,, tight newline 1021 1022 !"GRD-1979-12-31+1" ,, tight newline 1023 1024 !"GRD-1978-12-31+1" ,, tight newline 1025 1026 !"GRD-1977-12-31+1" ,, tight newline 1027 1028 !"GRD-1976-12-31+1" ,, tight newline 1029 1030 !"GRD-1975-12-31+1" ,, tight newline 1031 1032 !"GRD-1974-12-31+1" ,, tight newline 1033 1034 !"GRD-1973-12-31+1" ,, tight newline 1035 1036 !"GRD-1972-12-31+1" ,, tight newline 1037 1038 !"GRD-1972-06-30+1" >> end define ]]" 1039 1040 Define the static default for the leap parameter. 1041 1042 \item "[[ late define lgc-default-options as true [[ newline 1043 1044 !"leap" -> lgc-default-leap ]] [[ newline 1045 1046 !"siteconfig" -> << !"/etc/logiweb/lgc.conf" >> ]] [[ newline 1047 1048 !"userconfig" -> << !"~/.logiweb/lgc.conf" >> ]] [[ newline 1049 1050 !"path" -> << !"~/.logiweb/logiweb/:/rack.lgr" >> ]] [[ newline 1051 1052 !"rendering" -> << !"~/.logiweb/logiweb/:/" >> ]] [[ newline 1053 1054 !"link" -> << !":" ,, !"~/.logiweb/name/:" >> ]] [[ newline 1055 1056 !"namepath" -> << !"~/.logiweb/name/:/rack.lgr" >> ]] [[ newline 1057 1058 !"newline" -> << !"LF" >> ]] [[ newline 1059 1060 !"script" -> << !"#!/usr/bin/lgwam script" >> ]] [[ newline 1061 1062 !"verbose" -> << !"3" >> ]] [[ newline 1063 1064 !"options" -> << !"no" >> ]] [[ newline 1065 1066 !"help" -> << !"no" >> ]] [[ newline 1067 1068 !"help2" -> << !"no" >> ]] [[ newline 1069 1070 !"help3" -> << !"no" >> ]] [[ newline 1071 1072 !"version" -> << !"no" >> ]] [[ newline 1073 1074 !"license" -> << !"no" >> ]] end define ]]" 1075 1076 Define static defaults for all parameters. 1077 1078 \item "[[ late define lgc-process-argv ( v , t ) as newline 1079 1080 if v atom then t else newline 1081 1082 let a :: v = v in newline 1083 1084 if vector-prefix ( a , 2 ) = !"--" then newline 1085 1086 let l = lgc-process-long-argv ( vector-suffix ( a , 2 ) , t ) in newline 1087 1088 lgc-process-argv ( v , l ) else newline 1089 1090 if vector-prefix ( a , 1 ) = !"-" then newline 1091 1092 lgc-process-short-argv ( vector-suffix ( a , 1 ) , !"-" , v , t ) else newline 1093 1094 if vector-prefix ( a , 2 ) = !"++" then newline 1095 1096 lgc-process-short-argv ( vector-suffix ( a , 2 ) , !"++" , v , t ) else newline 1097 1098 if vector-prefix ( a , 1 ) = !"+" then newline 1099 1100 lgc-process-short-argv ( vector-suffix ( a , 1 ) , !"+" , v , t ) else newline 1101 1102 lgc-process-argv ( v , t [[ !"source" -> << a >> ]] ) end define ]]" 1103 1104 Process the command line arguments given in "[[ v ]]" and add them to the array "[[ t ]]". It is assumed that "[[ v ]]" is the list of genuine arguments, i.e.\ that argv[0] has been removed. 1105 1106 \item "[[ late define lgc-argv-short-to-long as true [[ newline 1107 1108 !"s" -> !"siteconfig" ]] [[ newline 1109 1110 !"u" -> !"userconfig" ]] [[ newline 1111 1112 !"p" -> !"path" ]] [[ newline 1113 1114 !"n" -> !"namepath" ]] [[ newline 1115 1116 !"r" -> !"rendering" ]] [[ newline 1117 1118 !"l" -> !"link" ]] [[ newline 1119 1120 !"o" -> !"option" ]] [[ newline 1121 1122 !"h" -> !"help" ]] [[ newline 1123 1124 !"H" -> !"help2" ]] [[ newline 1125 1126 !"v" -> !"verbose" ]] end define ]]" 1127 1128 Define the mapping from short to long parameter names. Internally in the compiler, parameters are always stored under their long name. 1129 1130 \item "[[ late define lgc-process-short-argv ( k , a , v , t ) as newline 1131 1132 let k prime = lgc-argv-short-to-long [[ k ]] in newline 1133 1134 let k = if k prime != true then k prime else k in newline 1135 1136 lgc-process-argv ( v tail , lgc-process-assignment ( k , a , v head , t ) ) end define ]]" 1137 1138 Process the short option with keyword "[[ k ]]" and assignment operator "[[ a ]]". The assignment operator may be \verb/-/ or \verb/+/ or \verb/++/. 1139 1140 \item "[[ late define lgc-split-long-arg ( a ) as newline 1141 1142 if a = !"". then 0 else newline 1143 1144 if vector-prefix ( a , 1 ) = !"=" then 0 else newline 1145 1146 if vector-prefix ( a , 1 ) = !"+" then 0 else newline 1147 1148 1 + lgc-split-long-arg ( vector-suffix ( a , 1 ) ) end define ]]" 1149 1150 Return the index of the end of the keyword. This is not very efficient, but who cares about efficiency in command line handling? 1151 1152 \item "[[ late define lgc-argv-downcase ( a ) as newline 1153 1154 bt2vector ( lgc-argv-downcase1 ( vector2byte* ( a ) ) ) end define ]]" 1155 1156 Change A..Z to a..z in the vector "[[ a ]]". 1157 1158 \item "[[ late define lgc-argv-downcase1 ( a ) as newline 1159 1160 if a atom then true else 1161 1162 let c :: a = a in newline 1163 1164 lgc-argv-downcase2 ( c ) :: lgc-argv-downcase1 ( a ) end define ]]" 1165 1166 Change A..Z to a..z in the list "[[ a ]]" of bytes. 1167 1168 \item "[[ late define lgc-argv-downcase2 ( c ) as newline 1169 1170 if c < !"A" - NULL then c else newline 1171 1172 if c > !"Z" - NULL then c else newline 1173 1174 c - !"A" + !"a" end define ]]" 1175 1176 Change A..Z to a..z. 1177 1178 \item "[[ late define lgc-process-long-argv ( a , t ) as newline 1179 1180 let p = lgc-split-long-arg ( a ) in newline 1181 1182 let k = lgc-argv-downcase ( vector-prefix ( a , p ) ) in newline 1183 1184 let a = vector-suffix ( a , p ) in newline 1185 1186 if a = !"". then t [[ k -> true ]] else newline 1187 1188 if vector-prefix ( a , 1 ) = !"=" then newline 1189 1190 lgc-process-assignment ( k , !"-" , vector-suffix ( a , 1 ) , t ) else newline 1191 1192 if vector-prefix ( a , 2 ) = !"++" then newline 1193 1194 lgc-process-assignment ( k , !"++" , vector-suffix ( a , 2 ) , t ) else newline 1195 1196 lgc-process-assignment ( k , !"+" , vector-suffix ( a , 1 ) , t ) end define ]]" 1197 1198 Split the long option a into a keyword, an assignment operator, and a value and execute the associated assignement. 1199 1200 Process the long option "[[ a ]]". 1201 1202 \item "[[ late define lgc-process-assignment ( k , a , v , t ) as newline 1203 1204 if a = !"-" then t [[ k -> << v >> ]] else newline 1205 1206 if a = !"+" then t [[ k -> v :: t [[ k ]] ]] else newline 1207 1208 t [[ k -> append ( t [[ k ]] , << v >> ) ]] end define ]]" 1209 1210 Assign the value "[[ v ]]" to the keyword "[[ k ]]" in the array "[[ t ]]" using the assignment operator "[[ a ]]". 1211 1212 \item "[[ late define lgc-process-env ( v , t ) as newline 1213 1214 if v atom then t else newline 1215 1216 let a :: v = v in newline 1217 1218 if lgc-argv-downcase ( vector-prefix ( a , 4 ) ) = !"lgc_" then newline 1219 1220 let l = lgc-process-long-argv ( vector-suffix ( a , 4 ) , t ) in newline 1221 1222 lgc-process-env ( v , l ) else newline 1223 1224 if lgc-argv-downcase ( vector-prefix ( a , 5 ) ) = !"home=" then newline 1225 1226 lgc-process-env ( v , lgc-process-long-argv ( a , t ) ) else newline 1227 1228 lgc-process-env ( v , t ) end define ]]" 1229 1230 Process the environment arguments given in "[[ v ]]" and add them to the array "[[ t ]]". 1231 1232 \item "[[ late define lgc-process-lines ( l , t ) as newline 1233 1234 if l atom then t else 1235 1236 let a :: l = l in newline 1237 1238 let t = lgc-process-long-argv ( a , t ) in newline 1239 1240 lgc-process-lines ( l , t ) end define ]]" 1241 1242 Process the configuration file lines given in "[[ v ]]" and add them to the array "[[ t ]]". It is assumed that "[[ v ]]" is the list of genuine lines, i.e.\ that empty lines and comment lines have been removed. 1243 1244 \item "[[ late define lgc-file2lines ( f ) as lgc-file2lines1 ( f , true , true ) end define ]]" 1245 1246 Convert the list "[[ f ]]" of singleton strings into a list of lines, removing empty lines and comment lines. 1247 1248 \item "[[ late define lgc-file2lines1 ( f , l , b ) as newline 1249 1250 if f atom then reverse ( lgc-add-line-to-lines ( b , l ) ) else newline 1251 1252 let c :: f = f in newline 1253 1254 if c = LF .or. c = CR then newline 1255 1256 lgc-file2lines1 ( f , lgc-add-line-to-lines ( b , l ) , true ) else newline 1257 1258 lgc-file2lines1 ( f , l , c :: b ) end define ]]" 1259 1260 Convert the list "[[ f ]]" of singleton strings into a list of lines. Lines are accumulated in "[[ l ]]" in reverse order. Characters of each line are buffered in "[[ b ]]" in reverse order. 1261 1262 \item "[[ late define lgc-add-line-to-lines ( b , l ) as newline 1263 1264 let b = reverse ( b ) in newline 1265 1266 if b atom then l else newline 1267 1268 if b head = !"#" then l else newline 1269 1270 vt2vector ( b ) :: l end define ]]" 1271 1272 Add the line "[[ b ]]" to the list "[[ l ]]" of lines unless "[[ b ]]" is empty or starts with a hash-mark. 1273 1274 \item "[[ late define lgc-process-file ( f , t ) as newline 1275 1276 let l = lgc-file2lines ( f ) in newline 1277 1278 lgc-process-lines ( l , t ) end define ]]" 1279 1280 Process the configuration file "[[ f ]]" and add parameter values to the array "[[ t ]]". 1281 1282 \item "[[ late define lgc-process-parameters ( s ) as newline 1283 1284 let << << true ,, true :: a ,, e ,, c ,, d >> >> = s [[ !"init" ]] in newline 1285 1286 let t = lgc-default-options in newline 1287 1288 let t = lgc-process-lines ( d , t ) in newline 1289 1290 let u = t [[ !"siteconfig" ]] in newline 1291 1292 let t = lgc-process-file ( s [[ !"siteconfig" ]] , t ) in newline 1293 1294 let v = t [[ !"userconfig" ]] in newline 1295 1296 let t = lgc-process-file ( s [[ !"userconfig" ]] , t ) in newline 1297 1298 let t = t [[ !"siteconfig" -> u ]] [[ !"userconfig" -> v ]] in newline 1299 1300 let t = lgc-process-env ( e , t ) in newline 1301 1302 let t = lgc-process-argv ( a , t ) in newline 1303 1304 t end define ]]" 1305 1306 Process parameters from all sources in "[[ s ]]". 1307 1308 \end{statements} 1309 1310 1311 1312 \subsection{Query processing} 1313 1314 Some invokations of the lgc compiler queries information rather than asking for compilation. The query options are \verb/help/, \verb/help2/, \verb/help3/, \verb/version/, \verb/license/, \verb/options/, and \verb/option/. The three first give preset responses, the fourth lists all options, and the last lists the value of a particular option. 1315 1316 \begin{statements} 1317 1318 \item "[[ late define lgc-help as newline 1319 1320 !" 1321 Logiweb compiler (lgc) 1322 Usage: lgc [option]... [source] 1323 --siteconfig or -s Location of site configuration file 1324 --userconfig or -u Location of user configuration file 1325 --path or -p Path for searching pages by reference 1326 --namepath or -n Path for searching pages by name 1327 --rendering or -r Location of rendering output 1328 --link or -l Location of links to rendering output 1329 --verbose or -v Set verbosity 1330 --option or -o Print given option and exit 1331 --help or -h Print present message and exit 1332 --help2 or -H Print help on further options 1333 1334 Examples: 1335 --path=x or -p x Set path to singleton x 1336 --path+x or +p x Add x in front of path 1337 --path++x or ++p x Add x at end of path 1338 --path Set path to the empty list 1339 1340 " end define ]]" 1341 1342 \item "[[ late define lgc-help2 as newline 1343 1344 !" 1345 Logiweb compiler (lgc) 1346 Usage: lgc [option]... [source] 1347 --help or -h Print help on frequently used options 1348 --help2 or -H Print present message 1349 --help3 Print help on config file options 1350 --version Print version 1351 --license Print license 1352 --options Print all options 1353 --source E.g. 'lgc --source=X' is like 'lgc X' 1354 1355 " end define ]]" 1356 1357 \item "[[ late define lgc-help3 as newline 1358 1359 !" 1360 Logiweb compiler (lgc) 1361 Usage: lgc [option]... [source] 1362 --help or -h Print help on frequently used options 1363 --help2 or -H Print help on further options 1364 --help3 Print present message and exit 1365 1366 The following options typically occur (without hyphens) in 1367 configuration files or at the end of scripts. 1368 1369 --leap Location of leap seconds 1370 --newline Host newline (CR, LF, CRLF, or LFCR) 1371 --script Script headline (e.g. #!/usr/bin/lgwam script) 1372 1373 " end define ]]" 1374 1375 \item "[[ late define lgc-version as newline 1376 1377 !"Logiweb compiler (lgc) version " :: !""$version" end define ]]" 1378 1379 \item "[[ late define lgc-license as newline 1380 !"Logiweb, a system for electronic distribution of mathematics 1381 Copyright (C) 2004-2009 Klaus Grue 1382 1383 This program is free software; you can redistribute it and/or modify 1384 it under the terms of the GNU General Public License as published by 1385 the Free Software Foundation; either version 2 of the License, or 1386 (at your option) any later version. 1387 1388 This program is distributed IN the hope that it will be useful, 1389 but WITHOUT ANY WARRANTY; without even the implied warranty of 1390 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1391 GNU General Public License for more details. 1392 1393 You should have received a copy of the GNU General Public License 1394 along with this program; if not, write to the Free Software 1395 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 021111307 USA 1396 1397 Contact: Klaus Grue, DIKU, Universitetsparken 1, DK2100 Copenhagen, 1398 Denmark, grue@diku.dk, http://logiweb.eu/, http://www.diku.dk/~grue/ 1399 1400 Logiweb is a system for distribution of mathematical definitions, 1401 lemmas, and proofs. For more on Logiweb, consult http://logiweb.eu/. 1402 " end define ]]" 1403 1404 \item "[[ late define lgc-options ( t ) as newline 1405 1406 << write request ( reverse ( lgc-options1 ( t , true ) ) ) >> end define ]]" 1407 1408 Print all options in the array "[[ t ]]" (in peculiar order). 1409 1410 \item "[[ late define lgc-options1 ( t , r ) as newline 1411 1412 if t atom then r else newline 1413 1414 if t head intp then lgc-options2 ( t tail , LF :: t head :: r ) else newline 1415 1416 lgc-options1 ( t head , lgc-options1 ( t tail , r ) ) end define ]]" 1417 1418 Add options in "[[ t ]]" to the list "[[ r ]]". 1419 1420 \item "[[ late define lgc-options2 ( t , r ) as newline 1421 1422 if t atom then r else newline 1423 1424 lgc-options2 ( t tail , LF :: t head :: !" " :: r ) end define ]]" 1425 1426 Add list "[[ t ]]" of values to "[[ r ]]". 1427 1428 \item "[[ late define lgc-option ( s ) as newline 1429 1430 if s atom then true else newline 1431 1432 writeln request ( s head ) :: lgc-option ( s tail ) end define ]]" 1433 1434 \item "[[ late define lgc-process-query ( s ) as newline 1435 1436 let t = lgc-process-parameters ( s ) in newline 1437 1438 let s = s [[ !"parameters" -> t ]] in newline 1439 1440 if t [[ !"help" ]] head != !"no" then << write request ( lgc-help ) >> else newline 1441 1442 if t [[ !"help2" ]] head != !"no" then << write request ( lgc-help2 ) >> else newline 1443 1444 if t [[ !"help3" ]] head != !"no" then << write request ( lgc-help3 ) >> else newline 1445 1446 if t [[ !"version" ]] head != !"no" then << write request ( lgc-version ) >> else newline 1447 1448 if t [[ !"license" ]] head != !"no" then << write request ( lgc-license ) >> else newline 1449 1450 if t [[ !"options" ]] head != !"no" then lgc-options ( t ) else newline 1451 1452 let o = t [[ !"option" ]] head in newline 1453 1454 if o != true .and. o != !"". then lgc-option ( t [[ o ]] ) else newline 1455 1456 let v = t [[ !"verbose" ]] head in newline 1457 1458 let e :: v = lgc-atoi ( vector2vector* ( v ) , true ) catch in newline 1459 1460 if e then << writeln request ( !"Invalid verbosity" ) >> else newline 1461 1462 let s = s [[ !"verbose" -> v ]] in newline 1463 1464 let e :: s = lgc-process-leap ( s ) catch in newline 1465 1466 if e then << writeln request ( s ) >> else newline 1467 1468 let s = s [[ !"time" -> lgc-unix2lgt ( s [[ !"time" ]] , s ) ]] in newline 1469 1470 lgc-lex-1 ( s ) end define ]]" 1471 1472 \end{statements} 1473 1474 1475 1476 " ]"\section{Time functions}"[ " 1477 1478 \subsection{Time schemes} 1479 1480 Logiweb uses the following time schemes 1481 1482 \begin{verbatim} 1483 TAI International atomic time 1484 UTC Universal coordinated time 1485 MJD Modified Julian day 1486 GRD Gregorian date 1487 LGT Logiweb time 1488 \end{verbatim} 1489 1490 1491 1492 \subsection{TAI} 1493 1494 TAI (International atomic time) is a 'paper' clock in the sense that it is a computed average of lots of real, atomic clocks located all over the world. 1495 1496 TAI counts seconds, minutes, and hours as regularly as possible. Each TAI day has 24 TAI hours, each TAI hour has 60 TAI minutes, and each TAI minute has 60 TAI seconds. Each TAI second is, as closely as possible, one SI second. An SI second is the duration of 9 192 631 770 periods of the radiation corresponding to the transition between the two hyperfine levels of the ground state of the caesium 133 atom. 1497 1498 TAI time is independent of the rotation of planet Earth. 1499 1500 In Logiweb, TAI hour hh, minute mm, and second ss is written TAI:hh:mm:ss. We have "[[ 00 <= h,h <= 23 ]]", "[[ 00 <= m,m < 59 ]]", and "[[ 00 <= s,s <= 59 ]]". Occasionally, we shall use TAI:24:00:00 to denote TAI:00:00:00 on the following day. Decimal fractions of a second are written after a dot as in TAI:12:23:34.456 which denotes 0.456 seconds past TAI:12:23:34. The notation is compatible with ISO 8601 except that we prepend ``TAI:'' to emphasize the use of International Atomic Time. 1501 1502 1503 1504 \subsection{UTC} 1505 1506 UTC is a combination of TAI and yet another time scale named UT1. 1507 1508 UT1 is a measure of the rotation angle of planet Earth relative to the direction from the Earth to the Sun. Each UT1 day has 24 UT1 hours, each UT1 hour has 60 UT1 minutes, and each UT1 minute has 60 UT1 seconds. It is noon in UT1 when Greenwich is under the Sun. At the time of writing (February 2009), UT1 is around 34 seconds behind TAI. In 1972, UT1 was 10 seconds behind TAI. 1509 1510 As mentioned, UTC is a combination of TAI and UT1. UTC equals TAI plus a politically decided offset. This UTC offset indicates how much UTC lacks behind TAI. At the time of writing, the UTC offset is 34 seconds indicating that UTC is 34 seconds behind TAI. 1511 1512 At any time, the UTC offset is an integral number of seconds, but the UTC offset may be incremented or decremented by decree from the International Earth Rotation Service (IERS). Hence, UTC depends on TAI and IERS, but IERS has the intension to keep the difference between UTC and UT1 below 0.9 seconds, so UTC indirectly depends on UT1. 1513 1514 UTC makes a leap whenever IERS increments or decrements the UTC offset. Such leaps are implemented by irregular UTC minutes. 1515 1516 A regular UTC minute has 60 UTC seconds. An irregular one either has 59 or 61. Apart from that UTC counts like TAI and UT1: days have 24 hours and hours have 60 minutes. 1517 1518 Whenever IERS increments (decrements) the UTC offset, the last minute of the last hour of a particular UTC day has 61 (59) seconds. IERS intends to place irregular seconds at the end of June 30 and December 31 when necessary and intends to announce the leaps in advance. 1519 1520 In Logiweb, UTC hour hh, minute mm, and second ss is written UTC:\-hh:\-mm:\-ss. We have "[[ 00 <= h,h <= 23 ]]", "[[ 00 <= m,m < 59 ]]", and "[[ 00 <= s,s <= 60 ]]". Occasionally, we shall use UTC:24:00:00 to denote UTC:00:00:00 on the following day. Decimal fractions of a second are written after a dot as in UTC:12:23:34.456 which denotes 0.456 seconds past UTC:12:23:34. The notation is compatible with ISO 8601 except that we prepend ``UTC:'' to emphasize the use of Universal Coordinated Time. 1521 1522 At the time of writing, IERS has never decremented the UTC offset, but has incremented the UTC offset at the end of the following days: 1523 1524 \begin{verbatim} 1525 GRD-1972-06-30 1526 GRD-1972-12-31 1527 GRD-1973-12-31 1528 GRD-1974-12-31 1529 GRD-1975-12-31 1530 GRD-1976-12-31 1531 GRD-1977-12-31 1532 GRD-1978-12-31 1533 GRD-1979-12-31 1534 GRD-1981-06-30 1535 GRD-1982-06-30 1536 GRD-1983-06-30 1537 GRD-1985-06-30 1538 GRD-1987-12-31 1539 GRD-1989-12-31 1540 GRD-1990-12-31 1541 GRD-1992-06-30 1542 GRD-1993-06-30 1543 GRD-1994-06-30 1544 GRD-1995-12-31 1545 GRD-1997-06-30 1546 GRD-1998-12-31 1547 GRD-2005-12-31 1548 GRD-2008-12-31 1549 \end{verbatim} 1550 1551 Before GRD-1972-06-03, the UTC offset was 10 seconds. 1552 1553 1554 1555 \subsection{MJD} 1556 1557 MJD (Modified Julian Day) is a scheme for counting days in a completely regular fasion. Each day is simply expressed by the number of days since a particular day. 1558 1559 MJD is a regular and reliable day count used by astronomers. Furthermore, it is politically correct in the sense that, even though Julius Caeser was quite controversial in his own time, few people today are offended by a time scale named after him. 1560 1561 MJD is based on yet another time scale named JD (Julian Day). JD expresses the number of days since noon, January 1, year -4712 (year 4713 BC), in the Julian calender. 1562 1563 In ancient times, a day was measured from noon to noon, so people actually counted nights instead of days (as a reminiscence, a period of 14 days is still called a fortnight in the English tongue). Today, we prefer to step our day counters when the sun is on the other side of the planet, which is of course difficult to observe, but which possesses little problem for modern technology. 1564 1565 To get a day count based on JD which steps at midnight, the Modified Julian Day (MJD) is offset from JD by 2400000.5 days. In consequence, MJD counts the number of days since GRD-1858-11-17. 1566 1567 When we combine MJD with UTC, then MJD steps at UTC:00:00:00. When we combine MJD with TAI, then MJD steps at TAI:00:00:00. Hence, MJD/UTC and MJD/TAI are two different day counts, but at the time of writing they merely differ by 34 seconds. 1568 1569 In Logiweb, MJD day d is written MJD-d. As an example, GRD-1858-11-17 equals MJD-0 and MJD-51544 equals GRD-2000-01-01. The day before MJD-0 is named MJD--1 (i.e. Modified Julian Day hyphen minus one). The notation follows ISO 8601 in using a hyphen in connection with day counting, but is otherwise completely unrelated. 1570 1571 Combinations of day and second counting schemes are glued together with a dot. As an example, 0.456 seconds past TAI:12:23:34 on MJD-51544 is written MJD-51544.TAI:12:23:34.456. This follows ISO-8601 in putting the day before the second but does not follow the suggestion of ISO-8601 to separate day and second by a capital ``T''. 1572 1573 1574 1575 \subsection{GRD} 1576 1577 GRD (Gregorian Date) is a scheme for counting days in a fasion so complicated that it has taken millennia to screw it up. Furthermore, GRD is ``politically incorrect'' in that it counts days, not after ``Jesus'', but after ``The Lord'' (Anno Domini), which is not completely neutral. 1578 1579 But GRD is widespread, and hence we use it in the Human-Computer-Interfaces of Logiweb. In Logiweb itself, GRD has no place. 1580 1581 In GRD, day 0 of a year is named ``January 1'', and day 100 is named April 11 (except if the year is divisible by 4, in which case it is named April 10 (except if the year is divisible by 100, in which case it is named April 11 (except if the year is divisible by 400, in which case it is named April 10))). 1582 1583 In Logiweb, Gregorian year Y, month MM, and day DD is written GRD-Y-MM-DD. We have "[[ 01 <= M,M <= 12 ]]" and "[[ 01 <= D,D <= 31 ]]". The notation is compatible with ISO 8601 except for the following: (1) We prepend ``GRD-'' to emphasize that we label days like the Gregorian calender does (GRD for GRegorian Date). (2) We allow the year to have more than four digits after year 9999 and to have less then four digits before year 1000. (3) We allow the year to be zero and negative. As examples, GRD-0-01-01 and GRD--5-01-01 are January 1 on year 1 BC and 6 BC, respectively. 1584 1585 When we combine GRD with UTC, then GRD steps at UTC:00:00:00. When we combine GRD with TAI, then GRD steps at TAI:00:00:00. Hence, GRD/UTC and GRD/TAI are two different day counts, but at the time of writing they merely differ by 34 seconds. 1586 1587 Combinations of day and second counting schemes are glued together with a dot. As an example, 0.456 seconds past UTC:12:23:34 on GRD-2000-01-01 is written GRD-2000-01-01.UTC:12:23:34.456. This follows ISO-8601 in putting the day before the second but does not follow the suggestion of ISO-8601 to separate day and second by a capital ``T''. 1588 1589 1590 1591 \subsection{LGT} 1592 1593 LGT (Logiweb time) is the number of TAI seconds since MJD-0.TAI:00:00:00. 1594 1595 Logiweb time is expressed on the form $ M \cdot 10 ^ {-E} $ where M is an integer and E is a cardinal (i.e. a non-negative integer). In Logiweb, M is always non-negative, so one could as well say that M is a cardinal. 1596 1597 Logiweb time $ M \cdot 10 ^ {-E} $ is written LGW-Me-E. As an example, 1598 1599 \begin{quote} 1600 LGW-1083564821686603e-6 1601 \end{quote} 1602 1603 \noindent equals 1604 1605 \begin{quote} 1606 GRD.2004-05-03.UTC:06:13:41.686603. 1607 \end{quote} 1608 1609 \noindent The e-E may be replaced by the following decadic suffixes: 1610 1611 \addvspace{\abovedisplayskip} 1612 1613 \begin{tabular}{|r|c|l|} 1614 \hline 1615 Exponent & Suffix & Name \\ 1616 \hline 1617 e-0 & U & unit \\ 1618 e-3 & m & milli \\ 1619 e-6 & u & micro \\ 1620 e-6 & $\mu$ & micro \\ 1621 e-9 & n & nano \\ 1622 e-12 & p & pico \\ 1623 e-15 & f & femto \\ 1624 e-18 & a & atto \\ 1625 e-21 & z & zepto \\ 1626 e-24 & y & yocto \\ 1627 \hline 1628 \end{tabular} 1629 1630 \addvspace{\belowdisplayskip} 1631 1632 In a Logiweb time like LGW-1083564821686603e-6 one should not replace the small e by a capital one as that may cause confusion with the decadic suffix E (Exa) which stands for $10^{15}$. 1633 1634 By the way note the following: Logiweb is a computational system intended for mathematics. In physics, one uses decadic prefixes that glue in front of physical units. In computing systems it is better to use decadic suffixes that glue behind numbers. When needed, Logiweb uses the SI units meter, kilogram, second, etc., and derived units. As an example, font sizes are measured in meters. A font size of twelve typographic points is 4218u, and a printer with a resolution of 600 dots per 0.0254 meters has a distance between pixels of 42.333u. An area of 1m by 1m (one milli meter by one milli meter) is $1m^2$ (one square milli) or 1u (one micro) or 1e-6 measured in the derived SI unit of square meters. A weight of 1m is one gram (one milli kilogram). A weight of 1um is one microgram (one micro milli kilogram). This is almost but not completely different from the use of decadic prefixes in the SI system. 1635 1636 1637 1638 \subsection{GUTC} 1639 1640 When presenting Logiweb time to a user, we use GRD/UTC which we shall refer to as GUTC. This section describes GUTC in more detail than the individual sections on GRD and UTC. 1641 1642 GUTC is irregular compared to Logiweb time in that it occasionally includes leap seconds and, furthermore, it counts days in a rather complicated (Gregorian) manner, which includes leap days. 1643 1644 GUTC is built up from the following cycles: 1645 1646 \textbf{GUTC second.} The length of a GUTC second is one SI second (which equals one TAI and one UTC second). Each GUTC second starts at the 'tick' of the TAI 'paper' clock. As an example, the duration from UTC:00:00:00 to UTC:00:00:01 on GRD-2000-03-01 (March 1, year 2000) is a GUTC second. 1647 1648 \textbf{GUTC minute.} Regular GUTC minutes consist of 60 GUTC seconds. Irregular GUTC minutes consist of 61 or 59 GUTC seconds. As an example, the duration from UTC:00:00:00 to UTC:00.01.00 on GRD-2000-03-01 is a regular GUTC minute. 1649 1650 \textbf{GUTC hour.} Regular GUTC hours consist of 60 regular GUTC minutes. Irregular GUTC hours consist of 59 regular GUTC minutes followed by one irregular GUTC minute. As an example, the duration from UTC:00:00:00 to UTC:01.00.00 on GRD-2000-03-01 is a regular GUTC hour. 1651 1652 \textbf{GUTC day.} Regular GUTC days consist of 24 regular GUTC hours. Irregular GUTC days consist of 23 regular GUTC hours followed by one irregular GUTC hour. As an example, the duration from GRD-2000-03-01.UTC:00:00:00 to GRD-2000-03-02.UTC:00.00.00 is a regular GUTC day. 1653 1654 \textbf{Long GUTC month.} A long GUTC month consists of 31 GUTC days. As an example, the duration from GRD-2000-03-01.UTC:00:00:00 to GRD-2000-04-01.UTC:00.00.00 (i.e. March) is a long GUTC month. 1655 1656 \textbf{Short GUTC month.} A short GUTC month consists of 30 GUTC days. As an example, the duration from GRD-2000-04-01.UTC:00:00:00 to GRD-2000-05-01.UTC:00.00.00 (i.e. April) is a short GUTC month. 1657 1658 \textbf{GUTC dimester.} A GUTC dimester (dimester = two months, compare trimester = tres menses = three months and semester = sex menses = six months) consists of a long GUTC month followed by a short one. As an example, the duration from March to April (inclusive) is a GUTC dimester. 1659 1660 \textbf{GUTC quimester.} A GUTC quimester (quimester = five months) consists of a long, a short, a long, a short, and a long GUTC month. In other words, a quimester consists of two regular dimesters followed by an irregular one that ends abruptly at the end of the quimester. As an example, the duration from March to July (inclusive) is a GUTC quimester. The duration from August to December is another quimester. 1661 1662 \textbf{GUTC Roman year.} A GUTC Roman year is the duration from March 1, inclusive, to the following March 1, exclusive. A regular Roman year has 365 GUTC days; an irregular one has one more. As an example, the period from GRD-2000-03-01.UTC:00:00:00 to GRD-2001-02-28.UTC:24:00:00 is GUTC Roman year 2000, which is regular. In contrast, the Gregorian year 2000 is a leap year and, hence, irregular. The difference arises because the Gregorian and Roman years have newyear before and after the leap day, respectively. 1663 1664 A GUTC Roman year consists of three quimesters, the third of which ends abruptly at the end of the year. As a consequence of the conventions mentioned until now, the last month of a regular GUTC Roman year (February) gets 28 GUTC days, and all the other months gets 30 and 31 GUTC days in the pattern prescribed by the Gregorian calender. 1665 1666 \textbf{GUTC olympiad.} A regular GUTC olympiad consists of three regular GUTC years followed by an irregular one. An irregular GUTC olympiad consists of four regular GUTC years. As an example, the period from March 1, 2000 to February 29, 2004 is a regular GUTC olympiad. 1667 1668 \textbf{GUTC century.} A regular GUTC century consists of 24 regular GUTC olympiads followed by an irregular one. An irregular GUTC olympiad consists of 25 regular GUTC olympiads. As an example, March 1, 2000 to February 28, 2100 is a regular GUTC century. 1669 1670 \textbf{GUTC Gregorian cycle.} A GUTC Gregorian cycle consists of three regular GUTC centuries followed by an irregular one. 1671 1672 The rules above allow to convert from LGT to GUTC and back provided one knows the location of leap seconds. A historical 'Roman year' just had 10 months, starting around vernal equinox. 10 month after vernal equinox, the romans stopped counting days and just waited for the next vernal equinox. The dimester/quimester structure described above is accidental. For the sake of Roman political correctness, the month of August (named after Augustus) was extended to 31 days to make it as long as July (named af Julius). 1673 1674 1675 1676 \subsection{Unix time} 1677 1678 Unix time counts seconds since GRD-1970-01-01.UTC:00:00:00. Each Unix day has 24 Unix hours, each Unix hour has 60 Unix minutes, and each Unix minute has 60 Unix seconds. Most Unix seconds are approximately equal to one SI second. 1679 1680 Each Unix computer maintains its own Unix time and each Unix computer tries to keep its Unix time in sync with UTC. When Unix time on a computer lacks behind UTC then the Unix system on that computer makes the Unix clock on that computer run faster until Unix time on that computer catches up with UTC. Likewise, the Unix system slows down the Unix clock when needed. 1681 1682 Whenever UTC makes a leap, Unix time makes a stumble. As an example, Unix time may stumble as follows: Whenever UTC makes a positive leap, Unix time counts at half speed for two seconds. In that way Unix time keeps in sync with UTC in the long run. 1683 1684 As can be seen, a Unix second is not always an SI second. Exactly how Unix time stumbles depends on the version of Unix used. 1685 1686 One can get a poor mans TAI from Unix time by stumbling backwards. That is what the Logiweb compiler does. When converting Unix time to poor mans TAI we assume that each Unix second corresponds to one TAI second except when a leap second occurs. Whenever UTC makes a positive leap, we assume that Unix time counts at half speed from UTC:23:59:59 to UTC:23:59:61 (UTC:23:59:61 equals UTC:00:00:00 on the next day). Whenever UTC makes a negative leap, we assume that Unix time counts at double speed from UTC:23:59:58 to UTC:23:59:59 (UTC:23:59:59 equals UTC:00:00:00 on the next day). 1687 1688 1689 1690 \subsection{The purpose of time stamps} 1691 1692 One purpose of using time stamps in Logiweb is as follows: A Logiweb reference includes a RIPEMD code. If the reference contained nothing else, there would be a theoretical limit of $ 2 ^ {160} $ Logiweb pages. Since Logiweb is supposed, among other, to support mathematical logic, it is convenient to have no upper limit on the number of pages, not even a theoretical one. Otherwise, one could fear pathological metatheorems stating that certain theorems fail because their proof would require more then $ 2 ^ {160} $ Logiweb pages to prove. As a countermeasure, Logiweb references include a timestamp. To ensure that there is not even an upper limit on the number of pages that can be published per second, the timestamp comprises an exponent and a mantissa, allowing time stamps to have arbitrary resolution. 1693 1694 Another reason for including a time stamp in Logiweb references is thus: RIPEMD ensures that the probability of generating two Logiweb pages with the same reference is negligible. However, adding a timestamp makes it possible to recover even in the theoretical situation where two pages get the same RIPEMD code anyway: One may simply resubmit both pages so that they get new time stamps. 1695 1696 A third reason for including a time stamp is thus: Logiweb pages are allowed to reference each other, but the pages and references are required to form a directed, acyclic graph. That can be enforced by a rule stating that a page is only allowed to reference pages which are older according to their time stamp. That is not used in the present version of Logiweb because RIPEMD is trusted to ensure acyclicity: If one tries to produce two Logiweb pages which reference each other, then the RIPEMD codes of each page will depend on the RIPEMD code of the other, making it infeasible to construct those codes. 1697 1698 Accidentally, the time stamps turned out to be quite convenient when rendering pages using \LaTeX: Some {\TeX} and {\LaTeX} styles need the date and time of submission to generate a front page, and that date and time may conveniently be taken from the time stamp of the page. 1699 1700 1701 1702 \subsection{Parameter names} 1703 1704 In the time conversion functions we use variable names thus: 1705 1706 \begin{tabular}{ll} 1707 1708 "[[ S ]]" & state \\ 1709 1710 "[[ g ]]" & Gregorian cycle (400 year period) \\ 1711 1712 "[[ c ]]" & Century (100 year period) \\ 1713 1714 "[[ o ]]" & Olympiad (4 year period) \\ 1715 1716 "[[ Y ]]" & Year \\ 1717 1718 "[[ q ]]" & Quimester (5 month period) \\ 1719 1720 "[[ d ]]" & Dimester (2 month period) \\ 1721 1722 "[[ M ]]" & Month \\ 1723 1724 "[[ D ]]" & Day \\ 1725 1726 "[[ h ]]" & Hour \\ 1727 1728 "[[ m ]]" & minute \\ 1729 1730 "[[ s ]]" & second \\ 1731 1732 "[[ f ]]" & fraction \\ 1733 1734 "[[ e ]]" & exponent \\ 1735 1736 "[[ G ]]" & Gregorian date "[[ << Y ,, M ,, D >> ]]" \\ 1737 1738 \end{tabular} 1739 1740 1741 1742 \subsection{Constants} 1743 1744 \begin{statements} 1745 1746 \item "[[ late define lgc-seconds-per-minute as 60 end define ]]" 1747 1748 \item "[[ late define lgc-seconds-per-day as 24 * 60 * 60 end define ]]" 1749 1750 \item "[[ late define lgc-minutes-per-hour as 60 end define ]]" 1751 1752 \item "[[ late define lgc-hours-per-day as 24 end define ]]" 1753 1754 \item "[[ late define lgc-days-per-month as 31 end define ]]" 1755 1756 \item "[[ late define lgc-days-per-dimester as 31 + 30 end define ]]" 1757 1758 \item "[[ late define lgc-days-per-quimester as 31 + 30 + 31 + 30 + 31 end define ]]" 1759 1760 \item "[[ late define lgc-days-per-year as 365 end define ]]" 1761 1762 \item "[[ late define lgc-days-per-olympiad as 4 * lgc-days-per-year + 1 end define ]]" 1763 1764 \item "[[ late define lgc-days-per-century as 25 * lgc-days-per-olympiad - 1 end define ]]" 1765 1766 \item "[[ late define lgc-days-per-Gregorian as 4 * lgc-days-per-century + 1 end define ]]" 1767 1768 \item "[[ late define lgc-months-per-dimester as 2 end define ]]" 1769 1770 \item "[[ late define lgc-months-per-quimester as 5 end define ]]" 1771 1772 \item "[[ late define lgc-months-per-year as 12 end define ]]" 1773 1774 \item "[[ late define lgc-month-of-march as 3 end define ]]" 1775 1776 March is month number three in the Gregorian calender. 1777 1778 \item "[[ late define lgc-years-per-olympiad as 4 end define ]]" 1779 1780 \item "[[ late define lgc-years-per-century as 100 end define ]]" 1781 1782 \item "[[ late define lgc-years-per-Gregorian as 400 end define ]]" 1783 1784 This is the length of the Gregorian cycle. 1785 1786 \item "[[ late define lgc-grd-of-mjd0 as << 1858 ,, 11 ,, 17 >> end define ]]" 1787 1788 \end{statements} 1789 1790 1791 1792 \subsection{Conversion from GRD to MJD} 1793 1794 \begin{statements} 1795 1796 \item "[[ late define lgc-grd2day ( G ) as newline 1797 1798 let << Y ,, M ,, D >> = G in newline 1799 1800 let M = lgc-months-per-year * Y + M - lgc-month-of-march in newline 1801 1802 let Y :: M = floor ( M , lgc-months-per-year ) in newline 1803 1804 let g = Y div lgc-years-per-Gregorian in newline 1805 1806 let c = Y div lgc-years-per-century in newline 1807 1808 let o = Y div lgc-years-per-olympiad in newline 1809 1810 let q :: M prime = floor ( M , lgc-months-per-quimester ) in newline 1811 1812 let d = M prime div lgc-months-per-dimester in newline 1813 1814 D - 1 + M * lgc-days-per-month + Y * lgc-days-per-year - d - q * 2 + o - c + g end define ]]" 1815 1816 Compute the number of days since GRD-0-03-01 as follows: 1817 1818 Destruct the Gregorian date "[[ G ]]" into year "[[ Y ]]", month "[[ M ]]", and day "[[ D ]]". Then compute the month count "[[ M ]]" since March, Gregorian year zero (recall that year zero is the one before year one, i.e.\ year one BC). 1819 1820 Then compute the Roman year "[[ Y ]]" and month "[[ M ]]". We count from zero so that March is month zero. The Romans counted March as month one. So October is month eight according to the Romans (Octo=8) but we count it as month seven. 1821 1822 After that, compute the day count "[[ D ]]" since GRD-0-03-01 as a linear combination of day, month, and year, and adjust for variations in the length of months and years. 1823 1824 \item "[[ late define lgc-day-of-mjd0 as lgc-grd2day ( lgc-grd-of-mjd0 ) end define ]]" 1825 1826 \item "[[ late define lgc-grd2mjd ( G ) as lgc-grd2day ( G ) - lgc-day-of-mjd0 end define ]]" 1827 1828 \end{statements} 1829 1830 1831 1832 \subsection{Conversion from MJD to GRD} 1833 1834 \begin{statements} 1835 1836 \item "[[ late define lgc-limited-floor ( x , y , l ) as newline 1837 1838 let R = floor ( x , y ) in newline 1839 1840 if R head < l then R else l :: x - l * y end define ]]" 1841 1842 Compute "[[ q :: r ]]" such that "[[ x = q * y + r ]]". The quotient "[[ q ]]" is the one computed by "[[ x div y ]]" except that it cannot exceed "[[ l ]]". 1843 1844 \item "[[ late define lgc-mjd-of-grd-0-03-01 as lgc-grd2mjd ( << 0 ,, 3 ,, 1 >> ) end define ]]" 1845 1846 \item "[[ late define lgc-mjd2grd ( D ) as newline 1847 1848 let D = D - lgc-mjd-of-grd-0-03-01 in newline 1849 1850 let g :: D = floor ( D , lgc-days-per-Gregorian ) in newline 1851 1852 let c :: D = lgc-limited-floor ( D , lgc-days-per-century , 3 ) in newline 1853 1854 let o :: D = floor ( D , lgc-days-per-olympiad ) in newline 1855 1856 let Y :: D = lgc-limited-floor ( D , lgc-days-per-year , 3 ) in newline 1857 1858 let q :: D = floor ( D , lgc-days-per-quimester ) in newline 1859 1860 let d :: D = floor ( D , lgc-days-per-dimester ) in newline 1861 1862 let M :: D = floor ( D , lgc-days-per-month ) in newline 1863 1864 let M = M + d * lgc-months-per-dimester in newline 1865 1866 let M = M + q * lgc-months-per-quimester in newline 1867 1868 let Y = Y + o * lgc-years-per-olympiad in newline 1869 1870 let Y = Y + c * lgc-years-per-century in newline 1871 1872 let Y = Y + g * lgc-years-per-Gregorian in newline 1873 1874 let M = M + Y * lgc-months-per-year in newline 1875 1876 let Y :: M = floor ( M + lgc-month-of-march - 1 , lgc-months-per-year ) in newline 1877 1878 << Y ,, M + 1 ,, D + 1 >> end define ]]" 1879 1880 Convert the Modified Julian Day "[[ D ]]" to a Gregorian date "[[ << Y ,, M ,, D >> ]]" as follows: 1881 1882 First compute the number of days "[[ D ]]" since GRD-0-03-01 (March 1, Gregorian year zero). Then convert "[[ D ]]" into a number of Gregorian cycles "[[ g ]]", centuries "[[ c ]]", olympiads "[[ o ]]", years "[[ Y ]]", quimesters "[[ q ]]", dimesters "[[ d ]]", months "[[ M ]]", and days "[[ D ]]". Then combine "[[ g ]]", "[[ c ]]", "[[ o ]]", and "[[ Y ]]" into the number of years "[[ Y ]]" since GRD-0-03-01, and convert "[[ q ]]", "[[ d ]]", and "[[ M ]]" into the number of months that have elapsed on top of those years. Then combine "[[ M ]]" and "[[ Y ]]" into the number of months "[[ M ]]" since GRD-0-03-01. Then move newyear to GRD-0-01-01 and convert back to year "[[ Y ]]" and month "[[ M ]]". Finally construct the Gregorian date, taking into acount that month and day count from one. 1883 1884 \end{statements} 1885 1886 1887 1888 \subsection{GRD Parsing functions} 1889 1890 \begin{statements} 1891 1892 \item "[[ late define lgc-parse-prefix ( p , a ) as newline 1893 1894 if p atom then a else newline 1895 1896 if p head != a head then exception else newline 1897 1898 lgc-parse-prefix ( p tail , a tail ) end define ]]" 1899 1900 \item "[[ late define lgc-prefix-grd as vt2vector* ( !"GRD-" ) end define ]]" 1901 1902 \item "[[ late define lgc-prefix-hyphen as vt2vector* ( !"-" ) end define ]]" 1903 1904 \item "[[ late define lgc-parse-leap ( a ) as newline 1905 1906 let a = lgc-parse-prefix ( lgc-prefix-grd , a ) in newline 1907 1908 let Y :: a = lgc-parse-int ( a ) in newline 1909 1910 let a = lgc-parse-prefix ( lgc-prefix-hyphen , a ) in newline 1911 1912 let M :: a = lgc-parse-int ( a ) in newline 1913 1914 let a = lgc-parse-prefix ( lgc-prefix-hyphen , a ) in newline 1915 1916 let D :: a = lgc-parse-int ( a ) in newline 1917 1918 let D = lgc-grd2mjd ( << Y ,, M ,, D >> ) in newline 1919 1920 let c :: a = a in newline 1921 1922 let l :: a = lgc-parse-int ( a ) in newline 1923 1924 if a pairp then exception else newline 1925 1926 if c = !"+" then D :: l else newline 1927 1928 if c = !"-" then D :: - l else exception end define ]]" 1929 1930 \item "[[ late define lgc-convert-leap ( L ) as newline 1931 1932 if L atom then true else newline 1933 1934 let a :: L = L in newline 1935 1936 let e :: v = lgc-parse-leap ( vt2vector* ( a ) ) catch in newline 1937 1938 if e then ( !"Invalid leap: " :: a ) raise else newline 1939 1940 v :: lgc-convert-leap ( L ) end define ]]" 1941 1942 Convert the list L of leap seconds on external form to a list of leap seconds on form "[[ << D :: U prime ,, ... >> ]]" where "[[ D ]]" is the day in MJD and "[[ U prime ]]" is the change in UTC lack (the amount UTC lacks behind TAI). The change "[[ U prime ]]" in UTC lack is +1 for a positive leap, -1 for a negative one. 1943 1944 \item "[[ late define lgc-check-leap ( L ) as newline 1945 1946 if L tail atom then true else newline 1947 1948 if L head head <= L tail head head then newline 1949 1950 !"Leap seconds must be stated in descending order" raise else newline 1951 1952 lgc-check-leap ( L tail ) end define ]]" 1953 1954 Check that the dates of leap seconds are stated in descending order. 1955 1956 \item "[[ late define lgc-initial-leap as 10 end define ]]" 1957 1958 The UTC lack before the first announced leap second. 1959 1960 \item "[[ late define lgc-add-leap ( L ) as newline 1961 1962 lgc-add-leap1 ( reverse ( L ) , lgc-initial-leap , true ) end define ]]" 1963 1964 Convert the list "[[ L ]]" on form "[[ << D :: U prime ,, ... >> ]]" into a list of form "[[ U :: << s :: U prime ,, ... >> ]]". The value of "[[ U prime ]]" is unchanged. The value of "[[ U ]]" is the UTC lack after all the leap seconds have occurred. The value of "[[ s ]]" is the end of the day "[[ D ]]" expressed in TAI. The ``end of the day'' equals the beginning of the next day, i.e.\ the point in time where the leap ends. Note that negative leaps are instantaneous so that they begin and end on the same moment whereas positive leaps have a duration of one second. 1965 1966 \item "[[ late define lgc-add-leap1 ( L , U , r ) as newline 1967 1968 if L atom then U :: r else newline 1969 1970 let ( D :: U prime ) :: L = L in newline 1971 1972 let U = U + U prime in newline 1973 1974 let s = ( D + 1 ) * lgc-seconds-per-day + U in newline 1975 1976 lgc-add-leap1 ( L , U , ( s :: U prime ) :: r ) end define ]]" 1977 1978 \item "[[ late define lgc-process-leap ( s ) as newline 1979 1980 let L = s [[ !"parameters" ]] [[ !"leap" ]] in newline 1981 1982 let L = lgc-convert-leap ( L ) in newline 1983 1984 lgc-check-leap ( L ) .then. newline 1985 1986 let L = lgc-add-leap ( L ) in newline 1987 1988 s [[ !"leap" -> L ]] end define ]]" 1989 1990 Extract the leap parameter from the state "[[ s ]]", convert it, and store it back into "[[ s [[ !"leap" ]] ]]". 1991 1992 \end{statements} 1993 1994 1995 1996 \subsection{Conversion from reference to Logiweb time} 1997 1998 The "[[ lgc-ref2lgt ( r ) ]]" function returns the time stamp of the Logiweb reference "[[ r ]]" expressed in Logiweb time. 1999 2000 \begin{statements} 2001 2002 \item "[[ late define lgc-ref2lgt ( r ) as newline 2003 2004 let r = vt2vector* ( r ) in newline 2005 2006 let v :: r = r in newline 2007 2008 if v != lgc-ref-version then lgc-panic ( !"Internal error: Wrong version" ) else newline 2009 2010 let r = list-suffix ( r , 20 ) in newline 2011 2012 let f :: r = parse-card ( r ) in newline 2013 2014 let e :: r = parse-card ( r ) in newline 2015 2016 << f ,, e >> end define ]]" 2017 2018 \end{statements} 2019 2020 2021 2022 \subsection{Conversion from Logiweb time to printed representation} 2023 2024 "[[ lgc-lgt2vt ( s ) ]]" converts the Logiweb time "[[ s = << f ,, e >> ]]" to a human readable Logiweb time. The return value is a vector tree. 2025 2026 \begin{statements} 2027 2028 \item "[[ late define lgc-lgt2vt ( s ) as newline 2029 2030 let << f ,, e >> = s in newline 2031 2032 let f = lgc-itoa ( f ) in newline 2033 2034 let e = lgc-itoa ( e ) in newline 2035 2036 << !"LGT-" ,, f ,, !"e-" ,, e >> end define ]]" 2037 2038 \end{statements} 2039 2040 2041 2042 \subsection{Conversion from Logiweb time to MJD/TAI} 2043 2044 "[[ lgc-lgt2mjdtai ( s ) ]]" converts the Logiweb time "[[ s = << f ,, e >> ]]" to MJD and TAI on form "[[ << D ,, h ,, m ,, s ,, f ,, e >> ]]" 2045 2046 "[[ lgc-lgt2mjdtai2vt ( s ) ]]" converts the Logiweb time "[[ s ]]" to human readable MJD and TAI. The return value is a vector tree. 2047 2048 The conversion is trivial because LGT expresses the number of TAI seconds since MJD-0.TAI:0:0:0 and since MJD, TAI, and LGT are all completely regular time counting schemes. 2049 2050 \begin{statements} 2051 2052 \item "[[ late define lgc-lgt2mjdtai ( s ) as newline 2053 2054 let << f ,, e >> = s in newline 2055 2056 let s :: f = floor ( f , exp10 ( e ) ) in newline 2057 2058 let m :: s = floor ( s , lgc-seconds-per-minute ) in newline 2059 2060 let h :: m = floor ( m , lgc-minutes-per-hour ) in newline 2061 2062 let D :: h = floor ( h , lgc-hours-per-day ) in newline 2063 2064 << D ,, h ,, m ,, s ,, f ,, e >> end define ]]" 2065 2066 \item "[[ late define lgc-lgt2mjdtai2vt ( s ) as newline 2067 2068 let << D ,, h ,, m ,, s ,, f ,, e >> = lgc-lgt2mjdtai ( s ) in newline 2069 2070 let D = lgc-itoa ( D ) in newline 2071 2072 let h = lgc-ctoa ( h , 2 ) in newline 2073 2074 let m = lgc-ctoa ( m , 2 ) in newline 2075 2076 let s = lgc-ctoa ( s , 2 ) in newline 2077 2078 let f = if e = 0 then true else !"." :: lgc-ctoa ( f , e ) in newline 2079 2080 << !"MJD-" ,, D ,, !".TAI:" ,, h ,, !":" ,, m ,, !":" ,, s ,, f >> end define ]]" 2081 2082 \end{statements} 2083 2084 2085 2086 \subsection{Conversion from Logiweb time to GRD/UTC} 2087 2088 At any time, UTC is a UTC lack "[[ U ]]" behind TAI. In 1972, the UTC lack "[[ U ]]" was 10 seconds. 2089 2090 We represent the location of leap seconds by a list "[[ L ]]" of form "[[ << s prime :: U prime ,, ... >> ]]" where "[[ s prime ]]" indicates the end time of a UTC leap expressed in LGT and "[[ U prime ]]" is "[[ + 1 ]]" for a positive leap and "[[ - 1 ]]" for a negative leap. At any time "[[ T ]]", the UTC lack equals 10 seconds plus the values of "[[ U prime ]]" for all leap seconds before "[[ T ]]". 2091 2092 The "[[ lgc-lgt2utc ( s , U , L ) ]]" function takes Logiweb second "[[ s ]]", a leap second list "[[ L ]]", and a UTC lack "[[ U ]]" as input. The UTC lack "[[ U ]]" must be the lack that applies after the last leap second in "[[ L ]]". 2093 2094 The "[[ lgc-lgt2utc ( s , U , L ) ]]" returns a pair "[[ u :: l ]]". The value of "[[ l ]]" is zero in case a positive UTC leap is in progress. At UTC time "[[ << h ,, m ,, s >> ]]" of MJD "[[ D ]]", the value of "[[ u ]]" is "[[ ( ( D * 24 + h ) * 60 + m ) * 60 + s - l ]]". We shall refer to "[[ u ]]" and "[[ l ]]" as the UTC second and leap, respectively. 2095 2096 As time progresses, the UTC second "[[ u ]]" is incremented once per second except when a leap second occurs. When a negative leap occurs, "[[ u ]]" is incremented twice instead of once. When a positive leap occurs, "[[ u ]]" has the same value of two consecutive seconds. During the second of those two seconds, the UTC leap equals "[[ 1 ]]". 2097 2098 "[[ lgc-lgt2grdutc2vt ( s , S ) ]]" expresses the Logiweb second "[[ s ]]" in human readable form using GRD and UTC. The return value is a vector tree. The "[[ lgc-lgt2grdutc2vt ( s , S ) ]]" function gets the UTC lack "[[ U ]]" and leap second list "[[ L ]]" from the state "[[ S ]]" and uses "[[ lgc-lgt2utc ( s , U , L ) ]]" to convert to UTC second "[[ u ]]" and leap "[[ l ]]". Then it converts "[[ u ]]" into year "[[ Y ]]", month "[[ M ]]", day "[[ D ]]", hour "[[ h ]]", minute "[[ m ]]", and second "[[ s ]]", and finally adds "[[ l ]]" to "[[ s ]]". 2099 2100 "[[ lgc-lgt2grdutc2v ( s , S ) ]]" is like "[[ lgc-lgt2grdutc2vt ( s , S ) ]]" except that it returns a vector. 2101 2102 \begin{statements} 2103 2104 \item "[[ late define lgc-lgt2utc ( s , U , L ) as newline 2105 2106 if L atom then s - U :: 0 else newline 2107 2108 let ( s prime :: U prime ) :: L = L in newline 2109 2110 if s prime <= s then s - U :: 0 else newline 2111 2112 if s prime <= s + U prime then s - U :: U prime else newline 2113 2114 lgc-lgt2utc ( s , U - U prime , L ) end define ]]" 2115 2116 \item "[[ late define lgc-lgt2grdutc ( s , S ) as newline 2117 2118 let U :: L = S [[ !"leap" ]] in newline 2119 2120 let << f ,, e >> = s in newline 2121 2122 let s :: f = floor ( f , exp10 ( e ) ) in newline 2123 2124 let s :: l = lgc-lgt2utc ( s , U , L ) in newline 2125 2126 let m :: s = floor ( s , lgc-seconds-per-minute ) in newline 2127 2128 let h :: m = floor ( m , lgc-minutes-per-hour ) in newline 2129 2130 let D :: h = floor ( h , lgc-hours-per-day ) in newline 2131 2132 let << Y ,, M ,, D >> = lgc-mjd2grd ( D ) in newline 2133 2134 << Y ,, M ,, D ,, h ,, m ,, s + l ,, f ,, e >> end define ]]" 2135 2136 \item "[[ late define lgc-lgt2grdutc2vt ( s , S ) as newline 2137 2138 let << Y ,, M ,, D ,, h ,, m ,, s ,, f ,, e >> = lgc-lgt2grdutc ( s , S ) in newline 2139 2140 let Y = lgc-itoa ( Y ) in newline 2141 2142 let M = lgc-ctoa ( M , 2 ) in newline 2143 2144 let D = lgc-ctoa ( D , 2 ) in newline 2145 2146 let h = lgc-ctoa ( h , 2 ) in newline 2147 2148 let m = lgc-ctoa ( m , 2 ) in newline 2149 2150 let s = lgc-ctoa ( s , 2 ) in newline 2151 2152 let f = if e = 0 then true else !"." :: lgc-ctoa ( f , e ) in newline 2153 2154 << !"GRD-" ,, Y ,, !"-" ,, M ,, !"-" ,, D ,, !".UTC:" ,, h ,, !":" ,, m ,, !":" ,, s ,, f >> end define ]]" 2155 2156 \item "[[ late define lgc-lgt2grdutc2v ( s , S ) as newline 2157 2158 vt2vector ( lgc-lgt2grdutc2vt ( s , S ) ) end define ]]" 2159 2160 \end{statements} 2161 2162 2163 2164 \subsection{Conversion from Unix time to Logiweb time} 2165 2166 As mentioned, the Logiweb compiler generates a poor mans TAI from Unix time. More specificially, the function below converts from Unix time to Logiweb time: 2167 2168 \begin{statements} 2169 2170 \item "[[ late define lgc-unix2lgt ( s , S ) as newline 2171 2172 let U :: L = S [[ !"leap" ]] in newline 2173 2174 let << f ,, e >> = s in newline 2175 2176 let E = exp10 ( e ) in newline 2177 2178 let s :: f = floor ( f , E ) in newline 2179 2180 let s = s + lgc-lgt-of-unix + U in newline 2181 2182 lgc-unix2lgt1 ( s , f , E , e , L ) end define ]]" 2183 2184 \item "[[ late define lgc-lgt-of-unix as lgc-grd2mjd ( << 1970 ,, 1 ,, 1 >> ) * lgc-seconds-per-day end define ]]" 2185 2186 "[[ lgc-lgt-of-unix ]]" indicates the begining of the TAI day containing the Unix epoch. More precisely, "[[ lgc-lgt-of-unix ]]" indicates 10 seconds before the Unix epoch since the UTC lack was 10 seconds in 1970. 2187 2188 \item "[[ late define lgc-unix2lgt1 ( s , f , E , e , L ) as newline 2189 2190 if L atom then << s * E + f ,, e >> else newline 2191 2192 let ( s prime :: U prime ) :: L = L in newline 2193 2194 let d = s - s prime in newline 2195 2196 if 0 <= d then << s * E + f ,, e >> else newline 2197 2198 if 0 <= d - 2 * U prime then << ( 10 * s prime + 5 * d ) * E + 5 * f ,, e + 1 >> else newline 2199 2200 if 0 <= d + U prime then << ( s prime + 2 * d ) * E + 2 * f ,, e >> else newline 2201 2202 lgc-unix2lgt1 ( s - U prime , f , E , e , L ) end define ]]" 2203 2204 \end{statements} 2205 2206 2207 2208 " ]"\section{Message generation}"[ " 2209 2210 This section defines functions for generation of error messages, warnings, and progress messages. 2211 2212 2213 2214 \subsection{State entries} 2215 2216 Message generation uses the following entries of the state: 2217 2218 \begin{itemize} 2219 2220 \item "[[ s [[ !"continue" ]] ]]" Set to false when error detected. 2221 2222 \item "[[ s [[ !"msg" ]] ]]" Stack of "[[ p :: m ]]" pairs where "[[ p ]]" is a position in the source file and "[[ m ]]" is a message to be printed. 2223 2224 \end{itemize} 2225 2226 2227 2228 \subsection{Integer input/output} 2229 2230 The "[[ lgc-atoi ( a , m ) ]]" function converts the sequence "[[ a ]]" of singleton strings to an integer. The function throws "[[ m ]]" in case of error. 2231 2232 The "[[ lgc-itoa ( i ) ]]" function converts the integer "[[ i ]]" to a list of singleton strings. 2233 2234 The "[[ lgc-ctoa ( c , w ) ]]" function converts the cardinal "[[ c ]]" to a vector tree and pads with zeros in front to make the string at least "[[ w ]]" characters wide. 2235 2236 The "[[ lgc-parse-int ( a ) ]]" function parses the integer at the beginning of the list "[[ a ]]" of singlton strings and returns "[[ i :: a prime ]]" where "[[ i ]]" is the integer and "[[ a prime ]]" is the unparsed part of "[[ a ]]". "[[ lgc-parse-int ( a ) ]]" throws an exception if no integer is found. 2237 2238 \begin{statements} 2239 2240 \item "[[ late define lgc-parse-int ( a ) as newline 2241 2242 if a atom then exception else newline 2243 2244 if a head != !"-" then lgc-parse-int1 ( a , 0 ) else newline 2245 2246 if a tail atom then exception else newline 2247 2248 let n :: a = lgc-parse-int1 ( a tail , 0 ) in - n :: a end define ]]" 2249 2250 Parse integer at beginning of the string "[[ a ]]". 2251 2252 \item "[[ late define lgc-parse-int1 ( a , r ) as newline 2253 2254 if a atom then r :: true else newline 2255 2256 let c = a head in newline 2257 2258 if c < !"0" .or. c > !"9" then r :: a else newline 2259 2260 lgc-parse-int1 ( a tail , c - !"0" + Base * r ) end define ]]" 2261 2262 Parse integer at beginning of the string "[[ a ]]", accumulating the result in "[[ r ]]". 2263 2264 \item "[[ late define lgc-atoi ( a , m ) as newline 2265 2266 let e :: n :: a = lgc-parse-int ( a ) catch in newline 2267 2268 if e .or. a != true then m raise else n end define ]]" 2269 2270 Convert the singleton list "[[ a ]]" to an integer. 2271 2272 \item "[[ late define lgc-itoa ( i ) as newline 2273 2274 if i = 0 then << "0" >> else newline 2275 2276 if i > 0 then lgc-itoa1 ( i , true ) else "-" :: lgc-itoa1 ( - i , true ) end define ]]" 2277 2278 Convert the integer "[[ i ]]" to a singleton list. 2279 2280 \item "[[ late define lgc-itoa1 ( i , r ) as newline 2281 2282 if i = 0 then r else newline 2283 2284 let i :: m = floor ( i , Base ) in newline 2285 2286 lgc-itoa1 ( i , m + !"0" :: r ) end define ]]" 2287 2288 Convert the cardinal "[[ i ]]" to a singleton list, accumulating the result in "[[ r ]]". 2289 2290 \item "[[ late define lgc-ctoa ( c , w ) as newline 2291 2292 let c = lgc-itoa1 ( c , true ) in newline 2293 2294 repeat ( w - length ( c ) , !"0" ) :: c end define ]]" 2295 2296 Convert the cardinal "[[ c ]]" to an integer of width at least "[[ w ]]", prepending with zeros as needed. 2297 2298 \item "[[ late define lgc-ordinal-suffix ( n ) as newline 2299 2300 if ( n div Base ) mod Base = 1 then "th" else newline 2301 2302 let n = n mod Base in newline 2303 2304 if n = 1 then "st" else newline 2305 2306 if n = 2 then "nd" else newline 2307 2308 if n = 3 then "rd" else "th" end define ]]" 2309 2310 Return the suffix to append to a cardinal to form an ordinal (where `cardinal' and `ordinal' are from linguistics, not from mathematics). 2311 2312 \item "[[ late define lgc-ordinal ( n ) as newline 2313 2314 lgc-itoa ( n ) :: lgc-ordinal-suffix ( n ) end define ]]" 2315 2316 Convert the cardinal "[[ n ]]" to an ordinal expressed as a vector tree. 2317 2318 \end{statements} 2319 2320 2321 2322 \subsection{Verbosity levels}\label{sec:VerbosityLevels} 2323 2324 When invoking the Logiwab compiler, the user can set the verbosity level. The default verbosity level is 3. The levels are: 2325 2326 \begin{description} 2327 2328 \item[1] Print error messages 2329 2330 \item[2] Print warning messages 2331 2332 \item[3] Print progress information 2333 2334 \item[4] Print more progress information 2335 2336 \item[5] Print debugging information 2337 2338 \end{description} 2339 2340 Each message has a severity level "[[ l ]]" where small values of "[[ l ]]" indicate a high severity level. Messages are only sent to the user when "[[ l <= v ]]" where "[[ v ]]" is the verbosity. 2341 2342 Verbosity level zero is reserved for silent operation. The present compiler, however, does not allow suppression of error messages. 2343 2344 2345 2346 \subsection{Message stacking} 2347 2348 Messages are stored in "[[ s [[ !"msg" ]] ]]". 2349 2350 The function "[[ lgc-add-message ( s , l , p , m ) ]]" adds the message "[[ m ]]" with severity level "[[ l ]]" in the state "[[ s ]]" provided that "[[ l <= v ]]" where "[[ v ]]" is the verbosity. 2351 2352 The value of "[[ p ]]" in "[[ lgc-add-message ( s , l , p , m ) ]]" must indicate the position in the source file which gave rise to the message. The value of "[[ p ]]" must be the position given as a byte offset. As an example, "[[ p = 5 ]]" indicates the position between the fifth and sixth byte of the file. Note that "[[ p ]]" is a byte offset and not a character offset. Characters are supposed to be encoded in Logiweb Unicode UTF-8, so one character can take up several bytes. A position "[[ p ]]" can indicate a position inside a character. A negative value of "[[ p ]]" represents the end of the source file. 2353 2354 Once a message "[[ m ]]" is added to the state "[[ s ]]", then "[[ s ]]" should be raised as an exception in case the message is fatal, and "[[ s ]]" should be used as the new state otherwise. The "[[ lgc-add-message ( s , l , p , m ) ]]" adds at most ten messages to the state. When "[[ lgc-add-message ( s , l , p , m ) ]]" adds the tenth message, it raises the resulting state as an exception. 2355 2356 The function "[[ lgc-throw-message ( s , p , m ) ]]" is like "[[ lgc-add-message ( s , l , p , m ) ]]" but always throws and always sets the severity to one. 2357 2358 \begin{statements} 2359 2360 \item "[[ late define lgc-max-messages as 10 end define ]]" 2361 2362 Maximum number of messages allowed from one run of the compiler. 2363 2364 \item "[[ late define lgc-add-message ( s , l , p , m ) as newline 2365 2366 let s = if l > 1 then s else s [[ !"continue" -> false ]] in newline 2367 2368 if s [[ !"verbose" ]] < l then s else newline 2369 2370 let M = s [[ !"msg" ]] in newline 2371 2372 let M = ( p :: m ) :: M in newline 2373 2374 let s = s [[ !"msg" -> M ]] in newline 2375 2376 if length ( M ) >= lgc-max-messages then s raise else s end define ]]" 2377 2378 Add message "[[ m ]]" relating to position "[[ p ]]" in the source file to the state "[[ s ]]" provided the severity level "[[ l ]]" is less than or equal to the verbosity. 2379 2380 \item "[[ late define lgc-throw-message ( s , p , m ) as newline 2381 2382 lgc-add-message ( s , 1 , p , m ) raise end define ]]" 2383 2384 Like Add message but always throws and always sets the severity to one. 2385 2386 \end{statements} 2387 2388 2389 2390 \subsection{Message reporting} 2391 2392 The "[[ lgc-report-messages ( s ) ]]" function formats messages stacked in "[[ s ]]" and convert them to a list of output events. 2393 2394 \begin{statements} 2395 2396 \item "[[ late define lgc-die ( m ) as newline 2397 2398 << writeln request ( m ) ,, quit request ( 1 ) >> end define ]]" 2399 2400 Die with last word "[[ m ]]". 2401 2402 \item "[[ late define lgc-report-messages ( s ) as newline 2403 2404 let M = s [[ !"msg" ]] in newline 2405 2406 if M then lgc-die ( !"Unhandled exception, goodbye." ) else newline 2407 2408 lgc-die ( lgc-report-messages1 ( s , M , !"Goodbye." ) ) end define ]]" 2409 2410 Extract messages from the state and convert them into a write request. 2411 2412 \item "[[ late define lgc-report-messages1 ( s , M , r ) as newline 2413 2414 if M atom then r else newline 2415 2416 let ( p :: m ) :: M = M in newline 2417 2418 if .not. p intp then lgc-panic ( !"Internal error: Error position is no int" ) else newline 2419 2420 lgc-report-messages1 ( s , M , lgc-report-messages2 ( s , p , m ) :: r ) end define ]]" 2421 2422 Format the list "[[ M ]]" of messages. 2423 2424 \item "[[ late define lgc-report-messages2 ( s , p , m ) as newline 2425 2426 let f = s [[ !"source" ]] in newline 2427 2428 let p = if p < 0 then length ( f ) else p in newline 2429 2430 let l :: c = lgc-position ( f , p , 1 , 1 ) in newline 2431 2432 let m _ { 1 } = !"Line " :: lgc-itoa ( l ) :: !" character " :: lgc-itoa ( c ) :: !":" in newline 2433 2434 let m _ { 2 } = lgc-report-message3 ( f , p ) in newline 2435 2436 !"---" :: LF :: m _ { 1 } :: LF :: m :: LF :: m _ { 2 } :: LF end define ]]" 2437 2438 Format the message "[[ m ]]" which relates to position "[[ p ]]" in the source file. Note that "[[ LF ]]" marks the end of a line regardless of the end-of-line convention of the underlying operating system. 2439 2440 \item "[[ late define lgc-position ( f , p , L , C ) as newline 2441 2442 if f atom .or. p = 0 then L :: C else newline 2443 2444 let c :: f = f in newline 2445 2446 if c = LF then lgc-position-1 ( CR , f , p - 1 , L + 1 , 1 ) else newline 2447 2448 if c = CR then lgc-position-1 ( LF , f , p - 1 , L + 1 , 1 ) else newline 2449 2450 if c = FF then lgc-position ( f , p - 1 , L + 1 , 1 ) else newline 2451 2452 if c = TAB then lgc-position ( f , p - 1 , L , C + 1 ) else newline 2453 2454 if c < SP then lgc-position ( f , p - 1 , L , C ) else newline 2455 2456 if lgc-char-start ( c ) then lgc-position ( f , p - 1 , L , C + 1 ) else newline 2457 2458 lgc-position ( f , p - 1 , L , C ) end define ]]" 2459 2460 Convert position "[[ p ]]" given as a byte offset to a pair "[[ L :: C ]]" of line number "[[ L ]]" and character number "[[ C ]]" assuming Logiweb Unicode UTF-8 encoding. 2461 2462 \item "[[ late define lgc-position-1 ( c , f , p , L , C ) as newline 2463 2464 if f head = c then lgc-position ( f tail , p , L , C ) else newline 2465 2466 lgc-position ( f , p , L , C ) end define ]]" 2467 2468 Same as above except that character "[[ c ]]" is ignored if it occurs at the beginning of "[[ f ]]". 2469 2470 \item "[[ late define lgc-max-lines as 3 end define ]]" 2471 2472 Maximum number of printed lines before and after error location. 2473 2474 \item "[[ late define lgc-max-chars as 80 end define ]]" 2475 2476 Maximum number of characters per line before and after error location. 2477 2478 \item "[[ late define lgc-report-message3 ( f , p ) as newline 2479 2480 let h :: t = lgc-split ( f , p , true ) in newline 2481 2482 let h = lgc-size-limit ( h , lgc-max-lines , lgc-max-chars , true ) in newline 2483 2484 let h = if h head = LF then h tail else h in newline 2485 2486 let t = lgc-size-limit ( t , lgc-max-lines , lgc-max-chars , true ) in newline 2487 2488 h :: !"|" :: LF :: !"---" :: LF :: reverse ( t tail ) end define ]]" 2489 2490 Split the file "[[ f ]]" into head "[[ h ]]" and tail "[[ t ]]" at position "[[ p ]]". Then limit head and tail to at most "[[ lgc-max-lines ]]" lines of at most "[[ lgc-max-chars ]]" characters each. Then glue the head and tail together. 2491 2492 \item "[[ late define lgc-split ( f , p , r ) as newline 2493 2494 if p = 0 .or. f atom then lgc-split1 ( r , f ) else lgc-split ( f tail , p - 1 , f head :: r ) end define ]]" 2495 2496 Pass "[[ p ]]" bytes from "[[ f ]]" to "[[ r ]]". Then call "[[ lgc-split1 ( r , f ) ]]" to move back to last character boundary. 2497 2498 \item "[[ late define lgc-split1 ( h , t ) as newline 2499 2500 if h atom .or. t atom .or. lgc-char-start ( t head ) then h :: t else newline 2501 2502 lgc-split1 ( h tail , h head :: t ) end define ]]" 2503 2504 Move backwards until the tail "[[ t ]]" starts at a character boundary. 2505 2506 \item "[[ late define lgc-char-start1 as NULL + 128 end define ]]" 2507 2508 The value of the smallest UTF-8 byte which does not start a character. 2509 2510 \item "[[ late define lgc-char-start2 as NULL + 128 + 64 end define ]]" 2511 2512 One plus the value of the largest UTF-8 byte which does not start a character. 2513 2514 \item "[[ late define lgc-char-start ( c ) as c < lgc-char-start1 .or. lgc-char-start2 <= c end define ]]" 2515 2516 True if the character "[[ c ]]" marks the start of a UTF-8 character (also true if "[[ c ]]" is illegal in UTF-8). 2517 2518 \item "[[ late define lgc-size-limit ( f , L , C , r ) as newline 2519 2520 if f atom .or. L = 0 then r else newline 2521 2522 if C = 0 then lgc-size-limit ( f , L - 1 , lgc-max-chars , r ) else newline 2523 2524 let c :: f = f in newline 2525 2526 let r = c :: r in newline 2527 2528 if c = LF then lgc-size-limit ( f , L - 1 , lgc-max-chars , r ) else newline 2529 2530 if lgc-char-start ( c ) then lgc-size-limit ( f , L , C - 1 , r ) else newline 2531 2532 lgc-size-limit ( f , L , C , r ) end define ]]" 2533 2534 \end{statements} 2535 2536 2537 2538 \subsection{Unconditional errors} 2539 2540 The "[[ lgc-error ( s , p , a ) ]]" function formats the message "[[ a ]]" and converts it to a list of output events. The "[[ lgc-simple-error ( a , s ) ]]" function does the same except that it simply outputs "[[ a ]]" and exits. 2541 2542 \begin{statements} 2543 2544 \item "[[ late define lgc-error ( s , p , a ) as newline 2545 2546 let e :: s = lgc-add-message ( s , 1 , p , a ) catch in newline 2547 2548 lgc-report-messages ( s ) end define ]]" 2549 2550 \item "[[ late define lgc-simple-error ( a , s ) as newline 2551 2552 let s = lgc-progress ( a , 1 , s ) in newline 2553 2554 lgc-do-events ( s ) end define ]]" 2555 2556 \end{statements} 2557 2558 2559 2560 \subsection{Progress messages} 2561 2562 The "[[ lgc-progress ( a , l , s ) ]]" function prints the message "[[ a ]]" unless the verbosity is less than the level "[[ l ]]". 2563 2564 The "[[ lgc-print ( p , a ) ]]" function prints "[[ a ]]" if "[[ p ]]" is true. The "[[ lgc-print ( p , a ) ]]" function uses "[[ print ( a ) ]]" rather than constructing an event. 2565 2566 \begin{statements} 2567 2568 \item "[[ late define lgc-progress ( a , l , s ) as newline 2569 2570 if s [[ !"verbose" ]] < l then s else newline 2571 2572 lgc-push-event ( s , writeln request ( a ) ) end define ]]" 2573 2574 \item "[[ late define lgc-print ( p , a ) as newline 2575 2576 if p then print ( a :: LF ) else true end define ]]" 2577 2578 \end{statements} 2579 2580 2581 2582 " ]"\section{Lexical analysis}"[ " 2583 2584 The Logiweb frontend language has a static and a dynamic syntax. The static and dynamic syntax are treated during lexical analysis and parsing, respectively. We define the static syntax in the following. 2585 2586 We shall refer to a sequence of two or more double quote characters as a \emph{multiquote}. Multiquotes mark the start of an escape sequence in Logiweb source files. 2587 2588 We shall refer to a multiquote followed by a character or the end of the file as an \emph{escape sequence}. Hence, an escape sequence covers both the multiquote and the first character (if any) after the multiquote. 2589 2590 Escape sequences that may occur in the body of a page are: 2591 2592 \begin{verbatim} 2593 ""! Start of string (until double quote or ""!""!.) 2594 ""!""!- Start of string (until double quote or ""!""!.) 2595 ""!""!; Start of short comment (until end of line) 2596 ""!""!{ Start of long comment (until ""!""!}) 2597 ""!""!# Binary include as string (until double quote or ""!""!.) 2598 ""!""!$ Text include as string (until double quote or ""!""!.) 2599 ""!""!P Page name (until end of line or ""!""!n) 2600 ""!""!R Reference (until end of line or ""!""!n) 2601 ""!""!D Definition (until ""!""!P, ""!""!R, ""!""!D or ""!""!B) 2602 ""!""!. The empty string (self-terminated) 2603 ""!""!S Page source as a string (self-terminated) 2604 ""!""!N Name definitions (self-terminated) 2605 ""!""!C Charge defintions (self-terminated) 2606 \end{verbatim} 2607 2608 The number of double quote characters in the escape sequence closing a long comment must equal the number of double quote characters in the escape sequence opening the long comment. Apart from this, the number of double quote characters in an escape sequence is of no importance. 2609 2610 Some examples read: 2611 \begin{verbatim} 2612 ""! this is a string ""! 2613 ""!""!- this is another string ""! 2614 ""! this is a third string ""!""!. 2615 ""!""!- this is a fourth string ""!""!. 2616 ""!""!; this is a short comment 2617 ""!""!{ this is a long comment ""!""!} 2618 ""!""!""!{ this is another long comment ""!""!""!} 2619 ""!""!""!{ this is a strange ""!""!}""!""!;""!""!{ long comment ""!""!""!} 2620 ""!""!#/this/is/a/binary/include""! 2621 ""!""!$/this/is/a/text/include""! 2622 ""!""!P qualifier 1 ""! qualifier 2 ""! this is a page name 2623 ""!""!R qualifier 3 ""! qualifier 4 ""! /this/is/a/reference 2624 ""!""!D 1.2.3 ""!""!; charge 2625 ""! + ""! ""!""!; production 2626 ""! - ""! ""!""!; another production 2627 ""!""!B ""!""!; body (end of definition) 2628 ""!""!. ""!""!; the empty string 2629 ""!""!S ""!""!; Page source as a string 2630 ""!""!N ""!""!; Name definitions 2631 ""!""!C ""!""!; Charge defintions 2632 \end{verbatim} 2633 2634 Escapes that may occur inside a string: 2635 2636 \begin{verbatim} 2637 ""!""!- No character 2638 ""!""!! Double quote 2639 ""!""!f Form feed 2640 ""!""!n Line feed 2641 ""!""!r Carriage return 2642 ""!""!t Horizontal tab 2643 ""!""!x Characters given in hexadecimal (until period) 2644 \end{verbatim} 2645 2646 Example: 2647 2648 \begin{verbatim} 2649 ""!AB""!""!-""!""!!""!""!x4344.""!""!!EF""!""!. 2650 \end{verbatim} 2651 2652 The string above comprises the following eight characters: 2653 2654 \begin{verbatim} 2655 AB""!CD""!DE 2656 \end{verbatim} 2657 2658 Escapes that may occur inside the path name part of a reference: 2659 2660 \begin{verbatim} 2661 ""!""!! Double quote 2662 \end{verbatim} 2663 2664 Having an escape in a reference is useful only in the unlikely event that a file name contains a double quote character. 2665 2666 Escapes that may occur inside a definition: 2667 2668 \begin{verbatim} 2669 ""!""!n Line feed 2670 \end{verbatim} 2671 2672 The escape sequence above allows to define more than one production on one line. 2673 2674 2675 2676 \subsection{State entries} 2677 2678 During lexical analysis, the compiler builds up a state "[[ s ]]" with the following contents: 2679 2680 \begin{itemize} 2681 2682 \item "[[ s [[ !"source" ]] ]]" The raw source text. 2683 2684 \item "[[ s [[ !"sourcename" ]] ]]" The path of the source text (after tilde-expansion and optionally appending of .lgs). 2685 2686 \item "[[ s [[ !"body" ]] ]]" The body of a page after lexical analysis. The body is a list of items of form "[[ c :: p :: S ]]" where "[[ c ]]" is a character, "[[ p ]]" is the position of that character in the source file, and "[[ S ]]" is the structure (if any) initiated by that structure. As an example, if "[[ c ]]" is "[[ lgc-esc-# ]]" then "[[ S ]]" is the name of the file to be included. 2687 2688 \item "[[ s [[ !"page" ]] ]]" The page name after lexical analysis. 2689 2690 \item "[[ s [[ !"def" ]] ]]" The definitions after lexical analysis. 2691 2692 \item "[[ s [[ !"bib" ]] ]]" The bibliography after lexical analysis. 2693 2694 \item "[[ s [[ !"nincludes" ]] ]]" Stack of pairs "[[ p :: n ]]" where the values of "[[ n ]]" are names of include files and "[[ p ]]" are the positions in the source file where they occur. 2695 2696 \item "[[ s [[ !"includes" ]] ]]" Array mapping names of include files to their contents. 2697 2698 \end{itemize} 2699 2700 2701 2702 \subsection{Lexical analysis main functions} 2703 2704 The "[[ lgc-lex-1 ( s ) ]]" function requests the source file and "[[ lgc-lex-2 ( x , s ) ]]" processes it. 2705 2706 \begin{statements} 2707 2708 \item "[[ late define lgc-lex-1 ( s ) as newline 2709 2710 let n = s [[ !"parameters" ]] [[ !"source" ]] head in newline 2711 2712 if n then << writeln request ( !"No source file specified" ) >> else newline 2713 2714 let n = lgc-tilde-expand ( n , s [[ !"parameters" ]] ) in newline 2715 2716 let s = s [[ !"sourcename" -> n ]] in newline 2717 2718 let s = lgc-progress ( lgc-lgt2grdutc2vt ( s [[ !"time" ]] , s ) , 3 , s ) in newline 2719 2720 let s = lgc-progress ( !"Reading file:" :: n , 3 , s ) in newline 2721 2722 let s = lgc-push-event ( s , fileTypeRead ( n ) ) in newline 2723 2724 lgc-exec-events ( s , lgc-lex-2 ( x , s ) ) end define ]]" 2725 2726 Process query, if any. Else go on to compilation. 2727 2728 \item "[[ late define lgc-lex-2 ( x , s ) as newline 2729 2730 let << true ,, << true ,, t :: f >> >> = x in newline 2731 2732 if t = FileTypeRegular then lgc-lex-4 ( f , s ) else newline 2733 2734 let n = s [[ !"sourcename" ]] :: !".lgs" in newline 2735 2736 let s = s [[ !"sourcename" -> n ]] in newline 2737 2738 let s = lgc-progress ( !"Reading file:" :: n , 3 , s ) in newline 2739 2740 let s = lgc-push-event ( s , fileTypeRead ( n ) ) in newline 2741 2742 lgc-exec-events ( s , lgc-lex-3 ( x , s ) ) end define ]]" 2743 2744 \item "[[ late define lgc-lex-3 ( x , s ) as newline 2745 2746 let << true ,, << true ,, t :: f >> >> = x in newline 2747 2748 if t = FileTypeRegular then lgc-lex-4 ( f , s ) else newline 2749 2750 << writeln request ( !"Source file not found" ) >> end define ]]" 2751 2752 \item "[[ late define lgc-lex-4 ( f , s ) as newline 2753 2754 let s = s [[ !"source" -> f ]] in newline 2755 2756 let e :: S = lgc-lex-source ( f , s ) catch in newline 2757 2758 if e then lgc-error ( s , S head , S tail ) else newline 2759 2760 lgc-include-1 ( S ) end define ]]" 2761 2762 Extract the source from the input event "[[ x ]]". Then prepare a state "[[ s ]]" for compilation. 2763 2764 \end{statements} 2765 2766 2767 2768 \subsection{Escape sequences} 2769 2770 We now define quantities like "[[ lgc-esc-# ]]" for representing escape sequences. We also define a value, "[[ lgc-EOF ]]", for representing the End Of File. 2771 2772 \begin{statements} 2773 2774 \item "[[ late define lgc-EOF as 0 end define ]]" 2775 2776 \item "[[ late define lgc-esc-. as !"." - NULL end define ]]" 2777 2778 \item "[[ late define lgc-esc-- as !"-" - NULL end define ]]" 2779 2780 \item "[[ late define lgc-esc-! as !"!" - NULL end define ]]" 2781 2782 \item "[[ late define lgc-esc-# as !"#" - NULL end define ]]" 2783 2784 \item "[[ late define lgc-esc-$ as !"$" - NULL end define ]]" 2785 2786 \item "[[ late define lgc-esc-left as !"[" - NULL end define ]]" 2787 2788 \item "[[ late define lgc-esc-right as !"]" - NULL end define ]]" 2789 2790 \item "[[ late define lgc-esc-brace as !"}" - NULL end define ]]" 2791 2792 \item "[[ late define lgc-esc-B as !"B" - NULL end define ]]" 2793 2794 \item "[[ late define lgc-esc-C as !"C" - NULL end define ]]" 2795 2796 \item "[[ late define lgc-esc-D as !"D" - NULL end define ]]" 2797 2798 \item "[[ late define lgc-esc-N as !"N" - NULL end define ]]" 2799 2800 \item "[[ late define lgc-esc-P as !"P" - NULL end define ]]" 2801 2802 \item "[[ late define lgc-esc-R as !"R" - NULL end define ]]" 2803 2804 \item "[[ late define lgc-esc-S as !"S" - NULL end define ]]" 2805 2806 \item "[[ late define lgc-esc-f as !"f" - NULL end define ]]" 2807 2808 \item "[[ late define lgc-esc-n as !"n" - NULL end define ]]" 2809 2810 \item "[[ late define lgc-esc-r as !"r" - NULL end define ]]" 2811 2812 \item "[[ late define lgc-esc-t as !"t" - NULL end define ]]" 2813 2814 \item "[[ late define lgc-esc-x as !"x" - NULL end define ]]" 2815 2816 \end{statements} 2817 2818 2819 2820 \subsection{Space trimming} 2821 2822 The following functions remove spaces at the beginning or end of a string. They can remove at most one space character at each end. The input and output are lists of singleton strings. 2823 2824 \begin{statements} 2825 2826 \item "[[ late define lgc-left-trim ( a ) as newline 2827 2828 if a head = SP then a tail else a end define ]]" 2829 2830 Remove leading space, if any. 2831 2832 \item "[[ late define lgc-right-trim ( a ) as newline 2833 2834 reverse ( lgc-left-trim ( reverse ( a ) ) ) end define ]]" 2835 2836 Remove trailing space, if any. 2837 2838 \item "[[ late define lgc-trim ( a ) as newline 2839 2840 lgc-right-trim ( lgc-left-trim ( a ) ) end define ]]" 2841 2842 Remove leading space, if any, and trailing space, if any. 2843 2844 \end{statements} 2845 2846 2847 2848 \subsection{Space contraction} 2849 2850 The following functions contracts multiple spaces into single space characters and possibly trims or reverses the strings. The input and output are lists of singleton strings. 2851 2852 \begin{statements} 2853 2854 \item "[[ late define lgc-reverse-contract ( a ) as newline 2855 2856 lgc-reverse-contract1 ( a , true ) end define ]]" 2857 2858 Contract multiple spaces in "[[ a ]]" to single spaces and reverse "[[ a ]]". 2859 2860 \item "[[ late define lgc-reverse-contract1 ( a , r ) as newline 2861 2862 if a atom then r else newline 2863 2864 let c :: a = a in newline 2865 2866 if c = SP .and. r head = SP then newline 2867 2868 lgc-reverse-contract1 ( a , r ) else newline 2869 2870 lgc-reverse-contract1 ( a , c :: r ) end define ]]" 2871 2872 Accumulate "[[ lgc-reverse-contract ( a ) ]]" in "[[ r ]]". 2873 2874 \item "[[ late define lgc-contract ( a ) as newline 2875 2876 reverse ( lgc-reverse-contract ( a ) ) end define ]]" 2877 2878 Contract multiple spaces in "[[ a ]]" to single spaces. 2879 2880 \item "[[ late define lgc-contract* ( a ) as newline 2881 2882 if a atom then true else newline 2883 2884 lgc-contract ( a head ) :: lgc-contract* ( a tail ) end define ]]" 2885 2886 Apply "[[ lgc-contract ( e ) ]]" in each element of the list "[[ a ]]". 2887 2888 \item "[[ late define lgc-trim-contract ( a ) as newline 2889 2890 lgc-left-trim ( reverse ( lgc-left-trim ( lgc-reverse-contract ( a ) ) ) ) end define ]]" 2891 2892 Contract multiple spaces in "[[ a ]]" to single spaces and remove leading and trailing spaces, if any. 2893 2894 \end{statements} 2895 2896 2897 2898 \subsection{Space trimming of text containing character positions} 2899 2900 The following functions remove spaces at the beginning or end of a string. They can remove at most one space character at each end. The input and output are lists of singleton strings. 2901 2902 \begin{statements} 2903 2904 \item "[[ late define lgc-lex-left-trim ( a ) as newline 2905 2906 if a head head = SP then lgc-lex-left-trim ( a tail ) else a end define ]]" 2907 2908 Remove leading spaces, if any. 2909 2910 \item "[[ late define lgc-lex-right-trim ( a ) as newline 2911 2912 reverse ( lgc-lex-left-trim ( reverse ( a ) ) ) end define ]]" 2913 2914 Remove trailing space, if any. 2915 2916 \item "[[ late define lgc-lex-trim ( a ) as newline 2917 2918 lgc-lex-right-trim ( lgc-lex-left-trim ( a ) ) end define ]]" 2919 2920 Remove leading space, if any, and trailing space, if any. 2921 2922 \end{statements} 2923 2924 2925 2926 \subsection{Space contraction of text containing character positions} 2927 2928 The following functions contracts multiple spaces into single space characters and possibly trims or reverses the strings. The input and output are lists of singleton strings. 2929 2930 \begin{statements} 2931 2932 \item "[[ late define lgc-lex-reverse-contract ( a ) as newline 2933 2934 lgc-lex-reverse-contract1 ( a , true ) end define ]]" 2935 2936 Contract multiple spaces in "[[ a ]]" to single spaces and reverse "[[ a ]]". 2937 2938 \item "[[ late define lgc-lex-reverse-contract1 ( a , r ) as newline 2939 2940 if a atom then r else newline 2941 2942 let c :: a = a in newline 2943 2944 if c head = SP .and. r head head = SP then newline 2945 2946 lgc-lex-reverse-contract1 ( a , r ) else newline 2947 2948 lgc-lex-reverse-contract1 ( a , c :: r ) end define ]]" 2949 2950 Accumulate "[[ lgc-lex-reverse-contract ( a ) ]]" in "[[ r ]]". 2951 2952 \item "[[ late define lgc-lex-contract ( a ) as newline 2953 2954 reverse ( lgc-lex-reverse-contract ( a ) ) end define ]]" 2955 2956 Contract multiple spaces in "[[ a ]]" to single spaces. 2957 2958 \item "[[ late define lgc-lex-reverse-contract* ( a ) as newline 2959 2960 if a atom then true else newline 2961 2962 lgc-lex-reverse-contract ( a head ) :: lgc-lex-reverse-contract* ( a tail ) end define ]]" 2963 2964 Apply "[[ lgc-lex-contract ( e ) ]]" in each element of the list "[[ a ]]". 2965 2966 \item "[[ late define lgc-lex-contract* ( a ) as newline 2967 2968 if a atom then true else newline 2969 2970 lgc-lex-contract ( a head ) :: lgc-lex-contract* ( a tail ) end define ]]" 2971 2972 Apply "[[ lgc-lex-contract ( e ) ]]" in each element of the list "[[ a ]]". 2973 2974 \item "[[ late define lgc-lex-reverse-trim-contract ( a ) as newline 2975 2976 lgc-lex-left-trim ( lgc-lex-reverse-contract ( lgc-lex-left-trim ( a ) ) ) end define ]]" 2977 2978 Contract multiple spaces in "[[ a ]]" to single spaces and remove leading and trailing spaces, if any. Reverse the list during the process. 2979 2980 \item "[[ late define lgc-lex-trim-contract ( a ) as newline 2981 2982 reverse ( lgc-lex-reverse-trim-contract ( a ) ) end define ]]" 2983 2984 Contract multiple spaces in "[[ a ]]" to single spaces and remove leading and trailing spaces, if any. 2985 2986 \end{statements} 2987 2988 2989 2990 \subsection{Lexical analysis} 2991 2992 Split source into constituents and store them in "[[ s [[ !"page" ]] ]]", "[[ s [[ !"bib" ]] ]]", "[[ s [[ !"def" ]] ]]", "[[ s [[ !"body" ]] ]]". 2993 2994 \begin{statements} 2995 2996 \item "[[ late define lgc-lex-source ( f , s ) as newline 2997 2998 let f = newline 2999 3000 let f = newline 3001 3002 let f = newline 3003 3004 let f = newline 3005 3006 let f = newline 3007 3008 lgc-lex-position ( f , 0 ) in newline 3009 3010 lgc-lex-newline ( f , true ) in newline 3011 3012 lgc-lex-comment1 ( f ) in newline 3013 3014 lgc-lex-escape1 ( f ) in newline 3015 3016 lgc-lex-collect ( f ) in newline 3017 3018 let g = lgc-lex-left-trim ( lgc-lex-extract-body ( f ) ) in newline 3019 3020 let s = s [[ !"body" -> g ]] in newline 3021 3022 let s = lgc-lex-extract-other ( f , s ) in newline 3023 3024 s end define ]]" 3025 3026 Apply lexical analysis to the source by adding positions, normalizing newline sequences, removing comments, replacing escape sequences by escape codes, and collecting structures (like strings) into tokens. The funny way of stating let-statements ensures that the rather large intermediate results can be re-claimed by the garbage collector. 3027 3028 \end{statements} 3029 3030 3031 3032 \subsection{Add positions to text} 3033 3034 \begin{statements} 3035 3036 \item "[[ late define lgc-lex-position ( f , p ) as newline 3037 3038 if f atom then true else newline 3039 3040 << f head ,, p >> :: lgc-lex-position ( f tail , p + 1 ) end define ]]" 3041 3042 Add position numbers to all characters. 3043 3044 \end{statements} 3045 3046 3047 3048 \subsection{Replace newline sequences with newline characters} 3049 3050 Input files are assumed to be encoded in Logiweb Unicode UTF-8. This is identical to the Unicode UTF-8 encoding with the following, additional conventions concerning ``special characters'', i.e.\ characters with codes between Code 0 and Code 31, inclusive: 3051 3052 \begin{description} 3053 3054 \item[Code 9 horizontal tab (TAB)] A TAB is treated as a Code 32 space. 3055 3056 \item[Code 10 line feed (LF)] An LF marks the end of a line. 3057 3058 \item[Code 12 form feed (FF)] An FF is treated as an LF. 3059 3060 \item[Code 13 carriage return (CR)] A CR is treated as an LF. However, an LF which follows a non-ignored CR is ignored and a CR which follows a non-ignored LF is ignored. As an example, the sequence "[[ << LF ,, CR ,, CR ,, LF >> ]]" is interpreted as a non-ignored "[[ LF ]]", an ignored "[[ CR ]]", a non-ignored "[[ CR ]]", and an ignored "[[ LF ]]". The non-ignored "[[ LF ]]" and "[[ CR ]]" both mark the end of a line. Hence, "[[ << LF ,, CR ,, CR ,, LF >> ]]" is interpreted as two "[[ LF ]]" characters. 3061 3062 \item[Other] All characters in the range 0--31 other than TAB, LF, FF, and CR are considered illegal. 3063 3064 \end{description} 3065 3066 \begin{statements} 3067 3068 \item "[[ late define lgc-lex-newline ( f , C ) as newline 3069 3070 if f atom then true else newline 3071 3072 let << c ,, p >> :: f = f in newline 3073 3074 if c >= !" " then << c ,, p >> :: lgc-lex-newline ( f , true ) else newline 3075 3076 if c = C then lgc-lex-newline ( f , true ) else newline 3077 3078 if c = LF then << c ,, p >> :: lgc-lex-newline ( f , CR ) else newline 3079 3080 if c = CR then << LF ,, p >> :: lgc-lex-newline ( f , LF ) else newline 3081 3082 if c = FF then << LF ,, p >> :: lgc-lex-newline ( f , true ) else newline 3083 3084 if c = TAB then << SP ,, p >> :: lgc-lex-newline ( f , true ) else 3085 3086 ( p :: !"Illegal character: 0x" :: lgc-string2mixed ( c ) ) raise end define ]]" 3087 3088 Normalize newline sequences in the text "[[ f ]]" into newline characters. 3089 3090 \end{statements} 3091 3092 3093 3094 \subsection{Remove comments} 3095 3096 Logiweb sources may contain short and long comments. 3097 3098 A short comment starts with a multiquote followed by a semicolon and ends by a newline or the end of the file. Form feed (FF) and carriage return (CR) characters are converted to newlines, so a short comment may effectively be ended by an FF or CR. 3099 3100 A long comment starts with a multiquote followed by a left brace and ends by a multiquote followed by a right brace. The number of double quote characters of the closing escape sequence must match the number of double quote characters of the opening escape sequence. 3101 3102 All escape sequences inside short and long comments are ignored, except that a right brace escape sequence of the right size ends a long comment. In normal usage, the programmer is supposed to use escape sequences starting with two double quote characters. But a programmer may occasionally want to comment out a piece of source text which contains a mix of comments, code, and strings, in which case a long comment of starting with three double quote characters may be used. 3103 3104 \begin{statements} 3105 3106 \item "[[ late define lgc-lex-comment1 ( f ) as newline 3107 3108 if f atom then true else newline 3109 3110 if f head head != QQ then f head :: lgc-lex-comment1 ( f tail ) else newline 3111 3112 lgc-lex-comment2 ( f head first , 1 , f tail ) end define ]]" 3113 3114 Remove comments from the text "[[ f ]]". 3115 3116 \item "[[ late define lgc-lex-comment2 ( P , n , f ) as newline 3117 3118 if f atom then repeat ( n , << QQ ,, P >> ) else newline 3119 3120 let << c ,, p >> :: f = f in newline 3121 3122 if c = QQ then lgc-lex-comment2 ( P , n + 1 , f ) else newline 3123 3124 if n > 1 .and. c = !";" then lgc-lex-comment3 ( f ) else newline 3125 3126 if n > 1 .and. c = !"{" then lgc-lex-comment4 ( P , n , 0 , f ) else newline 3127 3128 append ( repeat ( n , << QQ ,, P >> ) , << c ,, p >> :: lgc-lex-comment1 ( f ) ) end define ]]" 3129 3130 Parse the start of a comment. Invoke "[[ lgc-lex-comment3 ( f ) ]]" for \verb+""!""!;+ comments and "[[ lgc-lex-comment4 ( P , n , 0 , f ) ]]" for \verb+""!""!{+ comments. 3131 3132 \item "[[ late define lgc-lex-comment3 ( f ) as newline 3133 3134 if f atom then true else newline 3135 3136 if f head head = LF then lgc-lex-comment1 ( f tail ) else newline 3137 3138 lgc-lex-comment3 ( f tail ) end define ]]" 3139 3140 Remove all characters up to next newline. 3141 3142 \item "[[ late define lgc-lex-comment4 ( P , n , m , f ) as newline 3143 3144 if f atom then ( P :: !"End of file in long comment" ) raise else newline 3145 3146 if f head head = QQ then lgc-lex-comment4 ( P , n , m + 1 , f tail ) else newline 3147 3148 if m = n .and. f head head = !"}" then lgc-lex-comment1 ( f tail ) else newline 3149 3150 lgc-lex-comment4 ( P , n , 0 , f tail ) end define ]]" 3151 3152 \end{statements} 3153 3154 3155 3156 \subsection{Parse escape sequences} 3157 3158 \begin{statements} 3159 3160 \item "[[ late define lgc-lex-escape1 ( f ) as newline 3161 3162 if f atom then true else newline 3163 3164 if f head head = QQ then lgc-lex-escape2 ( f head first , f tail ) else newline 3165 3166 f head :: lgc-lex-escape1 ( f tail ) end define ]]" 3167 3168 Convert escape sequences in the text "[[ f ]]". 3169 3170 \item "[[ late define lgc-lex-escape2 ( P , f ) as newline 3171 3172 if f atom then << QQ ,, P >> :: true else newline 3173 3174 if f head head = QQ then lgc-lex-escape3 ( P , f tail ) else newline 3175 3176 << QQ ,, P >> :: lgc-lex-escape1 ( f ) end define ]]" 3177 3178 Convert the text "[[ f ]]" which follows one double quote. 3179 3180 \item "[[ late define lgc-lex-escape3 ( P , f ) as newline 3181 3182 if f atom then ( P :: !"End of file in escape sequence" ) raise else newline 3183 3184 let << c >> :: f = f in newline 3185 3186 if c = QQ then lgc-lex-escape3 ( P , f ) else newline 3187 3188 << c - NULL ,, P >> :: lgc-lex-escape1 ( f ) end define ]]" 3189 3190 Convert the text "[[ f ]]" which follows a multiquote. 3191 3192 \end{statements} 3193 3194 3195 3196 \subsection{Collect structures} 3197 3198 \begin{statements} 3199 3200 \item "[[ late define lgc-lex-collect ( f ) as newline 3201 3202 if f atom then true else newline 3203 3204 let << c ,, P >> :: f = f in newline 3205 3206 if c < NULL then lgc-lex-collect1 ( c , P , f ) else newline 3207 3208 if c = SP then << SP ,, P >> :: lgc-lex-space ( f ) else newline 3209 3210 if c = LF then << SP ,, P >> :: lgc-lex-space ( f ) else newline 3211 3212 if c = QQ then lgc-lex-string ( lgc-esc-- , P , true , f ) else newline 3213 3214 << c ,, P >> :: lgc-lex-collect ( f ) end define ]]" 3215 3216 Collect tokens in the text "[[ f ]]". 3217 3218 \item "[[ late define lgc-lex-collect1 ( c , P , f ) as newline 3219 3220 if c = lgc-esc-- then lgc-lex-string ( lgc-esc-- , P , true , f ) else newline 3221 3222 if c = lgc-esc-# then lgc-lex-string ( lgc-esc-# , P , true , f ) else newline 3223 3224 if c = lgc-esc-$ then lgc-lex-string ( lgc-esc-$ , P , true , f ) else newline 3225 3226 if c = lgc-esc-P then lgc-lex-page ( P , true , true , f ) else newline 3227 3228 if c = lgc-esc-R then lgc-lex-ref ( P , true , true , f ) else newline 3229 3230 if c = lgc-esc-D then lgc-lex-def ( f ) else newline 3231 3232 if c = lgc-esc-B then lgc-lex-collect ( f ) else newline 3233 3234 if c = lgc-esc-. then ( lgc-esc-- :: P :: '' ) :: lgc-lex-collect ( f ) else newline 3235 3236 if c = lgc-esc-S then << lgc-esc-S ,, P >> :: lgc-lex-collect ( f ) else newline 3237 3238 if c = lgc-esc-N then << lgc-esc-N ,, P >> :: lgc-lex-collect ( f ) else newline 3239 3240 if c = lgc-esc-C then << lgc-esc-C ,, P >> :: lgc-lex-collect ( f ) else newline 3241 3242 ( P :: !"Unknown escape in body: 0x" :: lgc-string2mixed ( c + NULL ) ) raise end define ]]" 3243 3244 Collect tokens that start with escape sequences in the text "[[ f ]]". 3245 3246 \end{statements} 3247 3248 3249 3250 \subsection{Space parsing} 3251 3252 \begin{statements} 3253 3254 \item "[[ late define lgc-lex-space ( f ) as newline 3255 3256 let c = f head head in newline 3257 3258 if c = SP .or. c = LF then lgc-lex-space ( f tail ) else newline 3259 3260 lgc-lex-collect ( f ) end define ]]" 3261 3262 Skip spaces. 3263 3264 \end{statements} 3265 3266 3267 3268 \subsection{Page parsing} 3269 3270 \begin{statements} 3271 3272 \item "[[ late define lgc-lex-page ( P , r , R , f ) as newline 3273 3274 if f atom then lgc-lex-page1 ( P , r , R , true ) else newline 3275 3276 let << c ,, p >> :: f = f in newline 3277 3278 if c = LF .or. c = lgc-esc-n then lgc-lex-page1 ( P , r , R , f ) else newline 3279 3280 if c = QQ then lgc-lex-page ( P , true , r :: R , f ) else newline 3281 3282 if c >= NULL then lgc-lex-page ( P , c :: r , R , f ) else newline 3283 3284 ( p :: !"Unknown escape in page: 0x" :: lgc-string2mixed ( c + NULL ) ) raise end define ]]" 3285 3286 Parse page directive until the end of the line. Chop at quotes. Accumulate characters in "[[ r ]]" and accumulate interquote strings in "[[ R ]]". Finally call "[[ lgc-lex-page1 ( P , r , R , f ) ]]" where "[[ r ]]" is the page name and "[[ R ]]" is the list of prefixes. 3287 3288 \item "[[ late define lgc-lex-page1 ( P , r , R , f ) as newline 3289 3290 let r = lgc-lex-reverse-trim-contract ( r ) in newline 3291 3292 let R = lgc-lex-reverse-contract* ( R ) in newline 3293 3294 if r then ( P :: !"Empty page name" ) raise else newline 3295 3296 ( lgc-esc-P :: P :: r :: R ) :: lgc-lex-collect ( f ) end define ]]" 3297 3298 Normalize the page name "[[ r ]]" and the prefixes "[[ R ]]". Then continue lexical analysis. 3299 3300 \end{statements} 3301 3302 3303 3304 \subsection{Reference parsing} 3305 3306 \begin{statements} 3307 3308 \item "[[ late define lgc-lex-ref ( P , r , R , f ) as newline 3309 3310 if f atom then lgc-lex-ref1 ( P , r , R , true ) else newline 3311 3312 let << c ,, p >> :: f = f in newline 3313 3314 if c = LF .or. c = lgc-esc-n then lgc-lex-ref1 ( P , r , R , f ) else newline 3315 3316 if c = QQ then lgc-lex-ref ( P , true , r :: R , f ) else newline 3317 3318 if c >= NULL then lgc-lex-ref ( P , c :: r , R , f ) else newline 3319 3320 ( p :: !"Unknown escape in reference: 0x" :: lgc-string2mixed ( c + NULL ) ) raise end define ]]" 3321 3322 Parse reference until the end of the line. Chop at quotes. Accumulate characters in "[[ r ]]" and accumulate interquote strings in "[[ R ]]". Finally call "[[ lgc-lex-page1 ( P , r , R , f ) ]]" where "[[ r ]]" is the reference and "[[ R ]]" is the list of prefixes. 3323 3324 \item "[[ late define lgc-lex-ref1 ( P , r , R , f ) as newline 3325 3326 let r = lgc-lex-reverse-trim-contract ( r ) in newline 3327 3328 let R = lgc-lex-reverse-contract* ( R ) in newline 3329 3330 if r then ( P :: !"Empty reference" ) raise else newline 3331 3332 ( lgc-esc-R :: P :: r :: R ) :: lgc-lex-collect ( f ) end define ]]" 3333 3334 Normalize the reference "[[ r ]]" and the prefixes "[[ R ]]". Then continue lexical analysis. 3335 3336 \end{statements} 3337 3338 3339 3340 \subsection{Definition parsing} 3341 3342 \begin{statements} 3343 3344 \item "[[ late define lgc-lex-def ( f ) as newline 3345 3346 if f atom then true else lgc-lex-def0 ( f head first , f head first , true , true , f ) end define ]]" 3347 3348 \item "[[ late define lgc-lex-def0 ( P , Q , r , R , f ) as newline 3349 3350 if f atom then lgc-lex-def2 ( P , Q , r , R , f ) else newline 3351 3352 let << c ,, p >> :: f = f in newline 3353 3354 if c = LF .or. c = lgc-esc-n then newline 3355 3356 lgc-lex-def0 ( P , f head first , true , lgc-lex-def1 ( Q , r , R ) , f ) else newline 3357 3358 if c >= NULL then lgc-lex-def0 ( P , Q , c :: r , R , f ) else newline 3359 3360 if c = lgc-esc-P .or. c = lgc-esc-R .or. c = lgc-esc-D .or. c = lgc-esc-B then newline 3361 3362 lgc-lex-def2 ( P , Q , r , R , << c ,, p >> :: f ) else 3363 3364 ( p :: !"Unknown escape in definition: 0x" :: lgc-string2mixed ( c + NULL ) ) raise end define ]]" 3365 3366 Parse lines until the end of the definition section. Chop at newlines. Accumulate characters in "[[ r ]]" and accumulate lines in "[[ R ]]". Finally call "[[ lgc-lex-def2 ( P , Q , r , R , f ) ]]" where "[[ r ]]" is the reference and "[[ R ]]" is the list of prefixes. "[[ P ]]" is the start of the definition directive and "[[ Q ]]" is the start of the line. 3367 3368 \item "[[ late define lgc-lex-def1 ( Q , r , R ) as newline 3369 3370 let r = reverse ( r ) in newline 3371 3372 if R then << r >> else newline 3373 3374 let p = r head first in newline 3375 3376 let r = lgc-lex-trim-contract ( r ) in newline 3377 3378 if r = true then R else newline 3379 3380 if r tail != true .or. r head head != QQ then r :: R else newline 3381 3382 ( Q :: !"Construct must contain at least one proper character" ) raise end define ]]" 3383 3384 \item "[[ late define lgc-lex-def2 ( P , Q , r , R , f ) as newline 3385 3386 let R = lgc-lex-def1 ( Q , r , R ) in newline 3387 3388 let R = reverse ( R ) in newline 3389 3390 ( lgc-esc-D :: P :: R ) :: lgc-lex-collect ( f ) end define ]]" 3391 3392 \end{statements} 3393 3394 3395 3396 \subsection{String parsing} 3397 3398 \begin{statements} 3399 3400 \item "[[ late define lgc-lex-string ( C , P , r , f ) as newline 3401 3402 if f atom then ( P :: !"End of file in string" ) raise else newline 3403 3404 let << c ,, p >> :: f = f in newline 3405 3406 if c = QQ .or. c = lgc-esc-. then ( C :: P :: vt2vector ( reverse ( r ) ) ) :: lgc-lex-collect ( f ) else newline 3407 3408 if c >= NULL then lgc-lex-string ( C , P , c :: r , f ) else newline 3409 3410 if c = lgc-esc-- then lgc-lex-string ( C , P , r , f ) else newline 3411 3412 if c = lgc-esc-! then lgc-lex-string ( C , P , QQ :: r , f ) else newline 3413 3414 if c = lgc-esc-f then lgc-lex-string ( C , P , FF :: r , f ) else newline 3415 3416 if c = lgc-esc-n then lgc-lex-string ( C , P , LF :: r , f ) else newline 3417 3418 if c = lgc-esc-r then lgc-lex-string ( C , P , CR :: r , f ) else newline 3419 3420 if c = lgc-esc-t then lgc-lex-string ( C , P , TAB :: r , f ) else newline 3421 3422 if c = lgc-esc-x then lgc-lex-hex ( C , P , p , r , f ) else newline 3423 3424 ( p :: !"Unknown escape in string: 0x" :: lgc-string2mixed ( c + NULL ) ) raise end define ]]" 3425 3426 \item "[[ late define lgc-lex-hex ( C , P , Q , r , f ) as newline 3427 3428 if f atom then ( P :: !"End of file in string" ) raise else 3429 3430 let << c ,, p >> :: f = f in newline 3431 3432 if c = QQ then ( Q :: !"End of string in hex code" ) raise else newline 3433 3434 if c = !"." then lgc-lex-string ( C , P , r , f ) else newline 3435 3436 if c = SP .or. c = LF then lgc-lex-hex ( C , P , Q , r , f ) else newline 3437 3438 if !"0" <= c .and. c <= !"9" then lgc-lex-hex1 ( C , P , Q , c - !"0" , r , f ) else newline 3439 3440 if !"A" <= c .and. c <= !"F" then lgc-lex-hex1 ( C , P , Q , c - !"A" + Base , r , f ) else newline 3441 3442 if c >= NULL then ( p :: !"Invalid character in hex constant" ) raise else 3443 3444 ( P :: !"Unknown escape in string: 0x" :: lgc-string2mixed ( c + NULL ) ) raise end define ]]" 3445 3446 \item "[[ late define lgc-lex-hex1 ( C , P , Q , d , r , f ) as newline 3447 3448 if f atom then ( P :: !"End of file in string" ) raise else newline 3449 3450 let << c ,, p >> :: f = f in newline 3451 3452 if c = QQ then ( Q :: !"End of string in hex code" ) raise else newline 3453 3454 if c = !"." then ( Q :: !"Odd number of digits in hex code" ) raise else newline 3455 3456 if c = SP .or. c = LF then lgc-lex-hex1 ( C , P , Q , d , r , f ) else newline 3457 3458 if !"0" <= c .and. c <= !"9" then lgc-lex-hex ( C , P , Q , NULL + d * 16 + c - !"0" :: r , f ) else newline 3459 3460 if !"A" <= c .and. c <= !"F" then lgc-lex-hex ( C , P , Q , NULL + d * 16 + c - !"A" + Base :: r , f ) else newline 3461 3462 if c >= NULL then ( p :: !"Invalid character in hex constant" ) raise else 3463 3464 ( P :: !"Unknown escape in string: 0x" :: lgc-string2mixed ( c + NULL ) ) raise end define ]]" 3465 3466 \end{statements} 3467 3468 3469 3470 \subsection{Extract result of lexical analysis} 3471 3472 \begin{statements} 3473 3474 \item "[[ late define lgc-lex-extract-body ( f ) as newline 3475 3476 if f atom then true else newline 3477 3478 let c = f head head in newline 3479 3480 if c = lgc-esc-P .or. c = lgc-esc-R .or. c = lgc-esc-D then lgc-lex-extract-body ( f tail ) else newline 3481 3482 if c = SP then lgc-lex-extract-body1 ( f head , f tail ) else newline 3483 3484 "";if f tail atom .and. c = SP then true else newline 3485 3486 f head :: lgc-lex-extract-body ( f tail ) end define ]]" 3487 3488 Extract the body from the text "[[ f ]]" by disregarding page, reference, and definition directives. 3489 3490 \item "[[ late define lgc-lex-extract-body1 ( x , f ) as newline 3491 3492 if f atom then true else newline 3493 3494 let c = f head head in newline 3495 3496 if c = lgc-esc-P .or. c = lgc-esc-R .or. c = lgc-esc-D then lgc-lex-extract-body1 ( x , f tail ) else newline 3497 3498 if c = SP then x :: lgc-lex-extract-body ( f tail ) else newline 3499 3500 x :: lgc-lex-extract-body ( f ) end define ]]" 3501 3502 Extract the body from the text "[[ f ]]" knowing that it follows the space character "[[ x ]]". 3503 3504 \item "[[ late define lgc-lex-extract-other ( f , s ) as newline 3505 3506 if f atom then s else newline 3507 3508 let c = f head head in newline 3509 3510 if c = lgc-esc-P then lgc-lex-extract-page ( f , s ) else newline 3511 3512 if c = lgc-esc-R then lgc-lex-extract-ref ( f , s ) else newline 3513 3514 if c = lgc-esc-D then lgc-lex-extract-def ( f , s ) else newline 3515 3516 if c = lgc-esc-$ then lgc-lex-extract-include ( f , s ) else newline 3517 3518 if c = lgc-esc-# then lgc-lex-extract-include ( f , s ) else newline 3519 3520 lgc-lex-extract-other ( f tail , s ) end define ]]" 3521 3522 \item "[[ late define lgc-lex-extract-page ( f , s ) as newline 3523 3524 if s [[ !"page" ]] != true then ( f head first :: !"More than one page name found" ) raise else 3525 3526 let s = s [[ !"page" -> f head tail tail ]] in newline 3527 3528 lgc-lex-extract-other ( f tail , s ) end define ]]" 3529 3530 \item "[[ late define lgc-lex-extract-ref ( f , s ) as newline 3531 3532 let s = push ( s , !"bib" , f head tail tail ) in newline 3533 3534 lgc-lex-extract-other ( f tail , s ) end define ]]" 3535 3536 \item "[[ late define lgc-lex-extract-def ( f , s ) as newline 3537 3538 let ( true :: p :: r :: R ) :: f = f in newline 3539 3540 let s = push ( s , !"def" , ( p :: r ) :: R ) in newline 3541 3542 lgc-lex-extract-other ( f , s ) end define ]]" 3543 3544 \item "[[ late define lgc-lex-extract-include ( f , s ) as newline 3545 3546 let ( true :: p :: n ) :: f = f in newline 3547 3548 let s = push ( s , !"nincludes" , p :: n ) in newline 3549 3550 lgc-lex-extract-other ( f , s ) end define ]]" 3551 3552 \end{statements} 3553 3554 3555 3556 \subsection{Include processing} 3557 3558 The "[[ lgc-include-1 ( s ) ]]" function requests the include files and "[[ lgc-include-2 ( x , s ) ]]" processes them. 3559 3560 \begin{statements} 3561 3562 \item "[[ late define lgc-include-1 ( s ) as newline 3563 3564 let l = s [[ !"nincludes" ]] in newline 3565 3566 if l atom then lgc-load-1 ( s ) else newline 3567 3568 let ( true :: n ) :: l = l in newline 3569 3570 if .not. s [[ !"includes" ]] [[ n ]] then lgc-include-1 ( s [[ !"nincludes" -> l ]] ) else newline 3571 3572 let n = lgc-tilde-expand ( n , s [[ !"parameters" ]] ) in newline 3573 3574 let s = lgc-progress ( !"Reading file:" :: n , 3 , s ) in newline 3575 3576 let s = lgc-push-event ( s , fileTypeRead ( n ) ) in newline 3577 3578 lgc-exec-events ( s , lgc-include-2 ( x , s ) ) end define ]]" 3579 3580 \item "[[ late define lgc-include-2 ( x , s ) as newline 3581 3582 let << true ,, << true ,, t :: f >> >> = x in newline 3583 3584 let l = s [[ !"nincludes" ]] in newline 3585 3586 let ( p :: n ) :: l = l in newline 3587 3588 if t = FileTypeNonexistent then newline 3589 3590 lgc-error ( s , p , !"Could not find include file " :: n ) else newline 3591 3592 let s = s [[ !"nincludes" -> l ]] in newline 3593 3594 let s = s [[ << !"includes" ,, n >> => f ]] in newline 3595 3596 lgc-include-1 ( s ) end define ]]" 3597 3598 \end{statements} 3599 3600 3601 3602 " ]"\section{Loading}"[ " 3603 3604 \subsection{Load processing} 3605 3606 The "[[ lgc-load-1 ( s ) ]]" function requests all Logiweb pages transitively referenced by the page being translated. 3607 3608 The source text references other pages using \verb+""!""!R+ escape sequences. The reference following the \verb+""!""!R+ escape sequence may be: 3609 3610 \begin{description} 3611 3612 \item[A url] such as \url{http://logiweb.eu/logiweb/page/base/fixed/vector/vector.lgw} or \url{file:~/.logiweb/latest/base/rack.lgr} 3613 3614 \item[A page name] such as \url{name:base} 3615 3616 \end{description} 3617 3618 References which do not contain a colon character are taken to be page names, so \url{name:base} can be abbreviated as \url{base}. Names are looked up using the \verb+namepath+ as described later. 3619 3620 A url must have type \verb+http:+ or \verb+file:+ or \verb+lgw:+. An http url is retrieved using an http GET operation. A file url is looked up in the local file system. Tilde expansion is performed on file urls. An lgw url is looked up using the \verb+path+ as described later. 3621 3622 An http or file url must have extension \verb+.lgw+ or \verb+.lgr+ or \verb+.lgu+. The extension determines the format of the referenced page. A url with extension \verb+.lgw+, \verb+.lgr+, and \verb+.lgu+ contains a Logiweb vector, rack, and url, respectively. A Logiweb vector is a compact format suited for transmitting over the Internet which takes some time to translate to internal form. A Logiweb rack is a more extensive format suited for storing in the local file system which is faster to translate to internal format. A Logiweb url is a like a symbolic link in that it just contains the http url of the page to be fetched. 3623 3624 As mentioned, names are translated to pages using the \verb+namepath+. This is done by considering the elements of \verb+namepath+ one at a time and replacing the rightmost colon character of the element by the given name. The result must be a url which is then looked up. If successful, the page found is used. Otherwise, the next element of the \verb+namepath+ is tried. 3625 3626 Similarly, urls of type \verb+lgw:+ are looked up using the \verb+path+ variable by replacing the rightmost colon character of each element by the characters following \verb+lgw:+. In this case, however, the characters following \verb+lgw:+ must be a Logiweb reference expressed in mixed endian hexadecimal. In mixed endian hexadecimal, bytes are written in network byte order and each byte is written as two hexadecimal digits with the most significant digit first. 3627 3628 Once a page is retrieved, it will be in either \verb+.lgw+ or \verb+.lgr+ format. If it is in \verb+.lgw+ format, then its reference is extracted and an attempt is made to look it up in \verb+.lgr+ format using the \verb+path+. If that is successful, loading is based on the \verb+.lgr+ version. 3629 3630 Note that one should only retrieve pages in \verb+.lgr+ format from trusted locations and only over high bandwidth channels. In practice, most users will be happy just retrieving \verb+.lgr+ pages from their own cache. Whenever the Logiweb compiler has translated an \verb+.lgw+ page, it stores the \verb+.lgr+ equivalent in the users cache so that the time consuming translation is done once only. 3631 3632 Loading a page involves the following major steps: 3633 3634 \begin{description} 3635 3636 \item[Fetch] Tranlate the reference to a page in \verb+.lgw+ or \verb+.lgr+ format. 3637 3638 \item[Trisect] Do a first round of processing of the page. 3639 3640 \item[Traverse] Transitively load all pages referenced by the page. 3641 3642 \item[Codify] Do a second round of processing of the page. 3643 3644 \end{description} 3645 3646 3647 3648 \subsection{State entries} 3649 3650 A number of hooks of the state are used for keeping track of the loading process: 3651 3652 \begin{description} 3653 3654 \item "[[ s [[ !"cluster" ]] [[ r ]] ]]" The cache of the page with reference "[[ r ]]". This is the main result of loading. 3655 3656 \item "[[ s [[ !"stack" ]] ]]" List of list of not yet loaded pages. The element at the bottom of the stack is a list of urls/names. The other elements are lists of references. Set to "[[ true ]]" when all pages are loaded. 3657 3658 \item "[[ s [[ !"events" ]] ]]" List of output events in reverse order. 3659 3660 \item "[[ s [[ !"path" ]] ]]" Search path (from path or namepath option). 3661 3662 \item "[[ s [[ !"fetching" ]] ]]" The url being fetched. 3663 3664 \item "[[ s [[ !"suffix" ]] ]]" The suffix of the url being fetched (lgw or lgr or lgu) 3665 3666 \item "[[ s [[ !"type" ]] ]]" The type of the url being fetched (http or file) 3667 3668 \item "[[ s [[ !"vector" ]] ]]" The vector of the page that has been fetched. This is set only when a page has been found in .lgw format but a search for the same page in .lgr format is in progress. 3669 3670 \item "[[ s [[ !"refbib" ]] ]]" The bibliography as a list of references. 3671 3672 \end{description} 3673 3674 3675 3676 \subsection{Loading in more detail} 3677 3678 Loading of a Logiweb page is a process which transforms a Logiweb page into an in-memory \emph{rack} structure suited for computer processing. A \emph{rack} is an inhomogeneous array, i.e.\ an array "[[ c ]]" for which "[[ c [[ i ]] ]]" contains different kinds of information for different values of "[[ i ]]". Values of indices "[[ i ]]" are named \emph{hooks}, and we shall refer to "[[ c [[ i ]] ]]" as the value that hangs on the the hook "[[ i ]]". Racks correspond to record structures in e.g.\ C. The input to the load process may be: 3679 3680 \begin{itemize} 3681 3682 \item The Logiweb reference of the page. The reference of a page is a sequence of about 30 bytes which provides a world-wide unique identification of the page. 3683 3684 \item The page itself in lgw or lgr format. 3685 3686 \item The name of a file which contain the page in lgw or lgr format. 3687 3688 \item An http url which points to a file which contains the page in lgw format. 3689 3690 \item The name of the page which, combinted with the namepath argument of the compiler allows to locate a file which contains the page in lgw or lgr format. 3691 3692 \end{itemize} 3693 3694 When given a Logiweb reference as input, loading comprises the following steps: 3695 3696 \begin{description} 3697 3698 \item[Fetch] Translate the reference of a page into the vector of the page. The vector of the page is a sequence of bytes which encodes the page in a compact way suited for transmission over a network. Fetching a page comprises two activities: 3699 3700 \begin{description} 3701 3702 \item[Locate] Translate the reference of a page into an http URL suited for getting the page. 3703 3704 \item[Get] Receive the vector using an http GET operation. 3705 3706 \end{description} 3707 3708 \item[Trisect] Parse the vector of the page into a bibliography, a dictionary, and a flat body. The bibliography is a sequence of references. Reference zero (the first reference) of the bibliography is the reference of the page itself. The proper references (all but the first one) are pointers to other Logiweb pages. The dictionary is an association list which maps indexes to arities. Indexes as well as arities are natural numbers. A flat body is a sequence of unparsed bytes. 3709 3710 \item[Traverse] Recursively load the proper references of tbe bibliography. 3711 3712 \item[Codify] Parse the flat body, macro expand the body and harvest \emph{revelations} (i.e.\ \emph{definitions}, \emph{introductions}, and \emph{proclamations}) from the expanded tree, then verify the correctness of the page. We shall refer to the outcome of macro expansion and harvesting as the \emph{expansion} and \emph{codex}, respectively, of the page. The expansion resembles an S-expression like the body does. The codex is an associative structure containing all revelations in the expansion organized in a way that makes the revelations easy to access. We shall refer to the outcome of verification as a \emph{diagnose} which, if empty, indicates that the page is correct. Codification comprises the following activities: 3713 3714 \begin{description} 3715 3716 \item[Unpack] Parse the flat body and return a parse tree. We shall refer to the parse tree as the \emph{body} of the page. The body resembles a Lisp S-expression. 3717 3718 \item[Initialize] Construct an initial codex. The initial codex is empty if the bibliography contains more than one reference (i.e. contains at least one proper reference). Otherwise, the codex contains exactly one entry which proclaims a \emph{proclamation} symbol. The user can use the proclamation symbol to assign semantics to other symbols and thus bootstrap the Logiweb system. This is for experienced, determined users only. Other users just reference at least one other page and thus leaves the bootstrap to somebody else. 3719 3720 \item[Compile] Compile all value definitions in the codex and lazily verify the page. During the first iteration of the codification there are no value definitions in the codex so the compilation done in the first iteration is always trivial. 3721 3722 \item[Macro expand] Macro expand the page. First look for a macro expander in the codex of the page. If one is found, apply it. Otherwise, look for a macro expander in the first reference of the page. If one is found, apply it. Otherwise, use the identity function as macro expander, i.e.\ use the body unchanged as expansion. 3723 3724 \item[Harvest] Scan the expansion for revelation symbols, i.e.\ for symbols which are proclaimed to denote definition, introduction, or proclamation. Each time a revelation symbol is found, add one revelation to the codex. When encountering a symbol which is proclaimed to be a hiding symbol, do not scan the subtrees of the symbol. If harvesting changes the codex, reiterate from \emph{Compile} above. 3725 3726 \end{description} 3727 3728 \end{description} 3729 3730 After loading a page, one may do the following: 3731 3732 \begin{itemize} 3733 3734 \item Render the page. Rendering may result in a human readable version of the page as well as executables. 3735 3736 \item Verify the page. Verification is done lazily during codification, so one just needs to force evaluation of the diagnose to do verification. 3737 3738 \item Dump the page to cache. Before a page can be cached, verification has to be forced. 3739 3740 \end{itemize} 3741 3742 3743 3744 \subsection{Top level function} 3745 3746 The "[[ lgc-load-1 ( s ) ]]" function implements traversing in that it arranges that all transitively referenced pages are loaded. When invoked, lexical analysis has placed a structure of form "[[ << n :: p ,, *** >> ]]" in "[[ s [[ !"bib" ]] ]]" where "[[ n ]]" is the name of a directly referenced page and "[[ p ]]" is a list of prefixes for grammar construction. The "[[ s [[ !"bib" ]] ]]" list is in reverse order compared to the source file, so first task is to reverse it. Then "[[ lgc-heads ( b ) ]]" is used to extract the names, and the list of names is stacked. During loading, this list of names appear at the bottom of the stack. All other elements of the stack are lists of references. The actual stacking of "[[ lgc-heads ( b ) ]]" is done by "[[ lgc-load-fetch0 ( << lgc-heads ( b ) >> , s ) ]]". 3747 3748 The "[[ lgc-load-setpath ( s ) ]]" function sets "[[ s [[ !"path" ]] ]]" to the path relevant for the first element of the top element of the stack. When there is more than one element in the stack, the top element is a list of references and, hence, the relevant path is "[[ s [[ !"parameters" ]] [[ !"path" ]] ]]". If the stack has one element then, usually, the relevant path is "[[ s [[ !"parameters" ]] [[ !"namepath" ]] ]]". If the first element of the top element is an explicit Logiweb reference (starting with "[[ !"lgw:" ]]") then the relevant path is "[[ s [[ !"parameters" ]] [[ !"path" ]] ]]". The "[[ lgc-load-setpath ( s ) ]]" function is defined separately because it is needed more than one place. 3749 3750 \begin{statements} 3751 3752 \item "[[ late define lgc-load-1 ( s ) as newline 3753 3754 let b = reverse ( s [[ !"bib" ]] ) in newline 3755 3756 let s = s [[ !"bib" -> b ]] in newline 3757 3758 lgc-load-fetch0 ( << lgc-heads ( b ) >> , s ) end define ]]" 3759 3760 Reverse the bibliography "[[ b ]]" from lexical analysis, extract page names, and call "[[ lgc-load-fetch0 ( S , s ) ]]" to stack the list of page names and invoke fetching. 3761 3762 \item "[[ late define lgc-load-fetch0 ( S , s ) as newline 3763 3764 let s = s [[ !"stack" -> S ]] in newline 3765 3766 let s = lgc-load-setpath ( s ) in newline 3767 3768 lgc-load-fetch ( s ) end define ]]" 3769 3770 Initialize the stack and leave further work to "[[ lgc-load-fetch ( s ) ]]". 3771 3772 \item "[[ late define lgc-load-setpath ( s ) as newline 3773 3774 let r = s [[ !"stack" ]] in newline 3775 3776 let p = r head head in newline 3777 3778 if p then s else newline 3779 3780 let s = lgc-progress-fetch ( p , r , s ) in newline 3781 3782 if r tail pairp .or. lgc-prefix ( lgc-lgw-prefix , p ) then newline 3783 3784 s [[ !"path" -> s [[ !"parameters" ]] [[ !"path" ]] ]] else newline 3785 3786 s [[ !"path" -> s [[ !"parameters" ]] [[ !"namepath" ]] ]] end define ]]" 3787 3788 Set "[[ s [[ !"path" ]] ]]" to path or namepath argument as appropriate. 3789 3790 \item "[[ late define lgc-progress-fetch ( p , r , s ) as newline 3791 3792 if r tail then lgc-progress ( !"Fetching " :: p , 3 , s ) else newline 3793 3794 let P = !"lgw:" :: lgc-string2mixed ( p ) in newline 3795 3796 if s [[ !"cluster" ]] [[ p ]] = true then newline 3797 3798 lgc-progress ( !"Fetching " :: P , 3 , s ) else newline 3799 3800 lgc-progress ( !"Fetching " :: P , 4 , s ) end define ]]" 3801 3802 \item "[[ late define lgc-heads ( b ) as newline 3803 3804 if b atom then true else b head head :: lgc-heads ( b tail ) end define ]]" 3805 3806 Extract the references from the bibliography "[[ b ]]". 3807 3808 \end{statements} 3809 3810 3811 3812 \subsection{Constants} 3813 3814 \begin{statements} 3815 3816 \item "[[ late define lgc-file-prefix as vt2vector* ( !"file:" ) end define ]]" 3817 3818 \item "[[ late define lgc-http-prefix as vt2vector* ( !"http:" ) end define ]]" 3819 3820 \item "[[ late define lgc-//-prefix as vt2vector* ( !"//" ) end define ]]" 3821 3822 \item "[[ late define lgc-lgw-prefix as vt2vector* ( !"lgw:" ) end define ]]" 3823 3824 \item "[[ late define lgc-name-prefix as vt2vector* ( !"name:" ) end define ]]" 3825 3826 \item "[[ late define lgw-suffix as vt2vector* ( !"lgw" ) end define ]]" 3827 3828 \item "[[ late define lgr-suffix as vt2vector* ( !"lgr" ) end define ]]" 3829 3830 \item "[[ late define lgu-suffix as vt2vector* ( !"lgu" ) end define ]]" 3831 3832 \end{statements} 3833 3834 3835 3836 \subsection{Auxiliary functions} 3837 3838 \begin{statements} 3839 3840 \item "[[ late define lgc-tilde-expand1 ( n , s ) as newline 3841 3842 if n then true else newline 3843 3844 if n head != !"~" then n else newline 3845 3846 s [[ !"parameters" ]] [[ "home" ]] :: n tail end define ]]" 3847 3848 Tilde expansion when "[[ n ]]" is a list of singleton strings. 3849 3850 \item "[[ late define lgc-cwd-expand ( n , s ) as newline 3851 3852 let n = vt2vector* ( n ) in newline 3853 3854 if n head = !"/" then n else s [[ !"cwd" ]] :: !"/" :: n end define ]]" 3855 3856 Expand relative pathname into absolute pathname. If combined with tilde expansion, do tilde expansion first. 3857 3858 \item "[[ late define lgc-prefix ( x , y ) as newline 3859 3860 if x atom then true else newline 3861 3862 if y atom then false else newline 3863 3864 x head = y head .and. lgc-prefix ( x tail , y tail ) end define ]]" 3865 3866 Return "[[ true ]]" if the list "[[ x ]]" is a prefix of the list "[[ y ]]". 3867 3868 \item "[[ late define lgc-char-split ( c , a ) as lgc-char-split1 ( c , a , true ) end define ]]" 3869 3870 Split the list "[[ a ]]" at the element with value "[[ c ]]" and return a pair "[[ u :: v ]]" of the list preceeding and succeeding "[[ c ]]". If "[[ c ]]" does not occur in "[[ a ]]" then "[[ u ]]" is set to "[[ a ]]" and "[[ v ]]" to "[[ true ]]". 3871 3872 \item "[[ late define lgc-char-split1 ( c , a , r ) as newline 3873 3874 if a atom then reverse ( r ) :: true else newline 3875 3876 let C :: a = a in newline 3877 3878 if c = C then reverse ( r ) :: a else newline 3879 3880 lgc-char-split1 ( c , a , C :: r ) end define ]]" 3881 3882 Compute "[[ u :: v = lgc-char-split ( c , a ) ]]", accumulating "[[ u ]]" in "[[ r ]]" in reverse order. 3883 3884 \item "[[ late define lgc-replace-colon ( n , r ) as newline 3885 3886 vt2vector* ( lgc-replace-colon1 ( reverse ( n ) , r ) ) end define ]]" 3887 3888 Replace the rightmost colon character in "[[ n ]]" by "[[ r ]]". 3889 3890 \item "[[ late define lgc-replace-colon1 ( n , r ) as newline 3891 3892 if n then exception else newline 3893 3894 let c :: n = n in newline 3895 3896 if c = !":" then reverse ( n ) :: r else newline 3897 3898 lgc-replace-colon1 ( n , r ) :: c end define ]]" 3899 3900 Auxiliary function for computing "[[ lgc-replace-colon ( n , r ) ]]". 3901 3902 \item "[[ late define lgc-file-suffix ( n ) as newline 3903 3904 let n = reverse ( n ) in newline 3905 3906 let u :: v = lgc-char-split ( !"." , n ) in newline 3907 3908 reverse ( u ) end define ]]" 3909 3910 \end{statements} 3911 3912 3913 3914 \subsection{Message generators} 3915 3916 \begin{statements} 3917 3918 \item "[[ late define lgc-load-fetch-ref-failed ( r , s ) as newline 3919 3920 lgc-simple-error ( !"Could not load reference " :: r , s ) end define ]]" 3921 3922 Complain about a reference which could not be loaded. "[[ r ]]" is supposed to be the name of the reference as given in the source file or the mixed endian hexadecimal representation of an indirectly referenced page. 3923 3924 \item "[[ late define lgc-load-no-colon ( s ) as newline 3925 3926 let n = s [[ !"path" ]] head in newline 3927 3928 lgc-simple-error ( !"Missing colon in path or namepath element " :: n , s ) end define ]]" 3929 3930 All elements of the path and namepath parameters must contain at least one colon character. 3931 3932 \item "[[ late define lgc-wrong-suffix ( n , s ) as newline 3933 3934 let s = lgc-progress ( !"Illegal suffix in path or namepath element " :: n , 1 , s ) in newline 3935 3936 lgc-simple-error ( !"Only .lgw, .lgr, and .lgu are legal suffixes" , s ) end define ]]" 3937 3938 \item "[[ late define lgc-wrong-lgu-suffix ( n , s ) as newline 3939 3940 let s = lgc-progress ( !"Illegal suffix in lgu link: " :: n , 1 , s ) in newline 3941 3942 let s = lgc-progress ( !"Only .lgw and .lgu are legal suffixes" , 1 , s ) in newline 3943 3944 lgc-simple-error ( !"Source of link: " :: s [[ !"type" ]] :: !":" :: s [[ !"fetching" ]] , s ) end define ]]" 3945 3946 All elements of the path and namepath parameters must contain at least one colon character. 3947 3948 \item "[[ late define lgc-load-malformed-url ( n , s ) as newline 3949 3950 lgc-simple-error ( !"Malformed url: http:" :: n , s ) end define ]]" 3951 3952 Complain about a malformed http url. Some valid http urls read: 3953 3954 \begin{itemize} 3955 3956 \item \verb+//my.domain:8080/my/path.lgw+ 3957 3958 \item \verb+//my.domain/my/path.lgr+ 3959 3960 \end{itemize} 3961 3962 \item "[[ late define lgc-load-malformed-lgu ( n , s ) as newline 3963 3964 let s = lgc-progress ( !"Malformed lgu link: " :: n , 1 , s ) in newline 3965 3966 let s = lgc-progress ( !"Such links must start with 'http:'" , 1 , s ) in newline 3967 3968 lgc-simple-error ( !"Source of link: " :: s [[ !"type" ]] :: !":" :: s [[ !"fetching" ]] , s ) end define ]]" 3969 3970 Complain about a malformed lgu link. 3971 3972 \item "[[ late define lgc-load-malformed-page ( s ) as newline 3973 3974 lgc-simple-error ( !"Malformed page found at " :: s [[ !"type" ]] :: !":" :: s [[ !"fetching" ]] , s ) end define ]]" 3975 3976 Complain about a malformed page. 3977 3978 \item "[[ late define lgc-load-wrong-page ( s ) as newline 3979 3980 lgc-simple-error ( !"Wrong page found at " :: s [[ !"type" ]] :: !":" :: s [[ !"fetching" ]] , s ) end define ]]" 3981 3982 Complain about a malformed page. 3983 3984 \end{statements} 3985 3986 3987 3988 \subsection{Requesting pages} 3989 3990 The "[[ lgc-load-fetch ( s ) ]]" function initiates loading of the first element of the top element of the stack (if any). When done, the function invokes "[[ lgc-grammar ( s ) ]]". 3991 3992 When the stack has more than one element, the top element of the stack is a list of references. In that case, the first element of the top element is loaded using a call to "[[ lgc-load-fetch-ref ( r , s ) ]]". Otherwise, "[[ lgc-load-fetch-name ( s ) ]]" is used. That function dispatches on the url type of the reference which may be "[[ !"file:" ]]", "[[ !"http:" ]]", "[[ !"lgw:" ]]", or "[[ !"name:" ]]", defaulting to "[[ !"name:" ]]". 3993 3994 If the reference is given as an url of type "[[ !"file:" ]]" or "[[ "http:" ]]" then "[[ lgc-load-fetch-file ( r , s ) ]]" or "[[ lgc-load-fetch-http ( r , s ) ]]" is called. Otherwise, the reference is looked up using the path. If the path is empty, it has been exhausted. Otherwise, the next element of the path is tried. When the next element of the path is tried, the rightmost colon character of the path element is replaced by the name or reference to be looked up, and "[[ lgc-load-fetch-path ( n , s ) ]]" is called which dispatches on the url type of the resulting url. 3995 3996 \begin{statements} 3997 3998 \item "[[ late define lgc-load-fetch ( s ) as newline 3999 4000 let r = s [[ !"stack" ]] in newline 4001 4002 if r head .and. r tail then lgc-grammar ( s [[ !"stack" -> true ]] ) else newline 4003 4004 let v = s [[ !"vector" ]] in newline 4005 4006 if .not. v then lgc-load-fetch-ref ( lgw-parse-string ( v ) head , s ) else newline 4007 4008 if r head then lgc-load-codify ( s ) else newline 4009 4010 if r tail then lgc-load-fetch-name ( s ) else newline 4011 4012 if .not. s [[ !"cluster" ]] [[ r head head ]] then lgc-load-fetch0 ( r head tail :: r tail , s ) else newline 4013 4014 lgc-load-fetch-ref ( r head head , s ) end define ]]" 4015 4016 Find out whether or not we are done with loading. If we are done, invoke "[[ lgc-grammar ( s ) ]]". Otherwise, if we have already found the page in .lgw format, look for the page in .lgr format. Otherwise, if we are at the bottom of the stack, fetch a url/name, else fetch a reference. 4017 4018 \item "[[ late define lgc-load-fetch-name ( s ) as newline 4019 4020 let n = s [[ !"stack" ]] head head in newline 4021 4022 if lgc-prefix ( lgc-file-prefix , n ) then newline 4023 4024 lgc-load-fetch-file ( list-suffix ( n , 5 ) , s ) else newline 4025 4026 if lgc-prefix ( lgc-http-prefix , n ) then newline 4027 4028 lgc-load-fetch-http ( list-suffix ( n , 5 ) , s ) else newline 4029 4030 if lgc-prefix ( lgc-lgw-prefix , n ) then newline 4031 4032 lgc-load-fetch-ref1 ( list-suffix ( n , 4 ) , s ) else newline 4033 4034 if lgc-prefix ( lgc-name-prefix , n ) then newline 4035 4036 lgc-load-fetch-ref1 ( list-suffix ( n , 5 ) , s ) else newline 4037 4038 lgc-load-fetch-ref1 ( n , s ) end define ]]" 4039 4040 Dispatch on url type. 4041 4042 \item "[[ late define lgc-load-fetch-ref ( r , s ) as newline 4043 4044 lgc-load-fetch-ref1 ( lgc-string2mixed ( r ) , s ) end define ]]" 4045 4046 Fetch an indirectly referenced page. Indirectly referenced pages are always looked up using the mixed endian hexadecimal representation of the Logiweb reference of the page. 4047 4048 \item "[[ late define lgc-load-fetch-ref1 ( r , s ) as newline 4049 4050 let p = s [[ !"path" ]] in newline 4051 4052 let v = s [[ !"vector" ]] in newline 4053 4054 if p .and. v then lgc-load-fetch-ref-failed ( r , s ) else newline 4055 4056 if p then lgc-load-receive-lgw1 ( v , s [[ !"vector" -> true ]] ) else newline 4057 4058 let n prime :: p = p in newline 4059 4060 let e :: n = lgc-replace-colon ( vt2vector* ( n prime ) , r ) catch in newline 4061 4062 if e then lgc-load-no-colon ( s ) else newline 4063 4064 let t = lgc-file-suffix ( n ) in newline 4065 4066 if t != lgw-suffix .and. t != lgr-suffix .and. t != lgu-suffix then newline 4067 4068 lgc-wrong-suffix ( n prime , s ) else newline 4069 4070 let s = s [[ !"suffix" -> t ]] in newline 4071 4072 let s = s [[ !"path" -> p ]] in newline 4073 4074 if .not. v .and. t != lgr-suffix then lgc-load-fetch-ref1 ( r , s ) else newline 4075 4076 lgc-load-fetch-path ( n , s ) end define ]]" 4077 4078 Locate page using "[[ s [[ !"path" ]] ]]" where "[[ s [[ !"path" ]] ]]" is the namepath parameter if we are at the bottom of the stack and the path parameter otherwise. In the latter case, "[[ r ]]" is always a mixed endian hexadecimal logiweb reference. The function tries the next element of the path, if any. When the path is exhausted, the function checks if we have the page in .lgw format. If we have, then the function translates the .lgw format. If not, then the function issues an error message. When the path is not exhausted, the function tries the next path element but only accepts elements with suffix .lgr if we already have the page in .lgw format. 4079 4080 \item "[[ late define lgc-load-fetch-path ( n , s ) as newline 4081 4082 if lgc-prefix ( lgc-file-prefix , n ) then newline 4083 4084 lgc-load-fetch-file ( list-suffix ( n , 5 ) , s ) else newline 4085 4086 if lgc-prefix ( lgc-http-prefix , n ) then newline 4087 4088 lgc-load-fetch-http ( list-suffix ( n , 5 ) , s ) else newline 4089 4090 lgc-load-fetch-file ( n , s ) end define ]]" 4091 4092 After replacing the rightmost colon of the next path element by the name being looked up, dispatch on url type (\verb+file:+ of \verb+http:+, defaulting to \verb+file:+). 4093 4094 \item "[[ late define lgc-load-fetch-file ( n , s ) as newline 4095 4096 let s = s [[ !"fetching" -> n ]] in newline 4097 4098 let s = s [[ !"type" -> "file" ]] in newline 4099 4100 let n = lgc-tilde-expand1 ( n , s ) in newline 4101 4102 let s = lgc-progress ( !"Reading file:" :: n , 4 , s ) in newline 4103 4104 let s = lgc-push-event ( s , fileTypeRead ( n ) ) in newline 4105 4106 lgc-exec-events ( s , lgc-load-receive ( x , s ) ) end define ]]" 4107 4108 Request given file. 4109 4110 \item "[[ late define lgc-load-fetch-http ( n , s ) as newline 4111 4112 let s = s [[ !"fetching" -> n ]] in newline 4113 4114 let s = s [[ !"type" -> "http" ]] in newline 4115 4116 let s = lgc-progress ( !"Reading http:" :: n , 4 , s ) in newline 4117 4118 if .not. lgc-prefix ( lgc-//-prefix , n ) then newline 4119 4120 lgc-load-malformed-url ( n , s ) else newline 4121 4122 let d :: q = lgc-char-split ( !"/" , list-suffix ( n , 2 ) ) in newline 4123 4124 let d :: p = lgc-char-split ( !":" , d ) in newline 4125 4126 let p = if p then !"80" else p in newline 4127 4128 let x :: p = lgc-atoi ( p , true ) catch in newline 4129 4130 if x .or. p < 0 .or. p > 65535 then newline 4131 4132 lgc-load-malformed-url ( n , s ) else newline 4133 4134 let s = lgc-push-event ( s , tcpQuery ( d , p , 3 , 0 , "GET /" :: q ) ) in newline 4135 4136 lgc-exec-events ( s , lgc-load-receive ( x , s ) ) end define ]]" 4137 4138 Request given http url with a patience of $ 3 \cdot 10 ^ 0 $ seconds. 4139 4140 \end{statements} 4141 4142 4143 4144 \subsection{Receiving pages} 4145 4146 The "[[ lgc-load-receive ( x , s ) ]]" may or may not receive a page. If it receives nothing, it calls "[[ lgc-load-received-nothing ( s ) ]]". Otherwise, it dispatched on the type of the received data. 4147 4148 \begin{statements} 4149 4150 \item "[[ late define lgc-load-receive ( x , s ) as 4151 4152 let << true ,, << true ,, x >> >> = x in newline 4153 4154 let t = s [[ !"type" ]] in newline 4155 4156 if t = !"http" .and. x .or. t = !"file" .and. x head = FileTypeNonexistent then newline 4157 4158 lgc-load-received-nothing ( s ) else newline 4159 4160 let x = if t = !"file" then x tail else x in newline 4161 4162 let t = s [[ !"suffix" ]] in newline 4163 4164 if t = lgw-suffix then lgc-load-receive-lgw ( x , s ) else newline 4165 4166 if t = lgr-suffix then lgc-load-receive-lgr ( x , s ) else newline 4167 4168 if t = lgu-suffix then lgc-load-receive-lgu ( x , s ) else newline 4169 4170 lgc-panic ( !"Internal error in lgc-load-receive" ) end define ]]" 4171 4172 \item "[[ late define lgc-load-received-nothing ( s ) as newline 4173 4174 let n = s [[ !"stack" ]] head head in newline 4175 4176 if lgc-prefix ( lgc-file-prefix , n ) .or. lgc-prefix ( lgc-http-prefix , n ) then newline 4177 4178 lgc-load-fetch-ref-failed ( n , s ) else newline 4179 4180 lgc-load-fetch ( s ) end define ]]" 4181 4182 \item "[[ late define lgc-load-receive-lgw ( x , s ) as newline 4183 4184 let e :: r :: true = lgw-parse-string ( x ) catch in newline 4185 4186 if e .or. r = !"". .or. vector-index ( r , 0 ) != lgc-logiweb-version then lgc-load-received-nothing ( s ) else newline 4187 4188 let ( R :: B ) :: S = s [[ !"stack" ]] in newline 4189 4190 if lgc-wrong-ref ( r , R , S ) then lgc-load-wrong-page ( s ) else newline 4191 4192 if S != true .or. lgc-prefix ( lgc-lgw-prefix , R ) then lgc-load-receive-lgw1 ( x , s ) else newline 4193 4194 if s [[ !"cluster" ]] [[ r ]] != true then lgc-load-fetch0 ( B :: S , push ( s , !"refbib" , r ) ) else newline 4195 4196 let s = s [[ !"vector" -> x ]] in newline 4197 4198 let s = s [[ !"path" -> s [[ !"parameters" ]] [[ !"path" ]] ]] in newline 4199 4200 lgc-load-fetch ( s ) end define ]]" 4201 4202 Receive the fetched page in .lgw format. Parse the reference of the received page. If the version number is wrong, consider the page non-existent. Otherwise check that the page is the one requested and complain if not. If the page is requested by reference, go on load it. Otherwise, it is requested by name in which case it might already be in the cluster or may be available in lgr format. First check if it is in the cluster and go on if it is. Otherwise, search for the page in lgr format. 4203 4204 \item "[[ late define lgc-load-receive-lgw1 ( x , s ) as newline 4205 4206 let e :: c = lgw-trisect ( x ) catch in newline 4207 4208 if e then lgc-load-malformed-page ( s ) else newline 4209 4210 let r = c [[ 0 ]] in newline 4211 4212 let true :: b = c [[ r ]] [[ !"bibliography" ]] in newline 4213 4214 let ( R :: B ) :: S = s [[ !"stack" ]] in newline 4215 4216 let s = if S then push ( s , !"refbib" , r ) else s in newline 4217 4218 let s = s [[ << !"cluster" ,, r >> => c ]] in newline 4219 4220 let n = if S then R else !"lgw:" :: lgc-string2mixed ( r ) in newline 4221 4222 lgc-load-fetch0 ( b :: ( ( r :: !".lgw" :: n ) :: B ) :: S , s ) end define ]]" 4223 4224 Receive a page in lgw format, knowing that the reference is the one requested and that there is no easy way to process the page. In this case, trisect the page and fetch the pages in the bibliography. 4225 4226 \item "[[ late define lgc-logiweb-version as 1 end define ]]" 4227 4228 The current version of Logiweb. 4229 4230 \item "[[ late define lgc-wrong-ref ( r , R , S ) as newline 4231 4232 if .not. S then r != R else newline 4233 4234 if .not. lgc-prefix ( lgc-lgw-prefix , R ) then false else newline 4235 4236 list-suffix ( R , 4 ) != lgc-string2mixed ( r ) end define ]]" 4237 4238 The "[[ lgc-wrong-ref ( r , R , S ) ]]" function returns "[[ true ]]" if the references "[[ r ]]" and "[[ R ]]" differ. If we are at the top of the stack (i.e.\ if "[[ S ]]" is empty) then "[[ R ]]" is a bibliographic reference which can only be compared to "[[ r ]]" if it is of type "[[ !"lgw:" ]]". 4239 4240 \item "[[ late define lgc-load-receive-lgr ( x , s ) as newline 4241 4242 let s = s [[ !"vector" -> true ]] in newline 4243 4244 let e :: c = sl2rack ( x ) catch in newline 4245 4246 if e then lgc-load-malformed-page ( s ) else newline 4247 4248 let r :: b = c [[ !"bibliography" ]] in newline 4249 4250 let c = true [[ 0 -> r ]] [[ r -> c ]] in newline 4251 4252 let ( R :: B ) :: S = s [[ !"stack" ]] in newline 4253 4254 if lgc-wrong-ref ( r , R , S ) then lgc-load-wrong-page ( s ) else newline 4255 4256 let s = if S then push ( s , !"refbib" , r ) else s in newline 4257 4258 if .not. s [[ !"cluster" ]] [[ r ]] then lgc-load-fetch0 ( B :: S , s ) else newline 4259 4260 let s = s [[ << !"cluster" ,, r >> => c ]] in newline 4261 4262 let n = if S then R else !"lgw:" :: lgc-string2mixed ( r ) in newline 4263 4264 lgc-load-fetch0 ( b :: ( ( r :: !".lgr" :: n ) :: B ) :: S , s ) end define ]]" 4265 4266 Receive the fetched page in .lgr format. Clear "[[ s [[ !"vector" ]] ]]" to indicate that we no longer try to find the page in .lgr format. Unpack the rack of the fetched page, convert it to a cache, and store it in the cluster. Then unstack the page that has been found, stack the type of the page (.lgw) and stack the bibliography. Then go on fetching pages. 4267 4268 \item "[[ late define lgc-load-receive-lgu ( n , s ) as newline 4269 4270 let n = reverse ( lgc-trim-newline ( reverse ( n ) ) ) in newline 4271 4272 let t = lgc-file-suffix ( n ) in newline 4273 4274 if t != lgw-suffix .and. t != lgu-suffix then newline 4275 4276 lgc-wrong-lgu-suffix ( n , s ) else newline 4277 4278 let s = s [[ !"suffix" -> t ]] in newline 4279 4280 if lgc-prefix ( lgc-http-prefix , n ) then newline 4281 4282 lgc-load-fetch-http ( list-suffix ( n , 5 ) , s ) else newline 4283 4284 lgc-load-malformed-lgu ( n , s ) end define ]]" 4285 4286 \item "[[ late define lgc-trim-newline ( n ) as newline 4287 4288 let c = n head in newline 4289 4290 if c = LF .or. c = CR then lgc-trim-newline ( n tail ) else n end define ]]" 4291 4292 \end{statements} 4293 4294 4295 4296 \subsection{Codifying loaded pages}\label{sec:CodifyingLoadedPages} 4297 4298 Loading a page involves a first round of processing, loading transitively referenced pages, and a second round of processing. The functions in the following perform the second round of processing. 4299 4300 \begin{statements} 4301 4302 \item "[[ late define lgc-load-codify ( s ) as newline 4303 4304 let true :: ( ( r :: t :: n ) :: true ) :: true = s [[ !"stack" ]] in newline 4305 4306 let s = lgc-progress ( !"Codifying " :: n , 3 , s ) in newline 4307 4308 lgc-exec-events ( s , lgc-load-codify1 ( x , s ) ) end define ]]" 4309 4310 Extract the reference "[[ r ]]" and type "[[ t ]]" of the page to be processed, add a progress message, flush the event queue, and invoke "[[ lgc-load-codify1 ( x , s ) ]]". 4311 4312 \item "[[ late define lgc-load-codify1 ( x , s ) as newline 4313 4314 let true :: ( ( r :: t :: n ) :: s prime ) :: s prime prime = s [[ !"stack" ]] in newline 4315 4316 let s = s [[ !"stack" -> s prime :: s prime prime ]] in newline 4317 4318 if t = !".lgw" then lgc-load-codify-lgw ( r , s ) else newline 4319 4320 if t = !".lgr" then lgc-load-codify-lgr ( r , s ) else newline 4321 4322 lgc-panic ( !"Internal error in lgc-load-codify1" ) end define ]]" 4323 4324 Unstack the reference "[[ r ]]" and type "[[ t ]]" of the page to be processed. Dispatch on "[[ t ]]". 4325 4326 \item "[[ late define lgc-load-codify-lgw ( r , s ) as newline 4327 4328 let s = lgc-load-codify-closure ( r , s ) in newline 4329 4330 let c = s [[ !"cluster" ]] [[ r ]] in newline 4331 4332 let e :: c = lgw-codify ( r , c , s [[ !"verbose" ]] ) catch in newline 4333 4334 if e then lgc-proclaim-error ( c , s ) else newline 4335 4336 let s = s [[ << !"cluster" ,, r >> => c ]] in newline 4337 4338 let s = lgc-load-setpath ( s ) in newline 4339 4340 lgc-load-render ( r , s ) end define ]]" 4341 4342 Call "[[ lgc-load-codify-closure ( r , s ) ]]" to add racks of transitively referenced pages to "[[ s [[ !"cluster" ]] [[ r ]] ]]" and caches of transitively referenced pages to "[[ s [[ !"cluster" ]] [[ r ]] [[ r ]] [[ !"cluster" ]] ]]". Then use "[[ lgw-codify ( r , s , v ) ]]" to codify the page. 4343 4344 \item "[[ late define lgc-load-codify-lgr ( r , s ) as newline 4345 4346 let s = lgc-load-codify-closure ( r , s ) in newline 4347 4348 let c = s [[ !"cluster" ]] [[ r ]] in newline 4349 4350 let c = lgr-cache-restore ( c ) in newline 4351 4352 let s = s [[ << !"cluster" ,, r >> => c ]] in newline 4353 4354 let s = lgc-load-setpath ( s ) in newline 4355 4356 lgc-load-render ( r , s ) end define ]]" 4357 4358 Same as "[[ lgc-load-codify-lgw ( r , s ) ]]" but faster since we have all information except compiled code. 4359 4360 \item "[[ late define lgc-load-render ( r , s ) as newline 4361 4362 let s = s [[ !"reference" -> r ]] in newline 4363 4364 let e :: p = lgc-render-dirname ( r , s ) catch in newline 4365 4366 if e then lgc-rendering-no-colon ( s ) else newline 4367 4368 let p = p :: !"index.html" in newline 4369 4370 let s = lgc-progress ( !"Probing " :: p , 4 , s ) in newline 4371 4372 let s = lgc-push-event ( s , fileType ( p ) ) in newline 4373 4374 lgc-exec-events ( s , lgc-load-render1 ( x , s ) ) end define ]]" 4375 4376 Probe "[[ !"index.html" ]]" to see if referenced page has to be re-rendered. 4377 4378 \item "[[ late define lgc-load-render1 ( x , s ) as newline 4379 4380 let << true ,, << true ,, f >> >> = x in newline 4381 4382 let s = lgc-progress ( if f head = NULL then !"Not found" else !"Found" , 4 , s ) in newline 4383 4384 if f head != NULL then lgc-load-fetch ( s ) else newline 4385 4386 let r = s [[ !"reference" ]] in newline 4387 4388 let n = lgc-ref2vt ( r , s ) in newline 4389 4390 let s = lgc-progress ( !"Rendering " :: n , 3 , s ) in newline 4391 4392 lgc-exec-events ( s , lgc-render ( x , s ) ) end define ]]" 4393 4394 Re-render referenced page if needed. Else go on fetching. 4395 4396 \item "[[ late define lgc-load-codify-closure ( r , s ) as newline 4397 4398 let c = s [[ !"cluster" ]] in newline 4399 4400 let c = lgr-cluster-closure ( r , c ) in newline 4401 4402 s [[ !"cluster" -> c ]] end define ]]" 4403 4404 Supplement "[[ s [[ !"cluster" ]] [[ r ]] ]]" with racks and "[[ s [[ !"cluster" ]] [[ r ]] [[ r ]] [[ !"cluster" ]] ]]" with caches of transitively referenced pages. 4405 4406 \end{statements} 4407 4408 4409 4410 \subsection{Trisecting} 4411 4412 The "[[ lgw-trisect ( v ) ]]" function splits the list "[[ v ]]" of singleton strings in lgw format into bibliography, dictionary, and flat body and returns a cache "[[ c ]]" with the following properties: 4413 4414 \begin{itemize} 4415 4416 \item "[[ c [[ 0 ]] ]]" is the reference "[[ r ]]" of the page. 4417 4418 \item "[[ c [[ r ]] [[ !"vector" ]] ]]" is the vector "[[ v ]]" of the page. 4419 4420 \item "[[ c [[ r ]] [[ !"bibliography" ]] ]]" is the bibliography of the page. 4421 4422 \item "[[ c [[ r ]] [[ !"dictionary" ]] ]]" is the dictionary of the page. 4423 4424 \item "[[ c [[ r ]] [[ !"body" ]] ]]" is the flat (unparsed) body of the page. 4425 4426 \end{itemize} 4427 4428 \begin{statements} 4429 4430 \item "[[ late define lgw-parse-string ( v ) as newline 4431 4432 let n :: v = parse-card ( v ) in newline 4433 4434 lgw-parse-string1 ( n , v , true ) end define ]]" 4435 4436 Parse the string at the beginning of "[[ v ]]" and return "[[ c :: v prime ]]" where "[[ c ]]" is the string and "[[ v prime ]]" is the unparsed part of "[[ v ]]". A string comprises a cardinal "[[ n ]]" followed by "[[ n ]]" bytes. 4437 4438 \item "[[ late define lgw-parse-string1 ( n , v , r ) as newline 4439 4440 if n = 0 then vt2vector ( r ) :: v else newline 4441 4442 if v atom then exception else newline 4443 4444 lgw-parse-string1 ( n - 1 , v tail , r :: v head ) end define ]]" 4445 4446 Accumulate the result of "[[ lgw-parse-string ( v ) ]]" in "[[ r ]]". 4447 4448 \item "[[ late define lgw-parse-bibliography ( v ) as lgw-parse-bibliography1 ( true , v ) end define ]]" 4449 4450 Parse a bibliography where a bibliography is a list of strings terminated by an empty string. 4451 4452 \item "[[ late define lgw-parse-bibliography1 ( r , v ) as newline 4453 4454 let b :: v = lgw-parse-string ( v ) in newline 4455 4456 if b = !"". then reverse ( r ) :: v else newline 4457 4458 lgw-parse-bibliography1 ( b + 0 :: r , v ) end define ]]" 4459 4460 Accumulate the result of "[[ lgw-parse-bibliography ( v ) ]]" in "[[ r ]]". 4461 4462 Using "[[ b + 0 ]]" instead of "[[ b ]]" above forces bibliographic entries to be stored as integers rather than vectors internally. That is done to circumvent a bug in the logiweb-0.1.x compiler. 4463 4464 \item "[[ late define lgw-parse-dictionary ( v ) as lgw-parse-dictionary1 ( true [[ 0 -> 0 ]] , v ) end define ]]" 4465 4466 Parse a dictionary where a dictionary is a list "[[ << i_1 ,, a_1 ,, ... >> ]]" of pairs of cardinals ended by a zero cardinal. Return the dictionary as an array which maps indices "[[ i_n ]]" to arities "[[ a_n ]]". It is understood that index 0 maps to arity 0. 4467 4468 \item "[[ late define lgw-parse-dictionary1 ( r , v ) as newline 4469 4470 let i :: v = parse-card ( v ) in newline 4471 4472 if i = 0 then r :: v else newline 4473 4474 let a :: v = parse-card ( v ) in newline 4475 4476 lgw-parse-dictionary1 ( r [[ i -> a ]] , v ) end define ]]" 4477 4478 Accumulate the result of "[[ lgw-parse-dictionary ( v ) ]]" in "[[ r ]]". 4479 4480 \item "[[ late define lgw-trisect ( V ) as newline 4481 4482 let b :: v = lgw-parse-bibliography ( V ) in newline 4483 4484 let r = b head in newline 4485 4486 let c = true [[ 0 -> r ]] in newline 4487 4488 let c = c [[ << r ,, !"vector" >> => vt2vector ( V ) ]] in newline 4489 4490 let c = c [[ << r ,, !"bibliography" >> => b ]] in newline 4491 4492 let d :: v = lgw-parse-dictionary ( v ) in newline 4493 4494 c [[ << r ,, !"dictionary" >> => d ]] [[ << r ,, !"body" >> => v ]] end define ]]" 4495 4496 Trisect the list "[[ v ]]" of singleton strings in lgw format into bibliography, dictionary, and flat body, and produce a cache "[[ c ]]" containing them. 4497 4498 \end{statements} 4499 4500 4501 4502 \subsection{Codifying} 4503 4504 The "[[ lgw-codify ( r , c , v ) ]]" function takes a reference "[[ r ]]" and a cache "[[ c ]]" as input and codifies the flat body found in it. The "[[ v ]]" parameter defines the verbosity (2- means silent, 3 means some output, 4+ means all output). The cache "[[ c ]]" is expected to contain the following: 4505 4506 \begin{itemize} 4507 4508 \item "[[ c [[ 0 ]] ]]": The reference of the page, i.e.\ a copy of "[[ r ]]" 4509 4510 \item "[[ c [[ r ]] [[ !"bibliography" ]] ]]": The bibliography of the page. 4511 4512 \item "[[ c [[ r ]] [[ !"dictionary" ]] ]]": The dictionary of the page. 4513 4514 \item "[[ c [[ r ]] [[ !"body" ]] ]]": The flat body of the page. 4515 4516 \item "[[ c [[ r ]] [[ !"cluster" ]] [[ r prime ]] ]]": The cache of page "[[ r prime ]]" provided "[[ r prime ]]" is in the transitive irreflexive bibliography of page "[[ r ]]". 4517 4518 \item "[[ c [[ r prime ]] ]]": The rack of page "[[ r prime ]]" provided "[[ r prime ]]" is in the transitive irreflexive bibliography of page "[[ r ]]". 4519 4520 \end{itemize} 4521 4522 The "[[ lgw-codify ( r , c , v ) ]]" function returns a cache "[[ c prime ]]" in which the following branches are changed: 4523 4524 \begin{itemize} 4525 4526 \item "[[ c [[ r ]] [[ !"body" ]] ]]": The body of the page. 4527 4528 \item "[[ c [[ r ]] [[ !"expansion" ]] ]]": The macro expanded body of the page. 4529 4530 \item "[[ c [[ r ]] [[ !"codex" ]] ]]": The codex of the page. 4531 4532 \item "[[ c [[ r ]] [[ !"code" ]] ]]": Compiled versions of value definitions in the codex. 4533 4534 \item "[[ c [[ r ]] [[ !"diagnose" ]] ]]": The diagnose of the page. The diagnose is maptagged and is computed lazily. In other words, verification is not done by "[[ lgw-codify ( r , c , v ) ]]". Rather, verification occurs when evaluation of the diagnose is forced by untagging it. The page is considered correct if the untagged diagnose is "[[ true ]]". 4535 4536 \end{itemize} 4537 4538 \begin{statements} 4539 4540 \item "[[ late define lgw-codify ( r , c , v ) as newline 4541 4542 lgc-print ( 4 <= v , " Unpack" ) .then. newline 4543 4544 let c = lgw-codify-unpack ( r , c ) in newline 4545 4546 lgc-print ( 4 <= v , " Initialize" ) .then. newline 4547 4548 let c = lgw-codify-initialize ( r , c ) in newline 4549 4550 lgw-codify1 ( r , c , v , 1 ) end define ]]" 4551 4552 \item "[[ late define lgw-codify1 ( r , c , v , n ) as newline 4553 4554 lgc-print ( 3 <= v , lgc-ordinal ( n ) :: " reading" ) .then. newline 4555 4556 lgc-print ( 4 <= v , " Compile" ) .then. newline 4557 4558 let c = compile ( c ) in newline 4559 4560 lgc-print ( 4 <= v , " Expand" ) .then. newline 4561 4562 let t = lgw-codify-expand ( r , c ) in newline 4563 4564 let C = c [[ << r ,, !"expansion" >> => t ]] in newline 4565 4566 let C = C [[ << r ,, !"codex" >> => true ]] in newline 4567 4568 lgc-print ( 4 <= v , " Harvest" ) .then. newline 4569 4570 let C = lgw-codify-harvest ( r , t , c , C ) in newline 4571 4572 lgc-print ( 4 <= v , " Compare" ) .then. newline 4573 4574 if c [[ r ]] [[ !"codex" ]] = C [[ r ]] [[ !"codex" ]] then compile ( C ) else newline 4575 4576 lgw-codify1 ( r , C , v , n + 1 ) end define ]]" 4577 4578 \end{statements} 4579 4580 4581 4582 \subsection{Unpacking} 4583 4584 The "[[ lgw-codify-unpack ( r , c ) ]]" function parses the flat body "[[ c [[ !"body" ]] ]]", stores the result back in "[[ c [[ !"body" ]] ]]", and returns the modified "[[ c ]]". 4585 4586 \begin{statements} 4587 4588 \item "[[ late define lgw-codify-unpack ( r , c ) as newline 4589 4590 let u = lgw-codify-unpacker ( r , c ) in newline 4591 4592 if u then lgw-codify-unpack1 ( r , c ) else newline 4593 4594 let v = c [[ r ]] [[ !"body" ]] in newline 4595 4596 let c = c [[ << r ,, !"body" >> => true ]] in newline 4597 4598 let t = prune ( ( eval ( u third , true , c ) apply c maptag apply v maptag ) untag , c ) in newline 4599 4600 c [[ << r ,, !"body" >> => t ]] end define ]]" 4601 4602 \item "[[ late define lgw-codify-unpacker ( r , c ) as newline 4603 4604 let b = c [[ r ]] [[ !"bibliography" ]] first in newline 4605 4606 if b then true else c [[ b ]] [[ !"codex" ]] [[ b ]] [[ 0 ]] [[ 0 ]] [[ !"unpack" ]] end define ]]" 4607 4608 \item "[[ late define lgw-codify-unpack1 ( r , c ) as newline 4609 4610 let v = c [[ r ]] [[ !"body" ]] in newline 4611 4612 let a = lgw-make-dict ( r , c ) in newline 4613 4614 let t = lgw-parse-tree ( a , << r >> , v ) in newline 4615 4616 c [[ << r ,, !"body" >> => t head ]] end define ]]" 4617 4618 Extract the flat body of page "[[ r ]]" from the cache "[[ c ]]". Parse it into a tree and store it back as the body of the tree. For the sake of efficiency, the bibliography "[[ b ]]" and the length "[[ l ]]" of the bibliography are computed once. Debugging information is accumulated in "[[ d ]]". 4619 4620 \item "[[ late define lgw-make-dict ( r , c ) as newline 4621 4622 let b = c [[ r ]] [[ !"bibliography" ]] in newline 4623 4624 let l = length ( b ) in lgw-make-dict1 ( 0 , b , l , c , true ) end define ]]" 4625 4626 Convert the bibliography "[[ b ]]" which has length "[[ l ]]" into an array "[[ a ]]" for which "[[ a [[ R + l * i ]] = << r ,, i ,, n >> ]]" where "[[ R ]]" is the relative reference of a symbol (the position of the reference in the bibliography), "[[ i ]]" is the index of a symbol, "[[ r ]]" is the absolute references of the symbol, and "[[ n ]]" is the arity of the symbol. 4627 4628 \item "[[ late define lgw-make-dict1 ( R , b , l , c , a ) as newline 4629 4630 if b atom then a else newline 4631 4632 let a = lgw-make-dict2 ( R , b head , l , c [[ b head ]] [[ !"dictionary" ]] , a ) in newline 4633 4634 lgw-make-dict1 ( R + 1 , b tail , l , c , a ) end define ]]" 4635 4636 \item "[[ late define lgw-make-dict2 ( R , r , l , d , a ) as newline 4637 4638 if d atom then a else newline 4639 4640 if .not. d head intp then lgw-make-dict2 ( R , r , l , d head , lgw-make-dict2 ( R , r , l , d tail , a ) ) else newline 4641 4642 let i = d head in newline 4643 4644 a [[ 1 + R + l * i -> << r ,, i ,, d tail >> ]] end define ]]" 4645 4646 Add the symbols in the dictionary "[[ d ]]" to the array "[[ a ]]" described under "[[ lgw-make-dict ( r , c ) ]]". "[[ R ]]" and "[[ r ]]" are the relative and absolute reference, respectively, of the page being processed and "[[ l ]]" is the length of the bibliography. 4647 4648 \item "[[ late define lgw-parse-tree ( a , d , v ) as newline 4649 4650 let c :: v = parse-card ( v ) in newline 4651 4652 if c = 0 then lgw-parse-tree-string ( d , v ) else newline 4653 4654 let << r ,, i ,, n >> = a [[ c ]] in newline 4655 4656 let t = lgw-parse-tree* ( a , n , 0 , d , v , true ) in newline 4657 4658 ( << r ,, i ,, d >> :: t head ) :: t tail end define ]]" 4659 4660 Convert the flat tree "[[ v ]]" into a tree. "[[ d ]]" must be debugging information to be installed in the tree. "[[ a ]]" must be the value of "[[ lgw-make-dict ( r , c ) ]]" where "[[ c ]]" is the cache of the page. 4661 4662 \item "[[ late define lgw-parse-tree* ( a , n , i , d , v , r ) as newline 4663 4664 if i >= n then reverse ( r ) :: v else newline 4665 4666 let t :: v = lgw-parse-tree ( a , i :: d , v ) in newline 4667 4668 lgw-parse-tree* ( a , n , i + 1 , d , v , t :: r ) end define ]]" 4669 4670 Parse "[[ n ]]" trees in the vector "[[ v ]]". "[[ d ]]" and "[[ a ]]" are described under the previous function. "[[ i ]]" counts from "[[ 0 ]]" to "[[ n - 1 ]]". The list of trees is accumulated in "[[ t ]]" in reverse order. 4671 4672 \item "[[ late define lgw-parse-tree-string ( d , v ) as newline 4673 4674 let s :: v = lgw-parse-string ( v ) in newline 4675 4676 << << 0 ,, s ,, d >> >> :: v end define ]]" 4677 4678 \end{statements} 4679 4680 4681 4682 \subsection{Initializing} 4683 4684 The "[[ lgw-codify-initialize ( r , c ) ]]" function stores an initial codex in "[[ c [[ r ]] [[ !"codex" ]] ]]" and returns the modified cache "[[ c ]]". 4685 4686 \begin{statements} 4687 4688 \item "[[ late define lgw-codify-initialize ( r , c ) as newline 4689 4690 if c [[ r ]] [[ !"bibliography" ]] tail pairp then c else newline 4691 4692 c [[ << r ,, !"codex" ,, r ,, 1 ,, 0 ,, !"definition" >> => << << 0 ,, !"proclaim" >> >> ]] end define ]]" 4693 4694 \end{statements} 4695 4696 4697 4698 \subsection{Macro expanding} 4699 4700 The "[[ lgw-codify-expand ( r , c ) ]]" function macro expands "[[ c [[ r ]] [[ !"body" ]] ]]" and returns the expansion. 4701 4702 \begin{statements} 4703 4704 \item "[[ late define lgw-codify-expand ( r , c ) as newline 4705 4706 let d = c [[ r ]] [[ !"codex" ]] [[ r ]] [[ 0 ]] [[ 0 ]] [[ !"macro" ]] in newline 4707 4708 if d pairp then lgw-codify-expand1 ( d , c ) else newline 4709 4710 let b = c [[ r ]] [[ !"bibliography" ]] first in 4711 4712 if b then c [[ r ]] [[ !"body" ]] else newline 4713 4714 let d = c [[ b ]] [[ !"codex" ]] [[ b ]] [[ 0 ]] [[ 0 ]] [[ !"macro" ]] in newline 4715 4716 if d pairp then lgw-codify-expand1 ( d , c ) else c [[ r ]] [[ !"body" ]] end define ]]" 4717 4718 Macro expand page "[[ r ]]" in cache "[[ c ]]". First look up the macro expander of the page itself and call it "[[ d ]]". If found, apply it. Else look up the macro expander of the bed page "[[ b ]]" and call it "[[ d ]]". If found, apply it. Else, default to the identity macro expander and return the body of the page. 4719 4720 \item "[[ late define lgw-codify-expand1 ( d , c ) as newline 4721 4722 let f = eval ( d third , true , c ) in newline 4723 4724 let t = ( f apply c maptag ) untag in newline 4725 4726 prune ( t , c ) end define ]]" 4727 4728 Evaluate right hand side of the macro expander definition "[[ d ]]". Then apply the result to the cache "[[ c ]]" and prune the outcome. 4729 4730 \end{statements} 4731 4732 4733 4734 \subsection{Harvesting} 4735 4736 The "[[ lgw-codify-harvest ( r , t , c , C ) ]]" function harvests the term "[[ t ]]" from page "[[ r ]]" in cache "[[ c ]]" and accumulate the result in the new cache "[[ C ]]" which is eventually returned. 4737 4738 \begin{statements} 4739 4740 \item "[[ late define lgw-codify-harvest ( r , t , c , C ) as newline 4741 4742 let d = c [[ t ref ]] [[ !"codex" ]] [[ t ref ]] [[ t idx ]] [[ 0 ]] [[ !"definition" ]] in newline 4743 4744 if d then lgw-codify-harvest* ( r , t tail , c , C ) else newline 4745 4746 if d idx = !"hide" then C else newline 4747 4748 if d idx = !"proclaim" then lgw-codify-proclaim ( r , t , C ) else newline 4749 4750 if ( d idx = !"define" .or. d idx = !"introduce" ) then lgw-codify-define ( r , t , c , C ) else C end define ]]" 4751 4752 Harvest the term "[[ t ]]" from page "[[ r ]]" in cache "[[ c ]]". Accumulate the result in the new cache "[[ C ]]". In the first line, store the definition aspect of the root of the tree "[[ t ]]" in "[[ d ]]". If "[[ d ]]" is empty then recurse. 4753 4754 \item "[[ late define lgw-codify-harvest* ( r , t , c , C ) as newline 4755 4756 if t atom then C else lgw-codify-harvest* ( r , t tail , c , lgw-codify-harvest ( r , t head , c , C ) ) end define ]]" 4757 4758 \item "[[ late define lgw-proclaim-array as true 4759 [[ newline !"apply" -> 2 :: !"value" ]] 4760 [[ newline !"lambda" -> 2 :: !"value" ]] 4761 [[ newline !"true" -> 0 :: !"value" ]] 4762 [[ newline !"if" -> 3 :: !"value" ]] 4763 [[ newline !"quote" -> 1 :: !"value" ]] 4764 [[ newline !"proclaim" -> 2 :: !"definition" ]] 4765 [[ newline !"define" -> 3 :: !"definition" ]] 4766 [[ newline !"introduce" -> 3 :: !"definition" ]] 4767 [[ newline !"hide" -> true :: !"definition" ]] end define ]]" 4768 4769 \item "[[ late define lgw-codify-proclaim ( r , t , C ) as newline 4770 4771 if t second ref != 0 then C else newline 4772 4773 if t first ref != r then t raise else newline 4774 4775 let d = lgw-proclaim-array [[ t second idx ]] in newline 4776 4777 if d .or. .not. d head .and. d head != length ( t first tail ) then newline 4778 4779 t raise else newline 4780 4781 if t second ref != 0 then t raise else newline 4782 4783 C [[ << r ,, !"codex" ,, r ,, t first idx ,, 0 ,, d tail >> => << << 0 ,, t second idx >> >> ]] end define ]]" 4784 4785 Add the proclamation "[[ t ]]" from page "[[ r ]]" to the cache "[[ C ]]". 4786 4787 \item "[[ late define lgw-tree2aspect ( t , c ) as newline 4788 4789 if t ref = 0 then t else c [[ t ref ]] [[ !"codex" ]] [[ t ref ]] [[ t idx ]] [[ 0 ]] [[ !"message" ]] third end define ]]" 4790 4791 Convert the term "[[ t ]]" into the aspect represented by the term according to the cache "[[ c ]]". If "[[ t ]]" is a string, then "[[ t ]]" is itself that aspect. Otherwise, the aspect represented by "[[ t ]]" is looked up in "[[ c ]]". If "[[ t ]]" does not represent any aspect the "[[ true ]]" is returned. 4792 4793 \item "[[ late define lgw-codify-define ( r , t , c , C ) as newline 4794 4795 let a = lgw-tree2aspect ( t first , c ) in newline 4796 4797 if a then C else newline 4798 4799 C [[ << r ,, !"codex" ,, t second ref ,, t second idx ,, a ref ,, a idx >> => t ]] end define ]]" 4800 4801 Find the aspect of the definition "[[ t ]]" from page "[[ r ]]" in the cache "[[ c ]]" and then accumulate the definition in "[[ C ]]". 4802 4803 \end{statements} 4804 4805 4806 4807 " ]"\section{Grammars}\label{sec:Grammars}"[ " 4808 4809 The Logiweb parser "[[ lgc-parse ( g , a ) ]]" converts a list "[[ a ]]" of tokens to a parse tree as specified by the grammar "[[ g ]]". We describe tokens and grammars in more detail in the following sections. 4810 4811 4812 4813 \subsection{Tokens} 4814 4815 A Logiweb token can be one of the following: 4816 4817 \begin{itemize} 4818 4819 \item A byte 4820 4821 \item A string 4822 4823 \item A binary include 4824 4825 \item A text include 4826 4827 \item An \verb+""!""!S+ escape sequence 4828 4829 \item An \verb+""!""!C+ escape sequence 4830 4831 \item An \verb+""!""!N+ escape sequence 4832 4833 \end{itemize} 4834 4835 Bytes from the source text are represented as singleton strings which in turn are represented by integers. As an example, a capital A in the input is represented by the singleton string "[[ !"A" ]]" which in turn is represented by the integer "[[ 65 + 256 = 321 ]]" where 65 is the Unicode UTF-8 representation of a capital A. Hence, a capital A in the input is represented by one token and that token has value 321. 4836 4837 As another example, a capital \AE\ (Unicode \verb+C6+) is represented by a \verb+C3+ (195) byte followed by a \verb+86+ (134) byte in UTF-8. Thus, a capital \AE\ is represented by two tokens, namely a "[[ 195 + 256 = 451 ]]" token followed by a "[[ 134 + 256 = 390 ]]" token. 4838 4839 Note that in the Logiweb programming language, a single character is represented by one or more tokens. This is opposite to languages like C where a token represents one or more characters. 4840 4841 A string is represented as a pair "[[ lgc-esc-- :: S ]]" where "[[ S ]]" is the string. As an example, \verb+""!ABC""!+ in the source text is represented by a token with value "[[ lgc-esc-- :: !"ABC" ]]". Recall that the value of "[[ lgc-esc-- ]]" is 45 where 45 is the Unicode of a hyphen. 4842 4843 A binary include is represented as the pair "[[ lgc-esc-# :: S ]]" where "[[ S ]]" is the name of the file to be included. Such a binary include represents a string whose bytes are taken verbatim from the included file. As an example, \verb+""!""!#ABC""!+ in the source text is represented by a token with value "[[ lgc-esc-# :: !"ABC" ]]". That token represents a string whose bytes are taken from the file named \verb+ABC+. 4844 4845 A text include is represented as the pair "[[ lgc-esc-$ :: S ]]" where "[[ S ]]" is the name of the file to be included. Such a text include represents a string whose bytes are taken from the included file except that carriage return and line feed characters are parsed as in Section \ref{sec:ByteParsing}. Note that in order to ensure cross platform interoperability, Logiweb marks the end of a line by a line feed character regardless of what the underlying operating system does. 4846 4847 The escape sequences \verb+""!""!S+ is represented by a token with value "[[ lgc-esc-S ]]" which in turn equals the Unicode of the character S. An "[[ lgc-esc-S ]]" token represents the entire source text represented as a string. This corresponds to a binary include of the source file. 4848 4849 The escape sequences \verb+""!""!C+ is represented by a token with value "[[ lgc-esc-C ]]" which in turn equals the Unicode of the character C. An "[[ lgc-esc-C ]]" token represents a list of charge definitions. 4850 4851 The escape sequences \verb+""!""!N+ is represented by a token with value "[[ lgc-esc-N ]]" which in turn equals the Unicode of the character N. An "[[ lgc-esc-N ]]" token represents a list of name definitions. 4852 4853 4854 4855 \subsection{Source grammars} 4856 4857 In the Logiweb programming language, grammars are defined in the source text. During lexical analysis, the grammar is extracted from the source file and converted into a \emph{trie} structure. A trie structure is essentially defined recursively as an array which maps integers to trie structures. 4858 4859 Hence, grammars exist in two forms: externally in the source text and internally as trie structures. We shall refer to these two forms as source and trie grammars, respectively. 4860 4861 A source grammar may look thus: 4862 4863 \begin{verbatim} 4864 ""!""!D 0 4865 x 4866 y 4867 z 4868 ""!""!D 4 4869 ""! + ""! 4870 \end{verbatim} 4871 4872 The source grammar above defines four constructs, "[[ x ]]", "[[ y ]]", "[[ z ]]", and "[[ *** + *** ]]". 4873 4874 Furthermore, a source grammar assigns an \emph{charge} (c.f.\ Section \ref{sec:Associativities}) to each construct. The source grammar above assigns charge 0 to "[[ x ]]", "[[ y ]]", and "[[ z ]]" and charge 4 to "[[ *** + *** ]]". 4875 4876 4877 4878 \subsection{Associativities}\label{sec:Associativities} 4879 4880 A charge consists of a sequence of integers separated by periods. As an example, 7.9.13 is a charge. 4881 4882 Trailing zeros are considered insignificant so 1.2, 1.2.0, and 1.2.0.0.0 represent the same charge. On the other hand, 1.1 and 1.10 are considered different since the 0 in 1.10 is part of the integer 10. 4883 4884 Associativities are ordered lexically. As an example, we have 4885 4886 \begin{verbatim} 4887 1 < 1.5 < 2.-10 < 2.-9 < 2.-1 < 2 < 2.1 < 2.9 < 2.10 < 3 4888 \end{verbatim} 4889 4890 Constructs with low charge bind tighter than constructs with high charge (so constructs with low charge has high priority and vice versa). 4891 4892 A charge is said to be \emph{even} (\emph{odd}) if its last, non-zero number is even (odd). As examples, 1.2.-10 and 1.2.-10.0 are even and 1.2.-11 and 1.2.-11.0 are odd. As a special case, charge 0 is considered to be even. 4893 4894 Constructs with even charge are \emph{preassociative}. A preassociative construct is left associative in text that runs left to right, right associative in text that runs right to left, top associative in text that runs from top to bottom, counter-clock-wise-associative in text written in clock-wise spirals, and so on. Constructs with odd charge are \emph{postassociative}. 4895 4896 4897 4898 \subsection{Constructs}\label{sec:Constructs} 4899 4900 Each construct has four properties: 4901 4902 \begin{itemize} 4903 4904 \item Name 4905 4906 \item Charge 4907 4908 \item Reference 4909 4910 \item Index 4911 4912 \end{itemize} 4913 4914 A name is a string of characters with the following restrictions: 4915 4916 \begin{itemize} 4917 4918 \item A name cannot contain characters with codes below 32 (space). 4919 4920 \item A name cannot start or end with a space 4921 4922 \item A name cannot have two or more spaces in a row anywhere in the name. 4923 4924 \item A name cannot have two or more double quote characters in a row anywhere in the name. 4925 4926 \item A name must contain at least one character which is not a double quote character. 4927 4928 \end{itemize} 4929 4930 In names, double quote characters serve as placeholders. As an example, consider the construct 4931 4932 \begin{verbatim} 4933 if ""! then ""! else ""! 4934 \end{verbatim} 4935 4936 When using that construct, one must replace the three double quote characters with expressions. 4937 4938 As mentioned in Section \ref{sec:Associativities}, a charge is a sequence of integers separated by periods. 4939 4940 The \emph{reference} of a construct is a cardinal (i.e.\ a non-negative integer). The reference of a construct is equal to the reference of the \emph{home page} of the construct. The home page of a construct is the page on which the construct is defined. 4941 4942 The \emph{index} of a construct is also a cardinal. Constructs on a page a numbered consequtively, starting with 1. In addition, every page has a \emph{page construct} whose name is the name of the page. The page construct has index 0. The page construct is defined by a \verb+""!""!P+ escape sequence. 4943 4944 Each construct also has a number of derived properties: 4945 4946 \begin{description} 4947 4948 \item[arity] The arity of a construct equals the total number of double quote characters in the name of the construct. 4949 4950 \item[Pre-openness] A construct is pre-open if its name begins with a double quote character and pre-closed otherwise. 4951 4952 \item[Post-closedness] A construct is post-open if its name ends with a double quote character and post-closed otherwise. 4953 4954 \item[Fixity] We shall say that a construct is open if it is pre- and post-open and that it is closed if it is pre- and post-closed. We shall say that a construct is prefix if it is pre-closed and post-open and suffix if it is pre-open and post-closed. 4955 4956 \end{description} 4957 4958 Some examples read: 4959 4960 \begin{tabular}{|l|l|l|l|} 4961 4962 \hline 4963 4964 Construct & Pre-openness & Post-openness & Fixity \\ 4965 4966 \hline 4967 4968 \verb/""! + ""!/ & Pre-open & Post-open & Open \\ 4969 4970 \verb+( ""! )+ & Pre-closed & Post-closed & Closed \\ 4971 4972 \verb+if ""! then ""! else ""!+ & Pre-closed & Post-open & Prefix \\ 4973 4974 \verb+""! factorial+ & Pre-open & Post-closed & Suffix \\ 4975 4976 \hline 4977 4978 \end{tabular} 4979 4980 Internally, we represent constructs by tuples "[[ << r ,, i ,, a ,, p ,, n ,, b ,, R >> ]]" where 4981 4982 \begin{description} 4983 4984 \item "[[ r ]]" is the reference of the construct (a cardinal) 4985 4986 \item "[[ i ]]" is the index of the construct (a cardinal) 4987 4988 \item "[[ a ]]" is the charge of the construct expressed as a list of integers. Charge 0 is represented by the empty list. 4989 4990 \item "[[ p ]]" is the post-openness of the construct expressed as a Boolean ("[[ p prime = true ]]" means that the construct is post-open. 4991 4992 \item "[[ n ]]" is the name of the construct expressed as a list of singleton strings. 4993 4994 \item "[[ b ]]" is the binary encoding of the construct used in Logiweb vectors. 4995 4996 \item "[[ R ]]" is the relative reference of the construct (the position of the construct in the bibliography). 4997 4998 \end{description} 4999 5000 In Logiweb vectors, constructs are represented by byte sequences. Suppose a page references "[[ N ]]" pages (including reference zero). The construct with index "[[ i ]]" from relative reference "[[ R ]]" is represented by the number "[[ 1 + i + N * R ]]" expressed as a list of septets. A cardinal is expressed as a list of septets by expressing the cardinal little endian base 128 and then adding 128 to all bytes except the last. 5001 5002 5003 5004 \subsection{Qualified constructs} 5005 5006 When importing constructs from different pages, the problem may arise that distinct constructs accidentally have the same name. To cope with that, the programmer may decide to \emph{qualify} constructs. 5007 5008 A construct is qualified by splicing a qualifier (a string) into its name. A qualifier must satisfy the following: 5009 5010 \begin{itemize} 5011 5012 \item A qualifier cannot contain characters with codes below 32 (space). 5013 5014 \item A qualifier cannot contain double quote characters. 5015 5016 \end{itemize} 5017 5018 A qualifier is spliced into the following location: 5019 5020 \begin{itemize} 5021 5022 \item If the construct does not start with a double quote then the qualifier is spliced in in front of the first character. 5023 5024 \item If the construct starts with a quote followed by a non-space then the qualifier is spliced in between the first and second character. 5025 5026 \item If the construct starts with a quote followed by a space followed by a non-quote then the qualifier is spliced in between the second and third character. 5027 5028 \item If the construct starts with a quote followed by a space followed by a quote then the space is doubled and the qualifier is spliced in between the two spaces. 5029 5030 \end{itemize} 5031 5032 Once the qualifier is spliced in, duplicate spaces in the result are reduced to single spaces and leading and trailing spaces are removed. Because of this, leading spaces in qualifiers have effect only on constructs which start with a quote followed by a non-space. In contrast, trailing spaces in qualifiers do have effect on all constructs except those which start with a double quote followed by a space followed by a double quote. Some examples are given in the following table. 5033 5034 \addvspace{\abovedisplayskip} 5035 5036 \begin{tabular}{|l|l|l|} 5037 5038 \hline 5039 5040 Qualifier & Name & Qualified name \\ 5041 5042 \hline 5043 5044 \verb*/ base / & \verb*/if ""! then ""! else ""!/ & \verb*/base if ""! then ""! else ""!/ \\ 5045 5046 \verb*/base / & \verb*/if ""! then ""! else ""!/ & \verb*/base if ""! then ""! else ""!/ \\ 5047 5048 \verb*/ base/ & \verb*/if ""! then ""! else ""!/ & \verb*/baseif ""! then ""! else ""!/ \\ 5049 5050 \verb*/base/ & \verb*/if ""! then ""! else ""!/ & \verb*/baseif ""! then ""! else ""!/ \\ 5051 5052 \hline 5053 5054 \verb*/ base / & \verb*/""! + ""!/ & \verb*/""! base + ""!/ \\ 5055 5056 \verb*/base / & \verb*/""! + ""!/ & \verb*/""! base + ""!/ \\ 5057 5058 \verb*/ base/ & \verb*/""! + ""!/ & \verb*/""! base+ ""!/ \\ 5059 5060 \verb*/base/ & \verb*/""! + ""!/ & \verb*/""! base+ ""!/ \\ 5061 5062 \hline 5063 5064 \verb*/ base / & \verb*/""!,""!/ & \verb*/""! base ,""!/ \\ 5065 5066 \verb*/base / & \verb*/""!,""!/ & \verb*/""!base ,""!/ \\ 5067 5068 \verb*/ base/ & \verb*/""!,""!/ & \verb*/""! base,""!/ \\ 5069 5070 \verb*/base/ & \verb*/""!,""!/ & \verb*/""!base,""!/ \\ 5071 5072 \hline 5073 5074 \verb*/ base / & \verb*/""! ""!/ & \verb*/""! base ""!/ \\ 5075 5076 \verb*/base / & \verb*/""! ""!/ & \verb*/""! base ""!/ \\ 5077 5078 \verb*/ base/ & \verb*/""! ""!/ & \verb*/""! base ""!/ \\ 5079 5080 \verb*/base/ & \verb*/""! ""!/ & \verb*/""! base ""!/ \\ 5081 5082 \hline 5083 5084 \end{tabular} 5085 5086 \addvspace{\belowdisplayskip} 5087 5088 The "[[ lgc-splice ( q , c ) ]]" splices the qualifier "[[ q ]]" into the construct "[[ c ]]": 5089 5090 \begin{statements} 5091 5092 \item "[[ late define lgc-panic ( x ) as trace ( x ) .then. bottom end define ]]" 5093 5094 \item "[[ late define lgc-splice ( q , c ) as newline 5095 5096 if c atom then lgc-panic ( !"Internal error 1 in lgc-splice" ) else newline 5097 5098 if c head != QQ then append ( lgc-left-trim ( q ) , c ) else newline 5099 5100 let c = c tail in newline 5101 5102 if c atom then lgc-panic ( !"Internal error 2 in lgc-splice" ) else newline 5103 5104 if c head != SP then QQ :: append ( q , c ) else newline 5105 5106 let c = c tail in newline 5107 5108 if c head != QQ then QQ :: SP :: append ( lgc-left-trim ( q ) , c ) else newline 5109 5110 QQ :: SP :: append ( lgc-trim ( q ) , SP :: c ) end define ]]" 5111 5112 \end{statements} 5113 5114 5115 5116 \subsection{Specifying qualification in source files} 5117 5118 When referencing a page, all constructs of that page are \emph{imported} and made available for use. As an example, the following line references a page named page1 and makes all constructs of that page available: 5119 5120 \begin{verbatim} 5121 ""!""!R page1 5122 \end{verbatim} 5123 5124 As another example, the following line references a page named page2 and qualifies all its constructs by \verb*+ qual2 +: 5125 5126 \begin{verbatim} 5127 ""!""!R qual2 ""! page2 5128 \end{verbatim} 5129 5130 One may specify more than one qualifier: 5131 5132 \begin{verbatim} 5133 ""!""!R qual3 ""! Qual3 ""! page3 5134 \end{verbatim} 5135 5136 If page3 defines a construct named \verb*/""! + ""!/ then the reference above allows to reference that construct as \verb*/""! qual3 + ""!/ or \verb*/""! Qual3 + ""!/ but not as \verb*/""! + ""!/. 5137 5138 One may specify an empty qualifier: 5139 5140 \begin{verbatim} 5141 ""!""!R""! qual4 ""! Qual4 ""! page4 5142 \end{verbatim} 5143 5144 If page4 defines a construct named \verb*/""! + ""!/ then the reference above allows to reference that construct as \verb*/""! qual4 + ""!/ or \verb*/""! Qual4 + ""!/ or \verb*/""! + ""!/. 5145 5146 When specifying an empty qualifier, the empty qualifier must be first in the list: if one tries to put it later then one is forced to put two double quote characters next to each other, yeilding an escape sequence. 5147 5148 The page construct also allows qualification: 5149 5150 \begin{verbatim} 5151 ""!""!P""! myqual ""! Myqual ""! mypage 5152 \end{verbatim} 5153 5154 The line above defines a page construct named \verb+mypage+ and qualifies all locally defined constructs by the empty string and \verb+myqual+ and \verb+Myqual+. That allows to define a construct named e.g.\ \verb*/""! + ""!/ and to refer to it is \verb*/""! + ""!/, \verb*/""! myqual + ""!/, and \verb*/""! Myqual + ""!/. 5155 5156 In case \verb+mypage+ is later on referenced from some other page, then only \verb*/""! + ""!/ will be imported from \verb+mypage+ to the referencing page. The referencing will not import constructs named \verb*/""! myqual + ""!/ and \verb*/""! Myqual + ""!/. But the referencing page may specify its own qualifications. 5157 5158 5159 5160 \subsection{Grammar ambiguity}\label{sec:GrammarAmbiguity} 5161 5162 The Logiweb language allows the user to define ambiguous grammars. Actually, the compiler makes no attempt to decide whether or not grammars are ambiguous. Rather, the compiler parses the source text according to the grammar and complains if it cannot parse the source or if it can parse the source in more than one way. In the latter case, the source is said to be ambiguous. 5163 5164 A grammar can be ambiguous in a particularly visible way: it can contain multiple constructs sharing the same name. As an example, suppose Page1 and Page2 both define a construct named \verb*/""! + ""!/ and that they are referenced thus: 5165 5166 \begin{verbatim} 5167 ""!""!R""! Qual1""! Page1 5168 ""!""!R""! Qual2""! Page2 5169 \end{verbatim} 5170 5171 The resulting grammar will know constructs named \verb*/""! + ""!/, \verb*/""! Qual1+ ""!/, and \verb*/""! Qual2+ ""!/. However, \verb*/""! + ""!/ will be the name of two, distinct constructs: one from Page1 and one from Page2. If the programmer writes e.g.\ \verb*/2 Qual1+ 3 Qual2+ 4/ then the first plus will be from Page1 and the second from Page2. But if the programmer writes e.g.\ \verb*/2 + 3/ then the programmer will get an error message stating that the source text can be parsed in more than one way. 5172 5173 5174 5175 \subsection{Trie grammars} 5176 5177 Consider the following source grammar: 5178 5179 \begin{verbatim} 5180 ""!""!D 0 5181 abc 5182 abd 5183 ""!""!D 4 5184 ""! + ""! 5185 \end{verbatim} 5186 5187 When the Logiweb compiler reads a grammar like the one above, it constructs a trie grammar "[[ g ]]" with the following properties: 5188 5189 "[[[ array ( left,left,left ) 5190 5191 g [[ !"a" ]] [[ !"b" ]] [[ !"c" ]] [[ 0 ]] & %% = %% & << *** >> \\ 5192 5193 g [[ !"a" ]] [[ !"b" ]] [[ !"d" ]] [[ 0 ]] & %% = %% & << *** >> \\ 5194 5195 g [[ !""-""!" ]] [[ !" " ]] [[ !"+" ]] [[ !" " ]] [[ !""-""!" ]] [[ 0 ]] & %% = %% & << *** >> 5196 5197 end array ]]]" 5198 5199 The value of "[[ g [[ !"a" ]] [[ !"b" ]] [[ !"c" ]] [[ 0 ]] ]]" is a list of \emph{grammar nodes}. The list has one node for each construct named \verb+abc+. In a typical situation, only one construct is named \verb+abc+ and the list will have only one node. However, as mentioned in Section \ref{sec:GrammarAmbiguity}, more than one construct can have the same name, in which case the list will have more than one node. 5200 5201 5202 5203 \subsection{Grammar nodes} 5204 5205 Each grammar node has form "[[ << r ,, i ,, C ,, p ,, n ,, b >> ]]" which specifies the reference, index, charge, post-openness, name, and byte representation of the construct, c.f.\ Section \ref{sec:Constructs}. 5206 5207 When the Logiweb compiler translates a source text, it loads all referenced pages and assembles a grammar comprising all constructs of all referenced pages plus all constructs defined by the page itself. All constructs are qualified as specified in \verb+""!""!P+ and verb+""!""!R+ statements before they enter the grammar. 5208 5209 The following functions may be used for accessing individual fields of grammar nodes. 5210 5211 \begin{statements} 5212 5213 \item "[[ late define lgc-node2ref ( n ) as n zeroth end define ]]" 5214 5215 \item "[[ late define lgc-node2idx ( n ) as n first end define ]]" 5216 5217 \item "[[ late define lgc-node2charge ( n ) as n second end define ]]" 5218 5219 \item "[[ late define lgc-node2open ( n ) as n third end define ]]" 5220 5221 \item "[[ late define lgc-node2closed ( n ) as .not. n third end define ]]" 5222 5223 \item "[[ late define lgc-node2name ( n ) as n fourth end define ]]" 5224 5225 \item "[[ late define lgc-node2binary ( n ) as n fifth end define ]]" 5226 5227 \item "[[ late define lgc-node2relref ( n ) as n sixth end define ]]" 5228 5229 \end{statements} 5230 5231 5232 5233 \subsection{Grammar construction} 5234 5235 The "[[ lgc-grammar1 ( x , s ) ]]" function adds the following to the state: 5236 5237 \begin{description} 5238 5239 \item "[[ s [[ !"grammar" ]] ]]" The grammar containing constructs from the page being translated and its directly referenced pages. 5240 5241 \item "[[ s [[ !"dictionary" ]] [[ i ]] ]]" Association list whose entires have form "[[ i :: a ]]" where "[[ i ]]" is the index of a construct of the current page and "[[ a ]]" is its associated arity. Sorted in descending "[[ i ]]". 5242 5243 \item "[[ s [[ !"binary" ]] [[ i ]] ]]" The binary representation of the construct with index "[[ i ]]" from the page being translated. 5244 5245 \item "[[ s [[ !"name" ]] [[ i ]] ]]" The name of the construct with index "[[ i ]]" from the page being translated. 5246 5247 \item "[[ s [[ !"charge" ]] [[ i ]] ]]" The charge of the construct with index "[[ i ]]" from the page being translated. 5248 5249 \item "[[ s [[ !"index" ]] ]]" The next unused index. 5250 5251 \end{description} 5252 5253 The "[[ x ]]" parameter allows "[[ lgc-grammar1 ( x , s ) ]]" to be invoked using by an exec event, but "[[ x ]]" is ignored as it is not supposed to contain meaningfull events. 5254 5255 \begin{statements} 5256 5257 \item "[[ late define lgc-grammar ( s ) as newline 5258 5259 lgc-exec-events ( s , lgc-grammar1 ( x , s ) ) end define ]]" 5260 5261 \item "[[ late define lgc-grammar1 ( x , s ) as newline 5262 5263 let b = reverse ( s [[ !"refbib" ]] ) in newline 5264 5265 let s = s [[ !"refbib" -> b ]] in newline 5266 5267 let s = s [[ !"grammar" -> lgc-grammar-init ]] in newline 5268 5269 let s = lgc-grammar-add-bib ( s [[ !"bib" ]] , 1 , b , s ) in newline 5270 5271 let e :: s = lgc-grammar-add-def ( s ) catch in newline 5272 5273 if e then lgc-report-messages ( s ) else newline 5274 5275 let s = lgc-progress ( !"Parsing" , 3 , s ) in newline 5276 5277 lgc-exec-events ( s , lgc-parse1 ( x , s ) ) end define ]]" 5278 5279 \item "[[ late define lgc-grammar-init as newline 5280 5281 let g = true in newline 5282 5283 let g = lgc-grammar-init1 ( lgc-esc-- , g ) in newline 5284 5285 let g = lgc-grammar-init1 ( lgc-esc-# , g ) in newline 5286 5287 let g = lgc-grammar-init1 ( lgc-esc-$ , g ) in newline 5288 5289 let g = lgc-grammar-init1 ( lgc-esc-C , g ) in newline 5290 5291 let g = lgc-grammar-init1 ( lgc-esc-N , g ) in newline 5292 5293 let g = lgc-grammar-init1 ( lgc-esc-S , g ) in g end define ]]" 5294 5295 \item "[[ late define lgc-grammar-init1 ( x , g ) as newline 5296 5297 g [[ << x ,, 0 >> => << << true ,, true ,, true ,, false >> >> ]] end define ]]" 5298 5299 \end{statements} 5300 5301 5302 5303 \subsection{Constructs from referenced pages} 5304 5305 \begin{statements} 5306 5307 \item "[[ late define lgc-grammar-add-bib ( B , R , b , s ) as newline 5308 5309 if b atom then s else newline 5310 5311 let s = lgc-grammar-add-ref ( B head , R , b head , s ) in newline 5312 5313 lgc-grammar-add-bib ( B tail , R + 1 , b tail , s ) end define ]]" 5314 5315 Add all constructs in referenced pages to the grammar in the state "[[ s ]]". "[[ b ]]" is a list of references of pages which have not yet been added. "[[ B ]]" is the list of the same references but taken from the source text. "[[ B ]]" contains prefixes to be added to constructs. "[[ R ]]" is the reletive reference of the first element of "[[ b ]]". 5316 5317 \item "[[ late define lgc-grammar-add-ref ( P , R , r , s ) as newline 5318 5319 let P = P tail in newline 5320 5321 let P = if P then << true >> else P in newline 5322 5323 let d = s [[ !"cluster" ]] [[ r ]] [[ r ]] [[ !"dictionary" ]] in newline 5324 5325 lgc-grammar-add-dictionary ( P , R , r , d , s ) end define ]]" 5326 5327 Add all constructs from the page with reference "[[ r ]]" and relative reference "[[ R ]]" to the grammar. "[[ P ]]" has form "[[ << n ,, p _ { 1 } ,, ... ,, p _ { n } >> ]]" where "[[ n ]]" is the way the page was referenced in the source text and the "[[ p ]]"'s are prefixes to be added to grammatical constructs. 5328 5329 \item "[[ late define lgc-grammar-add-dictionary ( P , R , r , d , s ) as newline 5330 5331 if d then s else newline 5332 5333 if d head intp then lgc-grammar-add-construct ( P , R , r , d , s ) else newline 5334 5335 lgc-grammar-add-dictionary ( P , R , r , d tail , lgc-grammar-add-dictionary ( P , R , r , d head , s ) ) end define ]]" 5336 5337 Add all constructs in the dictionary "[[ d ]]" to the grammar. "[[ P ]]" is the list of prefixes to be added to constructs and "[[ r ]]" and "[[ R ]]" are the reference and relative reference, respectively, of the page being added. 5338 5339 \item "[[ late define lgc-grammar-add-construct ( P , R , r , d , s ) as newline 5340 5341 let i :: a = d in newline 5342 5343 let n = lgc-aritysymbol2vt ( r , i , a , s ) in newline 5344 5345 let c = lgc-grammar-get-charge ( r , i , s ) in newline 5346 5347 lgc-grammar-add-construct1 ( P , R , i , c , n , s ) end define ]]" 5348 5349 Add the construct in the subdirectory "[[ d ]]" to the grammar. "[[ d ]]" has form "[[ i :: a ]]" where "[[ i ]]" and "[[ a ]]" are the index and arity, respectively, of the construct. The function looks up the name "[[ n ]]" and charge "[[ c ]]" of the construct and adds them to the grammar. 5350 5351 \item "[[ late define lgc-grammar-add-construct1 ( P , R , i , c , n , s ) as newline 5352 5353 if P then s else newline 5354 5355 let q :: P = P in newline 5356 5357 let N = lgc-splice ( q , n ) in newline 5358 5359 let p = ( N last = QQ ) in newline 5360 5361 let b = lgc-card2septet* ( 1 + R + i * ( 1 + length ( s [[ !"bib" ]] ) ) ) in newline 5362 5363 let t = << R ,, i ,, c ,, p ,, N ,, b ,, R >> in newline 5364 5365 let s = push* ( s , !"grammar" :: append ( N , << 0 >> ) , t ) in newline 5366 5367 lgc-grammar-add-construct1 ( P , R , i , c , n , s ) end define ]]". 5368 5369 Splice the qualifiers in the list "[[ P ]]" into the name "[[ n ]]", construct the tuple "[[ t ]]" which represents the construct, and add it to the grammar. 5370 5371 \item "[[ late define lgc-card2septet* ( c ) as newline 5372 5373 if c < septet-base then bt2vector* ( c ) else newline 5374 5375 let c :: r = floor ( c , septet-base ) in newline 5376 5377 bt2vector* ( r + septet-base ) :: lgc-card2septet* ( c ) end define ]]" 5378 5379 Express the cardinal "[[ c ]]" as a list of septets. 5380 5381 \item "[[ late define lgc-aritysymbol2vt ( r , i , a , s ) as newline 5382 5383 lgc-aritysymbol2vt1 ( r , i , a , s [[ !"cluster" ]] [[ r ]] ) end define ]]" 5384 5385 Find or construct a name for the symbol with reference "[[ r ]]", index "[[ i ]]", and arity "[[ a ]]" using the state "[[ s ]]". 5386 5387 \item "[[ late define lgc-aritysymbol2vt1 ( r , i , a , c ) as newline 5388 5389 let N = c [[ r ]] [[ !"codex" ]] [[ r ]] [[ i ]] [[ 0 ]] [[ !"name" ]] in newline 5390 5391 if N then lgc-grammar-default-construct ( r , i , a ) else newline 5392 5393 let << true ,, true ,, true ,, n >> = N in newline 5394 5395 if n ref != 0 then lgc-grammar-default-construct ( r , i , a ) else newline 5396 5397 let n = lgc-trim-contract ( vt2vector* ( n idx ) ) in newline 5398 5399 if n = true .or. n = << QQ >> then lgc-grammar-default-construct ( r , i , a ) else newline 5400 5401 if lgc-grammar-valid-construct ( a , n ) then n else newline 5402 5403 lgc-grammar-default-construct ( r , i , a ) end define ]]" 5404 5405 Find or construct a name for the symbol with reference "[[ r ]]", index "[[ i ]]", and arity "[[ a ]]" using the cache "[[ c ]]". 5406 5407 Look up the name definition "[[ N ]]". If no definition is found, use the default name. If a name definition is found, extract the right hand side "[[ n ]]" of the definition. If "[[ n ]]" is no string, use the default name. Else normalize the string. If the result is one of the two forbidden constructs, use the default name. Finally, if "[[ n ]]" has wrong arity or has two double quotes in row, use the default name. Else use the name "[[ n ]]". 5408 5409 \item "[[ late define lgc-grammar-valid-construct ( a , n ) as newline 5410 5411 if n then a = 0 else newline 5412 5413 let c :: n = n in newline 5414 5415 if c != QQ then lgc-grammar-valid-construct ( a , n ) else newline 5416 5417 n head != QQ .and. lgc-grammar-valid-construct ( a - 1 , n ) end define ]]" 5418 5419 Check that the name "[[ n ]]" has the right arity and does not have two double quotes in a row. 5420 5421 \item "[[ late define lgc-def2charge ( C ) as newline 5422 5423 if C then true else newline 5424 5425 let << true ,, true ,, true ,, c >> = C in newline 5426 5427 if c ref != 0 then true else newline 5428 5429 let c = vt2vector* ( c idx ) in newline 5430 5431 let e :: c = lgc-parse-charge1 ( c , true ) catch in newline 5432 5433 if e then true else c end define ]]" 5434 5435 Convert the charge definition "[[ C ]]" to a charge. Return the default charge "[[ true ]]" if the definition is missing or malformed. 5436 5437 \item "[[ late define lgc-grammar-get-charge ( r , i , s ) as newline 5438 5439 lgc-def2charge ( s [[ !"cluster" ]] [[ r ]] [[ r ]] [[ !"codex" ]] [[ r ]] [[ i ]] [[ 0 ]] [[ !"charge" ]] ) end define ]]" 5440 5441 Look up the charge definition "[[ C ]]" and convert it to a charge (i.e.\ a list of integers). 5442 5443 \end{statements} 5444 5445 5446 5447 \subsection{Default names} 5448 5449 The "[[ lgc-grammar-default-construct ( r , i , a ) ]]" construct returns a default name for the construct with reference "[[ r ]]", index "[[ i ]]", and arity "[[ a ]]". 5450 5451 \begin{statements} 5452 5453 \item "[[ late define lgc-grammar-default-construct ( r , i , a ) as newline 5454 5455 let r = lgc-string2mixed ( vector-subseq ( r , 1 , 3 ) ) in newline 5456 5457 let i = lgc-itoa ( i ) in newline 5458 5459 let a = lgc-grammar-default-arglist ( a ) in newline 5460 5461 vt2vector* ( << !"#[" ,, r ,, !":" ,, i ,, !"]" ,, a >> ) end define ]]" 5462 5463 Construct a default name for the construct with reference "[[ r ]]" and index "[[ i ]]". 5464 5465 \item "[[ late define lgc-grammar-default-arglist ( a ) as newline 5466 5467 if a = 0 then true else newline 5468 5469 << !" (" ,, lgc-grammar-default-arglist1 ( a - 1 ) ,, !" ""! )" >> end define ]]" 5470 5471 Construct the arglist of the default name of a construct with arity "[[ a ]]". 5472 5473 \item "[[ late define lgc-grammar-default-arglist1 ( a ) as newline 5474 5475 if a = 0 then true else newline 5476 5477 !" ""! ," :: lgc-grammar-default-arglist1 ( a - 1 ) end define ]]" 5478 5479 Auxiliary function for the previous function. 5480 5481 \end{statements} 5482 5483 5484 5485 \subsection{Constructs from source text} 5486 5487 \begin{statements} 5488 5489 \item "[[ late define lgc-grammar-add-def ( s ) as newline 5490 5491 let p = s [[ !"page" ]] in newline 5492 5493 if p then lgc-throw-message ( s , 0 , !"No page name found" ) else newline 5494 5495 let p :: P = p in newline 5496 5497 let P = if P then << true >> else P in newline 5498 5499 let s = s [[ !"index" -> 0 ]] in newline 5500 5501 let s = lgc-grammar-def-construct ( P , true , p , s ) in newline 5502 5503 let d = reverse ( s [[ !"def" ]] ) in newline 5504 5505 lgc-grammar-add-defs* ( P , d , s ) end define ]]" 5506 5507 Find the page name "[[ p ]]", the list "[[ P ]]" of prefixes, and the list "[[ d ]]" of charge sections. Add "[[ p ]]" as the construct with index zero and then add all constructs in "[[ d ]]". 5508 5509 \item "[[ late define lgc-grammar-def-construct ( P , c , n , s ) as newline 5510 5511 let i = s [[ !"index" ]] in newline 5512 5513 let s = s [[ !"index" -> i + 1 ]] in newline 5514 5515 let a = lgc-arity ( n ) in newline 5516 5517 let s = push ( s , !"dictionary" , i :: a ) in newline 5518 5519 let b = lgc-card2septet* ( 1 + i * ( 1 + length ( s [[ !"bib" ]] ) ) ) in newline 5520 5521 let s = s [[ << !"binary" ,, i >> => b ]] in newline 5522 5523 let s = s [[ << !"name" ,, i >> => n ]] in newline 5524 5525 let s = s [[ << !"charge" ,, i >> => lgc-charge2vector* ( c ) ]] in newline 5526 5527 lgc-grammar-add-construct1 ( P , 0 , i , c , n , s ) end define ]]" 5528 5529 Add the construct "[[ n ]]" with charge "[[ c ]]" and prefixes "[[ P ]]" to the state "[[ s ]]". The arity of the construct is found by counting double quote characters in "[[ n ]]" and the index "[[ i ]]" is taken from the state. 5530 5531 \item "[[ late define lgc-arity ( n ) as newline 5532 5533 if n atom then 0 else newline 5534 5535 if n head != QQ then lgc-arity ( n tail ) else newline 5536 5537 1 + lgc-arity ( n tail ) end define ]]" 5538 5539 Count the number of double quote characters in "[[ n ]]". 5540 5541 \item "[[ late define lgc-grammar-add-defs* ( P , d , s ) as newline 5542 5543 if d atom then s else newline 5544 5545 let s = lgc-grammar-add-defs ( P , d head , s ) in newline 5546 5547 lgc-grammar-add-defs* ( P , d tail , s ) end define ]]" 5548 5549 Add the list "[[ d ]]" of charge sections to the grammar. 5550 5551 \item "[[ late define lgc-grammar-add-defs ( P , d , s ) as newline 5552 5553 let p :: d = d in newline 5554 5555 let p = lgc-parse-charge ( p , s ) in newline 5556 5557 lgc-grammar-def-construct* ( P , p , d , s ) end define ]]" 5558 5559 Add the charge section "[[ d ]]" to the grammar. 5560 5561 \item "[[ late define lgc-grammar-def-construct* ( P , p , d , s ) as newline 5562 5563 if d atom then s else newline 5564 5565 let s = lgc-grammar-def-construct ( P , p , d head , s ) in newline 5566 5567 lgc-grammar-def-construct* ( P , p , d tail , s ) end define ]]" 5568 5569 Add all constructs in the list "[[ d ]]" of constructs to the grammar. 5570 5571 \item "[[ late define lgc-parse-charge ( a , s ) as newline 5572 5573 let p :: a = a in newline 5574 5575 let a = lgc-trim-contract ( a ) in newline 5576 5577 let e :: c = lgc-parse-charge1 ( a , true ) catch in newline 5578 5579 if .not. e then c else newline 5580 5581 let t = lgc-grammar-get-tuple ( s , a ) in newline 5582 5583 if t != true .and. t tail = true then t head second else newline 5584 5585 if t = true then newline 5586 5587 lgc-throw-message ( s , p , !"Malformed charge" ) else newline 5588 5589 lgc-throw-message ( s , p , !"Charge refers to ambiguous construct" ) end define ]]" 5590 5591 Remove the position "[[ p ]]" from "[[ a ]]". Then parse the singleton string "[[ a ]]" into a charge. If that fails, assume "[[ a ]]" is a construct and look up the charge of that construct. If no charge is found that way, complain. 5592 5593 \item "[[ late define lgc-parse-charge1 ( a , r ) as newline 5594 5595 let i :: a = lgc-parse-int ( a ) in newline 5596 5597 if a atom then reverse ( lgc-parse-charge2 ( i :: r ) ) else newline 5598 5599 if a head != !"." then exception else newline 5600 5601 lgc-parse-charge1 ( a tail , i :: r ) end define ]]" 5602 5603 Parse the charge "[[ a ]]" and accumulate it in reverse order in "[[ r ]]". 5604 5605 \item "[[ late define lgc-parse-charge2 ( r ) as newline 5606 5607 if r head != 0 then r else lgc-parse-charge2 ( r tail ) end define ]]" 5608 5609 Remove leading zeros. Since this is used on a reversed list, this function is effectively used for removing trailing zeros. 5610 5611 \item "[[ late define lgc-charge2vector* ( c ) as newline 5612 5613 if c atom then << !"0" >> else newline 5614 5615 append ( lgc-itoa ( c head ) , lgc-charge2vector*1 ( c tail ) ) end define ]]" 5616 5617 Convert the charge "[[ c ]]" to a singleton list. 5618 5619 \item "[[ late define lgc-charge2vector*1 ( c ) as newline 5620 5621 if c atom then true else newline 5622 5623 !"." :: append ( lgc-itoa ( c head ) , lgc-charge2vector*1 ( c tail ) ) end define ]]" 5624 5625 Convert the charge tail "[[ c ]]" to a singleton list. 5626 5627 \item "[[ late define lgc-grammar-get-tuple ( s , n ) as newline 5628 5629 get* ( s [[ !"grammar" ]] , n ) [[ 0 ]] end define ]]" 5630 5631 Get the tuple associated to the construct "[[ n ]]" in the grammar. 5632 5633 \end{statements} 5634 5635 5636 5637 " ]"\section{Parser}"[ " 5638 5639 As mentioned in the beginning of Section \ref{sec:Grammars}, the Logiweb parser "[[ lgc-parse ( g , a ) ]]" converts a list "[[ a ]]" of tokens to a parse tree as specified by the grammar "[[ g ]]". We now proceed to define "[[ lgc-parse ( g , a ) ]]" in detail. 5640 5641 5642 5643 \subsection{Token lists}\label{sec:TokenLists} 5644 5645 The list "[[ a ]]" of tokens is installed in "[[ s [[ !"body" ]] ]]" by lexical analysis. Each token in "[[ a ]]" has form "[[ c :: p :: S ]]". A token may have one of the following forms: 5646 5647 \begin{itemize} 5648 5649 \item "[[ c :: p :: true ]]" where "[[ c ]]" is a character represented as a singleton string from the source file and "[[ p ]]" is the position of that character. 5650 5651 \item "[[ lgc-esc-- :: p :: S ]]" where "[[ S ]]" is a string from the source file and "[[ p ]]" is the position of the beginning of the string. 5652 5653 \item "[[ lgc-esc-# :: p :: S ]]" where "[[ S ]]" is the name of a file to be binary included and "[[ p ]]" is the position of the beginning of the include directive. 5654 5655 \item "[[ lgc-esc-$ :: p :: S ]]" where "[[ S ]]" is the name of a file to be text included and "[[ p ]]" is the position of the beginning of the include directive. 5656 5657 \item "[[ lgc-esc-S :: p :: true ]]" where "[[ p ]]" is the position of the \verb+""!""!S+ escape sequence which gave rise to this token. 5658 5659 \item "[[ lgc-esc-C :: p :: true ]]" where "[[ p ]]" is the position of the \verb+""!""!S+ escape sequence which gave rise to this token. 5660 5661 \item "[[ lgc-esc-N :: p :: true ]]" where "[[ p ]]" is the position of the \verb+""!""!S+ escape sequence which gave rise to this token. 5662 5663 \end{itemize} 5664 5665 5666 5667 \subsection{Linear parse trees} 5668 5669 By a \emph{linear parse tree} we shall mean a text in which understood parentheses have been added. 5670 5671 As an example, consider a grammar with the following productions: 5672 5673 \begin{verbatim} 5674 x 5675 y 5676 z 5677 " * " 5678 " + " 5679 \end{verbatim} 5680 5681 If we use brackets to represent understood parentheses, then the linear parse tree of 5682 5683 \begin{verbatim} 5684 x + y + z 5685 \end{verbatim} 5686 5687 may read 5688 5689 \begin{verbatim} 5690 [[[x] + [y]] + [z]] 5691 \end{verbatim} 5692 5693 or 5694 5695 \begin{verbatim} 5696 [[x] + [[y] + [z]]] 5697 \end{verbatim} 5698 5699 5700 5701 \subsection{Left parse trees} 5702 5703 We now introduce the notion of a \emph{left parse tree}. A linear parse tree can be converted into a left parse tree in three steps: 5704 5705 \begin{enumerate} 5706 5707 \item Replace all left brackets that follow a left brack by a left brace. 5708 5709 \item Replace all right brackets which match a left brace by a right brace. 5710 5711 \item Delete all left braces. 5712 5713 \end{enumerate} 5714 5715 As an example, \verb/[[[x] + [y]] + [z]]/ is converted thus: 5716 5717 \begin{verbatim} 5718 [[[x] + [y]] + [z]] 5719 -> [{{x] + [y]] + [z]] 5720 -> [{{x} + [y]} + [z]] 5721 -> [x} + [y]} + [z]] 5722 \end{verbatim} 5723 5724 The conversion from linear to left parse tree is reversible: The two first steps are obviously reversible, and it is not too hard to see how to reverse the third one. 5725 5726 The goal of "[[ lgc-parse ( g , a ) ]]" is find a left parse tree "[[ t ]]" of the list "[[ a ]]" of tokens according to the grammar "[[ g ]]". 5727 5728 5729 5730 \subsection{Representation of left parse trees} 5731 5732 A left parse tree is represented by a list "[[ t ]]" of tokens. Each token has form "[[ c :: p :: S ]]" and can have one of the following forms: 5733 5734 \begin{itemize} 5735 5736 \item An input token. See Section \ref{sec:TokenLists} for the seven kinds of input tokens. 5737 5738 \item "[[ lgc-esc-left :: p :: true ]]" a left bracket. 5739 5740 \item "[[ lgc-esc-right :: p :: v ]]" a right bracket where "[[ v ]]" is the value which represents the construct ended by the bracket. 5741 5742 \item "[[ lgc-esc-brace :: p :: v ]]" a right brace where "[[ v ]]" is the value which represents the construct ended by the brace. 5743 5744 \end{itemize} 5745 5746 5747 5748 \subsection{Return value} 5749 5750 If "[[ lgc-parse ( g , a ) ]]" is unable to parse "[[ a ]]" according to the grammar "[[ g ]]", then it returns "[[ << p ,, s >> ]]" where "[[ p ]]" is the farthest position into "[[ a ]]" that the parser was able to go before it had to give up. "[[ s ]]" is a value useful for constructing an error message. 5751 5752 If "[[ lgc-parse ( g , a ) ]]" can interpret "[[ a ]]" in exactly one way then it returns "[[ << true ,, t >> ]]" where "[[ t ]]" is the interpretation expressed as a left parse tree. 5753 5754 If "[[ lgc-parse ( g , a ) ]]" can interpret "[[ a ]]" in more than one way then it returns "[[ << t ,, t prime >> raise ]]" where "[[ t ]]" and "[[ t prime ]]" are two, distinct interpretations of "[[ a ]]" expressed as two, distinct left parse trees. 5755 5756 5757 5758 \subsection{Restrictions on left parse trees} 5759 5760 The parser parses "[[ a ]]" as if all constructs are right associative and have the same charge. Hence, \verb/x + y + z/ should be interpreted as 5761 5762 \begin{verbatim} 5763 [[x] + [[y] + [z]]] 5764 \end{verbatim} 5765 5766 rather than 5767 5768 \begin{verbatim} 5769 [[[x] + [y]] + [z]] 5770 \end{verbatim} 5771 5772 Or, expressed using left parse trees, it should be interpreted as 5773 5774 \begin{verbatim} 5775 [x} + [y} + [z]]] 5776 \end{verbatim} 5777 5778 rather than 5779 5780 \begin{verbatim} 5781 [x} + [y]} + [z]] 5782 \end{verbatim} 5783 5784 This right-associative-same-charge parsing is implemented by adding a rule saying that a right brace is not allowed to follow a right bracket. 5785 5786 Furthermore, since we do not permit the empty construct, a right brace or bracket cannot follow a left bracket. 5787 5788 Furthermore, since we do not permit constructs with two double quotes in a row, a left bracket cannot follow a right brace or bracket. 5789 5790 Furthermore, since we do not permit the construct which contains one double quote and nothing else, a right bracket or brace cannot follow a right brace. 5791 5792 Finally, a left bracket cannot follow a left bracket due to the definition of left parse trees. 5793 5794 Hence, left parse trees can have sequences of right brackets, but apart from that, brackets and braces are separated by characters of input. 5795 5796 One consequence of the restrictions on grammars are that every construct contains at least one non-double-quote character. Hence, the parse tree of a page cannot have more nodes than the number of characters in the body of the source text. In principle, this ensures that "[[ lgc-parse ( g , a ) ]]" terminates in finite time. In practice, however, "[[ lgc-parse ( g , a ) ]]" can take very long time if the user defines a silly grammar. We consider making sensible grammars to be the responsibility of the user. We make absolutely no attempt to help users who define silly grammars. 5797 5798 5799 5800 \subsection{Functions for invoking charge rules} 5801 5802 Charge invokation functions vectorize a left parse tree into its binary representation respecting charge rules. The functions also take care of vectorizing of strings and includes and of autogeneration of name and charge definitions. 5803 5804 In the charge invokation functions, we use parameter names as follows: 5805 5806 \begin{tabular}{ll} 5807 5808 "[[ s ]]" & state \\ 5809 5810 "[[ L = t :: L ]]" & left parse tree, i.e.\ a list of tokens \\ 5811 5812 "[[ t = << c ,, p ,, v >> ]]" & token \\ 5813 5814 "[[ c ]]" & character \\ 5815 5816 "[[ p ]]" & position in source text \\ 5817 5818 "[[ v ]]" & value in token. The type of "[[ v ]]" depends on "[[ c ]]": \\ 5819 5820 \quad "[[ c = lgc-esc-- ]]" & "[[ v ]]" is a string \\ 5821 5822 \quad "[[ c = lgc-esc-# ]]" & "[[ v ]]" is the name of a binary include file \\ 5823 5824 \quad "[[ c = lgc-esc-$ ]]" & "[[ v ]]" is the name of a text include file \\ 5825 5826 \quad "[[ c = lgc-esc-right ]]" & "[[ v ]]" is a list "[[ N ]]" of nodes \\ 5827 5828 \quad "[[ c = lgc-esc-brace ]]" & "[[ v ]]" is a list "[[ N ]]" of nodes \\ 5829 5830 \quad otherwise & "[[ v ]]" is "[[ true ]]" \\ 5831 5832 "[[ C ]]" & charge \\ 5833 5834 "[[ r = M :: r ]]" & list of marked trees \\ 5835 5836 "[[ M = m :: P ]]" & marked tree \\ 5837 5838 "[[ m ]]" & mark; normally "[[ true ]]", occasionally "[[ false ]]" \\ 5839 5840 "[[ P = n :: A ]]" & partial tree \\ 5841 5842 "[[ N = n :: N ]]" & list of grammar nodes \\ 5843 5844 "[[ n = << R ,, i ,, C ,, p prime ,, N prime ,, b >> ]]" & grammar node \\ 5845 5846 "[[ R ]]" & relative reference \\ 5847 5848 "[[ i ]]" & index \\ 5849 5850 "[[ p prime ]]" & post-openness \\ 5851 5852 "[[ N prime ]]" & name of construct \\ 5853 5854 "[[ b ]]" & byte representation of construct \\ 5855 5856 "[[ A = a :: A ]]" & list of arguments \\ 5857 5858 "[[ a ]]" & argument as vector tree \\ 5859 5860 \end{tabular} 5861 5862 5863 5864 \subsection{Main charge functions} 5865 5866 \begin{statements} 5867 5868 \item "[[ late define lgc-charge ( L , s ) as newline 5869 5870 lgc-charge1 ( L , s , true ) end define ]]" 5871 5872 Convert the left parse tree "[[ L ]]" into a vector tree "[[ a ]]" which, when flattened, becomes the body of the produced Logiweb vector. 5873 5874 \item "[[ late define lgc-charge1 ( L , s , r ) as newline 5875 5876 if L then r else newline 5877 5878 let t :: L = L in newline 5879 5880 let r = lgc-charge2 ( t , L , s , r ) in newline 5881 5882 lgc-charge1 ( L , s , r ) end define ]]" 5883 5884 Process the left parse tree "[[ L ]]" one token at a time, accumulating the result in "[[ r ]]" as a list of marked, partial trees. As an exception, however, "[[ r ]]" is the final result when "[[ t ]]" is empty. That is due to the way "[[ lgc-charge2 ( t , L , s , r ) ]]" works. 5885 5886 \item "[[ late define lgc-charge2 ( t , L , s , r ) as newline 5887 5888 let << c ,, p ,, v >> = t in newline 5889 5890 if c >= NULL then r else newline 5891 5892 if c = lgc-esc-right then lgc-charge-right ( p , v , L , s , r ) else newline 5893 5894 if c = lgc-esc-brace then lgc-charge-brace ( p , v , L , s , r ) else newline 5895 5896 if c = lgc-esc-left then lgc-charge-left ( r ) else newline 5897 5898 if c = lgc-esc-- then lgc-charge-string ( v , r ) else newline 5899 5900 if c = lgc-esc-# then lgc-charge-binary ( v , s , r ) else newline 5901 5902 if c = lgc-esc-$ then lgc-charge-text ( v , s , r ) else newline 5903 5904 if c = lgc-esc-S then lgc-charge-source ( s , r ) else newline 5905 5906 if c = lgc-esc-N then lgc-charge-name ( p , s , r ) else newline 5907 5908 if c = lgc-esc-C then lgc-charge-charge ( p , s , r ) else newline 5909 5910 lgc-panic ( !"Internal error in lgc-charge2" ) end define ]]" 5911 5912 Destruct the token "[[ t ]]" into character "[[ c ]]", position "[[ p ]]", and additional data "[[ v ]]". Then dispatch on "[[ v ]]". All the functions return a list "[[ r ]]" of marked, partial trees except "[[ lgc-charge-left ( r ) ]]" which returns the final result of charge invokation when it processes the leftmost left bracket. 5913 5914 \end{statements} 5915 5916 5917 5918 \subsection{Charge handling of brackets and braces} 5919 5920 \begin{statements} 5921 5922 \item "[[ late define lgc-charge-right ( p , N , L , s , r ) as newline 5923 5924 if N tail then << true ,, N head >> :: r else newline 5925 5926 let a = lgc-charge-right1 ( L , 0 ) :: N in newline 5927 5928 lgc-parse-ambiguous-construct ( a , s ) end define ]]" 5929 5930 Process a right bracket. If the construct is ambiguous, throw the position "[[ p ]]" and the list "[[ N ]]" of possible interpretations. Otherwise, push a marked tree "[[ M = m :: P ]]" onto "[[ r ]]". The mark "[[ m ]]" is set to "[[ true ]]". The partial tree "[[ P = n :: A ]]" has node "[[ n = N head ]]" and an empty argument list "[[ A ]]". Later on, arguments are pushed onto "[[ A ]]". If the construct is pre-open then the mark "[[ m ]]" changes to "[[ false ]]" when processing the first argument (which is processed last since arguments are processed in reverse order). For pre-closed constructs, the mark never changes. 5931 5932 \item "[[ late define lgc-charge-right1 ( L , l ) as newline 5933 5934 if L atom then 0 else newline 5935 5936 let << c ,, p ,, v >> :: L = L in newline 5937 5938 if c = lgc-esc-right then lgc-charge-right1 ( L , l + 1 ) else newline 5939 5940 if c = lgc-esc-brace then lgc-charge-right1 ( L , l ) else newline 5941 5942 if c = lgc-esc-left then lgc-charge-right1 ( L , l - 1 ) else newline 5943 5944 if l > 0 then lgc-charge-right1 ( L , l ) else p end define ]]" 5945 5946 Skip "[[ l ]]" left brackets, then return the position of the first, proper character. 5947 5948 \item "[[ late define lgc-charge-brace ( p , N , L , s , r ) as newline 5949 5950 let r = lgc-charge-brace0 ( r ) in newline 5951 5952 lgc-charge-right ( p , N , L , s , r ) end define ]]" 5953 5954 Process a right brace. First reorganize the stack according to charge. Then, since a right brace represents a right bracket, call "[[ lgc-charge-right ( p , N , L , s , r ) ]]". 5955 5956 \item "[[ late define lgc-charge-brace0 ( r ) as newline 5957 5958 let ( true :: P ) :: r = r in newline 5959 5960 let n = P head in newline 5961 5962 let C = lgc-node2charge ( n ) in newline 5963 5964 let p = lgc-node2closed ( n ) in newline 5965 5966 let r prime = << false :: P >> in newline 5967 5968 lgc-charge-brace1 ( C , p , r prime , r ) end define ]]" 5969 5970 A right brace indicates that the construct at the top of the stack "[[ r ]]" is pre-open and that we are about to parse its first argument, so we change the mark of the top element of "[[ r ]]" to "[[ false ]]". Then we let the construct bubble up the parse tree to its proper location according to its charge. That is done by "[[ lgc-charge-brace1 ( C , p , r prime , r ) ]]" which moves the list "[[ r prime ]]" of marked trees down the stack "[[ r ]]" to its proper location according to the charge "[[ C ]]". 5971 5972 \item "[[ late define lgc-charge-brace1 ( C , p , r prime , r ) as newline 5973 5974 if r then revappend ( r prime , r ) else newline 5975 5976 let m :: n :: A = r head in newline 5977 5978 if p .and. .not. m then lgc-charge-brace1 ( C , p , r head :: r prime , r tail ) else newline 5979 5980 if A != true .or. lgc-node2closed ( n ) then revappend ( r prime , r ) else newline 5981 5982 if lgc-less-charge ( C , lgc-node2charge ( n ) ) then revappend ( r prime , r ) else newline 5983 5984 r head :: lgc-charge-brace1 ( C , p , r prime , r tail ) end define ]]" 5985 5986 Bubble the list "[[ r prime ]]" of marked trees to its proper location in the "[[ r ]]". "[[ C ]]" and "[[ p ]]" are the charge and post-closedness, respectively, of the last element of "[[ r prime ]]". If "[[ r ]]" is empty, "[[ r prime ]]" is already at the root and cannot bubble further. To bubble, the construct at the top of the stack must be post-open and must be in the state where its last argument is being processed. Since arguments are processed in reverse order, the last argument is being processed iff the argument list "[[ A ]]" is empty. Finally, the charge "[[ C ]]" must be larger than the charge of the top element for "[[ r prime ]]" to bubble. When "[[ r prime ]]" bubbles, it pushes the node above in front of it if the last element of "[[ r prime ]]" is post-closed. 5987 5988 \item "[[ late define lgc-less-charge ( x , y ) as newline 5989 5990 let a :: x = x in newline 5991 5992 let b :: y = y in newline 5993 5994 let a = if a then 0 else a in newline 5995 5996 let b = if b then 0 else b in newline 5997 5998 if a < b then true else newline 5999 6000 if a > b then false else newline 6001 6002 if x .and. y then oddp ( a ) else newline 6003 6004 lgc-less-charge ( x , y ) end define ]]" 6005 6006 Compare the charges "[[ x ]]" and "[[ y ]]" and return "[[ true ]]" if "[[ x ]]" is less than "[[ y ]]". The ordering is lexicographic with the following modifications: 6007 6008 \begin{enumerate} 6009 6010 \item If one of the two is shorter than the other, then the shorter one is padded with zeros to match the length of the longer. 6011 6012 \item If "[[ x ]]" and "[[ y ]]" are equal after padding, then return "[[ true ]]" if "[[ x ]]" and "[[ y ]]" end with an odd number. Constructs whose charge end with an odd number are right associative, so they should not bubble when they meet their equal. 6013 6014 \end{enumerate} 6015 6016 \item "[[ late define lgc-charge-left ( r ) as newline 6017 6018 let ( true :: n :: A ) :: r = r in newline 6019 6020 lgc-charge-left1 ( n , A , r ) end define ]]" 6021 6022 Process a left bracket. When processing in reverse order, a left bracket closes one right bracket and zero, one or more right braces. The right braces to be closed need not be the ones that match the left bracket since the stack "[[ r ]]" has been reorganized according to charge. Rather, we use the mark of the marked trees in "[[ r ]]" to find out how many constructs to close. 6023 6024 The construct at the top of the stack always has mark "[[ true ]]" so we unstack the top element, discards the mark, and destructs the partial tree into a node "[[ n ]]" and an argument list "[[ A ]]". Then we use "[[ lgc-charge-left1 ( n , A , r ) ]]" to process further constructs from "[[ r ]]" until "[[ r ]]" is empty or the top element has mark "[[ true ]]". In other words, we process the top element of "[[ r ]]" which is known to have mark "[[ true ]]" and then process all constructs at the top of "[[ r ]]" which have mark "[[ false ]]". 6025 6026 \item "[[ late define lgc-charge-left1 ( n , A , r ) as newline 6027 6028 let a = lgc-node2binary ( n ) :: A in newline 6029 6030 if r atom then a else newline 6031 6032 let ( m :: n :: A ) :: r = r in newline 6033 6034 if m then ( true :: n :: a :: A ) :: r else newline 6035 6036 lgc-charge-left1 ( n , a :: A , r ) end define ]]" 6037 6038 When "[[ lgc-charge-left1 ( n , A , r ) ]]" is called, "[[ n ]]" and "[[ A ]]" have just been popped from the top of "[[ r ]]". That top element is a partial tree which has just been completed and, thus, has become a complete tree representing a subterm of the body of the page. We convert that just completed tree to its representation as a vector tree "[[ a ]]". When "[[ a ]]" is flattened later on, that becomes the sequence of bytes representing the just completed tree. If "[[ r ]]" has become empty we return "[[ a ]]" with no further warning. Normally, we return a stack "[[ r ]]", so this could baffle the caller. However, the stack "[[ r ]]" becomes empty exactly when the left parse tree "[[ L ]]" becomes empty, so "[[ lgc-charge1 ( L , s , r ) ]]" will know that "[[ r ]]" is not a stack but, rather, the final result of charge invokation. If "[[ r ]]" is not empty we look at the mark "[[ m ]]" of the new top element. If "[[ m = true ]]" then we can close no more constructs and add "[[ a ]]" to the argument list of the top element. Otherwise we also add "[[ a ]]" to the argument list but then we recurse. 6039 6040 \end{statements} 6041 6042 6043 6044 \subsection{Charge handling of strings} 6045 6046 \begin{statements} 6047 6048 \item "[[ late define lgc-charge-string ( v , r ) as newline 6049 6050 lgc-charge-string1 ( vector-length ( v ) , v , r ) end define ]]" 6051 6052 Replace the top element of "[[ r ]]" by the string "[[ v ]]". "[[ v ]]" must be a vector. 6053 6054 \item "[[ late define lgc-charge-string1 ( l , v , r ) as newline 6055 6056 lgc-charge-bytes ( lgc-string2bytes ( l , v ) , r ) end define ]]" 6057 6058 Replace the top element of "[[ r ]]" by the string "[[ v ]]" of length "[[ l ]]". "[[ v ]]" may be an arbitrary vector tree. 6059 6060 \item "[[ late define lgc-string2bytes ( l , v ) as newline 6061 6062 NULL :: lgc-card2septet* ( l ) :: v end define ]]" 6063 6064 Convert the vector tree "[[ v ]]" of length "[[ l ]]" into the binary representation of a string. 6065 6066 \item "[[ late define lgc-charge-bytes ( b , r ) as newline 6067 6068 let n = << true ,, true ,, true ,, true ,, true ,, b >> in newline 6069 6070 << true ,, n >> :: r tail end define ]]" 6071 6072 Replace the top element of "[[ r ]]" by the bytes "[[ b ]]". "[[ b ]]" may be an arbitrary vector tree. 6073 6074 \item "[[ late define lgc-charge-binary ( v , s , r ) as newline 6075 6076 let v = s [[ !"includes" ]] [[ v ]] in newline 6077 6078 lgc-charge-string1 ( length ( v ) , v , r ) end define ]]" 6079 6080 Replace the top element of "[[ r ]]" by the include file named "[[ v ]]". 6081 6082 \item "[[ late define lgc-charge-text ( v , s , r ) as newline 6083 6084 let v = s [[ !"includes" ]] [[ v ]] in newline 6085 6086 let v = lgc-charge-text1 ( v , true , true ) in newline 6087 6088 lgc-charge-string1 ( length ( v ) , v , r ) end define ]]" 6089 6090 Replace the top element of "[[ r ]]" by the include file named "[[ v ]]" after processing of newlines. 6091 6092 \item "[[ late define lgc-charge-text1 ( a , i , r ) as newline 6093 6094 if a atom then reverse ( r ) else newline 6095 6096 let c :: a = a in newline 6097 6098 if c = i then lgc-charge-text1 ( a , true , r ) else newline 6099 6100 if c = CR then lgc-charge-text1 ( a , LF , LF :: r ) else newline 6101 6102 if c = LF then lgc-charge-text1 ( a , CR , LF :: r ) else newline 6103 6104 lgc-charge-text1 ( a , true , c :: r ) end define ]]" 6105 6106 Perform newline processing on the list "[[ a ]]" of singleton strings and accumulate the result in "[[ r ]]". 6107 6108 \item "[[ late define lgc-host-newline ( s ) as newline 6109 6110 let n = s [[ !"parameters" ]] [[ !"newline" ]] head in newline 6111 6112 let n = lgc-argv-downcase ( n ) in newline 6113 6114 if n = "crlf" then CRLF else newline 6115 6116 if n = "cr" then CR else newline 6117 6118 if n = "lfcf" then LFCR else LF end define ]]" 6119 6120 Return the host newline sequence as a vector tree. 6121 6122 \item "[[ late define lgc-get-newline ( s , v ) as newline 6123 6124 if v atom then lgc-host-newline ( s ) else newline 6125 6126 let c :: v = v in newline 6127 6128 if c = LF then if v head = CR then LFCR else LF else newline 6129 6130 if c = CR then if v head = LF then CRLF else CR else newline 6131 6132 lgc-get-newline ( s , v ) end define ]]" 6133 6134 Return the first newline sequence of the singleton list "[[ v ]]", defaulting to the host newline sequence. 6135 6136 \item "[[ late define lgc-add-newline ( s , v ) as newline 6137 6138 lgc-get-newline ( s , v ) :: v end define ]]" 6139 6140 Add a newline in front of the singleton list "[[ v ]]". 6141 6142 \item "[[ late define lgc-add-headline ( s , R , v ) as newline 6143 6144 let h :: true :: v = lgc-parse-headline ( v ) in newline 6145 6146 if h != true then append ( h , append ( R , v ) ) else newline 6147 6148 append ( lgc-headline , append ( R , lgc-add-newline ( s , v ) ) ) end define ]]" 6149 6150 Add a headline with reference "[[ R ]]". 6151 6152 \item "[[ late define lgc-charge-source ( s , r ) as newline 6153 6154 let v = s [[ !"source" ]] in newline 6155 6156 let v = lgc-add-headline ( s , true , v ) in newline 6157 6158 lgc-charge-string1 ( length ( v ) , v , r ) end define ]]" 6159 6160 Replace the top element of "[[ r ]]" by the source text after removal of the explicit reference "[[ R ]]" (if any). 6161 6162 \item "[[ late define lgc-headline as << QQ ,, QQ ,, !";" ,, !";" >> end define ]]" 6163 6164 \item "[[ late define lgc-parse-headline ( v ) as newline 6165 6166 let e :: V = lgc-parse-prefix ( lgc-headline , v ) catch in newline 6167 6168 if e then true :: true :: v else newline 6169 6170 lgc-headline :: lgc-parse-headline1 ( V , true ) end define ]]" 6171 6172 \item "[[ late define lgc-parse-headline1 ( v , r ) as newline 6173 6174 if v atom then r :: v else newline 6175 6176 let c :: V = v in newline 6177 6178 if !"0" <= c .and. c <= !"9" then lgc-parse-headline1 ( V , c :: r ) else newline 6179 6180 if !"A" <= c .and. c <= !"F" then lgc-parse-headline1 ( V , c :: r ) else r :: v end define ]]" 6181 6182 Remove all hex digits at the begining of "[[ v ]]". 6183 6184 \end{statements} 6185 6186 6187 6188 \subsection{Autogeneration of name and charge definitions} 6189 6190 \begin{statements} 6191 6192 \item "[[ late define lgc-charge-name ( p , s , r ) as newline 6193 6194 lgc-charge-auto ( p , "name" , s , r ) end define ]]" 6195 6196 Add a name definition for each construct in the dictionary. 6197 6198 \item "[[ late define lgc-charge-charge ( p , s , r ) as newline 6199 6200 lgc-charge-auto ( p , "charge" , s , r ) end define ]]" 6201 6202 Add a charge definition for each construct in the dictionary. 6203 6204 \item "[[ late define lgc-charge-auto ( p , n , s , r ) as newline 6205 6206 let b = lgc-charge-name-find ( p , !""-""! then ""!" , true , s ) in newline 6207 6208 let b = b :: lgc-charge-name-find ( p , !"def ""! of ""! as ""! enddef" , true , s ) in newline 6209 6210 let b = b :: lgc-charge-name-find ( p , n , n , s ) in newline 6211 6212 let v = lgc-charge-name-find ( p , !"var" , true , s ) in newline 6213 6214 let e = lgc-charge-name-find ( p , !"end" , true , s ) in newline 6215 6216 let d = s [[ !"dictionary" ]] in newline 6217 6218 let b = lgc-charge-auto1 ( d , b , v , s [[ n ]] , s [[ !"binary" ]] , e ) in newline 6219 6220 lgc-charge-bytes ( b , r ) end define ]]" 6221 6222 Find the constructs (lgcdef, lgcvar, lgcthen, lgcend, and either lgcname or lgccharge) needed for auto-construction of name or charge definitions. Then generate the definitions and replace the head of "[[ r ]]" with the result. 6223 6224 \item "[[ late define lgc-charge-name-find ( p , n , d , s ) as newline 6225 6226 let q = vt2vector* ( !"lgc" ) in newline 6227 6228 let n = lgc-splice ( q , vt2vector* ( n ) ) in newline 6229 6230 let b = lgc-charge-name2binary ( lgc-splice ( q , n ) , s ) in newline 6231 6232 if b != true then b else newline 6233 6234 let b = lgc-charge-name2binary ( n , s ) in newline 6235 6236 if b != true then b else newline 6237 6238 if d != true then lgc-string2bytes ( vector-length ( d ) , d ) else 6239 6240 let m = !"Cannot generate name and charge definitions (""!""!N and ""!""!C)" in newline 6241 6242 let m = m :: LF :: !"Can find neither " :: n :: !" nor " :: lgc-splice ( q , n ) in newline 6243 6244 lgc-throw-message ( s , p , m ) end define ]]" 6245 6246 Convert construct "[[ n ]]" prefixed with lgclgc or lgc to binary, defaulting to the string "[[ d ]]", if provided. 6247 6248 \item "[[ late define lgc-charge-name2binary ( n , s ) as newline 6249 6250 let N = lgc-grammar-get-tuple ( s , n ) in newline 6251 6252 let n = lgc-charge-best-node ( N ) in newline 6253 6254 lgc-node2binary ( n ) end define ]]" 6255 6256 Convert the name "[[ n ]]" given as a vector tree to a vector tree of bytes. Return "[[ true ]]" if "[[ n ]]" is not found. 6257 6258 \item "[[ late define lgc-charge-best-node ( N ) as newline 6259 6260 if N atom then true else newline 6261 6262 let n :: N = N in newline 6263 6264 let n prime = lgc-charge-best-node ( N ) in newline 6265 6266 if n prime then n else newline 6267 6268 let R = lgc-node2relref ( n ) in newline 6269 6270 let R prime = lgc-node2relref ( n prime ) in newline 6271 6272 if R < R prime then n else newline 6273 6274 if R prime < R then n prime else newline 6275 6276 let i = lgc-node2idx ( n ) in newline 6277 6278 let i prime = lgc-node2idx ( n prime ) in newline 6279 6280 if i < i prime then n else n prime end define ]]" 6281 6282 Return the node with lowest relative reference and index from the list "[[ N ]]" of nodes. If "[[ N ]]" is empty return "[[ true ]]". 6283 6284 \item "[[ late define lgc-charge-auto1 ( d , b , v , A , B , r ) as newline 6285 6286 if d atom then r else newline 6287 6288 let ( i :: a ) :: d = d in newline 6289 6290 let S = A [[ i ]] in newline 6291 6292 let S = lgc-string2bytes ( length ( S ) , S ) in newline 6293 6294 let r = b :: B [[ i ]] :: repeat ( a , v ) :: S :: r in newline 6295 6296 lgc-charge-auto1 ( d , b , v , A , B , r ) end define ]]" 6297 6298 Generate name or charge definitions for all constructs in the dictionary "[[ d ]]". "[[ b ]]" must contain the binary representations of lgcthen, lgcdef, and lgcname/lgccharge in that order. "[[ v ]]" must contain the binary representation of lgcvar. "[[ A ]]" must be an array from indexes to right hand sides (i.e.\ names or charges) expressed as singleton lists."[[ B ]]" must be an array from indexes to binary representations of constructs. 6299 6300 \end{statements} 6301 6302 6303 6304 \subsection{Vectorizing} 6305 6306 \begin{statements} 6307 6308 \item "[[ late define lgc-vectorize ( L , s ) as newline 6309 6310 let v = lgc-charge ( L , s ) in newline 6311 6312 let v = lgc-add-dict ( s [[ !"dictionary" ]] , v ) in newline 6313 6314 let v = lgc-add-bib ( s [[ !"refbib" ]] , v ) in newline 6315 6316 let v = lgc-add-ref ( s , v ) in newline 6317 6318 v end define ]]" 6319 6320 Reorganize the left parse tree "[[ L ]]" according to charge and add dictionary and bibliography to form the vector of the page being translated. 6321 6322 \item "[[ late define lgc-add-dict ( d , v ) as newline 6323 6324 if d atom then NULL :: v else newline 6325 6326 let ( i :: a ) :: d = d in newline 6327 6328 let v = lgc-add-dict ( d , v ) in newline 6329 6330 if i = 0 then v else newline 6331 6332 let i = lgc-card2septet* ( i ) in newline 6333 6334 let a = lgc-card2septet* ( a ) in i :: a :: v end define ]]" 6335 6336 Add the dictionary "[[ d ]]" to the vector tree "[[ v ]]". The dictionary "[[ d ]]" is supposed to have form "[[ << i :: a ,, *** >> ]]". The dictionary is supposed to be sorted in descending "[[ i ]]" but we do not depend on that. The last element (the page symbol) is supposed to have form "[[ 0 :: 0 ]]" but we do not depend on that either. 6337 6338 \item "[[ late define lgc-add-bib ( b , v ) as newline 6339 6340 if b atom then NULL :: v else newline 6341 6342 let r :: b = b in newline 6343 6344 let r = lgc-ref2vector* ( r ) in newline 6345 6346 let v = lgc-add-bib ( b , v ) in r :: v end define ]]" 6347 6348 Add the bibliography "[[ b ]]" to the vector tree "[[ v ]]". 6349 6350 \item "[[ late define lgc-ref2vector* ( r ) as newline 6351 6352 let l = vector-length ( r ) in newline 6353 6354 let l = lgc-card2septet* ( l ) in newline 6355 6356 let r = vt2vector* ( r ) in newline l :: r end define ]]" 6357 6358 Convert the reference "[[ r ]]" to a vector tree suited for inclusion in the vector of the page being translated. 6359 6360 \item "[[ late define lgc-ref-version as bt2vector ( 1 ) end define ]]" 6361 6362 \item "[[ late define lgc-hex2card ( c ) as newline 6363 6364 if !"0" <= c .and. c <= !"9" then c - "0" else newline 6365 6366 if !"A" <= c .and. c <= !"F" then c - "A" + Base else true end define ]]" 6367 6368 Convert the singleton string "[[ c ]]" to its hex value (or "[[ true ]]" if "[[ c ]]" is not a hex digit). 6369 6370 \item "[[ late define lgc-mixed2vector* ( R ) as newline 6371 6372 if R tail atom then true else newline 6373 6374 let c :: d :: R = R in newline 6375 6376 let D = bt2vector ( lgc-hex2card ( c ) * 16 + lgc-hex2card ( d ) ) in newline 6377 6378 D :: lgc-mixed2vector* ( R ) end define ]]" 6379 6380 \item "[[ late define lgc-add-ref ( s , v ) as newline 6381 6382 let h :: H :: true = lgc-parse-headline ( s [[ !"source" ]] ) in newline 6383 6384 if h then lgc-add-ref1 ( s , v ) else newline 6385 6386 let H = lgc-mixed2vector* ( reverse ( H ) ) in newline 6387 6388 let t = list-suffix ( H , 21 ) in newline 6389 6390 let R = ripemd ( t :: v ) in newline 6391 6392 let r = vt2vector* ( lgc-ref-version :: R :: t ) in newline 6393 6394 if H != r then lgc-add-ref1 ( s , v ) else newline 6395 6396 let r = append ( lgc-card2septet* ( length ( r ) ) , r ) in newline 6397 6398 r :: v end define ]]" 6399 6400 \item "[[ late define lgc-add-ref1 ( s , v ) as newline 6401 6402 let << m ,, e >> = s [[ !"time" ]] in newline 6403 6404 let m = lgc-card2septet* ( m ) in newline 6405 6406 let e = lgc-card2septet* ( e ) in newline 6407 6408 let R = ripemd ( m :: e :: v ) in newline 6409 6410 let r = vt2vector* ( lgc-ref-version :: R :: m :: e ) in newline 6411 6412 let r = append ( lgc-card2septet* ( length ( r ) ) , r ) in newline 6413 6414 r :: v end define ]]" 6415 6416 \end{statements} 6417 6418 6419 6420 \subsection{Invokation of the parser} 6421 6422 \begin{statements} 6423 6424 \item "[[ late define lgc-parse1 ( x , s ) as newline 6425 6426 let g = s [[ !"grammar" ]] in newline 6427 6428 let a = s [[ !"body" ]] in newline 6429 6430 let e :: v = lgc-parse ( g , a ) catch in newline 6431 6432 if e then lgc-parse-ambiguous ( v , s ) else newline 6433 6434 if v head != true then lgc-parse-no-interpretations ( v , s ) else newline 6435 6436 let e :: b = vt2vector* ( lgc-vectorize ( v tail , s ) ) catch in newline 6437 6438 if e then lgc-report-messages ( b ) else newline 6439 6440 let s = s [[ !"vector" -> b ]] in newline 6441 6442 lgc-parse2 ( s ) end define ]]" 6443 6444 Parse body according to given grammar. Store the resulting vector in "[[ s [[ !"vector" ]] ]]". Then pass control to "[[ lgc-parse2 ( s ) ]]" to handle header. 6445 6446 \item "[[ late define lgc-parse2 ( s ) as newline 6447 6448 let r :: true = lgw-parse-string ( s [[ !"vector" ]] ) in newline 6449 6450 let s = s [[ !"reference" -> r ]] in newline 6451 6452 let h :: R :: S = lgc-parse-headline ( s [[ !"source" ]] ) in newline 6453 6454 if h then lgc-parse3 ( s ) else newline 6455 6456 let r prime = lgc-string2mixed ( r ) in newline 6457 6458 if r prime = reverse ( R ) then newline lgc-parse4 ( r prime , s ) else newline 6459 6460 let S = h :: r prime :: S in newline 6461 6462 let s = lgc-progress ( !"Writing header back to source" , 3 , s ) in newline 6463 6464 let s = lgc-push-event ( s , fileWrite ( s [[ !"sourcename" ]] , S ) ) in newline 6465 6466 lgc-parse3 ( s ) end define ]]" 6467 6468 If source has no header, invoke codifier by a call to "[[ lgc-parse3 ( s ) ]]". If source has correct header, see if the page is already codified by a call to "[[ lgc-parse4 ( r prime , s ) ]]". If source has incorrect header, write correct header back to source and invoke codifier. 6469 6470 \item "[[ late define lgc-parse3 ( s ) as newline 6471 6472 let s = lgc-progress ( !"Codifying" , 3 , s ) in newline 6473 6474 lgc-exec-events ( s , lgc-parse-codify-lgw ( x , s ) ) end define ]]" 6475 6476 Invoke codifier. 6477 6478 \item "[[ late define lgc-parse4 ( r , s ) as newline 6479 6480 let s = s [[ !"path" -> s [[ !"parameters" ]] [[ !"path" ]] ]] in newline 6481 6482 lgc-parse5 ( s [[ !"mixed" -> r ]] ) end define ]]" 6483 6484 Set "[[ s [[ !"path" ]] ]]" to the search path and "[[ s [[ !"mixed" ]] ]]" to the mixed endian hexadecimal representation of the reference. Then see if the page is already codified. 6485 6486 \item "[[ late define lgc-parse5 ( s ) as newline 6487 6488 let P = s [[ !"path" ]] in newline 6489 6490 if P atom then lgc-parse3 ( s ) else newline 6491 6492 let p :: P = P in newline 6493 6494 let s = s [[ !"path" -> P ]] in newline 6495 6496 let e :: p = lgc-replace-colon ( vt2vector* ( p ) , s [[ !"mixed" ]] ) catch in newline 6497 6498 if e then lgc-load-no-colon ( s ) else newline 6499 6500 if lgc-file-suffix ( p ) != lgr-suffix then lgc-parse5 ( s ) else newline 6501 6502 if lgc-prefix ( lgc-http-prefix , p ) then lgc-parse5 ( s ) else newline 6503 6504 if lgc-prefix ( lgc-lgw-prefix , p ) then lgc-parse5 ( s ) else newline 6505 6506 if lgc-prefix ( lgc-name-prefix , p ) then lgc-parse5 ( s ) else newline 6507 6508 let p = if lgc-prefix ( lgc-file-prefix , p ) then list-suffix ( p , 5 ) else p in newline 6509 6510 let p = lgc-tilde-expand1 ( p , s ) in newline 6511 6512 let s = lgc-progress ( !"Reading file:" :: p , 4 , s ) in newline 6513 6514 let s = lgc-push-event ( s , fileTypeRead ( p ) ) in newline 6515 6516 lgc-exec-events ( s , lgc-parse6 ( x , s ) ) end define ]]" 6517 6518 See if the page is already codified. 6519 6520 \item "[[ late define lgc-parse6 ( x , s ) as newline 6521 6522 let << true ,, << true ,, true :: x >> >> = x in newline 6523 6524 if x then lgc-parse5 ( s ) else newline 6525 6526 let e :: c = sl2rack ( x ) catch in newline 6527 6528 if e then lgc-load-malformed-page ( s ) else newline 6529 6530 let r :: b = c [[ !"bibliography" ]] in newline 6531 6532 let c = true [[ 0 -> r ]] [[ r -> c ]] in newline 6533 6534 let s = s [[ << !"cluster" ,, r >> => c ]] in newline 6535 6536 let s = lgc-load-codify-closure ( r , s ) in newline 6537 6538 let c = s [[ !"cluster" ]] [[ r ]] in newline 6539 6540 let c = lgr-cache-restore ( c ) in newline 6541 6542 let s = s [[ << !"cluster" ,, r >> => c ]] in newline 6543 6544 let s = lgc-progress ( !"Rendering" , 3 , s ) in newline 6545 6546 lgc-exec-events ( s , lgc-render ( x , s ) ) end define ]]" 6547 6548 \end{statements} 6549 6550 6551 6552 \subsection{Definition of the parser} 6553 6554 \begin{statements} 6555 6556 \item "[[ late define lgc-parse ( g , a ) as newline 6557 6558 let t = << << lgc-esc-left ,, 0 ,, true >> >> in newline 6559 6560 let s = << g >> in newline 6561 6562 let r = << 0 ,, s >> in newline 6563 6564 lgc-parse-token ( a , t , s , r , g ) end define ]]" 6565 6566 Push a left bracket onto "[[ t ]]", set the top of the stack to the entire grammar, and set "[[ r ]]" to the best result so far (which is that we have moved zero characters into "[[ a ]]"). Then try to parse a token since a token is the only thing that can follow a left bracket in a left parse tree. 6567 6568 \item "[[ late define lgc-parse-any ( p , a , t , s , r , g ) as newline 6569 6570 let r = lgc-parse-left ( p , a , t , s , r , g ) in newline 6571 6572 let r = lgc-parse-right ( p , a , t , s , r , g ) in newline 6573 6574 let r = lgc-parse-brace ( p , a , t , s , r , g ) in newline 6575 6576 lgc-parse-token ( a , t , s , r , g ) end define ]]" 6577 6578 Parse the list "[[ a ]]" of tokens, accumulating the associated left parse tree in reverse order in "[[ t ]]". "[[ p ]]" is the position in the source file of the last parsed character. "[[ s ]]" is a stack of positions in the grammar which indicates where the parser is in the grammar. All elements of "[[ s ]]" below the top element are positioned right after a double quote. The value of "[[ r ]]" is the best result so far. "[[ g ]]" is the entire grammar. During parsing, one may regard "[[ g ]]" as a constant. 6579 6580 The `any' function above in turn tries to add a left bracket, a right bracket, a right brace, and a token to "[[ t ]]". This covers all possibilities which is what `any' refers to. 6581 6582 \item "[[ late define lgc-parse-left ( p , a , t , s , r , g ) as newline 6583 6584 if t head head = lgc-esc-left then r else newline 6585 6586 let G = s head [[ QQ ]] in newline 6587 6588 if G then r else newline 6589 6590 let t = << lgc-esc-left ,, p ,, true >> :: t in newline 6591 6592 lgc-parse-token ( a , t , g :: G :: s tail , r , g ) end define ]]" 6593 6594 If "[[ t ]]" starts with a left bracket we cannot add one more so we return the best result "[[ r ]]" found so far. Else, advance the top of the stack "[[ s ]]" by a double quote and store the result in "[[ G ]]". If "[[ G ]]" is empty, adding a left bracket to "[[ t ]]" is no option and we return the best result "[[ r ]]" found so far. Else add a left bracket to "[[ t ]]", replace the top of "[[ s ]]" by "[[ G ]]", and then push a fresh copy of the entire grammar "[[ g ]]" onto "[[ s ]]". 6595 6596 The function tries to add to "[[ t ]]" a \emph{left} bracket which is what `left' in the function name refers to. Only tokens can follow a left bracket, so the function calls the `token' function in case it succeeds to add a left bracket. 6597 6598 \item "[[ late define lgc-parse-right ( p , a , t , s , r , g ) as newline 6599 6600 let G = s head [[ 0 ]] in newline 6601 6602 if G then r else newline 6603 6604 let t = << lgc-esc-right ,, p ,, G >> :: t in newline 6605 6606 let s = s tail in newline 6607 6608 if .not. s then lgc-parse-any ( p , a , t , s , r , g ) else 6609 6610 if .not. a then r else newline 6611 6612 if r head then << r tail ,, t >> raise else true :: t end define ]]" 6613 6614 Advance the top of the stack "[[ s ]]" by an end of construct marker and store the result in "[[ G ]]". If "[[ G ]]" is empty, adding a right bracket to "[[ t ]]" is no option and we return the best result "[[ r ]]" found so far. Else add a right bracket to "[[ t ]]" and pop "[[ s ]]". If "[[ a ]]" or "[[ s ]]" are non-empty, continue parsing. Else, we have found an interpretation "[[ t ]]". If "[[ t ]]" is the second interpretation found, throw an exception containing both interpretations. Else return the interpretation as the best result found so far. 6615 6616 The function tries to add to "[[ t ]]" a \emph{right} bracket which is what `right' in the function name refers to. 6617 6618 \item "[[ late define lgc-parse-brace ( p , a , t , s , r , g ) as newline 6619 6620 let G = s head [[ 0 ]] in newline 6621 6622 if G then r else newline 6623 6624 if t head head = lgc-esc-right then r else newline 6625 6626 let t = << lgc-esc-brace ,, p ,, G >> :: t in newline 6627 6628 let G = g [[ QQ ]] in newline 6629 6630 if G then r else newline 6631 6632 let s = s tail in newline 6633 6634 lgc-parse-token ( a , t , G :: s , r , g ) end define ]]" 6635 6636 Same as the previous function with the following exceptions: (1) The stack "[[ s ]]" is handled differently. (2) To enforce all constructs to be right associative and to have the same charge, we check if "[[ a head head = lgc-esc-right ]]". If it is, we cannot add a brace since a right brace is not allowed to follow a right bracket. 6637 6638 The function tries to add to "[[ t ]]" a right \emph{brace} which is what `brace' in the function name refers to. Recall that "[[ t ]]" may contain right but not left braces. Only tokens can follow a left brace, so the function calls the `token' function in case it succeeds to add a left brace. 6639 6640 \item "[[ late define lgc-parse-token ( a , t , s , r , g ) as newline 6641 6642 if a then r else newline 6643 6644 let T :: a = a in newline 6645 6646 let G = s head [[ T head ]] in newline 6647 6648 if G then r else newline 6649 6650 let << true ,, p >> :: true = a in newline 6651 6652 let p = default ( - 1 , p ) in newline 6653 6654 let t = T :: t in newline 6655 6656 let s = G :: s tail in newline 6657 6658 let r = lgc-parse-best ( r , p , s ) in newline 6659 6660 lgc-parse-any ( p , a , t , s , r , g ) end define ]]" 6661 6662 If "[[ a ]]" is empty there are no more tokens to parse and we return the best result "[[ r ]]" found so far. Else, we advance the top of "[[ s ]]" by the next token and store the result in "[[ G ]]". If "[[ G ]]" is empty, moving a token to "[[ t ]]" is no option and we return "[[ r ]]". Else, we move the token to "[[ t ]]". The value of the best result found so far is updated if moving the token make us move farther into "[[ a ]]" than has been done before. 6663 6664 The function tries to add to "[[ t ]]" a \emph{token} which is what `token' in the function name refers to. All four kinds of items (left bracket, right bracket, right brace, or token) can follow a left brace, so the function calls the `any' function in case it succeeds to add a token. 6665 6666 \item "[[ late define lgc-parse-best ( r , p , s ) as newline 6667 6668 if r head then r else newline 6669 6670 if r head = - 1 then r else newline 6671 6672 if p = -1 then p :: s else newline 6673 6674 if r head > p then r else p :: s end define ]]" 6675 6676 Return the best result of "[[ r ]]" and "[[ p :: s ]]". If "[[ r head = true ]]" then "[[ r ]]" contains an interpretation which is better than the partial result "[[ p :: s ]]". Otherwise, "[[ r ]]" has form "[[ p prime :: s prime ]]" in which case one prefers the larger of "[[ p ]]" and "[[ p prime ]]" except that a value of "[[ - 1 ]]" denotes the end of the file which is larger than any position inside the file. 6677 6678 \end{statements} 6679 6680 6681 6682 \subsection{Message generators} 6683 6684 \begin{statements} 6685 6686 \item "[[ late define lgc-parse-no-interpretations ( v , s ) as newline 6687 6688 let p :: S = v in newline 6689 6690 let m = !"Syntax error" in newline 6691 6692 let m = m :: LF :: !"Cannot parse beyond this point" in newline 6693 6694 let a = lgc-parse-no-inter1 ( S ) in newline 6695 6696 let a = vt2vector* ( a ) in newline 6697 6698 if a then lgc-error ( s , p , m :: LF :: !"Expected e.g. end of file" :: LF :: !"---" ) else newline 6699 6700 let m = m :: LF :: !"Expected e.g. |" in newline 6701 6702 let m = m :: list-prefix ( a , 50 ) in newline 6703 6704 let m = m :: LF :: !"---" in newline 6705 6706 lgc-error ( s , p , m ) end define ]]" 6707 6708 Complain about syntactically invalid page. Suggest possible continuation. 6709 6710 \item "[[ late define lgc-parse-no-inter1 ( S ) as newline 6711 6712 if S atom then true else newline 6713 6714 lgc-shortest ( S head ) tail :: lgc-parse-no-inter1 ( S tail ) end define ]]" 6715 6716 Convert list "[[ S ]]" of grammars into possible continuation. 6717 6718 \item "[[ late define lgc-shortest ( g ) as newline 6719 6720 if g then 1 :: true else newline 6721 6722 if g head intp then lgc-shortest1 ( g ) else newline 6723 6724 lgc-shortest2 ( g ) end define ]]" 6725 6726 Return "[[ l :: r ]]" where "[[ r ]]" is the shortest production in the grammar "[[ g ]]" and "[[ l ]]" is the lenght of "[[ r ]]". 6727 6728 \item "[[ late define lgc-shortest1 ( g ) as newline 6729 6730 let c :: g = g in newline 6731 6732 if c = 0 then 0 :: true else newline 6733 6734 let l :: r = lgc-shortest ( g ) in l + 1 :: c :: r end define ]]" 6735 6736 Same as "[[ lgc-shortest ( g ) ]]" except that the head of "[[ g ]]" is known to be an integer. 6737 6738 \item "[[ late define lgc-shortest2 ( g ) as newline 6739 6740 let r = lgc-shortest ( g head ) in newline 6741 6742 let R = lgc-shortest ( g tail ) in newline 6743 6744 if r then R else newline 6745 6746 if R then r else newline 6747 6748 if r head < R head then r else R end define ]]" 6749 6750 Same as "[[ lgc-shortest ( g ) ]]" except that the head of "[[ g ]]" is known not to be an integer. 6751 6752 \item "[[ late define lgc-parse-ambiguous ( v , s ) as newline 6753 6754 lgc-parse-ambiguous1 ( reverse ( v zeroth ) , reverse ( v first ) , s ) end define ]]" 6755 6756 Complain about ambiguous page. 6757 6758 \item "[[ late define lgc-parse-ambiguous1 ( a , b , s ) as newline 6759 6760 if a head = b head then lgc-parse-ambiguous1 ( a tail , b tail , s ) else newline 6761 6762 let p = default ( a head tail head , b head tail head ) in newline 6763 6764 let m = !"Ambiguous source text" in newline 6765 6766 let m = m :: LF :: lgc-parse-ambiguous2 ( a ) in newline 6767 6768 let m = m :: LF :: lgc-parse-ambiguous2 ( b ) in newline 6769 6770 lgc-error ( s , p , m ) end define ]]" 6771 6772 Find first difference between the interpretations "[[ a ]]" and "[[ b ]]" and construct an error message based on that. 6773 6774 \item "[[ late define lgc-parse-ambiguous2 ( a ) as newline 6775 6776 if a then !"Could be at the end of the text" else newline 6777 6778 let c = a head head in newline 6779 6780 let p = lgc-parse-ambiguous3 ( a ) in newline 6781 6782 let c = lgc-parse-ambiguous4 ( a , 0 ) in newline 6783 6784 << !"Could be " ,, p ,, !" of " ,, c >> end define ]]" 6785 6786 Translate the list "[[ a ]]" of tokens into a possible interpretation. 6787 6788 "[[ late define lgc-parse-ambiguous3 ( a ) as newline 6789 6790 let c = a head head in newline 6791 6792 if c = lgc-esc-right .or. c = lgc-esc-brace then !"at the end" else newline 6793 6794 if c = lgc-esc-left then !"at the start" else !"in the middle" end define ]]" 6795 6796 Find location inside construct (start, middle, or end). 6797 6798 "[[ late define lgc-parse-ambiguous4 ( a , l ) as newline 6799 6800 if a atom then !"no construct" else newline 6801 6802 let << c ,, p ,, v >> :: a = a in newline 6803 6804 if c = lgc-esc-left then lgc-parse-ambiguous4 ( a , l + 1 ) else newline 6805 6806 if c != lgc-esc-right .and. c != lgc-esc-brace then lgc-parse-ambiguous4 ( a , l ) else newline 6807 6808 if l > 0 then lgc-parse-ambiguous4 ( a , if c = lgc-esc-brace then l else l - 1 ) else newline 6809 6810 let << << r ,, i ,, C ,, p ,, n ,, b >> >> = v in newline 6811 6812 if r then !"special construct" else << !"construct " ,, n >> end define ]]" 6813 6814 Skip "[[ l ]]" right brackets, then return the name of the next bracket or brace. 6815 6816 \item "[[ late define lgc-parse-ambiguous-construct ( a , s ) as newline 6817 6818 let << p ,, << R ,, i >> ,, << R prime ,, i prime ,, true ,, true ,, n prime >> >> = a in newline 6819 6820 let m = !"Use of ambiguous construct " :: n prime in newline 6821 6822 let m = m :: LF :: !"Could be construct " :: lgc-itoa ( i ) :: !" of reference " :: lgc-itoa ( R ) in newline 6823 6824 let m = m :: LF :: !"Could be construct " :: lgc-itoa ( i prime ) :: !" of reference " :: lgc-itoa ( R prime ) in newline 6825 6826 lgc-throw-message ( s , p , m ) end define ]]" 6827 6828 \item "[[ late define lgc-parse-cannot-trisect ( s ) as newline 6829 6830 lgc-simple-error ( !"Could not trisect generated page" , s ) end define ]]" 6831 6832 \item "[[ late define lgc-proclaim-error ( t , s ) as newline 6833 6834 let s = lgc-push-event ( s , writeln request ( !"Invalid proclamation:" ) ) in newline 6835 6836 let s = lgc-push-event ( s , writeln request ( lgc-tree2vt ( t , s ) ) ) in newline 6837 6838 lgc-do-events ( s ) end define ]]" 6839 6840 \end{statements} 6841 6842 6843 6844 \subsection{Codification of parsed page} 6845 6846 The function defined in this section codifies the page being translated as opposed to the function in Section \ref{sec:CodifyingLoadedPages} which codifies transitively referenced pages. 6847 6848 \begin{statements} 6849 6850 \item "[[ late define lgc-parse-codify-lgw ( x , s ) as newline 6851 6852 let v = s [[ !"vector" ]] in newline 6853 6854 let e :: c = lgw-trisect ( v ) catch in newline 6855 6856 if e then lgc-parse-cannot-trisect ( s ) else newline 6857 6858 let r = c [[ 0 ]] in newline 6859 6860 let s = s [[ << !"cluster" ,, r >> => c ]] in newline 6861 6862 let s = lgc-load-codify-closure ( r , s ) in newline 6863 6864 let c = s [[ !"cluster" ]] [[ r ]] in newline 6865 6866 let e :: c = lgw-codify ( r , c , s [[ !"verbose" ]] ) catch in newline 6867 6868 if e then lgc-proclaim-error ( c , s ) else newline 6869 6870 let s = s [[ << !"cluster" ,, r >> => c ]] in newline 6871 6872 let s = lgc-progress ( !"Rendering" , 3 , s ) in newline 6873 6874 lgc-exec-events ( s , lgc-render ( x , s ) ) end define ]]" 6875 6876 Trisect and codify the Logiweb vector "[[ v ]]". Then pass control to "[[ lgc-render ( x , s ) ]]" to render the page. 6877 6878 \end{statements} 6879 6880 6881 6882 " ]"\section{Rendering}\label{sec:Rendering}"[ " 6883 6884 \subsection{Layout of rendering} 6885 6886 Pages are rendered in a \emph{rendering directory}. The name of the rendering directory is obtained by replacing the rightmost colon character of the ``rendering'' option by the reference of the page in mixed endian hexadecimal. The default value of the rendering option is 6887 6888 \begin{verbatim} 6889 ~/.logiweb/logiweb/:/ 6890 \end{verbatim} 6891 6892 The rack of a page is stored as ``rack.lgr'' in the rendering directory. 6893 6894 Rendering of a page results in the following entries in the rendering directory: 6895 6896 \begin{description} 6897 6898 \item[index.html] Overview with html pointers. 6899 6900 \item[vector.lgw] The vector of the page (`lgw' for `LoGiWeb', acknowledging that this format is the main format for exchanges of Logiweb pages over the Internet). 6901 6902 \item[rack.lgr] The rack of the page. 6903 6904 \item[ref.lgp] The reference of the page (`p' in `lgp' stands for `pointer'; the obvious choice `r' for reference was taken by `rack'). 6905 6906 \item[source.lgs] The source text (if known). 6907 6908 \item[diagnose.txt] Diagnose as text, i.e.\ as Logiweb source text. 6909 6910 \item[diagnose.html] Diagnose in html. 6911 6912 \item[extract.html] Extract (time stamp, bibliography, dictionary, codex, and priority table) in html. 6913 6914 \item[logiweb.png] Logiweb icon in png. 6915 6916 \item[logiweb.ico] Logiweb favicon (small icon for browser titlebar). 6917 6918 \item[page/] Directory containing the user defined rendering of the page. 6919 6920 \item[page/logiweb.eps] Logiweb icon in eps. 6921 6922 \item[page/lgwinclude.tex] Include file with useful \TeX\ definitions. 6923 6924 \item[page/index.html] Typical location of document overview. 6925 6926 \item[page/page.pdf] Typical location of main document. 6927 6928 \item[page/diagnose.pdf] Typical location of diagnose in pdf. 6929 6930 \item[page/bin/] Typical location of generated binaries. 6931 6932 \end{description} 6933 6934 Contents of extract: 6935 6936 \begin{itemize} 6937 6938 \item Name and reference of page 6939 6940 \item Bibliography containing relref, name, and ref. 6941 6942 \item Codex. One codex section per symbol containing: name, index, arity, refname, relref, ref, definitions. 6943 6944 \item Priority table. 6945 6946 \end{itemize} 6947 6948 The following have been abandonned in favour of leaving such representations to user defined rendering: Rack in lisp. Rack in xml. Source translated to html. 6949 6950 6951 6952 \subsection{State entries} 6953 6954 Rendering uses the following entries of the state: 6955 6956 \begin{itemize} 6957 6958 \item "[[ s [[ !"reference" ]] ]]" The reference as a vector. 6959 6960 \item "[[ s [[ !"vector" ]] ]]" The page vector as a list of singletons. 6961 6962 \end{itemize} 6963 6964 6965 6966 \subsection{Messages} 6967 6968 \begin{statements} 6969 6970 \item "[[ late define lgc-rendering-no-colon ( s ) as newline 6971 6972 lgc-simple-error ( !"Missing colon in rendering option" , s ) end define ]]" 6973 6974 \end{statements} 6975 6976 6977 6978 \subsection{Translation of terms to Logiweb source} 6979 6980 The construct "[[ lgc-tree2vt ( t , s ) ]]" converts the tree "[[ t ]]" to a vector tree based on the state "[[ s ]]". 6981 6982 \begin{statements} 6983 6984 \item "[[ late define lgc-tree2vector* ( t , s ) as newline 6985 6986 if t then true else vt2vector* ( lgc-tree2vt ( t , s ) ) end define ]]" 6987 6988 Convert the tree "[[ t ]]" into a source text representation of "[[ t ]]". As a special case, if "[[ t ]]" is "[[ true ]]" then "[[ true ]]" is returned. 6989 6990 \item "[[ late define lgc-string2vt ( t ) as newline 6991 6992 if t = '' then QQ :: QQ :: !"." else newline 6993 6994 let t = vector2vector* ( t ) in newline 6995 6996 ( if t head = QQ then QQ :: QQ :: !"-" else QQ ) :: lgc-string2vt1 ( t ) :: QQ end define ]]" 6997 6998 Convert the string "[[ t ]]" given as a vector to a source representation of that string. 6999 7000 \item "[[ late define lgc-string2vt1 ( t ) as newline 7001 7002 if t atom then true else newline 7003 7004 let c :: t = t in newline 7005 7006 ( if c = QQ then QQ :: QQ :: !"!" else c ) :: lgc-string2vt1 ( t ) end define ]]" 7007 7008 Convert the string "[[ t ]]" given as a singleton list to a source representation in which quotes are escaped. 7009 7010 \item "[[ late define lgc-symbol2vt ( r , i , s ) as newline 7011 7012 lgc-symbol2vt1 ( r , i , s [[ !"cluster" ]] [[ r ]] ) end define ]]" 7013 7014 Convert reference "[[ r ]]" and index "[[ i ]]" into a symbol name using the state "[[ s ]]". 7015 7016 \item "[[ late define lgc-symbol2vt1 ( r , i , c ) as newline 7017 7018 let a = c [[ r ]] [[ !"dictionary" ]] [[ i ]] in newline 7019 7020 lgc-aritysymbol2vt1 ( r , i , a , c ) end define ]]" 7021 7022 Convert reference "[[ r ]]" and index "[[ i ]]" into a symbol name using the cache "[[ c ]]". 7023 7024 \item "[[ late define lgc-tree2vt ( t , s ) as newline 7025 7026 lgc-tree2vt0 ( false , false , t , s ) end define ]]" 7027 7028 Convert the tree "[[ t ]]" into a source text representation of "[[ t ]]". 7029 7030 \item "[[ late define lgc-tree2vt0 ( p , q , t , s ) as newline 7031 7032 let << r ,, i >> :: t = t in newline 7033 7034 if r = 0 then lgc-string2vt ( i ) else newline 7035 7036 let n = lgc-symbol2vt ( r , i , s ) in newline 7037 7038 let P = ( n head = QQ ) in newline 7039 7040 let Q = ( n last = QQ ) in newline 7041 7042 let t = lgc-tree*2vt ( P , Q , t , s ) in newline 7043 7044 let t = lgc-tree2vt1 ( n , t ) in newline 7045 7046 if q .and. P .or. p .and. Q then newline 7047 7048 << QQ ,, QQ ,, !"[" ,, t ,, QQ ,, QQ ,, !"]" >> else t end define ]]" 7049 7050 Convert the tree "[[ t ]]" into a source text representation of "[[ t ]]". "[[ p ]]" is true if "[[ t ]]" is the first argument of a pre-open construct and "[[ q ]]" is true if "[[ t ]]" is the last argument of a post-open construct. 7051 7052 \item "[[ late define lgc-open as << QQ ,, QQ ,, !"[" >> end define ]]" 7053 7054 \item "[[ late define lgc-close as << QQ ,, QQ ,, !"]" >> end define ]]" 7055 7056 \item "[[ late define lgc-tree*2vt ( P , Q , t , s ) as newline 7057 7058 if t atom then true else newline 7059 7060 lgc-tree2vt0 ( P , Q .and. t tail , t head , s ) :: lgc-tree*2vt ( false , Q , t tail , s ) end define ]]" 7061 7062 Apply "[[ lgc-tree2vt ( t , s ) ]]" to each element of "[[ t ]]". 7063 7064 \item "[[ late define lgc-tree2vt1 ( n , t ) as newline 7065 7066 if n atom then true else newline 7067 7068 let c :: n = n in newline 7069 7070 if c != QQ then c :: lgc-tree2vt1 ( n , t ) else newline 7071 7072 t head :: lgc-tree2vt1 ( n , t tail ) end define ]]" 7073 7074 Merge production "[[ n ]]" with treelist "[[ t ]]". 7075 7076 \item "[[ late define lgc-ref2vt ( r , s ) as newline 7077 7078 lgc-tree2vt ( << << r ,, 0 >> >> , s ) end define ]]" 7079 7080 Convert the reference "[[ r ]]" to the name of the associated page. 7081 7082 \end{statements} 7083 7084 7085 7086 \subsection{Translation of terms to Logiweb source} 7087 7088 The construct "[[ tree2vt ( t , c ) ]]" is not used in the lgc compiler but is included here because of its general applicability. It uses the cache "[[ c ]]" instead of the state "[[ s ]]". 7089 7090 \begin{statements} 7091 7092 \item "[[ eager define tree2vt ( t , c ) as newline 7093 7094 let << r ,, i >> :: t = t in newline 7095 7096 if r = 0 then lgc-string2vt ( i ) else newline 7097 7098 let n = lgc-symbol2vt1 ( r , i , c ) in newline 7099 7100 let t = tree*2vt ( t , c ) in newline 7101 7102 lgc-tree2vt1 ( n , t ) end define ]]" 7103 7104 Convert the tree "[[ t ]]" into a source text representation of "[[ t ]]". 7105 7106 \item "[[ eager define tree*2vt ( t , c ) as newline 7107 7108 if t atom then true else newline 7109 7110 tree2vt ( t head , c ) :: tree*2vt ( t tail , c ) end define ]]" 7111 7112 Apply "[[ tree2vt ( t , c ) ]]" to each element of "[[ t ]]". 7113 7114 \end{statements} 7115 7116 7117 7118 \subsection{General html constructors} 7119 7120 \begin{statements} 7121 7122 \item "[[ late define lgc-vector*2html ( w ) as newline 7123 7124 if w atom then true else newline 7125 7126 let c :: v = w in newline 7127 7128 if c = LF then CRLF :: lgc-vector*2html ( v ) else newline 7129 7130 if c < SP then lgc-vector*2html ( v ) else newline 7131 7132 if c = !"<" then !"<" :: lgc-vector*2html ( v ) else newline 7133 7134 if c = !">" then !">" :: lgc-vector*2html ( v ) else newline 7135 7136 if c = !"&" then !"&" :: lgc-vector*2html ( v ) else newline 7137 7138 if c != QQ then c :: lgc-vector*2html ( v ) else newline 7139 7140 if lgc-prefix ( lgc-open , w ) then lgc-html-open ( w ) else newline 7141 7142 if lgc-prefix ( lgc-close , w ) then lgc-html-close ( w ) else newline 7143 7144 c :: lgc-vector*2html ( v ) end define ]]" 7145 7146 Escape special html characters in "[[ v ]]". Translate understood opening and closing brackets by blue brackets. 7147 7148 \item "[[ late define lgc-html-open ( w ) as newline 7149 7150 let w = lgc-vector*2html ( list-suffix ( w , 3 ) ) in newline 7151 7152 !"[" :: w end define ]]" 7153 7154 Produce blue opening bracket. 7155 7156 \item "[[ late define lgc-html-close ( w ) as newline 7157 7158 let w = lgc-vector*2html ( list-suffix ( w , 3 ) ) in newline 7159 7160 !"]" :: w end define ]]" 7161 7162 Produce blue closing bracket. 7163 7164 \item "[[ late define lgc-tree2html ( t , s ) as newline 7165 7166 lgc-vector*2html ( vt2vector* ( lgc-tree2vt ( t , s ) ) ) end define ]]" 7167 7168 Translate the tree "[[ t ]]" to Logiweb source and escape special html characters. 7169 7170 \item "[[ late define lgc-html-begin ( t ) as !"<" :: t :: !">" end define ]]" 7171 7172 Enclose "[[ t ]]" in angle brackets, forming an opening tag. 7173 7174 \item "[[ late define lgc-html-end ( t ) as lgc-html-begin ( !"/" :: t ) end define ]]" 7175 7176 Prepend "[[ t ]]" by a slash and enclose in angle brackets, forming a closing tag. 7177 7178 \item "[[ late define lgc-html-tag ( t ) as lgc-html-begin ( t :: !"/" ) end define ]]" 7179 7180 Suffix "[[ t ]]" by a slash and enclose in angle brackets, forming a self contained tag. 7181 7182 \item "[[ late define lgc-html-br as lgc-html-tag ( !"br" ) :: CRLF end define ]]" 7183 7184 \item "[[ late define lgc-html-wrap ( t , b ) as newline 7185 7186 lgc-html-begin ( t ) :: b :: lgc-html-end ( t ) end define ]]" 7187 7188 Sandwich the body "[[ b ]]" between an opening and closing tag. 7189 7190 \item "[[ late define lgc-html-title ( t ) as lgc-html-wrap ( !"title" , t ) end define ]]" 7191 7192 Turn the string "[[ t ]]" into a title. 7193 7194 \item "[[ late define lgc-html-h2 ( t ) as CRLF :: lgc-html-wrap ( !"h2" , t ) end define ]]" 7195 7196 Turn the string "[[ t ]]" into headline. 7197 7198 \item "[[ late define lgc-html-h3 ( t ) as CRLF :: lgc-html-wrap ( !"h3" , t ) end define ]]" 7199 7200 Turn the string "[[ t ]]" into a second level headline. 7201 7202 \item "[[ late define lgc-html-h4 ( t ) as CRLF :: lgc-html-wrap ( !"h4" , t ) end define ]]" 7203 7204 Turn the string "[[ t ]]" into a third level headline. 7205 7206 \item "[[ late define lgc-html-p ( t ) as lgc-html-wrap ( !"p" , t ) end define ]]" 7207 7208 Turn the string "[[ t ]]" into a paragraph. 7209 7210 \item "[[ late define lgc-html-it ( t ) as lgc-html-wrap ( !"i" , t ) end define ]]" 7211 7212 Display the string "[[ t ]]" in italics. 7213 7214 \item "[[ late define lgc-html-tt ( t ) as lgc-html-wrap ( !"tt" , t ) end define ]]" 7215 7216 Display the string "[[ t ]]" in fixed width font. 7217 7218 \item "[[ late define lgc-html-ptt ( t ) as lgc-html-p ( lgc-html-tt ( t ) ) end define ]]" 7219 7220 Turn the string "[[ t ]]" into a paragraph in fixed width font. 7221 7222 \item "[[ late define lgc-html-string ( t ) as QQ :: t :: QQ end define ]]" 7223 7224 Enclose "[[ t ]]" in double quote characters. 7225 7226 \item "[[ late define lgc-html-arg ( k , v ) as newline 7227 7228 !" " :: k :: !"=" :: lgc-html-string ( v ) end define ]]" 7229 7230 Construct a keyword/value pair for inclusion in a tag. 7231 7232 \item "[[ late define lgc-html-favicon ( r ) as newline 7233 7234 let a = lgc-html-arg ( !"rel" , r ) in newline 7235 7236 let a = a :: lgc-html-arg ( !"href" , !"logiweb.ico" ) in newline 7237 7238 let a = a :: lgc-html-arg ( !"type" , !"image/x-icon" ) in newline 7239 7240 lgc-html-tag ( !"link" :: a ) end define ]]" 7241 7242 Construct a Logiweb favicon for inclusion in the head of an html page. The given ``rel'' type "[[ r ]]" may be "[[ !"icon" ]]" or "[[ !"shortcut icon" ]]". 7243 7244 \item "[[ late define lgc-html-utf8 as newline 7245 7246 let a = lgc-html-arg ( !"http-equiv" , !"Content-Type" ) in newline 7247 7248 let a = a :: lgc-html-arg ( !"content" , !"text/html; charset=UTF-8" ) in newline 7249 7250 lgc-html-tag ( !"meta" :: a ) end define ]]" 7251 7252 \item "[[ late define lgc-html-head ( t ) as newline 7253 7254 let a = lgc-html-utf8 in newline 7255 7256 let a = a :: CRLF :: lgc-html-title ( t ) in newline 7257 7258 let a = a :: CRLF :: lgc-html-favicon ( !"icon" ) in newline 7259 7260 let a = a :: CRLF :: lgc-html-favicon ( !"shortcut icon" ) in newline 7261 7262 lgc-html-wrap ( !"head" , a ) end define ]]" 7263 7264 Construct a head with the given title. 7265 7266 \item "[[ late define lgc-html-icon as newline 7267 7268 let a = lgc-html-arg ( !"alt" , !"Logiweb(TM)" ) in newline 7269 7270 let a = a :: CRLF :: lgc-html-arg ( !"align" , !"right" ) in newline 7271 7272 let a = a :: CRLF :: lgc-html-arg ( !"src" , !"logiweb.png" ) in newline 7273 7274 let a = a :: CRLF :: lgc-html-arg ( !"height" , !"62" ) in newline 7275 7276 let a = a :: CRLF :: lgc-html-arg ( !"width" , !"46" ) in newline 7277 7278 let a = a :: CRLF :: lgc-html-arg ( !"hspace" , !"30" ) in newline 7279 7280 lgc-html-tag ( !"img" :: a ) end define ]]" 7281 7282 Construct a Logiweb icon for inclusion in the body of an html page. 7283 7284 \item "[[ late define lgc-html-href ( r , t ) as newline 7285 7286 let a = lgc-html-begin ( !"a" :: lgc-html-arg ( !"href" , r ) ) in newline 7287 7288 a :: t :: lgc-html-end ( !"a" ) end define ]]" 7289 7290 Construct an html reference. 7291 7292 \item "[[ late define lgc-html-name ( r , t ) as newline 7293 7294 let a = lgc-html-begin ( !"a" :: lgc-html-arg ( !"name" , r ) ) in newline 7295 7296 a :: t :: lgc-html-end ( !"a" ) end define ]]" 7297 7298 Construct an html anchor. 7299 7300 \item "[[ late define lgc-html-named-h3 ( r , t ) as newline 7301 7302 lgc-html-h3 ( lgc-html-name ( r , t ) ) end define ]]" 7303 7304 Construct a second level headline which can serve as an anchor. 7305 7306 \item "[[ late define lgc-html-address ( s ) as newline 7307 7308 let r = s [[ !"reference" ]] in newline 7309 7310 let T = lgc-lgt2grdutc2vt ( lgc-ref2lgt ( r ) , s ) in newline 7311 7312 let h = !"http://logiweb.eu/logiweb/doc/compiler/index.html" in newline 7313 7314 let a = lgc-html-href ( h , !"The Logiweb compiler (lgc)" ) in newline 7315 7316 let h = !"http://logiweb.eu/logiweb/doc/misc/time.html" in newline 7317 7318 let a = a :: CRLF :: lgc-html-href ( h , T ) in newline 7319 7320 let a = lgc-html-wrap ( !"address" , a ) in newline 7321 7322 lgc-html-p ( a ) end define ]]" 7323 7324 Footer of auto-generated Logiweb pages. 7325 7326 \item "[[ late define lgc-html-body ( t , b , s ) as newline 7327 7328 let a = lgc-html-icon in newline 7329 7330 let a = a :: CRLF :: lgc-html-h2 ( t ) in newline 7331 7332 let a = a :: CRLF :: b :: CRLF :: CRLF :: lgc-html-address ( s ) in newline 7333 7334 lgc-html-wrap ( !"body" , a ) end define ]]" 7335 7336 Body of auto-generated Logiweb pages. 7337 7338 \item "[[ late define lgc-html-page ( t , b , s ) as newline 7339 7340 lgc-html-head ( t ) :: CRLF :: lgc-html-body ( t , b , s ) end define ]]" 7341 7342 Autogenerated Logiweb page with title "[[ t ]]" and body "[[ b ]]". 7343 7344 \item "[[ late define lgc-html-help as newline 7345 7346 let h = !"http://logiweb.eu/logiweb/doc/index.html" in newline 7347 7348 lgc-html-href ( h , !"Help" ) end define ]]" 7349 7350 \end{statements} 7351 7352 7353 7354 \subsection{Rendering} 7355 7356 \begin{statements} 7357 7358 \item "[[ late define lgc-render ( x , s ) as newline 7359 7360 let r = s [[ !"reference" ]] in newline 7361 7362 let t = lgc-ref2lgt ( r ) in newline 7363 7364 let u = lgc-lgt2grdutc2vt ( t , s ) in newline 7365 7366 let e :: p = lgc-render-dirname ( r , s ) catch in newline 7367 7368 if e then lgc-rendering-no-colon ( s ) else newline 7369 7370 let n = lgc-tree2html ( << << r ,, 0 >> >> , s ) in newline 7371 7372 let s = lgc-render-dir ( p , s ) in newline 7373 7374 let s = lgc-render-link ( p , s ) in newline 7375 7376 let s = lgc-render-icons ( p , s ) in newline 7377 7378 let s = lgc-render-index ( p , n , s ) in newline 7379 7380 let s = lgc-render-extract ( r , p , n , s ) in newline 7381 7382 let s = lgc-render-vector ( p , s ) in newline 7383 7384 let s = lgc-render-ref ( p , s ) in newline 7385 7386 let s = lgc-render-source ( p , s ) in newline 7387 7388 let s = lgc-progress ( !"Verifying" , 3 , s ) in newline 7389 7390 lgc-exec-events ( s , lgc-render-verify ( x , s ) ) end define ]]" 7391 7392 Render standard contents of root directory of page except diagnose. Then pass control to verification. 7393 7394 \end{statements} 7395 7396 7397 7398 \subsection{Rendering directory} 7399 7400 \begin{statements} 7401 7402 \item "[[ late define lgc-render-add-slash ( p ) as newline 7403 7404 if p then true else newline 7405 7406 let c :: p = p in newline 7407 7408 if p != true then c :: lgc-render-add-slash ( p ) else newline 7409 7410 if c = !"/" then << c >> else << c ,, !"/" >> end define ]]" 7411 7412 Add a slash to the end of the singleton list "[[ p ]]" unless "[[ p ]]" already has such a slash. 7413 7414 \item "[[ late define lgc-render-dirname ( r , s ) as newline 7415 7416 let r = lgc-string2mixed ( r ) in newline 7417 7418 let R :: true = s [[ !"parameters" ]] [[ !"rendering" ]] in newline 7419 7420 let R = lgc-render-add-slash ( vt2vector* ( R ) ) in newline 7421 7422 let p = lgc-replace-colon ( R , r ) in newline 7423 7424 lgc-tilde-expand1 ( p , s ) end define ]]" 7425 7426 Return the name of the rendering directory. 7427 7428 \item "[[ late define lgc-render-dir ( p , s ) as newline 7429 7430 lgc-push-event ( s , fileMkdir ( p :: !"page/" ) ) end define ]]" 7431 7432 Create the directory "[[ p ]]" and its ancestors. Also create a subdirectory named `page' under "[[ p ]]". (Actually, the function creates p/page and all its ancestors, including p itself). 7433 7434 \end{statements} 7435 7436 7437 7438 \subsection{Rendering of links} 7439 7440 \begin{statements} 7441 7442 \item "[[ late define lgc-lgs-suffix as reverse ( vt2vector* ( ".lgs" ) ) end define ]]" 7443 7444 \item "[[ late define lgc-page-name ( s ) as newline 7445 7446 let n = s [[ !"parameters" ]] [[ !"source" ]] head in newline 7447 7448 let n = vt2vector* ( n ) in newline 7449 7450 let n = reverse ( n ) in newline 7451 7452 let e :: n prime = lgc-parse-prefix ( lgc-lgs-suffix , n ) catch in 7453 7454 let n = if e then n else n prime in newline 7455 7456 lgc-page-name1 ( n , true ) end define ]]" 7457 7458 Return the name of the source file with directory names and suffix "[[ !".lgs" ]]" removed if present. As an example, if the source file is named "[[ !"../foo.lgs" ]]" then "[[ << !"f" ,, !"o" ,, !"o" >> ]]" is returned. 7459 7460 \item "[[ late define lgc-page-name1 ( n , r ) as newline 7461 7462 if n atom then r else newline 7463 7464 let c :: n = n in newline 7465 7466 if c = !"/" then r else newline 7467 7468 lgc-page-name1 ( n , c :: r ) end define ]]" 7469 7470 Remove directory names from the reverse path name "[[ n ]]" and accumulate the result in "[[ r ]]". 7471 7472 \item "[[ late define lgc-render-link ( p , s ) as newline 7473 7474 if s [[ !"stack" ]] != true then s else newline 7475 7476 let p = lgc-cwd-expand ( p , s ) in newline 7477 7478 let L = s [[ !"parameters" ]] [[ !"link" ]] in newline 7479 7480 let N = lgc-page-name ( s ) in newline 7481 7482 lgc-render-link1 ( p , N , L , s ) end define ]]" 7483 7484 Generate all links to the page root directory. 7485 7486 \item "[[ late define lgc-render-link1 ( p , N , L , s ) as newline 7487 7488 if L atom then s else newline 7489 7490 let l :: L = L in newline 7491 7492 let e :: n = lgc-replace-colon ( vt2vector* ( l ) , N ) catch in newline 7493 7494 let n = if e then l else n in newline 7495 7496 let n = lgc-tilde-expand1 ( n , s ) in newline 7497 7498 let s = lgc-push-event ( s , fileMkdir ( n ) ) in newline 7499 7500 let s = lgc-push-event ( s , fileRm ( n ) ) in newline 7501 7502 let s = lgc-push-event ( s , fileSymlink ( p , n ) ) in newline 7503 7504 lgc-render-link1 ( p , N , L , s ) end define ]]" 7505 7506 Replace the rightmost colon of each element of the link list "[[ L ]]" by the name "[[ N ]]" and create a link which points to "[[ p ]]". Also create ancestor directories as needed and overwrite the link if it exists already. 7507 7508 \end{statements} 7509 7510 7511 7512 \subsection{Rendering of non-html} 7513 7514 \begin{statements} 7515 7516 \item "[[ late define lgc-render-vector ( p , s ) as newline 7517 7518 let E = fileWrite ( p :: !"vector.lgw" , s [[ !"vector" ]] ) in newline 7519 7520 lgc-push-event ( s , E ) end define ]]" 7521 7522 Generate the vector of the page. 7523 7524 \item "[[ late define lgc-render-ref ( p , s ) as newline 7525 7526 let r = s [[ !"reference" ]] in newline 7527 7528 let r = lgc-string2mixed ( r ) in newline 7529 7530 let E = fileWrite ( p :: !"ref.lgp" , r ) in newline 7531 7532 lgc-push-event ( s , E ) end define ]]" 7533 7534 Generate the vector of the page. 7535 7536 \item "[[ late define lgc-render-source ( p , s ) as newline 7537 7538 let S = lgc-render-source1 ( s ) in newline 7539 7540 let E = fileWrite ( p :: !"source.lgs" , S ) in newline 7541 7542 lgc-push-event ( s , E ) end define ]]" 7543 7544 Write the source text to the rendering directory. The function is prepared for a situation where the source may be unknown. 7545 7546 \item "[[ late define lgc-render-source1 ( s ) as newline 7547 7548 let v = s [[ !"source" ]] in newline 7549 7550 if v then !"Source not known, sorry." else newline 7551 7552 let R = lgc-string2mixed ( s [[ !"reference" ]] ) in newline 7553 7554 lgc-add-headline ( s , R , v ) end define ]]" 7555 7556 Add reference to headline. Act sensibly if the source is unknown. 7557 7558 \item "[[ late define lgc-render-icons ( p , s ) as newline 7559 7560 let s = lgc-push-event ( s , fileWrite ( p :: !"logiweb.png" , lgc-logiweb.png ) ) in newline 7561 7562 let s = lgc-push-event ( s , fileWrite ( p :: !"logiweb.ico" , lgc-logiweb.ico ) ) in newline 7563 7564 lgc-push-event ( s , fileWrite ( p :: !"page/logiweb.eps" , lgc-logiweb.eps ) ) end define ]]" 7565 7566 Write icons to the rendering directory. 7567 7568 \end{statements} 7569 7570 7571 7572 \subsection{Rendering of index} 7573 7574 \begin{statements} 7575 7576 \item "[[ late define lgc-render-index ( p , n , s ) as newline 7577 7578 let t = !"Logiweb main menu of " :: n in newline 7579 7580 let a = lgc-html-h3 ( !"Rendering" ) in newline 7581 7582 let a = a :: CRLF :: lgc-html-href ( !"page/page.pdf" , !"Main text" ) in newline 7583 7584 let a = a :: CRLF :: lgc-html-href ( !"page/index.html" , !"Index" ) in newline 7585 7586 let a = a :: CRLF :: lgc-html-href ( !"page/diagnose.pdf" , !"Diagnose" ) in newline 7587 7588 let a = a :: CRLF :: lgc-html-h3 ( !"Debugging aids" ) in newline 7589 7590 let a = a :: CRLF :: lgc-html-href ( !"extract.html" , !"Extract" ) in newline 7591 7592 let a = a :: CRLF :: lgc-html-href ( !"source.lgs" , !"Source" ) in newline 7593 7594 let a = a :: CRLF :: lgc-html-href ( !"diagnose.html" , !"Diagnose" ) in newline 7595 7596 let a = a :: CRLF :: lgc-html-h3 ( !"Documentation" ) in newline 7597 7598 let a = a :: CRLF :: lgc-html-help in newline 7599 7600 let a = lgc-html-page ( t , a , s ) in newline 7601 7602 let E = fileWrite ( p :: !"index.html" , a ) in newline 7603 7604 lgc-push-event ( s , E ) end define ]]" 7605 7606 Write an html index to the rendering directory. 7607 7608 7609 7610 \subsection{Rendering of extract} 7611 7612 \begin{statements} 7613 7614 \item "[[ late define lgc-render-extract ( r , p , n , s ) as newline 7615 7616 let t = !"Logiweb extract of " :: n in newline 7617 7618 let a = lgc-html-href ( !"index.html" , !"Up" ) in newline 7619 7620 let a = a :: CRLF :: lgc-html-help in newline 7621 7622 let a = a :: CRLF :: lgc-render-extract-toc in newline 7623 7624 let a = a :: CRLF :: lgc-render-extract-date ( r , s ) in newline 7625 7626 let a = a :: CRLF :: lgc-render-bib ( r , s ) in newline 7627 7628 let a = a :: CRLF :: lgc-render-def ( r , s ) in newline 7629 7630 let a = a :: CRLF :: lgc-render-charge ( r , s ) in newline 7631 7632 let a = lgc-html-page ( t , a , s ) in newline 7633 7634 let E = fileWrite ( p :: !"extract.html" , a ) in newline 7635 7636 lgc-push-event ( s , E ) end define ]]" 7637 7638 Render the extract of the page. 7639 7640 \item "[[ late define lgc-render-extract-toc as newline 7641 7642 let a = lgc-html-href ( !"#timestamp" , !"Date of publication" ) :: lgc-html-br in newline 7643 7644 let a = a :: lgc-html-href ( !"#bibliography" , !"Bibliography" ) :: lgc-html-br in newline 7645 7646 let a = a :: lgc-html-href ( !"#codex" , !"Definitions" ) :: lgc-html-br in newline 7647 7648 let a = a :: lgc-html-href ( !"#charge" , !"Charges" ) in newline 7649 7650 let a = lgc-html-p ( a ) in newline 7651 7652 lgc-html-h3 ( !"Table of contents" ) :: CRLF :: a end define ]]" 7653 7654 Render a table of contents for the extract. 7655 7656 \item "[[ late define lgc-render-extract-date ( r , s ) as newline 7657 7658 let t = lgc-ref2lgt ( r ) in newline 7659 7660 let a = lgc-lgt2grdutc2vt ( t , s ) in newline 7661 7662 let a = a :: !" (Gregorian Date / Universal Coordinated Time)" in newline 7663 7664 let a = a :: lgc-html-br in newline 7665 7666 let a = a :: lgc-lgt2mjdtai2vt ( t ) in newline 7667 7668 let a = a :: !" (Modified Julian Day / International Atomic Time)" in newline 7669 7670 let a = a :: lgc-html-br in newline 7671 7672 let a = a :: lgc-lgt2vt ( t ) in newline 7673 7674 let a = a :: !" (Logiweb Time)" in newline 7675 7676 let a = lgc-html-p ( a ) in newline 7677 7678 lgc-html-named-h3 ( !"timestamp" , !"Date of publication" ) :: CRLF :: a end define ]]" 7679 7680 Render date of publication in three formats. 7681 7682 \end{statements} 7683 7684 7685 7686 \subsection{Rendering of bibliography} 7687 7688 \begin{statements} 7689 7690 \item "[[ late define lgc-render-bib ( r , s ) as newline 7691 7692 let b = s [[ !"cluster" ]] [[ r ]] [[ r ]] [[ !"bibliography" ]] in newline 7693 7694 let w = length ( lgc-itoa ( length ( b ) - 1 ) ) in newline 7695 7696 let a = lgc-html-named-h3 ( !"bibliography" , !"Bibliography" ) in newline 7697 7698 a :: CRLF :: lgc-html-ptt ( lgc-render-bib1 ( 0 , w , b , s ) ) end define ]]" 7699 7700 Render bibliography. 7701 7702 \item "[[ late define lgc-render-ref-link ( r , a ) as newline 7703 7704 let h = lgc-string2mixed ( r ) in newline 7705 7706 lgc-html-href ( !"../../logiweb/" :: h :: "/index.html" , a ) end define ]]" 7707 7708 Add link to page with reference r. 7709 7710 \item "[[ late define lgc-render-bib1 ( i , w , b , s ) as newline 7711 7712 let r :: b = b in newline 7713 7714 let h = lgc-string2mixed ( r ) in newline 7715 7716 let a = !"[" :: lgc-ctoa ( i , w ) :: !"] " in newline 7717 7718 let a = a :: lgc-ref2vt ( r , s ) in newline 7719 7720 let a = a :: !" (" :: h :: !")" in newline 7721 7722 let a = lgc-render-ref-link ( r , a ) in newline 7723 7724 if b then a else newline 7725 7726 a :: lgc-html-br :: lgc-render-bib1 ( i + 1 , w , b , s ) end define ]]" 7727 7728 Render each bibliography entry. 7729 7730 \end{statements} 7731 7732 7733 7734 \subsection{Rendering of definitions} 7735 7736 \begin{statements} 7737 7738 \item "[[ late define lgc-render-def ( r , s ) as newline 7739 7740 let a = lgc-html-named-h3 ( !"codex" , !"Definitions" ) in newline 7741 7742 let R = s [[ !"cluster" ]] [[ r ]] [[ r ]] in newline 7743 7744 let b = R [[ !"bibliography" ]] in newline 7745 7746 let c = R [[ !"codex" ]] in newline 7747 7748 let d = R [[ !"dictionary" ]] in newline 7749 7750 let I = array-domain ( d ) in newline 7751 7752 let a = a :: CRLF :: lgc-render-def-sym* ( r , r , I , s ) in newline 7753 7754 let c = c [[ r -> true ]] in newline 7755 7756 if c then a else newline 7757 7758 a :: CRLF :: lgc-render-def1 ( r , b , c , s ) end define ]]" 7759 7760 Render all definitions: Extract the rack "[[ R ]]" from the state "[[ s ]]". Then extract bibliography "[[ b ]]", codex "[[ c ]]", and dictionary "[[ d ]]". 7761 7762 Then render domestic definitions (i.e.\ definitions on page "[[ r ]]" of symbols from page "[[ r ]]"). The rendering of domestic definitions is special because a symbol gets a section even if it has no definitions. This allows the user to see that the symbol exists and to deduce its arity. In that way it is ensured that the information of the dictionary is present. 7763 7764 When a page has been rendered, it is removed from the codex "[[ c ]]" so that it is not rendered more than once. 7765 7766 \item "[[ late define lgc-render-def1 ( p , b , c , s ) as newline 7767 7768 if b atom then lgc-render-def2 ( p , array-domain ( c ) , c , s ) else newline 7769 7770 let r :: b = b in newline 7771 7772 let a = lgc-render-def-sym* ( p , r , array-domain ( c [[ r ]] ) , s ) in newline 7773 7774 let c = c [[ r -> true ]] in newline 7775 7776 if c then a else newline 7777 7778 a :: CRLF :: lgc-render-def1 ( p , b , c , s ) end define ]]" 7779 7780 Render definitions of symbols from directly referenced pages. Definitions are sorted according to the order in which pages are referenced. If (for some silly reason) the bibliography references some page more than once then the definitions of that page are only stated once. 7781 7782 \item "[[ late define lgc-render-def2 ( p , R , c , s ) as newline 7783 7784 if R atom then true else newline 7785 7786 let r :: R = R in newline 7787 7788 let a = lgc-render-def-sym* ( p , r , array-domain ( c [[ r ]] ) , s ) in newline 7789 7790 if R then a else newline 7791 7792 a :: CRLF :: lgc-render-def2 ( p , R , c , s ) end define ]]" 7793 7794 Render definitions of symbols from transitively referenced pages which have not yet been rendered. 7795 7796 \item "[[ late define lgc-render-def-sym* ( p , r , I , s ) as newline 7797 7798 if I atom then true else newline 7799 7800 let i :: I = I in newline 7801 7802 let a = lgc-render-def-sym ( p , r , i , s ) in newline 7803 7804 if I atom then a else newline 7805 7806 a :: CRLF :: lgc-render-def-sym* ( p , r , I , s ) end define ]]" 7807 7808 Render the definitions of the symbols with reference "[[ r ]]" and index in the list "[[ I ]]" of indices 7809 7810 \item "[[ late define lgc-render-def-sym ( p , r , i , s ) as newline 7811 7812 if r = 0 then lgc-render-def-string ( p , i , s ) else newline 7813 7814 let a = lgc-symbol2vt ( r , i , s ) in newline 7815 7816 let a = lgc-vector*2html ( a ) in newline 7817 7818 let a = lgc-html-h4 ( a ) in newline 7819 7820 let b = lgc-render-ref-link ( r , lgc-ref2vt ( r , s ) ) in newline 7821 7822 let b = !"Index " :: lgc-itoa ( i ) :: " of page " :: b in newline 7823 7824 let a = a :: CRLF :: lgc-html-p ( b ) in newline 7825 7826 let d = s [[ !"cluster" ]] [[ p ]] [[ p ]] [[ !"codex" ]] [[ r ]] [[ i ]] in newline 7827 7828 a :: CRLF :: lgc-render-def-sym1 ( d , array-domain ( d ) , s ) end define ]]" 7829 7830 Render the definitions of the symbol with reference "[[ r ]]" and index "[[ i ]]". 7831 7832 \item "[[ late define lgc-render-def-string ( p , i , s ) as newline 7833 7834 let a = lgc-vector*2html ( vt2vector* ( i ) ) in newline 7835 7836 let a = lgc-html-h4 ( lgc-html-it ( a ) ) in newline 7837 7838 let b = !"Index " :: lgc-itoa ( i ) :: " of the string page (page zero)" in newline 7839 7840 let a = a :: CRLF :: lgc-html-p ( b ) in newline 7841 7842 let d = s [[ !"cluster" ]] [[ p ]] [[ p ]] [[ !"codex" ]] [[ 0 ]] [[ i ]] in newline 7843 7844 a :: CRLF :: lgc-render-def-sym1 ( d , array-domain ( d ) , s ) end define ]]" 7845 7846 Render the definitions of the string "[[ i ]]". 7847 7848 \item "[[ late define lgc-render-def-sym1 ( D , R , s ) as newline 7849 7850 if R atom then true else newline 7851 7852 let r :: R = R in newline 7853 7854 let d = D [[ r ]] in newline 7855 7856 let a = lgc-render-def-sym2 ( d , array-domain ( d ) , s ) in newline 7857 7858 if R atom then a else newline 7859 7860 a :: CRLF :: lgc-render-def-sym1 ( D , R , s ) end define ]]" 7861 7862 Render definitions in "[[ D ]]" for the list "[[ R ]]" of aspect references. 7863 7864 \item "[[ late define lgc-render-def-sym2 ( D , I , s ) as newline 7865 7866 if I atom then true else newline 7867 7868 let i :: I = I in newline 7869 7870 let a = lgc-html-p ( lgc-render-def-sym3 ( D [[ i ]] , s ) ) in newline 7871 7872 if I atom then a else newline 7873 7874 a :: CRLF :: lgc-render-def-sym2 ( D , I , s ) end define ]]" 7875 7876 Render definitions in "[[ D ]]" for the list "[[ I ]]" of aspect indices. 7877 7878 \item "[[ late define lgc-render-def-sym3 ( t , s ) as newline 7879 7880 if t ref != 0 then lgc-tree2html ( t , s ) else newline 7881 7882 lgc-html-tt ( !"Proclamed meaning: " :: lgc-html-string ( t idx ) ) end define ]]" 7883 7884 \end{statements} 7885 7886 7887 7888 \subsection{Rendering of charges} 7889 7890 \begin{statements} 7891 7892 \item "[[ late define lgc-render-charge ( r , s ) as newline 7893 7894 let a = lgc-html-named-h3 ( !"charge" , !"Charges" ) in newline 7895 7896 let b = s [[ !"cluster" ]] [[ r ]] [[ r ]] [[ !"bibliography" ]] in newline 7897 7898 let C = lgc-collect-charge ( b , s , true ) in newline 7899 7900 a :: CRLF :: lgc-render-charge0 ( b , C , s , true ) end define ]]" 7901 7902 Construct "[[ C ]]" such that "[[ get* ( C , c ) tail ]]" equals "[[ false ]]" if some construct has charge "[[ c ]]" and such that "[[ get* ( C , c ) head [[ r ]] [[ i ]] ]]" equals "[[ false ]]" if the symbol with reference "[[ r ]]" and index "[[ i ]]" has charge "[[ c ]]". 7903 7904 \item "[[ late define lgc-collect-charge ( b , s , C ) as newline 7905 7906 if b atom then C else newline 7907 7908 let r :: b = b in newline 7909 7910 let c = s [[ !"cluster" ]] [[ r ]] [[ r ]] [[ !"codex" ]] [[ r ]] in newline 7911 7912 let C = lgc-collect-charge1 ( r , c , C ) in newline 7913 7914 lgc-collect-charge ( b , s , C ) end define ]]" 7915 7916 Collect all charges used on pages listed the bibliography "[[ b ]]" and add them to "[[ C ]]". 7917 7918 \item "[[ late define lgc-collect-charge1 ( r , c , C ) as newline 7919 7920 if c atom then C else newline 7921 7922 if c head intp then lgc-collect-charge2 ( r , c head , c tail , C ) else newline 7923 7924 let C = lgc-collect-charge1 ( r , c head , C ) in newline 7925 7926 lgc-collect-charge1 ( r , c tail , C ) end define ]]" 7927 7928 Collect all charges used by the subcodex "[[ c ]]". 7929 7930 \item "[[ late define lgc-collect-charge2 ( r , i , c , C ) as newline 7931 7932 let c = lgc-def2charge ( c [[ 0 ]] [[ !"charge" ]] ) in newline 7933 7934 lgc-collect-charge3 ( r , i , c , C ) end define ]]" 7935 7936 Add the symbol with reference "[[ r ]]", index "[[ i ]]", and charge "[[ c ]]" to "[[ C ]]". 7937 7938 \item "[[ late define lgc-collect-charge3 ( r , i , c , C ) as newline 7939 7940 if c atom then lgc-collect-charge4 ( r , i , C ) else newline 7941 7942 let C = if C tail != false then C else true [[ 0 -> C ]] in newline 7943 7944 C [[ c head -> lgc-collect-charge3 ( r , i , c tail , C [[ c head ]] ) ]] end define ]]" 7945 7946 Add the symbol with reference "[[ r ]]", index "[[ i ]]", and charge "[[ c ]]" to "[[ C ]]" by recursion in "[[ c ]]". 7947 7948 \item "[[ late define lgc-collect-charge4 ( r , i , C ) as newline 7949 7950 if C = true .or. C tail = false then C head [[ << r ,, i >> => false ]] :: false else newline 7951 7952 C [[ 0 -> lgc-collect-charge4 ( r , i , C [[ 0 ]] ) ]] end define ]]" 7953 7954 Add the symbol with reference "[[ r ]]" and index "[[ i ]]" to "[[ C ]]". Extend the charge by trailing zeros until we have "[[ C tail = false ]]". 7955 7956 \item "[[ late define lgc-render-charge0 ( b , C , s , c ) as newline 7957 7958 if C tail = false then lgc-render-charge2 ( b , C , s , c ) else newline 7959 7960 let D = array-domain ( C ) in lgc-render-charge1 ( b , C , D , s , c ) end define ]]" 7961 7962 \item "[[ late define lgc-render-charge1 ( b , C , D , s , c ) as newline 7963 7964 if D atom then true else newline 7965 7966 let d :: D = D in newline 7967 7968 let a = lgc-render-charge0 ( b , C [[ d ]] , s , d :: c ) in newline 7969 7970 if D atom then a else newline 7971 7972 a :: CRLF :: lgc-render-charge1 ( b , C , D , s , c ) end define ]]" 7973 7974 Render all charges in "[[ C ]]" in increasing order. "[[ D ]]" is the list of not yet processed part of the domain of "[[ C ]]". "[[ c ]]" accumulates the name of the charge. "[[ b ]]" is the bibliography of the page and "[[ s ]]" is the state. 7975 7976 \item "[[ late define lgc-render-charge2 ( b , C , s , c ) as newline 7977 7978 let C = C head in newline 7979 7980 let r :: b = b in newline 7981 7982 let a = lgc-render-charge-bib ( b , C , s ) in newline 7983 7984 let D = array-domain ( C [[ r ]] ) in newline 7985 7986 let a = a :: CRLF :: lgc-render-charge-self ( r , D , s ) in newline 7987 7988 let c = lgc-charge2vector* ( reverse ( lgc-parse-charge2 ( c ) ) ) in newline 7989 7990 lgc-html-h4 ( default ( !"0" , c ) ) :: CRLF :: lgc-html-ptt ( a ) end define ]]" 7991 7992 Render charge section for charge "[[ c ]]". 7993 7994 \item "[[ late define lgc-render-charge-bib ( b , C , s ) as newline 7995 7996 if b atom then true else newline 7997 7998 let r :: b = b in newline 7999 8000 let a = lgc-render-charge-bib ( b , C , s ) in newline 8001 8002 let D = array-domain ( C [[ r ]] ) in newline 8003 8004 if D then a else newline 8005 8006 lgc-symbol2vt ( r , D head , s ) :: lgc-html-br :: a end define ]]" 8007 8008 For each page listed in "[[ b ]]" render the first construct (if any) which occurs in "[[ C ]]". 8009 8010 \item "[[ late define lgc-render-charge-self ( r , D , s ) as newline 8011 8012 if D atom then true else newline 8013 8014 let i :: D = D in newline 8015 8016 let a = lgc-render-charge-self ( r , D , s ) in newline 8017 8018 lgc-symbol2vt ( r , i , s ) :: lgc-html-br :: a end define ]]" 8019 8020 Render all constructs in the list "[[ D ]]" of indices. 8021 8022 \end{statements} 8023 8024 8025 8026 \subsection{Verification} 8027 8028 \begin{statements} 8029 8030 \item "[[ late define lgc-render-verify ( x , s ) as newline 8031 8032 let r = s [[ !"reference" ]] in newline 8033 8034 let p = lgc-render-dirname ( r , s ) in newline 8035 8036 let n = lgc-tree2html ( << << r ,, 0 >> >> , s ) in newline 8037 8038 let d = s [[ !"cluster" ]] [[ r ]] [[ r ]] [[ !"diagnose" ]] untag in newline 8039 8040 let D = lgc-tree2vector* ( d , s ) in newline 8041 8042 let s = lgc-render-tdiagnose ( p , D , s ) in newline 8043 8044 let s = lgc-render-hdiagnose ( p , n , d , D , s ) in newline 8045 8046 let s = lgc-render-pdiagnose ( D , s ) in newline 8047 8048 let s = lgc-progress ( !"Dumping to cache" , 3 , s ) in newline 8049 8050 lgc-exec-events ( s , lgc-render-dump ( x , s ) ) end define ]]" 8051 8052 Render diagnose. Then pass control to cache dumping. 8053 8054 \item "[[ late define lgc-render-tdiagnose ( p , D , s ) as newline 8055 8056 let E = fileWrite ( p :: !"diagnose.txt" , D ) in newline 8057 8058 lgc-push-event ( s , E ) end define ]]" 8059 8060 Write the diagnose to the rendering directory. 8061 8062 \item "[[ late define lgc-render-pdiagnose ( D , s ) as newline 8063 8064 if D then lgc-progress ( LF :: !"The page is correct" :: LF , 2 , s ) else newline 8065 8066 let s = lgc-progress ( LF :: !"Claim failed" :: LF , 2 , s ) in newline 8067 8068 lgc-progress ( D , 3 , s ) end define ]]" 8069 8070 Write the diagnose to standard output (``p'' for ``progress'' or ``print''). 8071 8072 \end{statements} 8073 8074 8075 8076 \subsection{HTML rendering of diagnose} 8077 8078 \item "[[ late define lgc-render-hdiagnose ( p , n , d , D , s ) as newline 8079 8080 let t = !"Logiweb diagnose of " :: n in newline 8081 8082 let a = lgc-html-href ( !"index.html" , !"Up" ) in newline 8083 8084 let a = a :: CRLF :: lgc-html-help in newline 8085 8086 let d = if d then lgc-render-correct else lgc-render-hdiagnose1 ( D ) in newline 8087 8088 let a = lgc-html-page ( t , a :: CRLF :: d , s ) in newline 8089 8090 let E = fileWrite ( p :: !"diagnose.html" , a ) in newline 8091 8092 lgc-push-event ( s , E ) end define ]]" 8093 8094 Write an html version of the diagnose to the rendering directory. 8095 8096 \item "[[ late define lgc-render-correct as newline 8097 8098 lgc-html-h3 ( !"The page is correct" ) end define ]]" 8099 8100 Diagnose for correct pages. 8101 8102 \item "[[ late define lgc-render-hdiagnose1 ( D ) as newline 8103 8104 lgc-html-p ( lgc-vector*2html ( vt2vector* ( D ) ) ) end define ]]" 8105 8106 Diagnose for incorrect pages. 8107 8108 \end{statements} 8109 8110 8111 8112 \subsection{Dumping to cache} 8113 8114 \begin{statements} 8115 8116 \item "[[ late define lgc-render-dump ( x , s ) as newline 8117 8118 let r = s [[ !"reference" ]] in newline 8119 8120 let p = lgc-render-dirname ( r , s ) :: "rack.lgr" in newline 8121 8122 let R = s [[ !"cluster" ]] [[ r ]] [[ r ]] in newline 8123 8124 let R = lgr-rack-clean ( R ) in newline 8125 8126 let R = rack2sl ( R ) in newline 8127 8128 let s = lgc-progress ( !"Dumping to " :: p , 4 , s ) in newline 8129 8130 let s = lgc-push-event ( s , fileMkdir ( p ) ) in newline 8131 8132 let s = lgc-push-event ( s , fileWrite ( p , R ) ) in newline 8133 8134 let s = lgc-progress ( !"User rendering" , 3 , s ) in newline 8135 8136 lgc-exec-events ( s , lgc-render-user ( x , s ) ) end define ]]" 8137 8138 Dump the rack "[[ R ]]" and pass control to user rendering at end of rack dumping. 8139 8140 \end{statements} 8141 8142 8143 8144 8145 8146 " ]"\section{User rendering}"[ " 8147 8148 \subsection{Overview} 8149 8150 Rendering of a page comprises fixed rendering in the rendering directory as defined in Section \ref{sec:Rendering} plus user (i.e.\ author) defined rendering in a subdirectory named `page' of the rendering directory. By convension, the page directory is supposed to contain a file named `index.html' which is supposed to give a user (i.e.\ reader) friendly overview of the contents of the page directory. Furthermore, by convension, the page directory is supposed to contain a `bin' directory which is supposed to contain binaries defined on the page. 8151 8152 The author of a page may define his or her own rendering function or may rely on the default provided by the lgc-compiler. In any case, rendering is done in two stages: First, the page is converted into a vector tree "[[ R ]]" which contains \emph{rendering events}. Second, the tree "[[ R ]]" is converted into output events which are then executed by the Logiweb machine, ultimately resulting in files in the page directory. 8153 8154 Conversion of the tree "[[ R ]]" of rendering events to a list of output events is done by "[[ lgc-render-user1 ( R , true , s ) ]]" as defined in Section \ref{sec:MainUserRenderingFunctions}. This conversion allows the user to produce text files and binary files and to invoke latex, bibtex, makeindex, and dvipdfm. 8155 8156 The difference between text and binary files is in the handling of newlines. When producing a binary file, bytes are writen directly to the file. When producing a text file, newline sequences are converted to host newline sequences. 8157 8158 From the point of view of the implementer of Logiweb, the ability to call latex, bibtex, makeindex, and dvipdfm provides a cheap but not completely satisfactoy way to produce high quality documents. A more satisfactory solution would be to port those four programs to Logiweb and call them from the renderer inside the system. In that way Logiweb would not rely on external programs and could guarantee that pages would look the same regardless of e.g.\ which sty files are available at each site. 8159 8160 It should be noted that, once upon a time, Logiweb also allowed to call Mizar and also had facilities for generating MathML, XML, and several other formats. Today, Logiweb just allows the user to define his or her own renderer, so it is up to each author which formats he or she wants to support. 8161 8162 As mentioned, the author of a page may define his or her own rendering function or may rely on the default provided by the lgc-compiler. The conversion is done by "[[ lgc-render-expand ( r , s ) ]]" defined in Section \ref{sec:InvokationOfUserRendering}. In case the author has defined a renderer, it is invoked by "[[ lgc-render-expand1 ( d , V , c ) ]]", and otherwise default renderer "[[ lgc-render-default ( d , V , c ) ]]" is invoked. 8163 8164 The default renderer renders the body of the page in the page directory and the executables defined on the page in the bin directory under the page directory. The function for rendering of executables, "[[ lgc-render-exec ( r , V , c ) ]]" is quite simple. The function for rendering the body, "[[ lgc-render-body ( r , V , c ) ]]" is more complicated and resembles the function used for macro expansion on the base page. 8165 8166 However, to speed up rendering, the default renderer is split in two parts: a compiler and an evaluator. The compiler translates rendering definitions (use, show, and name definitions) to \emph{rendering code}. The evaluator evaluates the rendering code. In contrast, the macro expansion engine is an evaluator which directly interprets macro definitions. The reason for splitting rendering into compilation and evaluation is that compilation takes quite some time but only needs to be done once for each construct. Hence, each construct used is compiled and the resulting rendering code is memorized. 8167 8168 The "[[ lgc-render-body ( r , V , c ) ]]" function uses "[[ stateexpand ( t , s , c ) ]]" to render the body where "[[ t ]]" is the body expressed as a term, "[[ s ]]" is a \emph{rendering state} and "[[ c ]]" is the cache of the page. 8169 8170 A rendering state "[[ s ]]" has form "[[ f :: C :: V ]]" where "[[ f ]]" is a tagged function which is used by default for rendering subexpressions, "[[ C ]]" is used for memorizing rendering code, and "[[ V ]]" is a value passed down from calling to called renderers. In particular, "[[ V [[ !"parameters" ]] ]]" is supposed to contain the parameters used when invoking lgc. This should be used sparingly but may be used, e.g.\ when there is a need to know the newline convention of the underlying host system or when there is a need to know the location of leap seconds. In addition, "[[ V [[ !"cache" ]] ]]" contains the cache of the page. 8171 8172 8173 8174 \subsection{Variable names} 8175 8176 Default rendering converts a tree "[[ t ]]" into a vector tree "[[ R ]]" which we refer to as the rendering of "[[ t ]]". 8177 8178 In the default rendering functions, we use parameter names as follows: 8179 8180 \begin{tabular}{ll} 8181 8182 "[[ t ]]" & term to be rendered \\ 8183 8184 "[[ R ]]" & rendering \\ 8185 8186 "[[ T ]]" & right hand side of use or show definition \\ 8187 8188 "[[ p = T :: p ]]" & parameter list \\ 8189 8190 "[[ a = T :: a ]]" & argument list \\ 8191 8192 "[[ b = ( T :: t ) :: b ]]" & association list from parameters to arguments \\ 8193 8194 "[[ f ]]" & tagged function \\ 8195 8196 "[[ v ]]" & arbitrary value \\ 8197 8198 "[[ s = f :: v ]]" & rendering state \\ 8199 8200 "[[ c ]]" & cache \\ 8201 8202 \end{tabular} 8203 8204 8205 8206 \subsection{Main user rendering functions}\label{sec:MainUserRenderingFunctions} 8207 8208 \begin{statements} 8209 8210 \item "[[ late define lgc-render-user ( x , s ) as newline 8211 8212 let r = s [[ !"reference" ]] in newline 8213 8214 let E :: R = lgc-render-expand ( r , s ) catch in newline 8215 8216 if E then newline 8217 8218 lgc-simple-error ( "Exception raised during user rendering, goodbye." , s ) else newline 8219 8220 lgc-render-user1 ( R , true , s ) end define ]]" 8221 8222 Perform user rendering, then pass control to "[[ lgc-render-user1 ( R , S , s ) ]]" to get the rendering executed. 8223 8224 \item "[[ late define lgc-render-user0 ( R ) as newline 8225 8226 if R atom then true :: true else newline 8227 8228 if R head intp then R else lgc-render-user0 ( R head ) end define ]]" 8229 8230 Move down in "[[ R ]]" until right above an integer. 8231 8232 \item "[[ late define lgc-render-noevent as true [[ newline 8233 8234 !"file" -> false ]] [[ newline 8235 8236 !"exec" -> false ]] [[ newline 8237 8238 !"text" -> false ]] [[ newline 8239 8240 !"script" -> false ]] [[ newline 8241 8242 !"lgwam" -> false ]] [[ newline 8243 8244 !"latex" -> false ]] [[ newline 8245 8246 !"bibtex" -> false ]] [[ newline 8247 8248 !"makeindex" -> false ]] [[ newline 8249 8250 !"dvipdfm" -> false ]] end define ]]" 8251 8252 We have "[[ lgc-render-noevent [[ e ]] = false ]]" iff "[[ e ]]" names a rendering event. 8253 8254 \item "[[ late define lgc-render-user1 ( R , S , s ) as newline 8255 8256 if R atom then newline 8257 8258 if S then lgc-goodbye ( s ) else lgc-render-user1 ( S head , S tail , s ) else newline 8259 8260 let e :: R = R in newline 8261 8262 if .not. e intp .or. lgc-render-noevent [[ e ]] then lgc-render-user1 ( e , R :: S , s ) else 8263 8264 let s = s [[ !"renderstack" -> S ]] in newline 8265 8266 let r = s [[ !"reference" ]] in newline 8267 8268 let p = lgc-render-dirname ( r , s ) :: !"page/" in newline 8269 8270 let x :: R = lgc-render-user0 ( R ) in newline 8271 8272 if e = !"file" then lgc-render-file ( p , x , R , s ) else newline 8273 8274 if e = !"exec" then lgc-render-file-exec ( p , x , R , s ) else newline 8275 8276 if e = !"text" then lgc-render-text ( p , x , R , s ) else newline 8277 8278 if e = !"script" then lgc-render-text-exec ( p , x , R , s ) else newline 8279 8280 if e = !"lgwam" then lgc-render-lgwam ( p , x , R , s ) else newline 8281 8282 if e = !"latex" then lgc-render-invoke ( e , p , x , s ) else newline 8283 8284 if e = !"bibtex" then lgc-render-invoke ( e , p , x , s ) else newline 8285 8286 if e = !"makeindex" then lgc-render-invoke ( e , p , x , s ) else newline 8287 8288 if e = !"dvipdfm" then lgc-render-invoke ( e , p , x , s ) else 8289 8290 let s = lgc-progress ( !"Unknown rendering event: " :: e , 2 , s ) in newline 8291 8292 lgc-goodbye ( s ) end define ]]" 8293 8294 Translate the event "[[ R ]]" to an output event followed by passing control to "[[ lgc-render-user2 ( x , s ) ]]". 8295 8296 \item "[[ late define lgc-render-user2 ( x , s ) as newline 8297 8298 let s = lgc-render-response ( x , s ) in newline 8299 8300 let S = s [[ !"renderstack" ]] in newline 8301 8302 if S then lgc-goodbye ( s ) else newline 8303 8304 lgc-render-user1 ( S head , S tail , s ) end define ]]" 8305 8306 Receive the response from the previous rendering event, then search for the next rendering event. 8307 8308 \item "[[ late define lgc-render-response ( x , s ) as newline 8309 8310 let << true ,, << true ,, r >> >> = x in newline 8311 8312 if r = <<>> .or. r = << NULL >> then s else newline 8313 8314 let << p ,, e ,, n >> = s [[ !"invoked" ]] in newline 8315 8316 lgc-progress ( !"Error running " :: e :: SP :: n :: !" in " :: p , 2 , s ) end define ]]" 8317 8318 Complain if the last rendering event returned a non-zero exit code. 8319 8320 \item "[[ late define lgc-goodbye ( s ) as newline 8321 8322 if s [[ !"stack" ]] != true then lgc-load-fetch ( s ) else newline 8323 8324 let s = lgc-progress ( !"Goodbye" , 3 , s ) in newline 8325 8326 lgc-do-events ( s ) end define ]]" 8327 8328 Terminate execution. 8329 8330 \item "[[ late define lgc-render-refuse ( n , s ) as newline 8331 8332 let s = lgc-progress ( !"Improper filename: " :: n , 2 , s ) in newline 8333 8334 let s = lgc-progress ( lgc-render-path ( n ) , 2 , s ) in newline 8335 8336 lgc-goodbye ( s ) end define ]]" 8337 8338 Complain about filename, then quit. 8339 8340 \end{statements} 8341 8342 8343 8344 \subsection{Functions for executing individual rendering events} 8345 8346 \begin{statements} 8347 8348 \item "[[ late define lgc-render-file ( p , n , c , s ) as newline 8349 8350 if lgc-render-path ( n ) != true then lgc-render-refuse ( n , s ) else newline 8351 8352 let p = p :: n in newline 8353 8354 let s = lgc-progress ( !"Writing file:" :: p , 4 , s ) in newline 8355 8356 let E = fileMkdir ( p ) in newline 8357 8358 let s = lgc-push-event ( s , E ) in newline 8359 8360 let E = fileWrite ( p , c ) in newline 8361 8362 let s = lgc-push-event ( s , E ) in newline 8363 8364 lgc-exec-events ( s , lgc-render-user2 ( x , s ) ) end define ]]" 8365 8366 Write contents "[[ c ]]" to file named "[[ n ]]" relative to path "[[ p ]]". 8367 8368 \item "[[ late define lgc-render-file-exec ( p , n , c , s ) as newline 8369 8370 if lgc-render-path ( n ) != true then lgc-render-refuse ( n , s ) else newline 8371 8372 let p = p :: n in newline 8373 8374 let s = lgc-progress ( !"Writing file:" :: p , 4 , s ) in newline 8375 8376 let E = fileMkdir ( p ) in newline 8377 8378 let s = lgc-push-event ( s , E ) in newline 8379 8380 let E = fileWriteExec ( p , c ) in newline 8381 8382 let s = lgc-push-event ( s , E ) in newline 8383 8384 lgc-exec-events ( s , lgc-render-user2 ( x , s ) ) end define ]]" 8385 8386 Write contents "[[ c ]]" to executable file named "[[ n ]]" relative to path "[[ p ]]". 8387 8388 \item "[[ late define lgc-render-text ( p , n , c , s ) as newline 8389 8390 if lgc-render-path ( n ) != true then lgc-render-refuse ( n , s ) else newline 8391 8392 let p = p :: n in newline 8393 8394 let N = lgc-host-newline ( s ) in newline 8395 8396 let s = lgc-progress ( !"Writing file:" :: p , 4 , s ) in newline 8397 8398 let E = fileMkdir ( p ) in newline 8399 8400 let s = lgc-push-event ( s , E ) in newline 8401 8402 let E = textWrite ( p , N , c ) in newline 8403 8404 let s = lgc-push-event ( s , E ) in newline 8405 8406 lgc-exec-events ( s , lgc-render-user2 ( x , s ) ) end define ]]" 8407 8408 Write contents "[[ c ]]" with newline translation to file named "[[ n ]]" relative to path "[[ p ]]". 8409 8410 \item "[[ late define lgc-render-text-exec ( p , n , c , s ) as newline 8411 8412 if lgc-render-path ( n ) != true then lgc-render-refuse ( n , s ) else newline 8413 8414 let p = p :: n in newline 8415 8416 let N = lgc-host-newline ( s ) in newline 8417 8418 let s = lgc-progress ( !"Writing file:" :: p , 4 , s ) in newline 8419 8420 let E = fileMkdir ( p ) in newline 8421 8422 let s = lgc-push-event ( s , E ) in newline 8423 8424 let E = textWriteExec ( p , N , c ) in newline 8425 8426 let s = lgc-push-event ( s , E ) in newline 8427 8428 lgc-exec-events ( s , lgc-render-user2 ( x , s ) ) end define ]]" 8429 8430 Write contents "[[ c ]]" with newline translation to executable file named "[[ n ]]" relative to path "[[ p ]]". 8431 8432 \item "[[ late define lgc-render-add-lf ( a ) as newline 8433 8434 if a atom then true else newline 8435 8436 a head :: LF :: lgc-render-add-lf ( a tail ) end define ]]" 8437 8438 Add line feed after each element of "[[ a ]]". 8439 8440 \item "[[ late define lgc-render-lgwam ( p , n , c , s ) as newline 8441 8442 if lgc-render-path ( n ) != true then lgc-render-refuse ( n , s ) else newline 8443 8444 let p = p :: n in newline 8445 8446 let N = lgc-host-newline ( s ) in newline 8447 8448 let a = lgc-render-add-lf ( s [[ !"parameters" ]] [[ !"script" ]] ) in newline 8449 8450 let s = lgc-progress ( !"Writing file:" :: p , 4 , s ) in newline 8451 8452 let E = fileMkdir ( p ) in newline 8453 8454 let s = lgc-push-event ( s , E ) in newline 8455 8456 let E = textWriteExec ( p , N , a :: c ) in newline 8457 8458 let s = lgc-push-event ( s , E ) in newline 8459 8460 lgc-exec-events ( s , lgc-render-user2 ( x , s ) ) end define ]]" 8461 8462 Add script headline "[[ a ]]" to contents "[[ c ]]". Then write contents "[[ c ]]" with newline translation to executable file named "[[ n ]]" relative to path "[[ p ]]". This is supposed to work under Unix but, in the future, "[[ lgc-render-lgwam ( p , n , c , s ) ]]" is supposed to be enhanced to work under other operating systems as well. The intension is that an lgwam rendering event should work regardless of operating system. 8463 8464 \item "[[ late define lgc-render-invoke ( e , p , n , s ) as newline 8465 8466 if lgc-render-path ( n ) != true then lgc-render-refuse ( n , s ) else newline 8467 8468 let s = s [[ !"invoked" -> << p ,, e ,, n >> ]] in newline 8469 8470 let s = lgc-progress ( !"Invoking " :: e :: SP :: n , 4 , s ) in newline 8471 8472 let E = execlp1 ( p , e , n ) in newline 8473 8474 let s = lgc-push-event ( s , E ) in newline 8475 8476 lgc-exec-events ( s , lgc-render-user2 ( x , s ) ) end define ]]" 8477 8478 Write contents "[[ c ]]" with newline translation to executable file named "[[ n ]]" relative to path "[[ p ]]". 8479 8480 \end{statements} 8481 8482 8483 8484 \subsection{Safety check filename} 8485 8486 At present, we put restrictions on file names that occur in rendering events. Among other, we do not allow file names like "[[ !"../../foo" ]]". These restrictions prevent users from corrupting their file structure accidentally, but they do not provide any protection against malicious code. 8487 8488 Protection against malicious code requires one to establish a chroot or schroot jail or to abandon use of latex, bibtex, makeindex, and dvipdfm. The latter approach is best, but requires those four programs to be ported to the Logiweb programming language and included in the present compiler. 8489 8490 \begin{statements} 8491 8492 \item "[[ late define lgc-render-path ( n ) as newline 8493 8494 let n = vt2vector* ( n ) in newline 8495 8496 if n then !"Empty filename" else newline 8497 8498 if n head = !"/" then !"Relative filename starts with slash" else newline 8499 8500 if n = << !"." >> then !"Filename must be more than a dot" else newline 8501 8502 lgc-render-path-slash ( n ) end define ]]" 8503 8504 Return "[[ true ]]" if "[[ n ]]" is a proper path. Else return error message. 8505 8506 \item "[[ late define lgc-render-path-slash ( n ) as newline 8507 8508 if n atom then "Filename ends with a slash" else newline 8509 8510 if n = << !"." >> then "Filename ends with slash-dot" else newline 8511 8512 if n head = !"/" then "Filename contains two slashes in a row" else newline 8513 8514 lgc-render-path1 ( n ) end define ]]" 8515 8516 Return "[[ true ]]" if a slash followed by "[[ n ]]" is a proper path. Else return error message. 8517 8518 \item "[[ late define lgc-render-path1 ( n ) as newline 8519 8520 if n atom then true else newline 8521 8522 let c :: n = n in newline 8523 8524 if !"a" <= c .and. c <= !"z" then lgc-render-path1 ( n ) else newline 8525 8526 if !"A" <= c .and. c <= !"Z" then lgc-render-path1 ( n ) else newline 8527 8528 if !"0" <= c .and. c <= !"9" then lgc-render-path1 ( n ) else newline 8529 8530 if c = !"-" .or. c = !"_" then lgc-render-path1 ( n ) else newline 8531 8532 if c = !"." then lgc-render-path-dot ( n ) else newline 8533 8534 if c = !"/" then lgc-render-path-slash ( n ) else newline 8535 8536 !"Filename must be constructed from letters (a to z and A to Z)" :: newline 8537 8538 LF :: !"digits (0 to 9), hyphen (-), underscore (_), dot (.), and slash (/)" end define ]]" 8539 8540 Return "[[ true ]]" if non-slash followed by "[[ n ]]" is a proper path. Else return error message. 8541 8542 \item "[[ late define lgc-render-path-dot ( n ) as newline 8543 8544 if n head = !"." then !"Filename contains two dots in a row" else newline 8545 8546 lgc-render-path1 ( n ) end define ]]" 8547 8548 Return "[[ true ]]" if a dot followed by "[[ n ]]" is a proper path. Else return error message. 8549 8550 \end{statements} 8551 8552 8553 8554 \subsection{Invokation of user rendering}\label{sec:InvokationOfUserRendering} 8555 8556 The "[[ lgc-render-expand ( r , s ) ]]" function renders the page with reference "[[ r ]]" for state "[[ s ]]" and returns a list of rendering output events. 8557 8558 \begin{statements} 8559 8560 \item "[[ late define lgc-render-expand ( r , s ) as newline 8561 8562 let c = s [[ !"cluster" ]] [[ r ]] in newline 8563 8564 let V = true [[ !"cache" -> c ]] in newline 8565 8566 let V = V [[ !"parameters" -> s [[ !"parameters" ]] ]] in newline 8567 8568 let V = V [[ !"leap" -> s [[ !"leap" ]] ]] in newline 8569 8570 let d = c [[ r ]] [[ !"codex" ]] [[ r ]] [[ 0 ]] [[ 0 ]] [[ !"render" ]] in newline 8571 8572 if d pairp then lgc-render-expand1 ( d , V , c ) else newline 8573 8574 let b = c [[ r ]] [[ !"bibliography" ]] first in newline 8575 8576 if b then lgc-render-default ( r , V , c ) else newline 8577 8578 let d = c [[ b ]] [[ !"codex" ]] [[ b ]] [[ 0 ]] [[ 0 ]] [[ !"render" ]] in newline 8579 8580 if d pairp then lgc-render-expand1 ( d , V , c ) else newline 8581 8582 lgc-render-default ( r , V , c ) end define ]]" 8583 8584 Macro expand page "[[ r ]]" in cache "[[ c ]]". First look up the macro expander of the page itself and call it "[[ d ]]". If found, apply it. Else look up the macro expander of the bed page "[[ b ]]" and call it "[[ d ]]". If found, apply it. Else, default to the identity macro expander and return the body of the page. 8585 8586 \item "[[ late define lgc-render-expand1 ( d , V , c ) as newline 8587 8588 let f = eval ( d third , true , c ) in newline 8589 8590 ( f apply V maptag ) untag end define ]]" 8591 8592 Evaluate right hand side of the rendering definition "[[ d ]]". Then apply the result to the cache "[[ c ]]". 8593 8594 \item "[[ late define lgc-render-default ( r , V , c ) as newline 8595 8596 let R = lgc-render-exec ( r , V , c ) in newline 8597 8598 let R = R :: lgc-render-lgwinclude ( r , V , c ) in newline 8599 8600 let R = R :: lgc-render-diagnose ( r , V , c ) in newline 8601 8602 R :: lgc-render-body ( r , V , c ) end define ]]" 8603 8604 Default rendering of a cache "[[ c ]]" involves rendering of the body and rendering of executables. 8605 8606 \item "[[ late define lgc-render-body ( r , V , c ) as newline 8607 8608 let t = c [[ r ]] [[ "body" ]] in newline 8609 8610 stateexpand ( t , lgc-render-use :: true :: V , c ) head end define ]]" 8611 8612 Default rendering of a body is done by passing the body expressed as a term "[[ t ]]" and a rendering state "[[ f :: C :: V ]]" to the stateexpand function. 8613 8614 The real work is done by the function "[[ f ]]" which defines how to render the root of the body. "[[ f ]]" typically renders subterms of the root and then combine renderings of subterms into a rendering of the whole term. 8615 8616 The rendering cache "[[ C ]]" of accumulated information is set to "[[ true ]]". During rendering, information is accumulated in "[[ C ]]". The call to stateexpand results in a pair "[[ R :: C ]]" where "[[ R ]]" is the rendering and "[[ C ]]" is the final value of "[[ C ]]". The "[[ lgc-render-body ( r , V , c ) ]]" function discards this final "[[ C ]]" and returns the rendering "[[ R ]]". 8617 8618 The rendering state value "[[ V ]]" contains information that may by useful for the renderer. The rendering state value is passed down from calling to called renderer, so "[[ V ]]" can only be used for passing information from the root towards the leafs while rendering the body "[[ t ]]". 8619 8620 \item "[[ late define lgc-render-diagnose ( r , V , c ) as newline 8621 8622 let t = c [[ r ]] [[ "diagnose" ]] untag in newline 8623 8624 if t then lgc-render-diagnose1 ( !"No errors found" , r , V , c ) else newline 8625 8626 let R = stateexpand ( t , lgc-render-use :: true :: V , c ) head in newline 8627 8628 if t tail .or. .not. t tail tail then R else newline 8629 8630 let d = c [[ t ref ]] [[ !"codex" ]] [[ t ref ]] [[ t idx ]] [[ 0 ]] [[ !"use" ]] in newline 8631 8632 if d .or. .not. d second first t= d third then R else newline 8633 8634 lgc-render-diagnose1 ( R , r , V , c ) end define ]]" 8635 8636 \item "[[ late define lgc-render-diagnose1 ( m , r , V , c ) as newline 8637 8638 let N = lgc-render-pdftitle ( vt2vector* ( lgc-symbol2vt1 ( r , 0 , c ) ) ) in newline 8639 8640 let n = stateexpand ( << << r ,, 0 >> >> , lgc-render-show :: true :: V , c ) head in newline 8641 8642 let t = lgc-lgt2grdutc2vt ( lgc-ref2lgt ( r ) , V ) in newline 8643 8644 let R = newline 8645 8646 !"\documentclass[fleqn]{article} 8647 \setlength{\overfullrule}{1mm} 8648 \usepackage{latexsym} 8649 \setlength{\parindent}{0em} 8650 \setlength{\parskip}{1ex} 8651 \usepackage{graphicx} 8652 \usepackage[dvipdfm=true]{hyperref} 8653 \hypersetup{pdfpagemode=UseNone} 8654 \hypersetup{pdfstartpage=1} 8655 \hypersetup{pdfstartview=FitBH} 8656 \hypersetup{pdfpagescrop={120 80 490 730}} 8657 \hypersetup{pdftitle=Logiweb diagnose of " :: N :: !"} 8658 \hypersetup{colorlinks=true} 8659 \everymath{\rm} 8660 \begin{document}\raggedright 8661 \newlength{\lgwlinewidth} 8662 \setlength{\lgwlinewidth}{\linewidth} 8663 \begin{list}{}{\setlength{\leftmargin}{0mm} 8664 \setlength{\rightmargin}{20mm} 8665 \setlength{\topsep}{0mm} 8666 \setlength{\partopsep}{0mm} 8667 \setlength{\itemsep}{0mm} 8668 \setlength{\parsep}{0mm} 8669 }\item \makebox[0mm][l]{\makebox[\lgwlinewidth][r]{\includegraphics [0mm,18.5mm][16.5mm,19mm]{logiweb.eps}}}% 8670 {\bf{\Large Logiweb diagnose of $ " :: n :: !" $}} 8671 \end {list}\vspace{12.5mm} 8672 8673 " :: m :: !" 8674 8675 \vspace{2ex} 8676 8677 {\em\href{http://logiweb.eu/index.html}{The Logiweb compiler (lgc)}, 8678 \href {http://logiweb.eu/logiweb/doc/misc/time.html}{" :: t :: !"}} 8679 \end{document} 8680 8681 " in newline 8682 8683 let R = !"text" :: !"diagnose.tex" :: R in newline 8684 8685 let R = << R ,, !"latex" ,, !"diagnose" >> in newline 8686 8687 << R ,, !"dvipdfm" ,, !"diagnose" >> end define ]]" 8688 8689 \item "[[ late define lgc-render-pdftitle ( a ) as newline 8690 8691 if a atom then true else newline 8692 8693 let c :: a = a in newline 8694 8695 let a = lgc-render-pdftitle ( a ) in newline 8696 8697 if lgc-render-pdftitle1 ( c ) then c :: a else newline 8698 8699 !"(" :: lgc-string2mixed ( c ) :: !")" :: a end define ]]" 8700 8701 Convert the singleton list "[[ a ]]" into a vt which is safe to use as a pdftitle. 8702 8703 \item "[[ late define lgc-render-pdftitle1 ( c ) as newline 8704 8705 !"a" <= c .and. c <= !"z" .or. newline 8706 8707 !"A" <= c .and. c <= !"Z" .or. newline 8708 8709 !"0" <= c .and. c <= !"9" .or. newline 8710 8711 c = !" " .or. c = !":" .or. c = !"-" end define ]]" 8712 8713 Return "[[ true ]]" if "[[ c ]]" is a singleton which is safe to include in a pdftitle. This function is over-conservative. 8714 8715 \end{statements} 8716 8717 8718 8719 \subsection{Default rendering of executables} 8720 8721 \begin{statements} 8722 8723 \item "[[ late define lgc-render-exec ( r , V , c ) as newline 8724 8725 lgc-render-exec1 ( r , V , c [[ r ]] [[ !"codex" ]] [[ 0 ]] , true ) end define ]]" 8726 8727 Render all executables defined by page "[[ r ]]". 8728 8729 \item "[[ late define lgc-render-exec1 ( r , V , c , R ) as newline 8730 8731 if c atom then R else newline 8732 8733 if c head intp then lgc-render-exec2 ( r , V , c head , c tail , R ) else newline 8734 8735 lgc-render-exec1 ( r , V , c head , lgc-render-exec1 ( r , V , c tail , R ) ) end define ]]" 8736 8737 Render all executables defined by page "[[ r ]]" in subcodex "[[ c ]]" and accumulate the result in "[[ R ]]". 8738 8739 \item "[[ late define lgc-render-exec2 ( r , V , i , c , R ) as newline 8740 8741 let t = c [[ 0 ]] [[ !"execute" ]] third second in newline 8742 8743 if t then R else newline 8744 8745 let v = eval ( t , true , V [[ !"cache" ]] ) untag in newline 8746 8747 let v = lgc-render-exec-arg ( v , V ) in newline 8748 8749 let a = !"string" :: LF :: lgc-string2mixed ( r ) in newline 8750 8751 let a = a :: LF :: i :: LF :: !"execute" :: v in newline 8752 8753 let p = vt2vector ( "bin/" :: i ) in newline 8754 8755 << !"lgwam" ,, p ,, a >> :: R end define ]]" 8756 8757 Render executable if defined. 8758 8759 \item "[[ late define lgc-render-exec-arg ( v , V ) as newline 8760 8761 if v atom then LF else newline 8762 8763 let a :: v = v in newline 8764 8765 let w = lgc-render-exec-arg ( v , V ) in newline 8766 8767 if a intp then LF :: a :: w else newline 8768 8769 if .not. a mapp then w else newline 8770 8771 let a = ( a apply V maptag ) untag in newline 8772 8773 if a intp then LF :: a :: w else w end define ]]" 8774 8775 Insert newlines in front of each string in the list "[[ v ]]" of strings. Apply maptagged elements to "[[ V ]]" first. 8776 8777 \end{statements} 8778 8779 8780 8781 \subsection{Rendering of lgwinclude file} 8782 8783 Default rendering includes generation of a file named lgwinclude.tex. That file contains \TeX\ macros which can be useful to include. Using lgwinclude.tex is not a must, however. One can just as well use advanced rendering functions e.g.\ for setting \verb+\today+ to the timestamp of the page. 8784 8785 \begin{statements} 8786 8787 \item "[[ late define lgc-gdef ( x , y ) as << !"\gdef\" ,, x ,, !"{" ,, y ,, !"}" :: LF >> end define ]]" 8788 8789 Construct a \TeX\ global definition. 8790 8791 \item "[[ late define lgc-only-letters ( x ) as newline 8792 8793 if x pairp then lgc-only-letters ( x head ) :: lgc-only-letters ( x tail ) else newline 8794 8795 if .not. x intp then true else newline 8796 8797 if !"A" <= x .and. x <= !"Z" .or. !"a" <= x .and. x <= !"z" then x else true end define ]]" 8798 8799 Remove all characters which are not Latin letters from the vector tree "[[ x ]]". 8800 8801 \item "[[ late define lgc-gdef-ref ( r , c ) as newline 8802 8803 let n = lgc-symbol2vt1 ( r , 0 , c ) in newline 8804 8805 let n = vt2vector* ( n ) in newline 8806 8807 let n = lgc-only-letters ( n ) in newline 8808 8809 let X = lgc-string2mixed ( r ) in newline 8810 8811 let R = lgc-gdef ( !"lgwBlock" :: n , X ) in newline 8812 8813 R :: lgc-gdef ( !"lgwBreak" :: n , lgc-break ( X ) ) end define ]]" 8814 8815 Convert the reference "[[ r ]]" (given as a vector) into two definitions useful for referencing the page with reference "[[ r ]]". "[[ c ]]" must be the cache of the referencing page. 8816 8817 \item "[[ late define lgc-gdef-bib ( b , c ) as newline 8818 8819 if b atom then true else newline 8820 8821 lgc-gdef-ref ( b head , c ) :: lgc-gdef-bib ( b tail , c ) end define ]]" 8822 8823 Convert the bibliography "[[ b ]]" into two \TeX\ definitions for each reference. "[[ c ]]" must be the cache of the referencing page. 8824 8825 \item "[[ late define lgc-break ( v ) as lgc-break1 ( vt2vector* ( v ) ) end define ]]" 8826 8827 \item "[[ late define lgc-break1 ( v ) as newline 8828 8829 if v tail atom then v else newline 8830 8831 v head :: !"\lgwbreak" :: LF :: lgc-break1 ( v tail ) end define ]]" 8832 8833 \item "[[ late define lgc-render-lgwinclude ( r , V , c ) as newline 8834 8835 let t = lgc-ref2lgt ( r ) in newline 8836 8837 let R = lgc-gdef ( !"today" , lgc-lgt2grdutc2vt ( t , V ) ) in newline 8838 8839 let R = R :: lgc-gdef ( !"lgwlgt" , lgc-lgt2vt ( t ) ) in newline 8840 8841 let R = R :: lgc-gdef ( !"lgwmjdtai" , lgc-lgt2mjdtai2vt ( t ) ) in newline 8842 8843 let R = R :: lgc-gdef ( !"lgwgrdutc" , lgc-lgt2grdutc2vt ( t , V ) ) in newline 8844 8845 let << f ,, e >> = t in newline 8846 8847 let R = R :: lgc-gdef ( !"lgwmantissa" , lgc-itoa ( f ) ) in newline 8848 8849 let R = R :: lgc-gdef ( !"lgwexponent" , lgc-itoa ( e ) ) in newline 8850 8851 let << Y ,, M ,, D ,, h ,, m ,, s ,, f ,, e >> = lgc-lgt2grdutc ( t , V ) in newline 8852 8853 let R = R :: lgc-gdef ( !"lgwfraction" , lgc-ctoa ( f , e ) ) in newline 8854 8855 let R = R :: lgc-gdef ( !"lgwsecond" , lgc-ctoa ( s , 2 ) ) in newline 8856 8857 let R = R :: lgc-gdef ( !"lgwminute" , lgc-ctoa ( m , 2 ) ) in newline 8858 8859 let R = R :: lgc-gdef ( !"lgwhour" , lgc-ctoa ( h , 2 ) ) in newline 8860 8861 let R = R :: lgc-gdef ( !"lgwday" , lgc-ctoa ( D , 2 ) ) in newline 8862 8863 let R = R :: lgc-gdef ( !"lgwmonth" , lgc-ctoa ( M , 2 ) ) in newline 8864 8865 let R = R :: lgc-gdef ( !"lgwyear" , lgc-itoa ( Y ) ) in newline 8866 8867 let R = R :: lgc-gdef ( !"lgwbreak" , !"\linebreak[0]\hskip0em plus0.5em{}" ) in newline 8868 8869 let R = R :: lgc-gdef ( !"lgwhyphen" , !"-" ) in newline 8870 8871 let R = R :: lgc-gdef ( !"lgwunderscore" , !"\_" ) in newline 8872 8873 let X = default ( !"../../../logiweb/" , V [[ !"parameters" ]] [[ !"relay" ]] ) in newline 8874 8875 let R = R :: lgc-gdef ( !"lgwBlockRelay" , X ) in newline 8876 8877 let R = R :: lgc-gdef ( !"lgwBreakRelay" , lgc-break ( X ) ) in newline 8878 8879 let X = lgc-string2mixed ( r ) in newline 8880 8881 let R = R :: lgc-gdef ( !"lgwBlockThis" , X ) in newline 8882 8883 let R = R :: lgc-gdef ( !"lgwBreakThis" , lgc-break ( X ) ) in newline 8884 8885 let R = R :: lgc-gdef-bib ( c [[ r ]] [[ !"bibliography" ]] , c ) in newline 8886 8887 "text" :: "lgwinclude.tex" :: R end define ]]" 8888 8889 \end{statements} 8890 8891 8892 8893 \subsection{Rendering compiler} 8894 8895 The rendering compiler translates a right hand side "[[ T ]]" and a parameter list "[[ p ]]" of a rendering definition into rendering code. 8896 8897 The constituents of "[[ T ]]" are represented thus: A string "[[ << << 0 ,, i >> >> ]]" is represented by itself. A parameter is represented by the index of the parameter in the parameter list "[[ p ]]". A construct which has no value definition is represented as "[[ true ]]" followed by the translations of subterms. A construct which does have a value definition is represented as the code of that value definition followed by the translations of subterms. 8898 8899 In the latter case above, the code is assumed to be a function which does not depend on its parameters. For that reason, the code is applied to "[[ true ]]" as many times as its arity indicates to get rid of the parameters. Once that is done, the code is assumed to be a map-tagged function of one parameter. 8900 8901 The parameter is supposed to be of form "[[ a :: s :: c :: T ]]" where "[[ s ]]" in turn is of form "[[ f :: C :: V ]]". "[[ a ]]" is the list of subtrees of the construct being rendered. T is the list of subtrees of the construct in the rendering definition which is being evaluated. "[[ c ]]" is the cache of the page being rendered. "[[ f ]]" is a function suggested for rendering of subtrees (i.e.\ of the elements of "[[ a ]]"). "[[ C ]]" is used for memorizing information which only needs to be computed once (like compiled versions of definitions). "[[ V ]]" is passed down from root to leaf in the term being rendered. 8902 8903 \begin{statements} 8904 8905 \item "[[ late define lgc-index ( T , p , r ) as newline 8906 8907 if p atom then true else newline 8908 8909 if T t= p head then r else newline 8910 8911 lgc-index ( T , p tail , r + 1 ) end define ]]" 8912 8913 Find the position of the term "[[ T ]]" in the parameter list "[[ p ]]" and return that position. Return "[[ true ]]" if "[[ T ]]" is not found. 8914 8915 \item "[[ late define lgc-const2val ( f , x ) as newline 8916 8917 if x atom then f untag else newline 8918 8919 lgc-const2val ( f apply true maptag , x tail ) end define ]]" 8920 8921 Convert the code "[[ f ]]" of a constant construct to the constant value of the construct. The length of the list "[[ x ]]" indicates the arity of the construct. 8922 8923 \item "[[ late define lgc-render-compile ( T , p , c ) as newline 8924 8925 let << << r ,, i >> >> = T in newline 8926 8927 if r = 0 then T else newline 8928 8929 let f = c [[ r ]] [[ !"code" ]] [[ i ]] in newline 8930 8931 if .not. f mapp then lgc-render-compile1 ( T , p , c ) else newline 8932 8933 let f = lgc-const2val ( f , T tail ) in newline 8934 8935 if .not. f mapp then lgc-render-compile1 ( T , p , c ) else newline 8936 8937 f :: lgc-render-compile* ( T tail , p , c ) end define ]]" 8938 8939 Convert the right hand side "[[ T ]]" and parameter list "[[ p ]]" into a compiled right hand side. In a compiled right hand side, symbols are replaced by their codes, parameters are replaced by their indices, and strings are kept as they are. 8940 8941 \item "[[ late define lgc-render-compile1 ( T , p , c ) as newline 8942 8943 let t = lgc-index ( T , p , 0 ) in newline 8944 8945 if t intp then t else newline 8946 8947 true :: lgc-render-compile* ( T tail , p , c ) end define ]]" 8948 8949 Convert the right hand side "[[ T ]]" and parameter list "[[ p ]]" into a compiled right hand side when "[[ T ]]" is known not to have a valid definition. 8950 8951 \item "[[ late define lgc-render-compile* ( T , p , c ) as newline 8952 8953 if T atom then true else newline 8954 8955 lgc-render-compile ( T head , p , c ) :: lgc-render-compile* ( T tail , p , c ) end define ]]" 8956 8957 Coordinatewise application of "[[ lgc-render-compile ( T , p , c ) ]]". 8958 8959 \end{statements} 8960 8961 8962 8963 \subsection{Rendering evaluator} 8964 8965 The rendering evaluator evaluates rendering code "[[ T ]]" for a rendering state "[[ s ]]" and cache "[[ c ]]". Furthermore, the evaluator takes a list "[[ a ]]" of subtrees of the construct being rendered. 8966 8967 \begin{statements} 8968 8969 \item "[[ late define lgc-render-eval ( T , a , s , c ) as newline 8970 8971 if T intp then stateexpand ( nth ( T , a ) , s , c ) else newline 8972 8973 let f :: T = T in newline 8974 8975 let true :: C :: V = s in newline 8976 8977 if f pairp then f first :: C else newline 8978 8979 if f mapp then ( f apply ( ( a :: s :: c :: T ) maptag ) ) untag else newline 8980 8981 if T then true :: C else newline 8982 8983 if T tail then lgc-render-eval ( T head , a , lgc-render-show :: C :: V , c ) else newline 8984 8985 lgc-render-eval* ( T , a , s , c ) end define ]]" 8986 8987 Apply the compiled right hand side "[[ T ]]" to the argument list "[[ a ]]", rendering state "[[ s ]]", and cache "[[ c ]]". 8988 8989 \item "[[ late define lgc-render-eval* ( T , a , s , c ) as newline 8990 8991 let f :: C :: V = s in newline 8992 8993 if T atom then true :: C else newline 8994 8995 let A :: C = lgc-render-eval ( T head , a , s , c ) in newline 8996 8997 let B :: C = lgc-render-eval* ( T tail , a , f :: C :: V , c ) in newline 8998 8999 ( A :: B ) :: C end define ]]" 9000 9001 Coordinatewise application of "[[ lgc-render-eval ( T , a , s , c ) ]]". 9002 9003 If "[[ T ]]" is a string then the function returns the string. 9004 9005 Else, if the root of "[[ T ]]" has a value definition then we assume it to be a renderer. A renderer is supposed to be a function whose right hand side has form "[[ map ( \ u . *** ) ]]". Such a function ignores its arguments, so we use "[[ lgc-const2val ( f , x ) ]]" to convert the function to its constant value and then apply it to all available information. 9006 9007 Else, we look up "[[ T ]]" in the list "[[ b ]]" of bindings and render the subtree "[[ t ]]" if one is found. 9008 9009 Else, we concatenate the renderings of all subterms of "[[ T ]]". 9010 9011 \end{statements} 9012 9013 9014 9015 \subsection{Use rendering} 9016 9017 \begin{statements} 9018 9019 \item "[[ late define lgc-render-use as map ( \ x . lgc-render-use1 ( x ) ) end define ]]" 9020 9021 Rendering state for use rendering. 9022 9023 \item "[[ late define lgc-render-use1 ( x ) as newline 9024 9025 let << t ,, s ,, c >> = x in newline 9026 9027 let f :: C :: V = s in newline 9028 9029 if t then !"\mbox{\tt\char34}" :: C else newline 9030 9031 if t head then lgc-understood ( lgc-render-use1 ( << t first ,, s ,, c >> ) ) :: C else newline 9032 9033 let << << r ,, i >> >> = t in newline 9034 9035 if r = 0 then i :: C else newline 9036 9037 let T = C [[ !"use" ]] [[ r ]] [[ i ]] in newline 9038 9039 if .not. T then lgc-render-eval ( T , t tail , s , c ) else newline 9040 9041 let T :: C = lgc-render-compile-use ( r , i , C , c ) in newline 9042 9043 lgc-render-eval ( T , t tail , f :: C :: V , c ) end define ]]" 9044 9045 Produce the rendering of the tree "[[ t ]]" for the rendering state "[[ s ]]" and the cache "[[ c ]]". The function has to treat certain malformed trees in certain ways: A value of "[[ true ]]" has to be rendered as a double quote because the Logiweb compiler uses "[[ true ]]" as a placeholder when rendering partial trees. The Logiweb compiler uses that e.g.\ when rendering the Logiweb symbols in the dictionary of a page. Furthermore, a tree whose root is "[[ true ]]" should be enclosed in blue brackets because the Logiweb compiler represents an understood parenthesis as the root "[[ true ]]" with one subtree. The Logiweb compiler uses that e.g.\ when rendering the diagnose of a faulty page. 9046 9047 \item "[[ late define lgc-render-compile-use ( r , i , C , c ) as newline 9048 9049 let T :: C = lgc-render-compile-use1 ( r , i , C , c ) in newline 9050 9051 let C = C [[ << !"use" ,, r ,, i >> => T ]] in T :: C end define ]]" 9052 9053 Compile the use definition of the construct with reference "[[ r ]]" and index "[[ i ]]" into rendering code and memorize the result in "[[ C ]]". 9054 9055 \item "[[ late define lgc-render-compile-use1 ( r , i , C , c ) as newline 9056 9057 let d = c [[ r ]] [[ "codex" ]] [[ r ]] [[ i ]] [[ 0 ]] [[ !"use" ]] in newline 9058 9059 if d pairp then lgc-render-compile ( d third , d second tail , c ) :: C else newline 9060 9061 lgc-render-compile-show ( r , i , C , c ) end define ]]" 9062 9063 Compile the use definition of the construct with reference "[[ r ]]" and index "[[ i ]]" into rendering code. 9064 9065 \item "[[ late define lgc-understood ( t ) as newline 9066 9067 LF :: !"\ \linebreak[0]\textcolor{blue}{[}\linebreak[0]\ " :: t :: newline 9068 9069 LF :: !"\ \linebreak[0]\textcolor{blue}{]}\linebreak[0]\ " end define ]]" 9070 9071 Function for enclosing "[[ t ]]" in blue brackets. 9072 9073 \end{statements} 9074 9075 9076 9077 \subsection{Show rendering} 9078 9079 \begin{statements} 9080 9081 \item "[[ late define lgc-render-show as map ( \ x . lgc-render-show1 ( x ) ) end define ]]" 9082 9083 Rendering state for show rendering. 9084 9085 \item "[[ late define lgc-render-show1 ( x ) as newline 9086 9087 let << t ,, s ,, c >> = x in newline 9088 9089 let f :: C :: V = s in newline 9090 9091 if t then !"\mbox{\tt\char34}" :: C else newline 9092 9093 if t head then lgc-understood ( lgc-render-show1 ( << t first ,, s ,, c >> ) ) :: C else newline 9094 9095 let << << r ,, i >> >> = t in newline 9096 9097 if r = 0 then lgc-render-string ( i ) :: C else newline 9098 9099 let T = C [[ !"show" ]] [[ r ]] [[ i ]] in newline 9100 9101 if .not. T then lgc-render-eval ( T , t tail , s , c ) else newline 9102 9103 let T :: C = lgc-render-compile-show ( r , i , C , c ) in newline 9104 9105 lgc-render-eval ( T , t tail , f :: C :: V , c ) end define ]]" 9106 9107 Produce the rendering of the tree "[[ t ]]" for the rendering state "[[ s ]]" and the cache "[[ c ]]". The function has to treat certain malformed trees in certain ways: A value of "[[ true ]]" has to be rendered as a double quote because the Logiweb compiler uses "[[ true ]]" as a placeholder when rendering partial trees. The Logiweb compiler uses that e.g.\ when rendering the Logiweb symbols in the dictionary of a page. Furthermore, a tree whose root is "[[ true ]]" should be enclosed in blue brackets because the Logiweb compiler represents an understood parenthesis as the root "[[ true ]]" with one subtree. The Logiweb compiler uses that e.g.\ when rendering the diagnose of a faulty page. 9108 9109 \item "[[ late define lgc-render-compile-show ( r , i , C , c ) as newline 9110 9111 let T = lgc-render-compile-show1 ( r , i , c ) in newline 9112 9113 let C = C [[ << !"show" ,, r ,, i >> => T ]] in T :: C end define ]]" 9114 9115 \item "[[ late define lgc-render-compile-show1 ( r , i , c ) as newline 9116 9117 let d = c [[ r ]] [[ "codex" ]] [[ r ]] [[ i ]] [[ 0 ]] [[ !"show" ]] in newline 9118 9119 if d pairp then lgc-render-compile ( d third , d second tail , c ) else newline 9120 9121 lgc-render-name ( r , i , c ) end define ]]" 9122 9123 Compile the show definition of the construct with reference "[[ r ]]" and index "[[ i ]]" into rendering code. 9124 9125 \end{statements} 9126 9127 9128 9129 \subsection{Rendering based on name} 9130 9131 \begin{statements} 9132 9133 \item "[[ late define lgc-render-name ( r , i , c ) as newline 9134 9135 let n = lgc-symbol2vt1 ( r , i , c ) in newline 9136 9137 let n = vt2vector* ( n ) in newline 9138 9139 let n = lgc-render-name1 ( n , true ) in newline 9140 9141 true :: << << 0 ,, n head >> >> :: lgc-render-name2 ( n tail , 0 ) end define ]]" 9142 9143 Function for compiling constructs that do not have a tex aspect. 9144 9145 \item "[[ late define lgc-render-name1 ( n , r ) as newline 9146 9147 if n atom then << lgc-render-string0 ( reverse ( r ) ) >> else newline 9148 9149 let c :: n = n in newline 9150 9151 if c != QQ then lgc-render-name1 ( n , c :: r ) else newline 9152 9153 lgc-render-string0 ( reverse ( r ) ) :: lgc-render-name1 ( n , true ) end define ]]" 9154 9155 Convert the name "[[ n ]]" into a list of inter-quote strings. 9156 9157 \item "[[ late define lgc-render-name2 ( n , i ) as newline 9158 9159 if n atom then true else newline 9160 9161 i :: << << 0 ,, n head >> >> :: lgc-render-name2 ( n tail , i + 1 ) end define ]]" 9162 9163 Merge the list "[[ n ]]" of inter-quote strings with parameter indexes. 9164 9165 \end{statements} 9166 9167 9168 9169 \subsection{Show rendering of strings} 9170 9171 \begin{statements} 9172 9173 \item "[[ late define lgc-render-string ( i ) as newline 9174 9175 let i = vt2vector* ( i ) in newline 9176 9177 let i = lgc-render-string0 ( i ) in newline 9178 9179 !"\mbox{`}" :: i :: !"\mbox{'}" end define ]]" 9180 9181 Render the string "[[ i ]]". 9182 9183 \item "[[ late define lgc-render-string0 ( i ) as newline 9184 9185 lgc-render-string1 ( i , lgc-render-array , true ) end define ]]" 9186 9187 \item "[[ late define lgc-render-string1 ( i , a , b ) as newline 9188 9189 if i atom then lgc-render-string2 ( b , true ) else newline 9190 9191 let c :: i = i in newline 9192 9193 let d = a [[ c ]] in newline 9194 9195 if d then lgc-render-string2 ( c :: b , lgc-render-string0 ( i ) ) else newline 9196 9197 if d intp then d :: lgc-render-string0 ( i ) else newline 9198 9199 lgc-render-string1 ( i , d , c :: b ) end define ]]" 9200 9201 Look up the byte sequence at the beginning of "[[ i ]]" in the trie "[[ a ]]" and, simultaneously, accumulate the looked up bytes in "[[ b ]]". If the array provides a translation (i.e.\ if "[[ a [[ c ]] ]]" is a string) then include that translation in the result and discard "[[ b ]]". If the array provides no translation (i.e.\ if "[[ a [[ c ]] = true ]]") then give up and render "[[ b ]]" as a sequence of bytes. Otherwise, look at one more byte. 9202 9203 \item "[[ late define lgc-render-string2 ( b , i ) as newline 9204 9205 if b atom then i else newline 9206 9207 let c :: b = b in newline 9208 9209 let m :: n = floor ( c - NULL , 16 ) in newline 9210 9211 let m = lgc-hexdigit ( m ) in newline 9212 9213 let n = lgc-hexdigit ( n ) in newline 9214 9215 lgc-render-string2 ( b , !"(" :: m :: n :: !")" :: i ) end define ]]" 9216 9217 Render "[[ b ]]" as a sequence of bytes and revappend them to "[[ i ]]". 9218 9219 \item "[[ late define lgc-render-array as newline 9220 true tight endline 9221 [[ LF -> vt2vector ( LF :: !"\newline " ) ]] tight endline 9222 [[ !" " -> vt2vector ( !"\linebreak [0]\ " ) ]] tight endline 9223 [[ !"!" -> !"!" ]] tight endline 9224 [[ !""-""!" -> !"\mbox{\tt\char34}" ]] tight endline 9225 [[ !"#" -> !"\#" ]] tight endline 9226 [[ !"$" -> !"\$" ]] tight endline 9227 [[ !"%" -> !"\%" ]] tight endline 9228 [[ !"&" -> !"\&" ]] tight endline 9229 [[ !"'" -> !"\mbox{'}" ]] tight endline 9230 [[ !"(" -> !"(" ]] tight endline 9231 [[ !")" -> !")" ]] tight endline 9232 [[ !"*" -> !"{*}" ]] tight endline 9233 [[ !"+" -> !"{+}" ]] tight endline 9234 [[ !"," -> !"," ]] tight endline 9235 [[ !"-" -> !"\mbox{-}" ]] tight endline 9236 [[ !"." -> !"." ]] tight endline 9237 [[ !"/" -> !"/" ]] tight endline 9238 [[ !"0" -> !"0" ]] tight endline 9239 [[ !"1" -> !"1" ]] tight endline 9240 [[ !"2" -> !"2" ]] tight endline 9241 [[ !"3" -> !"3" ]] tight endline 9242 [[ !"4" -> !"4" ]] tight endline 9243 [[ !"5" -> !"5" ]] tight endline 9244 [[ !"6" -> !"6" ]] tight endline 9245 [[ !"7" -> !"7" ]] tight endline 9246 [[ !"8" -> !"8" ]] tight endline 9247 [[ !"9" -> !"9" ]] tight endline 9248 [[ !":" -> !"{:}" ]] tight endline 9249 [[ !";" -> !";" ]] tight endline 9250 [[ !"<" -> !"<" ]] tight endline 9251 [[ !"=" -> !"{=}" ]] tight endline 9252 [[ !">" -> !">" ]] tight endline 9253 [[ !"?" -> !"?" ]] tight endline 9254 [[ !"@" -> !"@" ]] tight endline 9255 [[ !"A" -> !"A" ]] tight endline 9256 [[ !"B" -> !"B" ]] tight endline 9257 [[ !"C" -> !"C" ]] tight endline 9258 [[ !"D" -> !"D" ]] tight endline 9259 [[ !"E" -> !"E" ]] tight endline 9260 [[ !"F" -> !"F" ]] tight endline 9261 [[ !"G" -> !"G" ]] tight endline 9262 [[ !"H" -> !"H" ]] tight endline 9263 [[ !"I" -> !"I" ]] tight endline 9264 [[ !"J" -> !"J" ]] tight endline 9265 [[ !"K" -> !"K" ]] tight endline 9266 [[ !"L" -> !"L" ]] tight endline 9267 [[ !"M" -> !"M" ]] tight endline 9268 [[ !"N" -> !"N" ]] tight endline 9269 [[ !"O" -> !"O" ]] tight endline 9270 [[ !"P" -> !"P" ]] tight endline 9271 [[ !"Q" -> !"Q" ]] tight endline 9272 [[ !"R" -> !"R" ]] tight endline 9273 [[ !"S" -> !"S" ]] tight endline 9274 [[ !"T" -> !"T" ]] tight endline 9275 [[ !"U" -> !"U" ]] tight endline 9276 [[ !"V" -> !"V" ]] tight endline 9277 [[ !"W" -> !"W" ]] tight endline 9278 [[ !"X" -> !"X" ]] tight endline 9279 [[ !"Y" -> !"Y" ]] tight endline 9280 [[ !"Z" -> !"Z" ]] tight endline 9281 [[ !"[" -> !"[" ]] tight endline 9282 [[ !"\" -> !"\mbox{$\backslash$}" ]] tight endline 9283 [[ !"]" -> !"]" ]] tight endline 9284 [[ !"^" -> !"{\char94}" ]] tight endline 9285 [[ !"_" -> !"\_" ]] tight endline 9286 [[ !"`" -> !"\mbox{`}" ]] tight endline 9287 [[ !"a" -> !"a" ]] tight endline 9288 [[ !"b" -> !"b" ]] tight endline 9289 [[ !"c" -> !"c" ]] tight endline 9290 [[ !"d" -> !"d" ]] tight endline 9291 [[ !"e" -> !"e" ]] tight endline 9292 [[ !"f" -> !"f" ]] tight endline 9293 [[ !"g" -> !"g" ]] tight endline 9294 [[ !"h" -> !"h" ]] tight endline 9295 [[ !"i" -> !"i" ]] tight endline 9296 [[ !"j" -> !"j" ]] tight endline 9297 [[ !"k" -> !"k" ]] tight endline 9298 [[ !"l" -> !"l" ]] tight endline 9299 [[ !"m" -> !"m" ]] tight endline 9300 [[ !"n" -> !"n" ]] tight endline 9301 [[ !"o" -> !"o" ]] tight endline 9302 [[ !"p" -> !"p" ]] tight endline 9303 [[ !"q" -> !"q" ]] tight endline 9304 [[ !"r" -> !"r" ]] tight endline 9305 [[ !"s" -> !"s" ]] tight endline 9306 [[ !"t" -> !"t" ]] tight endline 9307 [[ !"u" -> !"u" ]] tight endline 9308 [[ !"v" -> !"v" ]] tight endline 9309 [[ !"w" -> !"w" ]] tight endline 9310 [[ !"x" -> !"x" ]] tight endline 9311 [[ !"y" -> !"y" ]] tight endline 9312 [[ !"z" -> !"z" ]] tight endline 9313 [[ !"{" -> !"\{" ]] tight endline 9314 [[ !"|" -> !"|" ]] tight endline 9315 [[ !"}" -> !"\}" ]] tight endline 9316 [[ !"~" -> !"{\char126}" ]] tight endline 9317 [[ << NULL + 195 ,, NULL + 198 >> => !"\mbox{\AE}" ]] tight endline 9318 [[ << NULL + 195 ,, NULL + 216 >> => !"\mbox{\O}" ]] tight endline 9319 [[ << NULL + 195 ,, NULL + 197 >> => !"\mbox{\AA}" ]] tight endline 9320 [[ << NULL + 195 ,, NULL + 230 >> => !"\mbox{\ae}" ]] tight endline 9321 [[ << NULL + 195 ,, NULL + 248 >> => !"\mbox{\o}" ]] tight endline 9322 [[ << NULL + 195 ,, NULL + 229 >> => !"\mbox{\aa}" ]] tight endline 9323 end define ]]" 9324 9325 Typesetting of ASCII and Danish characters. The Danish characters are included to show how multibyte characters are treated. Once the present source is expressed in UTF-8 one can replace e.g.\ "[[ << NULL + 195 ,, NULL + 198 >> ]]" with "[[ vt2vector* ( !"x" ) ]]" where x should be replaced by \AE. 9326 9327 \end{statements} 9328 9329 9330 9331 " ]"\section{Test cases} 9332 9333 \subsection{Lexical Analysis} 9334 9335 \begin{statements} 9336 9337 \item "[[ late define lgc-test ( f ) as newline 9338 9339 let f = vt2vector* ( f ) in newline 9340 9341 let s = true [[ !"source" -> f ]] in newline 9342 9343 let s = s [[ !"verbose" -> 3 ]] in newline 9344 9345 let e :: S = lgc-lex-source ( f , s ) catch in newline 9346 9347 let s = if e then s [[ !"msg" -> S ]] else S in newline 9348 9349 s [[ !"body" -> reverse ( s [[ !"body" ]] ) ]] end define ]]" 9350 9351 The function above invokes lexical analysis on the source text "[[ f ]]". 9352 9353 At some time in the past, "[[ s [[ !"body" ]] ]]" was reversed so that it appears in natural order. But the test cases below still compare "[[ s [[ !"body" ]] ]]" to reversed lists, so the function above reverses "[[ s [[ !"body" ]] ]]" to make it work with the old test cases below. 9354 9355 \item "[[ etst lgc-test ( !"abc" ) [[ !"body" ]] ; << << !"c" ,, 2 >> ,, << !"b" ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9356 9357 \item "[[ etst lgc-test ( << !"a" ,, SP ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 2 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9358 9359 \item "[[ etst lgc-test ( << !"a" ,, SP ,, SP ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 3 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9360 9361 \item "[[ etst lgc-test ( << SP ,, SP ,, !"a" ,, SP ,, SP ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 5 >> ,, << SP ,, 3 >> ,, << !"a" ,, 2 >> >> end test ]]" 9362 9363 \item "[[ etst lgc-test ( << !"a" ,, TAB ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 2 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9364 9365 \item "[[ etst lgc-test ( << !"a" ,, FF ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 2 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9366 9367 \item "[[ etst lgc-test ( << !"a" ,, CR ,, LF ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 3 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9368 9369 \item "[[ etst lgc-test ( << !"a" ,, LF ,, CR ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 3 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9370 9371 \item "[[ etst lgc-test ( << !"a" ,, CR ,, LF ,, CR ,, LF ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 5 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9372 9373 \item "[[ etst lgc-test ( << !"a" ,, CR ,, LF ,, LF ,, CR ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 5 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9374 9375 \item "[[ etst lgc-test ( << !"a" ,, LF ,, CR ,, CR ,, LF ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 5 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9376 9377 \item "[[ etst lgc-test ( << !"a" ,, LF ,, CR ,, LF ,, CR ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 5 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9378 9379 \item "[[ etst lgc-test ( << !"a" ,, LF ,, FF ,, CR ,, !"b" >> ) [[ !"body" ]] ; << << !"b" ,, 4 >> ,, << SP ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9380 9381 \item "[[ etst lgc-test ( ""-""!""!C""!""!N""!""!S" ) [[ !"body" ]] ; << << lgc-esc-S ,, 6 >> ,, << lgc-esc-N ,, 3 >> ,, << lgc-esc-C ,, 0 >> >> end test ]]" 9382 9383 \item "[[ etst lgc-test ( << !"a""!""!;b" ,, LF ,, !"c" >> ) [[ !"body" ]] ; << << !"c" ,, 6 >> ,, << !"a" ,, 0 >> >> end test ]]" 9384 9385 \item "[[ etst lgc-test ( !"a""!""!{b""!""!}c" ) [[ !"body" ]] ; << << !"c" ,, 8 >> ,, << !"a" ,, 0 >> >> end test ]]" 9386 9387 \item "[[ etst lgc-test ( !"a""!""!{b""!""!""!}c""!""!}d" ) [[ !"body" ]] ; << << !"d" ,, 13 >> ,, << !"a" ,, 0 >> >> end test ]]" 9388 9389 \item "[[ etst lgc-test ( !"a""!bc""!d" ) [[ !"body" ]] ; << << !"d" ,, 5 >> ,, lgc-esc-- :: 1 :: !"bc" ,, << !"a" ,, 0 >> >> end test ]]" 9390 9391 \item "[[ etst lgc-test ( !"a""!""!-bc""!d" ) [[ !"body" ]] ; << << !"d" ,, 7 >> ,, lgc-esc-- :: 1 :: !"bc" ,, << !"a" ,, 0 >> >> end test ]]" 9392 9393 \item "[[ etst lgc-test ( !"a""!""!$bc""!d" ) [[ !"body" ]] ; << << !"d" ,, 7 >> ,, lgc-esc-$ :: 1 :: !"bc" ,, << !"a" ,, 0 >> >> end test ]]" 9394 9395 \item "[[ etst lgc-test ( !"a""!""!#bc""!d" ) [[ !"body" ]] ; << << !"d" ,, 7 >> ,, lgc-esc-# :: 1 :: !"bc" ,, << !"a" ,, 0 >> >> end test ]]" 9396 9397 \item "[[ etst lgc-test ( !"a""!""!#bc""!""!.d" ) [[ !"body" ]] ; << << !"d" ,, 9 >> ,, lgc-esc-# :: 1 :: !"bc" ,, << !"a" ,, 0 >> >> end test ]]" 9398 9399 \item "[[ etst lgc-test ( !"a""!b""!""!nc""!d" ) [[ !"body" ]] ; << << !"d" ,, 8 >> ,, lgc-esc-- :: 1 :: vt2vector ( !"b" :: LF :: !"c" ) ,, << !"a" ,, 0 >> >> end test ]]" 9400 9401 \item "[[ etst lgc-test ( !"a""!b""!""!!c""!d" ) [[ !"body" ]] ; << << !"d" ,, 8 >> ,, lgc-esc-- :: 1 :: vt2vector ( !"b" :: QQ :: !"c" ) ,, << !"a" ,, 0 >> >> end test ]]" 9402 9403 \item "[[ etst lgc-test ( !"a""!b""!""!-c""!d" ) [[ !"body" ]] ; << << !"d" ,, 8 >> ,, lgc-esc-- :: 1 :: vt2vector ( !"b" :: !"c" ) ,, << !"a" ,, 0 >> >> end test ]]" 9404 9405 \item "[[ etst lgc-test ( !"a""!b""!""!rc""!d" ) [[ !"body" ]] ; << << !"d" ,, 8 >> ,, lgc-esc-- :: 1 :: vt2vector ( !"b" :: CR :: !"c" ) ,, << !"a" ,, 0 >> >> end test ]]" 9406 9407 \item "[[ etst lgc-test ( !"a""!b""!""!fc""!d" ) [[ !"body" ]] ; << << !"d" ,, 8 >> ,, lgc-esc-- :: 1 :: vt2vector ( !"b" :: FF :: !"c" ) ,, << !"a" ,, 0 >> >> end test ]]" 9408 9409 \item "[[ etst lgc-test ( !"a""!b""!""!tc""!d" ) [[ !"body" ]] ; << << !"d" ,, 8 >> ,, lgc-esc-- :: 1 :: vt2vector ( !"b" :: TAB :: !"c" ) ,, << !"a" ,, 0 >> >> end test ]]" 9410 9411 \item "[[ etst lgc-test ( !"a""!b""!""!x41.c""!d" ) [[ !"body" ]] ; << << !"d" ,, 11 >> ,, lgc-esc-- :: 1 :: !"bAc" ,, << !"a" ,, 0 >> >> end test ]]" 9412 9413 \item "[[ etst lgc-test ( !"a""!b""!""!x4142.c""!d" ) [[ !"body" ]] ; << << !"d" ,, 13 >> ,, lgc-esc-- :: 1 :: !"bABc" ,, << !"a" ,, 0 >> >> end test ]]" 9414 9415 \item "[[ etst lgc-test ( !"a""!""!-""!""!x4142.""!d" ) [[ !"body" ]] ; << << !"d" ,, 13 >> ,, lgc-esc-- :: 1 :: !"AB" ,, << !"a" ,, 0 >> >> end test ]]" 9416 9417 \item "[[ etst lgc-test ( << QQ ,, SP ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: SP >> end test ]]" 9418 9419 \item "[[ etst lgc-test ( << QQ ,, SP ,, SP ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: !" " >> end test ]]" 9420 9421 \item "[[ etst lgc-test ( << QQ ,, TAB ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: SP >> end test ]]" 9422 9423 \item "[[ etst lgc-test ( << QQ ,, FF ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: vt2vector ( LF ) >> end test ]]" 9424 9425 \item "[[ etst lgc-test ( << QQ ,, CR ,, LF ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: vt2vector ( LF ) >> end test ]]" 9426 9427 \item "[[ etst lgc-test ( << QQ ,, LF ,, CR ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: vt2vector ( LF ) >> end test ]]" 9428 9429 \item "[[ etst lgc-test ( << QQ ,, CR ,, LF ,, CR ,, LF ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: vt2vector ( LF :: LF ) >> end test ]]" 9430 9431 \item "[[ etst lgc-test ( << QQ ,, CR ,, LF ,, LF ,, CR ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: vt2vector ( LF :: LF ) >> end test ]]" 9432 9433 \item "[[ etst lgc-test ( << QQ ,, LF ,, CR ,, CR ,, LF ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: vt2vector ( LF :: LF ) >> end test ]]" 9434 9435 \item "[[ etst lgc-test ( << QQ ,, LF ,, CR ,, LF ,, CR ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: vt2vector ( LF :: LF ) >> end test ]]" 9436 9437 \item "[[ etst lgc-test ( << QQ ,, LF ,, FF ,, CR ,, QQ >> ) [[ !"body" ]] ; << lgc-esc-- :: 0 :: vt2vector ( LF :: LF :: LF ) >> end test ]]" 9438 9439 \item "[[ etst lgc-test ( !"a""!""!.b" ) [[ !"body" ]] ; << << !"b" ,, 4 >> ,, lgc-esc-- :: 1 :: !"". ,, << !"a" ,, 0 >> >> end test ]]" 9440 9441 \item "[[ etst lgc-test ( !"ab""!""!Pcd""nef" ) [[ !"body" ]] ; << << !"f" ,, 9 >> ,, << !"e" ,, 8 >> ,, << !"b" ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9442 9443 \item "[[ etst lgc-test ( !"ab""!""!Pcd""nef" ) [[ !"page" ]] ; << << !"c" ,, !"d" >> >> end test ]]" 9444 9445 \item "[[ etst lgc-test ( !"ab""!""!P c d ""nef" ) [[ !"page" ]] ; << << !"c" ,, SP ,, !"d" >> >> end test ]]" 9446 9447 \item "[[ etst lgc-test ( !"ab""!""!Pab""!cd""!ef""nef" ) [[ !"page" ]] ; << << !"e" ,, !"f" >> ,, << !"c" ,, !"d" >> ,, << !"a" ,, !"b" >> >> end test ]]" 9448 9449 \item "[[ etst lgc-test ( !"ab""!""!P a b ""! c d ""! e f ""nef" ) [[ !"page" ]] ; << << !"e" ,, SP ,, !"f" >> ,, << SP ,, !"c" ,, SP ,, !"d" ,, SP >> ,, << SP ,, !"a" ,, SP ,, !"b" ,, SP >> >> end test ]]" 9450 9451 \item "[[ etst lgc-test ( !"abyz" ) [[ !"bib" ]] ; <<>> end test ]]" 9452 9453 \item "[[ etst lgc-test ( !"ab""!""!Rcd""nyz" ) [[ !"bib" ]] ; << << << !"c" ,, !"d" >> >> >> end test ]]" 9454 9455 \item "[[ etst lgc-test ( !"ab""!""!Rcd""n""!""!Ref""nyz" ) [[ !"bib" ]] ; << << << !"e" ,, !"f" >> >> ,, << << !"c" ,, !"d" >> >> >> end test ]]" 9456 9457 \item "[[ etst lgc-test ( !"ab""!""!Rcd""!ef""!gh""n""!""!Rij""nyz" ) [[ !"bib" ]] ; << << << !"i" ,, !"j" >> >> ,, << << !"g" ,, !"h" >> ,, << !"e" ,, !"f" >> ,, << !"c" ,, !"d" >> >> >> end test ]]" 9458 9459 \item "[[ etst lgc-test ( !"ab""!""!R c d ""! e f ""! g h ""n""!""!Rij""nyz" ) [[ !"bib" ]] ; << << << !"i" ,, !"j" >> >> ,, << << !"g" ,, SP ,, !"h" >> ,, << SP ,, !"e" ,, SP ,, !"f" ,, SP >> ,, << SP ,, !"c" ,, SP ,, !"d" ,, SP >> >> >> end test ]]" 9460 9461 \item "[[ etst lgc-test ( !"ab""!""!D1""n c d ""! e f ""! g h ""n""!ij""!kl""!""n""!""!D2""nmn""!""!Byz" ) [[ !"def" ]] ; << << << 45 ,, "2" >> ,, << "m" ,, "n" >> >> ,, << << 5 ,, "1" >> ,, << "c" ,, SP ,, "d" ,, SP ,, QQ ,, SP ,, "e" ,, SP ,, "f" ,, SP ,, QQ ,, SP ,, "g" ,, SP ,, "h" >> ,, << QQ ,, "i" ,, "j" ,, QQ ,, "k" ,, "l" ,, QQ >> >> >> end test ]]" 9462 9463 \item "[[ etst lgc-test ( !"ab""!""!D c d ""! e f ""! g h ""n""!ij""!kl""!""n""!""!Dmn""!""!Byz" ) [[ !"body" ]] ; << << !"z" ,, 49 >> ,, << !"y" ,, 48 >> ,, << !"b" ,, 1 >> ,, << !"a" ,, 0 >> >> end test ]]" 9464 9465 \end{statements} 9466 9467 9468 9469 \subsection{Splicing} 9470 9471 \begin{statements} 9472 9473 \item "[[ etst lgc-splice ( vt2vector* ( !" base " ) , vt2vector* ( !"if ""! then ""! else ""!" ) ) ; vt2vector* ( !"base if ""! then ""! else ""!" ) end test ]]" 9474 9475 \item "[[ etst lgc-splice ( vt2vector* ( !"base " ) , vt2vector* ( !"if ""! then ""! else ""!" ) ) ; vt2vector* ( !"base if ""! then ""! else ""!" ) end test ]]" 9476 9477 \item "[[ etst lgc-splice ( vt2vector* ( !" base" ) , vt2vector* ( !"if ""! then ""! else ""!" ) ) ; vt2vector* ( !"baseif ""! then ""! else ""!" ) end test ]]" 9478 9479 \item "[[ etst lgc-splice ( vt2vector* ( !"base" ) , vt2vector* ( !"if ""! then ""! else ""!" ) ) ; vt2vector* ( !"baseif ""! then ""! else ""!" ) end test ]]" 9480 9481 \item "[[ etst lgc-splice ( vt2vector* ( !" base " ) , vt2vector* ( !""-""! + ""!" ) ) ; vt2vector* ( !""-""! base + ""!" ) end test ]]" 9482 9483 \item "[[ etst lgc-splice ( vt2vector* ( !"base " ) , vt2vector* ( !""-""! + ""!" ) ) ; vt2vector* ( !""-""! base + ""!" ) end test ]]" 9484 9485 \item "[[ etst lgc-splice ( vt2vector* ( !" base" ) , vt2vector* ( !""-""! + ""!" ) ) ; vt2vector* ( !""-""! base+ ""!" ) end test ]]" 9486 9487 \item "[[ etst lgc-splice ( vt2vector* ( !"base" ) , vt2vector* ( !""-""! + ""!" ) ) ; vt2vector* ( !""-""! base+ ""!" ) end test ]]" 9488 9489 \item "[[ etst lgc-splice ( vt2vector* ( !" base " ) , vt2vector* ( !""-""!,""!" ) ) ; vt2vector* ( !""-""! base ,""!" ) end test ]]" 9490 9491 \item "[[ etst lgc-splice ( vt2vector* ( !"base " ) , vt2vector* ( !""-""!,""!" ) ) ; vt2vector* ( !""-""!base ,""!" ) end test ]]" 9492 9493 \item "[[ etst lgc-splice ( vt2vector* ( !" base" ) , vt2vector* ( !""-""!,""!" ) ) ; vt2vector* ( !""-""! base,""!" ) end test ]]" 9494 9495 \item "[[ etst lgc-splice ( vt2vector* ( !"base" ) , vt2vector* ( !""-""!,""!" ) ) ; vt2vector* ( !""-""!base,""!" ) end test ]]" 9496 9497 \item "[[ etst lgc-splice ( vt2vector* ( !" base " ) , vt2vector* ( !""-""! ""!" ) ) ; vt2vector* ( !""-""! base ""!" ) end test ]]" 9498 9499 \item "[[ etst lgc-splice ( vt2vector* ( !"base " ) , vt2vector* ( !""-""! ""!" ) ) ; vt2vector* ( !""-""! base ""!" ) end test ]]" 9500 9501 \item "[[ etst lgc-splice ( vt2vector* ( !" base" ) , vt2vector* ( !""-""! ""!" ) ) ; vt2vector* ( !""-""! base ""!" ) end test ]]" 9502 9503 \item "[[ etst lgc-splice ( vt2vector* ( !"base" ) , vt2vector* ( !""-""! ""!" ) ) ; vt2vector* ( !""-""! base ""!" ) end test ]]" 9504 9505 \end{statements} 9506 9507 9508 9509 \subsection{Auxiliary definitions} 9510 9511 \begin{statements} 9512 9513 \item "[[ late define selfref as self [[ 0 ]] end define ]]" 9514 9515 \item "[[ late define baseref as base [[ 0 ]] end define ]]" 9516 9517 \item "[[ late define lgw-trisect-self as newline 9518 9519 let v = self [[ selfref ]] [[ !"vector" ]] in newline 9520 9521 let c = lgw-trisect ( vt2vector* ( v ) ) in newline 9522 9523 c [[ baseref -> base [[ baseref ]] ]] end define ]]" 9524 9525 \item "[[ late define lgw-trisect-base as newline 9526 9527 lgw-trisect ( vt2vector* ( base [[ baseref ]] [[ !"vector" ]] ) ) end define ]]" 9528 9529 \item "[[ late define lgw-codify-self as lgw-codify ( selfref , lgw-trisect-self , 4 ) end define ]]" 9530 9531 \item "[[ late define lgw-codify-base as lgw-codify ( baseref , lgw-trisect-base , 4 ) end define ]]" 9532 9533 \end{statements} 9534 9535 9536 9537 \subsection{Trisecting of lgw files} 9538 9539 \begin{statements} 9540 9541 \item "[[ etst lgw-parse-string ( bt2vector* ( << 2 ,, 65 ,, 66 ,, 67 >> ) ) ; << !"AB" ,, "C" >> end test ]]" 9542 9543 \item "[[ etst lgw-parse-bibliography ( bt2vector* ( << 1 ,, 65 ,, 1 ,, 66 ,, 0 ,, 67 >> ) ) ; << << !"A" ,, !"B" >> ,, !"C" >> end test ]]" 9544 9545 \item "[[ etst lgw-parse-dictionary ( bt2vector* ( << 1 ,, 0 ,, 2 ,, 1 ,, 0 ,, 67 >> ) ) ; << true [[ 0 -> 0 ]] [[ 1 -> 0 ]] [[ 2 -> 1 ]] ,, "C" >> end test ]]" 9546 9547 \item "[[ etst lgw-trisect ( bt2vector* ( << 1 ,, 65 ,, 1 ,, 66 ,, 0 ,, 1 ,, 0 ,, 2 ,, 1 ,, 0 ,, 67 >> ) ) ; true [[ 0 -> !"A" ]] [[ << !"A" ,, !"vector" >> => bt2vector ( << 1 ,, 65 ,, 1 ,, 66 ,, 0 ,, 1 ,, 0 ,, 2 ,, 1 ,, 0 ,, 67 >> ) ]] [[ << !"A" ,, !"bibliography" >> => << !"A" ,, !"B" >> ]] [[ << !"A" ,, !"dictionary" ,, 0 >> => 0 ]] [[ << !"A" ,, !"dictionary" ,, 1 >> => 0 ]] [[ << !"A" ,, !"dictionary" ,, 2 >> => 1 ]] [[ << !"A" ,, !"body" >> => << !"C" >> ]] end test ]]" 9548 9549 \end{statements} 9550 9551 9552 9553 ""{ 9554 9555 THIS IS TIME CONSUMING. 9556 9557 The "codify self" test covers the "unpack self", "expand self" and "harvest self" test cases so the latter are only useful when locating a bug. 9558 9559 \subsection{Codification of self} 9560 9561 \begin{statements} 9562 9563 \item "[[ etst measure ( "trisect self" , lgw-trisect-self [[ selfref ]] [[ !"bibliography" ]] ) ; self [[ selfref ]] [[ !"bibliography" ]] end test ]]" 9564 9565 \item "[[ etst lgw-trisect-self [[ selfref ]] [[ !"dictionary" ]] ; self [[ selfref ]] [[ !"dictionary" ]] end test ]]" 9566 9567 \item "[[ etst measure ( "unpack self" , lgw-codify-unpack ( selfref , lgw-trisect-self ) ) [[ selfref ]] [[ !"body" ]] ; self [[ selfref ]] [[ !"body" ]] end test ]]" 9568 9569 \item "[[ etst measure ( "expand self" , lgw-codify-expand ( selfref , self ) ) ; self [[ selfref ]] [[ !"expansion" ]] end test ]]" 9570 9571 \item "[[ etst measure ( "harvest self" , lgw-codify-harvest ( selfref , self [[ selfref ]] [[ !"expansion" ]] , self , self [[ << selfref ,, !"codex" >> => true ]] ) [[ selfref ]] [[ !"codex" ]] ) ; self [[ selfref ]] [[ !"codex" ]] end test ]]" 9572 9573 \item "[[ etst measure ( "codify self" , lgw-codify-self [[ selfref ]] [[ !"body" ]] ) ; self [[ selfref ]] [[ !"body" ]] end test ]]" 9574 9575 \item "[[ etst lgw-codify-self [[ selfref ]] [[ !"expansion" ]] ; self [[ selfref ]] [[ !"expansion" ]] end test ]]" 9576 9577 \item "[[ etst lgw-codify-self [[ selfref ]] [[ !"codex" ]] ; self [[ selfref ]] [[ !"codex" ]] end test ]]" 9578 9579 \end{statements} 9580 9581 ""} 9582 9583 9584 9585 ""{ 9586 9587 THIS IS TIME CONSUMING. 9588 9589 See above for dependency between tests. 9590 9591 \subsection{Codification of base} 9592 9593 \begin{statements} 9594 9595 \item "[[ etst measure ( "trisect base" , lgw-trisect-base [[ baseref ]] [[ !"bibliography" ]] ) ; base [[ baseref ]] [[ !"bibliography" ]] end test ]]" 9596 9597 \item "[[ etst lgw-trisect-base [[ baseref ]] [[ !"dictionary" ]] ; base [[ baseref ]] [[ !"dictionary" ]] end test ]]" 9598 9599 \item "[[ etst measure ( "unpack base" , lgw-codify-unpack ( baseref , lgw-trisect-base ) ) [[ baseref ]] [[ !"body" ]] ; base [[ baseref ]] [[ !"body" ]] end test ]]" 9600 9601 \item "[[ etst measure ( "expand base" , lgw-codify-expand ( baseref , base ) ) ; base [[ baseref ]] [[ !"expansion" ]] end test ]]" 9602 9603 \item "[[ etst measure ( "harvest base" , lgw-codify-harvest ( baseref , base [[ baseref ]] [[ !"expansion" ]] , base , base [[ << baseref ,, !"codex" >> => true ]] ) [[ baseref ]] [[ !"codex" ]] ) ; base [[ baseref ]] [[ !"codex" ]] end test ]]" 9604 9605 \item "[[ etst measure ( "codify base" , lgw-codify-base [[ baseref ]] [[ !"body" ]] ) ; base [[ baseref ]] [[ !"body" ]] end test ]]" 9606 9607 \item "[[ etst lgw-codify-base [[ baseref ]] [[ !"expansion" ]] ; base [[ baseref ]] [[ !"expansion" ]] end test ]]" 9608 9609 \item "[[ etst lgw-codify-base [[ baseref ]] [[ !"codex" ]] ; base [[ baseref ]] [[ !"codex" ]] end test ]]" 9610 9611 \end{statements} 9612 9613 ""} 9614 9615 9616 9617 \subsection{Test of conversion from GRD to MJD} 9618 9619 \begin{statements} 9620 9621 \item "[[ etst lgc-grd2mjd ( << 1858 ,, 11 ,, 17 >> ) ; 0 end test ]]" 9622 9623 \item "[[ etst lgc-grd2mjd ( << 1858 ,, 11 ,, 18 >> ) ; 1 end test ]]" 9624 9625 \item "[[ etst lgc-grd2mjd ( << 1858 ,, 11 ,, 20 >> ) ; 3 end test ]]" 9626 9627 \item "[[ etst lgc-grd2mjd ( << 1858 ,, 11 ,, 30 >> ) ; 13 end test ]]" 9628 9629 \item "[[ etst lgc-grd2mjd ( << 1858 ,, 12 ,, 01 >> ) ; 14 end test ]]" 9630 9631 \item "[[ etst lgc-grd2mjd ( << 1858 ,, 12 ,, 31 >> ) ; 44 end test ]]" 9632 9633 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 01 ,, 01 >> ) ; 45 end test ]]" 9634 9635 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 02 ,, 01 >> ) ; 45 + 31 end test ]]" 9636 9637 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 03 ,, 01 >> ) ; 45 + 31 + 28 end test ]]" 9638 9639 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 04 ,, 01 >> ) ; 45 + 31 + 28 + 31 end test ]]" 9640 9641 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 05 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 end test ]]" 9642 9643 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 06 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 + 31 end test ]]" 9644 9645 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 07 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 + 31 + 30 end test ]]" 9646 9647 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 08 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 end test ]]" 9648 9649 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 09 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 end test ]]" 9650 9651 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 10 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 end test ]]" 9652 9653 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 11 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 end test ]]" 9654 9655 \item "[[ etst lgc-grd2mjd ( << 1859 ,, 12 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 end test ]]" 9656 9657 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 01 ,, 01 >> ) ; 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 end test ]]" 9658 9659 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 01 ,, 01 >> ) ; 45 + 365 end test ]]" 9660 9661 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 02 ,, 01 >> ) ; 45 + 365 + 31 end test ]]" 9662 9663 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 03 ,, 01 >> ) ; 45 + 365 + 31 + 29 end test ]]" 9664 9665 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 04 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 end test ]]" 9666 9667 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 05 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 end test ]]" 9668 9669 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 06 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 + 31 end test ]]" 9670 9671 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 07 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 end test ]]" 9672 9673 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 08 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 end test ]]" 9674 9675 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 09 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 end test ]]" 9676 9677 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 10 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 end test ]]" 9678 9679 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 11 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 end test ]]" 9680 9681 \item "[[ etst lgc-grd2mjd ( << 1860 ,, 12 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 end test ]]" 9682 9683 \item "[[ etst lgc-grd2mjd ( << 1861 ,, 01 ,, 01 >> ) ; 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 end test ]]" 9684 9685 \item "[[ etst lgc-grd2mjd ( << 1861 ,, 01 ,, 01 >> ) ; 45 + 365 + 366 end test ]]" 9686 9687 \item "[[ etst lgc-grd2mjd ( << 1862 ,, 01 ,, 01 >> ) ; 45 + 365 + 366 + 365 end test ]]" 9688 9689 \item "[[ etst lgc-grd2mjd ( << 1863 ,, 01 ,, 01 >> ) ; 45 + 365 + 366 + 365 + 365 end test ]]" 9690 9691 \item "[[ etst lgc-grd2mjd ( << 1864 ,, 01 ,, 01 >> ) ; 45 + 365 + 366 + 365 + 365 + 365 end test ]]" 9692 9693 \item "[[ etst lgc-grd2mjd ( << 1865 ,, 01 ,, 01 >> ) ; 45 + 365 + 366 + 365 + 365 + 365 + 366 end test ]]" 9694 9695 \item "[[ etst lgc-grd2mjd ( << 1900 ,, 01 ,, 01 >> ) ; 15020 end test ]]" 9696 9697 \item "[[ etst lgc-grd2mjd ( << 1900 ,, 02 ,, 28 >> ) ; 15078 end test ]]" 9698 9699 \item "[[ etst lgc-grd2mjd ( << 1900 ,, 03 ,, 01 >> ) ; 15079 end test ]]" 9700 9701 \item "[[ etst lgc-grd2mjd ( << 2000 ,, 01 ,, 01 >> ) ; 51544 end test ]]" 9702 9703 \item "[[ etst lgc-grd2mjd ( << 2000 ,, 02 ,, 28 >> ) ; 51602 end test ]]" 9704 9705 \item "[[ etst lgc-grd2mjd ( << 2000 ,, 03 ,, 01 >> ) ; 51604 end test ]]" 9706 9707 \item "[[ etst lgc-grd2mjd ( << 2100 ,, 02 ,, 28 >> ) ; 88127 end test ]]" 9708 9709 \item "[[ etst lgc-grd2mjd ( << 2100 ,, 03 ,, 01 >> ) ; 88128 end test ]]" 9710 9711 \item "[[ etst lgc-grd2mjd ( << 2200 ,, 02 ,, 28 >> ) ; 124651 end test ]]" 9712 9713 \item "[[ etst lgc-grd2mjd ( << 2200 ,, 03 ,, 01 >> ) ; 124652 end test ]]" 9714 9715 \item "[[ etst lgc-grd2mjd ( << 2300 ,, 02 ,, 28 >> ) ; 161175 end test ]]" 9716 9717 \item "[[ etst lgc-grd2mjd ( << 2300 ,, 03 ,, 01 >> ) ; 161176 end test ]]" 9718 9719 \item "[[ etst lgc-grd2mjd ( << 2400 ,, 02 ,, 28 >> ) ; 197699 end test ]]" 9720 9721 \item "[[ etst lgc-grd2mjd ( << 2400 ,, 03 ,, 01 >> ) ; 197701 end test ]]" 9722 9723 \end{statements} 9724 9725 9726 9727 \subsection{Test of conversion from MJD to GRD} 9728 9729 \begin{statements} 9730 9731 \item "[[ etst << 1858 ,, 11 ,, 17 >> ; lgc-mjd2grd ( 0 ) end test ]]" 9732 9733 \item "[[ etst << 1858 ,, 11 ,, 18 >> ; lgc-mjd2grd ( 1 ) end test ]]" 9734 9735 \item "[[ etst << 1858 ,, 11 ,, 20 >> ; lgc-mjd2grd ( 3 ) end test ]]" 9736 9737 \item "[[ etst << 1858 ,, 11 ,, 30 >> ; lgc-mjd2grd ( 13 ) end test ]]" 9738 9739 \item "[[ etst << 1858 ,, 12 ,, 01 >> ; lgc-mjd2grd ( 14 ) end test ]]" 9740 9741 \item "[[ etst << 1858 ,, 12 ,, 31 >> ; lgc-mjd2grd ( 44 ) end test ]]" 9742 9743 \item "[[ etst << 1859 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 ) end test ]]" 9744 9745 \item "[[ etst << 1859 ,, 02 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 ) end test ]]" 9746 9747 \item "[[ etst << 1859 ,, 03 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 ) end test ]]" 9748 9749 \item "[[ etst << 1859 ,, 04 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 ) end test ]]" 9750 9751 \item "[[ etst << 1859 ,, 05 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 ) end test ]]" 9752 9753 \item "[[ etst << 1859 ,, 06 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 + 31 ) end test ]]" 9754 9755 \item "[[ etst << 1859 ,, 07 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 + 31 + 30 ) end test ]]" 9756 9757 \item "[[ etst << 1859 ,, 08 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 ) end test ]]" 9758 9759 \item "[[ etst << 1859 ,, 09 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 ) end test ]]" 9760 9761 \item "[[ etst << 1859 ,, 10 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 ) end test ]]" 9762 9763 \item "[[ etst << 1859 ,, 11 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 ) end test ]]" 9764 9765 \item "[[ etst << 1859 ,, 12 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 ) end test ]]" 9766 9767 \item "[[ etst << 1860 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 ) end test ]]" 9768 9769 \item "[[ etst << 1860 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 ) end test ]]" 9770 9771 \item "[[ etst << 1860 ,, 02 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 ) end test ]]" 9772 9773 \item "[[ etst << 1860 ,, 03 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 ) end test ]]" 9774 9775 \item "[[ etst << 1860 ,, 04 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 ) end test ]]" 9776 9777 \item "[[ etst << 1860 ,, 05 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 ) end test ]]" 9778 9779 \item "[[ etst << 1860 ,, 06 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 + 31 ) end test ]]" 9780 9781 \item "[[ etst << 1860 ,, 07 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 ) end test ]]" 9782 9783 \item "[[ etst << 1860 ,, 08 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 ) end test ]]" 9784 9785 \item "[[ etst << 1860 ,, 09 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 ) end test ]]" 9786 9787 \item "[[ etst << 1860 ,, 10 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 ) end test ]]" 9788 9789 \item "[[ etst << 1860 ,, 11 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 ) end test ]]" 9790 9791 \item "[[ etst << 1860 ,, 12 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 ) end test ]]" 9792 9793 \item "[[ etst << 1861 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 ) end test ]]" 9794 9795 \item "[[ etst << 1861 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 366 ) end test ]]" 9796 9797 \item "[[ etst << 1862 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 366 + 365 ) end test ]]" 9798 9799 \item "[[ etst << 1863 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 366 + 365 + 365 ) end test ]]" 9800 9801 \item "[[ etst << 1864 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 366 + 365 + 365 + 365 ) end test ]]" 9802 9803 \item "[[ etst << 1865 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 45 + 365 + 366 + 365 + 365 + 365 + 366 ) end test ]]" 9804 9805 \item "[[ etst << 1900 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 15020 ) end test ]]" 9806 9807 \item "[[ etst << 1900 ,, 02 ,, 28 >> ; lgc-mjd2grd ( 15078 ) end test ]]" 9808 9809 \item "[[ etst << 1900 ,, 03 ,, 01 >> ; lgc-mjd2grd ( 15079 ) end test ]]" 9810 9811 \item "[[ etst << 2000 ,, 01 ,, 01 >> ; lgc-mjd2grd ( 51544 ) end test ]]" 9812 9813 \item "[[ etst << 2000 ,, 02 ,, 28 >> ; lgc-mjd2grd ( 51602 ) end test ]]" 9814 9815 \item "[[ etst << 2000 ,, 03 ,, 01 >> ; lgc-mjd2grd ( 51604 ) end test ]]" 9816 9817 \item "[[ etst << 2100 ,, 02 ,, 28 >> ; lgc-mjd2grd ( 88127 ) end test ]]" 9818 9819 \item "[[ etst << 2100 ,, 03 ,, 01 >> ; lgc-mjd2grd ( 88128 ) end test ]]" 9820 9821 \item "[[ etst << 2200 ,, 02 ,, 28 >> ; lgc-mjd2grd ( 124651 ) end test ]]" 9822 9823 \item "[[ etst << 2200 ,, 03 ,, 01 >> ; lgc-mjd2grd ( 124652 ) end test ]]" 9824 9825 \item "[[ etst << 2300 ,, 02 ,, 28 >> ; lgc-mjd2grd ( 161175 ) end test ]]" 9826 9827 \item "[[ etst << 2300 ,, 03 ,, 01 >> ; lgc-mjd2grd ( 161176 ) end test ]]" 9828 9829 \item "[[ etst << 2400 ,, 02 ,, 28 >> ; lgc-mjd2grd ( 197699 ) end test ]]" 9830 9831 \item "[[ etst << 2400 ,, 03 ,, 01 >> ; lgc-mjd2grd ( 197701 ) end test ]]" 9832 9833 \end{statements} 9834 9835 9836 9837 \subsection{Test of GRD parsing functions} 9838 9839 \begin{statements} 9840 9841 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02+1" >> ) ; << lgc-grd2mjd ( << 2000 ,, 01 ,, 02 >> ) :: +1 >> end test ]]" 9842 9843 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02-1" >> ) ; << lgc-grd2mjd ( << 2000 ,, 01 ,, 02 >> ) :: -1 >> end test ]]" 9844 9845 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02+1" ,, !"GRD-2000-01-01-1" >> ) ; << lgc-grd2mjd ( << 2000 ,, 01 ,, 02 >> ) :: +1 ,, lgc-grd2mjd ( << 2000 ,, 01 ,, 01 >> ) :: -1 >> end test ]]" 9846 9847 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02+1" ,, !"ERD-2000-01-01-1" >> ) ; ( !"Invalid leap: " :: !"ERD-2000-01-01-1" ) raise end test ]]" 9848 9849 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02+1" ,, !"GRD:2000-01-01-1" >> ) ; ( !"Invalid leap: " :: !"GRD:2000-01-01-1" ) raise end test ]]" 9850 9851 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02+1" ,, !"GRD-20A0-01-01-1" >> ) ; ( !"Invalid leap: " :: !"GRD-20A0-01-01-1" ) raise end test ]]" 9852 9853 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02+1" ,, !"GRD-2000:01-01-1" >> ) ; ( !"Invalid leap: " :: !"GRD-2000:01-01-1" ) raise end test ]]" 9854 9855 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02+1" ,, !"GRD-2000-01:01-1" >> ) ; ( !"Invalid leap: " :: !"GRD-2000-01:01-1" ) raise end test ]]" 9856 9857 \item "[[ etst lgc-convert-leap ( << !"GRD-2000-01-02+1" ,, !"GRD-2000-01-01:1" >> ) ; ( !"Invalid leap: " :: !"GRD-2000-01-01:1" ) raise end test ]]" 9858 9859 \item "[[ etst lgc-convert-leap ( << !"ARD-2000-01-02+1" ,, !"GRD-2000-01-01:1" >> ) ; ( !"Invalid leap: " :: !"ARD-2000-01-02+1" ) raise end test ]]" 9860 9861 \item "[[ etst lgc-process-leap ( true [[ << !"parameters" ,, !"leap" >> => << !"GRD-2000-01-02+1" ,, !"GRD-2000-01-01-1" >> ]] ) [[ !"leap" ]] ; << 10 ,, lgc-grd2mjd ( << 2000 ,, 01 ,, 03 >> ) * 24 * 60 * 60 + 10 :: +1 ,, lgc-grd2mjd ( << 2000 ,, 01 ,, 02 >> ) * 24 * 60 * 60 + 9 :: -1 >> end test ]]" 9862 9863 \item "[[ etst lgc-process-leap ( true [[ << !"parameters" ,, !"leap" >> => << !"GRD-2000-01-02+1" ,, !"GRD-2000-01-01+1" >> ]] ) [[ !"leap" ]] ; << 12 ,, lgc-grd2mjd ( << 2000 ,, 01 ,, 03 >> ) * 24 * 60 * 60 + 12 :: +1 ,, lgc-grd2mjd ( << 2000 ,, 01 ,, 02 >> ) * 24 * 60 * 60 + 11 :: +1 >> end test ]]" 9864 9865 \item "[[ etst lgc-process-leap ( true [[ << !"parameters" ,, !"leap" >> => << !"GRD-2000-01-02+1" ,, !"ARD-2000-01-01-1" >> ]] ) [[ !"leap" ]] ; ( !"Invalid leap: " :: !"ARD-2000-01-01-1" ) raise end test ]]" 9866 9867 \item "[[ etst lgc-process-leap ( true [[ << !"parameters" ,, !"leap" >> => << !"GRD-2000-01-01-1" ,, !"GRD-2000-01-02+1" >> ]] ) [[ !"leap" ]] ; !"Leap seconds must be stated in descending order" raise end test ]]" 9868 9869 \end{statements} 9870 9871 9872 9873 \subsection{Test of conversion from Logiweb time to MJD/TAI} 9874 9875 \begin{statements} 9876 9877 \item "[[ etst lgc-lgt2mjdtai ( << 0 ,, 6 >> ) ; 9878 << 0 ,, 0 ,, 0 ,, 0 ,, 0 ,, 6 >> end test ]]" 9879 9880 \item "[[ etst lgc-lgt2mjdtai ( << 0 ,, 2 >> ) ; 9881 << 0 ,, 0 ,, 0 ,, 0 ,, 0 ,, 2 >> end test ]]" 9882 9883 \item "[[ etst lgc-lgt2mjdtai ( << 0 ,, 0 >> ) ; 9884 << 0 ,, 0 ,, 0 ,, 0 ,, 0 ,, 0 >> end test ]]" 9885 9886 \item "[[ etst lgc-lgt2mjdtai ( << 1 ,, 6 >> ) ; 9887 << 0 ,, 0 ,, 0 ,, 0 ,, 1 ,, 6 >> end test ]]" 9888 9889 \item "[[ etst lgc-lgt2mjdtai ( << 1 ,, 2 >> ) ; 9890 << 0 ,, 0 ,, 0 ,, 0 ,, 1 ,, 2 >> end test ]]" 9891 9892 \item "[[ etst lgc-lgt2mjdtai ( << 10 ,, 2 >> ) ; 9893 << 0 ,, 0 ,, 0 ,, 0 ,, 10 ,, 2 >> end test ]]" 9894 9895 \item "[[ etst lgc-lgt2mjdtai ( << 100 ,, 2 >> ) ; 9896 << 0 ,, 0 ,, 0 ,, 1 ,, 0 ,, 2 >> end test ]]" 9897 9898 \item "[[ etst lgc-lgt2mjdtai ( << 100 * 10 ,, 2 >> ) ; 9899 << 0 ,, 0 ,, 0 ,, 10 ,, 0 ,, 2 >> end test ]]" 9900 9901 \item "[[ etst lgc-lgt2mjdtai ( << 100 * 60 ,, 2 >> ) ; 9902 << 0 ,, 0 ,, 1 ,, 0 ,, 0 ,, 2 >> end test ]]" 9903 9904 \item "[[ etst lgc-lgt2mjdtai ( << 100 * 60 * 10 ,, 2 >> ) ; 9905 << 0 ,, 0 ,, 10 ,, 0 ,, 0 ,, 2 >> end test ]]" 9906 9907 \item "[[ etst lgc-lgt2mjdtai ( << 100 * 60 * 60 ,, 2 >> ) ; 9908 << 0 ,, 1 ,, 0 ,, 0 ,, 0 ,, 2 >> end test ]]" 9909 9910 \item "[[ etst lgc-lgt2mjdtai ( << 100 * 60 * 60 * 10 ,, 2 >> ) ; 9911 << 0 ,, 10 ,, 0 ,, 0 ,, 0 ,, 2 >> end test ]]" 9912 9913 \item "[[ etst lgc-lgt2mjdtai ( << 100 * 60 * 60 * 24 ,, 2 >> ) ; 9914 << 1 ,, 0 ,, 0 ,, 0 ,, 0 ,, 2 >> end test ]]" 9915 9916 \item "[[ etst lgc-lgt2mjdtai ( << 100 * 60 * 60 * 24 * 10 ,, 2 >> ) ; 9917 << 10 ,, 0 ,, 0 ,, 0 ,, 0 ,, 2 >> end test ]]" 9918 9919 \item "[[ etst lgc-lgt2mjdtai ( << - 100 * 60 * 60 * 24 * 10 ,, 2 >> ) ; 9920 << - 10 ,, 0 ,, 0 ,, 0 ,, 0 ,, 2 >> end test ]]" 9921 9922 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 0 ,, 6 >> ) ) ; !"MJD-0.TAI:00:00:00.000000" end test ]]" 9923 9924 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 0 ,, 2 >> ) ) ; !"MJD-0.TAI:00:00:00.00" end test ]]" 9925 9926 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 0 ,, 0 >> ) ) ; !"MJD-0.TAI:00:00:00" end test ]]" 9927 9928 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 1 ,, 6 >> ) ) ; !"MJD-0.TAI:00:00:00.000001" end test ]]" 9929 9930 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 1 ,, 2 >> ) ) ; !"MJD-0.TAI:00:00:00.01" end test ]]" 9931 9932 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 10 ,, 2 >> ) ) ; !"MJD-0.TAI:00:00:00.10" end test ]]" 9933 9934 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 100 ,, 2 >> ) ) ; !"MJD-0.TAI:00:00:01.00" end test ]]" 9935 9936 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 100 * 10 ,, 2 >> ) ) ; !"MJD-0.TAI:00:00:10.00" end test ]]" 9937 9938 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 100 * 60 ,, 2 >> ) ) ; !"MJD-0.TAI:00:01:00.00" end test ]]" 9939 9940 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 100 * 60 * 10 ,, 2 >> ) ) ; !"MJD-0.TAI:00:10:00.00" end test ]]" 9941 9942 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 100 * 60 * 60 ,, 2 >> ) ) ; !"MJD-0.TAI:01:00:00.00" end test ]]" 9943 9944 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 100 * 60 * 60 * 10 ,, 2 >> ) ) ; !"MJD-0.TAI:10:00:00.00" end test ]]" 9945 9946 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 100 * 60 * 60 * 24 ,, 2 >> ) ) ; !"MJD-1.TAI:00:00:00.00" end test ]]" 9947 9948 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << 100 * 60 * 60 * 24 * 10 ,, 2 >> ) ) ; !"MJD-10.TAI:00:00:00.00" end test ]]" 9949 9950 \item "[[ etst vt2vector ( lgc-lgt2mjdtai2vt ( << - 100 * 60 * 60 * 24 * 10 ,, 2 >> ) ) ; !"MJD--10.TAI:00:00:00.00" end test ]]" 9951 9952 \end{statements} 9953 9954 9955 9956 \subsection{Test of conversion from Logiweb time to GRD/UTC} 9957 9958 \begin{statements} 9959 9960 \item "[[ late define test-leaps as newline 9961 9962 << 11 ,, 6 * 60 + 11 :: + 1 ,, 4 * 60 + 10 :: + 1 ,, 2 * 60 + 9 :: - 1 >> end define ]]" 9963 9964 A situation where a negative leap occured two minutes after epoch and two positive ones occured four and six minutes after epoch. 9965 9966 \item "[[ etst 0 :: 0 ; lgc-lgt2utc ( 0 , 0 , <<>> ) end test ]]" 9967 9968 \item "[[ etst - 10 :: 0 ; lgc-lgt2utc ( 0 , 10 , <<>> ) end test ]]" 9969 9970 \item "[[ etst 0 :: 0 ; lgc-lgt2utc ( 10 , 10 , <<>> ) end test ]]" 9971 9972 \item "[[ etst 362 :: 0 ; lgc-lgt2utc ( 373 , test-leaps head , test-leaps tail ) end test ]]" 9973 9974 \item "[[ etst 361 :: 0 ; lgc-lgt2utc ( 372 , test-leaps head , test-leaps tail ) end test ]]" 9975 9976 \item "[[ etst 360 :: 0 ; lgc-lgt2utc ( 371 , test-leaps head , test-leaps tail ) end test ]]" 9977 9978 \item "[[ etst 359 :: 1 ; lgc-lgt2utc ( 370 , test-leaps head , test-leaps tail ) end test ]]" 9979 9980 \item "[[ etst 359 :: 0 ; lgc-lgt2utc ( 369 , test-leaps head , test-leaps tail ) end test ]]" 9981 9982 \item "[[ etst 358 :: 0 ; lgc-lgt2utc ( 368 , test-leaps head , test-leaps tail ) end test ]]" 9983 9984 \item "[[ etst 302 :: 0 ; lgc-lgt2utc ( 312 , test-leaps head , test-leaps tail ) end test ]]" 9985 9986 \item "[[ etst 301 :: 0 ; lgc-lgt2utc ( 311 , test-leaps head , test-leaps tail ) end test ]]" 9987 9988 \item "[[ etst 300 :: 0 ; lgc-lgt2utc ( 310 , test-leaps head , test-leaps tail ) end test ]]" 9989 9990 \item "[[ etst 299 :: 0 ; lgc-lgt2utc ( 309 , test-leaps head , test-leaps tail ) end test ]]" 9991 9992 \item "[[ etst 298 :: 0 ; lgc-lgt2utc ( 308 , test-leaps head , test-leaps tail ) end test ]]" 9993 9994 \item "[[ etst 297 :: 0 ; lgc-lgt2utc ( 307 , test-leaps head , test-leaps tail ) end test ]]" 9995 9996 \item "[[ etst 242 :: 0 ; lgc-lgt2utc ( 252 , test-leaps head , test-leaps tail ) end test ]]" 9997 9998 \item "[[ etst 241 :: 0 ; lgc-lgt2utc ( 251 , test-leaps head , test-leaps tail ) end test ]]" 9999 10000 \item "[[ etst 240 :: 0 ; lgc-lgt2utc ( 250 , test-leaps head , test-leaps tail ) end test ]]" 10001 10002 \item "[[ etst 239 :: 1 ; lgc-lgt2utc ( 249 , test-leaps head , test-leaps tail ) end test ]]" 10003 10004 \item "[[ etst 239 :: 0 ; lgc-lgt2utc ( 248 , test-leaps head , test-leaps tail ) end test ]]" 10005 10006 \item "[[ etst 238 :: 0 ; lgc-lgt2utc ( 247 , test-leaps head , test-leaps tail ) end test ]]" 10007 10008 \item "[[ etst 182 :: 0 ; lgc-lgt2utc ( 191 , test-leaps head , test-leaps tail ) end test ]]" 10009 10010 \item "[[ etst 181 :: 0 ; lgc-lgt2utc ( 190 , test-leaps head , test-leaps tail ) end test ]]" 10011 10012 \item "[[ etst 180 :: 0 ; lgc-lgt2utc ( 189 , test-leaps head , test-leaps tail ) end test ]]" 10013 10014 \item "[[ etst 179 :: 0 ; lgc-lgt2utc ( 188 , test-leaps head , test-leaps tail ) end test ]]" 10015 10016 \item "[[ etst 178 :: 0 ; lgc-lgt2utc ( 187 , test-leaps head , test-leaps tail ) end test ]]" 10017 10018 \item "[[ etst 177 :: 0 ; lgc-lgt2utc ( 186 , test-leaps head , test-leaps tail ) end test ]]" 10019 10020 \item "[[ etst 122 :: 0 ; lgc-lgt2utc ( 131 , test-leaps head , test-leaps tail ) end test ]]" 10021 10022 \item "[[ etst 121 :: 0 ; lgc-lgt2utc ( 130 , test-leaps head , test-leaps tail ) end test ]]" 10023 10024 \item "[[ etst 120 :: 0 ; lgc-lgt2utc ( 129 , test-leaps head , test-leaps tail ) end test ]]" 10025 10026 \item "[[ etst 118 :: 0 ; lgc-lgt2utc ( 128 , test-leaps head , test-leaps tail ) end test ]]" 10027 10028 \item "[[ etst 117 :: 0 ; lgc-lgt2utc ( 127 , test-leaps head , test-leaps tail ) end test ]]" 10029 10030 \item "[[ etst 116 :: 0 ; lgc-lgt2utc ( 126 , test-leaps head , test-leaps tail ) end test ]]" 10031 10032 \item "[[ etst 62 :: 0 ; lgc-lgt2utc ( 72 , test-leaps head , test-leaps tail ) end test ]]" 10033 10034 \item "[[ etst 61 :: 0 ; lgc-lgt2utc ( 71 , test-leaps head , test-leaps tail ) end test ]]" 10035 10036 \item "[[ etst 60 :: 0 ; lgc-lgt2utc ( 70 , test-leaps head , test-leaps tail ) end test ]]" 10037 10038 \item "[[ etst 59 :: 0 ; lgc-lgt2utc ( 69 , test-leaps head , test-leaps tail ) end test ]]" 10039 10040 \item "[[ etst 58 :: 0 ; lgc-lgt2utc ( 68 , test-leaps head , test-leaps tail ) end test ]]" 10041 10042 \item "[[ etst 57 :: 0 ; lgc-lgt2utc ( 67 , test-leaps head , test-leaps tail ) end test ]]" 10043 10044 \item "[[ etst 2 :: 0 ; lgc-lgt2utc ( 12 , test-leaps head , test-leaps tail ) end test ]]" 10045 10046 \item "[[ etst 1 :: 0 ; lgc-lgt2utc ( 11 , test-leaps head , test-leaps tail ) end test ]]" 10047 10048 \item "[[ etst 0 :: 0 ; lgc-lgt2utc ( 10 , test-leaps head , test-leaps tail ) end test ]]" 10049 10050 \item "[[ late define test-leapstate as true [[ !"leap" -> test-leaps ]] end define ]]" 10051 10052 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 0 ,, 0 ,, 6 >> ; 10053 lgc-lgt2grdutc ( << 0 ,, 6 >> , true [[ !"leap" -> << 0 >> ]] ) end test ]]" 10054 10055 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 10 ,, 0 ,, 6 >> ; 10056 lgc-lgt2grdutc ( << 0 ,, 6 >> , true [[ !"leap" -> << - 10 >> ]] ) end test ]]" 10057 10058 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 11 ,, 23 ,, 2 >> ; 10059 lgc-lgt2grdutc ( << 123 ,, 2 >> , true [[ !"leap" -> << - 10 >> ]] ) end test ]]" 10060 10061 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 11 ,, 0 ,, 0 >> ; 10062 lgc-lgt2grdutc ( << 1 ,, 0 >> , true [[ !"leap" -> << - 10 >> ]] ) end test ]]" 10063 10064 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 00 ,, 0 ,, 0 >> ; 10065 lgc-lgt2grdutc ( << 10 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10066 10067 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 01 ,, 0 ,, 0 >> ; 10068 lgc-lgt2grdutc ( << 11 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10069 10070 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 02 ,, 0 ,, 0 >> ; 10071 lgc-lgt2grdutc ( << 12 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10072 10073 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 57 ,, 0 ,, 0 >> ; 10074 lgc-lgt2grdutc ( << 67 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10075 10076 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 58 ,, 0 ,, 0 >> ; 10077 lgc-lgt2grdutc ( << 68 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10078 10079 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 0 ,, 59 ,, 0 ,, 0 >> ; 10080 lgc-lgt2grdutc ( << 69 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10081 10082 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 1 ,, 00 ,, 0 ,, 0 >> ; 10083 lgc-lgt2grdutc ( << 70 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10084 10085 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 1 ,, 01 ,, 0 ,, 0 >> ; 10086 lgc-lgt2grdutc ( << 71 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10087 10088 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 1 ,, 02 ,, 0 ,, 0 >> ; 10089 lgc-lgt2grdutc ( << 72 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10090 10091 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 1 ,, 56 ,, 0 ,, 0 >> ; 10092 lgc-lgt2grdutc ( << 126 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10093 10094 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 1 ,, 57 ,, 0 ,, 0 >> ; 10095 lgc-lgt2grdutc ( << 127 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10096 10097 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 1 ,, 58 ,, 0 ,, 0 >> ; 10098 lgc-lgt2grdutc ( << 128 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10099 10100 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 2 ,, 00 ,, 0 ,, 0 >> ; 10101 lgc-lgt2grdutc ( << 129 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10102 10103 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 2 ,, 01 ,, 0 ,, 0 >> ; 10104 lgc-lgt2grdutc ( << 130 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10105 10106 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 2 ,, 02 ,, 0 ,, 0 >> ; 10107 lgc-lgt2grdutc ( << 131 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10108 10109 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 2 ,, 57 ,, 0 ,, 0 >> ; 10110 lgc-lgt2grdutc ( << 186 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10111 10112 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 2 ,, 58 ,, 0 ,, 0 >> ; 10113 lgc-lgt2grdutc ( << 187 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10114 10115 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 2 ,, 59 ,, 0 ,, 0 >> ; 10116 lgc-lgt2grdutc ( << 188 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10117 10118 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 3 ,, 00 ,, 0 ,, 0 >> ; 10119 lgc-lgt2grdutc ( << 189 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10120 10121 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 3 ,, 01 ,, 0 ,, 0 >> ; 10122 lgc-lgt2grdutc ( << 190 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10123 10124 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 3 ,, 02 ,, 0 ,, 0 >> ; 10125 lgc-lgt2grdutc ( << 191 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10126 10127 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 3 ,, 58 ,, 0 ,, 0 >> ; 10128 lgc-lgt2grdutc ( << 247 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10129 10130 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 3 ,, 59 ,, 0 ,, 0 >> ; 10131 lgc-lgt2grdutc ( << 248 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10132 10133 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 3 ,, 60 ,, 0 ,, 0 >> ; 10134 lgc-lgt2grdutc ( << 249 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10135 10136 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 4 ,, 00 ,, 0 ,, 0 >> ; 10137 lgc-lgt2grdutc ( << 250 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10138 10139 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 4 ,, 01 ,, 0 ,, 0 >> ; 10140 lgc-lgt2grdutc ( << 251 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10141 10142 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 4 ,, 02 ,, 0 ,, 0 >> ; 10143 lgc-lgt2grdutc ( << 252 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10144 10145 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 4 ,, 57 ,, 0 ,, 0 >> ; 10146 lgc-lgt2grdutc ( << 307 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10147 10148 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 4 ,, 58 ,, 0 ,, 0 >> ; 10149 lgc-lgt2grdutc ( << 308 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10150 10151 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 4 ,, 59 ,, 0 ,, 0 >> ; 10152 lgc-lgt2grdutc ( << 309 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10153 10154 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 5 ,, 00 ,, 0 ,, 0 >> ; 10155 lgc-lgt2grdutc ( << 310 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10156 10157 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 5 ,, 01 ,, 0 ,, 0 >> ; 10158 lgc-lgt2grdutc ( << 311 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10159 10160 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 5 ,, 02 ,, 0 ,, 0 >> ; 10161 lgc-lgt2grdutc ( << 312 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10162 10163 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 5 ,, 58 ,, 0 ,, 0 >> ; 10164 lgc-lgt2grdutc ( << 368 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10165 10166 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 5 ,, 59 ,, 0 ,, 0 >> ; 10167 lgc-lgt2grdutc ( << 369 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10168 10169 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 5 ,, 60 ,, 0 ,, 0 >> ; 10170 lgc-lgt2grdutc ( << 370 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10171 10172 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 6 ,, 00 ,, 0 ,, 0 >> ; 10173 lgc-lgt2grdutc ( << 371 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10174 10175 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 6 ,, 01 ,, 0 ,, 0 >> ; 10176 lgc-lgt2grdutc ( << 372 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10177 10178 \item "[[ etst << 1858 ,, 11 ,, 17 ,, 0 ,, 6 ,, 02 ,, 0 ,, 0 >> ; 10179 lgc-lgt2grdutc ( << 373 ,, 0 ,, 0 >> , test-leapstate ) end test ]]" 10180 10181 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:00.000000" ; newline 10182 lgc-lgt2grdutc2v ( << 0 ,, 6 >> , true [[ !"leap" -> << 0 >> ]] ) end test ]]" 10183 10184 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:10.000000" ; newline 10185 lgc-lgt2grdutc2v ( << 0 ,, 6 >> , true [[ !"leap" -> << - 10 >> ]] ) end test ]]" 10186 10187 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:11.23" ; newline 10188 lgc-lgt2grdutc2v ( << 123 ,, 2 >> , true [[ !"leap" -> << - 10 >> ]] ) end test ]]" 10189 10190 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:11" ; newline 10191 lgc-lgt2grdutc2v ( << 1 ,, 0 >> , true [[ !"leap" -> << - 10 >> ]] ) end test ]]" 10192 10193 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:00" ; newline 10194 lgc-lgt2grdutc2v ( << 10 ,, 0 >> , test-leapstate ) end test ]]" 10195 10196 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:01" ; newline 10197 lgc-lgt2grdutc2v ( << 11 ,, 0 >> , test-leapstate ) end test ]]" 10198 10199 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:02" ; newline 10200 lgc-lgt2grdutc2v ( << 12 ,, 0 >> , test-leapstate ) end test ]]" 10201 10202 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:57" ; newline 10203 lgc-lgt2grdutc2v ( << 67 ,, 0 >> , test-leapstate ) end test ]]" 10204 10205 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:58" ; newline 10206 lgc-lgt2grdutc2v ( << 68 ,, 0 >> , test-leapstate ) end test ]]" 10207 10208 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:59" ; newline 10209 lgc-lgt2grdutc2v ( << 69 ,, 0 >> , test-leapstate ) end test ]]" 10210 10211 \item "[[ etst !"GRD-1858-11-17.UTC:00:01:00" ; newline 10212 lgc-lgt2grdutc2v ( << 70 ,, 0 >> , test-leapstate ) end test ]]" 10213 10214 \item "[[ etst !"GRD-1858-11-17.UTC:00:01:01" ; newline 10215 lgc-lgt2grdutc2v ( << 71 ,, 0 >> , test-leapstate ) end test ]]" 10216 10217 \item "[[ etst !"GRD-1858-11-17.UTC:00:01:02" ; newline 10218 lgc-lgt2grdutc2v ( << 72 ,, 0 >> , test-leapstate ) end test ]]" 10219 10220 \item "[[ etst !"GRD-1858-11-17.UTC:00:01:56" ; newline 10221 lgc-lgt2grdutc2v ( << 126 ,, 0 >> , test-leapstate ) end test ]]" 10222 10223 \item "[[ etst !"GRD-1858-11-17.UTC:00:01:57" ; newline 10224 lgc-lgt2grdutc2v ( << 127 ,, 0 >> , test-leapstate ) end test ]]" 10225 10226 \item "[[ etst !"GRD-1858-11-17.UTC:00:01:58" ; newline 10227 lgc-lgt2grdutc2v ( << 128 ,, 0 >> , test-leapstate ) end test ]]" 10228 10229 \item "[[ etst !"GRD-1858-11-17.UTC:00:02:00" ; newline 10230 lgc-lgt2grdutc2v ( << 129 ,, 0 >> , test-leapstate ) end test ]]" 10231 10232 \item "[[ etst !"GRD-1858-11-17.UTC:00:02:01" ; newline 10233 lgc-lgt2grdutc2v ( << 130 ,, 0 >> , test-leapstate ) end test ]]" 10234 10235 \item "[[ etst !"GRD-1858-11-17.UTC:00:02:02" ; newline 10236 lgc-lgt2grdutc2v ( << 131 ,, 0 >> , test-leapstate ) end test ]]" 10237 10238 \item "[[ etst !"GRD-1858-11-17.UTC:00:02:57" ; newline 10239 lgc-lgt2grdutc2v ( << 186 ,, 0 >> , test-leapstate ) end test ]]" 10240 10241 \item "[[ etst !"GRD-1858-11-17.UTC:00:02:58" ; newline 10242 lgc-lgt2grdutc2v ( << 187 ,, 0 >> , test-leapstate ) end test ]]" 10243 10244 \item "[[ etst !"GRD-1858-11-17.UTC:00:02:59" ; newline 10245 lgc-lgt2grdutc2v ( << 188 ,, 0 >> , test-leapstate ) end test ]]" 10246 10247 \item "[[ etst !"GRD-1858-11-17.UTC:00:03:00" ; newline 10248 lgc-lgt2grdutc2v ( << 189 ,, 0 >> , test-leapstate ) end test ]]" 10249 10250 \item "[[ etst !"GRD-1858-11-17.UTC:00:03:01" ; newline 10251 lgc-lgt2grdutc2v ( << 190 ,, 0 >> , test-leapstate ) end test ]]" 10252 10253 \item "[[ etst !"GRD-1858-11-17.UTC:00:03:02" ; newline 10254 lgc-lgt2grdutc2v ( << 191 ,, 0 >> , test-leapstate ) end test ]]" 10255 10256 \item "[[ etst !"GRD-1858-11-17.UTC:00:03:58" ; newline 10257 lgc-lgt2grdutc2v ( << 247 ,, 0 >> , test-leapstate ) end test ]]" 10258 10259 \item "[[ etst !"GRD-1858-11-17.UTC:00:03:59" ; newline 10260 lgc-lgt2grdutc2v ( << 248 ,, 0 >> , test-leapstate ) end test ]]" 10261 10262 \item "[[ etst !"GRD-1858-11-17.UTC:00:03:60" ; newline 10263 lgc-lgt2grdutc2v ( << 249 ,, 0 >> , test-leapstate ) end test ]]" 10264 10265 \item "[[ etst !"GRD-1858-11-17.UTC:00:04:00" ; newline 10266 lgc-lgt2grdutc2v ( << 250 ,, 0 >> , test-leapstate ) end test ]]" 10267 10268 \item "[[ etst !"GRD-1858-11-17.UTC:00:04:01" ; newline 10269 lgc-lgt2grdutc2v ( << 251 ,, 0 >> , test-leapstate ) end test ]]" 10270 10271 \item "[[ etst !"GRD-1858-11-17.UTC:00:04:02" ; newline 10272 lgc-lgt2grdutc2v ( << 252 ,, 0 >> , test-leapstate ) end test ]]" 10273 10274 \item "[[ etst !"GRD-1858-11-17.UTC:00:04:57" ; newline 10275 lgc-lgt2grdutc2v ( << 307 ,, 0 >> , test-leapstate ) end test ]]" 10276 10277 \item "[[ etst !"GRD-1858-11-17.UTC:00:04:58" ; newline 10278 lgc-lgt2grdutc2v ( << 308 ,, 0 >> , test-leapstate ) end test ]]" 10279 10280 \item "[[ etst !"GRD-1858-11-17.UTC:00:04:59" ; newline 10281 lgc-lgt2grdutc2v ( << 309 ,, 0 >> , test-leapstate ) end test ]]" 10282 10283 \item "[[ etst !"GRD-1858-11-17.UTC:00:05:00" ; newline 10284 lgc-lgt2grdutc2v ( << 310 ,, 0 >> , test-leapstate ) end test ]]" 10285 10286 \item "[[ etst !"GRD-1858-11-17.UTC:00:05:01" ; newline 10287 lgc-lgt2grdutc2v ( << 311 ,, 0 >> , test-leapstate ) end test ]]" 10288 10289 \item "[[ etst !"GRD-1858-11-17.UTC:00:05:02" ; newline 10290 lgc-lgt2grdutc2v ( << 312 ,, 0 >> , test-leapstate ) end test ]]" 10291 10292 \item "[[ etst !"GRD-1858-11-17.UTC:00:05:58" ; newline 10293 lgc-lgt2grdutc2v ( << 368 ,, 0 >> , test-leapstate ) end test ]]" 10294 10295 \item "[[ etst !"GRD-1858-11-17.UTC:00:05:59" ; newline 10296 lgc-lgt2grdutc2v ( << 369 ,, 0 >> , test-leapstate ) end test ]]" 10297 10298 \item "[[ etst !"GRD-1858-11-17.UTC:00:05:60" ; newline 10299 lgc-lgt2grdutc2v ( << 370 ,, 0 >> , test-leapstate ) end test ]]" 10300 10301 \item "[[ etst !"GRD-1858-11-17.UTC:00:06:00" ; newline 10302 lgc-lgt2grdutc2v ( << 371 ,, 0 >> , test-leapstate ) end test ]]" 10303 10304 \item "[[ etst !"GRD-1858-11-17.UTC:00:06:01" ; newline 10305 lgc-lgt2grdutc2v ( << 372 ,, 0 >> , test-leapstate ) end test ]]" 10306 10307 \item "[[ etst !"GRD-1858-11-17.UTC:00:06:02" ; newline 10308 lgc-lgt2grdutc2v ( << 373 ,, 0 >> , test-leapstate ) end test ]]" 10309 10310 \item "[[ late define test-leapstate2 as newline 10311 10312 lgc-process-leap ( true [[ << !"parameters" ,, !"leap" >> => lgc-default-leap ]] ) end define ]]" 10313 10314 \item "[[ etst !"GRD-2009-02-18.UTC:08:56:04" ; newline 10315 lgc-lgt2grdutc2v ( << 4741664198 ,, 0 >> , test-leapstate2 ) end test ]]" 10316 10317 GRD-2009-02-18.UTC:08:56:04 = MJD-54880.TAI:08:56:38. 10318 10319 \item "[[ etst !"GRD-1858-11-17.UTC:00:00:00" ; newline 10320 lgc-lgt2grdutc2v ( << 10 ,, 0 >> , test-leapstate2 ) end test ]]" 10321 10322 \item "[[ etst !"GRD-1972-07-01.UTC:00:00:01" ; newline 10323 lgc-lgt2grdutc2v ( << lgc-grd2mjd ( << 1972 ,, 7 ,, 1 >> ) * 24 * 60 * 60 + 12 ,, 0 >> , test-leapstate2 ) end test ]]" 10324 10325 \item "[[ etst !"GRD-1972-07-01.UTC:00:00:00" ; newline 10326 lgc-lgt2grdutc2v ( << lgc-grd2mjd ( << 1972 ,, 7 ,, 1 >> ) * 24 * 60 * 60 + 11 ,, 0 >> , test-leapstate2 ) end test ]]" 10327 10328 \item "[[ etst !"GRD-1972-06-30.UTC:23:59:60" ; newline 10329 lgc-lgt2grdutc2v ( << lgc-grd2mjd ( << 1972 ,, 7 ,, 1 >> ) * 24 * 60 * 60 + 10 ,, 0 >> , test-leapstate2 ) end test ]]" 10330 10331 \item "[[ etst !"GRD-1972-06-30.UTC:23:59:59" ; newline 10332 lgc-lgt2grdutc2v ( << lgc-grd2mjd ( << 1972 ,, 7 ,, 1 >> ) * 24 * 60 * 60 + 9 ,, 0 >> , test-leapstate2 ) end test ]]" 10333 10334 \item "[[ etst !"GRD-1972-06-30.UTC:23:59:58" ; newline 10335 lgc-lgt2grdutc2v ( << lgc-grd2mjd ( << 1972 ,, 7 ,, 1 >> ) * 24 * 60 * 60 + 8 ,, 0 >> , test-leapstate2 ) end test ]]" 10336 10337 \end{statements} 10338 10339 10340 10341 \subsection{Test of conversion from Unix time to Logiweb time} 10342 10343 \begin{statements} 10344 10345 \item "[[ etst !"GRD-1970-01-01.UTC:00:00:00" ; newline 10346 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 0 ,, 0 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10347 10348 \item "[[ etst !"GRD-1970-01-01.UTC:00:00:00.000000" ; newline 10349 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 0 ,, 6 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10350 10351 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:58.0" ; newline 10352 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487980 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10353 10354 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:58.9" ; newline 10355 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487989 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10356 10357 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:59.0" ; newline 10358 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487990 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10359 10360 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:59.2" ; newline 10361 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487991 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10362 10363 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:59.4" ; newline 10364 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487992 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10365 10366 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:59.6" ; newline 10367 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487993 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10368 10369 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:59.8" ; newline 10370 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487994 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10371 10372 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:60.0" ; newline 10373 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487995 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10374 10375 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:60.2" ; newline 10376 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487996 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10377 10378 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:60.4" ; newline 10379 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487997 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10380 10381 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:60.6" ; newline 10382 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487998 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10383 10384 \item "[[ etst !"GRD-1998-12-31.UTC:23:59:60.8" ; newline 10385 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151487999 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10386 10387 \item "[[ etst !"GRD-1999-01-01.UTC:00:00:00.0" ; newline 10388 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 9151488000 ,, 1 >> , test-leapstate2 ) , test-leapstate2 ) end test ]]" 10389 10390 \item "[[ late define test-leapstate3 as newline 10391 10392 lgc-process-leap ( true [[ << !"parameters" ,, !"leap" >> => << !"GRD-1970-01-01-1" >> ]] ) end define ]]" 10393 10394 \item "[[ etst !"GRD-1970-01-01.UTC:00:00:00" ; newline 10395 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 0 ,, 0 >> , test-leapstate3 ) , test-leapstate2 ) end test ]]" 10396 10397 \item "[[ etst !"GRD-1970-01-01.UTC:00:00:00.000000" ; newline 10398 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 0 ,, 6 >> , test-leapstate3 ) , test-leapstate2 ) end test ]]" 10399 10400 \item "[[ etst !"GRD-1970-01-01.UTC:23:59:57.0" ; newline 10401 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 863970 ,, 1 >> , test-leapstate3 ) , test-leapstate3 ) end test ]]" 10402 10403 \item "[[ etst !"GRD-1970-01-01.UTC:23:59:57.9" ; newline 10404 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 863979 ,, 1 >> , test-leapstate3 ) , test-leapstate3 ) end test ]]" 10405 10406 \item "[[ etst !"GRD-1970-01-01.UTC:23:59:58.00" ; newline 10407 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 863980 ,, 1 >> , test-leapstate3 ) , test-leapstate3 ) end test ]]" 10408 10409 \item "[[ etst !"GRD-1970-01-01.UTC:23:59:58.05" ; newline 10410 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 863981 ,, 1 >> , test-leapstate3 ) , test-leapstate3 ) end test ]]" 10411 10412 \item "[[ etst !"GRD-1970-01-01.UTC:23:59:58.45" ; newline 10413 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 863989 ,, 1 >> , test-leapstate3 ) , test-leapstate3 ) end test ]]" 10414 10415 \item "[[ etst !"GRD-1970-01-01.UTC:23:59:58.50" ; newline 10416 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 863990 ,, 1 >> , test-leapstate3 ) , test-leapstate3 ) end test ]]" 10417 10418 \item "[[ etst !"GRD-1970-01-01.UTC:23:59:58.95" ; newline 10419 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 863999 ,, 1 >> , test-leapstate3 ) , test-leapstate3 ) end test ]]" 10420 10421 \item "[[ etst !"GRD-1970-01-02.UTC:00:00:00.0" ; newline 10422 lgc-lgt2grdutc2v ( lgc-unix2lgt ( << 864000 ,, 1 >> , test-leapstate3 ) , test-leapstate3 ) end test ]]" 10423 10424 \end{statements} 10425 10426 10427 10428 \bibliography{./page} 10429 " 10430 appendix " 10431 \title{Compiler - appendix} 10432 10433 \author{Klaus Grue} 10434 10435 \maketitle 10436 10437 \tableofcontents 10438 10439 10440 10441 \section{\TeX\ definitions} 10442 10443 \begin{statements} 10444 10445 \item "[[ tex show define late define x as y end define as " 10446 [ "[ texshow x end texshow ]" 10447 \stackrel{\bullet\bullet}{=} "[ y ]" 10448 ]" end define ]]" 10449 10450 \end{statements} 10451 10452 10453 10454 \section{Icon definitions} 10455 10456 \begin{statements} 10457 10458 \item "[[ late define lgc-logiweb.png as include ( 10459 ""#logiweb.png" ) end define ]]" 10460 10461 \item "[[ late define lgc-logiweb.ico as include ( 10462 ""#logiweb.ico" ) end define ]]" 10463 10464 \item "[[ late define lgc-logiweb.eps as include ( 10465 ""#logiweb.eps" ) end define ]]" 10466 10467 \end{statements} 10468 10469 " 10470 end page 10471 10472 10473 10474