source: trunk/abcl/src/org/armedbear/lisp/scripting/lisp/abcl-script.lisp @ 11623

Last change on this file since 11623 was 11623, checked in by astalla, 14 years ago

Perfectioned ABCL auto-configuration when using JSR-223; added option to
compile scripts using temp files (default) or using the run-time
compiler; added example of usage of ABCL with JSR-223.

  • Property svn:eol-style set to LF
File size: 5.6 KB
Line 
1;;; abcl-script.lisp
2;;;
3;;; Copyright (C) 2008 Alessio Stalla
4;;;
5;;; This program is free software; you can redistribute it and/or
6;;; modify it under the terms of the GNU General Public License
7;;; as published by the Free Software Foundation; either version 2
8;;; of the License, or (at your option) any later version.
9;;;
10;;; This program is distributed in the hope that it will be useful,
11;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13;;; GNU General Public License for more details.
14;;;
15;;; You should have received a copy of the GNU General Public License
16;;; along with this program; if not, write to the Free Software
17;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18;;;
19;;; As a special exception, the copyright holders of this library give you
20;;; permission to link this library with independent modules to produce an
21;;; executable, regardless of the license terms of these independent
22;;; modules, and to copy and distribute the resulting executable under
23;;; terms of your choice, provided that you also meet, for each linked
24;;; independent module, the terms and conditions of the license of that
25;;; module.  An independent module is a module which is not derived from
26;;; or based on this library.  If you modify this library, you may extend
27;;; this exception to your version of the library, but you are not
28;;; obligated to do so.  If you do not wish to do so, delete this
29;;; exception statement from your version.
30
31(in-package :abcl-script)
32
33(defconstant +global-scope+
34  (jfield "javax.script.ScriptContext" "GLOBAL_SCOPE"))
35
36(defconstant +engine-scope+
37  (jfield "javax.script.ScriptContext" "ENGINE_SCOPE"))
38
39(defconstant +put-binding+ (jmethod "javax.script.Bindings"
40            "put"
41            "java.lang.String"
42            "java.lang.Object"))
43
44(defconstant +get-bindings+ (jmethod "javax.script.ScriptContext"
45             "getBindings"
46             "int"))
47
48(defun generate-bindings (bindings)
49  (let ((*package* (find-package :abcl-script-user)))
50    (mapcar (lambda (binding) (list (read-from-string (car binding))
51            (cdr binding)))
52      bindings)))
53
54(defun generate-java-bindings (bindings-list actual-bindings java-bindings)
55  (loop :for binding  :in actual-bindings
56  :for jbinding :in bindings-list
57  :collect `(jcall +put-binding+
58       ,java-bindings ,(car jbinding) ,(car binding))))
59
60(defmacro with-script-context ((global-bindings engine-bindings stdin stdout script-context)
61             body)
62  (let ((actual-global-bindings (gensym))
63  (actual-engine-bindings (gensym)))
64    `(let ((*package* (find-package :abcl-script-user))
65     (*standard-input* ,stdin)
66     (*standard-output* ,stdout)
67     (,actual-global-bindings (generate-bindings ,global-bindings))
68     (,actual-engine-bindings (generate-bindings ,engine-bindings)))
69      (eval `(let ((*standard-input* ,,stdin)
70       (*standard-output* ,,stdout)
71       (*package* (find-package :abcl-script-user)))
72        (let (,@,actual-global-bindings)
73    (let (,@,actual-engine-bindings)
74      (prog1
75          (progn ,@,body)
76        (finish-output *standard-output*)
77        ,@(generate-java-bindings
78           ,global-bindings 
79           ,actual-global-bindings
80           (jcall +get-bindings+ ,script-context +global-scope+))
81        ,@(generate-java-bindings
82           ,engine-bindings 
83           ,actual-engine-bindings
84           (jcall +get-bindings+ ,script-context +engine-scope+))))))))))
85 
86(defun eval-script (global-bindings engine-bindings stdin stdout
87        code-string script-context)
88  (with-script-context (global-bindings engine-bindings stdin stdout script-context)
89    (read-from-string
90     (concatenate 'string "(" code-string ")"))))
91
92(defun eval-compiled-script (global-bindings engine-bindings stdin stdout
93           function script-context)
94  (with-script-context (global-bindings engine-bindings stdin stdout script-context)
95    `((funcall ,function))))
96
97(defun compile-script (code-string)
98  (if *compile-using-temp-files*
99      (let* ((tmp-file (jstatic (jmethod "java.io.File" "createTempFile" "java.lang.String" "java.lang.String")
100        nil "abcl-src-file-" ".lisp"))
101       (tmp-file-path (jcall (jmethod "java.io.File" "getAbsolutePath") tmp-file)))
102  (jcall (jmethod "java.io.File" "deleteOnExit") tmp-file) ;to be really-really-really sure...
103  (unwind-protect
104       (progn
105         (with-open-file (stream tmp-file-path :direction :output :if-exists :overwrite)
106     (prin1 code-string stream)
107     (finish-output stream))
108         (let ((compiled-file (compile-file tmp-file-path)))
109     (jcall (jmethod "java.io.File" "deleteOnExit")
110      (jnew (jconstructor "java.io.File" "java.lang.String")
111            (namestring compiled-file)))
112     (lambda () (load compiled-file))))
113    (delete-file tmp-file-path)))
114      (eval 
115       `(compile
116   nil
117   (lambda ()
118     ,@(let ((*package* (find-package :abcl-script-user)))
119      (read-from-string (concatenate 'string "(" code-string ")"))))))))
120
121;;Java interface implementation
122
123(defvar *interface-implementation-map* (make-hash-table :test #'equal))
124
125(defun find-java-interface-implementation (interface)
126  (gethash interface *interface-implementation-map*))
127
128(defun register-java-interface-implementation (interface impl)
129  (setf (gethash interface *interface-implementation-map*) impl))
130
131(defun remove-java-interface-implementation (interface)
132  (remhash interface *interface-implementation-map*))
133
134(defun define-java-interface-implementation (interface implementation &optional lisp-this)
135  (register-java-interface-implementation
136   interface
137   (jmake-proxy interface implementation lisp-this)))
138
139;Let's load it so asdf package is already defined when loading config.lisp
140(require 'asdf)
Note: See TracBrowser for help on using the repository browser.