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

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

Fixed compilation with temp files with JSR-223. Refactoring of AbclScriptEngine?
(mostly elimination of dead code). Changed policy of use of #'sys::%debugger-hook-function
in an attempt to have the throwing debugger cover more cases; it still doesn't
work always.

  • Property svn:eol-style set to LF
File size: 5.7 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 eval-in-script-context ((global-bindings engine-bindings stdin stdout script-context)
61          body)
62  "Sets up an environment in which to evaluate a piece of code coming from Java through the JSR-223 methods."
63  (let ((actual-global-bindings (gensym))
64  (actual-engine-bindings (gensym)))
65    `(let ((*package* (find-package :abcl-script-user))
66     (*standard-input* ,stdin)
67     (*standard-output* ,stdout)
68     (*debugger-hook* (if *use-throwing-debugger*
69        #'sys::%debugger-hook-function
70        *debugger-hook*))
71     (,actual-global-bindings (generate-bindings ,global-bindings))
72     (,actual-engine-bindings (generate-bindings ,engine-bindings)))
73       (eval `(let (,@,actual-global-bindings)
74    (let (,@,actual-engine-bindings)
75      (prog1
76          (progn ,@,body)
77        (finish-output *standard-output*)
78        ,@(generate-java-bindings
79           ,global-bindings 
80           ,actual-global-bindings
81           (jcall +get-bindings+ ,script-context +global-scope+))
82        ,@(generate-java-bindings
83           ,engine-bindings 
84           ,actual-engine-bindings
85           (jcall +get-bindings+ ,script-context +engine-scope+)))))))))
86 
87(defun eval-script (global-bindings engine-bindings stdin stdout
88        code-string script-context)
89  (eval-in-script-context (global-bindings engine-bindings stdin stdout script-context)
90    (read-from-string
91     (concatenate 'string "(" code-string ")"))))
92
93(defun eval-compiled-script (global-bindings engine-bindings stdin stdout
94           function script-context)
95  (eval-in-script-context (global-bindings engine-bindings stdin stdout script-context)
96    `((funcall ,function))))
97
98(defun compile-script (code-string)
99  (if *compile-using-temp-files*
100      (let* ((tmp-file (jstatic (jmethod "java.io.File" "createTempFile" "java.lang.String" "java.lang.String")
101        nil "abcl-src-file-" ".lisp"))
102       (tmp-file-path (jcall (jmethod "java.io.File" "getAbsolutePath") tmp-file)))
103  (jcall (jmethod "java.io.File" "deleteOnExit") tmp-file) ;to be really-really-really sure...
104  (unwind-protect
105       (progn
106         (with-open-file (stream tmp-file-path :direction :output)
107     (princ "(in-package :abcl-script-user)" stream)
108     (princ code-string stream)
109     (finish-output stream))
110         (let ((compiled-file (compile-file tmp-file-path)))
111     (jcall (jmethod "java.io.File" "deleteOnExit")
112      (jnew (jconstructor "java.io.File" "java.lang.String")
113            (namestring compiled-file)))
114     (lambda ()
115       (let ((*package* (find-package :abcl-script-user)))
116         (load compiled-file :verbose t :print t)))))
117    (delete-file tmp-file-path)))
118      (eval 
119       `(compile
120   nil
121   (lambda ()
122     ,@(let ((*package* (find-package :abcl-script-user)))
123         (read-from-string
124    (concatenate 'string "(" code-string " cl:t)")))))))) ;return T in conformity of what LOAD does.
125
126;;Java interface implementation - TODO
127
128(defvar *interface-implementation-map* (make-hash-table :test #'equal))
129
130(defun find-java-interface-implementation (interface)
131  (gethash interface *interface-implementation-map*))
132
133(defun register-java-interface-implementation (interface implementation &optional lisp-this)
134  (setf (gethash interface *interface-implementation-map*)
135  (jmake-proxy interface implementation lisp-this)))
136
137(defun remove-java-interface-implementation (interface)
138  (remhash interface *interface-implementation-map*))
139
140;Let's load it so asdf package is already defined when loading config.lisp
141(require 'asdf)
Note: See TracBrowser for help on using the repository browser.