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

Last change on this file was 12020, checked in by astalla, 15 years ago

Corrected the installation and use of the throwing debugger (sys:%debugger-hook-function).

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