X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=ecmalisp.lisp;h=0801df4f45a88266e40c01ab26aa684da8b56243;hb=ad28d0c42e2a8b37c0213a37f5966f7198fe8b02;hp=a6a0948957f35094d1fcbcae801d9861d24bae7a;hpb=af915c33942c151a340a7209e22824f56a75461e;p=jscl.git diff --git a/ecmalisp.lisp b/ecmalisp.lisp index a6a0948..0801df4 100644 --- a/ecmalisp.lisp +++ b/ecmalisp.lisp @@ -23,7 +23,7 @@ ;;; language to the compiler to be able to run. #+ecmalisp -(js-eval "function id (x) { return x; }") +(js-eval "function pv (x) { return typeof x === 'object' && 'car' in x ? x.car : x; }") #+ecmalisp (progn @@ -281,7 +281,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 @@ -675,6 +675,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. @@ -1129,10 +1138,14 @@ "return func;" *newline*) (join strs))) + +(defvar *compiling-lambda-p* nil) + (define-compilation lambda (lambda-list &rest body) (let ((required-arguments (lambda-list-required-arguments lambda-list)) (optional-arguments (lambda-list-optional-arguments lambda-list)) (rest-argument (lambda-list-rest-argument lambda-list)) + (*compiling-lambda-p* t) documentation) ;; Get the documentation string for the lambda function (when (and (stringp (car body)) @@ -1148,24 +1161,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) @@ -1190,7 +1204,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 "};" @@ -1229,6 +1243,7 @@ (concat "(" var " = " (ls-compile val) ")")) + ;;; Literals (defun escape-string (string) (let ((output "") @@ -1538,7 +1553,6 @@ "})" *newline*) (error (concat "Unknown tag `" n "'."))))) - (define-compilation unwind-protect (form &rest clean-up) (js!selfcall "var ret = " (ls-compile nil) ";" *newline* @@ -1549,6 +1563,21 @@ "}" *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* + "function values(){" *newline* + (indent "var result = [];" *newline* + "for (var i=0; i