1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-17 09:10:22 +02:00

Rebuild nested scopes for js continuations

* module/language/cps/compile-js.scm (compile-cont, compile-clause):
  Rebuild nested scopes for $kargs, using dominator information.
  (compile-fun, compile-clauses): Pass down dominator information.
This commit is contained in:
Ian Price 2017-06-20 19:05:59 +01:00
parent 936050c657
commit c2589b5c48

View file

@ -5,6 +5,7 @@
#:use-module ((language js-il)
#:renamer (lambda (x) (if (eqv? x 'make-prompt) 'make-prompt* x)))
#:use-module (ice-9 match)
#:use-module ((srfi srfi-1) #:select (append-map))
#:export (compile-js))
(define intmap-select (@@ (language cps compile-bytecode) intmap-select))
@ -27,12 +28,13 @@
(define (compile-fun cps kfun)
(define doms (compute-dom-edges (compute-idoms cps kfun)))
(match (intmap-ref cps kfun)
(($ $kfun src meta self tail clause)
(make-function
(make-id self)
(make-kid tail)
(compile-clauses cps clause self)))))
(compile-clauses cps doms clause self)))))
(define (extract-and-compile-conts cps)
@ -57,22 +59,21 @@
(intmap-fold step cps '()))
(define (compile-clauses cps clause self)
(define (compile-clauses cps doms clause self)
;; FIXME: This duplicates all the conts in each clause, and requires
;; the inliner to remove them. A better solution is to change the
;; function type to contain a separate map of conts, but this requires
;; more code changes, and is should constitute a separate commit.
(define function-conts (extract-and-compile-conts cps))
(let loop ((clause clause))
(match (intmap-ref cps clause)
(($ $kclause arity body #f)
`((,(make-kid clause)
,(arity->params arity self)
,(compile-clause cps arity body self function-conts))))
,(compile-clause cps doms arity body self))))
(($ $kclause arity body next)
`((,(make-kid clause)
,(arity->params arity self)
,(compile-clause cps arity body self function-conts))
,(compile-clause cps doms arity body self))
. ,(loop next))))))
@ -91,27 +92,48 @@
allow-other-keys?))))
(define (compile-clause cps arity body self bindings)
(define (compile-clause cps doms arity body self)
(match arity
(($ $arity req opt rest ((_ _ kw-syms) ...) _)
(let ((ids (map make-id
(append req opt kw-syms (if rest (list rest) '())))))
(make-continuation
(cons (make-id self) ids)
(make-local bindings (make-continue (make-kid body) ids)))))))
(make-local (list (cons (make-kid body) (compile-cont cps doms body)))
(make-continue (make-kid body) ids)))))))
(define (compile-cont cps cont)
(match (intmap-ref cps cont)
;; The term in a $kargs is always a $continue
(($ $kargs names syms ($ $continue k src exp))
(make-continuation (map make-id syms) (compile-exp exp k)))
(($ $kreceive ($ $arity req _ (? symbol? rest) _ _) k2)
(let ((ids (map make-id (append req (list rest)))))
(make-continuation ids (make-continue (make-kid k2) ids))))
(($ $kreceive ($ $arity req _ #f _ _) k2)
(let ((ids (map make-id req)))
(make-continuation ids (make-continue (make-kid k2) ids))))))
(define (compile-cont cps doms cont)
(define (redominate label exp)
;; This ensures that functions which are dominated by a $kargs [e.g.
;; because they need its arguments] are moved into its body, and so
;; we get correct scoping.
(define (find&compile-dominated label)
(append-map (lambda (label)
(match (intmap-ref cps label)
(($ $ktail) '()) ; ignore tails
(($ $kargs)
;; kargs may bind more arguments
(list (cons (make-kid label) (compile label))))
(else
;; otherwise, even if it dominates other conts,
;; it doesn't need to contain them
(cons (cons (make-kid label) (compile label))
(find&compile-dominated label)))))
(intmap-ref doms label)))
(make-local (find&compile-dominated label) exp))
(define (compile cont)
(match (intmap-ref cps cont)
;; The term in a $kargs is always a $continue
(($ $kargs names syms ($ $continue k src exp))
(make-continuation (map make-id syms)
(redominate cont (compile-exp exp k))))
(($ $kreceive ($ $arity req _ (? symbol? rest) _ _) k2)
(let ((ids (map make-id (append req (list rest)))))
(make-continuation ids (make-continue (make-kid k2) ids))))
(($ $kreceive ($ $arity req _ #f _ _) k2)
(let ((ids (map make-id req)))
(make-continuation ids (make-continue (make-kid k2) ids))))))
(compile cont))
(define (compile-exp exp k)
(match exp