(module aspect-scheme2 mzscheme
(require (only (lib "list.ss") foldl foldr))
(define-syntaxes (let~ let*~ letrec~)
(let* ([process (lambda (stx var0 val0 . flat?)
(syntax-case var0 (values)
[(values var ...) (null? flat?) #`((var ...) . #,val0)]
[_ (let loop ([var var0] [args '()])
(if (identifier? var)
(if (null? args)
(let ([val (syntax->list val0)])
(if (and (pair? val) (null? (cdr val)))
(list (if (null? flat?) (list var) var) (car val))
(raise-syntax-error #f "bad binding" stx #`(#,var0 #,@val0))))
(let ([sym (syntax-e var)])
(let loop ([i (sub1 (length args))]
[as (reverse args)]
[val val0])
(if (< i 0)
(list (if (null? flat?) (list var) var)
(car (syntax->list val)))
(loop (sub1 i) (cdr as)
(let ([val #`((lambda #,(car as) #,@val))])
(if (zero? i)
val
(syntax-property val
'inferred-name
(if (zero? i)
sym
(string->symbol
(format "~a:~a" sym i)))))))))))
(syntax-case var ()
[(var . args1) (loop #'var (cons #'args1 args))])))]))]
[mk-bindings
(lambda (stx bindings . flat?)
(syntax-case bindings ()
[((var val more ...) ...)
(datum->syntax-object #'bindings
(map (lambda (x y) (apply process stx x y flat?))
(syntax->list #'(var ...))
(syntax->list #'((val more ...) ...)))
#'bindings)]))]
[mk-let
(lambda (tag . lbl)
(lambda (stx)
(syntax-case stx ()
[(_ label bindings body0 body ...)
(and (identifier? #'label) (pair? lbl))
(quasisyntax/loc stx
(#,(car lbl) label #,(mk-bindings stx #'bindings #t) body0 body ...))]
[(_ bindings body0 body ...)
(quasisyntax/loc stx
(#,tag #,(mk-bindings stx #'bindings) body0 body ...))])))])
(values (mk-let #'let-values #'let)
(mk-let #'let*-values)
(mk-let #'letrec-values))))
(define-struct aspect (pc adv))
(define-struct jp (target args))
(define-struct (call-jp jp)( ))
(define-struct (exec-jp jp)( ))
(define-struct (adv-jp jp)( ))
(define-syntax fluid-let-parameter
(syntax-rules ()
[(_ ([p v]) e ...)
(let ([y v])
(let ([swap (lambda ()
(let ([t (p)])
(p y)
(set! y t)))])
(dynamic-wind swap
(lambda () e ...)
swap)))]))
(define dynamic-aspects (make-parameter '()))
(define static-aspects (make-parameter '()))
(define-syntaxes (fluid-around around)
(let ([round (lambda (param)
(lambda (stx)
(syntax-case stx ()
[(_ pc adv body0 ...)
(quasisyntax/loc stx
(fluid-let-parameter ([#,param (cons (make-aspect pc adv) (#,param))])
body0 ...))])))])
(values (round #`dynamic-aspects) (round #`static-aspects))))
(define-syntax lambda/static
(syntax-rules ()
[(_ params body ...)
(let ([aspects (static-aspects)])
(lambda params
(fluid-let-parameter ([static-aspects aspects])
body ...)))]))
(define toplevel-aspects (make-parameter '()))
(define (toplevel-around pc adv)
(toplevel-aspects (cons (make-aspect pc adv) (toplevel-aspects))))
(define (current-aspects)
(append (dynamic-aspects)
(static-aspects)
(toplevel-aspects)))
(define (jp-context)
(continuation-mark-set->list
(current-continuation-marks)
'joinpoint))
(define-syntax with-joinpoint
(syntax-rules ()
[(_ jp body ...)
((lambda (x) x)
(with-continuation-mark 'joinpoint jp
(begin body ...)))]))
(define-syntax app/weave
(syntax-rules ()
[(_ f a ...) (app/weave/rt f a ...)]))
(define (app/weave/rt fun-val . arg-vals)
(if (primitive? fun-val)
(apply fun-val arg-vals)
(let ([jp (make-call-jp fun-val arg-vals)])
(with-joinpoint jp
(apply (weave (lambda arg-vals
(with-joinpoint (make-exec-jp fun-val arg-vals)
(apply fun-val arg-vals)))
'() jp (jp-context)
(current-aspects))
arg-vals)))))
(define (weave fun-val jp- jp jp+ aspects)
(foldr (lambda (aspect fun)
(cond
[((aspect-pc aspect) jp- jp jp+)
=> (lambda (ctxt-vals)
(with-joinpoint (make-adv-jp (aspect-adv aspect) ctxt-vals)
(apply ((aspect-adv aspect) fun) ctxt-vals)))]
[else fun]))
fun-val
aspects))
(define ((&& . pcs) jp- jp jp+)
(let loop ([pcs pcs]
[res '()])
(if (null? pcs)
(reverse res)
(let ([r ((car pcs) jp- jp jp+)])
(and r
(loop (cdr pcs) (append (reverse r) res)))))))
(define ((|| . pcs) jp- jp jp+)
(let loop ([pcs pcs])
(and (not (null? pcs))
(or ((car pcs) jp- jp jp+)
(loop (cdr pcs))))))
(define ((! pc) jp- jp jp+)
(and (not (pc jp- jp jp+))
'()))
(define (top? jp- jp jp+)
(and (null? jp+)
'()))
(define (top pc)
(&& pc
(! (cflowbelow pc))))
(define ((below pc) jp- jp jp+)
(and (not (null? jp+))
(pc (cons jp jp-) (car jp+) (cdr jp+))))
(define ((above pc) jp- jp jp+)
(and (not (null? jp-))
(pc (cdr jp-) (car jp-) (cons jp jp+))))
(define (bottom pc)
(&& pc
(! (cflowabove pc))))
(define (bottom? jp- jp jp+)
(and (null? jp-)
'()))
(define (target jp- jp jp+)
(list (jp-target jp)))
(define (args jp- jp jp+)
(jp-args jp))
(define ((some-args as) jp- jp jp+)
(foldl (lambda (a v l)
(if a
(cons v l)
l))
'()
as
(jp-args jp)))
(define ((kind= k?) jp- jp jp+)
(and (k? jp)
'()))
(define call? (kind= call-jp?))
(define exec? (kind= exec-jp?))
(define adv? (kind= adv-jp?))
(define ((target= f) jp- jp jp+)
(and (eq? f (jp-target jp))
'()))
(define (call f)
(&& call?
(target= f)))
(define (exec f)
(&& exec?
(target= f)))
(define (adv a)
(&& adv?
(target= a)))
(define (((cflow-walk step end) pc) jp- jp jp+)
((|| pc
(&& (! end)
(step ((cflow-walk step end) pc)))) jp- jp jp+))
(define (cflowtop pc)
(cflowbelow (top pc)))
(define (cflowbelow pc)
(below ((cflow-walk below top?) pc)))
(define (cflowabove pc)
(above ((cflow-walk above bottom) pc)))
(define (cflowbottom pc)
(cflowbelow (bottom pc)))
(define (cflow pc)
((cflow-walk below top?) pc))
(define (within f)
(cflowbelow (&& (exec f)
(! (cflowabove call?)))))
(provide (all-from-except mzscheme let
let*
letrec
#%app
lambda)
(rename let~ let)
(rename let*~ let*)
(rename letrec~ letrec)
(rename app/weave #%app)
(rename #%app app/prim)
fluid-around
(rename lambda/static lambda)
around
toplevel-around
&& || !
top? top below above bottom bottom?
target args some-args
call? exec? adv? call exec adv
cflowtop cflowbelow cflowbottom cflowabove
cflow within
))