2014-07-19 01:59:34 -04:00
|
|
|
;;; Hygienic Macros
|
|
|
|
|
|
|
|
(define-library (picrin macro)
|
2014-08-05 13:07:02 -04:00
|
|
|
(import (picrin base macro)
|
|
|
|
(picrin base)
|
|
|
|
(picrin list)
|
2014-08-05 13:14:43 -04:00
|
|
|
(picrin symbol)
|
2014-08-05 12:14:43 -04:00
|
|
|
(scheme base)
|
2014-07-19 01:59:34 -04:00
|
|
|
(picrin dictionary))
|
|
|
|
|
|
|
|
;; assumes no derived expressions are provided yet
|
|
|
|
|
|
|
|
(define (walk proc expr)
|
2014-07-19 05:15:38 -04:00
|
|
|
"walk on symbols"
|
2014-07-19 01:59:34 -04:00
|
|
|
(if (null? expr)
|
|
|
|
'()
|
|
|
|
(if (pair? expr)
|
|
|
|
(cons (walk proc (car expr))
|
|
|
|
(walk proc (cdr expr)))
|
|
|
|
(if (vector? expr)
|
2014-07-19 05:26:09 -04:00
|
|
|
(list->vector (walk proc (vector->list expr)))
|
2014-07-19 05:15:38 -04:00
|
|
|
(if (symbol? expr)
|
|
|
|
(proc expr)
|
|
|
|
expr)))))
|
2014-07-19 01:59:34 -04:00
|
|
|
|
2014-07-19 05:26:03 -04:00
|
|
|
(define (memoize f)
|
2014-07-26 03:20:26 -04:00
|
|
|
"memoize on symbols"
|
2014-07-19 05:26:03 -04:00
|
|
|
(define cache (make-dictionary))
|
|
|
|
(lambda (sym)
|
2014-08-29 10:57:55 -04:00
|
|
|
(call-with-values (lambda () (dictionary-ref cache sym))
|
|
|
|
(lambda (value exists)
|
|
|
|
(if exists
|
|
|
|
value
|
|
|
|
(begin
|
|
|
|
(define val (f sym))
|
|
|
|
(dictionary-set! cache sym val)
|
|
|
|
val))))))
|
2014-07-19 05:14:11 -04:00
|
|
|
|
|
|
|
(define (make-syntactic-closure env free form)
|
2014-07-19 05:26:03 -04:00
|
|
|
|
|
|
|
(define resolve
|
|
|
|
(memoize
|
|
|
|
(lambda (sym)
|
|
|
|
(make-identifier sym env))))
|
|
|
|
|
2014-07-19 05:15:38 -04:00
|
|
|
(walk
|
2014-07-19 05:14:11 -04:00
|
|
|
(lambda (sym)
|
|
|
|
(if (memq sym free)
|
|
|
|
sym
|
2014-07-19 05:26:03 -04:00
|
|
|
(resolve sym)))
|
2014-07-19 01:59:34 -04:00
|
|
|
form))
|
|
|
|
|
|
|
|
(define (close-syntax form env)
|
|
|
|
(make-syntactic-closure env '() form))
|
|
|
|
|
|
|
|
(define-syntax capture-syntactic-environment
|
|
|
|
(lambda (form use-env mac-env)
|
|
|
|
(list (cadr form) (list (make-identifier 'quote mac-env) mac-env))))
|
|
|
|
|
|
|
|
(define (sc-macro-transformer f)
|
|
|
|
(lambda (expr use-env mac-env)
|
|
|
|
(make-syntactic-closure mac-env '() (f expr use-env))))
|
|
|
|
|
|
|
|
(define (rsc-macro-transformer f)
|
|
|
|
(lambda (expr use-env mac-env)
|
|
|
|
(make-syntactic-closure use-env '() (f expr mac-env))))
|
|
|
|
|
|
|
|
(define (er-macro-transformer f)
|
|
|
|
(lambda (expr use-env mac-env)
|
|
|
|
|
2014-07-19 05:26:03 -04:00
|
|
|
(define rename
|
|
|
|
(memoize
|
|
|
|
(lambda (sym)
|
|
|
|
(make-identifier sym mac-env))))
|
2014-07-19 01:59:34 -04:00
|
|
|
|
|
|
|
(define (compare x y)
|
|
|
|
(if (not (symbol? x))
|
|
|
|
#f
|
|
|
|
(if (not (symbol? y))
|
|
|
|
#f
|
|
|
|
(identifier=? use-env x use-env y))))
|
|
|
|
|
|
|
|
(f expr rename compare)))
|
|
|
|
|
|
|
|
(define (ir-macro-transformer f)
|
|
|
|
(lambda (expr use-env mac-env)
|
|
|
|
|
2014-07-19 05:10:14 -04:00
|
|
|
(define icache* (make-dictionary))
|
|
|
|
|
2014-07-19 05:26:03 -04:00
|
|
|
(define inject
|
|
|
|
(memoize
|
|
|
|
(lambda (sym)
|
|
|
|
(define id (make-identifier sym use-env))
|
|
|
|
(dictionary-set! icache* id sym)
|
|
|
|
id)))
|
|
|
|
|
|
|
|
(define rename
|
|
|
|
(memoize
|
|
|
|
(lambda (sym)
|
|
|
|
(make-identifier sym mac-env))))
|
2014-07-19 05:10:14 -04:00
|
|
|
|
|
|
|
(define (compare x y)
|
|
|
|
(if (not (symbol? x))
|
|
|
|
#f
|
|
|
|
(if (not (symbol? y))
|
|
|
|
#f
|
|
|
|
(identifier=? mac-env x mac-env y))))
|
2014-07-19 01:59:34 -04:00
|
|
|
|
2014-07-19 05:28:10 -04:00
|
|
|
(walk (lambda (sym)
|
2014-08-29 10:57:55 -04:00
|
|
|
(call-with-values (lambda () (dictionary-ref icache* sym))
|
|
|
|
(lambda (value exists)
|
|
|
|
(if exists
|
|
|
|
value
|
|
|
|
(rename sym)))))
|
2014-07-19 05:28:10 -04:00
|
|
|
(f (walk inject expr) inject compare))))
|
2014-07-19 01:59:34 -04:00
|
|
|
|
2014-07-26 01:13:12 -04:00
|
|
|
(define (strip-syntax form)
|
|
|
|
(walk ungensym form))
|
|
|
|
|
2014-07-19 22:11:39 -04:00
|
|
|
(define-syntax define-macro
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr r c)
|
|
|
|
(define formal (car (cdr expr)))
|
|
|
|
(define body (cdr (cdr expr)))
|
|
|
|
(if (symbol? formal)
|
|
|
|
(list (r 'define-syntax) formal
|
|
|
|
(list (r 'lambda) (list (r 'form) '_ '_)
|
|
|
|
(list (r 'apply) (car body) (list (r 'cdr) (r 'form)))))
|
|
|
|
(list (r 'define-macro) (car formal)
|
|
|
|
(cons (r 'lambda)
|
|
|
|
(cons (cdr formal)
|
|
|
|
body)))))))
|
|
|
|
|
2014-08-05 12:46:11 -04:00
|
|
|
(export identifier?
|
|
|
|
identifier=?
|
|
|
|
make-identifier
|
2014-07-26 01:54:44 -04:00
|
|
|
make-syntactic-closure
|
2014-07-19 01:59:34 -04:00
|
|
|
close-syntax
|
|
|
|
capture-syntactic-environment
|
|
|
|
sc-macro-transformer
|
|
|
|
rsc-macro-transformer
|
|
|
|
er-macro-transformer
|
2014-07-19 22:11:39 -04:00
|
|
|
ir-macro-transformer
|
2014-07-26 01:13:12 -04:00
|
|
|
strip-syntax
|
2014-07-19 22:11:39 -04:00
|
|
|
define-macro))
|