summaryrefslogtreecommitdiff
path: root/src/guile/skribilo/evaluator.scm
diff options
context:
space:
mode:
Diffstat (limited to 'src/guile/skribilo/evaluator.scm')
-rw-r--r--src/guile/skribilo/evaluator.scm203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/guile/skribilo/evaluator.scm b/src/guile/skribilo/evaluator.scm
new file mode 100644
index 0000000..8502d51
--- /dev/null
+++ b/src/guile/skribilo/evaluator.scm
@@ -0,0 +1,203 @@
+;;; eval.scm -- Skribilo evaluator.
+;;;
+;;; Copyright 2003-2004 Erick Gallesio - I3S-CNRS/ESSI <eg@essi.fr>
+;;; Copyright 2005,2006 Ludovic Courtès <ludovic.courtes@laas.fr>
+;;;
+;;;
+;;; This program is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2 of the License, or
+;;; (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+;;; USA.
+
+
+(define-module (skribilo evaluator)
+ :export (evaluate-document evaluate-document-from-port
+ load-document include-document *load-options*)
+ :autoload (skribilo parameters) (*verbose* *document-path*)
+ :autoload (skribilo location) (<location>)
+ :autoload (skribilo ast) (ast? markup?)
+ :autoload (skribilo engine) (*current-engine*
+ engine? find-engine engine-ident)
+ :autoload (skribilo reader) (*document-reader*)
+
+ :autoload (skribilo verify) (verify)
+ :autoload (skribilo resolve) (resolve!)
+
+ :autoload (skribilo module) (*skribilo-user-module*))
+
+
+(use-modules (skribilo utils syntax)
+ (skribilo condition)
+ (skribilo debug)
+ (skribilo output)
+ (skribilo lib)
+
+ (ice-9 optargs)
+ (oop goops)
+ (srfi srfi-1)
+ (srfi srfi-13)
+ (srfi srfi-34)
+ (srfi srfi-35)
+ (srfi srfi-39))
+
+
+(fluid-set! current-reader %skribilo-module-reader)
+
+
+;;;
+;;; %EVALUATE
+;;;
+(define (%evaluate expr)
+ ;; Evaluate EXPR, an arbitrary S-expression that may contain calls to the
+ ;; markup functions defined in a markup package such as
+ ;; `(skribilo package base)', e.g., `(bold "hello")'.
+ (let ((result (eval expr (*skribilo-user-module*))))
+
+ (if (ast? result)
+ (let ((file (source-property expr 'filename))
+ (line (source-property expr 'line))
+ (column (source-property expr 'column)))
+ (slot-set! result 'loc
+ (make <location>
+ :file file :line line :pos column))))
+
+ result))
+
+
+
+;;;
+;;; EVALUATE-DOCUMENT
+;;;
+(define* (evaluate-document a e :key (env '()))
+ ;; Argument A must denote an AST of something like that, not just an
+ ;; S-exp.
+ (with-debug 2 'evaluate-document
+ (debug-item "a=" a " e=" (engine-ident e))
+ (let ((a2 (resolve! a e env)))
+ (debug-item "resolved a=" a)
+ (let ((a3 (verify a2 e)))
+ (debug-item "verified a=" a3)
+ (output a3 e)))))
+
+;;;
+;;; EVALUATE-DOCUMENT-FROM-PORT
+;;;
+(define* (evaluate-document-from-port port engine
+ :key (env '())
+ (reader (*document-reader*)))
+ (with-debug 2 'evaluate-document-from-port
+ (debug-item "engine=" engine)
+ (debug-item "reader=" reader)
+
+ (let ((e (if (symbol? engine) (find-engine engine) engine)))
+ (debug-item "e=" e)
+ (if (not (engine? e))
+ (skribe-error 'evaluate-document-from-port "cannot find engine" engine)
+ (let loop ((exp (reader port)))
+ (with-debug 10 'evaluate-document-from-port
+ (debug-item "exp=" exp))
+ (unless (eof-object? exp)
+ (evaluate-document (%evaluate exp) e :env env)
+ (loop (reader port))))))))
+
+
+;;;
+;;; LOAD-DOCUMENT
+;;;
+
+;; Options that may make sense to a specific back-end or package.
+(define-public *load-options* (make-parameter '()))
+
+;; List of the names of files already loaded.
+(define *loaded-files* (make-parameter '()))
+
+(define* (load-document file :key (engine #f) (path #f) :allow-other-keys
+ :rest opt)
+ (with-debug 4 'skribe-load
+ (debug-item " engine=" engine)
+ (debug-item " path=" path)
+ (debug-item " opt=" opt)
+
+ (let* ((ei (*current-engine*))
+ (path (append (cond
+ ((not path) (*document-path*))
+ ((string? path) (list path))
+ ((not (and (list? path) (every? string? path)))
+ (raise (condition (&invalid-argument-error
+ (proc-name 'load-document)
+ (argument path)))))
+ (else path))
+ %load-path))
+ (filep (or (search-path path file)
+ (search-path (append path %load-path) file)
+ (search-path (append path %load-path)
+ (let ((dot (string-rindex file #\.)))
+ (if dot
+ (string-append
+ (string-take file dot)
+ ".scm")
+ file))))))
+
+ (unless (and (string? filep) (file-exists? filep))
+ (raise (condition (&file-search-error
+ (file-name file)
+ (path path)))))
+
+ ;; Pass the additional options to the back-end and/or packages being
+ ;; used.
+ (parameterize ((*load-options* opt))
+
+ ;; Load this file if not already done
+ ;; FIXME: Shouldn't we remove this logic? -- Ludo'.
+ (unless (member filep (*loaded-files*))
+ (cond
+ ((> (*verbose*) 1)
+ (format (current-error-port) " [loading file: ~S ~S]\n" filep opt))
+ ((> (*verbose*) 0)
+ (format (current-error-port) " [loading file: ~S]\n" filep)))
+
+ ;; Load it
+ (with-input-from-file filep
+ (lambda ()
+ (evaluate-document-from-port (current-input-port) ei)))
+
+ (*loaded-files* (cons filep (*loaded-files*))))))))
+
+;;;
+;;; INCLUDE-DOCUMENT
+;;;
+(define* (include-document file :key (path (*document-path*))
+ (reader (*document-reader*)))
+ (unless (every string? path)
+ (raise (condition (&invalid-argument-error (proc-name 'include-document)
+ (argument path)))))
+
+ (let ((full-path (search-path path file)))
+ (unless (and (string? full-path) (file-exists? full-path))
+ (raise (condition (&file-search-error
+ (file-name file)
+ (path path)))))
+
+ (when (> (*verbose*) 0)
+ (format (current-error-port) " [including file: ~S]\n" full-path))
+
+ (with-input-from-file full-path
+ (lambda ()
+ (let Loop ((exp (reader (current-input-port)))
+ (res '()))
+ (if (eof-object? exp)
+ (if (and (pair? res) (null? (cdr res)))
+ (car res)
+ (reverse! res))
+ (Loop (reader (current-input-port))
+ (cons (%evaluate exp) res))))))))