Adapt ecmascript compiler to recent tree-il changes for prompts.
[bpt/guile.git] / module / language / ecmascript / compile-tree-il.scm
CommitLineData
eb1482ac
AW
1;;; ECMAScript for Guile
2
8a41c56a 3;; Copyright (C) 2009, 2011 Free Software Foundation, Inc.
eb1482ac
AW
4
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.
9;;;;
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.
14;;;;
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
18
19;;; Code:
20
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))
27
0c65f52c
AW
28(define-syntax-rule (-> (type arg ...))
29 `(type ,arg ...))
eb1482ac 30
0c65f52c
AW
31(define-syntax-rule (@implv sym)
32 (-> (@ '(language ecmascript impl) 'sym)))
eb1482ac 33
0c65f52c 34(define-syntax-rule (@impl sym arg ...)
ca128245 35 (-> (call (@implv sym) arg ...)))
eb1482ac
AW
36
37(define (empty-lexical-environment)
38 '())
39
40(define (econs name gensym env)
d61e866c 41 (acons name (-> (lexical name gensym)) env))
eb1482ac
AW
42
43(define (lookup name env)
44 (or (assq-ref env name)
45 (-> (toplevel name))))
46
47(define (compile-tree-il exp env opts)
48 (values
d61e866c
AW
49 (parse-tree-il
50 (-> (begin (@impl js-init)
51 (comp exp (empty-lexical-environment)))))
eb1482ac
AW
52 env
53 env))
54
55(define (location x)
56 (and (pair? x)
57 (let ((props (source-properties x)))
58 (and (not (null? props))
59 props))))
60
61;; for emacs:
62;; (put 'pmatch/source 'scheme-indent-function 1)
63
0c65f52c
AW
64(define-syntax-rule (pmatch/source x clause ...)
65 (let ((x x))
66 (let ((res (pmatch x
67 clause ...)))
68 (let ((loc (location x)))
69 (if loc
70 (set-source-properties! res (location x))))
71 res)))
eb1482ac 72
c0cfa9ef
AW
73(define current-return-tag (make-parameter #f))
74
75(define (return expr)
76 (-> (abort (or (current-return-tag) (error "return outside function"))
77 (list expr)
78 (-> (const '())))))
79
80(define (with-return-prompt body-thunk)
81 (let ((tag (gensym "return")))
82 (parameterize ((current-return-tag
83 (-> (lexical 'return tag))))
84 (-> (let '(return) (list tag)
2aed2667 85 (list (-> (primcall 'make-prompt-tag)))
5270bb5b
MW
86 (-> (prompt #t
87 (current-return-tag)
88 (-> (lambda '()
89 (-> (lambda-case
90 `((() #f #f #f () ())
91 ,(body-thunk))))))
c0cfa9ef 92 (let ((val (gensym "val")))
5270bb5b
MW
93 (-> (lambda '()
94 (-> (lambda-case
95 `(((k val) #f #f #f () (,(gensym) ,val))
96 ,(-> (lexical 'val val)))))))))))))))
c0cfa9ef 97
eb1482ac
AW
98(define (comp x e)
99 (let ((l (location x)))
100 (define (let1 what proc)
101 (let ((sym (gensym)))
102 (-> (let (list sym) (list sym) (list what)
103 (proc sym)))))
104 (define (begin1 what proc)
105 (let1 what (lambda (v)
106 (-> (begin (proc v)
107 (-> (lexical v v)))))))
108 (pmatch/source x
109 (null
110 ;; FIXME, null doesn't have much relation to EOL...
111 (-> (const '())))
112 (true
113 (-> (const #t)))
114 (false
115 (-> (const #f)))
116 ((number ,num)
117 (-> (const num)))
118 ((string ,str)
119 (-> (const str)))
120 (this
d61e866c 121 (@impl get-this))
eb1482ac 122 ((+ ,a)
7081d4f9
AW
123 (-> (call (-> (primitive '+))
124 (@impl ->number (comp a e))
125 (-> (const 0)))))
eb1482ac 126 ((- ,a)
7081d4f9 127 (-> (call (-> (primitive '-)) (-> (const 0)) (comp a e))))
eb1482ac
AW
128 ((~ ,a)
129 (@impl bitwise-not (comp a e)))
130 ((! ,a)
131 (@impl logical-not (comp a e)))
132 ((+ ,a ,b)
7081d4f9 133 (-> (call (-> (primitive '+)) (comp a e) (comp b e))))
eb1482ac 134 ((- ,a ,b)
7081d4f9 135 (-> (call (-> (primitive '-)) (comp a e) (comp b e))))
eb1482ac 136 ((/ ,a ,b)
7081d4f9 137 (-> (call (-> (primitive '/)) (comp a e) (comp b e))))
eb1482ac 138 ((* ,a ,b)
7081d4f9 139 (-> (call (-> (primitive '*)) (comp a e) (comp b e))))
eb1482ac
AW
140 ((% ,a ,b)
141 (@impl mod (comp a e) (comp b e)))
142 ((<< ,a ,b)
143 (@impl shift (comp a e) (comp b e)))
144 ((>> ,a ,b)
145 (@impl shift (comp a e) (comp `(- ,b) e)))
146 ((< ,a ,b)
7081d4f9 147 (-> (call (-> (primitive '<)) (comp a e) (comp b e))))
eb1482ac 148 ((<= ,a ,b)
7081d4f9 149 (-> (call (-> (primitive '<=)) (comp a e) (comp b e))))
eb1482ac 150 ((> ,a ,b)
7081d4f9 151 (-> (call (-> (primitive '>)) (comp a e) (comp b e))))
eb1482ac 152 ((>= ,a ,b)
7081d4f9 153 (-> (call (-> (primitive '>=)) (comp a e) (comp b e))))
eb1482ac
AW
154 ((in ,a ,b)
155 (@impl has-property? (comp a e) (comp b e)))
156 ((== ,a ,b)
7081d4f9 157 (-> (call (-> (primitive 'equal?)) (comp a e) (comp b e))))
eb1482ac 158 ((!= ,a ,b)
7081d4f9
AW
159 (-> (call (-> (primitive 'not))
160 (-> (call (-> (primitive 'equal?))
161 (comp a e) (comp b e))))))
eb1482ac 162 ((=== ,a ,b)
7081d4f9 163 (-> (call (-> (primitive 'eqv?)) (comp a e) (comp b e))))
eb1482ac 164 ((!== ,a ,b)
7081d4f9
AW
165 (-> (call (-> (primitive 'not))
166 (-> (call (-> (primitive 'eqv?))
167 (comp a e) (comp b e))))))
eb1482ac
AW
168 ((& ,a ,b)
169 (@impl band (comp a e) (comp b e)))
170 ((^ ,a ,b)
171 (@impl bxor (comp a e) (comp b e)))
172 ((bor ,a ,b)
173 (@impl bior (comp a e) (comp b e)))
174 ((and ,a ,b)
175 (-> (if (@impl ->boolean (comp a e))
176 (comp b e)
177 (-> (const #f)))))
178 ((or ,a ,b)
179 (let1 (comp a e)
180 (lambda (v)
181 (-> (if (@impl ->boolean (-> (lexical v v)))
182 (-> (lexical v v))
183 (comp b e))))))
184 ((if ,test ,then ,else)
185 (-> (if (@impl ->boolean (comp test e))
186 (comp then e)
187 (comp else e))))
d61e866c 188 ((if ,test ,then)
eb1482ac
AW
189 (-> (if (@impl ->boolean (comp test e))
190 (comp then e)
191 (@implv *undefined*))))
192 ((postinc (ref ,foo))
193 (begin1 (comp `(ref ,foo) e)
194 (lambda (var)
195 (-> (set! (lookup foo e)
7081d4f9
AW
196 (-> (call (-> (primitive '+))
197 (-> (lexical var var))
198 (-> (const 1)))))))))
eb1482ac
AW
199 ((postinc (pref ,obj ,prop))
200 (let1 (comp obj e)
201 (lambda (objvar)
202 (begin1 (@impl pget
203 (-> (lexical objvar objvar))
204 (-> (const prop)))
205 (lambda (tmpvar)
206 (@impl pput
207 (-> (lexical objvar objvar))
208 (-> (const prop))
7081d4f9
AW
209 (-> (call (-> (primitive '+))
210 (-> (lexical tmpvar tmpvar))
211 (-> (const 1))))))))))
eb1482ac
AW
212 ((postinc (aref ,obj ,prop))
213 (let1 (comp obj e)
214 (lambda (objvar)
215 (let1 (comp prop e)
216 (lambda (propvar)
217 (begin1 (@impl pget
218 (-> (lexical objvar objvar))
219 (-> (lexical propvar propvar)))
220 (lambda (tmpvar)
221 (@impl pput
222 (-> (lexical objvar objvar))
223 (-> (lexical propvar propvar))
7081d4f9
AW
224 (-> (call (-> (primitive '+))
225 (-> (lexical tmpvar tmpvar))
226 (-> (const 1))))))))))))
eb1482ac
AW
227 ((postdec (ref ,foo))
228 (begin1 (comp `(ref ,foo) e)
229 (lambda (var)
230 (-> (set (lookup foo e)
7081d4f9
AW
231 (-> (call (-> (primitive '-))
232 (-> (lexical var var))
233 (-> (const 1)))))))))
eb1482ac
AW
234 ((postdec (pref ,obj ,prop))
235 (let1 (comp obj e)
236 (lambda (objvar)
237 (begin1 (@impl pget
238 (-> (lexical objvar objvar))
239 (-> (const prop)))
240 (lambda (tmpvar)
241 (@impl pput
242 (-> (lexical objvar objvar))
243 (-> (const prop))
7081d4f9
AW
244 (-> (call (-> (primitive '-))
245 (-> (lexical tmpvar tmpvar))
246 (-> (const 1))))))))))
eb1482ac
AW
247 ((postdec (aref ,obj ,prop))
248 (let1 (comp obj e)
249 (lambda (objvar)
250 (let1 (comp prop e)
251 (lambda (propvar)
252 (begin1 (@impl pget
253 (-> (lexical objvar objvar))
254 (-> (lexical propvar propvar)))
255 (lambda (tmpvar)
256 (@impl pput
257 (-> (lexical objvar objvar))
258 (-> (lexical propvar propvar))
259 (-> (inline
260 '- (-> (lexical tmpvar tmpvar))
261 (-> (const 1))))))))))))
262 ((preinc (ref ,foo))
263 (let ((v (lookup foo e)))
264 (-> (begin
265 (-> (set! v
7081d4f9
AW
266 (-> (call (-> (primitive '+))
267 v
268 (-> (const 1))))))
eb1482ac
AW
269 v))))
270 ((preinc (pref ,obj ,prop))
271 (let1 (comp obj e)
272 (lambda (objvar)
7081d4f9
AW
273 (begin1 (-> (call (-> (primitive '+))
274 (@impl pget
275 (-> (lexical objvar objvar))
276 (-> (const prop)))
277 (-> (const 1))))
eb1482ac
AW
278 (lambda (tmpvar)
279 (@impl pput (-> (lexical objvar objvar))
280 (-> (const prop))
281 (-> (lexical tmpvar tmpvar))))))))
282 ((preinc (aref ,obj ,prop))
283 (let1 (comp obj e)
284 (lambda (objvar)
285 (let1 (comp prop e)
286 (lambda (propvar)
7081d4f9
AW
287 (begin1 (-> (call (-> (primitive '+))
288 (@impl pget
289 (-> (lexical objvar objvar))
290 (-> (lexical propvar propvar)))
291 (-> (const 1))))
eb1482ac
AW
292 (lambda (tmpvar)
293 (@impl pput
294 (-> (lexical objvar objvar))
295 (-> (lexical propvar propvar))
296 (-> (lexical tmpvar tmpvar))))))))))
297 ((predec (ref ,foo))
298 (let ((v (lookup foo e)))
299 (-> (begin
300 (-> (set! v
7081d4f9 301 (-> (call (-> (primitive '-))
eb1482ac
AW
302 v
303 (-> (const 1))))))
304 v))))
305 ((predec (pref ,obj ,prop))
306 (let1 (comp obj e)
307 (lambda (objvar)
7081d4f9
AW
308 (begin1 (-> (call (-> (primitive '-))
309 (@impl pget
310 (-> (lexical objvar objvar))
311 (-> (const prop)))
312 (-> (const 1))))
eb1482ac
AW
313 (lambda (tmpvar)
314 (@impl pput
315 (-> (lexical objvar objvar))
316 (-> (const prop))
317 (-> (lexical tmpvar tmpvar))))))))
318 ((predec (aref ,obj ,prop))
319 (let1 (comp obj e)
320 (lambda (objvar)
321 (let1 (comp prop e)
322 (lambda (propvar)
7081d4f9
AW
323 (begin1 (-> (call (-> (primitive '-))
324 (@impl pget
325 (-> (lexical objvar objvar))
326 (-> (lexical propvar propvar)))
327 (-> (const 1))))
eb1482ac
AW
328 (lambda (tmpvar)
329 (@impl pput
330 (-> (lexical objvar objvar))
331 (-> (lexical propvar propvar))
332 (-> (lexical tmpvar tmpvar))))))))))
333 ((ref ,id)
334 (lookup id e))
335 ((var . ,forms)
d61e866c
AW
336 `(begin
337 ,@(map (lambda (form)
338 (pmatch form
339 ((,x ,y)
340 (-> (define x (comp y e))))
341 ((,x)
342 (-> (define x (@implv *undefined*))))
343 (else (error "bad var form" form))))
344 forms)))
345 ((begin)
346 (-> (void)))
347 ((begin ,form)
348 (comp form e))
eb1482ac
AW
349 ((begin . ,forms)
350 `(begin ,@(map (lambda (x) (comp x e)) forms)))
351 ((lambda ,formals ,body)
7e01997e
AW
352 (let ((syms (map (lambda (x)
353 (gensym (string-append (symbol->string x) " ")))
354 formals)))
d61e866c
AW
355 `(lambda ()
356 (lambda-case
1e2a8edb 357 ((() ,formals #f #f ,(map (lambda (x) (@implv *undefined*)) formals) ,syms)
c0cfa9ef
AW
358 ,(with-return-prompt
359 (lambda ()
360 (comp-body e body formals syms))))))))
eb1482ac
AW
361 ((call/this ,obj ,prop . ,args)
362 (@impl call/this*
363 obj
7e01997e 364 (-> (lambda '()
d61e866c 365 `(lambda-case
1e2a8edb 366 ((() #f #f #f () ())
7081d4f9 367 (call ,(@impl pget obj prop) ,@args)))))))
eb1482ac
AW
368 ((call (pref ,obj ,prop) ,args)
369 (comp `(call/this ,(comp obj e)
370 ,(-> (const prop))
371 ,@(map (lambda (x) (comp x e)) args))
372 e))
373 ((call (aref ,obj ,prop) ,args)
374 (comp `(call/this ,(comp obj e)
375 ,(comp prop e)
376 ,@(map (lambda (x) (comp x e)) args))
377 e))
378 ((call ,proc ,args)
7081d4f9
AW
379 `(call ,(comp proc e)
380 ,@(map (lambda (x) (comp x e)) args)))
eb1482ac 381 ((return ,expr)
c0cfa9ef 382 (return (comp expr e)))
eb1482ac 383 ((array . ,args)
7081d4f9
AW
384 `(call ,(@implv new-array)
385 ,@(map (lambda (x) (comp x e)) args)))
eb1482ac 386 ((object . ,args)
7081d4f9
AW
387 `(call ,(@implv new-object)
388 ,@(map (lambda (x)
389 (pmatch x
390 ((,prop ,val)
391 (-> (call (-> (primitive 'cons))
392 (-> (const prop))
393 (comp val e))))
394 (else
395 (error "bad prop-val pair" x))))
396 args)))
eb1482ac
AW
397 ((pref ,obj ,prop)
398 (@impl pget
399 (comp obj e)
400 (-> (const prop))))
401 ((aref ,obj ,index)
402 (@impl pget
403 (comp obj e)
404 (comp index e)))
405 ((= (ref ,name) ,val)
406 (let ((v (lookup name e)))
407 (-> (begin
408 (-> (set! v (comp val e)))
409 v))))
410 ((= (pref ,obj ,prop) ,val)
411 (@impl pput
412 (comp obj e)
413 (-> (const prop))
414 (comp val e)))
415 ((= (aref ,obj ,prop) ,val)
416 (@impl pput
417 (comp obj e)
418 (comp prop e)
419 (comp val e)))
420 ((+= ,what ,val)
421 (comp `(= ,what (+ ,what ,val)) e))
422 ((-= ,what ,val)
423 (comp `(= ,what (- ,what ,val)) e))
424 ((/= ,what ,val)
425 (comp `(= ,what (/ ,what ,val)) e))
426 ((*= ,what ,val)
427 (comp `(= ,what (* ,what ,val)) e))
428 ((%= ,what ,val)
429 (comp `(= ,what (% ,what ,val)) e))
430 ((>>= ,what ,val)
431 (comp `(= ,what (>> ,what ,val)) e))
432 ((<<= ,what ,val)
433 (comp `(= ,what (<< ,what ,val)) e))
434 ((>>>= ,what ,val)
435 (comp `(= ,what (>>> ,what ,val)) e))
436 ((&= ,what ,val)
437 (comp `(= ,what (& ,what ,val)) e))
438 ((bor= ,what ,val)
439 (comp `(= ,what (bor ,what ,val)) e))
440 ((^= ,what ,val)
441 (comp `(= ,what (^ ,what ,val)) e))
442 ((new ,what ,args)
443 (@impl new
444 (map (lambda (x) (comp x e))
445 (cons what args))))
446 ((delete (pref ,obj ,prop))
447 (@impl pdel
448 (comp obj e)
449 (-> (const prop))))
450 ((delete (aref ,obj ,prop))
451 (@impl pdel
452 (comp obj e)
453 (comp prop e)))
454 ((void ,expr)
455 (-> (begin
456 (comp expr e)
457 (@implv *undefined*))))
458 ((typeof ,expr)
459 (@impl typeof
460 (comp expr e)))
461 ((do ,statement ,test)
462 (let ((%loop (gensym "%loop "))
463 (%continue (gensym "%continue ")))
464 (let ((e (econs '%loop %loop (econs '%continue %continue e))))
465 (-> (letrec '(%loop %continue) (list %loop %continue)
7e01997e
AW
466 (list (-> (lambda '()
467 (-> (lambda-case
1e2a8edb 468 `((() #f #f #f () ())
7e01997e
AW
469 ,(-> (begin
470 (comp statement e)
7081d4f9 471 (-> (call (-> (lexical '%continue %continue)))))))))))
7e01997e
AW
472 (-> (lambda '()
473 (-> (lambda-case
1e2a8edb 474 `((() #f #f #f () ())
7e01997e 475 ,(-> (if (@impl ->boolean (comp test e))
7081d4f9 476 (-> (call (-> (lexical '%loop %loop))))
7e01997e 477 (@implv *undefined*)))))))))
7081d4f9 478 (-> (call (-> (lexical '%loop %loop)))))))))
eb1482ac
AW
479 ((while ,test ,statement)
480 (let ((%continue (gensym "%continue ")))
481 (let ((e (econs '%continue %continue e)))
482 (-> (letrec '(%continue) (list %continue)
7e01997e
AW
483 (list (-> (lambda '()
484 (-> (lambda-case
1e2a8edb 485 `((() #f #f #f () ())
7e01997e
AW
486 ,(-> (if (@impl ->boolean (comp test e))
487 (-> (begin (comp statement e)
7081d4f9 488 (-> (call (-> (lexical '%continue %continue))))))
7e01997e 489 (@implv *undefined*)))))))))
7081d4f9 490 (-> (call (-> (lexical '%continue %continue)))))))))
eb1482ac
AW
491
492 ((for ,init ,test ,inc ,statement)
493 (let ((%continue (gensym "%continue ")))
494 (let ((e (econs '%continue %continue e)))
495 (-> (letrec '(%continue) (list %continue)
7e01997e
AW
496 (list (-> (lambda '()
497 (-> (lambda-case
1e2a8edb 498 `((() #f #f #f () ())
7e01997e
AW
499 ,(-> (if (if test
500 (@impl ->boolean (comp test e))
501 (comp 'true e))
502 (-> (begin (comp statement e)
503 (comp (or inc '(begin)) e)
7081d4f9 504 (-> (call (-> (lexical '%continue %continue))))))
7e01997e 505 (@implv *undefined*)))))))))
eb1482ac 506 (-> (begin (comp (or init '(begin)) e)
7081d4f9 507 (-> (call (-> (lexical '%continue %continue)))))))))))
eb1482ac
AW
508
509 ((for-in ,var ,object ,statement)
510 (let ((%enum (gensym "%enum "))
511 (%continue (gensym "%continue ")))
512 (let ((e (econs '%enum %enum (econs '%continue %continue e))))
513 (-> (letrec '(%enum %continue) (list %enum %continue)
514 (list (@impl make-enumerator (comp object e))
7e01997e
AW
515 (-> (lambda '()
516 (-> (lambda-case
1e2a8edb 517 `((() #f #f #f () ())
7e01997e
AW
518 (-> (if (@impl ->boolean
519 (@impl pget
520 (-> (lexical '%enum %enum))
521 (-> (const 'length))))
522 (-> (begin
523 (comp `(= ,var (call/this ,(-> (lexical '%enum %enum))
524 ,(-> (const 'pop))))
525 e)
526 (comp statement e)
7081d4f9 527 (-> (call (-> (lexical '%continue %continue))))))
7e01997e 528 (@implv *undefined*)))))))))
7081d4f9 529 (-> (call (-> (lexical '%continue %continue)))))))))
eb1482ac
AW
530
531 ((block ,x)
532 (comp x e))
533 (else
534 (error "compilation not yet implemented:" x)))))
535
7e01997e 536(define (comp-body e body formals formal-syms)
eb1482ac 537 (define (process)
7e01997e 538 (let lp ((in body) (out '()) (rvars '()))
eb1482ac
AW
539 (pmatch in
540 (((var (,x) . ,morevars) . ,rest)
541 (lp `((var . ,morevars) . ,rest)
542 out
7e01997e
AW
543 (if (or (memq x rvars) (memq x formals))
544 rvars
545 (cons x rvars))))
eb1482ac
AW
546 (((var (,x ,y) . ,morevars) . ,rest)
547 (lp `((var . ,morevars) . ,rest)
548 `((= (ref ,x) ,y) . ,out)
7e01997e
AW
549 (if (or (memq x rvars) (memq x formals))
550 rvars
551 (cons x rvars))))
eb1482ac
AW
552 (((var) . ,rest)
553 (lp rest out rvars))
554 ((,x . ,rest) (guard (and (pair? x) (eq? (car x) 'lambda)))
555 (lp rest
556 (cons x out)
557 rvars))
558 ((,x . ,rest) (guard (pair? x))
559 (receive (sub-out rvars)
560 (lp x '() rvars)
561 (lp rest
562 (cons sub-out out)
563 rvars)))
564 ((,x . ,rest)
565 (lp rest
566 (cons x out)
567 rvars))
568 (()
569 (values (reverse! out)
570 rvars)))))
571 (receive (out rvars)
572 (process)
573 (let* ((names (reverse rvars))
574 (syms (map (lambda (x)
575 (gensym (string-append (symbol->string x) " ")))
576 names))
7e01997e 577 (e (fold econs (fold econs e formals formal-syms) names syms)))
d61e866c 578 (-> (let names syms (map (lambda (x) (@implv *undefined*)) names)
7e01997e 579 (comp out e))))))