summaryrefslogtreecommitdiff
path: root/support
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2003-08-05 10:49:46 +0000
committerpaltherr <paltherr@epfl.ch>2003-08-05 10:49:46 +0000
commitb25aa75bcb9f49f06d1af7fb0b057debf19f3da5 (patch)
treed1653891e222205178e511c1174d2fe6b99c85c7 /support
parentbb672e7f07f05d03ee0a7b0da69c6cf763a542b9 (diff)
downloadscala-b25aa75bcb9f49f06d1af7fb0b057debf19f3da5.tar.gz
scala-b25aa75bcb9f49f06d1af7fb0b057debf19f3da5.tar.bz2
scala-b25aa75bcb9f49f06d1af7fb0b057debf19f3da5.zip
- Added scalatex.scm
Diffstat (limited to 'support')
-rwxr-xr-xsupport/latex/scalatex.scm214
1 files changed, 214 insertions, 0 deletions
diff --git a/support/latex/scalatex.scm b/support/latex/scalatex.scm
new file mode 100755
index 0000000000..762b70a18c
--- /dev/null
+++ b/support/latex/scalatex.scm
@@ -0,0 +1,214 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Embedded Scala Script Evaluator
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; $Id$
+
+;; Commands:
+;; \begin{scalaprogram}{<name>} ... \end{scalaprogram}
+;; begin a complete Scala program with given name
+;; \beginscalaprogram{<name>} ... \endscalaprogram
+;; begin a Scala program with given name, which can be omitted in
+;; which case the program is anonymous
+;; \scalaprogramoutput{<name>}
+;; insert the output of the given program, which must be ended
+;; \begin{scalacode} ... \end{scalacode}
+;; begin a section of Scala code which is added to the current
+;; program, and printed in the final result
+;; \begin{scalainvisiblecode} ... \end{scalainvisiblecode}
+;; like \begin{scalacode}, but the code doesn't get printed
+
+;; TODO
+;; - add interaction with siris using commands like:
+;; \beginscalainteraction, \endscalainteraction, visible/invisible code,
+;; visible code whose result is not visible
+
+;; Diagnostics
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define verbose? #t)
+
+(define (message str . args)
+ (when verbose?
+ (apply format (error-output-port) str args)
+ (newline (error-output-port))))
+
+(define (fail line-num msg . args)
+ (format #t "~a:~a: ~a" "<in-file>" line-num (apply format #f msg args)))
+
+;; Syntax
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-syntax when
+ (syntax-rules ()
+ ((when cond body1 body2 ...)
+ (if cond (begin body1 body2 ...)))))
+
+(define-syntax unless
+ (syntax-rules ()
+ ((unless cond body1 body2 ...)
+ (if (not cond) (begin body1 body2 ...)))))
+
+;; Temporary directories / files
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; AList associating temporary directories with program names.
+(define temp-dirs '())
+
+(define (get-temp-dir prog-name)
+ (cond ((assoc prog-name temp-dirs) => cdr)
+ (else
+ (let ((dir (temp-file-iterate (lambda (dir) (create-directory dir) dir)
+ "/tmp/temp-~a")))
+ (set! temp-dirs (alist-cons prog-name dir temp-dirs))
+ dir))))
+
+(define (clean-temp-dirs)
+ (for-each (lambda (file/dir)
+ (let ((dir (cdr file/dir)))
+ (message "Cleaning up temporary class directory (~a)" dir)
+ (run (rm -rf ,dir))))
+ temp-dirs))
+
+(define (scala-file-name prog-name)
+ (expand-file-name (replace-extension prog-name ".scala")
+ (get-temp-dir prog-name)))
+
+(define (open-scala-program name)
+ (open-output-file (scala-file-name name)))
+
+(define (close-scala-program name port)
+ (compile-scala-program name)
+ (close-output-port port))
+
+;; Compiling and running Scala programs
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (compile-scala-program prog-name)
+ (let ((file-name (scala-file-name prog-name))
+ (classes-dir (get-temp-dir prog-name)))
+ (message "Compiling file ~a to directory ~a" file-name classes-dir)
+ (run (socos -d ,classes-dir ,file-name))))
+
+(define (append-scala-program-output prog-name out-port)
+ (let ((classes-dir (get-temp-dir prog-name)))
+ (message "Running program ~a" prog-name)
+ (with-env (("CLASSPATH" . ,(string-append classes-dir ":" (getenv "CLASSPATH"))))
+ (write-string (run/string (java ,prog-name)) out-port))))
+
+
+;; Main iteration
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (begin-scala-code port)
+ (format port "\\begin{verbatim}\n"))
+(define (end-scala-code port)
+ (format port "\\end{verbatim}\n"))
+
+(define (scala-rx contents)
+ (rx bos (* space) ,@contents (* space)))
+
+(define (scala-begin-rx env-name)
+ (scala-rx (string-append "\\begin{" env-name "}")))
+(define (scala-end-rx env-name)
+ (scala-rx (string-append "\\end{" env-name "}")))
+
+(define scalatex
+ (let ((prog-name-rx (rx (* (| alphanum ("_"))))))
+ (lambda (in-port out-port)
+ (awk (read-line in-port) (line) line-num ((prog-name #f)
+ (prog-port #f)
+ (expr #f)
+ (in-fragment? #f)
+ (copy? #t))
+ ;; Program.
+ ((regexp-search (scala-rx (rx "\\beginscalaprogram"
+ "{" (submatch ,prog-name-rx) "}"))
+ line)
+ => (lambda (match)
+ (let ((prog-name (or (match:substring match 1) "anonymous")))
+ (values prog-name
+ (open-scala-program prog-name)
+ #f
+ #f
+ copy?))))
+
+ ((regexp-search (scala-rx "\\endscalaprogram") line)
+ (close-scala-program prog-name prog-port)
+ (values #f #f #f #f copy?))
+
+ ((regexp-search (scala-rx (rx "\\begin{scalaprogram}"
+ "{" (submatch ,prog-name-rx) "}"))
+ line)
+ => (lambda (match)
+ (begin-scala-code out-port)
+ (let ((prog-name (or (match:substring match 1) "anonymous")))
+ (values prog-name
+ (open-scala-program prog-name)
+ #f
+ #t
+ #t))))
+
+ ((regexp-search (scala-end-rx "scalaprogram") line)
+ (end-scala-code out-port)
+ (close-scala-program prog-name prog-port)
+ (values #f #f #f #f copy?))
+
+ ;; Insertion of program output.
+ ((regexp-search (scala-rx (rx "\\scalaprogramoutput"
+ "{" (submatch ,prog-name-rx) "}"))
+ line)
+ => (lambda (match)
+ (let ((prog-name (match:substring match 1)))
+ (begin-scala-code out-port)
+ (append-scala-program-output prog-name out-port)
+ (end-scala-code out-port))
+ (values prog-name prog-port #f in-fragment? copy?)))
+
+ ;; Visible code fragment.
+ ((regexp-search (scala-begin-rx "scalacode") line)
+ (begin-scala-code out-port)
+ (values prog-name prog-port #f #t #t))
+
+ ((regexp-search (scala-end-rx "scalacode") line)
+ (end-scala-code out-port)
+ (values prog-name prog-port #f #f #t))
+
+ ;; Invisible code fragment.
+ ((regexp-search (scala-begin-rx "scalainvisiblecode") line)
+ (values prog-name prog-port #f #t #f))
+
+ ((regexp-search (scala-end-rx "scalainvisiblecode") line)
+ (values prog-name prog-port #f #f #t))
+
+ (else
+ (when in-fragment?
+ (write-string line prog-port)
+ (newline prog-port))
+ (when copy?
+ (write-string line out-port)
+ (newline out-port))
+ (values prog-name
+ prog-port
+ (and expr (string-append expr line))
+ in-fragment?
+ copy?))))))
+
+(define (display-usage-and-exit prog)
+ (format #t "Usage: ~a <in-file> <out-file>\n" prog))
+
+(define (main cmd-line)
+ (let ((prog (car cmd-line))
+ (args (cdr cmd-line)))
+ (if (= 2 (length args))
+ (call-with-input-file (first args)
+ (lambda (in-port)
+ (call-with-output-file (second args)
+ (lambda (out-port)
+ (format out-port "%% DO NOT EDIT - AUTOMATICALLY GENERATED FILE\n")
+ (format out-port "%% Generated from \"~a\" on ~a by ~a\n\n"
+ (first args)
+ (format-date "~Y-~m-~d [~H:~M]" (date))
+ (user-login-name))
+ (scalatex in-port out-port)
+ (clean-temp-dirs)))))
+ (display-usage-and-exit prog))))