2013-12-10 12:14:08 -05:00
|
|
|
;;; core syntaces
|
|
|
|
(define-library (picrin core-syntax)
|
|
|
|
(import (scheme base)
|
2014-02-08 13:17:51 -05:00
|
|
|
(picrin macro))
|
2013-12-10 12:14:08 -05:00
|
|
|
|
2014-07-19 00:22:24 -04:00
|
|
|
(define-syntax syntax-error
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr rename compare)
|
|
|
|
(apply error (cdr expr)))))
|
|
|
|
|
2014-07-16 22:32:52 -04:00
|
|
|
(define-syntax define-auxiliary-syntax
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr r c)
|
|
|
|
(list (r 'define-syntax) (cadr expr)
|
|
|
|
(list (r 'lambda) '_
|
|
|
|
(list (r 'error) "invalid use of auxiliary syntax"))))))
|
|
|
|
|
|
|
|
(define-auxiliary-syntax else)
|
|
|
|
(define-auxiliary-syntax =>)
|
|
|
|
(define-auxiliary-syntax _)
|
|
|
|
(define-auxiliary-syntax ...)
|
|
|
|
(define-auxiliary-syntax unquote)
|
|
|
|
(define-auxiliary-syntax unquote-splicing)
|
|
|
|
|
2013-12-10 06:09:27 -05:00
|
|
|
(define-syntax let
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr r compare)
|
2014-01-10 22:56:51 -05:00
|
|
|
(if (symbol? (cadr expr))
|
2013-12-10 06:09:27 -05:00
|
|
|
(begin
|
2014-07-19 01:25:22 -04:00
|
|
|
(define name (car (cdr expr)))
|
|
|
|
(define bindings (car (cdr (cdr expr))))
|
|
|
|
(define body (cdr (cdr (cdr expr))))
|
2013-12-10 06:09:27 -05:00
|
|
|
(list (r 'let) '()
|
|
|
|
(list (r 'define) name
|
|
|
|
(cons (r 'lambda) (cons (map car bindings) body)))
|
|
|
|
(cons name (map cadr bindings))))
|
|
|
|
(begin
|
2014-02-07 13:18:13 -05:00
|
|
|
(set! bindings (cadr expr))
|
|
|
|
(set! body (cddr expr))
|
2013-12-10 06:09:27 -05:00
|
|
|
(cons (cons (r 'lambda) (cons (map car bindings) body))
|
|
|
|
(map cadr bindings)))))))
|
|
|
|
|
|
|
|
(define-syntax cond
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr r compare)
|
|
|
|
(let ((clauses (cdr expr)))
|
|
|
|
(if (null? clauses)
|
|
|
|
#f
|
2014-07-19 01:25:22 -04:00
|
|
|
(begin
|
|
|
|
(define clause (car clauses))
|
|
|
|
(if (compare (r 'else) (car clause))
|
|
|
|
(cons (r 'begin) (cdr clause))
|
|
|
|
(if (if (>= (length clause) 2)
|
|
|
|
(compare (r '=>) (list-ref clause 1))
|
|
|
|
#f)
|
|
|
|
(list (r 'let) (list (list (r 'x) (car clause)))
|
|
|
|
(list (r 'if) (r 'x)
|
|
|
|
(list (list-ref clause 2) (r 'x))
|
|
|
|
(cons (r 'cond) (cdr clauses))))
|
|
|
|
(list (r 'if) (car clause)
|
|
|
|
(cons (r 'begin) (cdr clause))
|
|
|
|
(cons (r 'cond) (cdr clauses)))))))))))
|
2013-12-10 06:09:27 -05:00
|
|
|
|
|
|
|
(define-syntax and
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr r compare)
|
|
|
|
(let ((exprs (cdr expr)))
|
2014-02-11 07:35:56 -05:00
|
|
|
(cond
|
|
|
|
((null? exprs)
|
|
|
|
#t)
|
2014-07-19 00:22:24 -04:00
|
|
|
((= (length exprs) 1)
|
2014-02-11 07:35:56 -05:00
|
|
|
(car exprs))
|
|
|
|
(else
|
|
|
|
(list (r 'let) (list (list (r 'it) (car exprs)))
|
|
|
|
(list (r 'if) (r 'it)
|
|
|
|
(cons (r 'and) (cdr exprs))
|
|
|
|
(r 'it)))))))))
|
2013-12-10 06:09:27 -05:00
|
|
|
|
|
|
|
(define-syntax or
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr r compare)
|
|
|
|
(let ((exprs (cdr expr)))
|
2014-02-11 07:35:56 -05:00
|
|
|
(cond
|
|
|
|
((null? exprs)
|
|
|
|
#t)
|
2014-07-19 00:22:24 -04:00
|
|
|
((= (length exprs) 1)
|
2014-02-11 07:35:56 -05:00
|
|
|
(car exprs))
|
|
|
|
(else
|
|
|
|
(list (r 'let) (list (list (r 'it) (car exprs)))
|
|
|
|
(list (r 'if) (r 'it)
|
|
|
|
(r 'it)
|
|
|
|
(cons (r 'or) (cdr exprs))))))))))
|
2013-12-10 02:00:47 -05:00
|
|
|
|
2013-12-10 06:09:27 -05:00
|
|
|
(define-syntax quasiquote
|
2014-02-12 08:31:17 -05:00
|
|
|
(ir-macro-transformer
|
|
|
|
(lambda (form inject compare)
|
|
|
|
|
2014-07-19 00:22:24 -04:00
|
|
|
(define (quasiquote? form)
|
|
|
|
(and (pair? form) (compare (car form) 'quasiquote)))
|
|
|
|
|
|
|
|
(define (unquote? form)
|
|
|
|
(and (pair? form) (compare (car form) 'unquote)))
|
|
|
|
|
|
|
|
(define (unquote-splicing? form)
|
|
|
|
(and (pair? form) (pair? (car form))
|
|
|
|
(compare (car (car form)) 'unquote-splicing)))
|
|
|
|
|
2014-02-12 08:31:17 -05:00
|
|
|
(define (qq depth expr)
|
2013-12-10 06:09:27 -05:00
|
|
|
(cond
|
2014-02-12 08:31:17 -05:00
|
|
|
;; unquote
|
2014-07-19 00:22:24 -04:00
|
|
|
((unquote? expr)
|
2014-02-12 08:31:17 -05:00
|
|
|
(if (= depth 1)
|
|
|
|
(car (cdr expr))
|
|
|
|
(list 'list
|
|
|
|
(list 'quote (inject 'unquote))
|
|
|
|
(qq (- depth 1) (car (cdr expr))))))
|
|
|
|
;; unquote-splicing
|
2014-07-19 00:22:24 -04:00
|
|
|
((unquote-splicing? expr)
|
2014-02-12 08:31:17 -05:00
|
|
|
(if (= depth 1)
|
|
|
|
(list 'append
|
|
|
|
(car (cdr (car expr)))
|
|
|
|
(qq depth (cdr expr)))
|
|
|
|
(list 'cons
|
|
|
|
(list 'list
|
|
|
|
(list 'quote (inject 'unquote-splicing))
|
|
|
|
(qq (- depth 1) (car (cdr (car expr)))))
|
|
|
|
(qq depth (cdr expr)))))
|
|
|
|
;; quasiquote
|
2014-07-19 00:22:24 -04:00
|
|
|
((quasiquote? expr)
|
2014-02-12 08:31:17 -05:00
|
|
|
(list 'list
|
|
|
|
(list 'quote (inject 'quasiquote))
|
|
|
|
(qq (+ depth 1) (car (cdr expr)))))
|
|
|
|
;; list
|
|
|
|
((pair? expr)
|
|
|
|
(list 'cons
|
|
|
|
(qq depth (car expr))
|
|
|
|
(qq depth (cdr expr))))
|
2014-06-28 06:43:49 -04:00
|
|
|
;; vector
|
|
|
|
((vector? expr)
|
|
|
|
(list 'list->vector (qq depth (vector->list expr))))
|
2014-02-12 08:31:17 -05:00
|
|
|
;; simple datum
|
|
|
|
(else
|
|
|
|
(list 'quote expr))))
|
|
|
|
|
|
|
|
(let ((x (cadr form)))
|
|
|
|
(qq 1 x)))))
|
2013-12-10 06:09:27 -05:00
|
|
|
|
|
|
|
#;
|
|
|
|
(define-syntax let*
|
|
|
|
(ir-macro-transformer
|
|
|
|
(lambda (form inject compare)
|
|
|
|
(let ((bindings (cadr form))
|
|
|
|
(body (cddr form)))
|
|
|
|
(if (null? bindings)
|
|
|
|
`(let () ,@body)
|
|
|
|
`(let ((,(caar bindings)
|
|
|
|
,@(cdar bindings)))
|
|
|
|
(let* (,@(cdr bindings))
|
|
|
|
,@body)))))))
|
|
|
|
|
|
|
|
(define-syntax let*
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form r compare)
|
|
|
|
(let ((bindings (cadr form))
|
|
|
|
(body (cddr form)))
|
|
|
|
(if (null? bindings)
|
|
|
|
`(,(r 'let) () ,@body)
|
|
|
|
`(,(r 'let) ((,(caar bindings)
|
|
|
|
,@(cdar bindings)))
|
|
|
|
(,(r 'let*) (,@(cdr bindings))
|
|
|
|
,@body)))))))
|
|
|
|
|
2013-12-10 11:37:33 -05:00
|
|
|
(define-syntax letrec*
|
2013-12-10 06:09:27 -05:00
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form r compare)
|
|
|
|
(let ((bindings (cadr form))
|
|
|
|
(body (cddr form)))
|
|
|
|
(let ((vars (map (lambda (v) `(,v #f)) (map car bindings)))
|
|
|
|
(initials (map (lambda (v) `(,(r 'set!) ,@v)) bindings)))
|
|
|
|
`(,(r 'let) (,@vars)
|
|
|
|
,@initials
|
|
|
|
,@body))))))
|
|
|
|
|
2013-12-10 11:37:33 -05:00
|
|
|
(define-syntax letrec
|
2013-12-10 06:09:27 -05:00
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form rename compare)
|
2013-12-10 11:37:33 -05:00
|
|
|
`(,(rename 'letrec*) ,@(cdr form)))))
|
2013-12-10 06:09:27 -05:00
|
|
|
|
|
|
|
(define-syntax do
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form r compare)
|
2014-07-19 01:25:22 -04:00
|
|
|
(let ((bindings (car (cdr form)))
|
|
|
|
(finish (car (cdr (cdr form))))
|
|
|
|
(body (cdr (cdr (cdr form)))))
|
2013-12-10 06:09:27 -05:00
|
|
|
`(,(r 'let) ,(r 'loop) ,(map (lambda (x)
|
|
|
|
(list (car x) (cadr x)))
|
|
|
|
bindings)
|
|
|
|
(,(r 'if) ,(car finish)
|
2014-01-08 06:18:44 -05:00
|
|
|
(,(r 'begin) ,@(cdr finish))
|
2013-12-10 06:09:27 -05:00
|
|
|
(,(r 'begin) ,@body
|
|
|
|
(,(r 'loop) ,@(map (lambda (x)
|
|
|
|
(if (null? (cddr x))
|
|
|
|
(car x)
|
|
|
|
(car (cddr x))))
|
2014-01-08 06:18:44 -05:00
|
|
|
bindings)))))))))
|
2013-12-10 06:09:27 -05:00
|
|
|
|
|
|
|
(define-syntax when
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr rename compare)
|
|
|
|
(let ((test (cadr expr))
|
|
|
|
(body (cddr expr)))
|
|
|
|
`(,(rename 'if) ,test
|
|
|
|
(,(rename 'begin) ,@body)
|
|
|
|
#f)))))
|
|
|
|
|
|
|
|
(define-syntax unless
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr rename compare)
|
|
|
|
(let ((test (cadr expr))
|
|
|
|
(body (cddr expr)))
|
|
|
|
`(,(rename 'if) ,test
|
|
|
|
#f
|
|
|
|
(,(rename 'begin) ,@body))))))
|
2013-12-10 02:00:47 -05:00
|
|
|
|
2013-12-10 04:48:53 -05:00
|
|
|
(define-syntax case
|
2013-12-10 06:09:27 -05:00
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (expr r compare)
|
2013-12-10 04:48:53 -05:00
|
|
|
(let ((key (cadr expr))
|
|
|
|
(clauses (cddr expr)))
|
2013-12-10 06:09:27 -05:00
|
|
|
`(,(r 'let) ((,(r 'key) ,key))
|
2013-12-10 04:48:53 -05:00
|
|
|
,(let loop ((clauses clauses))
|
|
|
|
(if (null? clauses)
|
|
|
|
#f
|
2014-07-19 01:25:22 -04:00
|
|
|
(begin
|
|
|
|
(define clause (car clauses))
|
|
|
|
`(,(r 'if) ,(if (compare (r 'else) (car clause))
|
|
|
|
'#t
|
|
|
|
`(,(r 'or)
|
|
|
|
,@(map (lambda (x)
|
|
|
|
`(,(r 'eqv?) ,(r 'key) (,(r 'quote) ,x)))
|
|
|
|
(car clause))))
|
|
|
|
,(if (compare (r '=>) (list-ref clause 1))
|
|
|
|
`(,(list-ref clause 2) ,(r 'key))
|
|
|
|
`(,(r 'begin) ,@(cdr clause)))
|
|
|
|
,(loop (cdr clauses)))))))))))
|
2013-12-10 04:48:53 -05:00
|
|
|
|
2014-07-16 01:30:45 -04:00
|
|
|
(define-syntax letrec-syntax
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form r c)
|
|
|
|
(let ((formal (car (cdr form)))
|
|
|
|
(body (cdr (cdr form))))
|
|
|
|
`(let ()
|
|
|
|
,@(map (lambda (x)
|
|
|
|
`(,(r 'define-syntax) ,(car x) ,(cadr x)))
|
|
|
|
formal)
|
|
|
|
,@body)))))
|
|
|
|
|
2014-07-20 01:55:17 -04:00
|
|
|
(define-syntax let-syntax
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form r c)
|
|
|
|
`(,(r 'letrec-syntax) ,@(cdr form)))))
|
|
|
|
|
2014-07-22 01:34:39 -04:00
|
|
|
(import (scheme read) (scheme file))
|
|
|
|
|
|
|
|
(define-syntax include
|
|
|
|
(letrec ((read-file
|
|
|
|
(lambda (filename)
|
|
|
|
(let ((port (open-input-file filename)))
|
|
|
|
(dynamic-wind
|
|
|
|
(lambda () #f)
|
|
|
|
(lambda ()
|
|
|
|
(let loop ((expr (read port)) (exprs '()))
|
|
|
|
(if (eof-object? expr)
|
|
|
|
(reverse exprs)
|
|
|
|
(loop (read port) (cons expr exprs)))))
|
|
|
|
(lambda ()
|
|
|
|
(close-port port)))))))
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form rename compare)
|
|
|
|
(let ((filenames (cdr form)))
|
|
|
|
(let ((exprs (apply append (map read-file filenames))))
|
|
|
|
`(,(rename 'begin) ,@exprs)))))))
|
|
|
|
|
2013-12-10 02:00:47 -05:00
|
|
|
(export let let* letrec letrec*
|
|
|
|
quasiquote unquote unquote-splicing
|
|
|
|
and or
|
2013-12-10 04:48:53 -05:00
|
|
|
cond case else =>
|
2013-12-10 06:21:29 -05:00
|
|
|
do when unless
|
2014-07-20 01:55:17 -04:00
|
|
|
let-syntax letrec-syntax
|
2014-07-22 01:34:39 -04:00
|
|
|
include
|
2013-12-10 06:21:29 -05:00
|
|
|
_ ... syntax-error))
|
2013-12-10 02:00:47 -05:00
|
|
|
|
2014-07-19 02:11:17 -04:00
|
|
|
(import (picrin core-syntax))
|
|
|
|
|
|
|
|
(export let let* letrec letrec*
|
|
|
|
quasiquote unquote unquote-splicing
|
|
|
|
and or
|
|
|
|
cond case else =>
|
|
|
|
do when unless
|
2014-07-20 01:55:17 -04:00
|
|
|
let-syntax letrec-syntax
|
2014-07-22 01:34:39 -04:00
|
|
|
include
|
2014-07-19 02:11:17 -04:00
|
|
|
_ ... syntax-error)
|
2013-12-10 11:11:54 -05:00
|
|
|
|
|
|
|
;;; multiple value
|
2014-07-19 02:11:32 -04:00
|
|
|
(define-library (picrin values)
|
2013-12-10 11:11:54 -05:00
|
|
|
(import (scheme base)
|
2014-07-19 02:11:17 -04:00
|
|
|
(picrin macro))
|
2013-12-10 11:11:54 -05:00
|
|
|
|
2013-12-10 11:37:33 -05:00
|
|
|
(define-syntax let*-values
|
2013-12-10 11:30:06 -05:00
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form r c)
|
|
|
|
(let ((formals (cadr form)))
|
|
|
|
(if (null? formals)
|
|
|
|
`(,(r 'let) () ,@(cddr form))
|
|
|
|
`(,(r 'call-with-values) (,(r 'lambda) () ,@(cdar formals))
|
|
|
|
(,(r 'lambda) (,@(caar formals))
|
2013-12-10 11:37:33 -05:00
|
|
|
(,(r 'let*-values) (,@(cdr formals))
|
2013-12-10 11:30:06 -05:00
|
|
|
,@(cddr form)))))))))
|
|
|
|
|
2013-12-10 11:37:33 -05:00
|
|
|
(define-syntax let-values
|
2013-12-10 11:34:57 -05:00
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form r c)
|
2013-12-10 11:37:33 -05:00
|
|
|
`(,(r 'let*-values) ,@(cdr form)))))
|
2013-12-10 11:34:57 -05:00
|
|
|
|
2014-06-29 02:07:52 -04:00
|
|
|
(define (walk proc expr)
|
|
|
|
(cond
|
|
|
|
((null? expr)
|
|
|
|
'())
|
|
|
|
((pair? expr)
|
|
|
|
(cons (proc (car expr))
|
|
|
|
(walk proc (cdr expr))))
|
|
|
|
((vector? expr)
|
2014-07-22 01:28:30 -04:00
|
|
|
(list->vector (map proc (vector->list expr))))
|
2014-06-29 02:07:52 -04:00
|
|
|
(else
|
|
|
|
(proc expr))))
|
|
|
|
|
|
|
|
(define (flatten expr)
|
|
|
|
(let ((list '()))
|
|
|
|
(walk
|
|
|
|
(lambda (x)
|
|
|
|
(set! list (cons x list)))
|
|
|
|
expr)
|
|
|
|
(reverse list)))
|
|
|
|
|
|
|
|
(define uniq
|
|
|
|
(let ((counter 0))
|
|
|
|
(lambda (x)
|
|
|
|
(let ((sym (string->symbol (string-append "var$" (number->string counter)))))
|
|
|
|
(set! counter (+ counter 1))
|
|
|
|
sym))))
|
|
|
|
|
2013-12-10 11:48:26 -05:00
|
|
|
(define-syntax define-values
|
2014-06-29 02:07:52 -04:00
|
|
|
(ir-macro-transformer
|
|
|
|
(lambda (form inject compare)
|
|
|
|
(let* ((formal (cadr form))
|
|
|
|
(formal* (walk uniq formal))
|
|
|
|
(exprs (cddr form)))
|
|
|
|
`(begin
|
2014-07-19 01:30:29 -04:00
|
|
|
,@(map
|
|
|
|
(lambda (var) `(define ,var #f))
|
|
|
|
(flatten formal))
|
2014-06-29 02:07:52 -04:00
|
|
|
(call-with-values (lambda () ,@exprs)
|
|
|
|
(lambda ,formal*
|
2014-07-19 01:30:29 -04:00
|
|
|
,@(map
|
|
|
|
(lambda (var val) `(set! ,var ,val))
|
|
|
|
(flatten formal)
|
|
|
|
(flatten formal*)))))))))
|
2013-12-10 11:48:26 -05:00
|
|
|
|
2014-02-02 00:26:58 -05:00
|
|
|
(export let-values
|
2013-12-10 11:48:26 -05:00
|
|
|
let*-values
|
|
|
|
define-values))
|
2013-12-10 11:11:54 -05:00
|
|
|
|
2014-01-08 10:39:45 -05:00
|
|
|
;;; parameter
|
|
|
|
(define-library (picrin parameter)
|
|
|
|
(import (scheme base)
|
2014-07-22 20:18:58 -04:00
|
|
|
(picrin macro))
|
2014-01-08 10:39:45 -05:00
|
|
|
|
2014-07-12 11:56:09 -04:00
|
|
|
(define-syntax with
|
|
|
|
(ir-macro-transformer
|
|
|
|
(lambda (form inject compare)
|
|
|
|
(let ((before (car (cdr form)))
|
|
|
|
(after (car (cdr (cdr form))))
|
|
|
|
(body (cdr (cdr (cdr form)))))
|
|
|
|
`(begin
|
|
|
|
(,before)
|
|
|
|
(let ((result (begin ,@body)))
|
|
|
|
(,after)
|
|
|
|
result))))))
|
|
|
|
|
2014-01-08 10:39:45 -05:00
|
|
|
(define-syntax parameterize
|
2014-07-12 11:56:09 -04:00
|
|
|
(ir-macro-transformer
|
|
|
|
(lambda (form inject compare)
|
|
|
|
(let ((formal (car (cdr form)))
|
|
|
|
(body (cdr (cdr form))))
|
|
|
|
(let ((vars (map car formal))
|
|
|
|
(vals (map cadr formal)))
|
|
|
|
`(with
|
2014-07-22 20:18:58 -04:00
|
|
|
(lambda ()
|
|
|
|
,@(map (lambda (var val) `(parameter-push! ,var ,val)) vars vals))
|
|
|
|
(lambda ()
|
|
|
|
,@(map (lambda (var) `(parameter-pop! ,var)) vars))
|
2014-07-12 11:56:09 -04:00
|
|
|
,@body))))))
|
2014-01-08 10:39:45 -05:00
|
|
|
|
2014-07-22 20:18:58 -04:00
|
|
|
(export parameterize))
|
2014-01-08 10:39:45 -05:00
|
|
|
|
2014-02-18 12:01:02 -05:00
|
|
|
;;; Record Type
|
|
|
|
(define-library (picrin record)
|
|
|
|
(import (scheme base)
|
2014-07-19 02:11:17 -04:00
|
|
|
(picrin macro))
|
2014-02-18 12:01:02 -05:00
|
|
|
|
|
|
|
(define record-marker (list 'record-marker))
|
|
|
|
|
|
|
|
(define real-vector? vector?)
|
|
|
|
|
2014-03-25 01:39:44 -04:00
|
|
|
(set! vector?
|
|
|
|
(lambda (x)
|
|
|
|
(and (real-vector? x)
|
|
|
|
(or (= 0 (vector-length x))
|
|
|
|
(not (eq? (vector-ref x 0)
|
|
|
|
record-marker))))))
|
2014-02-18 12:01:02 -05:00
|
|
|
|
|
|
|
#|
|
|
|
|
;; (scheme eval) is not provided for now
|
|
|
|
(define eval
|
|
|
|
(let ((real-eval eval))
|
|
|
|
(lambda (exp env)
|
|
|
|
((real-eval `(lambda (vector?) ,exp))
|
|
|
|
vector?))))
|
|
|
|
|#
|
|
|
|
|
|
|
|
(define (record? x)
|
|
|
|
(and (real-vector? x)
|
|
|
|
(< 0 (vector-length x))
|
|
|
|
(eq? (vector-ref x 0) record-marker)))
|
|
|
|
|
|
|
|
(define (make-record size)
|
|
|
|
(let ((new (make-vector (+ size 1))))
|
|
|
|
(vector-set! new 0 record-marker)
|
|
|
|
new))
|
|
|
|
|
|
|
|
(define (record-ref record index)
|
|
|
|
(vector-ref record (+ index 1)))
|
|
|
|
|
|
|
|
(define (record-set! record index value)
|
|
|
|
(vector-set! record (+ index 1) value))
|
|
|
|
|
|
|
|
(define record-type% (make-record 3))
|
|
|
|
(record-set! record-type% 0 record-type%)
|
|
|
|
(record-set! record-type% 1 'record-type%)
|
|
|
|
(record-set! record-type% 2 '(name field-tags))
|
|
|
|
|
|
|
|
(define (make-record-type name field-tags)
|
|
|
|
(let ((new (make-record 3)))
|
|
|
|
(record-set! new 0 record-type%)
|
|
|
|
(record-set! new 1 name)
|
|
|
|
(record-set! new 2 field-tags)
|
|
|
|
new))
|
|
|
|
|
|
|
|
(define (record-type record)
|
|
|
|
(record-ref record 0))
|
|
|
|
|
|
|
|
(define (record-type-name record-type)
|
|
|
|
(record-ref record-type 1))
|
|
|
|
|
|
|
|
(define (record-type-field-tags record-type)
|
|
|
|
(record-ref record-type 2))
|
|
|
|
|
|
|
|
(define (field-index type tag)
|
|
|
|
(let rec ((i 1) (tags (record-type-field-tags type)))
|
|
|
|
(cond ((null? tags)
|
|
|
|
(error "record type has no such field" type tag))
|
|
|
|
((eq? tag (car tags)) i)
|
|
|
|
(else (rec (+ i 1) (cdr tags))))))
|
|
|
|
|
|
|
|
(define (record-constructor type tags)
|
|
|
|
(let ((size (length (record-type-field-tags type)))
|
|
|
|
(arg-count (length tags))
|
|
|
|
(indexes (map (lambda (tag) (field-index type tag)) tags)))
|
|
|
|
(lambda args
|
|
|
|
(if (= (length args) arg-count)
|
|
|
|
(let ((new (make-record (+ size 1))))
|
|
|
|
(record-set! new 0 type)
|
|
|
|
(for-each (lambda (arg i) (record-set! new i arg)) args indexes)
|
|
|
|
new)
|
|
|
|
(error "wrong number of arguments to constructor" type args)))))
|
|
|
|
|
|
|
|
(define (record-predicate type)
|
|
|
|
(lambda (thing)
|
|
|
|
(and (record? thing)
|
|
|
|
(eq? (record-type thing)
|
|
|
|
type))))
|
|
|
|
|
|
|
|
(define (record-accessor type tag)
|
|
|
|
(let ((index (field-index type tag)))
|
|
|
|
(lambda (thing)
|
|
|
|
(if (and (record? thing)
|
|
|
|
(eq? (record-type thing)
|
|
|
|
type))
|
|
|
|
(record-ref thing index)
|
|
|
|
(error "accessor applied to bad value" type tag thing)))))
|
|
|
|
|
|
|
|
(define (record-modifier type tag)
|
|
|
|
(let ((index (field-index type tag)))
|
|
|
|
(lambda (thing value)
|
|
|
|
(if (and (record? thing)
|
|
|
|
(eq? (record-type thing)
|
|
|
|
type))
|
|
|
|
(record-set! thing index value)
|
|
|
|
(error "modifier applied to bad value" type tag thing)))))
|
|
|
|
|
|
|
|
(define-syntax define-record-field
|
|
|
|
(ir-macro-transformer
|
|
|
|
(lambda (form inject compare?)
|
2014-07-19 01:25:22 -04:00
|
|
|
(let ((type (car (cdr form)))
|
|
|
|
(field-tag (car (cdr (cdr form))))
|
|
|
|
(acc-mod (cdr (cdr (cdr form)))))
|
2014-02-18 12:01:02 -05:00
|
|
|
(if (= 1 (length acc-mod))
|
|
|
|
`(define ,(car acc-mod)
|
|
|
|
(record-accessor ,type ',field-tag))
|
|
|
|
`(begin
|
|
|
|
(define ,(car acc-mod)
|
|
|
|
(record-accessor ,type ',field-tag))
|
|
|
|
(define ,(cadr acc-mod)
|
|
|
|
(record-modifier ,type ',field-tag))))))))
|
|
|
|
|
|
|
|
(define-syntax define-record-type
|
|
|
|
(ir-macro-transformer
|
|
|
|
(lambda (form inject compare?)
|
|
|
|
(let ((type (cadr form))
|
2014-07-19 01:25:22 -04:00
|
|
|
(constructor (car (cdr (cdr form))))
|
|
|
|
(predicate (car (cdr (cdr (cdr form)))))
|
|
|
|
(field-tag (cdr (cdr (cdr (cdr form))))))
|
2014-02-18 12:01:02 -05:00
|
|
|
`(begin
|
|
|
|
(define ,type
|
|
|
|
(make-record-type ',type ',(cdr constructor)))
|
|
|
|
(define ,(car constructor)
|
|
|
|
(record-constructor ,type ',(cdr constructor)))
|
|
|
|
(define ,predicate
|
|
|
|
(record-predicate ,type))
|
|
|
|
,@(map
|
|
|
|
(lambda (x)
|
|
|
|
`(define-record-field ,type ,(car x) ,(cadr x) ,@(cddr x)))
|
|
|
|
field-tag))))))
|
|
|
|
|
2014-07-19 02:13:47 -04:00
|
|
|
(export define-record-type))
|
2014-02-18 12:01:02 -05:00
|
|
|
|
2013-12-10 02:00:47 -05:00
|
|
|
(import (picrin macro)
|
2014-07-19 02:11:32 -04:00
|
|
|
(picrin values)
|
2014-02-18 12:01:02 -05:00
|
|
|
(picrin parameter)
|
|
|
|
(picrin record))
|
2013-11-09 02:33:52 -05:00
|
|
|
|
2014-02-02 00:26:58 -05:00
|
|
|
(export let-values
|
2013-12-10 11:48:26 -05:00
|
|
|
let*-values
|
|
|
|
define-values)
|
2013-12-10 11:11:54 -05:00
|
|
|
|
2014-01-08 10:39:45 -05:00
|
|
|
(export make-parameter
|
|
|
|
parameterize)
|
|
|
|
|
2014-07-19 02:13:47 -04:00
|
|
|
(export define-record-type)
|
2014-02-18 12:01:02 -05:00
|
|
|
|
2013-12-09 13:00:33 -05:00
|
|
|
(define (fold f s xs)
|
|
|
|
(if (null? xs)
|
|
|
|
s
|
|
|
|
(fold f (f (car xs) s) (cdr xs))))
|
2013-11-10 18:01:29 -05:00
|
|
|
|
2013-11-14 06:41:51 -05:00
|
|
|
;;; 6.6 Characters
|
|
|
|
|
|
|
|
(define-macro (define-char-transitive-predicate name op)
|
|
|
|
`(define (,name . cs)
|
2013-12-10 10:58:25 -05:00
|
|
|
(apply ,op (map char->integer cs))))
|
2013-11-14 06:41:51 -05:00
|
|
|
|
|
|
|
(define-char-transitive-predicate char=? =)
|
|
|
|
(define-char-transitive-predicate char<? <)
|
|
|
|
(define-char-transitive-predicate char>? >)
|
|
|
|
(define-char-transitive-predicate char<=? <=)
|
|
|
|
(define-char-transitive-predicate char>=? >=)
|
|
|
|
|
2013-12-10 10:13:57 -05:00
|
|
|
(export char=?
|
|
|
|
char<?
|
|
|
|
char>?
|
|
|
|
char<=?
|
|
|
|
char>=?)
|
|
|
|
|
2013-11-17 11:26:03 -05:00
|
|
|
;;; 6.7 String
|
|
|
|
|
|
|
|
(define (string->list string . opts)
|
|
|
|
(let ((start (if (pair? opts) (car opts) 0))
|
|
|
|
(end (if (>= (length opts) 2)
|
|
|
|
(cadr opts)
|
|
|
|
(string-length string))))
|
|
|
|
(do ((i start (+ i 1))
|
|
|
|
(res '()))
|
2014-01-08 06:18:44 -05:00
|
|
|
((= i end)
|
2013-11-17 11:26:03 -05:00
|
|
|
(reverse res))
|
|
|
|
(set! res (cons (string-ref string i) res)))))
|
|
|
|
|
|
|
|
(define (list->string list)
|
2014-02-08 13:41:13 -05:00
|
|
|
(let ((len (length list)))
|
|
|
|
(let ((v (make-string len)))
|
|
|
|
(do ((i 0 (+ i 1))
|
|
|
|
(l list (cdr l)))
|
|
|
|
((= i len)
|
|
|
|
v)
|
|
|
|
(string-set! v i (car l))))))
|
|
|
|
|
|
|
|
(define (string . objs)
|
|
|
|
(list->string objs))
|
2013-11-17 11:26:03 -05:00
|
|
|
|
2014-02-08 13:10:58 -05:00
|
|
|
(export string string->list list->string)
|
2013-12-10 10:13:57 -05:00
|
|
|
|
2013-11-14 03:58:12 -05:00
|
|
|
;;; 6.8. Vector
|
|
|
|
|
|
|
|
(define (vector . objs)
|
2014-07-21 09:51:33 -04:00
|
|
|
(list->vector objs))
|
2013-11-17 04:35:45 -05:00
|
|
|
|
2013-11-17 11:29:54 -05:00
|
|
|
(define (vector->string . args)
|
|
|
|
(list->string (apply vector->list args)))
|
|
|
|
|
|
|
|
(define (string->vector . args)
|
|
|
|
(list->vector (apply string->list args)))
|
|
|
|
|
2014-07-22 01:08:48 -04:00
|
|
|
(export vector vector->string string->vector)
|
2013-12-10 10:13:57 -05:00
|
|
|
|
2013-11-14 04:01:44 -05:00
|
|
|
;;; 6.9 bytevector
|
|
|
|
|
|
|
|
(define (bytevector . objs)
|
|
|
|
(let ((len (length objs)))
|
|
|
|
(let ((v (make-bytevector len)))
|
|
|
|
(do ((i 0 (+ i 1))
|
|
|
|
(l objs (cdr l)))
|
2014-01-08 06:18:44 -05:00
|
|
|
((= i len)
|
2013-11-14 04:01:44 -05:00
|
|
|
v)
|
|
|
|
(bytevector-u8-set! v i (car l))))))
|
2013-11-17 11:40:57 -05:00
|
|
|
|
2013-12-10 10:58:25 -05:00
|
|
|
(define (bytevector->list v start end)
|
|
|
|
(do ((i start (+ i 1))
|
|
|
|
(res '()))
|
2014-01-08 06:18:44 -05:00
|
|
|
((= i end)
|
2013-12-10 10:58:25 -05:00
|
|
|
(reverse res))
|
|
|
|
(set! res (cons (bytevector-u8-ref v i) res))))
|
|
|
|
|
|
|
|
(define (list->bytevector v)
|
|
|
|
(apply bytevector v))
|
|
|
|
|
|
|
|
(define (utf8->string v . opts)
|
|
|
|
(let ((start (if (pair? opts) (car opts) 0))
|
|
|
|
(end (if (>= (length opts) 2)
|
|
|
|
(cadr opts)
|
|
|
|
(bytevector-length v))))
|
|
|
|
(list->string (map integer->char (bytevector->list v start end)))))
|
|
|
|
|
|
|
|
(define (string->utf8 s . opts)
|
|
|
|
(let ((start (if (pair? opts) (car opts) 0))
|
|
|
|
(end (if (>= (length opts) 2)
|
|
|
|
(cadr opts)
|
|
|
|
(string-length s))))
|
|
|
|
(list->bytevector (map char->integer (string->list s start end)))))
|
|
|
|
|
2013-12-10 10:13:57 -05:00
|
|
|
(export bytevector
|
2014-07-22 00:55:35 -04:00
|
|
|
bytevector->list
|
|
|
|
list->bytevector
|
2013-12-10 10:58:25 -05:00
|
|
|
utf8->string
|
|
|
|
string->utf8)
|
2013-12-10 10:13:57 -05:00
|
|
|
|
2013-11-28 11:50:10 -05:00
|
|
|
;;; 6.10 control features
|
|
|
|
|
2014-07-22 20:41:55 -04:00
|
|
|
(define (string-map f . strings)
|
|
|
|
(list->string (apply map f (map string->list strings))))
|
|
|
|
|
|
|
|
(define (string-for-each f . strings)
|
|
|
|
(apply for-each f (map string->list strings)))
|
|
|
|
|
|
|
|
(define (vector-map f . vectors)
|
|
|
|
(list->vector (apply map f (map vector->list vectors))))
|
|
|
|
|
|
|
|
(define (vector-for-each f . vectors)
|
|
|
|
(apply for-each f (map vector->list vectors)))
|
2013-12-10 08:53:59 -05:00
|
|
|
|
2014-01-22 08:21:48 -05:00
|
|
|
(export string-map string-for-each
|
2013-12-10 10:13:57 -05:00
|
|
|
vector-map vector-for-each)
|
|
|
|
|
2013-12-10 08:53:59 -05:00
|
|
|
;;; 6.13. Input and output
|
|
|
|
|
|
|
|
(define (call-with-port port proc)
|
|
|
|
(dynamic-wind
|
|
|
|
(lambda () #f)
|
|
|
|
(lambda () (proc port))
|
|
|
|
(lambda () (close-port port))))
|
2013-12-10 10:13:57 -05:00
|
|
|
|
|
|
|
(export call-with-port)
|
2014-02-07 13:04:54 -05:00
|
|
|
|
2014-04-03 02:34:55 -04:00
|
|
|
;;; syntax-rules
|
|
|
|
(define-library (picrin syntax-rules)
|
|
|
|
(import (scheme base)
|
2014-07-19 01:25:22 -04:00
|
|
|
(picrin macro))
|
2014-04-03 02:34:55 -04:00
|
|
|
|
|
|
|
;;; utility functions
|
|
|
|
(define (reverse* l)
|
|
|
|
;; (reverse* '(a b c d . e)) => (e d c b a)
|
|
|
|
(let loop ((a '())
|
|
|
|
(d l))
|
|
|
|
(if (pair? d)
|
|
|
|
(loop (cons (car d) a) (cdr d))
|
|
|
|
(cons d a))))
|
|
|
|
|
|
|
|
(define (var->sym v)
|
|
|
|
(let loop ((cnt 0)
|
|
|
|
(v v))
|
|
|
|
(if (symbol? v)
|
|
|
|
(string->symbol (string-append (symbol->string v) "/" (number->string cnt)))
|
|
|
|
(loop (+ 1 cnt) (car v)))))
|
|
|
|
|
|
|
|
(define push-var list)
|
|
|
|
|
|
|
|
(define (every? pred l)
|
|
|
|
(if (null? l)
|
|
|
|
#t
|
|
|
|
(and (pred (car l)) (every? pred (cdr l)))))
|
|
|
|
|
|
|
|
(define (flatten l)
|
|
|
|
(cond
|
|
|
|
((null? l) '())
|
|
|
|
((pair? (car l))
|
|
|
|
(append (flatten (car l)) (flatten (cdr l))))
|
|
|
|
(else
|
|
|
|
(cons (car l) (flatten (cdr l))))))
|
|
|
|
|
|
|
|
;;; main function
|
|
|
|
(define-syntax syntax-rules
|
|
|
|
(er-macro-transformer
|
|
|
|
(lambda (form r compare)
|
|
|
|
(define _define (r 'define))
|
|
|
|
(define _let (r 'let))
|
|
|
|
(define _if (r 'if))
|
|
|
|
(define _begin (r 'begin))
|
|
|
|
(define _lambda (r 'lambda))
|
|
|
|
(define _set! (r 'set!))
|
|
|
|
(define _not (r 'not))
|
|
|
|
(define _and (r 'and))
|
|
|
|
(define _car (r 'car))
|
|
|
|
(define _cdr (r 'cdr))
|
|
|
|
(define _cons (r 'cons))
|
|
|
|
(define _pair? (r 'pair?))
|
|
|
|
(define _null? (r 'null?))
|
|
|
|
(define _symbol? (r 'symbol?))
|
|
|
|
(define _eqv? (r 'eqv?))
|
|
|
|
(define _string=? (r 'string=?))
|
|
|
|
(define _map (r 'map))
|
|
|
|
(define _vector->list (r 'vector->list))
|
|
|
|
(define _list->vector (r 'list->vector))
|
|
|
|
(define _quote (r 'quote))
|
|
|
|
(define _quasiquote (r 'quasiquote))
|
|
|
|
(define _unquote (r 'unquote))
|
|
|
|
(define _unquote-splicing (r 'unquote-splicing))
|
|
|
|
(define _syntax-error (r 'syntax-error))
|
|
|
|
(define _call/cc (r 'call/cc))
|
|
|
|
(define _er-macro-transformer (r 'er-macro-transformer))
|
|
|
|
|
|
|
|
(define (compile-match ellipsis literals pattern)
|
|
|
|
(letrec ((compile-match-base
|
|
|
|
(lambda (pattern)
|
|
|
|
(cond ((compare pattern (r '_)) (values #f '()))
|
|
|
|
((member pattern literals compare)
|
|
|
|
(values
|
|
|
|
`(,_if (,_and (,_symbol? expr) (cmp expr (rename ',pattern)))
|
|
|
|
#f
|
|
|
|
(exit #f))
|
|
|
|
'()))
|
|
|
|
((and ellipsis (compare pattern ellipsis))
|
|
|
|
(values `(,_syntax-error "invalid pattern") '()))
|
|
|
|
((symbol? pattern)
|
|
|
|
(values `(,_set! ,(var->sym pattern) expr) (list pattern)))
|
|
|
|
((pair? pattern)
|
|
|
|
(compile-match-list pattern))
|
|
|
|
((vector? pattern)
|
|
|
|
(compile-match-vector pattern))
|
|
|
|
((string? pattern)
|
|
|
|
(values
|
|
|
|
`(,_if (,_not (,_string=? ',pattern expr))
|
|
|
|
(exit #f))
|
|
|
|
'()))
|
|
|
|
(else
|
|
|
|
(values
|
|
|
|
`(,_if (,_not (,_eqv? ',pattern expr))
|
|
|
|
(exit #f))
|
|
|
|
'())))))
|
|
|
|
|
|
|
|
(compile-match-list
|
|
|
|
(lambda (pattern)
|
|
|
|
(let loop ((pattern pattern)
|
|
|
|
(matches '())
|
|
|
|
(vars '())
|
|
|
|
(accessor 'expr))
|
|
|
|
(cond ;; (hoge)
|
|
|
|
((not (pair? (cdr pattern)))
|
|
|
|
(let*-values (((match1 vars1) (compile-match-base (car pattern)))
|
|
|
|
((match2 vars2) (compile-match-base (cdr pattern))))
|
|
|
|
(values
|
|
|
|
`(,_begin ,@(reverse matches)
|
|
|
|
(,_if (,_pair? ,accessor)
|
|
|
|
(,_begin
|
|
|
|
(,_let ((expr (,_car ,accessor)))
|
|
|
|
,match1)
|
|
|
|
(,_let ((expr (,_cdr ,accessor)))
|
|
|
|
,match2))
|
|
|
|
(exit #f)))
|
|
|
|
(append vars (append vars1 vars2)))))
|
|
|
|
;; (hoge ... rest args)
|
|
|
|
((and ellipsis (compare (cadr pattern) ellipsis))
|
|
|
|
(let-values (((match-r vars-r) (compile-match-list-reverse pattern)))
|
|
|
|
(values
|
|
|
|
`(,_begin ,@(reverse matches)
|
|
|
|
(,_let ((expr (,_let loop ((a ())
|
|
|
|
(d ,accessor))
|
|
|
|
(,_if (,_pair? d)
|
|
|
|
(loop (,_cons (,_car d) a) (,_cdr d))
|
|
|
|
(,_cons d a)))))
|
|
|
|
,match-r))
|
|
|
|
(append vars vars-r))))
|
|
|
|
(else
|
|
|
|
(let-values (((match1 vars1) (compile-match-base (car pattern))))
|
|
|
|
(loop (cdr pattern)
|
|
|
|
(cons `(,_if (,_pair? ,accessor)
|
2014-06-26 18:28:56 -04:00
|
|
|
(,_let ((expr (,_car ,accessor)))
|
2014-04-03 02:34:55 -04:00
|
|
|
,match1)
|
|
|
|
(exit #f))
|
|
|
|
matches)
|
|
|
|
(append vars vars1)
|
|
|
|
`(,_cdr ,accessor))))))))
|
|
|
|
|
|
|
|
(compile-match-list-reverse
|
|
|
|
(lambda (pattern)
|
|
|
|
(let loop ((pattern (reverse* pattern))
|
|
|
|
(matches '())
|
|
|
|
(vars '())
|
|
|
|
(accessor 'expr))
|
|
|
|
(cond ((and ellipsis (compare (car pattern) ellipsis))
|
|
|
|
(let-values (((match1 vars1) (compile-match-ellipsis (cadr pattern))))
|
|
|
|
(values
|
|
|
|
`(,_begin ,@(reverse matches)
|
|
|
|
(,_let ((expr ,accessor))
|
|
|
|
,match1))
|
|
|
|
(append vars vars1))))
|
|
|
|
(else
|
|
|
|
(let-values (((match1 vars1) (compile-match-base (car pattern))))
|
|
|
|
(loop (cdr pattern)
|
|
|
|
(cons `(,_let ((expr (,_car ,accessor))) ,match1) matches)
|
|
|
|
(append vars vars1)
|
|
|
|
`(,_cdr ,accessor))))))))
|
|
|
|
|
|
|
|
(compile-match-ellipsis
|
|
|
|
(lambda (pattern)
|
|
|
|
(let-values (((match vars) (compile-match-base pattern)))
|
|
|
|
(values
|
|
|
|
`(,_let loop ((expr expr))
|
|
|
|
(,_if (,_not (,_null? expr))
|
|
|
|
(,_let ,(map (lambda (var) `(,(var->sym var) '())) vars)
|
|
|
|
(,_let ((expr (,_car expr)))
|
|
|
|
,match)
|
|
|
|
,@(map
|
|
|
|
(lambda (var)
|
|
|
|
`(,_set! ,(var->sym (push-var var))
|
|
|
|
(,_cons ,(var->sym var) ,(var->sym (push-var var)))))
|
|
|
|
vars)
|
|
|
|
(loop (,_cdr expr)))))
|
|
|
|
(map push-var vars)))))
|
|
|
|
|
|
|
|
(compile-match-vector
|
|
|
|
(lambda (pattern)
|
|
|
|
(let-values (((match vars) (compile-match-list (vector->list pattern))))
|
|
|
|
(values
|
|
|
|
`(,_let ((expr (,_vector->list expr)))
|
|
|
|
,match)
|
|
|
|
vars)))))
|
|
|
|
|
|
|
|
(let-values (((match vars) (compile-match-base (cdr pattern))))
|
|
|
|
(values `(,_let ((expr (,_cdr expr)))
|
|
|
|
,match
|
|
|
|
#t)
|
|
|
|
vars))))
|
|
|
|
|
|
|
|
;;; compile expand
|
|
|
|
(define (compile-expand ellipsis reserved template)
|
|
|
|
(letrec ((compile-expand-base
|
|
|
|
(lambda (template ellipsis-valid)
|
2014-07-17 03:11:33 -04:00
|
|
|
(cond ((member template reserved eq?)
|
2014-04-03 02:34:55 -04:00
|
|
|
(values (var->sym template) (list template)))
|
|
|
|
((symbol? template)
|
|
|
|
(values `(rename ',template) '()))
|
|
|
|
((pair? template)
|
|
|
|
(compile-expand-list template ellipsis-valid))
|
|
|
|
((vector? template)
|
|
|
|
(compile-expand-vector template ellipsis-valid))
|
|
|
|
(else
|
|
|
|
(values `',template '())))))
|
|
|
|
|
|
|
|
(compile-expand-list
|
|
|
|
(lambda (template ellipsis-valid)
|
|
|
|
(let loop ((template template)
|
|
|
|
(expands '())
|
|
|
|
(vars '()))
|
|
|
|
(cond ;; (... hoge)
|
|
|
|
((and ellipsis-valid
|
|
|
|
(pair? template)
|
|
|
|
(compare (car template) ellipsis))
|
|
|
|
(if (and (pair? (cdr template)) (null? (cddr template)))
|
|
|
|
(compile-expand-base (cadr template) #f)
|
|
|
|
(values '(,_syntax-error "invalid template") '())))
|
|
|
|
;; hoge
|
|
|
|
((not (pair? template))
|
|
|
|
(let-values (((expand1 vars1)
|
|
|
|
(compile-expand-base template ellipsis-valid)))
|
|
|
|
(values
|
|
|
|
`(,_quasiquote (,@(reverse expands) . (,_unquote ,expand1)))
|
|
|
|
(append vars vars1))))
|
|
|
|
;; (a ... rest syms)
|
|
|
|
((and ellipsis-valid
|
|
|
|
(pair? (cdr template))
|
|
|
|
(compare (cadr template) ellipsis))
|
|
|
|
(let-values (((expand1 vars1)
|
|
|
|
(compile-expand-base (car template) ellipsis-valid)))
|
|
|
|
(loop (cddr template)
|
|
|
|
(cons
|
|
|
|
`(,_unquote-splicing
|
|
|
|
(,_map (,_lambda ,(map var->sym vars1) ,expand1)
|
|
|
|
,@(map (lambda (v) (var->sym (push-var v))) vars1)))
|
|
|
|
expands)
|
|
|
|
(append vars (map push-var vars1)))))
|
|
|
|
(else
|
|
|
|
(let-values (((expand1 vars1)
|
|
|
|
(compile-expand-base (car template) ellipsis-valid)))
|
|
|
|
(loop (cdr template)
|
|
|
|
(cons
|
|
|
|
`(,_unquote ,expand1)
|
|
|
|
expands)
|
|
|
|
(append vars vars1))))))))
|
|
|
|
|
|
|
|
(compile-expand-vector
|
|
|
|
(lambda (template ellipsis-valid)
|
|
|
|
(let-values (((expand1 vars1)
|
|
|
|
(compile-expand-list (vector->list template) ellipsis-valid)))
|
|
|
|
`(,_list->vector ,expand1)
|
|
|
|
vars1))))
|
|
|
|
|
|
|
|
(compile-expand-base template ellipsis)))
|
|
|
|
|
|
|
|
(define (check-vars vars-pattern vars-template)
|
|
|
|
;;fixme
|
|
|
|
#t)
|
|
|
|
|
|
|
|
(define (compile-rule ellipsis literals rule)
|
|
|
|
(let ((pattern (car rule))
|
|
|
|
(template (cadr rule)))
|
|
|
|
(let*-values (((match vars-match)
|
|
|
|
(compile-match ellipsis literals pattern))
|
|
|
|
((expand vars-expand)
|
|
|
|
(compile-expand ellipsis (flatten vars-match) template)))
|
|
|
|
(if (check-vars vars-match vars-expand)
|
|
|
|
(list vars-match match expand)
|
|
|
|
'mismatch))))
|
|
|
|
|
|
|
|
(define (expand-clauses clauses rename)
|
|
|
|
(cond ((null? clauses)
|
|
|
|
`(,_quote (syntax-error "no matching pattern")))
|
|
|
|
((compare (car clauses) 'mismatch)
|
|
|
|
`(,_syntax-error "invalid rule"))
|
|
|
|
(else
|
2014-07-19 01:25:22 -04:00
|
|
|
(let ((vars (list-ref (car clauses) 0))
|
|
|
|
(match (list-ref (car clauses) 1))
|
|
|
|
(expand (list-ref (car clauses) 2)))
|
2014-04-03 02:34:55 -04:00
|
|
|
`(,_let ,(map (lambda (v) (list (var->sym v) '())) vars)
|
|
|
|
(,_let ((result (,_call/cc (,_lambda (exit) ,match))))
|
|
|
|
(,_if result
|
|
|
|
,expand
|
|
|
|
,(expand-clauses (cdr clauses) rename))))))))
|
|
|
|
|
|
|
|
(define (normalize-form form)
|
|
|
|
(if (and (list? form) (>= (length form) 2))
|
|
|
|
(let ((ellipsis '...)
|
|
|
|
(literals (cadr form))
|
|
|
|
(rules (cddr form)))
|
|
|
|
|
|
|
|
(when (symbol? literals)
|
|
|
|
(set! ellipsis literals)
|
|
|
|
(set! literals (car rules))
|
|
|
|
(set! rules (cdr rules)))
|
|
|
|
|
|
|
|
(if (and (symbol? ellipsis)
|
|
|
|
(list? literals)
|
|
|
|
(every? symbol? literals)
|
|
|
|
(list? rules)
|
|
|
|
(every? (lambda (l) (and (list? l) (= (length l) 2))) rules))
|
|
|
|
(if (member ellipsis literals compare)
|
|
|
|
`(syntax-rules #f ,literals ,@rules)
|
|
|
|
`(syntax-rules ,ellipsis ,literals ,@rules))
|
|
|
|
#f))
|
|
|
|
#f))
|
|
|
|
|
|
|
|
(let ((form (normalize-form form)))
|
|
|
|
(if form
|
2014-07-19 01:25:22 -04:00
|
|
|
(let ((ellipsis (list-ref form 1))
|
|
|
|
(literals (list-ref form 2))
|
|
|
|
(rules (list-tail form 3)))
|
2014-04-03 02:34:55 -04:00
|
|
|
(let ((clauses (map (lambda (rule) (compile-rule ellipsis literals rule))
|
|
|
|
rules)))
|
|
|
|
`(,_er-macro-transformer
|
|
|
|
(,_lambda (expr rename cmp)
|
|
|
|
,(expand-clauses clauses r)))))
|
|
|
|
|
|
|
|
`(,_syntax-error "malformed syntax-rules"))))))
|
|
|
|
|
|
|
|
(export syntax-rules))
|
|
|
|
|
|
|
|
(import (picrin syntax-rules))
|
|
|
|
(export syntax-rules)
|
2014-07-15 04:51:27 -04:00
|
|
|
|
2014-06-29 04:45:49 -04:00
|
|
|
(define-syntax guard-aux
|
|
|
|
(syntax-rules (else =>)
|
|
|
|
((guard-aux reraise (else result1 result2 ...))
|
|
|
|
(begin result1 result2 ...))
|
|
|
|
((guard-aux reraise (test => result))
|
|
|
|
(let ((temp test))
|
|
|
|
(if temp
|
|
|
|
(result temp)
|
|
|
|
reraise)))
|
|
|
|
((guard-aux reraise (test => result)
|
|
|
|
clause1 clause2 ...)
|
|
|
|
(let ((temp test))
|
|
|
|
(if temp
|
|
|
|
(result temp)
|
|
|
|
(guard-aux reraise clause1 clause2 ...))))
|
|
|
|
((guard-aux reraise (test))
|
|
|
|
(or test reraise))
|
|
|
|
((guard-aux reraise (test) clause1 clause2 ...)
|
|
|
|
(let ((temp test))
|
|
|
|
(if temp
|
|
|
|
temp
|
|
|
|
(guard-aux reraise clause1 clause2 ...))))
|
|
|
|
((guard-aux reraise (test result1 result2 ...))
|
|
|
|
(if test
|
|
|
|
(begin result1 result2 ...)
|
|
|
|
reraise))
|
|
|
|
((guard-aux reraise
|
|
|
|
(test result1 result2 ...)
|
|
|
|
clause1 clause2 ...)
|
|
|
|
(if test
|
|
|
|
(begin result1 result2 ...)
|
|
|
|
(guard-aux reraise clause1 clause2 ...)))))
|
|
|
|
|
|
|
|
(define-syntax guard
|
|
|
|
(syntax-rules ()
|
|
|
|
((guard (var clause ...) e1 e2 ...)
|
|
|
|
((call/cc
|
|
|
|
(lambda (guard-k)
|
|
|
|
(with-exception-handler
|
|
|
|
(lambda (condition)
|
|
|
|
((call/cc
|
|
|
|
(lambda (handler-k)
|
|
|
|
(guard-k
|
|
|
|
(lambda ()
|
|
|
|
(let ((var condition))
|
|
|
|
(guard-aux
|
|
|
|
(handler-k
|
|
|
|
(lambda ()
|
|
|
|
(raise-continuable condition)))
|
|
|
|
clause ...))))))))
|
|
|
|
(lambda ()
|
|
|
|
(call-with-values
|
|
|
|
(lambda () e1 e2 ...)
|
|
|
|
(lambda args
|
|
|
|
(guard-k
|
|
|
|
(lambda ()
|
|
|
|
(apply values args)))))))))))))
|
|
|
|
|
|
|
|
(export guard)
|