(define elucidator-version "1")
(define elucidator-verbose-mode #t)
(define (display-message message)
(if elucidator-verbose-mode
(begin (display (string-append message)) (newline))))
(define start-run-time (current-time))
(define software-base-directory laml-dir)
(define scheme-library "lib")
(define the-library (string-append software-base-directory scheme-library "/"))
(define software-directory (string-append software-base-directory "styles/elucidator/"))
(define source-directory #f)
(define (relative-source-html-destination-path-fragment)
"html/")
(define (html-directory)
(string-append source-directory (relative-source-html-destination-path-fragment)))
(define (internal-file name)
(string-append source-directory "internal/" name))
(define (documentation-source-file name)
(string-append source-directory name))
(define (relative-to-startup-dir dir) (string-append (startup-directory) dir))
(display-message
(string-append
"Welcome to the Scheme Elucidator (version "
elucidator-version
") and the LAML software." ))
(display-message "Copyright (c) Kurt Normark (normark@cs.auc.dk), Aalborg University, Denmark")
(display-message "Loading libraries and the schemeDoc tool")
(lib-load "file-read.scm")
(lib-load "html.scm")
(lib-load "html-v1.scm")
(lib-load "time.scm")
(lib-load "hex.scm")
(load (string-append laml-dir "tools/schemedoc/schemedoc.scm"))
(display-message "Loading elucidator software")
(define scheme-syntax-procedure-list (file-read (string-append laml-dir "r4rs/" "scheme-knowledge.lsp")))
(define rs4r-url-prefix #f)
(define elucidator-home-url #f)
(define previous-next-elucidators #f)
(define elucidator-previous-url #f)
(define elucidator-next-url #f)
(define elucidator-color-scheme #f)
(define make-duplicated-name-index? #t)
(define make-cross-reference-index? #t)
(define make-defining-name-index? #t)
(define make-large-source-files? #t)
(define link-definitions-to-cross-reference-index? #t)
(define copy-image-files? #t)
(define (make-all-indexes)
(set! make-duplicated-name-index? #t)
(set! make-cross-reference-index? #t)
(set! make-defining-name-index? #t))
(define (make-no-indexes)
(set! make-duplicated-name-index? #f)
(set! make-cross-reference-index? #f)
(set! make-defining-name-index? #f))
(define process-only-sources #f)
(define (process-only . source-keys)
(set! process-only-sources source-keys))
(define (minimum-processing)
(make-no-indexes)
(process-only)
(set! make-large-source-files? #f))
(define (maximum-processing)
(make-all-indexes)
(set! make-large-source-files? #t))
(define separate-program-menu? #f)
(define underline-program-links #f)
(define underline-documentation-links #f)
(define default-program-font-size 'small)
(define default-table-of-content 'overall)
(define comment-handling 'syntactical)
(define syntactical-comment-designator "!!!comment")
(define show-sectional-comment-name #t)
(define COMMENT-FORM-START (string-append "(" syntactical-comment-designator " "))
(define source-marker-kind 'as-image)
(define elucidator-marker-char #\@)
(define elucidator-marker-char-string (as-string elucidator-marker-char))
(define elucidator-escape-char #\\)
(define elucidator-escape-char-string (as-string elucidator-escape-char))
(define documentation-filename-without-extension #f)
(define documentation-title #f)
(define documentation-author #f)
(define documentation-email #f)
(define documentation-affiliation #f)
(define documentation-abstract #f)
(define program-source-list '())
(define manual-source-list '())
(define source-list-list-process '())
(define source-key-list '())
(define defining-name-occurences '())
(define documentation-source-marker-occurences '())
(define defined-applied-names '())
(define documented-name-occurences '())
(define documentation-key-title-alist '())
(define documentation-key-numbering-alist '())
(define documentation-elements '())
(define manual-name-file-map '())
(define (set-source-directory dir)
(set! source-directory dir))
(define (set-documentation-name name)
(set! documentation-filename-without-extension name))
(define (documentation-intro title author email affiliation abstract)
(set! documentation-title title)
(set! documentation-author author)
(set! documentation-email email)
(set! documentation-affiliation affiliation)
(set! documentation-abstract abstract))
(define end-file-empty-lines 25)
(define browser-pixel-width 1100)
(define control-frame-pixel-height 130)
(define toc-columns-detail 3)
(define toc-columns-overall 3)
(define p-link-prefix-char "{")
(define p-link-suffix-char "}")
(define d-link-prefix-char "[")
(define d-link-suffix-char "]")
(define present-hidden-ids? #f)
(define strong-link-char #\*)
(define weak-link-char #\+)
(define none-link-char #\-)
(define default-program-link 'weak)
(define manual-frame-from-documentation "program-frame" )
(define manual-frame-from-program "documentation-frame")
(define elucidator-image-files
(list "cross-index.gif" "doc-left.gif" "doc-left-weak.gif" "index.gif"
"question-left-arrow.gif" "question-right-arrow.gif" "small-square.gif" "three-frames-horizontal.gif"
"three-frames.gif" "home.gif"
"contents.gif" "overall-contents.gif"
"xx.gif" "small-green-up-triangle.gif"
"source-mark-black.gif" "source-mark-grey.gif" "source-mark-silver.gif"
"source-mark-maroon.gif" "source-mark-red.gif" "source-mark-purple.gif"
"source-mark-green.gif" "source-mark-lime.gif" "source-mark-olive.gif"
"source-mark-yellow.gif" "source-mark-navy.gif" "source-mark-blue.gif"
"source-mark-tetal.gif" "source-mark-aqua.gif" "source-mark-fuchsia.gif"
"small-up.gif" "small-up-blind.gif" "small-next.gif" "small-next-blind.gif"
"small-prev.gif" "small-prev-blind.gif"
"nav-left.gif" "nav-right.gif" "nav-left-empty.gif" "nav-right-empty.gif"
"laml-mini-icon-1.gif"
))
(define alphabetic-cross-reference-index? #t)
(define alphabetic-defined-name-index? #t)
(define blank-initial-program? #f)
(define (display-warning message)
(if elucidator-verbose-mode
(begin (display (string-append "WARNING: " message)) (newline))))
(define (internal-reference id)
(string-append (as-string id)))
(define (program-source . elements)
(set! program-source-list
(cons elements program-source-list)))
(define (manual-source . elements)
(set! manual-source-list
(cons elements manual-source-list)))
(define (documentation-section . elements)
(set! section-number (+ section-number 1))
(set! subsection-number 0)
(let ((id (get-value 'id elements))
(title (get-value 'title elements))
(numbering (section-numbering))
(raw-numbering (list section-number subsection-number))
)
(set! documentation-elements
(cons
(append (make-associations
(list 'kind 'numbering 'raw-numbering)
(list 'section numbering raw-numbering))
elements)
documentation-elements))
(set! documentation-key-title-alist
(cons (cons id title) documentation-key-title-alist))
(set! documentation-key-numbering-alist
(cons (cons id numbering) documentation-key-numbering-alist))
))
(define (documentation-entry . elements)
(set! subsection-number (+ subsection-number 1))
(let ((id (get-value 'id elements))
(title (get-value 'title elements))
(numbering (subsection-numbering))
(raw-numbering (list section-number subsection-number))
)
(set! documentation-elements
(cons
(append (make-associations
(list 'kind 'numbering 'raw-numbering)
(list 'entry numbering raw-numbering))
elements)
documentation-elements))
(set! documentation-key-title-alist
(cons (cons id title) documentation-key-title-alist))
(set! documentation-key-numbering-alist
(cons (cons id numbering) documentation-key-numbering-alist))
))
(define (make-associations keys values)
(pair-up keys (map list values)))
(define (begin-documentation)
(if (and (equal? "html/" (relative-source-html-destination-path-fragment))
(not (directory-exists? (string-append source-directory "html/"))))
(make-directory-in-directory source-directory "html"))
(ensure-directory-existence! (string-append source-directory (relative-source-html-destination-path-fragment)) "images")
(ensure-directory-existence! source-directory "internal")
)
(define (end-documentation)
(display-message "Making the help page")
(make-elucidator-help-page)
(if copy-image-files?
(begin
(display-message "Copying image files")
(copy-files
elucidator-image-files
(string-append software-directory "images/")
(string-append source-directory (relative-source-html-destination-path-fragment) "images/") )))
(set! program-source-list (reverse program-source-list))
(store-lisp-expression program-source-list (internal-file "program-source-list"))
(set! manual-name-file-map (pre-process-manual-lsp-files manual-source-list))
(set! documentation-elements (reverse documentation-elements))
(store-lisp-expression (reverse (map car documentation-key-title-alist)) (internal-file "documentation-ids"))
(let ((program-source-list-process
(filter process-source? program-source-list))
(program-source-list-non-process
(filter (negate process-source?) program-source-list)))
(if (eq? comment-handling 'syntactical)
(begin
(display-message "Pre-processing lexical comments in source files")
(pre-process-comments-in-files! program-source-list-process)
)
(display-message "NO Pre-processing lexical comments in source files")
)
(display-message "Parsing source files")
(set! source-list-list-process
(map read-source
(map source-file-determinator program-source-list-process)))
(set! source-key-list
(map (lambda (ps) (get-value 'key ps)) program-source-list))
(let ((source-key-list-process (map (lambda (ps) (get-value 'key ps)) program-source-list-process))
(source-key-list-non-process (map (lambda (ps) (get-value 'key ps)) program-source-list-non-process)))
(display-message "Collecting and reading defining name occurences")
(set! defining-name-occurences
(append
(accumulate-right
append
'()
(map2 (lambda (sl key)
(let ((def-names (defined-names sl)))
(store-defined-names key def-names)
(map (lambda (dn) (cons dn key)) def-names)))
source-list-list-process
source-key-list-process))
(accumulate-right
append
'()
(map restore-defined-names source-key-list-non-process)))
)
(display-message "Presenting and resolving links in the documentation")
(write-text-file
(page
"documentation"
(documentation-contents)
(color-of-group "doc") black black black
)
(html-destination "documentation"))
(store-lisp-expression (reverse documented-name-occurences) (internal-file "documented-names"))
(set! documentation-source-marker-occurences (reverse documentation-source-marker-occurences))
(display-message "Making program source files")
(for-each
(lambda(ps source-list)
(display-message (string-append " " (get-value 'key ps)))
(make-source-program-file (get-value 'key ps) (defaulted-get-value 'group ps "program") (source-file-determinator ps) (get-value 'language ps)
source-list defining-name-occurences documented-name-occurences 'small))
program-source-list-process
source-list-list-process
)
(if (or make-large-source-files? (eq? default-program-font-size 'large))
(begin
(display-message "Making LARGE program source files")
(for-each
(lambda(ps source-list)
(display-message (string-append " " (get-value 'key ps)))
(make-source-program-file (get-value 'key ps) (defaulted-get-value 'group ps "program") (source-file-determinator ps) (get-value 'language ps)
source-list defining-name-occurences documented-name-occurences 'large))
program-source-list-process
source-list-list-process
)))
(display-message "Making the control file")
(write-text-file
(page
"control"
(con-space
(icon-bar)
(when-generated))
(color-of-group "index") black black black
)
(html-destination "control"))
(if make-duplicated-name-index?
(begin
(display-message "Making the duplicate report")
(write-text-file
(page "Duplicate report"
(con
(icon-bar)
(present-duplicated-definitions)
) (color-of-group "index") black black black
)
(html-destination "duplicate-report")))
(display-message "NO duplicated name index is being generated")
)
(if make-defining-name-index?
(let ((sorted-defining-name-occurences (sort-list defining-name-occurences name-entry-leq?)))
(display-message "Making index of defined names")
(display-message
(if alphabetic-defined-name-index?
" alphabetically broken"
" as one large index"))
(if alphabetic-defined-name-index?
(let* ((splitted-defining-name-occurences (split-defining-name-occurences sorted-defining-name-occurences))
(alphabet (map downcase-string (map first-letter-of (map caar splitted-defining-name-occurences)))))
(map2 (lambda (dan letter)
(make-defining-name-index dan letter alphabet))
splitted-defining-name-occurences
alphabet)
(make-overall-defining-name-index alphabet))
(begin
(write-text-file
(page "Alphabetic index of defined names"
(con
(icon-bar)
(present-defined-name-index sorted-defining-name-occurences)
) (color-of-group "index") black black black
)
(html-destination "defining-name-index")))))
(display-message "NO index of defined names is being generated")
)
(if make-cross-reference-index?
(begin
(display-message "Extracting applied-defined name pairs from parsed source files")
(set! defined-applied-names
(applied-names-multiple-sources
(append
source-list-list-process
(map read-source
(map (lambda (ps) (get-value 'file-location ps)) program-source-list-non-process))
)))
(display-message "Presenting the extracted cross reference index")
(display-message
(if alphabetic-cross-reference-index?
" alphabetically broken"
" as one large index"))
(let ((extended-defined-applied-names
(merge-defined-and-defined-applied-lists
defined-applied-names
(sort-list
(map (lambda (x) (cons (car x) #f)) defining-name-occurences) (lambda (x y) (string<=? (as-string x) (as-string y)))))))
(if alphabetic-cross-reference-index?
(let* ((sdan (split-defined-applied-names extended-defined-applied-names))
(alphabet (map downcase-string (map first-letter-of (map caar sdan)))))
(map2 (lambda (dan letter)
(make-cross-reference-index dan letter alphabet))
sdan
alphabet)
(make-overall-cross-reference-index alphabet)
)
(write-text-file
(page "Alphabetic cross reference index"
(con
(icon-bar)
(present-cross-reference-index
extended-defined-applied-names)
) (color-of-group "index") black black black
)
(html-destination "cross-reference-index")))))
(display-message "NO cross reference index is being generated")
)
(display-message "Presenting overall documentation table of contents")
(write-text-file
(page "Documentation table of contents"
(con
(icon-bar)
(present-documentation-contents documentation-elements 'overall)
(when-generated)
) (color-of-group "index") black black black
)
(html-destination "documentation-toc-overall"))
(display-message "Presenting detailed documentation table of contents")
(write-text-file
(page "Documentation table of contents"
(con
(icon-bar)
(present-documentation-contents documentation-elements 'detail)
(when-generated)
) (color-of-group "index") black black black
)
(html-destination "documentation-toc-detail"))
(write-text-file
(page "Program Menu"
(source-file-links-for-program-menu program-source-list)
(color-of-group "index") black black black
)
(html-destination "program-menu"))
(display-message "Making frame files")
(make-frame-file-in-html-dir
"Scheme Elucidator"
(elucidator-frame
(documentation-toc-name)
"program-menu"
"documentation"
(initial-program-page program-source-list)
""
)
"index")
(display-message (string-append "The Elucidator result is available in " (source-filename-without-extension scheme-system) ".html,"))
(display-message (string-append "which is located in the same directory as the setup and documentation files"))
(make-frame-file-in-source-dir
"Scheme Elucidator"
(elucidator-frame
(documentation-toc-name)
"program-menu"
"documentation"
(initial-program-page program-source-list)
(relative-source-html-destination-path-fragment)
)
(source-filename-without-extension scheme-system))
(make-frame-file-in-html-dir
"Scheme Elucidator"
(elucidator-frame-horizontal
(documentation-toc-name)
"program-menu"
"documentation"
(initial-program-page program-source-list)
""
)
"index-horizontal")
(let ((program-frame-content
(con
(vertical-space 1)
(center (font 6 grey "The Scheme Elucidator"))
(center (font 6 grey "Program Frame"))
(vertical-space 1)
(center (narrow-with-pixels 100
(font 4 grey
(con
(p "Scheme source programs are shown here when they are selected in the documentation frame.")
(p
(if separate-program-menu?
"You can also select the programs in the upper right menu."
"You can also select the programs in the upper control frame."))))))))
)
(write-text-file
(page "Blank Initial Program"
program-frame-content
white black black black
)
(html-destination "blank-initial-program"))
(write-text-file
(page "Blank Initial Program"
program-frame-content
white black black black
)
(html-destination "blank-initial-program-LARGE")))
(display-message (string-append "Total processing time: " (present-time-interval (- (current-time) start-run-time))))
)))
(define (initial-program-page program-source-list)
(if blank-initial-program?
"blank-initial-program"
(get-value 'key (car program-source-list))))
(define (pre-process-manual-lsp-files manual-source-list)
(flatten
(map pre-process-manual-lsp-file
(map (lambda (entry) (car (get 'file-location entry))) manual-source-list)
(map (lambda (entry) (car (get 'url-location entry))) manual-source-list))))
(define (pre-process-manual-lsp-file full-manual-file-path manual-url)
(let* ((full-manual-file-path-manlsp (string-append (file-name-initial-path full-manual-file-path) (file-name-proper full-manual-file-path) "." "manlsp"))
(full-manual-file-path-lsp (string-append (file-name-initial-path full-manual-file-path) (file-name-proper full-manual-file-path) "." "lsp"))
(actual-full-manual-file-path
(cond ((file-exists? full-manual-file-path-manlsp) full-manual-file-path-manlsp)
((file-exists? full-manual-file-path-lsp) full-manual-file-path-lsp)
(else (laml-error "pre-process-manual-lsp-file: Cannot locate internal manual file:" full-manual-file-path-manlsp "or " full-manual-file-path-lsp))))
)
(letrec ((manual-page? (lambda (lsp-entry) (equal? "manual-page" (car (get 'kind lsp-entry)))))
(get-symbol-name-of-lsp-entry (lambda (lsp-entry) (car (get 'title lsp-entry))))
)
(if (file-exists? actual-full-manual-file-path)
(let ((lsp-structure (file-read actual-full-manual-file-path)))
(map (lambda (name)
(cons name manual-url))
(map get-symbol-name-of-lsp-entry (filter manual-page? lsp-structure))))
(laml-error "Cannot locate LAML manual file: " actual-full-manual-file-path)))))
(define (documentation-toc-name)
(cond ((eq? default-table-of-content 'overall) "documentation-toc-overall")
((eq? default-table-of-content 'detailed) "documentation-toc-detail")
(else (laml-error "documentation-toc-name: Unknown default-table-of-content: " default-table-of-content))))
(define (source-file-determinator source-descriptor)
(cond ((eq? comment-handling 'syntactical) (internal-syntactic-commented-file (get-value 'key source-descriptor)))
((eq? comment-handling 'lexical) (get-value 'file-location source-descriptor))
(else (error "source-file-determinator: Unknown kind of comment-handling"))))
(define (internal-syntactic-commented-file source-key)
(string-append source-directory "internal/" (as-string source-key) "-syntactical-comments"))
(define (pre-process-comments-in-files! source-file-list)
(map pre-process-comments! source-file-list))
(define (pre-process-comments! source-file-descriptor)
(let* ((input-file (get-value 'file-location source-file-descriptor))
(source-key (get-value 'key source-file-descriptor))
(output-file (internal-syntactic-commented-file source-key)))
(lexical-to-syntactical-comments! input-file output-file)))
(define (when-generated)
(let* ((dt (date-time (current-time)))
(date (car dt))
(time (cadr dt)))
(font 2 red (con "Generated: " date ", " time))))
(define (store-lisp-expression expr file-path)
(if (file-exists? file-path) (delete-file file-path))
(with-output-to-file file-path
(lambda () (write expr))))
(define (icon-bar)
(left-right-banner
(table-3 0 (append (if previous-next-elucidators (list 30 30 30) '())
(if elucidator-home-url (list 30 30) '())
(list 30 30 30 30 30 30 30 30 30 30 30 30 60 1000))
(list
(append
(if previous-next-elucidators
(list
(if elucidator-previous-url
(a-tag-target elucidator-previous-url (image "nav-left.gif" "Go to previous elucidator") "_top")
(image "nav-left-empty.gif" ""))
(if elucidator-next-url
(a-tag-target elucidator-next-url (image "nav-right.gif" "Go to next elucidator") "_top")
(image "nav-right-empty.gif" ""))
" "
)
'())
(if elucidator-home-url
(list
(a-tag-target elucidator-home-url (image "home.gif" "Go home") "_top")
" ")
'())
(list
(a-tag-target "index.html" (image "three-frames.gif" "Reset Elucidator to vertical layout") "_top")
(a-tag-target "index-horizontal.html" (image "three-frames-horizontal.gif" "Reset Elucidator to horizontal layout") "_top")
" "
(a-tag-target "defining-name-index.html"
(image "index.gif" "Alphabetic index of defined names in the program") "control-frame")
(a-tag-target "cross-reference-index.html" (image "cross-index.gif" "Cross reference index") "control-frame")
(a-tag-target "duplicate-report.html" (image "xx.gif" "Duplicated definitions") "control-frame")
" "
(a-tag-target "documentation-toc-detail.html" (image "contents.gif" "Detailed documentation table of contents") "control-frame")
(a-tag-target "documentation-toc-overall.html" (image "overall-contents.gif" "Overall documentation table of contents") "control-frame")
" "
(a-tag-target "elucidator-help.html"
(image "question-left-arrow.gif" "Elucidator Help Page to be shown in the documentation frame")
"documentation-frame")
(a-tag-target "elucidator-help.html"
(image "question-right-arrow.gif" "Elucidator Help Page to be shown in the program frame")
"program-frame")
" "
(if (not separate-program-menu?) (source-file-links program-source-list) "")
)))
'middle
)
(laml-power-icon 0 'small)
)
)
(define (process-source? program-source)
(let ((source-key (get-value 'key program-source)))
(if process-only-sources
(member source-key process-only-sources)
#t)))
(define (restore-defined-names source-key)
(let ((restore-filename (defining-names-file source-key)))
(if (file-exists? restore-filename)
(let* ((ip (open-input-file restore-filename))
(res (read ip)))
(display-message (string-append " Restoring defined names from " source-key ".names"))
(close-input-port ip)
(map
(lambda (entry) (cons (as-symbol (car entry)) (cdr entry)))
res))
(begin
(display-warning (string-append "No defining names stored for " source-key))
'()))))
(define (store-defined-names source-key defined-names)
(let ((store-filename (defining-names-file source-key))
(keyed-names (map (lambda (dn) (cons (as-string dn) source-key)) defined-names)))
(if (file-exists? store-filename) (delete-file store-filename))
(with-output-to-file store-filename
(lambda () (write keyed-names)))))
(define (defining-names-file source-key)
(string-append source-directory "internal/" source-key ".names"))
(define (source-file-links program-source-list)
(let* ((source-key-list (map (lambda (ps) (get-value 'key ps)) program-source-list))
(source-group-list (map (lambda (ps) (defaulted-get-value 'group ps "program")) program-source-list))
(source-file-list (map (lambda (ps) (get-value 'file-location ps)) program-source-list))
(size-string (if (eq? default-program-font-size 'large) "-LARGE" ""))
)
(table-1 1
(map (lambda (sk) (* (string-length sk) 7)) source-key-list)
(map color-of-group source-group-list)
(list
(map2
(lambda (sk sf)
(html:a
(font-size 2 sk)
'href (add-file-extension (string-append sk size-string) "html")
'title sf
'target "program-frame"
'style (if underline-program-links "{text-decoration: underline;}" "{text-decoration: none;}")
)
)
source-key-list
source-file-list)))))
(define (source-file-links-for-program-menu program-source-list)
(let* ((source-key-list (map (lambda (ps) (get-value 'key ps)) program-source-list))
(source-group-list (map (lambda (ps) (defaulted-get-value 'group ps "program")) program-source-list))
(source-file-list (map (lambda (ps) (get-value 'file-location ps)) program-source-list))
(size-string (if (eq? default-program-font-size 'large) "-LARGE" ""))
)
(table-4 1
(list 240)
(map color-of-group source-group-list)
(map2
(lambda (sk sf)
(list
(html:a
(font-size 2 sk)
'href (add-file-extension (string-append sk size-string) "html")
'title sf
'target "program-frame"
'style (if underline-program-links "{text-decoration: underline;}" "{text-decoration: none;}")
)
)
)
source-key-list
source-file-list))))
(define (make-syntax-function syntax-symbol)
(lambda values
(cons syntax-symbol values)))
(define (tag-kind kind-symbol elements)
(cons (list 'kind kind-symbol) elements))
(define (get-value key elements)
(let ((res (assoc key elements)))
(if (and (list? res) (> (length res) 1))
(cadr res)
(error (string-append "get-value in elucidator: Problems accessing a value of a syntax element: " (as-string res))))))
(define (defaulted-get-value key elements default-value)
(let ((res (assoc key elements)))
(if (and (list? res) (> (length res) 1))
(cadr res)
default-value)))
(define (get-values key elements)
(cdr (assoc key elements)))
(define key (make-syntax-function 'key))
(define file-location (make-syntax-function 'file-location))
(define url-location (make-syntax-function 'url-location))
(define language (make-syntax-function 'language))
(define group (make-syntax-function 'group))
(define id (make-syntax-function 'id))
(define title (make-syntax-function 'title))
(define index-words (make-syntax-function 'index-words))
(define intro (make-syntax-function 'intro))
(define sources (make-syntax-function 'sources))
(define body (make-syntax-function 'body))
(define (html-destination filename)
(string-append (html-directory) filename ".html"))
(define (source-destination filename)
(string-append source-directory filename ".html"))
(define black-and-white-coloring #f)
(define defined-color (make-color 255 0 0))
(define comment-color (make-color 112 168 0))
(define applied-color (make-color 0 0 128))
(define documentation-section-color (make-color 0 204 255))
(define documentation-entry-color (make-color 0 204 255))
(define documentation-program-link-color red)
(define documentation-program-link-color-weak applied-color)
(define documentation-documentation-link-color blue)
(define none-reference-color (make-color 70 70 70))
(define r4rs-scheme-color brown)
(define manual-name-color (make-color 0 90 0))
(define default-background-color white)
(define documentation-background-color (make-color 255 236 217))
(define program-background-color-1 white)
(define program-background-color-2 (make-color 221 255 221))
(define program-background-color-3 (make-color 198 226 255))
(define program-background-color-4 (make-color 255 230 230))
(define program-background-color-5 (make-color 226 226 199))
(define program-background-color-6 (make-color 255 255 193))
(define program-background-color-7 (make-color 224 224 224))
(define program-background-color-8 (make-color 255 210 255))
(define program-background-color-9 (make-color 155 255 255))
(define program-background-color-10 (make-color 255 214 193))
(define (apply-black-and-white-hardcopy-colors!)
(set! defined-color black)
(set! comment-color black)
(set! applied-color black)
(set! documentation-section-color (make-color 0 204 255))
(set! documentation-entry-color (make-color 0 204 255))
(set! documentation-program-link-color black)
(set! documentation-program-link-color-weak black)
(set! documentation-documentation-link-color black)
(set! none-reference-color black)
(set! underline-program-links #f)
(set! underline-documentation-links #t)
(set! r4rs-scheme-color black)
)
(if black-and-white-coloring (apply-black-and-white-hardcopy-colors!))
(define image-file-access 'sub-directory)
(define (image file-name help-text) (html:img 'src (image-file file-name) 'alt help-text 'border 0))
(define (read-source file)
(let* ((ip (open-input-file file))
(res (read-source-1 ip '())))
(close-input-port ip)
(reverse res)))
(define (read-source-1 input-port source-list)
(if (eof-object? (peek-char input-port))
source-list
(read-source-1 input-port (cons (read input-port) source-list))))
(define (defined-names source-list)
(defined-names-1 source-list '()))
(define (defined-names-1 source-list res)
(if (null? source-list)
(reverse res)
(let ((form (car source-list)))
(if (is-define-form? form)
(defined-names-1 (cdr source-list) (cons (defined-name form) res))
(if (syntactical-comment? form)
(let ((section-name (section-name-comment? (comment-string-of-syntactical-comment form))))
(if section-name
(defined-names-1 (cdr source-list) (cons (as-symbol section-name) res))
(defined-names-1 (cdr source-list) res)))
(defined-names-1 (cdr source-list) res))))))
(define (is-define-form? x)
(and (list? x)
(> (length x) 1)
(or (eq? (car x) 'define)
(and (symbol? (car x))
(let ((s (symbol->string (car x))))
(and (> (string-length s) 6)
(string=? (downcase-string (substring s 0 7)) "define-")))))))
(define (syntactical-comment? x)
(and (list? x)
(not (null? x))
(eq? (car x) (as-symbol syntactical-comment-designator))))
(define comment-string-of-syntactical-comment (make-selector-function 3 'comment-string-of-syntactical-comment))
(define comment-level-of-syntactical-comment (make-selector-function 2 'comment-level-of-syntactical-comment))
(define (section-name-comment? comment-string)
(let ((p1 (skip-chars-in-string comment-string white-space-char-list 0)))
(if (looking-at-substring? comment-string p1 "::")
(let ((p2 (find-in-string comment-string #\: (+ p1 2))))
(if p2
(substring comment-string (+ p1 2) p2)
#f))
#f)))
(define (defined-name x)
(if (pair? (cadr x))
(car (cadr x))
(cadr x)))
(define (bounded-names x)
(cond ((is-define-form? x) (parameter-names x))
((let-form? x) (let-names x))
((lambda-form? x) (lambda-names x))
(else '())))
(define (parameter-names x)
(cond ((pair? (cadr x))
(let ((call-form (cadr x)))
(cond ((list? call-form) (cdr call-form))
((pair? call-form)
(cond ((pair? (cdr call-form)) (append (proper-part (cdr call-form)) (list (first-improper-part (cdr call-form)))))
((symbol? (cdr call-form)) (list (cdr call-form))))
))))
((symbol? (cadr x))
(if (> (length x) 2)
(let ((y (caddr x)))
(if (and (pair? y) (eq? (car y) 'lambda))
(let ((par (cadr y)))
(cond ((symbol? par) (list par))
((list? par) par)
((pair? par) (append (proper-part par) (list (first-improper-part par))))))
'()))
'()))
(else '())))
(define symbol-of-scheme-knowledge (make-selector-function 1 'symbol-of-scheme-knowledge))
(define category-of-scheme-knowledge (make-selector-function 2 'category-of-scheme-knowledge))
(define essentiality-of-scheme-knowledge (make-selector-function 3 'essentiality-of-scheme-knowledge))
(define (url-of-scheme-knowledge entry)
(if (and rs4r-url-prefix (>= (length entry) 4))
(string-append rs4r-url-prefix "r4rs_" (as-string (fourth entry)) ".htm#" (fifth entry))
#f))
(define (elucidate-program-source source-path destination-path source-list defined-names documented-names size source-key source-group)
(let ((of destination-path))
(if (file-exists? of) (delete-file of))
(let ((ip (open-input-file source-path))
(op (open-output-file of)))
(write-string-to-port
(pre-page (string-append "Source file") (color-of-group source-group) black black black)
op)
(write-string-to-port (con (start-tag "font" 'size (if (eq? size 'small) 2 3)) (start-tag "pre")) op)
(elucidate-program-source-1 ip op source-list defined-names documented-names size source-key (length source-list))
(write-string-to-port (con (end-tag "pre") (end-tag "font")) op)
(write-string-to-port (vertical-space end-file-empty-lines) op)
(write-string-to-port
(post-page)
op)
(close-input-port ip)
(close-output-port op) )))
(define (add-file-extension f ext)
(string-append f "." ext))
(define (elucidate-program-source-1 ip op source-list defined-names documented-names size source-key source-length)
(set! last-define-a-name #f)
(skip-white-space ip op)
(if (not (eof-object? (peek-char ip)))
(let ((form (car source-list))
(next-form (if (> source-length 1) (cadr source-list) #f)))
(elucidate-program-form ip op form next-form defined-names documented-names size source-key #t)
(elucidate-program-source-1 ip op (cdr source-list) defined-names documented-names size source-key (- source-length 1)))
))
(define enclosing-definition-name #f)
(define last-define-a-name #f)
(define (elucidate-program-form ip op f nf defined-names documented-names size source-key at-top? . optional-parameter-list)
(let ((trailing-parenthesis (optional-parameter 1 optional-parameter-list 'yes)))
(cond ((null? f)
(if (eq? trailing-parenthesis 'yes)
(begin
(skip-white-space ip op)
(match-start-parenthesis ip op)
(skip-white-space ip op)
(match-end-parenthesis ip op)
(skip-white-space ip op)
)))
((quote-in-input? ip f)
(begin
(write-char #\' op)
(elucidate-program-form ip op (cadr f) #f '() documented-names size source-key #f)
(skip-white-space ip op)))
((backquote-in-input? ip f)
(begin
(write-char #\` op)
(elucidate-program-form ip op (cadr f) #f defined-names documented-names size source-key #f)
(skip-white-space ip op)))
((unquote-in-input? ip f)
(begin
(write-char #\, op)
(let ((ch (peek-char ip)))
(if (eqv? #\@ ch)
(begin
(read-char ip)
(write-char #\@ op)
(elucidate-program-form ip op (cadr f) #f defined-names documented-names size source-key #f)
)
(begin
(elucidate-program-form ip op (cadr f) #f defined-names documented-names size source-key #f)
)))
(skip-white-space ip op)
)
)
((eof-object? f)
)
((symbol? f) (match-symbol f ip op defined-names size)
(skip-white-space ip op))
((string? f) (match-string f ip op)
(skip-white-space ip op))
((number? f) (match-number f ip op)
(skip-white-space ip op))
((char? f) (match-char f ip op)
(skip-white-space ip op))
((boolean? f) (match-boolean f ip op)
(skip-white-space ip op))
((syntactical-comment? f)
(let ((sectional-comment (section-name-comment? (comment-string-of-syntactical-comment f))))
(if sectional-comment
(set! enclosing-definition-name sectional-comment))
(match-syntactical-comment-without-output ip)
(read-char ip)
(if sectional-comment
(write-string-to-port (con (total-doc-navigator (as-symbol sectional-comment) documented-names size source-key) (br)) op))
(if (is-define-form? nf)
(let ((def-name (defined-name nf)))
(write-string-to-port (a-name (as-string def-name)) op)
(set! last-define-a-name def-name)))
(write-string-to-port (render-syntactical-comment (comment-string-of-syntactical-comment f) (comment-level-of-syntactical-comment f)) op)
)
)
((is-define-form? f)
(let* ((bn (bounded-names f))
(reduced-defined-names (list-difference-2 defined-names bn)))
(set! enclosing-definition-name (defined-name f))
(skip-white-space ip op)
(if (not (eq? last-define-a-name (defined-name f)))
(write-string-to-port (a-name (as-string (defined-name f))) op))
(set! last-define-a-name #f)
(if at-top?
(write-string-to-port (con (total-doc-navigator (defined-name f) documented-names size source-key) (br)) op))
(match-start-parenthesis ip op)
(skip-white-space ip op)
(match-symbol (car f) ip op '() size)
(skip-white-space ip op)
(write-string-to-port (con (start-tag "b") (start-tag "font" 'color (rgb-string-list defined-color))) op)
(elucidate-restricted-define-form ip op (cadr f) size)
(write-string-to-port (con (end-tag "font") (end-tag "b")) op)
(skip-white-space ip op)
(for-each
(lambda (sf nf)
(skip-white-space ip op)
(elucidate-program-form
ip op sf nf
reduced-defined-names
documented-names size source-key #f))
(cddr f)
(if (null? (cddr f)) '() (append (cdddr f) (list #f)))
)
(skip-white-space ip op)
(match-end-parenthesis ip op)
(skip-white-space ip op)))
((pair? f)
(let* ((bn (bounded-names f))
(reduced-defined-names (list-difference-2 defined-names bn))
)
(skip-white-space ip op)
(if (eq? trailing-parenthesis 'yes) (match-start-parenthesis ip op))
(elucidate-program-form
ip op (car f) #f
reduced-defined-names documented-names size source-key #f)
(skip-white-space ip op)
(let ((next-ch (peek-char ip)))
(if (eqv? next-ch #\.)
(begin
(read-char ip)
(let ((next-ch (peek-char ip)))
(if (white-space? next-ch)
(begin
(write-char #\. op)
(skip-white-space ip op)
(elucidate-program-form
ip op (cdr f) #f
reduced-defined-names documented-names size source-key #f))
(begin
(elucidate-program-form
ip op (cdr f) #f
reduced-defined-names documented-names size source-key #f 'no)
)
)
)
)
(let ((rest (cdr f)))
(elucidate-program-form
ip op rest #f
reduced-defined-names documented-names size source-key #f 'no)
)
)
)
(skip-white-space ip op)
(if (eq? trailing-parenthesis 'yes) (match-end-parenthesis ip op))
(skip-white-space ip op)
)
)
((vector? f)
(let* ((lf (vector->list f))
(bn (bounded-names f))
(reduced-defined-names (list-difference-2 defined-names bn)))
(match-number-sign ip op)
(match-start-parenthesis ip op)
(for-each
(lambda (sf nf)
(skip-white-space ip op)
(elucidate-program-form
ip op sf nf
reduced-defined-names
documented-names
size source-key #f))
lf
(if (null? lf) '() (append (cdr lf) (list #f)))
)
(skip-white-space ip op)
(match-end-parenthesis ip op)
(skip-white-space ip op))
)
(else (error (string-append "elucidate-program-form: unknown kind of expression" (as-string f))))))
)
(define (dot-notation-ahead? ip)
(let ((ch1 (peek-char ip)))
(if (eqv? ch1 #\.)
(let ((ch2 (peek-char ip)))
(white-space? ch2)
)
#f)))
(define (match-syntactical-comment-without-output ip)
(read-char ip)
(read ip)
(read ip)
(read ip)
(read-char ip)
)
(define indeed-section-comment #f)
(define (render-syntactical-comment comment-string comment-level)
(let* ((sectional-comment (section-name-comment? comment-string))
(decorate-comment
(lambda (comment-rendering)
(cond ((and sectional-comment (= comment-level 1))
(html:b (font-color (make-color 49 72 0) comment-rendering) 'style "{background-color: rgb(255,255,0);}"))
((and sectional-comment (= comment-level 2))
(html:b (font-color (make-color 49 72 0) comment-rendering) 'style "{background-color: rgb(255,255,0);}"))
((and sectional-comment (>= comment-level 3))
(html:b (font-color (make-color 49 72 0) comment-rendering) 'style "{background-color: rgb(255,255,0);}"))
(else (font-color comment-color comment-rendering))
)
)
)
)
(set! indeed-section-comment sectional-comment)
(let ((comment-string-1 (strip-trailing-characters (list #\newline #\return) comment-string)))
(set! state-list '())
(decorate-comment
(string-append
(make-string comment-level #\;)
" "
(do-render-syntactical-comment
comment-string-1 comment-level 0 (string-length comment-string-1)
comment-output-string 0 comment-max-length 'normal ""))))))
(define comment-max-length 10000)
(define comment-output-string (make-string comment-max-length #\space))
(define debugging-syntactical-comment-rendering #f)
(define state-list '())
(define (do-render-syntactical-comment c-str c-lev inptr inlength outstr outptr outlength current-state collected-str)
(if (>= outptr (- outlength 500))
(error "do-render-syntactical-comment: Close to output string overflow. Make comment-max-length larger"))
(if (= inptr inlength)
(string-append
(substring outstr 0 outptr)
(cond ((and (eq? current-state 'source-char) (> (string-length collected-str) 0))
(render-source-char collected-str))
(else ""))
)
(let* ((inch (string-ref c-str inptr))
(trans-res (syntactical-comment-transition current-state inch collected-str c-lev))
(next-state (car trans-res))
(toput (as-string (cadr trans-res)))
(collected-str (caddr trans-res))
)
(if debugging-syntactical-comment-rendering
(set! state-list (cons (list (as-string inch) next-state collected-str) state-list)))
(put-into-string! outstr outptr toput)
(do-render-syntactical-comment c-str c-lev (+ 1 inptr) inlength outstr (+ outptr (string-length toput))
outlength next-state collected-str)
)))
(define sectional-comment-char #\:)
(define sectional-comment-char-string (as-string sectional-comment-char))
(define elucidator-marker-char-string (as-string elucidator-marker-char))
(define (hp single-string-char)
(cond ((equal? single-string-char "<") "<")
((equal? single-string-char ">") ">")
(else single-string-char)))
(define (syntactical-comment-transition in-state ch collected-str c-level)
(let ((char (as-string ch))
(expl (string-append "A link to a program source marker in " (as-string previous-strong-program-word))))
(cond
((and (symbol? in-state) (eq? in-state 'normal))
(cond ((equal? char sectional-comment-char-string) (list 'colon-initial-1 "" ""))
((equal? char elucidator-marker-char-string) (list 'at-sign "" ""))
((equal? char (as-string #\newline)) (list 'newline "" ""))
(else (list 'normal (hp char) collected-str))))
((and (symbol? in-state) (eq? in-state 'colon-initial-1))
(cond ((equal? char sectional-comment-char-string) (list 'colon-initial-2 "" ""))
((equal? char elucidator-marker-char-string) (list 'at-sign (as-string sectional-comment-char) ""))
((equal? char (as-string #\newline)) (list 'newline
(string-append (as-string sectional-comment-char)) ""))
(else (list 'normal (string-append (as-string sectional-comment-char) (hp char))
collected-str))))
((and (symbol? in-state) (eq? in-state 'colon-initial-2))
(cond ((equal? char sectional-comment-char-string) (error "syntactical-comment-transition: more than two colons not allowed"))
((equal? char elucidator-marker-char-string) (error "syntactical-comment-transition: @ in section name not allowed"))
((equal? char (as-string #\newline)) (error "syntactical-comment-transition: newline not allowed in section name"))
(else (list 'within-section-name ""
(string-append collected-str char)))))
((and (symbol? in-state) (eq? in-state 'within-section-name))
(cond ((equal? char sectional-comment-char-string) (list 'colon-after-1 "" collected-str))
((equal? char elucidator-marker-char-string) (error "syntactical-comment-transition: @ in section name not allowed"))
((equal? char (as-string #\newline)) (error "syntactical-comment-transition: newline not allowed in section name"))
(else (list 'within-section-name ""
(string-append collected-str char)))))
((and (symbol? in-state) (eq? in-state 'colon-after-1))
(cond ((equal? char sectional-comment-char-string) (list 'normal (render-sectional-comment collected-str) ""))
((equal? char elucidator-marker-char-string) (error "syntactical-comment-transition: @ in section name not allowed"))
((equal? char (as-string #\newline)) (error "syntactical-comment-transition: newline not allowed in section name"))
(else (list 'within-section-name ""
(string-append collected-str sectional-comment-char-string char)))))
((and (symbol? in-state) (eq? in-state 'colon-after-2))
(cond ((equal? char sectional-comment-char-string) (error "syntactical-comment-transition: three colons not allowed"))
((equal? char elucidator-marker-char-string) (list 'at-sign (render-sectional-comment collected-str) ""))
((equal? char (as-string #\newline)) (list 'newline (render-sectional-comment collected-str) ""))
(else (list 'normal (string-append (render-sectional-comment collected-str) (hp char)) ""))))
((and (symbol? in-state) (eq? in-state 'at-sign))
(cond ((equal? char sectional-comment-char-string) (error "syntactical-comment-transition: colon after source mark char not allowed"))
((equal? char elucidator-marker-char-string) (error "syntactical-comment-transition: double @ not allowed"))
((equal? char (as-string #\newline)) (error "syntactical-comment-transition: newline after @ not allowed"))
(else (list 'source-char "" char))))
((and (symbol? in-state) (eq? in-state 'source-char))
(cond ((equal? char sectional-comment-char-string) (list 'colon-initial-1 elucidator-marker-char-string ""))
((equal? char elucidator-marker-char-string) (list 'at-sign elucidator-marker-char-string ""))
((equal? char (as-string #\space)) (list 'normal
(string-append (render-source-char collected-str) " ") ""))
((equal? char (as-string #\return)) (list 'source-char "" collected-str))
((equal? char (as-string #\newline)) (list 'newline
(render-source-char collected-str) ""))
(else (list 'normal (string-append elucidator-marker-char-string (hp char)) ""))))
((and (symbol? in-state) (eq? in-state 'space-after-source-char))
(cond ((equal? char sectional-comment-char-string) (list 'colon-initial-1 (render-source-char collected-str) ""))
((equal? char elucidator-marker-char-string) (list 'at-sign (render-source-char collected-str) ""))
(else (list 'normal (string-append (render-source-char collected-str) (hp char)) ""))))
((and (symbol? in-state) (eq? in-state 'newline))
(cond ((equal? char sectional-comment-char-string) (list 'colon-initial-1 (comment-glyph c-level) ""))
((equal? char elucidator-marker-char-string) (list 'at-sign (comment-glyph c-level) ""))
((equal? char (as-string #\space)) (list 'newline-and-spaces "" char))
((equal? char (as-string #\newline)) (list 'newline (comment-glyph c-level) ""))
(else (list 'normal (string-append (comment-glyph c-level) " " (hp char)) ""))))
((and (symbol? in-state) (eq? in-state 'newline-and-spaces))
(cond ((equal? char (as-string #\space)) (list 'newline-and-spaces "" (string-append collected-str char)))
((equal? char sectional-comment-char-string) (list 'colon-initial-1 (string-append (comment-glyph c-level collected-str)) ""))
((equal? char elucidator-marker-char-string) (list 'at-sign (string-append (comment-glyph c-level collected-str)) ""))
((equal? char (as-string #\newline)) (list 'newline (string-append (comment-glyph c-level collected-str)) ""))
(else (list 'normal (string-append (comment-glyph c-level collected-str) " " (hp char)) ""))))
(else (error (string-append
"syntactical-comment-transition error: unknown state "
(as-string in-state)))
)
)))
(define (comment-glyph comment-level . in-between-newline-and-semicolon)
(let ((in-between (if (null? in-between-newline-and-semicolon) #f (car in-between-newline-and-semicolon))))
(string-append
(as-string #\newline)
(if in-between in-between "")
(make-string comment-level #\;)
)))
(define (render-sectional-comment section-name)
(if indeed-section-comment
(begin
(set! indeed-section-comment #f)
(string-append
(a-name section-name)
(if show-sectional-comment-name
(b (font-color red section-name))
""))
)
(string-append
(as-string sectional-comment-char) (as-string sectional-comment-char)
section-name
(as-string sectional-comment-char) (as-string sectional-comment-char))))
(define (render-source-char source-char-string)
(string-append
(a-name
(string-append
(as-string enclosing-definition-name)
"-@" source-char-string))
(doc-source-marker-link
documentation-source-marker-occurences
source-char-string
enclosing-definition-name)
))
(define (doc-navigator name documented-names)
(let ((res (assq name documented-names)) )
(if res
(let* ((res-docid (cadr res))
(weak-strong (caddr res))
(res-doc-title (cdr (assq res-docid documentation-key-title-alist)))
)
(con (a-tag-target (string-append "documentation.html" "#" (as-string res-docid))
(cond ((eq? strong-weak 'strong) (image "doc-left.gif" title))
((eq? strong-weak 'weak) (image "doc-left-weak.gif" title))
(else (error "doc-link: problems determining strong or weak documentation link")))
"documentation-frame"
)
(br)))
"")))
(define (total-doc-navigator name documented-names size source-key)
(let* ((doc-entries (filter (lambda (e) (eq? name (car e))) documented-names))
(reversed-doc-entries (reverse doc-entries))
(unique-reversed-doc-entries-0
(remove-duplicates-by-predicate
reversed-doc-entries
(lambda (x y) (and (eq? (cadr x) (cadr y)) (eq? (caddr x) (caddr y))) )))
(unique-reversed-doc-entries (remove-redundant-weak-entries unique-reversed-doc-entries-0))
)
(con
(if (or make-large-source-files? (eq? default-program-font-size 'large))
(con
(if (eq? size 'small)
(a-tag (string-append source-key "-LARGE" ".html" "#" (as-string name)) (image "small-square.gif" "Show source file in large font"))
(a-tag (string-append source-key ".html" "#" (as-string name)) (image "small-square.gif" "Show source file in small font")))
(horizontal-space 1)
)
"")
(if link-definitions-to-cross-reference-index?
(let* ((name-string (as-string name))
(name-first-letter (as-string (string-ref name-string 0))))
(con
(a-tag-target
(if alphabetic-cross-reference-index?
(string-append "cross-reference-index" "-" (hygienic-file-character (downcase-string name-first-letter)) ".html" "#" name-string)
(string-append "cross-reference-index" ".html" "#" name-string))
(image "small-green-up-triangle.gif"
(string-append "In " source-key ": " "Link from " name-string " to it's cross reference table entry"))
"control-frame")
(horizontal-space 1)
))
"")
(if (not (null? unique-reversed-doc-entries))
(string-merge
(map
(lambda (de)
(let* ((doc-id (cadr de))
(strong-weak (caddr de))
(number (cdr (assq doc-id documentation-key-numbering-alist)))
(doc-entry-title (cdr (assq doc-id documentation-key-title-alist))))
(doc-link name doc-id (string-append number ". " doc-entry-title) strong-weak))
)
unique-reversed-doc-entries)
(make-list (- (length unique-reversed-doc-entries) 1) (horizontal-space 1)))
""))))
(define (remove-redundant-weak-entries entries)
(remove-redundant-weak-entries-1 entries entries '()))
(define (remove-redundant-weak-entries-1 all-entries entries res)
(letrec ((redundant-weak-entry?
(lambda (e1 e2)
(and (not (equal? e1 e2)) (eq? 'weak (caddr e1)) (eq? (cadr e1) (cadr e2))))))
(cond ((null? entries) (reverse res))
((member-by-predicate (car entries) all-entries redundant-weak-entry?)
(remove-redundant-weak-entries-1 all-entries (cdr entries) res))
(else (remove-redundant-weak-entries-1 all-entries (cdr entries) (cons (car entries) res))))))
(define (documentation-url doc-id)
(string-append "documentation.html" "#" (as-string doc-id)))
(define (doc-link name doc-id title strong-weak)
(a-tag-target
(documentation-url doc-id)
(cond ((eq? strong-weak 'strong) (image "doc-left.gif" title))
((eq? strong-weak 'weak) (image "doc-left-weak.gif" title))
(else (error "doc-link: problems determining strong or weak documentation link")))
"documentation-frame"))
(define (list-difference-2 defined-name-pairs bounded-names)
(list-difference-3 defined-name-pairs bounded-names '()))
(define (list-difference-3 lst1 lst2 res)
(cond ((null? lst1) (reverse res))
((memq (caar lst1) lst2) (list-difference-3 (cdr lst1) lst2 res))
(else (list-difference-3 (cdr lst1) lst2 (cons (car lst1) res)))))
(define (elucidate-restricted-define-form ip op f size)
(cond ((symbol? f) (match-simple-symbol f ip op))
((list? f)
(match-start-parenthesis ip op)
(for-each
(lambda (sf)
(skip-white-space ip op)
(elucidate-restricted-define-form ip op sf size))
f)
(skip-white-space ip op)
(match-end-parenthesis ip op))
((pair? f)
(let ((p1 (proper-part f))
(p2 (first-improper-part f)))
(skip-white-space ip op)
(match-start-parenthesis ip op)
(for-each
(lambda (sf)
(skip-white-space ip op)
(elucidate-restricted-define-form ip op sf size))
p1)
(skip-white-space ip op)
(match-dot ip op)
(skip-white-space ip op)
(elucidate-restricted-define-form ip op p2 size)
(skip-white-space ip op)
(match-end-parenthesis ip op)
))))
(define (quote-in-input? ip form)
(let ((ch (peek-char ip)))
(if (and (eqv? #\' ch) (and (list? form) (> (length form) 1) (eq? (car form) 'quote)) )
(begin
(read-char ip)
#t)
#f)))
(define (backquote-in-input? ip form)
(let ((ch (peek-char ip)))
(if (and (eqv? #\` ch) (and (list? form) (> (length form) 1) (eq? (car form) 'quasiquote)))
(begin
(read-char ip)
#t)
#f)))
(define (unquote-in-input? ip form)
(let ((ch (peek-char ip)))
(if (and (eqv? #\, ch) (and (list? form) (> (length form) 1) (or (eq? (car form) 'unquote) (eq? (car form) 'unquote-splicing))))
(begin
(read-char ip)
#t)
#f)))
(define (match-symbol sym ip op defined-names size)
(read ip)
(let* ((source-key (name-memq sym defined-names))
(sym-string (as-string sym))
(protected-symbol-string (html-protect sym-string))
(symbol (as-symbol protected-symbol-string))
(size-string (if (eq? size 'large) "-LARGE" ""))
)
(if source-key
(write-string-to-port
(html:a
(font-color applied-color protected-symbol-string)
'href (string-append source-key size-string ".html" "#" (as-string sym))
'title source-key
'style (if underline-program-links "{text-decoration: underline;}" "{text-decoration: none;}")
)
op)
(let ((entry (scheme-knowledge-entry sym)))
(if entry
(let ((url (url-of-scheme-knowledge entry)))
(if url
(write-string-to-port
(html:a
((scheme-syntax-procedure-decorate entry) protected-symbol-string)
'href url
'style (if underline-program-links "{text-decoration: underline;}" "{text-decoration: none;}")
'target manual-frame-from-program
'title "R4RS Scheme form"
)
op)
(write-string-to-port
((scheme-syntax-procedure-decorate entry) protected-symbol-string)
op)))
(let ((man-entry (find-manual-entry sym-string)))
(if man-entry
(let ((url (string-append (cdr man-entry) "#" sym-string)))
(write-string-to-port
(html:a
(font-color manual-name-color protected-symbol-string)
'href url
'style (if underline-program-links "{text-decoration: underline;}" "{text-decoration: none;}")
'target manual-frame-from-program
'title (string-append "Manual: " (file-name-proper url))
)
op))
(display protected-symbol-string op))))))))
(define (match-simple-symbol sym ip op)
(read ip)
(let* ((sym-string (as-string sym))
(protected-symbol-string (html-protect sym-string))
(symbol (as-symbol protected-symbol-string))
)
(display protected-symbol-string op)))
(define (scheme-syntax-procedure-decorate entry)
(cond ((eq? 'syntax (category-of-scheme-knowledge entry)) b)
((eq? 'procedure (category-of-scheme-knowledge entry)) brown-normal)
(else id-1)))
(define (brown-normal txt)
(font-color r4rs-scheme-color (if black-and-white-coloring (em txt) txt)))
(define (id-1 x) x)
(define (scheme-knowledge-entry symbol)
(scheme-knowledge-entry-1 symbol scheme-syntax-procedure-list))
(define (scheme-knowledge-entry-1 symbol lst)
(cond ((null? lst) #f)
((eq? (symbol-of-scheme-knowledge (car lst)) symbol)
(car lst))
(else (scheme-knowledge-entry-1 symbol (cdr lst)))))
(define (name-memq sym defined-names)
(cond ((null? defined-names) #f)
((eq? sym (caar defined-names)) (cdar defined-names))
(else (name-memq sym (cdr defined-names)))))
(define (find-manual-entry name)
(find-in-list
(lambda (name-file-pair)
(equal? (car name-file-pair) name))
manual-name-file-map))
(define (match-string str ip op)
(read ip)
(write (html-protect str) op))
(define (match-char ch ip op)
(read ip)
(write ch op))
(define (match-number n ip op)
(read ip)
(write n op))
(define (match-boolean b ip op)
(read ip)
(write b op))
(define (match-start-parenthesis ip op)
(let ((ch (read-char ip)))
(if (or (eqv? ch #\() (eqv? ch #\[))
(write-char ch op)
(error (string-append "match error: start parenthesis expected:" (as-string ch))))))
(define (match-end-parenthesis ip op)
(let ((ch (read-char ip)))
(if (or (eqv? ch #\)) (eqv? ch #\]))
(write-char ch op)
(error "match error: end parenthesis expected:" (as-string ch)))))
(define (match-dot ip op)
(let ((ch (read-char ip)))
(if (eqv? ch #\.)
(write-char #\. op)
(error "match error: dot expected. Problems if we deal with unnormlized dotted forms"))))
(define (match-number-sign ip op)
(let ((ch (read-char ip)))
(if (eqv? ch #\#)
(write-char #\# op)
(error "match error: number sign expected:" (as-string ch)))))
(define (skip-white-space ip op)
(let ((ch (peek-char ip)))
(cond ((white-space? ch) (begin (read-char ip) (write-char ch op) (skip-white-space ip op)))
((comment-begin? ch) (begin (skip-comment ip op) (skip-white-space ip op)))
(else 'empty))))
(define (white-space? ch)
(if (eof-object? ch)
#f
(let ((n (char->integer ch)))
(or (eqv? n 32) (eqv? n 9) (eqv? n 10) (eqv? n 12) (eqv? n 13)))))
(define (comment-begin? ch)
(eqv? #\; ch))
(define (skip-comment ip op)
(write-string-to-port (start-tag "font" 'color (rgb-string-list comment-color)) op)
(skip-comment-1 ip op)
(write-string-to-port (end-tag "font") op))
(define (report-ambiguous-doc-source-markers amb-list)
(let ((doc-sections
(map (lambda (pid-did-sm)
(let ((doc-id (cadr pid-did-sm)))
(cdr (assq doc-id documentation-key-numbering-alist))))
amb-list)))
(string-append
CR "The relation is ambiguous." CR
(if (= 1 (length amb-list)) "The other relevant section is " "The other relevant sections are ")
(string-merge doc-sections (make-list (- (length amb-list) 1) ", " )))))
(define (doc-source-marker-link documentation-source-marker-occurences mark-char enclosing-definition-name)
(let* ((relevant-occurences
(filter (lambda (pid-did-sm)
(let ((pid (car pid-did-sm))
(sm (caddr pid-did-sm)))
(and (equal? (as-string pid) (as-string enclosing-definition-name))
(equal? (as-string sm) (as-string mark-char)))))
documentation-source-marker-occurences))
(lgt (length relevant-occurences)))
(cond ((= lgt 0) (display-warning
(string-append "No corresponding source marker in the documention: Marker '" (as-string mark-char) "' in "
(as-string enclosing-definition-name))))
((> lgt 1) (display-warning
(string-append "Ambiguous source marker '" (as-string mark-char) "' for "
(as-string enclosing-definition-name) " in the documentation. Using the first one")))
(else ""))
(cond ((>= lgt 1)
(let* ((used-occ (car relevant-occurences))
(doc-id (cadr used-occ))
(num (cdr (assq doc-id documentation-key-numbering-alist)))
(sec-title (cdr (assq doc-id documentation-key-title-alist)))
(ambiguous? (if (> lgt 1) (report-ambiguous-doc-source-markers (cdr relevant-occurences)) ""))
(explanation
(string-append "A linked program source marker to section " num ":" CR (string-it-single sec-title) ambiguous? CR
"Mark char: " (as-string mark-char) ))
)
(a-tag-target (string-append "documentation.html" "#" (as-string doc-id) "-" "@" (as-string mark-char))
(source-marker-image mark-char explanation)
"documentation-frame")))
(else (source-marker-image mark-char "A program source marker WITHOUT a link to the documentation")))))
(define (skip-comment-1 ip op)
(let ((ch (read-char ip)))
(cond ((eof-object? ch) #f)
((eol? ch) (write-char ch op))
((eqv? ch #\<) (write-string-to-port "<" op) (skip-comment-1 ip op))
((eqv? ch #\>) (write-string-to-port ">" op) (skip-comment-1 ip op))
((eqv? ch elucidator-marker-char)
(let ((source-marker-char (read-char ip))
(next-char (read-char ip))
)
(if (is-white-space? next-char)
(write-string-to-port
(string-append
(a-name
(string-append
(as-string enclosing-definition-name)
"-@" (as-string source-marker-char)))
(doc-source-marker-link
documentation-source-marker-occurences
source-marker-char
enclosing-definition-name)
(as-string next-char))
op)
(write-string-to-port
(string-append (as-string elucidator-marker-char) (as-string source-marker-char) (as-string next-char))
op))
(skip-comment-1 ip op)))
(else (begin (write-char ch op) (skip-comment-1 ip op))))))
(define (eol? ch)
(eqv? ch #\newline))
(define (lucid file)
(let* ((source-list (read-source (add-file-extension file "scm")))
(defining-names (defined-names source-list)))
(elucidate-program-source (string-append file ".scm") (string-append file ".html") source-list defining-names '())))
(define (elucidator-frame control-filename program-menu-filename documentation-filename program-filename directory-prefix)
(letrec ((frame-file (lambda (f) (string-append directory-prefix (add-file-extension f "html"))))
(sized-frame-file
(lambda (f) (frame-file (string-append f (if (eq? default-program-font-size 'large) "-LARGE" "")))))
)
(html:frameset
(con (control-frame control-filename program-menu-filename directory-prefix)
(html:frameset
(con (html:frame "" 'name "documentation-frame" 'src (frame-file documentation-filename) 'scrolling "yes")
(html:frame "" 'name "program-frame" 'src (sized-frame-file program-filename) 'scrolling "yes")
)
'cols "50%,50%" 'border 5 'bordercolor (rgb-string-list black))
)
'rows (string-append (as-string control-frame-pixel-height) ",*") 'border 5 'bordercolor (rgb-string-list black)))
)
(define (elucidator-frame-horizontal control-filename program-menu-filename documentation-filename program-filename directory-prefix)
(letrec ((frame-file (lambda (f) (string-append directory-prefix (add-file-extension f "html"))))
(sized-frame-file
(lambda (f) (frame-file (string-append f (if (eq? default-program-font-size 'large) "-LARGE" "")))))
)
(html:frameset
(con (control-frame control-filename program-menu-filename directory-prefix)
(html:frame "" 'name "documentation-frame" 'src (frame-file documentation-filename) 'scrolling "yes")
(html:frame "" 'name "program-frame" 'src (sized-frame-file program-filename) 'scrolling "yes")
)
'rows (string-append (as-string control-frame-pixel-height) ",360,*") 'border 5 'bordercolor (rgb-string-list black)))
)
(define (control-frame control-filename program-menu-filename directory-prefix)
(letrec ((frame-file (lambda (f) (string-append directory-prefix (add-file-extension f "html")))))
(if separate-program-menu?
(html:frameset
(con (html:frame "" 'name "control-frame" 'src (frame-file control-filename) 'scrolling "auto")
(html:frame "" 'name "program-menu" 'src (frame-file program-menu-filename) 'scrolling "auto")
)
'cols "*,240" 'border 1 'bordercolor (rgb-string-list black))
(html:frame "" 'name "control-frame" 'src (frame-file control-filename) 'scrolling "auto"))))
(define (make-frame-file-in-html-dir title frames filename)
(write-text-file
(html:html
(con (html:head
(html:title documentation-title))
frames))
(html-destination filename)))
(define (make-frame-file-in-source-dir title frames filename)
(write-text-file
(html:html
(con (html:head
(html:title documentation-title))
frames))
(source-destination filename)))
(define (documentation-contents)
(con
(a-name "START")
(h 1 (font-color blue (guard-text documentation-title)))
(present-author-info (map guard-text (list documentation-author documentation-email documentation-affiliation))) (p)
(present-abstract (guard-text documentation-abstract)) (vertical-space 1)
(accumulate-right
string-append
""
(map present-documentation-element documentation-elements))
(vertical-space end-file-empty-lines)
))
(define (present-documentation-element doc-el)
(let ((kind (get-value 'kind doc-el)))
(cond ((eq? kind 'section) (present-documentation-section doc-el))
((eq? kind 'entry) (present-documentation-entry doc-el))
(else (error "present-documentation-element: unknown kind of documentation element")))))
(define section-number 0)
(define subsection-number 0)
(define (section-numbering)
(string-append (as-string section-number)))
(define (subsection-numbering)
(string-append (as-string section-number) "." (as-string subsection-number)))
(define (present-documentation-section doc-el)
(let* ((title (get-value 'title doc-el))
(section-numbering (get-value 'numbering doc-el))
(section-number (car (get-value 'raw-numbering doc-el)))
(title-1 (con section-numbering (horizontal-space 2) title))
(intro (get-value 'intro doc-el))
(id (get-value 'id doc-el))
(hidden-id-pres (font 2 documentation-entry-color (as-string id)))
(subsection-elements (filter (subsections? section-number) documentation-elements))
)
(con
(a-name (internal-reference id))
(con
(color-frame-width
(con (section-navigation-banner doc-el) (horizontal-space 1) (if present-hidden-ids? hidden-id-pres "") (br)
(b (con-space (font-size 5 title-1) )) (br)
(do-program-link-documentation intro id)
)
documentation-section-color
"1200")
(indent-pixels 10 (brl (map present-documentation-subsection-element subsection-elements)))
)
(vertical-space 1))))
(define (present-documentation-entry doc-el)
(let* ((title (get-value 'title doc-el))
(entry-numbering (get-value 'numbering doc-el))
(title-1 (con entry-numbering (horizontal-space 2) title))
(body (get-value 'body doc-el))
(id (get-value 'id doc-el))
(hidden-id-pres (font 2 documentation-entry-color (as-string id)))
)
(con
(a-name (internal-reference id))
(color-frame-width (con-space (section-navigation-banner doc-el) (if present-hidden-ids? hidden-id-pres "") (br)
(b (font-size 4 title-1))
)
documentation-entry-color "1200")
(do-program-link-documentation body id)
(vertical-space 2))))
(define (subsections? n)
(lambda (doc-el)
(let ((kind (get-value 'kind doc-el))
(raw-num (get-value 'raw-numbering doc-el)))
(and (eq? kind 'entry) (eqv? n (car raw-num))))))
(define (section-subsection? n m)
(lambda (doc-el)
(let ((raw-num (get-value 'raw-numbering doc-el)))
(and (eqv? n (car raw-num)) (eqv? m (cadr raw-num))))))
(define (present-author-info au)
(let ((au1 (if (not (null? au)) (cons (copyright-owner (car au)) (cdr au)) au)))
(h 3
(con
(apply con
(map (lambda (e) (con e (horizontal-space 4))) au1))
))))
(define (present-abstract abstr)
(let ((width 1200))
(con (color-frame-width (em (con (b "Abstract. ") abstr)) grey2 width) (p)) ))
(define (guard-text str)
(if str str "???"))
(define (make-source-program-file source-key source-group source-file language source-list defining-names documented-names size)
(elucidate-program-source
source-file
(string-append (html-directory) source-key (if (eq? size 'large) "-LARGE" "") ".html")
source-list
defining-names
documented-names
size
source-key
source-group))
(define linking-output-factor 10)
(define (do-program-link-documentation str doc-id)
(let* ((strlgt (string-length str))
(outmax (+ 900 (* linking-output-factor strlgt)))
(res-str (make-string outmax #\space))
)
(set! state-list '())
(do-program-link-documentation-1 doc-id str 0 strlgt res-str 0 outmax 'normal-text "")))
(define state-list '())
(define debugging-program-linking #f)
(define (do-program-link-documentation-1 doc-id instr inptr inlength outstr outptr outlength current-state collected-word)
(if (>= outptr (- outlength 500))
(error "do-program-link-documentation-1: Close to output string overflow. Make linking-output-factor larger"))
(if (= inptr inlength)
(substring outstr 0 outptr)
(let* ((inch (string-ref instr inptr))
(trans-res (program-linking-transition current-state inch collected-word doc-id))
(next-state (car trans-res))
(toput (as-string (cadr trans-res)))
(collected-word (caddr trans-res))
)
(if debugging-program-linking
(set! state-list (cons (list (as-string inch) next-state collected-word) state-list)))
(put-into-string! outstr outptr toput)
(do-program-link-documentation-1 doc-id instr (+ 1 inptr) inlength outstr (+ outptr (string-length toput))
outlength next-state collected-word)
)))
(define (program-linking-transition in-state ch collected-word doc-id)
(let ((char (as-string ch))
(expl (string-append "A link to a program source marker in " (as-string previous-strong-program-word))))
(cond ((and (symbol? in-state) (eq? in-state 'normal-text))
(cond ((equal? char p-link-prefix-char) (list 'entering-p-link-word "" collected-word))
((equal? char d-link-prefix-char) (list 'entering-d-link-word "" collected-word))
((equal? char p-link-suffix-char) (display-warning "Misplaced end-of-link char")
(list 'normal-text "" collected-word))
((equal? char elucidator-marker-char-string) (list 'inside-marker "" ""))
((equal? char elucidator-escape-char-string) (list 'normal-text-escape "" collected-word))
(else (list 'normal-text char collected-word))))
((and (symbol? in-state) (eq? in-state 'inside-marker))
(cond ((or (equal? char p-link-suffix-char) (equal? char p-link-prefix-char)
(equal? char d-link-prefix-char) (equal? char d-link-suffix-char))
(display-warning "Unexpected marker char")
(list 'normal-text (string-append elucidator-marker-char-string char) collected-word))
(else (list 'normal-text
(begin
(source-mark-register previous-strong-program-word doc-id char)
(con (source-mark-anchor (source-marker-glyph char expl) char)
(a-name (string-append (as-string doc-id) "-" "@" (as-string char)))))
collected-word))
))
((and (symbol? in-state) (eq? in-state 'normal-text-escape))
(cond (else (list 'normal-text char collected-word))))
((and (symbol? in-state) (eq? in-state 'entering-p-link-word))
(cond ((equal? char p-link-suffix-char) (display-warning "Empty link word")
(list 'leaving-p-link-word "" collected-word))
((equal? char p-link-prefix-char) (display-warning "Misplaced begin-of-link char")
(list 'inside-p-link-word "" collected-word))
((or (equal? char d-link-prefix-char) (equal? char d-link-prefix-char)) (display-warning "Misplaced documentation link char")
(list 'inside-p-link-word "" collected-word))
(else (list 'inside-p-link-word "" char))))
((and (symbol? in-state) (eq? in-state 'entering-d-link-word))
(cond ((equal? char d-link-suffix-char) (display-warning "Empty link word")
(list 'leaving-d-link-word "" collected-word))
((equal? char d-link-prefix-char) (display-warning "Misplaced begin-of-link char")
(list 'inside-d-link-word "" collected-word))
((or (equal? char p-link-prefix-char) (equal? char p-link-prefix-char)) (display-warning "Misplaced program link char")
(list 'inside-d-link-word "" collected-word))
(else (list 'inside-d-link-word "" char))))
((and (symbol? in-state) (eq? in-state 'inside-p-link-word))
(cond ((equal? char p-link-suffix-char) (list 'leaving-p-link-word (linking-from-doc-to-prog collected-word doc-id) ""))
((equal? char p-link-prefix-char) (display-warning "Misplaced begin-of-link prog char")
(list 'inside-p-link-word "" collected-word))
((or (equal? char d-link-prefix-char) (equal? char d-link-prefix-char)) (display-warning "Misplaced documentation link char")
(list 'inside-p-link-word "" collected-word))
(else (list 'inside-p-link-word "" (string-append collected-word char)))))
((and (symbol? in-state) (eq? in-state 'inside-d-link-word))
(cond ((equal? char d-link-suffix-char) (list 'leaving-d-link-word (linking-from-doc-to-doc collected-word doc-id) ""))
((equal? char d-link-prefix-char) (display-warning "Misplaced begin-of-link doc char")
(list 'inside-d-link-word "" collected-word))
((or (equal? char p-link-prefix-char) (equal? char p-link-prefix-char)) (display-warning "Misplaced program link char")
(list 'inside-d-link-word "" collected-word))
(else (list 'inside-d-link-word "" (string-append collected-word char)))))
((and (symbol? in-state) (eq? in-state 'leaving-p-link-word))
(cond ((equal? char p-link-suffix-char) (display-warning "Misplaced end-of-link prog char")
(list 'leaving-p-link-word "" collected-word))
((equal? char p-link-prefix-char) (list 'inside-p-link-word "" collected-word))
((equal? char d-link-prefix-char) (list 'inside-d-link-word "" collected-word))
(else (list 'normal-text char collected-word))))
((and (symbol? in-state) (eq? in-state 'leaving-d-link-word))
(cond ((equal? char d-link-suffix-char) (display-warning "Misplaced end-of-link doc char")
(list 'leaving-p-link-word "" collected-word))
((equal? char p-link-prefix-char) (list 'inside-p-link-word "" collected-word))
((equal? char d-link-prefix-char) (list 'inside-d-link-word "" collected-word))
(else (list 'normal-text char collected-word))))
(else (error "program-linking-transition error: unknown state"))
)))
(define (source-mark-register previous-strong-program-word doc-id char)
(set! documentation-source-marker-occurences
(cons (list previous-strong-program-word doc-id char)
documentation-source-marker-occurences)))
(define (linking-from-doc-to-doc collected-word doc-id)
(let* ((ass-number (assq (as-symbol collected-word) documentation-key-numbering-alist))
(ass-title (assq (as-symbol collected-word) documentation-key-title-alist))
(ref-number (if ass-number (cdr ass-number) #f))
(ref-title (if ass-title (cdr ass-title) #f))
(url (if ref-number (string-append "documentation.html" "#" collected-word) #f)))
(if url
(html:a
(font-color documentation-documentation-link-color ref-number)
'href url
'style "{text-decoration: underline;}"
'target "documentation-frame"
'title (if ref-title ref-title ""))
(begin
(display-warning (string-append "Cannot find a linking target of the documentation linking word: " collected-word))
collected-word))))
(define previous-strong-program-word #f)
(define (linking-from-doc-to-prog word doc-id)
(let* ((kind (kind-of-program-link? word))
(qualification (qualified-program-link? word))
(word-1 (proper-linking-word word qualification))
(strong? (eq? kind 'strong))
(strong-weak-symbol (if strong? 'strong 'weak))
(link-targets (filter (lambda (dno) (equal? word-1 (as-string (car dno)))) defining-name-occurences))
(size-string (if (eq? default-program-font-size 'large) "-LARGE" ""))
)
(cond ((eq? kind 'none)
(font-color none-reference-color (kbd word-1)))
((and (empty-string? word-1) (not (empty-string? qualification)))
(let ((source-key qualification))
(html:a
(font-color (if strong? documentation-program-link-color documentation-program-link-color-weak) (kbd (b source-key)))
'href (string-append source-key size-string ".html")
'target "program-frame"
'title (string-append "Link to program file: " source-key)
'style (if underline-documentation-links "{text-decoration: underline;}" "{text-decoration: none;}")
)
))
((= (length link-targets) 0)
(let ((man-entry (find-manual-entry word-1))
)
(if man-entry
(let ((url (string-append (cdr man-entry) "#" word-1)))
(html:a
(font-color manual-name-color word-1)
'href url
'style (if underline-program-links "{text-decoration: underline;}" "{text-decoration: none;}")
'target manual-frame-from-documentation
'title (string-append "Manual: " (file-name-proper url))
))
(begin
(display-warning (string-append "Documentation to program linking: Cannot find linking target of " word-1))
word-1)))
)
((= (length link-targets) 1)
(let ((source-key (cdr (car link-targets))))
(if strong? (set! previous-strong-program-word word-1))
(set! documented-name-occurences (cons (list (as-symbol word-1) doc-id strong-weak-symbol) documented-name-occurences))
(if (and qualification (not (equal? qualification source-key)))
(display-warning (string-append "Disregarding the qualification of " word)))
(html:a
(font-color (if strong? documentation-program-link-color documentation-program-link-color-weak) (if (and strong? black-and-white-coloring) (b (kbd word-1)) (kbd word-1)))
'href (string-append source-key size-string ".html" "#" word-1)
'target "program-frame"
'title source-key
'style (if underline-documentation-links "{text-decoration: underline;}" "{text-decoration: none;}")
)
))
((and (> (length link-targets) 1) qualification)
(let* ((possible-source-keys (map cdr link-targets))
(qualification-ok (member qualification possible-source-keys))
(source-key (if qualification-ok qualification (cdr (car link-targets)))))
(if strong? (set! previous-strong-program-word word-1))
(set! documented-name-occurences (cons (list (as-symbol word-1) doc-id strong-weak-symbol) documented-name-occurences))
(if (not qualification-ok)
(display-warning (string-append "Illegal qualification in " word ". Using that in " source-key)))
(html:a
(font-color (if strong? documentation-program-link-color documentation-program-link-color-weak) (kbd word-1))
'href (string-append source-key size-string ".html" "#" word-1)
'target "program-frame"
'title source-key
'style (if underline-documentation-links "{text-decoration: underline;}" "{text-decoration: none;}")
)
))
((> (length link-targets) 1)
(let ((source-key (cdr (car link-targets))))
(if strong? (set! previous-strong-program-word word-1))
(set! documented-name-occurences (cons (list (as-symbol word-1) doc-id strong-weak-symbol) documented-name-occurences))
(display-warning (string-append "Multiple targets of the program reference " word-1
". Consider a qualification. " "Using that in " source-key))
(html:a
(font-color (if strong? documentation-program-link-color documentation-program-link-color-weak) (kbd word-1))
'href (string-append source-key size-string ".html" "#" word-1)
'target "program-frame"
'title source-key
'style (if underline-documentation-links "{text-decoration: underline;}" "{text-decoration: none;}")
)
))
)))
(define (qualified-program-link? word)
(let ((end-qual (find-in-string word #\$)))
(if end-qual
(let* ((init-char (string-ref word 0))
(start-qual
(cond ((eqv? init-char strong-link-char) 1)
((eqv? init-char weak-link-char) 1)
((eqv? init-char none-link-char) 1)
(else 0)))
(candidate-qual (substring word start-qual end-qual)))
(if (member candidate-qual source-key-list)
candidate-qual
#f))
#f)))
(define (proper-linking-word word qualification)
(if qualification
(substring word (+ 1 (find-in-string word #\$)) (string-length word))
(let* ((init-char (string-ref word 0))
(start (cond ((eqv? init-char strong-link-char) 1)
((eqv? init-char weak-link-char) 1)
((eqv? init-char none-link-char) 1)
(else 0))))
(substring word start (string-length word)))))
(define (strong-program-link? word)
(if (>= (string-length word) 1)
(eqv? (string-ref word 0) strong-link-char)
#f))
(define (kind-of-program-link? word)
(if (>= (string-length word) 1)
(let ((ch (string-ref word 0)))
(cond ((eqv? ch strong-link-char) 'strong)
((eqv? ch weak-link-char) 'weak)
((eqv? ch none-link-char) 'none)
(else default-program-link)))
#f))
(define (linking-word-of-strong-link star-word)
(substring star-word 1 (string-length star-word)))
(define (linking-word-of-other-link link-word)
(substring link-word 1 (string-length link-word)))
(define (duplicated-definitions name-def-list)
(let* ((sorted-names (sort-list name-def-list name-entry-leq?))
(paired-names (if (null? sorted-names) '() (pair-up sorted-names (cdr sorted-names))))
(filtered-pairs (filter (lambda (p) (eq? (car (car p)) (car (cdr p)))) paired-names))
(duplicate-names (map caar filtered-pairs)))
(filter (lambda (ne) (memq (car ne) duplicate-names)) sorted-names)))
(define (present-duplicated-definitions)
(let ((dd (duplicated-definitions defining-name-occurences)))
(con
(indent-pixels 10
(multi-column-list 4 (map present-a-duplicate dd) browser-pixel-width))
(font-size 1 (em "Navigation to duplicates in the same source file is not supported")))))
(define (present-a-duplicate d)
(con
(a-tag-target
(string-append (cdr d) ".html" "#" (as-string (car d)))
(font-size 2 (con (as-string (car d))))
"program-frame")
(font-size 2 (con " in file " (cdr d)))))
(define (name-entry-leq? x y)
(string<=? (as-string (car x)) (as-string (car y))))
(define (present-defined-name-index sorted-defining-name-occurences)
(con
(indent-pixels 10
(multi-column-list 6
(map present-a-defining-name-entry sorted-defining-name-occurences) browser-pixel-width))
))
(define (present-a-defining-name-entry d)
(let ((sourcefile (cdr d))
(size-string (if (eq? default-program-font-size 'large) "-LARGE" ""))
)
(html:a
(font 2 defined-color (con (html-protect (as-string (car d)))))
'href (string-append sourcefile size-string ".html" "#" (as-string (car d)))
'target "program-frame"
'title sourcefile)))
(define (applied-names-multiple-sources source-list-list)
(sort-list
(accumulate-right
append
'()
(map applied-names source-list-list))
name-entry-leq?))
(define (applied-names source-list)
(applied-names-1 source-list '()))
(define (applied-names-1 source-list res)
(cond ((null? source-list) res)
((is-define-form? (car source-list))
(let* ((define-form (car source-list))
(def-name (defined-name define-form))
(this-contribution (map (lambda (appl-name) (cons appl-name def-name)) (applied-names-one-form define-form))))
(applied-names-1 (cdr source-list) (append this-contribution res))))
(else (applied-names-1 (cdr source-list) res))
))
(define (applied-names-one-form f)
(cond ((eof-object? f)
)
((symbol? f) (if (defining-in-batch? f) (list f) '()))
((string? f) '())
((number? f) '())
((char? f) '())
((boolean? f) '())
((vector? f) (applied-names-one-form (vector->list f)))
((and (list? f) (null? f)) '())
((and (list? f) (function-define-form? f)) (applied-names-one-form (cdddr f)))
((and (list? f) (is-define-form? f)) (applied-names-one-form (cddr f)))
((and (list? f) (lambda-form? f)) (applied-names-one-form (cddr f)))
((and (list? f) (let-form? f)) (append (applied-names-one-form (let-vals f)) (applied-names-one-form (cddr f))))
((list? f) (append (applied-names-one-form (car f)) (applied-names-one-form (cdr f))))
((pair? f)
(let ((p1 (proper-part f))
(p2 (first-improper-part f)))
(append (applied-names-one-form p1) (applied-names-one-form p2))
))
(else (error (string-append "applied-names-one-form: unknown kind of expression" (as-string f))))))
(define (defining-in-batch? name)
(if (assq name defining-name-occurences) #t #f))
(define (function-define-form? x)
(and (list? x)
(> (length x) 2)
(eq? (car x) 'define)
(symbol? (cadr x))
(pair? (caddr x))))
(define (lambda-form? x)
(and (list? x)
(> (length x) 2)
(eq? (car x) 'lambda)))
(define (let-form? x)
(and (list? x)
(> (length x) 2)
(or (eq? (car x) 'let) (eq? (car x) 'let*) (eq? (car x) 'letrec))))
(define (let-vals let-form)
(let ((binding-forms (if (named-let? let-form)
(caddr let-form)
(cadr let-form))))
(accumulate-right append '() (map cdr binding-forms))))
(define (let-names let-form)
(let ((binding-forms (if (named-let? let-form)
(caddr let-form)
(cadr let-form))))
(accumulate-right append '() (map (lambda (b) (list (car b))) binding-forms))))
(define (named-let? let-form)
(symbol? (cadr let-form)))
(define (lambda-names lambda-form)
(let ((par-list (cadr lambda-form)))
(cond ((list? par-list) par-list)
((symbol? par-list) (list par-list))
((pair? par-list) (append (proper-part par-list) (list (first-improper-part par-list))))
(error "lambda name: unknown kind of the lambda form's parameter list"))))
(define (present-cross-reference-index appl-def-name-list-1)
(let* ((appl-def-name-sublisted
(sublist-by-predicate appl-def-name-list-1 (lambda (x y n) (not (eq? (car x) (car y))))))
(appl-def-name-sublisted-1
(map (lambda (sublist)
(remove-duplicates-by-predicate
sublist
(lambda (x y) (eq? (cdr x) (cdr y)))))
appl-def-name-sublisted))
)
(indent-pixels 5
(table-3 0
(list 200 1000)
(map present-applied-sublist appl-def-name-sublisted-1)))))
(define (present-applied-sublist sl)
(let* ((sorted-sl (sort-list sl (lambda (x y) (string<=? (as-string (cdr x)) (as-string (cdr y))))))
(appl-name (car (car sl)))
(def-table
(multi-column-list 5
(map present-defined-entry sorted-sl) (- browser-pixel-width 200)))
(sourcefile (source-key-of-defining-name appl-name))
(size-string (if (eq? default-program-font-size 'large) "-LARGE" ""))
)
(list (con
(a-name (html-protect (as-string appl-name)))
(box
(html:a
(b (font 2 defined-color (html-protect (as-string appl-name))))
'href (string-append sourcefile size-string ".html" "#" (as-string appl-name))
'target "program-frame"
'title sourcefile)))
def-table)))
(define (present-defined-entry appl-def-entry)
(let* ((appl-name (car appl-def-entry))
(def-name (cdr appl-def-entry))
(sourcefile (source-key-of-defining-name def-name))
(size-string (if (eq? default-program-font-size 'large) "-LARGE" ""))
)
(if def-name
(html:a
(font-size 2 (con (html-protect (as-string def-name))))
'href (string-append sourcefile size-string ".html" "#" (as-string def-name))
'target "program-frame"
'title sourcefile)
(font-size 2 (em "not used")))))
(define (source-key-of-defining-name name)
(let ((res (filter (lambda (dno) (eq? name (car dno))) defining-name-occurences)))
(cond ((= (length res) 0) "??")
((= (length res) 1) (cdr (car res)))
((> (length res) 1) (cdr (car res)))
)))
(define (merge-defined-and-defined-applied-lists def-applied-list def-list)
(merge-defined-and-defined-applied-lists-1 def-applied-list def-list '()))
(define (merge-defined-and-defined-applied-lists-1 lst1 lst2 res)
(letrec ((lt-cars? (lambda (x y) (string<? (as-string (car x)) (as-string (car y)))))
(eq-cars? (lambda (x y) (eq? (car x) (car y))))
)
(cond ((and (null? lst1) (null? lst2)) (reverse res))
((null? lst1) (append (reverse res) lst2))
((null? lst2) (append (reverse res) lst1))
((eq-cars? (car lst1) (car lst2))
(merge-defined-and-defined-applied-lists-1 (cdr lst1) (cdr lst2) (cons (car lst1) res)))
((lt-cars? (car lst1) (car lst2))
(merge-defined-and-defined-applied-lists-1 (cdr lst1) lst2 (cons (car lst1) res)))
((lt-cars? (car lst2) (car lst1))
(merge-defined-and-defined-applied-lists-1 lst1 (cdr lst2) (cons (car lst2) res)))
(else (error "merge-defined-and-defined-applied-lists-1: should not happen!")))))
(define (present-documentation-contents doc-elements kind)
(let ((doc-elements-1
(cond ((eq? kind 'detail) doc-elements)
((eq? kind 'overall) (filter (lambda (e) (eq? (get-value 'kind e) 'section)) doc-elements)))))
(n-column-list
(if (eq? kind 'detail) toc-columns-detail toc-columns-overall)
(map present-documentation-content-element doc-elements-1)
browser-pixel-width)))
(define (present-documentation-content-element element)
(let ((kind (get-value 'kind element))
(doc-id (get-value 'id element))
(n (get-value 'numbering element))
(ttl (get-value 'title element)))
(font-size 2
(con
(cond ((eq? kind 'entry) (horizontal-space 4))
((eq? kind 'section) "")
(else (error "present-documentation-content-element: unknown kind of documentation element")))
n (horizontal-space 2)
(a-tag-target (string-append "documentation.html" "#" (as-string doc-id))
ttl
"documentation-frame"
)))))
(define (present-documentation-subsection-element element)
(let ((doc-id (get-value 'id element))
(n (get-value 'numbering element))
(ttl (get-value 'title element)))
(font-size 2
(con
n (horizontal-space 2)
(a-tag-target (string-append "documentation.html" "#" (as-string doc-id))
(font-color black ttl)
"documentation-frame"
)))))
(define (documentation-from file)
(display-message (string-append "Parsing the textual documentation file"))
(reset-collection)
(let* ((ip (open-input-file (string-append source-directory file))))
(documentation-intro-from-port ip)
(documentation-units-from-port ip)
(close-input-port ip)))
(define (documentation-intro-from-port ip)
(let* ((skip1 (skip-while white-space-or-separator? ip))
(intro (accept-documentation-intro ip)))
(define-documentation-intro! intro)))
(define (documentation-units-from-port ip)
(let* ((skip1 (skip-while white-space-or-separator? ip))
(unit (accept-documentation-unit ip))
(separator-skip (skip-while white-space-or-separator? ip))
)
(if (unit-ok? unit)
(define-unit! unit)
(error (string-append "documentation-units-from-port: Malformed documentation unit: " (as-string unit))))
(if (not (eof-object? next-doc-char))
(documentation-units-from-port ip))))
(define (unit-ok? unit)
#t)
(define unit-list '())
(define (define-unit! unit)
(let ((doc-form (make-documentation-form unit)))
(set! unit-list (cons doc-form unit-list))
(eval-cur-env doc-form)))
(define (define-documentation-intro! intro-list)
(documentation-intro
(first intro-list) (second intro-list) (third intro-list)
(fourth intro-list) (fifth intro-list)))
(define (make-documentation-form unit)
(let* ((kind-string (car (car unit)))
(kind (cond ((equal? kind-string ".ENTRY") 'documentation-entry)
((equal? kind-string ".SECTION") 'documentation-section)
(else (error "make-documentation-form: Unknown documentation kind"))))
(id (as-symbol (cadr (car unit))))
(title (cadr unit))
(body (caddr unit)))
(list kind
(list 'id (list 'quote id))
(list 'title title)
(if (eq? kind 'documentation-entry) (list 'body body) (list 'intro body)))))
(define (accept-documentation-unit ip)
(let* ((id (accept-doc-id ip))
(ttl (accept-doc-title ip))
(bd (accept-doc-body ip)))
(list id ttl bd)))
(define (accept-documentation-intro ip)
(let* ((ttl (accept-doc-title ip))
(aut (accept-doc-author ip))
(email (accept-doc-email ip))
(af (accept-doc-affiliation ip))
(abstr (accept-doc-abstract ip))
)
(list ttl aut email af abstr)))
(define (accept-doc-author ip)
(let* ((keyword (collect-until is-white-space? ip))
(res (doc-check (equal? keyword ".AUTHOR") ".AUTHOR expected"))
(skip1 (skip-while is-white-space? ip))
(res (collect-until end-of-line? ip))
(skip2 (skip-while is-white-space? ip)))
res))
(define (accept-doc-email ip)
(let* ((keyword (collect-until is-white-space? ip))
(res (doc-check (equal? keyword ".EMAIL") ".EMAIL expected"))
(skip1 (skip-while is-white-space? ip))
(res (collect-until end-of-line? ip))
(skip2 (skip-while is-white-space? ip)))
res))
(define (accept-doc-affiliation ip)
(let* ((keyword (collect-until is-white-space? ip))
(res (doc-check (equal? keyword ".AFFILIATION") ".AFFILIATION expected"))
(skip1 (skip-while is-white-space? ip))
(res (collect-until end-of-line? ip))
(skip2 (skip-while is-white-space? ip)))
res))
(define (accept-doc-abstract ip)
(let* ((keyword (collect-until is-white-space? ip))
(res (doc-check (equal? keyword ".ABSTRACT") ".ABSTRACT expected"))
(skip1 (skip-while is-white-space? ip))
(body (accept-body-text ip)))
body))
(define (accept-doc-id ip)
(let* ((unit (collect-until is-white-space? ip))
(res (doc-check (or (equal? unit ".ENTRY") (equal? unit ".SECTION")) ".ENTRY or .SECTION expected"))
(skip1 (skip-while is-white-space? ip))
(id (collect-until is-white-space? ip))
(skip2 (skip-while is-white-space? ip)))
(list unit id)))
(define (accept-doc-title ip)
(let* ((keyword (collect-until is-white-space? ip))
(res (doc-check (equal? keyword ".TITLE") ".TITLE expected"))
(skip1 (skip-while is-white-space? ip))
(ttl (collect-until end-of-line? ip))
(skip2 (skip-while is-white-space? ip)))
ttl))
(define (accept-doc-body ip)
(let* ((keyword (collect-until is-white-space? ip))
(res (doc-check (equal? keyword ".BODY") ".BODY expected"))
(skip1 (skip-while is-white-space? ip))
(body (accept-body-text ip)))
body))
(define (accept-body-text ip)
(let* ((body-list (reverse (accept-body-text-1 ip '())))
(cr-list (make-list (- (length body-list) 1) CR-string)))
(string-merge
body-list
cr-list)))
(define CR-string (as-string #\newline))
(define (accept-body-text-1 ip res)
(let* ((line (collect-until end-of-line? ip))
(skip1 (eat-eol-chars ip)))
(cond ((end-unit? line) res)
(else (accept-body-text-1 ip (cons line res))))))
(define (doc-check condition error-text)
(if (not condition)
(error (string-append "Line " (as-string doc-line-number) ": " error-text))))
(define (end-unit? line)
(if (< (string-length line) 4)
#f
(equal? ".END" (substring line 0 4))))
(define buffer-length 10000)
(define collection-buffer (make-string buffer-length #\space))
(define next-doc-char #f)
(define doc-line-number 1)
(define (reset-collection)
(set! collection-buffer (make-string buffer-length #\space))
(set! next-doc-char #f)
(set! doc-line-number 1))
(define (collect-until p ip)
(collect-until-1 p ip collection-buffer 0)
)
(define (collect-until-1 p ip buffer next)
(let ((ch (read-next-doc-char ip)))
(if (or (p ch) (eof-object? ch))
(begin
(set! next-doc-char ch)
(substring buffer 0 next))
(begin
(string-set! buffer next ch)
(collect-until-1 p ip buffer (+ 1 next))))))
(define (read-next-doc-char ip)
(if next-doc-char
(let ((res next-doc-char))
(set! next-doc-char #f)
res)
(let ((ch (read-char ip)))
(if (and (not (eof-object? ch)) (= 10 (char->integer ch))) (set! doc-line-number (+ doc-line-number 1)))
ch)))
(define (skip-while p ip)
(let ((ch (read-next-doc-char ip)))
(if (p ch)
(skip-while p ip)
(set! next-doc-char ch))))
(define (eat-eol-chars ip)
(let ((ch (read-char ip)))
(cond ((eof-object? ch) (set! next-doc-char ch))
((= 10 (as-number ch)) (set! next-doc-char #f))
(else (set! next-doc-char ch)))))
(define (skip-once p ip)
(let ((ch (read-next-doc-char ip)))
(if (p ch)
(let ((ch (read-next-doc-char ip)))
(set! next-doc-char ch))
(set! next-doc-char ch))))
(define (is-white-space? ch)
(if (eof? ch)
#f
(let ((n (as-number ch)))
(or (eqv? n 32) (eqv? n 9) (eqv? n 10) (eqv? n 12) (eqv? n 13)))))
(define (white-space-or-separator? ch)
(if (eof? ch)
#f
(or (is-white-space? ch) (eqv? #\- ch))))
(define (end-of-line? ch)
(if (eof? ch)
#f
(let ((n (as-number ch)))
(or (eqv? n 10) (eqv? n 13)))))
(define (eof? ch)
(eof-object? ch))
(define (make-elucidator-help-page)
(let ((kn-email "normark@cs.auc.dk")
(kn-www "http://www.cs.auc.dk/~normark/")
)
(letrec ((an-entry (lambda (x y) (con (font-color red (b x)) (br) y))))
(write-text-file
(page
"Elucidator help page"
(con-par
(h 1 (font-color blue "The Elucidator Help Page"))
(con "The "
(a-tag-target "http://www.cs.auc.dk/~normark/elucidative-programming/index.html" "elucidative programming home page" "elu-home") " and the "
(a-tag-target "http://dopu.cs.auc.dk" "DOPU page" "dopu-home") " are the primary places to find information
about elucidative programming.")
(con-space "The pages shown in this browser is the result of 'elucidating' a number of programs and a documentation file.
The main purpose is to present " (em "internal program documentation") " side by side with a number of source programs.
The leftmost window shows the documentation, and the rightmost window one of the programs. The topmost window
is a menu and index window, from which a number of aspects can be controlled.")
(con-space (em "Elucidative programming") " is variant of "
(a-tag "http://www.loria.fr/services/tex/english/litte.html" "literate programming") ", as coined by Knuth in the early eighties.
In most literate programming tools (called WEB tools), fragments of programs are defined inside the
program documentation. In literate programming, a tool (called tangle) can extract and assemble the program fragments according to
the rules of the programming language. Another tool (called weave) formats the documentation, generates indexes,
and presents all of it in a nice-looking paper format.")
"The main characteristics of elucidative programming in relation to literate programming are:"
(ol (list
(an-entry "The program source files are not affected at all."
"It is not necessary to split the programs into fragments,
and to organize these in the context of the program explanations.
An existing program source file can be handled.")
(an-entry "The program and the documentation are shown side by side."
"We do not go for an embedded presentation of the program inside its documentation.
Rather, we provide for mutual navigation
between program and documentation in a two-frame layout")
(an-entry "The program units which we document, are whole abstractions."
"Things get simpler when we can settle on documentation of named abstractions
instead of arbitrary program fragments (sometimes called 'chunks' or 'scraps')")
(an-entry "We support on-line presentation in a browser."
"Literate programming tools were primary oriented towards presentation of the weaved results on a static paper medium.")
(an-entry "The elucidator tool use specific knowledge about the programming language."
(con "The language knowledge is used to identify the names in the program. Applied names are related to their definitions,
and the program is decorated with colors and extensive linking. Currently we support the programming language "
(a-tag "http://www.schemers.org" "Scheme") " and Java (see " (a-tag "http://dopu.cs.auc.dk/portal.html" "the web pages about the Java elucidator") ")."
))
(an-entry "Program and documentation indexes are available."
"A tables of contents, an index of the program definitions, and a cross reference index is available")
(an-entry "The creation of the format, from which the elucidated information is generated,
is supported by a special set of editor commands."
"In that way it is realistic to handle the practical aspect of documenting a program while it is written")
))
(con-space "A " (em "documentation bundle") " consist of a single documentation file, a number of program files, and a setup file.
The documentation file is described in very simple, textual format, which allows the use of HTML tags for formatting.
As mentioned above, there are no special requirements to the program files.
The setup files is a Scheme file, which describes the the constituents of the documentation bundle
together with a number of processing parameters.
Running the setup file through a Scheme processor generates the HTML pages shown in this browser.")
"The icons in the menu and index frame (at the top) are now described:"
(table-3
1
(list 100 600)
(list
(map b (list "Icon" "Explanation"))
(list (image "three-frames.gif" "")
"Reset the elucidator to vertical layout (the default layout). All frames are reverted to the 'start position'.")
(list (image "three-frames-horizontal.gif" "")
"Reset the elucidator to a horizontal layout. This is an alternative layout in which the documentation and
a selected program are shown under each other, in full width")
(list (image "index.gif" "" )
"Presents an index of all defined names in the menu and index frame, just below the icons at the top of the window.
The index is pr. default broken into fragments according to starting letter of the defined name.")
(list (image "cross-index.gif" "" )
"Presents a cross reference index in the menu and index frame.
A cross reference index relates all applied names to the definition, in which they occur.
The index is pr. default broken into fragments according to starting letter of the applied name.")
(list (image "xx.gif" "")
"Present an index of all named defined more than once in the documentation bundle.
This is useful information in a Lisp program")
(list (image "overall-contents.gif" "") "Present an overall table of contents for the documentation in the menu and index frame.
This table of contents only covers the top-level section, but no subsections.")
(list (image "contents.gif" "") "Present a table of contents for the documentation in the menu and index frame.
This table of contents convers both top-level sections and subsections (also called entries).")
(list (image "question-left-arrow.gif" "") "Present an Elucidator help page in the documentation frame to the left")
(list (image "question-right-arrow.gif" "") "Present an Elucidator help page in the program frame to the right")
)
)
"The icons in the rightmost group allows navigation to each of the program files in a documentation bundle."
(con-space "From the documentation frame (to the left) it is possible to adjust the program window, such that a given piece of
program is shown. Similarly, from the program frame (to the right), the yellow left arrows "
(image "doc-left.gif" "") " can be used to find the
section in the documentation, which " (em "explains") " the particular program unit. The light yellow arrows " (image "doc-left-weak.gif" "") " refer to a documentation section
which " (em "mentions") " the definition (as opposed to explaining it). We talk about strong and weak relations between the documentation and the program resp.
Besides these means of navigation
it is possible to navigate inside the documentation frame, and inside the program frames.")
(con "Inside the program and inside documentation sections you may find small color bullets like " (image "source-mark-red.gif" "") ". These are called " (em "source markers") ".
The source markers are used
to point out a particular place in a piece of program, which is discussed in a documentation section. You can click on a source marker in
the documentation in order to navigate to the corresponding source marker in the program. Also navigation in the opposite direction is supported
from most source markers. The popup text, which appears in most browsers when the cursor rests on a source marker, gives useful additional information
about the source marker.
Notice that a source marker in the documentation is associated with
the closest preceding " (em "strong") " documentation-program relation.")
(con-space "The source programs are, by default, shown using a fairly small font size. The small square symbols "
(image "small-square.gif" "") " can be used to toggle the program frames to use larger font.
Notice that the small square symbol is only shown in certain configurations
(when the variable " (kbd "make-large-source-files?") " is true or in the case that variable
default-program-font-size is set to large)")
(con "The icon " (image "small-green-up-triangle.gif" "")
" is an anchor of a link from a definition to an entry in the cross reference index.
This link is very convenient because it allows us to follow call chains via the cross reference index:
Go from a definition of N to the cross reference entry N. Find via that entry a function F which calls N;
Go the cross reference entry of F, and find a function G which calls F, etc.")
(con-space "The elucidator is written in Scheme, using the "
(a-tag "http://www.cs.auc.dk/~normark/laml/" "LAML") " software packages.")
(em "You can use the browser's back button to establish the original contents of this frame,
or you can activate the reset elucidator icon in the top left corner
to return to the standard layout.")
(con-space "Kurt Nørmark" (br) "Aalborg University" (br) kn-email (br) (a-tag kn-www))
)
white black blue blue)
(html-destination "elucidator-help") ))))
(define marker-associations
(list
(list #\a "red" '(255 0 0))
(list #\b "green" '(0 128 0))
(list #\c "blue" '(0 0 255))
(list #\d "black" '(0 0 0))
(list #\e "maroon" '(128 0 0))
(list #\f "grey" '(128 128 128))
(list #\g "purple" '(128 0 128))
(list #\h "silver" '(192 192 192))
(list #\i "tetal" '(0 128 128))
(list #\j "aqua" '(0 255 255))
(list #\k "lime" '(0 255 0))
(list #\l "olive" '(128 128 0))
(list #\m "yellow" '(255 255 0))
(list #\n "navy" '(0 0 128))
(list #\o "fuchsia" '(255 0 255))
))
(define (source-marker-image ch explanation)
(let* ((ch1 (as-char ch))
(ass-res (assv ch1 marker-associations))
(color (if ass-res (cadr ass-res) "error")))
(image (string-append "source-mark-" color ".gif") explanation)))
(define (source-marker-glyph ch explanation)
(cond ((eq? source-marker-kind 'as-text) (source-marker-text ch #f))
((eq? source-marker-kind 'as-colored-text) (source-marker-text ch #t))
((eq? source-marker-kind 'as-image) (source-marker-image ch explanation))
(else (error (string-append
"source-marker-glyph: Problems determining the kind of source marker in the documentation: "
(as-string source-marker))))))
(define (source-marker-text ch color?)
(let* ((ch1 (as-char ch))
(ass-res (assv ch1 marker-associations))
(color (if ass-res (cadr ass-res) "??"))
(text (string-append color " " "marker"))
(rgb-list (if ass-res (caddr ass-res) '(0 0 0))))
(font-color (if color? rgb-list '(0 0 0)) (b text))))
(define (source-mark-anchor mark-glyph mark-char)
(let ((link-targets (filter (lambda (dno) (equal? previous-strong-program-word (as-string (car dno)))) defining-name-occurences))
(size-string (if (eq? default-program-font-size 'large) "-LARGE" ""))
)
(cond ((= (length link-targets) 0)
(display-warning
(string-append "Linking from source marker in documentation: Cannot find linking target of " ))
mark-glyph)
((= (length link-targets) 1)
(let ((source-key (cdr (car link-targets))))
(a-tag-target
(string-append source-key size-string ".html" "#" previous-strong-program-word "-@" mark-char)
mark-glyph
"program-frame")))
((>= (length link-targets) 1)
(let ((source-key (cdr (car link-targets))))
(display-warning (string-append "Linking from source marker in documentation: Multiple targets of " previous-strong-program-word))
(a-tag-target
(string-append source-key size-string ".html" "#" previous-strong-program-word "-@" mark-char)
mark-glyph
"program-frame"))))))
(define (section-navigation-banner doc-el)
(let* ((cur-nums (get-value 'raw-numbering doc-el))
(cur-sect (car cur-nums))
(cur-subsect (cadr cur-nums)))
(if (= 0 cur-subsect)
(let ((up (documentation-url "START"))
(prev (if (= 1 cur-sect)
#f
(doc-section-url (- cur-sect 1) 0)))
(next (doc-section-url (+ cur-sect 1) 0)))
(section-navigation-banner-1 doc-el up prev next))
(let ((up (doc-section-url cur-sect 0))
(prev (if (= 1 cur-subsect)
#f
(doc-section-url cur-sect (- cur-subsect 1))))
(next (doc-section-url cur-sect (+ cur-subsect 1))))
(section-navigation-banner-1 doc-el up prev next)))))
(define (section-navigation-banner-1 doc-el up prev next)
(letrec ((url-of (lambda (x) (cond ((pair? x) (car x))
((string? x) x)
(else (error "url-of: unknown type of parameter")))))
(title-of (lambda (x) (cond ((pair? x) (cdr x))
((string? x) "")
(else (error "title-of: unknown type of parameter"))))))
(con
(if up (a-tag (url-of up) (image "small-up.gif" (title-of up))) (image "small-up-blind.gif" "")) (horizontal-space 1)
(if prev (a-tag (url-of prev) (image "small-prev.gif" (title-of prev))) (image "small-prev-blind.gif" "")) (horizontal-space 1)
(if next (a-tag (url-of next) (image "small-next.gif" (title-of next))) (image "small-next-blind.gif" "")))))
(define (doc-section-url n m)
(let ((res (filter (section-subsection? n m) documentation-elements)))
(cond ((= 1 (length res))
(let* ((element (car res))
(id (get-value 'id element))
(ttl (get-value 'title element))
)
(cons (documentation-url id) ttl)))
((= 0 (length res)) #f)
((> (length res) 1)
(error (string-append "doc-subsection-url: multiple sections/entries cannot exists: "
(as-string n) "." (as-string m)))))))
(define (split-defined-applied-names dan-list)
(sublist-by-predicate
dan-list
(lambda (cur prev n)
(not (eqv? (string-ref (as-string (car cur)) 0)
(string-ref (as-string (car prev)) 0))))))
(define (first-letter-of x)
(as-string (string-ref (as-string x) 0)))
(define (make-cross-reference-index da-names letter alphabet)
(write-text-file
(page (string-append "Alphabetic cross reference index: letter " letter)
(con
(icon-bar)
(b (font 3 blue "Cross reference index: ")) (horizontal-space 2)
(alphabetic-link-array-1 "cross-reference-index" alphabet letter)
(present-cross-reference-index da-names) (p)
(alphabetic-link-array-1 "cross-reference-index" alphabet letter)
(vertical-space 8)
) (color-of-group "index") black black black
)
(html-destination (string-append "cross-reference-index" "-" (hygienic-file-character (downcase-string letter))))))
(define (make-overall-cross-reference-index alphabet)
(write-text-file
(page "Overall alphabetic cross reference index"
(con
(icon-bar)
(b (font 3 blue "Cross reference index: ")) (horizontal-space 2)
(alphabetic-link-array-1
"cross-reference-index"
(map downcase-string alphabet)) (br)
(font-size 2 (em "Navigate to subindexes via tha alphabet above"))
)
(color-of-group "index") black black black
)
(html-destination "cross-reference-index")))
(define (split-defining-name-occurences dno)
(sublist-by-predicate
dno
(lambda (cur prev n)
(not (eqv? (string-ref (as-string (car cur)) 0)
(string-ref (as-string (car prev)) 0))))))
(define (make-defining-name-index dno letter alphabet)
(write-text-file
(page (string-append "Defining name index: letter " letter)
(con
(icon-bar)
(b (font 3 blue "Index of definitions: ")) (horizontal-space 2)
(alphabetic-link-array-1 "defining-name-index" alphabet letter)
(present-defined-name-index dno)
) (color-of-group "index") black black black
)
(html-destination (string-append "defining-name-index" "-" (hygienic-file-character (downcase-string letter))))))
(define (make-overall-defining-name-index alphabet)
(write-text-file
(page "Overall defining name index"
(con
(icon-bar)
(b (font 3 blue "Index of definitions: ")) (horizontal-space 2)
(alphabetic-link-array-1
"defining-name-index"
(map downcase-string alphabet)) (br)
(font-size 2 (em "Navigate to subindexes via tha alphabet above"))
)
(color-of-group "index") black black black
)
(html-destination "defining-name-index")))
(define (make-color-scheme . group-color-plist)
(propertylist-to-alist group-color-plist))
(define (color-of-group group)
(if elucidator-color-scheme
(let ((group-color (assoc group elucidator-color-scheme)))
(if (pair? group-color)
(cdr group-color)
default-background-color))
default-background-color))
(define (laml-power-icon . optional-parameter-list)
(let ((extra-level (optional-parameter 1 optional-parameter-list 0))
(icon-size (as-symbol (optional-parameter 2 optional-parameter-list 'large)))
)
(a-tag-target "http://www.cs.auc.dk/~normark/laml/"
(html:img 'src (string-append
(cond ((eq? icon-size 'large) "images/laml-power-icon-1.gif")
((eq? icon-size 'small) "images/laml-mini-icon-1.gif")
(else (laml-error "laml-power-icon: third parameter must either be large or small"))))
'alt "Program Oriented Web Engineering - using LAML") "_top")))
(define (hygienic-file-character ch)
(let ((ch-n (as-number (as-char ch))))
(cond ((or (= ch-n 60) (= ch-n 62))
(string-append "c" (as-string ch-n)))
(else ch))))
(define (alphabetic-link-array-1 target-file-prefix alphabet . emphasis-letter)
(let* ((em-let (if (not (null? emphasis-letter)) (as-string (car emphasis-letter)) #f))
(alphabet-1 (map as-string alphabet)))
(apply string-append
(map
(lambda (letter)
(string-append
(a-tag (string-append target-file-prefix "-" (hygienic-file-character letter) ".html")
(if (and em-let (equal? em-let letter))
(font 4 red (b (capitalize-string-nd letter)))
(capitalize-string-nd letter))
(horizontal-space 1))
" "
))
alphabet-1))))