Pass argument count explicitly instead of use arguments.length
authorDavid Vázquez <davazp@gmail.com>
Wed, 1 May 2013 17:46:48 +0000 (18:46 +0100)
committerDavid Vázquez <davazp@gmail.com>
Wed, 1 May 2013 17:46:48 +0000 (18:46 +0100)
jscl.html
src/compiler.lisp
src/prelude.js

index 656af67..3cd1330 100644 (file)
--- a/jscl.html
+++ b/jscl.html
 
         var startPrompt = function () {
           // Start the prompt with history enabled.
-          jqconsole.Write(lisp.evalString(pv, '(CL:PACKAGE-NAME CL:*PACKAGE*)') + '> ', 'jqconsole-prompt');
+          jqconsole.Write(lisp.evalString(pv, 1, '(CL:PACKAGE-NAME CL:*PACKAGE*)') + '> ', 'jqconsole-prompt');
           jqconsole.Prompt(true, function (input) {
             // Output input with the class jqconsole-return.
             if (input[0] != ','){
                 try {
-                    var vs = lisp.evalInput(mv, input);
+                    var vs = lisp.evalInput(mv, 1, input);
                     for (var i=0; i<vs.length; i++){
-                       jqconsole.Write(lisp.print(pv, vs[i]) + '\n', 'jqconsole-return');
+                       jqconsole.Write(lisp.print(pv, 1, vs[i]) + '\n', 'jqconsole-return');
                     }
                 } catch(error) {
                     jqconsole.Write('ERROR: ' + (error.message || error) + '\n', 'jqconsole-error');
                 }
             } else {
-                jqconsole.Write(lisp.compileString(pv, input.slice(1)) + '\n', 'jqconsole-return');
+                jqconsole.Write(lisp.compileString(pv, 1, input.slice(1)) + '\n', 'jqconsole-return');
             }
             // Restart the prompt.
             startPrompt();
           }, function(input){
             try {
-                lisp.read(pv, input[0]==','? input.slice(1): input);
+                lisp.read(pv, 1, input[0]==','? input.slice(1): input);
             } catch(error) {
                 return 0;
             }
index b6eca08..96bd5b6 100644 (file)
     (n-required-arguments n-optional-arguments rest-p)
   ;; Note: Remember that we assume that the number of arguments of a
   ;; call is at least 1 (the values argument).
-  (let ((min (1+ n-required-arguments))
-        (max (if rest-p 'n/a (+ 1 n-required-arguments n-optional-arguments))))
+  (let ((min n-required-arguments)
+        (max (if rest-p 'n/a (+ n-required-arguments n-optional-arguments))))
     (block nil
       ;; Special case: a positive exact number of arguments.
-      (when (and (< 1 min) (eql min max))
-        (return (code "checkArgs(arguments, " min ");" *newline*)))
+      (when (and (< 0 min) (eql min max))
+        (return (code "checkArgs(nargs, " min ");" *newline*)))
       ;; General case:
       (code
-       (when (< 1 min)
-         (code "checkArgsAtLeast(arguments, " min ");" *newline*))
+       (when (< 0 min)
+         (code "checkArgsAtLeast(nargs, " min ");" *newline*))
        (when (numberp max)
-         (code "checkArgsAtMost(arguments, " max ");" *newline*))))))
+         (code "checkArgsAtMost(nargs, " max ");" *newline*))))))
 
 (defun compile-lambda-optional (ll)
   (let* ((optional-arguments (ll-optional-arguments-canonical ll))
         (n-required-arguments (length (ll-required-arguments ll)))
         (n-optional-arguments (length optional-arguments)))
     (when optional-arguments
-      (code (mapconcat (lambda (arg)
-                         (code "var " (translate-variable (first arg)) "; " *newline*
-                               (when (third arg)
-                                 (code "var " (translate-variable (third arg))
-                                       " = " (ls-compile t)
-                                       "; " *newline*))))
-                       optional-arguments)
-            "switch(arguments.length-1){" *newline*
+      (code "switch(nargs){" *newline*
             (let ((cases nil)
                   (idx 0))
               (progn
     (when rest-argument
       (let ((js!rest (translate-variable rest-argument)))
         (code "var " js!rest "= " (ls-compile nil) ";" *newline*
-              "for (var i = arguments.length-1; i>="
-              (+ 1 n-required-arguments n-optional-arguments)
+              "for (var i = nargs-1; i>=" (+ n-required-arguments n-optional-arguments)
               "; i--)" *newline*
-              (indent js!rest " = {car: arguments[i], cdr: ") js!rest "};"
-              *newline*)))))
+              (indent js!rest " = {car: arguments[i+2], cdr: " js!rest "};" *newline*))))))
 
 (defun compile-lambda-parse-keywords (ll)
   (let ((n-required-arguments
      ;; Parse keywords
      (flet ((parse-keyword (keyarg)
              ;; ((keyword-name var) init-form)
-             (code "for (i=" (+ 1 n-required-arguments n-optional-arguments)
-                    "; i<arguments.length; i+=2){" *newline*
+             (code "for (i=" (+ n-required-arguments n-optional-arguments)
+                    "; i<nargs; i+=2){" *newline*
                     (indent
-                     "if (arguments[i] === " (ls-compile (caar keyarg)) "){" *newline*
+                     "if (arguments[i+2] === " (ls-compile (caar keyarg)) "){" *newline*
                      (indent (translate-variable (cadr (car keyarg)))
-                             " = arguments[i+1];"
+                             " = arguments[i+3];"
                              *newline*
                              (let ((svar (third keyarg)))
                                (when svar
                      "}" *newline*)
                     "}" *newline*
                     ;; Default value
-                    "if (i == arguments.length){" *newline*
+                    "if (i == nargs){" *newline*
                     (indent (translate-variable (cadr (car keyarg))) " = " (ls-compile (cadr keyarg)) ";" *newline*)
                     "}" *newline*)))
        (when keyword-arguments
                (mapconcat #'parse-keyword keyword-arguments))))
      ;; Check for unknown keywords
      (when keyword-arguments
-       (code "for (i=" (+ 1 n-required-arguments n-optional-arguments)
-             "; i<arguments.length; i+=2){" *newline*
+       (code "for (i=" (+ n-required-arguments n-optional-arguments)
+             "; i<nargs; i+=2){" *newline*
              (indent "if ("
                      (join (mapcar (lambda (x)
-                                     (concat "arguments[i] !== " (ls-compile (caar x))))
+                                     (concat "arguments[i+2] !== " (ls-compile (caar x))))
                                    keyword-arguments)
                            " && ")
                      ")" *newline*
                                     (ll-svars ll)))))
         (lambda-name/docstring-wrapper name documentation
          "(function ("
-         (join (cons "values"
-                     (mapcar #'translate-variable
-                             (append required-arguments optional-arguments)))
+         (join (list* "values"
+                      "nargs"
+                      (mapcar #'translate-variable
+                              (append required-arguments optional-arguments)))
                ",")
          "){" *newline*
          (indent
 (define-compilation multiple-value-call (func-form &rest forms)
   (js!selfcall
     "var func = " (ls-compile func-form) ";" *newline*
-    "var args = [" (if *multiple-value-p* "values" "pv") "];" *newline*
+    "var args = [" (if *multiple-value-p* "values" "pv") ", 0];" *newline*
     "return "
     (js!selfcall
       "var values = mv;" *newline*
                          "else" *newline*
                          (indent "args.push(vs);" *newline*)))
                  forms)
+      "args[1] = args.length-2;" *newline*
       "return func.apply(window, args);" *newline*) ";" *newline*))
 
 (define-compilation multiple-value-prog1 (first-form &rest forms)
   (js!selfcall
     "var f = " (ls-compile func) ";" *newline*
     "return (typeof f === 'function'? f: f.fvalue)("
-    (join (cons (if *multiple-value-p* "values" "pv")
-                (mapcar #'ls-compile args))
+    (join (list* (if *multiple-value-p* "values" "pv")
+                 (integer-to-string (length args))
+                 (mapcar #'ls-compile args))
           ", ")
     ")"))
 
             (last (car (last args))))
         (js!selfcall
           "var f = " (ls-compile func) ";" *newline*
-          "var args = [" (join (cons (if *multiple-value-p* "values" "pv")
-                                     (mapcar #'ls-compile args))
+          "var args = [" (join (list* (if *multiple-value-p* "values" "pv")
+                                      (integer-to-string (length args))
+                                      (mapcar #'ls-compile args))
                                ", ")
           "];" *newline*
           "var tail = (" (ls-compile last) ");" *newline*
           "while (tail != " (ls-compile nil) "){" *newline*
           "    args.push(tail.car);" *newline*
+          "    args[1] += 1;" *newline*
           "    tail = tail.cdr;" *newline*
           "}" *newline*
           "return (typeof f === 'function'? f : f.fvalue).apply(this, args);" *newline*))))
     (if *multiple-value-p*
         (js!selfcall
           "var v = globalEval(string);" *newline*
-          "if (typeof v !== 'object' || !('multiple-value' in v)){" *newline*
-          (indent "v = [v];" *newline*
-                  "v['multiple-value'] = true;" *newline*)
-          "}" *newline*
-          "return values.apply(this, v);" *newline*)
+          "return values.apply(this, forcemv(v));" *newline*)
         "globalEval(string)")))
 
 (define-builtin error (string)
 
 (defun compile-funcall (function args)
   (let* ((values-funcs (if *multiple-value-p* "values" "pv"))
-         (arglist (concat "(" (join (cons values-funcs (mapcar #'ls-compile args)) ", ") ")")))
+         (arglist (concat "(" (join (list* values-funcs
+                                           (integer-to-string (length args))
+                                           (mapcar #'ls-compile args)) ", ") ")")))
     (unless (or (symbolp function)
                 (and (consp function)
                      (eq (car function) 'lambda)))
index 277a9d9..67b0427 100644 (file)
@@ -25,11 +25,11 @@ function forcemv (x) {
 var values = mv;
 
 function checkArgsAtLeast(args, n){
-    if (args.length < n) throw 'too few arguments';
+    if (args < n) throw 'too few arguments';
 }
 
 function checkArgsAtMost(args, n){
-    if (args.length > n) throw 'too many arguments';
+    if (args > n) throw 'too many arguments';
 }
 
 function checkArgs(args, n){