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