X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=ecmalisp.lisp;h=0d091a66a5b354e1bd53033c938239bd238c0147;hb=4951c2dad634560b91b4d0bf3b6545dd02bfa887;hp=abef67980b839048a82342fcb1983b96245307ae;hpb=2074402385524f4d1b1b6250fe7d2b092eb21612;p=jscl.git diff --git a/ecmalisp.lisp b/ecmalisp.lisp index abef679..0d091a6 100644 --- a/ecmalisp.lisp +++ b/ecmalisp.lisp @@ -23,6 +23,11 @@ ;;; language to the compiler to be able to run. #+ecmalisp +(js-eval "function pv (x) { return x; }") +#+ecmalisp +(js-eval "var values = pv;") + +#+ecmalisp (progn (eval-when-compile (%compile-defmacro 'defmacro @@ -278,7 +283,7 @@ (revappend list '())) (defmacro psetq (&rest pairs) - (let (;; For each pair, we store here a list of the form + (let ( ;; For each pair, we store here a list of the form ;; (VARIABLE GENSYM VALUE). (assignments '())) (while t @@ -672,6 +677,15 @@ (aset v i x) (incf i)))) +#+ecmalisp +(progn + (defun values-list (list) + (values-array (list-to-vector list))) + + (defun values (&rest args) + (values-list args))) + + ;;; Like CONCAT, but prefix each line with four spaces. Two versions ;;; of this function are available, because the Ecmalisp version is ;;; very slow and bootstraping was annoying. @@ -970,6 +984,8 @@ ;;; too. The respective real functions are defined in the target (see ;;; the beginning of this file) as well as some primitive functions. +(defvar *multiple-value-p* nil) + (defvar *compilation-unit-checks* '()) (defun make-binding (name type value &optional declarations) @@ -1091,8 +1107,8 @@ (define-compilation if (condition true false) (concat "(" (ls-compile condition) " !== " (ls-compile nil) - " ? " (ls-compile true) - " : " (ls-compile false) + " ? " (ls-compile true *multiple-value-p*) + " : " (ls-compile false *multiple-value-p*) ")")) (defvar *lambda-list-keywords* '(&optional &rest)) @@ -1126,6 +1142,7 @@ "return func;" *newline*) (join strs))) + (define-compilation lambda (lambda-list &rest body) (let ((required-arguments (lambda-list-required-arguments lambda-list)) (optional-arguments (lambda-list-optional-arguments lambda-list)) @@ -1145,24 +1162,25 @@ (lambda-docstring-wrapper documentation "(function (" - (join (mapcar #'translate-variable - (append required-arguments optional-arguments)) + (join (cons "values" + (mapcar #'translate-variable + (append required-arguments optional-arguments))) ",") "){" *newline* ;; Check number of arguments (indent (if required-arguments - (concat "if (arguments.length < " (integer-to-string n-required-arguments) + (concat "if (arguments.length < " (integer-to-string (1+ n-required-arguments)) ") throw 'too few arguments';" *newline*) "") (if (not rest-argument) (concat "if (arguments.length > " - (integer-to-string (+ n-required-arguments n-optional-arguments)) + (integer-to-string (+ 1 n-required-arguments n-optional-arguments)) ") throw 'too many arguments';" *newline*) "") ;; Optional arguments (if optional-arguments - (concat "switch(arguments.length){" *newline* + (concat "switch(arguments.length-1){" *newline* (let ((optional-and-defaults (lambda-list-optional-arguments-with-default lambda-list)) (cases nil) @@ -1187,7 +1205,7 @@ (let ((js!rest (translate-variable rest-argument))) (concat "var " js!rest "= " (ls-compile nil) ";" *newline* "for (var i = arguments.length-1; i>=" - (integer-to-string (+ n-required-arguments n-optional-arguments)) + (integer-to-string (+ 1 n-required-arguments n-optional-arguments)) "; i--)" *newline* (indent js!rest " = " "{car: arguments[i], cdr: ") js!rest "};" @@ -1226,6 +1244,7 @@ (concat "(" var " = " (ls-compile val) ")")) + ;;; Literals (defun escape-string (string) (let ((output "") @@ -1535,7 +1554,6 @@ "})" *newline*) (error (concat "Unknown tag `" n "'."))))) - (define-compilation unwind-protect (form &rest clean-up) (js!selfcall "var ret = " (ls-compile nil) ";" *newline* @@ -1546,6 +1564,28 @@ "}" *newline* "return ret;" *newline*)) +(define-compilation multiple-value-call (func-form &rest forms) + (let ((func (ls-compile func-form))) + (js!selfcall + "var args = [values];" *newline* + "values = function(){" *newline* + (indent "var result = [];" *newline* + "result['multiple-value'] = true;" *newline* + "for (var i=0; i