;; @module embed
;; @author Ralph Ronnquist, Real Thing Entertainment Pty. Ltd.
;; @location http://www.realthing.com.au/files/newlisp/embed.lsp
;; @version 1.0
;; @description Utility for embedding
;
;; This is a utility module for producing an embedded newlisp program,
;; including all loaded source. It instruments the "load" function to
;; use an embedded source if such exists, or else to capture the
;; external file for embedding. Embedding is a three-stage procedure:
;
;; <ul>
;
;; <li> Place a clause:
;;    <pre>(Embed:embed-save <main-file>)</pre>
;;    in the main program file at the point where the program is fully
;;    loaded, but before its main activity starts.</li>
;;
;; <li>Generate an embedding base by running newlisp with embed.lsp as
;;    its first module:
;;    <pre>% newlisp embed.lsp main-file.lsp</pre>
;;    This generates the file embed-main-file.lsp; i.e., the prefix
;;    "embed-" to the main file name given to <embed-save> above. Note
;;    that only files loaded via the <load> function are included in
;;    the embedding, and not those given on the command line.</li>
;;
;; <li>Run newlisp embedding with the embedding base:
;;    <pre>% newlisp -x embed-main-file.lsp program</pre></li>
;; </ul>
;; <hr>
;; @syntax (embed-save <main-file>)
;; @param <main-file> is the name of the main file to append.
;
;; When invoked for creating the embedding base, the <embed-save>
;; function writes this as an embeddable source file for the
;; application and exits.
;;
;; The embedding base constists of a preamble that is a snapshot of
;; the Embed context, which in particular includes the <embedded>
;; variable as set up with all loaded files, and its <initial>
;; variable set to false. This is followed by action clauses to
;; redirect the <load> function to <embed-load>, which uses the
;; embedded sources rather than loading external files. Finally the
;; given main file is appended.
;;
;; When invoked in the embedded appliation, <embed-save> just returns
;; without ado.
;
;; @syntax (embed-load <filename>)
;
;; The <embed-load> function replicates the standard load function,
;; but taking its input from pre-loaded files from the <embedded>
;; alist, if possible, and otherwise capturing those that are read in
;; into the <embedded> ailst.

(context 'Embed)

(when (null? embedded)
  (set 'embedded '())
  (set 'initial true)
  (define (embed-load filename)
    (let ((content (lookup filename embedded)))
      (when (null? content)
	(push (list filename (setf content (read-file filename))) embedded -1))
      (eval-string content MAIN)))

  (define (embed-save main-file)
    (when initial
      (set 'initial nil)
      (let ((filename (string "embed-" main-file)))
	(write-file filename (source 'Embed))
	(append-file filename [text]
(context MAIN)
(constant 'load Embed:embed-load)
;---- Main file
[/text] )
	(append-file filename (read-file main-file))
	(exit 0))))

  (context MAIN)
  (constant 'load Embed:embed-load)
) ; Matches (when (null? embedded)




syntax highlighting with newLISP and newLISPdoc