(module aspect-scheme mzscheme
(require (rename (lib "list.ss") foldr foldr))
(define (c-c-m key)
(continuation-mark-set->list
(current-continuation-marks)
key))
(define-syntax (w-c-m stx)
(syntax-case stx ()
[(_ tag mark body)
(syntax ((lambda (x) x)
(with-continuation-mark tag mark body)))]))
(define-struct aspect (pc adv))
(define (current-aspects)
(append (current-dynamic-aspects)
(current-static-aspects)))
(define-syntax (fluid-around stx)
(syntax-case stx ()
[(_ pc adv body)
(syntax (w-c-m 'dynamic-aspect (make-aspect pc adv)
body))]))
(define-syntax (app/weave stx)
(syntax-case stx ()
[(_ f a ...) (syntax (app/weave/rt f a ...))]))
(define (app/weave/rt fun-val . arg-vals)
(if (primitive? fun-val)
(apply fun-val arg-vals)
(w-c-m 'joinpoint fun-val
(apply (weave fun-val (c-c-m 'joinpoint) (current-aspects))
arg-vals))))
(define (weave fun-val jp* aspects)
(foldr (lambda (a r)
(if ((aspect-pc a) jp*)
(lambda vs
(apply ((aspect-adv a) r) vs))
r))
fun-val
aspects))
(define (current-dynamic-aspects)
(c-c-m 'dynamic-aspect))
(define-syntax (around stx)
(syntax-case stx ()
[(_ pc adv body)
(syntax (w-c-m 'static-aspect
(cons (make-aspect pc adv)
(current-static-aspects))
body))]))
(define-syntax (lambda/static stx)
(syntax-case stx ()
[(_ params body ...)
(syntax
(let ([env (current-static-aspects)])
(lambda params
(w-c-m 'static-aspect env
(begin body ...)))))]))
(define (current-static-aspects)
(let ([aspectss (c-c-m 'static-aspect)])
(if (null? aspectss)
'()
(car aspectss))))
(define (call f)
(lambda (jp*)
(eq? f (car jp*))))
(define (top)
(lambda (jp*)
(null? jp*)))
(define (below pc)
(lambda (jp*)
(and (not (null? (cdr jp*)))
(pc (cdr jp*)))))
(define (&& . pcs)
(lambda (jp*)
(andmap (lambda (pc) (pc jp*)) pcs)))
(define (|| . pcs)
(lambda (jp*)
(ormap (lambda (pc) (pc jp*)) pcs)))
(define (! pc)
(lambda (jp*)
(not (pc jp*))))
(define (within f)
(below (call f)))
(define (cflow pc)
(&& (! top)
(|| pc
(cflowbelow pc))))
(define (cflowbelow pc)
(&& (! top)
(below (cflow pc))))
(provide (all-from-except mzscheme #%app lambda)
(rename app/weave #%app)
(rename #%app app/prim)
fluid-around
(rename lambda/static lambda)
around
call top below && || ! within cflow cflowbelow))