1 ;;; ECMAScript for Guile
3 ;; Copyright (C) 2009 Free Software Foundation, Inc.
5 ;;;; This library is free software; you can redistribute it and/or
6 ;;;; modify it under the terms of the GNU Lesser General Public
7 ;;;; License as published by the Free Software Foundation; either
8 ;;;; version 3 of the License, or (at your option) any later version.
10 ;;;; This library is distributed in the hope that it will be useful,
11 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ;;;; Lesser General Public License for more details.
15 ;;;; You should have received a copy of the GNU Lesser General Public
16 ;;;; License along with this library; if not, write to the Free Software
17 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 (define-module (language ecmascript compile-tree-il)
22 #:use-module (language tree-il)
23 #:use-module (ice-9 receive)
24 #:use-module (system base pmatch)
25 #:use-module (srfi srfi-1)
26 #:export (compile-tree-il))
36 (-> (module-ref '(language ecmascript impl) 'sym #t)))))
41 (-> (apply (@implv sym) arg ...)))))
43 (define (empty-lexical-environment)
46 (define (econs name gensym env)
47 (acons name gensym env))
49 (define (lookup name env)
50 (or (assq-ref env name)
51 (-> (toplevel name))))
53 (define (compile-tree-il exp env opts)
55 (parse-tree-il (comp exp (empty-lexical-environment)))
61 (let ((props (source-properties x)))
62 (and (not (null? props))
66 ;; (put 'pmatch/source 'scheme-indent-function 1)
68 (define-syntax pmatch/source
74 (let ((loc (location x)))
76 (set-source-properties! res (location x))))
80 (let ((l (location x)))
81 (define (let1 what proc)
83 (-> (let (list sym) (list sym) (list what)
85 (define (begin1 what proc)
86 (let1 what (lambda (v)
88 (-> (lexical v v)))))))
91 ;; FIXME, null doesn't have much relation to EOL...
102 (@impl get-this '()))
104 (-> (apply (-> (primitive '+))
105 (@impl ->number (comp a e))
108 (-> (apply (-> (primitive '-)) (-> (const 0)) (comp a e))))
110 (@impl bitwise-not (comp a e)))
112 (@impl logical-not (comp a e)))
114 (-> (apply (-> (primitive '+)) (comp a e) (comp b e))))
116 (-> (apply (-> (primitive '-)) (comp a e) (comp b e))))
118 (-> (apply (-> (primitive '/)) (comp a e) (comp b e))))
120 (-> (apply (-> (primitive '*)) (comp a e) (comp b e))))
122 (@impl mod (comp a e) (comp b e)))
124 (@impl shift (comp a e) (comp b e)))
126 (@impl shift (comp a e) (comp `(- ,b) e)))
128 (-> (apply (-> (primitive '<)) (comp a e) (comp b e))))
130 (-> (apply (-> (primitive '<=)) (comp a e) (comp b e))))
132 (-> (apply (-> (primitive '>)) (comp a e) (comp b e))))
134 (-> (apply (-> (primitive '>=)) (comp a e) (comp b e))))
136 (@impl has-property? (comp a e) (comp b e)))
138 (-> (apply (-> (primitive 'equal?)) (comp a e) (comp b e))))
140 (-> (apply (-> (primitive 'not))
141 (-> (apply (-> (primitive 'equal?))
142 (comp a e) (comp b e))))))
144 (-> (apply (-> (primitive 'eqv?)) (comp a e) (comp b e))))
146 (-> (apply (-> (primitive 'not))
147 (-> (apply (-> (primitive 'eqv?))
148 (comp a e) (comp b e))))))
150 (@impl band (comp a e) (comp b e)))
152 (@impl bxor (comp a e) (comp b e)))
154 (@impl bior (comp a e) (comp b e)))
156 (-> (if (@impl ->boolean (comp a e))
162 (-> (if (@impl ->boolean (-> (lexical v v)))
165 ((if ,test ,then ,else)
166 (-> (if (@impl ->boolean (comp test e))
169 ((if ,test ,then ,else)
170 (-> (if (@impl ->boolean (comp test e))
172 (@implv *undefined*))))
173 ((postinc (ref ,foo))
174 (begin1 (comp `(ref ,foo) e)
176 (-> (set! (lookup foo e)
177 (-> (apply (-> (primitive '+))
178 (-> (lexical var var))
179 (-> (const 1)))))))))
180 ((postinc (pref ,obj ,prop))
184 (-> (lexical objvar objvar))
188 (-> (lexical objvar objvar))
190 (-> (apply (-> (primitive '+))
191 (-> (lexical tmpvar tmpvar))
192 (-> (const 1))))))))))
193 ((postinc (aref ,obj ,prop))
199 (-> (lexical objvar objvar))
200 (-> (lexical propvar propvar)))
203 (-> (lexical objvar objvar))
204 (-> (lexical propvar propvar))
205 (-> (apply (-> (primitive '+))
206 (-> (lexical tmpvar tmpvar))
207 (-> (const 1))))))))))))
208 ((postdec (ref ,foo))
209 (begin1 (comp `(ref ,foo) e)
211 (-> (set (lookup foo e)
212 (-> (apply (-> (primitive '-))
213 (-> (lexical var var))
214 (-> (const 1)))))))))
215 ((postdec (pref ,obj ,prop))
219 (-> (lexical objvar objvar))
223 (-> (lexical objvar objvar))
225 (-> (apply (-> (primitive '-))
226 (-> (lexical tmpvar tmpvar))
227 (-> (const 1))))))))))
228 ((postdec (aref ,obj ,prop))
234 (-> (lexical objvar objvar))
235 (-> (lexical propvar propvar)))
238 (-> (lexical objvar objvar))
239 (-> (lexical propvar propvar))
241 '- (-> (lexical tmpvar tmpvar))
242 (-> (const 1))))))))))))
244 (let ((v (lookup foo e)))
247 (-> (apply (-> (primitive '+))
251 ((preinc (pref ,obj ,prop))
254 (begin1 (-> (apply (-> (primitive '+))
256 (-> (lexical objvar objvar))
260 (@impl pput (-> (lexical objvar objvar))
262 (-> (lexical tmpvar tmpvar))))))))
263 ((preinc (aref ,obj ,prop))
268 (begin1 (-> (apply (-> (primitive '+))
270 (-> (lexical objvar objvar))
271 (-> (lexical propvar propvar)))
275 (-> (lexical objvar objvar))
276 (-> (lexical propvar propvar))
277 (-> (lexical tmpvar tmpvar))))))))))
279 (let ((v (lookup foo e)))
282 (-> (apply (-> (primitive '-))
286 ((predec (pref ,obj ,prop))
289 (begin1 (-> (apply (-> (primitive '-))
291 (-> (lexical objvar objvar))
296 (-> (lexical objvar objvar))
298 (-> (lexical tmpvar tmpvar))))))))
299 ((predec (aref ,obj ,prop))
304 (begin1 (-> (apply (-> (primitive '-))
306 (-> (lexical objvar objvar))
307 (-> (lexical propvar propvar)))
311 (-> (lexical objvar objvar))
312 (-> (lexical propvar propvar))
313 (-> (lexical tmpvar tmpvar))))))))))
321 (-> (define x (comp y e))))
323 (-> (define x (@implv *undefined*))))
324 (else (error "bad var form" form))))
327 `(begin ,@(map (lambda (x) (comp x e)) forms)))
328 ((lambda ,formals ,body)
329 (let ((syms (map (lambda (x)
330 (gensym (string-append (symbol->string x) " ")))
334 `((() ,formals #f #f () ,syms #f)
335 ,(comp-body e body formals syms))))))))
336 ((call/this ,obj ,prop . ,args)
341 `((() #f #f #f () () #f)
342 (apply ,(@impl pget obj prop) ,@args))))))))
343 ((call (pref ,obj ,prop) ,args)
344 (comp `(call/this ,(comp obj e)
346 ,@(map (lambda (x) (comp x e)) args))
348 ((call (aref ,obj ,prop) ,args)
349 (comp `(call/this ,(comp obj e)
351 ,@(map (lambda (x) (comp x e)) args))
354 `(apply ,(comp proc e)
355 ,@(map (lambda (x) (comp x e)) args)))
357 (-> (apply (-> (primitive 'return))
360 `(apply ,(@implv new-array)
361 ,@(map (lambda (x) (comp x e)) args)))
367 (-> (apply (-> (primitive 'cons))
371 (error "bad prop-val pair" x))))
381 ((= (ref ,name) ,val)
382 (let ((v (lookup name e)))
384 (-> (set! v (comp val e)))
386 ((= (pref ,obj ,prop) ,val)
391 ((= (aref ,obj ,prop) ,val)
397 (comp `(= ,what (+ ,what ,val)) e))
399 (comp `(= ,what (- ,what ,val)) e))
401 (comp `(= ,what (/ ,what ,val)) e))
403 (comp `(= ,what (* ,what ,val)) e))
405 (comp `(= ,what (% ,what ,val)) e))
407 (comp `(= ,what (>> ,what ,val)) e))
409 (comp `(= ,what (<< ,what ,val)) e))
411 (comp `(= ,what (>>> ,what ,val)) e))
413 (comp `(= ,what (& ,what ,val)) e))
415 (comp `(= ,what (bor ,what ,val)) e))
417 (comp `(= ,what (^ ,what ,val)) e))
420 (map (lambda (x) (comp x e))
422 ((delete (pref ,obj ,prop))
426 ((delete (aref ,obj ,prop))
433 (@implv *undefined*))))
437 ((do ,statement ,test)
438 (let ((%loop (gensym "%loop "))
439 (%continue (gensym "%continue ")))
440 (let ((e (econs '%loop %loop (econs '%continue %continue e))))
441 (-> (letrec '(%loop %continue) (list %loop %continue)
442 (list (-> (lambda '()
444 `((() #f #f #f () () #f)
447 (-> (apply (-> (lexical '%continue %continue)))))))))))
450 `((() #f #f #f () () #f)
451 ,(-> (if (@impl ->boolean (comp test e))
452 (-> (apply (-> (lexical '%loop %loop))))
453 (@implv *undefined*)))))))))
454 (-> (apply (-> (lexical '%loop %loop)))))))))
455 ((while ,test ,statement)
456 (let ((%continue (gensym "%continue ")))
457 (let ((e (econs '%continue %continue e)))
458 (-> (letrec '(%continue) (list %continue)
459 (list (-> (lambda '()
461 `((() #f #f #f () () #f)
462 ,(-> (if (@impl ->boolean (comp test e))
463 (-> (begin (comp statement e)
464 (-> (apply (-> (lexical '%continue %continue))))))
465 (@implv *undefined*)))))))))
466 (-> (apply (-> (lexical '%continue %continue)))))))))
468 ((for ,init ,test ,inc ,statement)
469 (let ((%continue (gensym "%continue ")))
470 (let ((e (econs '%continue %continue e)))
471 (-> (letrec '(%continue) (list %continue)
472 (list (-> (lambda '()
474 `((() #f #f #f () () #f)
476 (@impl ->boolean (comp test e))
478 (-> (begin (comp statement e)
479 (comp (or inc '(begin)) e)
480 (-> (apply (-> (lexical '%continue %continue))))))
481 (@implv *undefined*)))))))))
482 (-> (begin (comp (or init '(begin)) e)
483 (-> (apply (-> (lexical '%continue %continue)))))))))))
485 ((for-in ,var ,object ,statement)
486 (let ((%enum (gensym "%enum "))
487 (%continue (gensym "%continue ")))
488 (let ((e (econs '%enum %enum (econs '%continue %continue e))))
489 (-> (letrec '(%enum %continue) (list %enum %continue)
490 (list (@impl make-enumerator (comp object e))
493 `((() #f #f #f () () #f)
494 (-> (if (@impl ->boolean
496 (-> (lexical '%enum %enum))
497 (-> (const 'length))))
499 (comp `(= ,var (call/this ,(-> (lexical '%enum %enum))
503 (-> (apply (-> (lexical '%continue %continue))))))
504 (@implv *undefined*)))))))))
505 (-> (apply (-> (lexical '%continue %continue)))))))))
510 (error "compilation not yet implemented:" x)))))
512 (define (comp-body e body formals formal-syms)
514 (let lp ((in body) (out '()) (rvars '()))
516 (((var (,x) . ,morevars) . ,rest)
517 (lp `((var . ,morevars) . ,rest)
519 (if (or (memq x rvars) (memq x formals))
522 (((var (,x ,y) . ,morevars) . ,rest)
523 (lp `((var . ,morevars) . ,rest)
524 `((= (ref ,x) ,y) . ,out)
525 (if (or (memq x rvars) (memq x formals))
530 ((,x . ,rest) (guard (and (pair? x) (eq? (car x) 'lambda)))
534 ((,x . ,rest) (guard (pair? x))
535 (receive (sub-out rvars)
545 (values (reverse! out)
549 (let* ((names (reverse rvars))
550 (syms (map (lambda (x)
551 (gensym (string-append (symbol->string x) " ")))
553 (e (fold econs (fold econs e formals formal-syms) names syms)))
554 (-> (let names syms (map (lambda (x) (->@implv *undefined*)) names)