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 ((%args (gensym "%args ")))
330 (-> (lambda '%args %args '()
331 (comp-body (econs '%args %args e) body formals '%args)))))
332 ((call/this ,obj ,prop . ,args)
335 (-> (lambda '() '() '()
336 `(apply ,(@impl pget obj prop) ,@args)))))
337 ((call (pref ,obj ,prop) ,args)
338 (comp `(call/this ,(comp obj e)
340 ,@(map (lambda (x) (comp x e)) args))
342 ((call (aref ,obj ,prop) ,args)
343 (comp `(call/this ,(comp obj e)
345 ,@(map (lambda (x) (comp x e)) args))
348 `(apply ,(comp proc e)
349 ,@(map (lambda (x) (comp x e)) args)))
351 (-> (apply (-> (primitive 'return))
354 `(apply ,(@implv new-array)
355 ,@(map (lambda (x) (comp x e)) args)))
361 (-> (apply (-> (primitive 'cons))
365 (error "bad prop-val pair" x))))
375 ((= (ref ,name) ,val)
376 (let ((v (lookup name e)))
378 (-> (set! v (comp val e)))
380 ((= (pref ,obj ,prop) ,val)
385 ((= (aref ,obj ,prop) ,val)
391 (comp `(= ,what (+ ,what ,val)) e))
393 (comp `(= ,what (- ,what ,val)) e))
395 (comp `(= ,what (/ ,what ,val)) e))
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 (bor ,what ,val)) e))
411 (comp `(= ,what (^ ,what ,val)) e))
414 (map (lambda (x) (comp x e))
416 ((delete (pref ,obj ,prop))
420 ((delete (aref ,obj ,prop))
427 (@implv *undefined*))))
431 ((do ,statement ,test)
432 (let ((%loop (gensym "%loop "))
433 (%continue (gensym "%continue ")))
434 (let ((e (econs '%loop %loop (econs '%continue %continue e))))
435 (-> (letrec '(%loop %continue) (list %loop %continue)
436 (list (-> (lambda '() '() '()
439 (-> (apply (-> (lexical '%continue %continue)))
442 (-> (lambda '() '() '()
443 (-> (if (@impl ->boolean (comp test e))
444 (-> (apply (-> (lexical '%loop %loop))))
445 (@implv *undefined*))))))
446 (-> (apply (-> (lexical '%loop %loop)))))))))
447 ((while ,test ,statement)
448 (let ((%continue (gensym "%continue ")))
449 (let ((e (econs '%continue %continue e)))
450 (-> (letrec '(%continue) (list %continue)
451 (list (-> (lambda '() '() '()
452 (-> (if (@impl ->boolean (comp test e))
453 (-> (begin (comp statement e)
454 (-> (apply (-> (lexical '%continue %continue))))))
455 (@implv *undefined*))))))
456 (-> (apply (-> (lexical '%continue %continue)))))))))
458 ((for ,init ,test ,inc ,statement)
459 (let ((%continue (gensym "%continue ")))
460 (let ((e (econs '%continue %continue e)))
461 (-> (letrec '(%continue) (list %continue)
462 (list (-> (lambda '() '() '()
464 (@impl ->boolean (comp test e))
466 (-> (begin (comp statement e)
467 (comp (or inc '(begin)) e)
468 (-> (apply (-> (lexical '%continue %continue))))))
469 (@implv *undefined*))))))
470 (-> (begin (comp (or init '(begin)) e)
471 (-> (apply (-> (lexical '%continue %continue)))))))))))
473 ((for-in ,var ,object ,statement)
474 (let ((%enum (gensym "%enum "))
475 (%continue (gensym "%continue ")))
476 (let ((e (econs '%enum %enum (econs '%continue %continue e))))
477 (-> (letrec '(%enum %continue) (list %enum %continue)
478 (list (@impl make-enumerator (comp object e))
479 (-> (lambda '() '() '()
480 (-> (if (@impl ->boolean
482 (-> (lexical '%enum %enum))
483 (-> (const 'length))))
485 (comp `(= ,var (call/this ,(-> (lexical '%enum %enum))
489 (-> (apply (-> (lexical '%continue %continue))))))
490 (@implv *undefined*))))))
491 (-> (apply (-> (lexical '%continue %continue)))))))))
496 (error "compilation not yet implemented:" x)))))
498 (define (comp-body e body formals %args)
500 (let lp ((in body) (out '()) (rvars (reverse formals)))
502 (((var (,x) . ,morevars) . ,rest)
503 (lp `((var . ,morevars) . ,rest)
505 (if (memq x rvars) rvars (cons x rvars))))
506 (((var (,x ,y) . ,morevars) . ,rest)
507 (lp `((var . ,morevars) . ,rest)
508 `((= (ref ,x) ,y) . ,out)
509 (if (memq x rvars) rvars (cons x rvars))))
512 ((,x . ,rest) (guard (and (pair? x) (eq? (car x) 'lambda)))
516 ((,x . ,rest) (guard (pair? x))
517 (receive (sub-out rvars)
527 (values (reverse! out)
531 (let* ((names (reverse rvars))
532 (syms (map (lambda (x)
533 (gensym (string-append (symbol->string x) " ")))
535 (e (fold acons e names syms)))
536 (let ((%argv (lookup %args e)))
537 (let lp ((names names) (syms syms))
539 ;; fixme: here check for too many args
541 (-> (let (list (car names)) (list (car syms))
542 (list (-> (if (-> (apply (-> (primitive 'null?)) %argv))
543 (-> (@implv *undefined*))
544 (-> (let1 (-> (apply (-> (primitive 'car)) %argv))
547 (-> (apply (-> (primitive 'cdr)) %argv))))
548 (-> (lexical v v))))))))
549 (lp (cdr names) (cdr syms))))))))))