Merge remote-tracking branch 'origin/stable-2.0'
[bpt/guile.git] / module / language / ecmascript / compile-tree-il.scm
index a97e555..2fe0d92 100644 (file)
@@ -1,6 +1,6 @@
 ;;; ECMAScript for Guile
 
-;; Copyright (C) 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2009, 2011 Free Software Foundation, Inc.
 
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
   #:use-module (srfi srfi-1)
   #:export (compile-tree-il))
 
-(define-syntax ->
-  (syntax-rules ()
-    ((_ (type arg ...))
-     `(type ,arg ...))))
+(define-syntax-rule (-> (type arg ...))
+  `(type ,arg ...))
 
-(define-syntax @implv
-  (syntax-rules ()
-    ((_ sym)
-     (-> (@ '(language ecmascript impl) 'sym)))))
+(define-syntax-rule (@implv sym)
+  (-> (@ '(language ecmascript impl) 'sym)))
 
-(define-syntax @impl
-  (syntax-rules ()
-    ((_ sym arg ...)
-     (-> (apply (@implv sym) arg ...)))))
+(define-syntax-rule (@impl sym arg ...)
+  (-> (call (@implv sym) arg ...)))
 
 (define (empty-lexical-environment)
   '())
 ;; for emacs:
 ;; (put 'pmatch/source 'scheme-indent-function 1)
 
-(define-syntax pmatch/source
-  (syntax-rules ()
-    ((_ x clause ...)
-     (let ((x x))
-       (let ((res (pmatch x
-                    clause ...)))
-         (let ((loc (location x)))
-           (if loc
-               (set-source-properties! res (location x))))
-         res)))))
+(define-syntax-rule (pmatch/source x clause ...)
+  (let ((x x))
+    (let ((res (pmatch x
+                 clause ...)))
+      (let ((loc (location x)))
+        (if loc
+            (set-source-properties! res (location x))))
+      res)))
+
+(define current-return-tag (make-parameter #f))
+
+(define (return expr)
+  (-> (abort (or (current-return-tag) (error "return outside function"))
+             (list expr)
+             (-> (const '())))))
+
+(define (with-return-prompt body-thunk)
+  (let ((tag (gensym "return")))
+    (parameterize ((current-return-tag
+                    (-> (lexical 'return tag))))
+      (-> (let '(return) (list tag)
+               (list (-> (primcall 'make-prompt-tag)))
+               (-> (prompt (current-return-tag)
+                           (body-thunk)
+                           (let ((val (gensym "val")))
+                             (-> (lambda-case
+                                  `(((k val) #f #f #f () (,(gensym) ,val))
+                                    ,(-> (lexical 'val val)))))))))))))
 
 (define (comp x e)
   (let ((l (location x)))
       (this
        (@impl get-this))
       ((+ ,a)
-       (-> (apply (-> (primitive '+))
-                  (@impl ->number (comp a e))
-                  (-> (const 0)))))
+       (-> (call (-> (primitive '+))
+                 (@impl ->number (comp a e))
+                 (-> (const 0)))))
       ((- ,a)
-       (-> (apply (-> (primitive '-)) (-> (const 0)) (comp a e))))
+       (-> (call (-> (primitive '-)) (-> (const 0)) (comp a e))))
       ((~ ,a)
        (@impl bitwise-not (comp a e)))
       ((! ,a)
        (@impl logical-not (comp a e)))
       ((+ ,a ,b)
-       (-> (apply (-> (primitive '+)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive '+)) (comp a e) (comp b e))))
       ((- ,a ,b)
-       (-> (apply (-> (primitive '-)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive '-)) (comp a e) (comp b e))))
       ((/ ,a ,b)
-       (-> (apply (-> (primitive '/)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive '/)) (comp a e) (comp b e))))
       ((* ,a ,b)
-       (-> (apply (-> (primitive '*)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive '*)) (comp a e) (comp b e))))
       ((% ,a ,b)
        (@impl mod (comp a e) (comp b e)))
       ((<< ,a ,b)
       ((>> ,a ,b)
        (@impl shift (comp a e) (comp `(- ,b) e)))
       ((< ,a ,b)
-       (-> (apply (-> (primitive '<)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive '<)) (comp a e) (comp b e))))
       ((<= ,a ,b)
-       (-> (apply (-> (primitive '<=)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive '<=)) (comp a e) (comp b e))))
       ((> ,a ,b)
-       (-> (apply (-> (primitive '>)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive '>)) (comp a e) (comp b e))))
       ((>= ,a ,b)
-       (-> (apply (-> (primitive '>=)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive '>=)) (comp a e) (comp b e))))
       ((in ,a ,b)
        (@impl has-property? (comp a e) (comp b e)))
       ((== ,a ,b)
-       (-> (apply (-> (primitive 'equal?)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive 'equal?)) (comp a e) (comp b e))))
       ((!= ,a ,b)
-       (-> (apply (-> (primitive 'not))
-                  (-> (apply (-> (primitive 'equal?))
-                             (comp a e) (comp b e))))))
+       (-> (call (-> (primitive 'not))
+                 (-> (call (-> (primitive 'equal?))
+                           (comp a e) (comp b e))))))
       ((=== ,a ,b)
-       (-> (apply (-> (primitive 'eqv?)) (comp a e) (comp b e))))
+       (-> (call (-> (primitive 'eqv?)) (comp a e) (comp b e))))
       ((!== ,a ,b)
-       (-> (apply (-> (primitive 'not))
-                  (-> (apply (-> (primitive 'eqv?))
-                             (comp a e) (comp b e))))))
+       (-> (call (-> (primitive 'not))
+                 (-> (call (-> (primitive 'eqv?))
+                           (comp a e) (comp b e))))))
       ((& ,a ,b)
        (@impl band (comp a e) (comp b e)))
       ((^ ,a ,b)
        (begin1 (comp `(ref ,foo) e)
                (lambda (var)
                  (-> (set! (lookup foo e)
-                           (-> (apply (-> (primitive '+))
-                                      (-> (lexical var var))
-                                      (-> (const 1)))))))))
+                           (-> (call (-> (primitive '+))
+                                     (-> (lexical var var))
+                                     (-> (const 1)))))))))
       ((postinc (pref ,obj ,prop))
        (let1 (comp obj e)
              (lambda (objvar)
                          (@impl pput
                                 (-> (lexical objvar objvar))
                                 (-> (const prop))
-                                (-> (apply (-> (primitive '+))
-                                           (-> (lexical tmpvar tmpvar))
-                                           (-> (const 1))))))))))
+                                (-> (call (-> (primitive '+))
+                                          (-> (lexical tmpvar tmpvar))
+                                          (-> (const 1))))))))))
       ((postinc (aref ,obj ,prop))
        (let1 (comp obj e)
              (lambda (objvar)
                                  (@impl pput
                                         (-> (lexical objvar objvar))
                                         (-> (lexical propvar propvar))
-                                        (-> (apply (-> (primitive '+))
-                                                   (-> (lexical tmpvar tmpvar))
-                                                   (-> (const 1))))))))))))
+                                        (-> (call (-> (primitive '+))
+                                                  (-> (lexical tmpvar tmpvar))
+                                                  (-> (const 1))))))))))))
       ((postdec (ref ,foo))
        (begin1 (comp `(ref ,foo) e)
                (lambda (var)
                  (-> (set (lookup foo e)
-                          (-> (apply (-> (primitive '-))
-                                     (-> (lexical var var))
-                                     (-> (const 1)))))))))
+                          (-> (call (-> (primitive '-))
+                                    (-> (lexical var var))
+                                    (-> (const 1)))))))))
       ((postdec (pref ,obj ,prop))
        (let1 (comp obj e)
              (lambda (objvar)
                          (@impl pput
                                 (-> (lexical objvar objvar))
                                 (-> (const prop))
-                                (-> (apply (-> (primitive '-))
-                                           (-> (lexical tmpvar tmpvar))
-                                           (-> (const 1))))))))))
+                                (-> (call (-> (primitive '-))
+                                          (-> (lexical tmpvar tmpvar))
+                                          (-> (const 1))))))))))
       ((postdec (aref ,obj ,prop))
        (let1 (comp obj e)
              (lambda (objvar)
        (let ((v (lookup foo e)))
          (-> (begin
                (-> (set! v
-                         (-> (apply (-> (primitive '+))
-                                    v
-                                    (-> (const 1))))))
+                         (-> (call (-> (primitive '+))
+                                   v
+                                   (-> (const 1))))))
                v))))
       ((preinc (pref ,obj ,prop))
        (let1 (comp obj e)
              (lambda (objvar)
-               (begin1 (-> (apply (-> (primitive '+))
-                                  (@impl pget
-                                         (-> (lexical objvar objvar))
-                                         (-> (const prop)))
-                                  (-> (const 1))))
+               (begin1 (-> (call (-> (primitive '+))
+                                 (@impl pget
+                                        (-> (lexical objvar objvar))
+                                        (-> (const prop)))
+                                 (-> (const 1))))
                        (lambda (tmpvar)
                          (@impl pput (-> (lexical objvar objvar))
                                 (-> (const prop))
              (lambda (objvar)
                (let1 (comp prop e)
                      (lambda (propvar)
-                       (begin1 (-> (apply (-> (primitive '+))
-                                          (@impl pget
-                                                 (-> (lexical objvar objvar))
-                                                 (-> (lexical propvar propvar)))
-                                          (-> (const 1))))
+                       (begin1 (-> (call (-> (primitive '+))
+                                         (@impl pget
+                                                (-> (lexical objvar objvar))
+                                                (-> (lexical propvar propvar)))
+                                         (-> (const 1))))
                                (lambda (tmpvar)
                                  (@impl pput
                                         (-> (lexical objvar objvar))
        (let ((v (lookup foo e)))
          (-> (begin
                (-> (set! v
-                        (-> (apply (-> (primitive '-))
+                         (-> (call (-> (primitive '-))
                                    v
                                    (-> (const 1))))))
                v))))
       ((predec (pref ,obj ,prop))
        (let1 (comp obj e)
              (lambda (objvar)
-               (begin1 (-> (apply (-> (primitive '-))
-                                  (@impl pget
-                                         (-> (lexical objvar objvar))
-                                         (-> (const prop)))
-                                  (-> (const 1))))
+               (begin1 (-> (call (-> (primitive '-))
+                                 (@impl pget
+                                        (-> (lexical objvar objvar))
+                                        (-> (const prop)))
+                                 (-> (const 1))))
                        (lambda (tmpvar)
                          (@impl pput
                                 (-> (lexical objvar objvar))
              (lambda (objvar)
                (let1 (comp prop e)
                      (lambda (propvar)
-                       (begin1 (-> (apply (-> (primitive '-))
-                                          (@impl pget
-                                                 (-> (lexical objvar objvar))
-                                                 (-> (lexical propvar propvar)))
-                                          (-> (const 1))))
+                       (begin1 (-> (call (-> (primitive '-))
+                                         (@impl pget
+                                                (-> (lexical objvar objvar))
+                                                (-> (lexical propvar propvar)))
+                                         (-> (const 1))))
                                (lambda (tmpvar)
                                  (@impl pput
                                         (-> (lexical objvar objvar))
          `(lambda ()
             (lambda-case
              ((() ,formals #f #f ,(map (lambda (x) (@implv *undefined*)) formals) ,syms)
-              ,(comp-body e body formals syms))))))
+              ,(with-return-prompt
+                (lambda ()
+                  (comp-body e body formals syms))))))))
       ((call/this ,obj ,prop . ,args)
        (@impl call/this*
               obj
               (-> (lambda '() 
                     `(lambda-case
                       ((() #f #f #f () ())
-                       (apply ,(@impl pget obj prop) ,@args)))))))
+                       (call ,(@impl pget obj prop) ,@args)))))))
       ((call (pref ,obj ,prop) ,args)
        (comp `(call/this ,(comp obj e)
                          ,(-> (const prop))
                          ,@(map (lambda (x) (comp x e)) args))
              e))
       ((call ,proc ,args)
-       `(apply ,(comp proc e)                
-               ,@(map (lambda (x) (comp x e)) args)))
+       `(call ,(comp proc e)                
+              ,@(map (lambda (x) (comp x e)) args)))
       ((return ,expr)
-       (-> (apply (-> (primitive 'return))
-                  (comp expr e))))
+       (return (comp expr e)))
       ((array . ,args)
-       `(apply ,(@implv new-array)
-               ,@(map (lambda (x) (comp x e)) args)))
+       `(call ,(@implv new-array)
+              ,@(map (lambda (x) (comp x e)) args)))
       ((object . ,args)
-       (@impl new-object
-              (map (lambda (x)
-                     (pmatch x
-                       ((,prop ,val)
-                        (-> (apply (-> (primitive 'cons))
-                                   (-> (const prop))
-                                   (comp val e))))
-                       (else
-                        (error "bad prop-val pair" x))))
-                   args)))
+       `(call ,(@implv new-object)
+              ,@(map (lambda (x)
+                       (pmatch x
+                         ((,prop ,val)
+                          (-> (call (-> (primitive 'cons))
+                                    (-> (const prop))
+                                    (comp val e))))
+                         (else
+                          (error "bad prop-val pair" x))))
+                     args)))
       ((pref ,obj ,prop)
        (@impl pget
               (comp obj e)
                                         `((() #f #f #f () ())
                                           ,(-> (begin
                                                  (comp statement e)
-                                                 (-> (apply (-> (lexical '%continue %continue)))))))))))
+                                                 (-> (call (-> (lexical '%continue %continue)))))))))))
                              (-> (lambda '()
                                    (-> (lambda-case
                                         `((() #f #f #f () ())
                                           ,(-> (if (@impl ->boolean (comp test e))
-                                                   (-> (apply (-> (lexical '%loop %loop))))
+                                                   (-> (call (-> (lexical '%loop %loop))))
                                                    (@implv *undefined*)))))))))
-                       (-> (apply (-> (lexical '%loop %loop)))))))))
+                       (-> (call (-> (lexical '%loop %loop)))))))))
       ((while ,test ,statement)
        (let ((%continue (gensym "%continue ")))
          (let ((e (econs '%continue %continue e)))
                                         `((() #f #f #f () ())
                                           ,(-> (if (@impl ->boolean (comp test e))
                                                    (-> (begin (comp statement e)
-                                                              (-> (apply (-> (lexical '%continue %continue))))))
+                                                              (-> (call (-> (lexical '%continue %continue))))))
                                                    (@implv *undefined*)))))))))
-                       (-> (apply (-> (lexical '%continue %continue)))))))))
+                       (-> (call (-> (lexical '%continue %continue)))))))))
       
       ((for ,init ,test ,inc ,statement)
        (let ((%continue (gensym "%continue ")))
                                                        (comp 'true e))
                                                    (-> (begin (comp statement e)
                                                               (comp (or inc '(begin)) e)
-                                                              (-> (apply (-> (lexical '%continue %continue))))))
+                                                              (-> (call (-> (lexical '%continue %continue))))))
                                                    (@implv *undefined*)))))))))
                        (-> (begin (comp (or init '(begin)) e)
-                                  (-> (apply (-> (lexical '%continue %continue)))))))))))
+                                  (-> (call (-> (lexical '%continue %continue)))))))))))
       
       ((for-in ,var ,object ,statement)
        (let ((%enum (gensym "%enum "))
                                                                                   ,(-> (const 'pop))))
                                                               e)
                                                         (comp statement e)
-                                                        (-> (apply (-> (lexical '%continue %continue))))))
+                                                        (-> (call (-> (lexical '%continue %continue))))))
                                                   (@implv *undefined*)))))))))
-                       (-> (apply (-> (lexical '%continue %continue)))))))))
+                       (-> (call (-> (lexical '%continue %continue)))))))))
       
       ((block ,x)
        (comp x e))