From: David Vázquez Date: Sat, 4 May 2013 01:38:13 +0000 (+0100) Subject: String and function FFI conversion X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=84e86dfe99d64c1cb0bec680c9154dd9b2d34ca6;p=jscl.git String and function FFI conversion --- diff --git a/src/compiler.lisp b/src/compiler.lisp index 4379565..7171140 100644 --- a/src/compiler.lisp +++ b/src/compiler.lisp @@ -1505,6 +1505,9 @@ (define-builtin string-upcase (x) (code "make_lisp_string(xstring(" x ").toUpperCase())")) +(define-builtin %lisp-to-js (x) (code "lisp_to_js(" x ")")) +(define-builtin %js-to-lisp (x) (code "js_to_lisp(" x ")")) + (define-builtin string-length (x) (code x ".length")) diff --git a/src/ffi.lisp b/src/ffi.lisp index 7d902a7..73d95a0 100644 --- a/src/ffi.lisp +++ b/src/ffi.lisp @@ -16,6 +16,9 @@ (defvar *js-package* (make-package "JS")) +(defun lisp-to-js (x) (%lisp-to-js x)) +(defun js-to-list (x) (%js-to-lisp x)) + (defun ffi-intern-hook (symbol) (when (eq (symbol-package symbol) *js-package*) (let ((sym-name (symbol-name symbol)) @@ -28,8 +31,8 @@ ;; consing, as well as allow inline declarations. (fset symbol (eval `(lambda (&rest ,args) - (let ((,args (list-to-vector ,args))) - (%js-call (%js-vref ,sym-name) ,args))))) + (let ((,args (list-to-vector (mapcar #'lisp-to-js ,args)))) + (js-to-list (%js-call (%js-vref ,sym-name) ,args)))))) ;; Define it as a symbol macro to access to the ;; Javascript variable literally. (%define-symbol-macro symbol `(%js-vref ,(string symbol)))))) diff --git a/src/prelude.js b/src/prelude.js index ca5cfdb..601781f 100644 --- a/src/prelude.js +++ b/src/prelude.js @@ -61,3 +61,26 @@ function make_lisp_string (string){ function xstring(x){ return x.join(''); } + +function lisp_to_js (x) { + if (typeof x == 'object' && 'length' in x && x.type == 'character') + return xstring(x); + else if (typeof x == 'function'){ + // Trampoline calling the Lisp function + return (function(){ + return x.apply(this, [pv, arguments.length] + Array.prototype.slice.call(arguments)); + }) + } + else return x; +} + +function js_to_lisp (x) { + if (typeof x == 'string') + return make_lisp_string(x); + else if (typeof x == 'function'){ + // Trampoline calling the JS function + return (function(values, nargs){ + return x.apply(this, Array.prototype.slice.call(arguments, 2)); + }) + } else return x; +}