prelude to base
This commit is contained in:
parent
c2982a4252
commit
0095fa6a57
|
@ -1,6 +1,6 @@
|
||||||
list(APPEND PICLIB_SCHEME_LIBS
|
list(APPEND PICLIB_SCHEME_LIBS
|
||||||
${PROJECT_SOURCE_DIR}/piclib/picrin/macro.scm # the only dependency prelude requires
|
${PROJECT_SOURCE_DIR}/piclib/picrin/macro.scm
|
||||||
${PROJECT_SOURCE_DIR}/piclib/prelude.scm
|
${PROJECT_SOURCE_DIR}/piclib/scheme/base.scm
|
||||||
${PROJECT_SOURCE_DIR}/piclib/picrin/array.scm
|
${PROJECT_SOURCE_DIR}/piclib/picrin/array.scm
|
||||||
${PROJECT_SOURCE_DIR}/piclib/picrin/dictionary.scm
|
${PROJECT_SOURCE_DIR}/piclib/picrin/dictionary.scm
|
||||||
${PROJECT_SOURCE_DIR}/piclib/picrin/test.scm
|
${PROJECT_SOURCE_DIR}/piclib/picrin/test.scm
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
;;; core syntaces
|
(define-library (scheme base)
|
||||||
(define-library (picrin core-syntax)
|
(import (picrin macro))
|
||||||
(import (scheme base)
|
|
||||||
(picrin macro))
|
;; core syntax
|
||||||
|
|
||||||
(define-syntax syntax-error
|
(define-syntax syntax-error
|
||||||
(er-macro-transformer
|
(er-macro-transformer
|
||||||
|
@ -275,23 +275,46 @@
|
||||||
do when unless
|
do when unless
|
||||||
let-syntax letrec-syntax
|
let-syntax letrec-syntax
|
||||||
include
|
include
|
||||||
_ ... syntax-error))
|
_ ... syntax-error)
|
||||||
|
|
||||||
(import (picrin core-syntax))
|
|
||||||
|
|
||||||
(export let let* letrec letrec*
|
;; utility functions
|
||||||
quasiquote unquote unquote-splicing
|
|
||||||
and or
|
|
||||||
cond case else =>
|
|
||||||
do when unless
|
|
||||||
let-syntax letrec-syntax
|
|
||||||
include
|
|
||||||
_ ... syntax-error)
|
|
||||||
|
|
||||||
;;; multiple value
|
(define (walk proc expr)
|
||||||
(define-library (picrin values)
|
(cond
|
||||||
(import (scheme base)
|
((null? expr)
|
||||||
(picrin macro))
|
'())
|
||||||
|
((pair? expr)
|
||||||
|
(cons (walk proc (car expr))
|
||||||
|
(walk proc (cdr expr))))
|
||||||
|
((vector? expr)
|
||||||
|
(list->vector (map proc (vector->list expr))))
|
||||||
|
(else
|
||||||
|
(proc expr))))
|
||||||
|
|
||||||
|
(define (flatten expr)
|
||||||
|
(let ((list '()))
|
||||||
|
(walk
|
||||||
|
(lambda (x)
|
||||||
|
(set! list (cons x list)))
|
||||||
|
expr)
|
||||||
|
(reverse list)))
|
||||||
|
|
||||||
|
(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 (every? pred l)
|
||||||
|
(if (null? l)
|
||||||
|
#t
|
||||||
|
(and (pred (car l)) (every? pred (cdr l)))))
|
||||||
|
|
||||||
|
|
||||||
|
;; extra syntax
|
||||||
|
|
||||||
(define-syntax let*-values
|
(define-syntax let*-values
|
||||||
(er-macro-transformer
|
(er-macro-transformer
|
||||||
|
@ -309,26 +332,6 @@
|
||||||
(lambda (form r c)
|
(lambda (form r c)
|
||||||
`(,(r 'let*-values) ,@(cdr form)))))
|
`(,(r 'let*-values) ,@(cdr form)))))
|
||||||
|
|
||||||
(define (walk proc expr)
|
|
||||||
(cond
|
|
||||||
((null? expr)
|
|
||||||
'())
|
|
||||||
((pair? expr)
|
|
||||||
(cons (proc (car expr))
|
|
||||||
(walk proc (cdr expr))))
|
|
||||||
((vector? expr)
|
|
||||||
(list->vector (map proc (vector->list expr))))
|
|
||||||
(else
|
|
||||||
(proc expr))))
|
|
||||||
|
|
||||||
(define (flatten expr)
|
|
||||||
(let ((list '()))
|
|
||||||
(walk
|
|
||||||
(lambda (x)
|
|
||||||
(set! list (cons x list)))
|
|
||||||
expr)
|
|
||||||
(reverse list)))
|
|
||||||
|
|
||||||
(define uniq
|
(define uniq
|
||||||
(let ((counter 0))
|
(let ((counter 0))
|
||||||
(lambda (x)
|
(lambda (x)
|
||||||
|
@ -355,338 +358,8 @@
|
||||||
|
|
||||||
(export let-values
|
(export let-values
|
||||||
let*-values
|
let*-values
|
||||||
define-values))
|
define-values)
|
||||||
|
|
||||||
;;; parameter
|
|
||||||
(define-library (picrin parameter)
|
|
||||||
(import (scheme base)
|
|
||||||
(picrin macro))
|
|
||||||
|
|
||||||
(define-syntax parameterize
|
|
||||||
(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)))
|
|
||||||
`(begin
|
|
||||||
,@(map (lambda (var val) `(parameter-push! ,var ,val)) vars vals)
|
|
||||||
(let ((result (begin ,@body)))
|
|
||||||
,@(map (lambda (var) `(parameter-pop! ,var)) vars)
|
|
||||||
result)))))))
|
|
||||||
|
|
||||||
(export parameterize))
|
|
||||||
|
|
||||||
;;; Record Type
|
|
||||||
(define-library (picrin record)
|
|
||||||
(import (scheme base)
|
|
||||||
(scheme eval)
|
|
||||||
(picrin macro))
|
|
||||||
|
|
||||||
(define record-marker (list 'record-marker))
|
|
||||||
|
|
||||||
(define real-vector? vector?)
|
|
||||||
|
|
||||||
(set! vector?
|
|
||||||
(lambda (x)
|
|
||||||
(and (real-vector? x)
|
|
||||||
(or (= 0 (vector-length x))
|
|
||||||
(not (eq? (vector-ref x 0)
|
|
||||||
record-marker))))))
|
|
||||||
|
|
||||||
(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?)
|
|
||||||
(let ((type (car (cdr form)))
|
|
||||||
(field-tag (car (cdr (cdr form))))
|
|
||||||
(acc-mod (cdr (cdr (cdr form)))))
|
|
||||||
(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))
|
|
||||||
(constructor (car (cdr (cdr form))))
|
|
||||||
(predicate (car (cdr (cdr (cdr form)))))
|
|
||||||
(field-tag (cdr (cdr (cdr (cdr form))))))
|
|
||||||
`(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))))))
|
|
||||||
|
|
||||||
(export define-record-type))
|
|
||||||
|
|
||||||
(import (picrin macro)
|
|
||||||
(picrin values)
|
|
||||||
(picrin parameter)
|
|
||||||
(picrin record))
|
|
||||||
|
|
||||||
(export let-values
|
|
||||||
let*-values
|
|
||||||
define-values)
|
|
||||||
|
|
||||||
(export make-parameter
|
|
||||||
parameterize)
|
|
||||||
|
|
||||||
(export define-record-type)
|
|
||||||
|
|
||||||
;;; 6.6 Characters
|
|
||||||
|
|
||||||
(define-macro (define-char-transitive-predicate name op)
|
|
||||||
`(define (,name . cs)
|
|
||||||
(apply ,op (map char->integer cs))))
|
|
||||||
|
|
||||||
(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>=? >=)
|
|
||||||
|
|
||||||
(export char=?
|
|
||||||
char<?
|
|
||||||
char>?
|
|
||||||
char<=?
|
|
||||||
char>=?)
|
|
||||||
|
|
||||||
;;; 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 '()))
|
|
||||||
((= i end)
|
|
||||||
(reverse res))
|
|
||||||
(set! res (cons (string-ref string i) res)))))
|
|
||||||
|
|
||||||
(define (list->string list)
|
|
||||||
(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))
|
|
||||||
|
|
||||||
(export string string->list list->string)
|
|
||||||
|
|
||||||
;;; 6.8. Vector
|
|
||||||
|
|
||||||
(define (vector . objs)
|
|
||||||
(list->vector objs))
|
|
||||||
|
|
||||||
(define (vector->string . args)
|
|
||||||
(list->string (apply vector->list args)))
|
|
||||||
|
|
||||||
(define (string->vector . args)
|
|
||||||
(list->vector (apply string->list args)))
|
|
||||||
|
|
||||||
(export vector vector->string string->vector)
|
|
||||||
|
|
||||||
;;; 6.9 bytevector
|
|
||||||
|
|
||||||
(define (bytevector->list v start end)
|
|
||||||
(do ((i start (+ i 1))
|
|
||||||
(res '()))
|
|
||||||
((= i end)
|
|
||||||
(reverse res))
|
|
||||||
(set! res (cons (bytevector-u8-ref v i) res))))
|
|
||||||
|
|
||||||
(define (list->bytevector list)
|
|
||||||
(let ((len (length list)))
|
|
||||||
(let ((v (make-bytevector len)))
|
|
||||||
(do ((i 0 (+ i 1))
|
|
||||||
(l list (cdr l)))
|
|
||||||
((= i len)
|
|
||||||
v)
|
|
||||||
(bytevector-u8-set! v i (car l))))))
|
|
||||||
|
|
||||||
(define (bytevector . objs)
|
|
||||||
(list->bytevector objs))
|
|
||||||
|
|
||||||
(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)))))
|
|
||||||
|
|
||||||
(export bytevector
|
|
||||||
bytevector->list
|
|
||||||
list->bytevector
|
|
||||||
utf8->string
|
|
||||||
string->utf8)
|
|
||||||
|
|
||||||
;;; 6.10 control features
|
|
||||||
|
|
||||||
(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)))
|
|
||||||
|
|
||||||
(export string-map string-for-each
|
|
||||||
vector-map vector-for-each)
|
|
||||||
|
|
||||||
;;; 6.13. Input and output
|
|
||||||
|
|
||||||
(define (call-with-port port proc)
|
|
||||||
(dynamic-wind
|
|
||||||
(lambda () #f)
|
|
||||||
(lambda () (proc port))
|
|
||||||
(lambda () (close-port port))))
|
|
||||||
|
|
||||||
(export call-with-port)
|
|
||||||
|
|
||||||
;;; syntax-rules
|
|
||||||
(define-library (picrin syntax-rules)
|
|
||||||
(import (scheme base)
|
|
||||||
(picrin macro))
|
|
||||||
|
|
||||||
;;; 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
|
(define-syntax syntax-rules
|
||||||
(er-macro-transformer
|
(er-macro-transformer
|
||||||
(lambda (form r compare)
|
(lambda (form r compare)
|
||||||
|
@ -717,6 +390,16 @@
|
||||||
(define _call/cc (r 'call/cc))
|
(define _call/cc (r 'call/cc))
|
||||||
(define _er-macro-transformer (r 'er-macro-transformer))
|
(define _er-macro-transformer (r 'er-macro-transformer))
|
||||||
|
|
||||||
|
(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 (compile-match ellipsis literals pattern)
|
(define (compile-match ellipsis literals pattern)
|
||||||
(letrec ((compile-match-base
|
(letrec ((compile-match-base
|
||||||
(lambda (pattern)
|
(lambda (pattern)
|
||||||
|
@ -970,68 +653,344 @@
|
||||||
|
|
||||||
`(,_syntax-error "malformed syntax-rules"))))))
|
`(,_syntax-error "malformed syntax-rules"))))))
|
||||||
|
|
||||||
(export syntax-rules))
|
(export syntax-rules)
|
||||||
|
|
||||||
(import (picrin syntax-rules))
|
(define-syntax guard-aux
|
||||||
(export syntax-rules)
|
(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-aux
|
(define-syntax guard
|
||||||
(syntax-rules (else =>)
|
(syntax-rules ()
|
||||||
((guard-aux reraise (else result1 result2 ...))
|
((guard (var clause ...) e1 e2 ...)
|
||||||
(begin result1 result2 ...))
|
((call/cc
|
||||||
((guard-aux reraise (test => result))
|
(lambda (guard-k)
|
||||||
(let ((temp test))
|
(with-exception-handler
|
||||||
(if temp
|
(lambda (condition)
|
||||||
(result temp)
|
((call/cc
|
||||||
reraise)))
|
(lambda (handler-k)
|
||||||
((guard-aux reraise (test => result)
|
(guard-k
|
||||||
clause1 clause2 ...)
|
(lambda ()
|
||||||
(let ((temp test))
|
(let ((var condition))
|
||||||
(if temp
|
(guard-aux
|
||||||
(result temp)
|
(handler-k
|
||||||
(guard-aux reraise clause1 clause2 ...))))
|
(lambda ()
|
||||||
((guard-aux reraise (test))
|
(raise-continuable condition)))
|
||||||
(or test reraise))
|
clause ...))))))))
|
||||||
((guard-aux reraise (test) clause1 clause2 ...)
|
(lambda ()
|
||||||
(let ((temp test))
|
(call-with-values
|
||||||
(if temp
|
(lambda () e1 e2 ...)
|
||||||
temp
|
(lambda args
|
||||||
(guard-aux reraise clause1 clause2 ...))))
|
(guard-k
|
||||||
((guard-aux reraise (test result1 result2 ...))
|
(lambda ()
|
||||||
(if test
|
(apply values args)))))))))))))
|
||||||
(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
|
(export 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)
|
(import (picrin parameter))
|
||||||
|
|
||||||
|
(define-syntax parameterize
|
||||||
|
(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)))
|
||||||
|
`(begin
|
||||||
|
,@(map (lambda (var val) `(parameter-push! ,var ,val)) vars vals)
|
||||||
|
(let ((result (begin ,@body)))
|
||||||
|
,@(map (lambda (var) `(parameter-pop! ,var)) vars)
|
||||||
|
result)))))))
|
||||||
|
|
||||||
|
(export parameterize make-parameter)
|
||||||
|
|
||||||
|
(define-library (picrin record)
|
||||||
|
(import (scheme base)
|
||||||
|
(scheme eval)
|
||||||
|
(picrin macro))
|
||||||
|
|
||||||
|
(define record-marker (list 'record-marker))
|
||||||
|
|
||||||
|
(define real-vector? vector?)
|
||||||
|
|
||||||
|
(set! vector?
|
||||||
|
(lambda (x)
|
||||||
|
(and (real-vector? x)
|
||||||
|
(or (= 0 (vector-length x))
|
||||||
|
(not (eq? (vector-ref x 0)
|
||||||
|
record-marker))))))
|
||||||
|
|
||||||
|
(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?)
|
||||||
|
(let ((type (car (cdr form)))
|
||||||
|
(field-tag (car (cdr (cdr form))))
|
||||||
|
(acc-mod (cdr (cdr (cdr form)))))
|
||||||
|
(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))
|
||||||
|
(constructor (car (cdr (cdr form))))
|
||||||
|
(predicate (car (cdr (cdr (cdr form)))))
|
||||||
|
(field-tag (cdr (cdr (cdr (cdr form))))))
|
||||||
|
`(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))))))
|
||||||
|
|
||||||
|
(export define-record-type))
|
||||||
|
|
||||||
|
(import (picrin record))
|
||||||
|
|
||||||
|
(export define-record-type)
|
||||||
|
|
||||||
|
|
||||||
|
;; 6.6 Characters
|
||||||
|
|
||||||
|
(define-macro (define-char-transitive-predicate name op)
|
||||||
|
`(define (,name . cs)
|
||||||
|
(apply ,op (map char->integer cs))))
|
||||||
|
|
||||||
|
(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>=? >=)
|
||||||
|
|
||||||
|
(export char=?
|
||||||
|
char<?
|
||||||
|
char>?
|
||||||
|
char<=?
|
||||||
|
char>=?)
|
||||||
|
|
||||||
|
;; 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 '()))
|
||||||
|
((= i end)
|
||||||
|
(reverse res))
|
||||||
|
(set! res (cons (string-ref string i) res)))))
|
||||||
|
|
||||||
|
(define (list->string list)
|
||||||
|
(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))
|
||||||
|
|
||||||
|
(export string string->list list->string)
|
||||||
|
|
||||||
|
;; 6.8. Vector
|
||||||
|
|
||||||
|
(define (vector . objs)
|
||||||
|
(list->vector objs))
|
||||||
|
|
||||||
|
(define (vector->string . args)
|
||||||
|
(list->string (apply vector->list args)))
|
||||||
|
|
||||||
|
(define (string->vector . args)
|
||||||
|
(list->vector (apply string->list args)))
|
||||||
|
|
||||||
|
(export vector vector->string string->vector)
|
||||||
|
|
||||||
|
;; 6.9 bytevector
|
||||||
|
|
||||||
|
(define (bytevector->list v start end)
|
||||||
|
(do ((i start (+ i 1))
|
||||||
|
(res '()))
|
||||||
|
((= i end)
|
||||||
|
(reverse res))
|
||||||
|
(set! res (cons (bytevector-u8-ref v i) res))))
|
||||||
|
|
||||||
|
(define (list->bytevector list)
|
||||||
|
(let ((len (length list)))
|
||||||
|
(let ((v (make-bytevector len)))
|
||||||
|
(do ((i 0 (+ i 1))
|
||||||
|
(l list (cdr l)))
|
||||||
|
((= i len)
|
||||||
|
v)
|
||||||
|
(bytevector-u8-set! v i (car l))))))
|
||||||
|
|
||||||
|
(define (bytevector . objs)
|
||||||
|
(list->bytevector objs))
|
||||||
|
|
||||||
|
(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)))))
|
||||||
|
|
||||||
|
(export bytevector
|
||||||
|
bytevector->list
|
||||||
|
list->bytevector
|
||||||
|
utf8->string
|
||||||
|
string->utf8)
|
||||||
|
|
||||||
|
;; 6.10 control features
|
||||||
|
|
||||||
|
(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)))
|
||||||
|
|
||||||
|
(export string-map string-for-each
|
||||||
|
vector-map vector-for-each)
|
||||||
|
|
||||||
|
;; 6.13. Input and output
|
||||||
|
|
||||||
|
(define (call-with-port port proc)
|
||||||
|
(dynamic-wind
|
||||||
|
(lambda () #f)
|
||||||
|
(lambda () (proc port))
|
||||||
|
(lambda () (close-port port))))
|
||||||
|
|
||||||
|
(export call-with-port))
|
Loading…
Reference in New Issue