(SETF OGET) AND (SETF OGET*)
[jscl.git] / src / ffi.lisp
1 ;;; ffi.lisp ---
2
3 ;; JSCL is free software: you can redistribute it and/or
4 ;; modify it under the terms of the GNU General Public License as
5 ;; published by the Free Software Foundation, either version 3 of the
6 ;; License, or (at your option) any later version.
7 ;;
8 ;; JSCL is distributed in the hope that it will be useful, but
9 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
10 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 ;; General Public License for more details.
12 ;;
13 ;; You should have received a copy of the GNU General Public License
14 ;; along with JSCL.  If not, see <http://www.gnu.org/licenses/>.
15
16 (defvar *js-package*
17   (make-package "JS"))
18
19 (defun ffi-intern-hook (symbol)
20   (when (eq (symbol-package symbol) *js-package*)
21     (let ((sym-name (symbol-name symbol))
22           (args (gensym)))
23       ;; Generate a trampoline to call the JS function
24       ;; properly. This trampoline is very inefficient,
25       ;; but it still works. Ideas to optimize this are
26       ;; provide a special lambda keyword
27       ;; cl::&rest-vector to avoid list argument
28       ;; consing, as well as allow inline declarations.
29       (fset symbol (eval `(%js-vref ,sym-name)))
30       ;; Define it as a symbol macro to access to the
31       ;; Javascript variable literally.
32       (%define-symbol-macro symbol `(%js-vref ,(string symbol))))))
33
34 (setq *intern-hook* #'ffi-intern-hook)
35
36 (defvar *root* (%js-vref "window"))
37
38 (define-setf-expander oget (object key &rest keys)
39   (let* ((keys (cons key keys))
40          (g!object (gensym))
41          (g!keys (mapcar (lambda (s)
42                            (declare (ignore s))
43                            (gensym))
44                          keys))
45          (g!value (gensym)))
46     (values `(,g!object ,@g!keys)
47             `(,object ,@keys)
48             `(,g!value)
49             `(oset ,g!value ,g!object ,@g!keys)
50             `(oget ,g!object ,@g!keys))))
51
52 (define-setf-expander oget* (object key &rest keys)
53   (let* ((keys (cons key keys))
54          (g!object (gensym))
55          (g!keys (mapcar (lambda (s)
56                            (declare (ignore s))
57                            (gensym))
58                          keys))
59          (g!value (gensym)))
60     (values `(,g!object ,@g!keys)
61             `(,object ,@keys)
62             `(,g!value)
63             `(oset* ,g!value ,g!object ,@g!keys)
64             `(oget* ,g!object ,@g!keys))))
65
66
67