~ chicken-r7rs (master) e2f4e1782efd2ae75583f6c8c9b40a5c8f64af04
commit e2f4e1782efd2ae75583f6c8c9b40a5c8f64af04 Author: Evan Hanson <evhan@foldling.org> AuthorDate: Thu Jan 16 07:35:01 2014 +0000 Commit: Evan Hanson <evhan@foldling.org> CommitDate: Thu Jan 16 07:35:01 2014 +0000 Most of scheme.base, stub rest of libs, define-library/inclusion fixes diff --git a/NOTES.org b/NOTES.org index 70891db..d370938 100644 --- a/NOTES.org +++ b/NOTES.org @@ -5,15 +5,27 @@ NOTES - possible reimplement using core functionality. * Use of "define-values" is elegant but loses lambda-info for the defined procedures. + - Removed. * "export" does not support "(rename ...)" specifier yet. - this needs extensions to the core module system. * "(import SYMBOL)" is currently allowed. Should it not? + - I think this is needed for backwards compatibility (when an R7RS module imports a non-R7RS module). * Redefinition of "import" causes "re-importing" warnings. - The warnings could be removed in core, it's usefulness is not completely clear. -* Just renaming procedures (like from srfi-4) doesn't change their lambda-info names. - - This is sort of confusing, do we care (or should we "(define new old)")? +* Just reexporting procedures (like from srfi-4) doesn't change their lambda-info names. + - This is sort of confusing, do we care? - Also, this makes the locations from errors (from ##sys#check-whatever) wrong/misleading. + +* Should bytevectors be implemented over blobs instead of srfi-4 (or something else)? + +* I think library forms (i.e. ".sld" files) should look for includes relative to themselves + - not sure how to get that info when expanding define-library + +* UTF8? Not required, but should (use r7rs) include this extension, like it includes numbers? + +* get-environment-variable: "It is also an error to mutate the resulting string" ... + - can we just ignore this? diff --git a/r7rs-compile-time.scm b/r7rs-compile-time.scm index 5a74cfa..ad24c86 100644 --- a/r7rs-compile-time.scm +++ b/r7rs-compile-time.scm @@ -4,7 +4,6 @@ (import matchable) (use srfi-1 files extras data-structures) - (define (parse-library-name name loc) (define (fail) (syntax-error loc "invalid library name" name)) (match name @@ -29,7 +28,8 @@ ;;XXX scan include-path? (let* ((name2 (parse-library-name name loc)) (sname2 (symbol->string name2))) - (or (file-exists? (string-append sname2 ".import.so")) + (or (##sys#provided? name2) + (file-exists? (string-append sname2 ".import.so")) (file-exists? (string-append sname2 ".import.scm")) (extension-information name2)))) @@ -93,19 +93,9 @@ `(##core#require-extension (,name) #f)))) (strip-syntax (cdr x)))))))) -(define (current-source-directory) - (pathname-directory - (or (and (feature? #:compiling) ##compiler#source-filename) - ##sys#current-source-filename))) - (define (read-forms filename ci?) - (read-file - (if (absolute-pathname? filename) - filename - (make-pathname (current-source-directory) filename)) - (lambda (port) - (parameterize ((case-sensitive ci?)) - (read port))))) + (parameterize ((case-sensitive (not ci?))) + (##sys#include-forms-from-file filename))) (define (parse-library-definition form dummy-export) ; expects stripped syntax (match form @@ -148,11 +138,11 @@ ,(parse-decls more))) ((('include fnames ...) . more) `(##core#begin - ,@(process-includes fnames #f) + ,(process-includes fnames #f) ,(parse-decls more))) ((('include-ci fnames ...) . more) `(##core#begin - ,@(process-includes fnames #t) + ,(process-includes fnames #t) ,(parse-decls more))) ((('include-library-declarations fnames ...) . more) `(##core#begin @@ -164,7 +154,7 @@ ,(parse-decls more))) ((('begin code ...) . more) `(##core#begin - (##core#begin ,@code) + ,@code ,(parse-decls more))) (decl (syntax-error 'define-library "invalid library declaration" decl)))) `(##core#begin diff --git a/r7rs.scm b/r7rs.scm index 54c7ac3..7615d70 100644 --- a/r7rs.scm +++ b/r7rs.scm @@ -1,14 +1,16 @@ (module r7rs (define-library import import-for-syntax export syntax-rules) (import (except scheme syntax-rules)) ;XXX except ... - (import (only chicken include)) ;XXX except ... + (import (only chicken feature? include)) ;XXX except ... ;; For syntax definition helpers. (import-for-syntax r7rs-compile-time matchable) (begin-for-syntax (require-library r7rs-compile-time)) ;; For extended number literals. - (require-library numbers) + (if (feature? 'compiler-extension) + (require-library numbers-syntax) + (require-extension numbers)) ;; For #u8(...) syntax. (require-extension srfi-4) diff --git a/r7rs.setup b/r7rs.setup index 13c8073..b6f72f1 100644 --- a/r7rs.setup +++ b/r7rs.setup @@ -4,7 +4,7 @@ (use make srfi-1) (define scheme-modules - '("case-lambda" "char" "complex" "cxr" "eval" "file" "inexact" "load" "process-context" "r5rs" "read" "write")) ;XXX + '("case-lambda" "char" "complex" "cxr" "eval" "file" "inexact" "lazy" "load" "process-context" "r5rs" "read" "repl" "time" "write")) ;XXX (make (("r7rs-compile-time.so" ("r7rs-compile-time.scm" "r7rs-compile-time-module.scm") (compile -s -O3 -d1 r7rs-compile-time-module.scm -J -o r7rs-compile-time.so) diff --git a/scheme.base-interface.scm b/scheme.base-interface.scm index 26a2c94..c6e9cab 100644 --- a/scheme.base-interface.scm +++ b/scheme.base-interface.scm @@ -7,9 +7,7 @@ apply assoc assq assv begin - #| - binary-port? - |# + binary-port? ; XXX boolean? boolean=? bytevector bytevector-append @@ -68,12 +66,10 @@ if #| import ; provided by the "r7rs" module - import-for-syntax ; XXX should we? Probably not, it's not in r7rs... + import-for-syntax ; same |# include - #| include-ci - |# input-port-open? output-port-open? input-port? output-port? integer? @@ -83,9 +79,6 @@ letrec letrec* let-values let*-values let-syntax letrec-syntax - #| - library ; for "cond-expand" - |# list list-copy list-ref list-set! list-tail list? list->vector make-bytevector @@ -111,9 +104,7 @@ pair? parameterize peek-char - #| peek-u8 - |# port? procedure? quasiquote @@ -122,16 +113,12 @@ raise raise-continuable rational? rationalize - #| read-bytevector read-bytevector! - |# read-char read-error? - #| read-line read-string read-u8 - |# real? reverse round @@ -140,67 +127,49 @@ square string string->list list->string - #| string->utf8 utf8->string - |# string->symbol symbol->string - #| string->vector - |# string-append string-copy - #| string-copy! - |# string-fill! - #| string-for-each - |# string-length - #| string-map - |# string-ref string-set! string=? string<? string>? string<=? string>=? string? - substring - #| symbol=? - |# symbol? syntax-error #| - syntax-rules - textual-port? + syntax-rules ; provided by the "r7rs" module |# + textual-port? ; XXX truncate truncate/ truncate-quotient truncate-remainder - #| u8-ready? - |# unless #| - unquote unquote-splicing + unquote unquote-splicing ; provided by `quasiquote` |# values vector - #| vector-append vector-copy vector-copy! vector-for-each vector-length vector-map - |# vector-ref vector-set! + vector->list + vector->string + vector? when with-exception-handler - #| write-bytevector - |# write-char - #| write-string write-u8 - |# zero? ) diff --git a/scheme.base.scm b/scheme.base.scm index ec4e8f0..dd4001f 100644 --- a/scheme.base.scm +++ b/scheme.base.scm @@ -1,43 +1,71 @@ (module scheme.base () -(import (except scheme syntax-rules cond-expand include +(import (except chicken with-exception-handler include + quotient remainder modulo vector-copy!)) +(import (except scheme syntax-rules cond-expand assoc list-set! list-tail member char=? char<? char>? char<=? char>=? - string=? string<? string>? string<=? string>=?)) + string=? string<? string>? string<=? string>=? + string-copy string->list + vector->list)) (import (prefix (only scheme char=? char<? char>? char<=? char>=? string=? string<? string>? string<=? string>=?) %)) -(import (except chicken with-exception-handler raise include quotient remainder modulo)) (import (rename (only chicken include) (include %include))) -(import (rename (only srfi-4 ; TODO: utf8<->string - make-u8vector subu8vector u8vector u8vector? - u8vector-length u8vector-ref u8vector-set!) - (u8vector? bytevector?) - (make-u8vector make-bytevector) +(import (rename (only srfi-4 make-u8vector subu8vector u8vector u8vector? + u8vector-length u8vector-ref u8vector-set! + read-u8vector read-u8vector! write-u8vector) (u8vector bytevector) (u8vector-length bytevector-length) (u8vector-ref bytevector-u8-ref) - (u8vector-set! bytevector-u8-set!))) + (u8vector-set! bytevector-u8-set!) + (u8vector? bytevector?) + (make-u8vector make-bytevector) + (write-u8vector write-bytevector))) (%include "scheme.base-interface.scm") +;; For syntax definition helpers. (begin-for-syntax (require-library r7rs-compile-time)) (import-for-syntax r7rs-compile-time) (import r7rs-compile-time) (import numbers) +;; read/write-string/line/byte +(require-library extras) +(import (prefix (only extras read-string write-string) %)) +(import (rename (only extras read-line read-byte write-byte) + (read-byte read-u8) + (write-byte write-u8))) + +;; flush-output +(import (rename (only chicken flush-output) + (flush-output flush-output-port))) + +;; u8-ready? +(import (rename (only scheme char-ready?) + (char-ready? u8-ready?))) + +;; Non-R5RS string-* +(require-library srfi-13) +(import (prefix (only srfi-13 string-for-each string-map) %)) +(import (only srfi-13 string-copy string-copy! string-fill! string->list)) + ;;; ;;; 4.1.7. Inclusion ;;; (define-syntax include - (syntax-rules () - ((_ str) - (%include str)) - ((_ str . rest) - (begin - (%include str) - (include . rest))))) + (er-macro-transformer + (lambda (e r c) + (cons (r 'begin) + (append-map (cut read-forms <> #f) (cdr e)))))) + +(define-syntax include-ci + (er-macro-transformer + (lambda (e r c) + (cons (r 'begin) + (append-map (cut read-forms <> #t) (cdr e)))))) ;;; ;;; 4.2.1. Conditionals @@ -117,7 +145,7 @@ ;;; 6.2.6 Numerical operations ;;; -(: square (number --> number)) +(: square (number -> number)) (define (square n) (* n n)) @@ -240,6 +268,14 @@ (##sys#fast-reverse res) (lp (cons (car lst) res) (cdr lst))))) +;;; +;;; 6.5 Symbols +;;; + +(: symbol=? (symbol symbol #!rest symbol -> boolean)) + +(define-extended-arity-comparator symbol=? eqv? ##sys#check-symbol) + ;;; ;;; 6.6 Characters ;;; @@ -272,63 +308,287 @@ (define-extended-arity-comparator string<=? %string<=? ##sys#check-string) (define-extended-arity-comparator string>=? %string>=? ##sys#check-string) +(: string->vector (string #!optional fixnum fixnum -> (vector-of char))) +(: vector->string ((vector-of char) #!optional fixnum fixnum -> string)) + +(define string->vector + (let ((s->v (lambda (s start . end) + (##sys#check-string s 'string->vector) + (let* ((len (##sys#size s)) + (end (optional end len))) + (##sys#check-range start 0 (fx+ end 1) 'string->vector) + (##sys#check-range end start (fx+ len 1) 'string->vector) + (let ((v (##sys#make-vector (fx- end start)))) + (do ((ti 0 (fx+ ti 1)) + (fi start (fx+ fi 1))) + ((fx= fi end) v) + (##sys#setslot v ti (##core#inline "C_subchar" s fi)))))))) + (case-lambda + ((s) (s->v s 0)) + ((s start) (s->v s start)) + ((s start end) (s->v s start end))))) + +(define vector->string + (let ((v->s (lambda (v start . end) + (##sys#check-vector v 'vector->string) + (let* ((len (##sys#size v)) + (end (optional end len))) + (##sys#check-range start 0 (fx+ end 1) 'vector->string) + (##sys#check-range end start (fx+ len 1) 'vector->string) + (let ((s (##sys#make-string (fx- end start)))) + (do ((ti 0 (fx+ ti 1)) + (fi start (fx+ fi 1))) + ((fx= fi end) s) + (let ((c (##sys#slot v fi))) + (##sys#check-char c 'vector->string) + (##core#inline "C_setsubchar" s ti c)))))))) + (case-lambda + ((v) (v->s v 0)) + ((v start) (v->s v start)) + ((v start end) (v->s v start end))))) + +;;; +;;; 6.8. Vectors +;;; + +(: vector-append (#!rest vector -> vector)) +(: vector-copy (forall (a) ((vector-of a) #!optional fixnum fixnum -> (vector-of a)))) +(: vector-copy! (vector fixnum vector #!optional fixnum fixnum -> undefined)) +(: vector->list (forall (a) ((vector-of a) #!optional fixnum fixnum -> (list-of a)))) + +(define vector-copy + (let ((copy (lambda (v start . end) + (##sys#check-vector v 'vector-copy) + (let* ((len (##sys#size v)) + (end (optional end len))) + (##sys#check-range start 0 (fx+ end 1) 'vector-copy) + (##sys#check-range end start (fx+ len 1) 'vector-copy) + (let ((vec (##sys#make-vector (fx- end start)))) + (do ((ti 0 (fx+ ti 1)) + (fi start (fx+ fi 1))) + ((fx>= fi end) vec) + (##sys#setslot vec ti (##sys#slot v fi)))))))) + (case-lambda + ((v) (copy v 0)) + ((v start) (copy v start)) + ((v start end) (copy v start end))))) + +(define vector-copy! + (let ((copy! (lambda (to at from start . end) + (##sys#check-vector to 'vector-copy!) + (##sys#check-vector from 'vector-copy!) + (let* ((tlen (##sys#size to)) + (flen (##sys#size from)) + (end (optional end flen))) + (##sys#check-range at 0 (fx+ tlen 1) 'vector-copy!) + (##sys#check-range start 0 (fx+ end 1) 'vector-copy!) + (##sys#check-range end start (fx+ flen 1) 'vector-copy!) + (##sys#check-range (fx- end start) 0 (fx+ (fx- tlen at) 1) 'vector-copy!) + (do ((fi start (fx+ fi 1)) + (ti at (fx+ ti 1))) + ((fx= fi end)) + (##sys#setslot to ti (##sys#slot from fi))))))) + (case-lambda + ((to at from) (copy! to at from 0)) + ((to at from start) (copy! to at from start)) + ((to at from start end) (copy! to at from start end))))) + +(define vector->list + (let ((v->l (lambda (v start . end) + (##sys#check-vector v 'vector->list) + (let* ((len (##sys#size v)) + (end (optional end len))) + (##sys#check-range start 0 (fx+ end 1) 'vector->list) + (##sys#check-range end start (fx+ len 1) 'vector->list) + (do ((i start (fx+ i 1)) + (l '() (cons (##sys#slot v i) l))) + ((fx= i end) (##sys#fast-reverse l))))))) + (case-lambda + ((v) (v->l v 0)) + ((v start) (v->l v start)) + ((v start end) (v->l v start end))))) + +(define (vector-append . vs) + (##sys#for-each (cut ##sys#check-vector <> 'vector-append) vs) + (let* ((lens (map ##sys#size vs)) + (vec (##sys#make-vector (foldl fx+ 0 lens)))) + (do ((vs vs (cdr vs)) + (lens lens (cdr lens)) + (i 0 (fx+ i (car lens)))) + ((null? vs) vec) + (vector-copy! vec i (car vs) 0 (car lens))))) + ;;; ;;; 6.9. Bytevectors ;;; (define-type bytevector u8vector) +(: bytevector (#!rest fixnum -> bytevector)) +(: bytevector-append (#!rest bytevector -> bytevector)) (: bytevector-copy (bytevector #!optional fixnum fixnum -> bytevector)) +(: bytevector-copy! (bytevector fixnum bytevector #!optional fixnum fixnum -> undefined)) +(: bytevector-length (bytevector -> fixnum)) +(: bytevector-u8-ref (bytevector fixnum -> fixnum)) +(: bytevector-u8-set! (bytevector fixnum fixnum -> void)) +(: bytevector? (* -> boolean : bytevector)) +(: make-bytevector (fixnum #!optional fixnum -> bytevector)) +(: string->utf8 (string #!optional fixnum fixnum -> bytevector)) +(: utf8->string (bytevector #!optional fixnum fixnum -> string)) +(: write-bytevector (bytevector #!optional output-port -> fixnum)) (define bytevector-copy (case-lambda - ((v) (bytevector-copy v 0 (bytevector-length v))) - ((v s) (bytevector-copy v s (bytevector-length v))) - ((v s e) - (##sys#check-structure v 'u8vector 'bytevector-copy) - (##sys#check-exact s 'bytevector-copy) - (##sys#check-exact e 'bytevector-copy) - (unless (and (fx<= 0 s) (fx<= s e) (fx<= e (bytevector-length v))) - (error 'bytevector-copy "invalid indices" s e)) - (subu8vector v s e)))) - -(: bytevector-copy! (bytevector fixnum bytevector #!optional fixnum fixnum -> undefined)) + ((bv) + (##sys#check-structure bv 'u8vector 'bytevector-copy) + (subu8vector bv 0 (bytevector-length bv))) + ((bv start) + (##sys#check-structure bv 'u8vector 'bytevector-copy) + (subu8vector bv start (bytevector-length bv))) + ((bv start end) + (subu8vector bv start end)))) (define bytevector-copy! - (case-lambda - ((t a f) (bytevector-copy! t a f 0 (bytevector-length f))) - ((t a f s) (bytevector-copy! t a f s (bytevector-length f))) - ((t a f s e) - (##sys#check-structure t 'u8vector 'bytevector-copy!) - (##sys#check-structure f 'u8vector 'bytevector-copy!) - (##sys#check-exact a 'bytevector-copy) - (##sys#check-exact s 'bytevector-copy) - (##sys#check-exact e 'bytevector-copy) - (unless (and (fx<= 0 a) - (fx<= 0 s) - (fx<= e (bytevector-length f)) - (fx<= (fx- e s) (fx- (bytevector-length t) a))) - (error 'bytevector-copy! "invalid indices" a s e)) - (do ((s s (fx+ s 1)) - (a a (fx+ a 1))) - ((fx= s e)) - (bytevector-u8-set! t a (bytevector-u8-ref f s)))))) + (let ((copy! (lambda (to at from start . end) + (##sys#check-structure to 'u8vector 'bytevector-copy!) + (##sys#check-structure from 'u8vector 'bytevector-copy!) + (let* ((tlen (bytevector-length to)) + (flen (bytevector-length from)) + (end (optional end flen))) + (##sys#check-range at 0 (fx+ tlen 1) 'bytevector-copy!) + (##sys#check-range start 0 (fx+ end 1) 'bytevector-copy!) + (##sys#check-range end start (fx+ flen 1) 'bytevector-copy!) + (##sys#check-range (fx- end start) 0 (fx+ (fx- tlen at) 1) 'bytevector-copy!) + (do ((fi start (fx+ fi 1)) + (ti at (fx+ ti 1))) + ((fx= fi end)) + (bytevector-u8-set! to ti (bytevector-u8-ref from fi))))))) + (case-lambda + ((to at from) (copy! to at from 0)) + ((to at from start) (copy! to at from start)) + ((to at from start end) (copy! to at from start end))))) + +(define (bytevector-append . bvs) + (##sys#for-each (cut ##sys#check-structure <> 'u8vector 'bytevector-append) bvs) + (let* ((lens (map bytevector-length bvs)) + (bv (make-bytevector (foldl fx+ 0 lens)))) + (do ((bvs bvs (cdr bvs)) + (lens lens (cdr lens)) + (i 0 (fx+ i (car lens)))) + ((null? bvs) bv) + (bytevector-copy! bv i (car bvs) 0 (car lens))))) + +;; +;; XXX TODO There's nothing "utf8" about these at the moment! They +;; should check their strings ("It is an error for bytevector to contain +;; invalid UTF-8 byte sequences."). +;; + +(define utf8->string + (let ((bv->s (lambda (bv start . end) + (##sys#check-structure bv 'u8vector 'utf8->string) + (let* ((len (bytevector-length bv)) + (end (optional end len))) + (##sys#check-range start 0 (fx+ end 1) 'utf8->string) + (##sys#check-range end start (fx+ len 1) 'utf8->string) + (let ((s (##sys#make-string (fx- end start)))) + (do ((si 0 (fx+ si 1)) + (vi start (fx+ vi 1))) + ((fx= si end) s) + (##sys#setbyte s si (bytevector-u8-ref bv vi)))))))) + (case-lambda + ((bv) (bv->s bv 0)) + ((bv start) (bv->s bv start)) + ((bv start end) (bv->s bv start end))))) + +(define string->utf8 + (let ((s->bv (lambda (s start . end) + (##sys#check-string s 'string->utf8) + (let* ((len (##sys#size s)) + (end (optional end len))) + (##sys#check-range start 0 (fx+ end 1) 'string->utf8) + (##sys#check-range end start (fx+ len 1) 'string->utf8) + (let ((bv (make-bytevector (fx- end start)))) + (do ((vi 0 (fx+ vi 1)) + (si start (fx+ si 1))) + ((fx= vi end) bv) + (bytevector-u8-set! bv vi (##sys#byte s si)))))))) + (case-lambda + ((s) (s->bv s 0)) + ((s start) (s->bv s start)) + ((s start end) (s->bv s start end))))) -(: bytevector-append (#!rest bytevector -> bytevector)) +;;; +;;; 6.10. Control features +;;; -(define (bytevector-append . vs) - (for-each (cut ##sys#check-structure <> 'u8vector 'bytevector-append) vs) - (let* ((ls (map bytevector-length vs)) - (ov (make-bytevector (foldl fx+ 0 ls)))) - (let lp ((i 0) - (vs vs) - (ls ls)) - (cond ((null? vs) ov) - (else - (bytevector-copy! ov i (car vs) 0 (car ls)) - (lp (fx+ i (car ls)) - (cdr vs) - (cdr ls))))))) +(: string-for-each ((char -> *) string #!rest string -> void)) +(: string-map ((char -> char) string #!rest string -> string)) +(: vector-for-each ((* -> *) vector #!rest vector -> void)) +(: vector-map ((* -> *) vector #!rest vector -> vector)) + +(define string-map + (case-lambda + ((proc str) + (%string-map proc str)) + ((proc . strs) + (##sys#check-closure proc 'string-map) + (##sys#for-each (cut ##sys#check-string <> 'string-map) strs) + (let* ((len (foldl fxmin most-positive-fixnum (map ##sys#size strs))) + (str (##sys#make-string len))) + (do ((i 0 (fx+ i 1))) + ((fx= i len) str) + (string-set! str i (apply proc (map (cut string-ref <> i) strs)))))))) + +(define string-for-each + (case-lambda + ((proc str) + (%string-for-each proc str)) + ((proc . strs) + (##sys#check-closure proc 'string-for-each) + (##sys#for-each (cut ##sys#check-string <> 'string-for-each) strs) + (let* ((len (foldl fxmin most-positive-fixnum (map ##sys#size strs))) + (str (##sys#make-string len))) + (do ((i 0 (fx+ i 1))) + ((fx= i len) str) + (apply proc (map (cut string-ref <> i) strs))))))) + +(define vector-map + (case-lambda + ((proc v) + (##sys#check-closure proc 'vector-map) + (##sys#check-vector v 'vector-map) + (let* ((len (##sys#size v)) + (vec (##sys#make-vector len))) + (do ((i 0 (fx+ i 1))) + ((fx= i len) vec) + (##sys#setslot vec i (proc (##sys#slot v i)))))) + ((proc . vs) + (##sys#check-closure proc 'vector-map) + (##sys#for-each (cut ##sys#check-vector <> 'vector-map) vs) + (let* ((len (foldl fxmin most-positive-fixnum (map ##sys#size vs))) + (vec (##sys#make-vector len))) + (do ((i 0 (fx+ i 1))) + ((fx= i len) vec) + (##sys#setslot vec i (apply proc (map (cut vector-ref <> i) vs)))))))) + +(define vector-for-each + (case-lambda + ((proc v) + (##sys#check-closure proc 'vector-for-each) + (##sys#check-vector v 'vector-for-each) + (let ((len (##sys#size v))) + (do ((i 0 (fx+ i 1))) + ((fx= i len)) + (proc (##sys#slot v i))))) + ((proc . vs) + (##sys#check-closure proc 'vector-for-each) + (##sys#for-each (cut ##sys#check-vector <> 'vector-for-each) vs) + (let* ((len (foldl fxmin most-positive-fixnum (map ##sys#size vs))) + (vec (##sys#make-vector len))) + (do ((i 0 (fx+ i 1))) + ((fx= i len) vec) + (apply proc (map (cut vector-ref <> i) vs))))))) ;;; ;;; 6.11. Exceptions @@ -338,29 +598,31 @@ (: raise (* -> noreturn)) (: raise-continuable (* -> . *)) +(define with-exception-handler) +(define raise) +(define raise-continuable) + ;; XXX TODO: This is not threadsafe! -(define-values (with-exception-handler raise raise-continuable) - (let ((exception-handlers - (let ((lst (list ##sys#current-exception-handler))) - (set-cdr! lst lst) - lst))) - (values - ;; with-exception-handler - (lambda (handler thunk) - (dynamic-wind - (lambda () - ;; We might be interoperating with srfi-12 handlers set by intermediate - ;; non-R7RS code, so check if a new handler was set in the meanwhile. - (unless (eq? (car exception-handlers) ##sys#current-exception-handler) - (set! exception-handlers - (cons ##sys#current-exception-handler exception-handlers))) - (set! exception-handlers (cons handler exception-handlers)) - (set! ##sys#current-exception-handler handler)) - thunk - (lambda () - (set! exception-handlers (cdr exception-handlers)) - (set! ##sys#current-exception-handler (car exception-handlers))))) - ;; raise +(let ((exception-handlers + (let ((lst (list ##sys#current-exception-handler))) + (set-cdr! lst lst) + lst))) + (set! with-exception-handler + (lambda (handler thunk) + (dynamic-wind + (lambda () + ;; We might be interoperating with srfi-12 handlers set by intermediate + ;; non-R7RS code, so check if a new handler was set in the meanwhile. + (unless (eq? (car exception-handlers) ##sys#current-exception-handler) + (set! exception-handlers + (cons ##sys#current-exception-handler exception-handlers))) + (set! exception-handlers (cons handler exception-handlers)) + (set! ##sys#current-exception-handler handler)) + thunk + (lambda () + (set! exception-handlers (cdr exception-handlers)) + (set! ##sys#current-exception-handler (car exception-handlers)))))) + (set! raise (lambda (obj) (with-exception-handler (cadr exception-handlers) @@ -371,13 +633,13 @@ 'exn 'message "exception handler returned" 'arguments '() - 'location #f))))) - ;; raise-continuable + 'location #f)))))) + (set! raise-continuable (lambda (obj) (with-exception-handler (cadr exception-handlers) (lambda () - ((cadr exception-handlers) obj))))))) + ((cadr exception-handlers) obj)))))) (: error-object? (* --> boolean : (struct condition))) (: error-object-message ((struct condition) -> string)) @@ -390,32 +652,47 @@ (: read-error? (* --> boolean)) (: file-error? (* --> boolean)) -(define-values (read-error? file-error?) - (let ((exn? (condition-predicate 'exn)) - (i/o? (condition-predicate 'i/o)) - (file? (condition-predicate 'file)) - (syntax? (condition-predicate 'syntax))) - (values - ;; read-error? - (lambda (obj) - (and (exn? obj) - (or (i/o? obj) ; XXX Not fine-grained enough. - (syntax? obj)))) - ;; file-error? - (lambda (obj) - (and (exn? obj) - (file? obj)))))) - +(define read-error?) +(define file-error?) + +(let ((exn? (condition-predicate 'exn)) + (i/o? (condition-predicate 'i/o)) + (file? (condition-predicate 'file)) + (syntax? (condition-predicate 'syntax))) + (set! read-error? + (lambda (obj) + (and (exn? obj) + (or (i/o? obj) ; XXX Not fine-grained enough. + (syntax? obj))))) + (set! file-error? + (lambda (obj) + (and (exn? obj) + (file? obj))))) ;;; ;;; 6.13. Input and Output ;;; +(: binary-port? (* --> boolean)) (: call-with-port (port (port -> . *) -> . *)) (: close-port (port -> void)) -(: output-port-open? (output-port -> boolean)) -(: input-port-open? (input-port -> boolean)) (: eof-object (--> eof)) +(: input-port-open? (input-port -> boolean)) +(: output-port-open? (output-port -> boolean)) +(: peek-u8 (#!optional input-port -> fixnum)) +(: read-bytevector (number #!optional input-port -> (or bytevector eof))) +(: read-bytevector! (bytevector #!optional input-port number number -> fixnum)) +(: read-string (number #!optional input-port -> (or string eof))) +(: read-u8 (#!optional input-port -> fixnum)) +(: textual-port? (* --> boolean)) +(: u8-ready? (#!optional input-port -> boolean)) +(: write-string (string #!optional input-port fixnum fixnum -> void)) +(: write-u8 (fixnum #!optional output-port -> void)) + +;; sic, TODO + +(define binary-port? port?) +(define textual-port? port?) (define (call-with-port port proc) (receive ret @@ -440,6 +717,67 @@ (define (eof-object) #!eof) -(define flush-output-port flush-output) +(define peek-u8 + (case-lambda + (() + (char->integer (peek-char))) + ((port) + (##sys#check-input-port port #t 'peek-u8) + (char->integer (peek-char port))))) + +(define read-string + (let ((read-string/eof (lambda (k port) + (##sys#check-input-port port #t 'read-string) + (if (eof-object? (peek-char port)) + #!eof + (%read-string k port))))) + (case-lambda + ((k) + (read-string/eof k ##sys#standard-input)) + ((k port) + (read-string/eof k port))))) + +(define write-string + (case-lambda + ((s) + (%write-string s #f ##sys#standard-output)) + ((s port) + (%write-string s #f port)) + ((s port start) + (##sys#check-string s 'write-string) + (let ((len (##sys#size s))) + (##sys#check-range start 0 (fx+ len 1) 'write-string) + (%write-string (##sys#substring s start len) #f port))) + ((s port start end) + (##sys#check-string s 'write-string) + (##sys#check-range start 0 (fx+ end 1) 'write-string) + (##sys#check-range end start (fx+ (##sys#size s) 1) 'write-string) + (%write-string (##sys#substring s start end) #f port)))) + +(define read-bytevector + (let ((read-u8vector/eof + (lambda (k port) + (let ((bv (read-u8vector k port))) + (if (fx= 0 (bytevector-length bv)) #!eof bv))))) + (case-lambda + ((k) + (read-u8vector/eof k ##sys#standard-input)) + ((k port) + (read-u8vector/eof k port))))) + +(define read-bytevector! + (let ((read-u8vector!/eof + (lambda (k bv . args) + (let ((r (apply read-u8vector! k bv args))) + (if (fx= r 0) #!eof r))))) + (case-lambda + ((bv) + (read-u8vector!/eof #f bv)) + ((bv port) + (read-u8vector!/eof #f bv port)) + ((bv port start) + (read-u8vector!/eof #f bv port start)) + ((bv port start end) + (read-u8vector!/eof (fx- end start) bv port start))))) ) diff --git a/scheme.file.scm b/scheme.file.scm index 7e783cc..c83f4d3 100644 --- a/scheme.file.scm +++ b/scheme.file.scm @@ -2,14 +2,15 @@ call-with-output-file call-with-input-file delete-file - ; TODO open-binary-input-file + open-binary-input-file open-input-file with-input-from-file call-with-output-file file-exists? - ; TODO open-binary-output-file + open-binary-output-file open-output-file with-output-to-file) + (import scheme) (import (rename (only chicken delete-file file-exists? :) (file-exists? chicken-file-exists?))) @@ -22,4 +23,10 @@ (define (file-exists? filename) (and (chicken-file-exists? filename) #t)) + (: open-binary-input-file (string -> input-port)) + (: open-binary-output-file (string -> output-port)) + + (define (open-binary-input-file path) (open-input-file path #:binary)) + (define (open-binary-output-file path) (open-output-file path #:binary)) + ) diff --git a/scheme.lazy.scm b/scheme.lazy.scm new file mode 100644 index 0000000..362e3e4 --- /dev/null +++ b/scheme.lazy.scm @@ -0,0 +1,6 @@ +(module scheme.lazy (delay + delay-force + force + make-promise + promise?) + (import scheme chicken)) diff --git a/scheme.load.scm b/scheme.load.scm index c15a856..f664f86 100644 --- a/scheme.load.scm +++ b/scheme.load.scm @@ -1,3 +1,14 @@ (module scheme.load (load) + (import chicken) + (import (rename scheme (load %load) + (eval %eval))) - (import scheme)) + (: load (string #!optional (struct environment) -> undefined)) + + (define load + (case-lambda + ((filename) + (%load filename)) + ((filename environment) + (%load filename (lambda (exp) + (%eval exp environment))))))) diff --git a/scheme.process-context.scm b/scheme.process-context.scm index 169db2b..22dabe2 100644 --- a/scheme.process-context.scm +++ b/scheme.process-context.scm @@ -1,10 +1,8 @@ (module scheme.process-context (command-line - exit emergency-exit - ;;XXX - ;get-environment-variable - ;get-environment-variables - ) + exit + get-environment-variable + get-environment-variables) (import scheme (rename chicken (exit chicken:exit)) @@ -15,13 +13,41 @@ ;;; (: command-line (-> (list-of string))) -(: exit (* -> noreturn)) -(: emergency-exit (* -> noreturn)) +(: get-environment-variables (-> (list-of (pair string string)))) +(: exit (#!optional * -> noreturn)) +(: emergency-exit (#!optional * -> noreturn)) (define (command-line) ;; Don't cache these; they may be parameterized at any time! (cons (program-name) (command-line-arguments))) +;; XXX get-environment-variables copied from posixunix.scm. +;; (And not actually expected to work on other platforms yet.) + +#> +#ifdef __APPLE__ +# include <crt_externs.h> +# define C_getenventry(i) ((*_NSGetEnviron())[ i ]) +#else +extern char **environ; +# define C_getenventry(i) (environ[ i ]) +#endif +<# + +(define get-environment-variables + (let ([get (foreign-lambda c-string "C_getenventry" int)]) + (lambda () + (let loop ([i 0]) + (let ([entry (get i)]) + (if entry + (let scan ([j 0]) + (if (char=? #\= (##core#inline "C_subchar" entry j)) + (cons (cons (##sys#substring entry 0 j) + (##sys#substring entry (fx+ j 1) (##sys#size entry))) + (loop (fx+ i 1))) + (scan (fx+ j 1)) ) ) + '())))))) + (define (->exit-status obj) (cond ((integer? obj) obj) ((eq? obj #f) 1) diff --git a/scheme.repl.scm b/scheme.repl.scm new file mode 100644 index 0000000..fd95054 --- /dev/null +++ b/scheme.repl.scm @@ -0,0 +1,2 @@ +(module scheme.repl (interaction-environment) + (import scheme)) diff --git a/scheme.time.scm b/scheme.time.scm new file mode 100644 index 0000000..3951771 --- /dev/null +++ b/scheme.time.scm @@ -0,0 +1,8 @@ +(module scheme.time (current-second + current-jiffy + jiffies-per-second) + (import scheme) + (import (rename chicken (current-seconds current-second))) + ;; sic, XXX, TODO, etc. + (define current-jiffy current-second) + (define (jiffies-per-second) 1)) diff --git a/tests/include-ci.scm b/tests/include-ci.scm new file mode 100644 index 0000000..9fa9c33 --- /dev/null +++ b/tests/include-ci.scm @@ -0,0 +1 @@ +(DISPLAY "abc") diff --git a/tests/include.scm b/tests/include.scm new file mode 100644 index 0000000..217e174 --- /dev/null +++ b/tests/include.scm @@ -0,0 +1 @@ +(display "abc") diff --git a/tests/run.scm b/tests/run.scm index 1032672..3749247 100644 --- a/tests/run.scm +++ b/tests/run.scm @@ -10,7 +10,6 @@ (ports) (scheme base) (scheme char) - (scheme eval) (scheme file) (scheme read) (scheme write)) @@ -20,6 +19,25 @@ (test-begin "r7rs tests") +(test-group "4.1.7: Inclusion" + (test-group "include" + (test "multiple filenames" + "abcabc" + (with-output-to-string + (lambda () (include "include.scm" "include.scm")))) + (test-error "case sensitivity" + (with-output-to-string + (lambda () (include "include-ci.scm"))))) + (test-group "include-ci" + (test "multiple filenames" + "abcabc" + (with-output-to-string + (lambda () (include-ci "include.scm" "include.scm")))) + (test "case sensitivity" + "abc" + (with-output-to-string + (lambda () (include-ci "include-ci.scm")))))) + (test-group "6.2.6: numerical operations" (test-group "floor/...truncate-remainder" (test '(2 1) (receive (floor/ 5 2))) @@ -75,7 +93,12 @@ (test 1 (remainder 13 -4)) (test -1 (modulo -13 -4)) (test -1 (remainder -13 -4)) - (test -1.0 (remainder -13 -4.0)))) + (test -1.0 (remainder -13 -4.0))) + + (test-group "square" + (test 1 (square 1)) + (test 16 (square 4)) + (test 16.0 (square 4.0)))) (test-group "6.3: booleans" ;; How silly... @@ -309,6 +332,24 @@ (test '((3 8 2 8)) (list b)) (test '((1 8 2 8)) (list a)))) +(test-group "6.5: Symbols" + (test-group "symbol=?" + (test-error (symbol=?)) + (test-error (symbol=? 'a)) + (test-error (symbol=? 'a 1)) + (test-error (symbol=? 'a 'b 1)) + (test #t (symbol=? '|| '||)) + (test #t (symbol=? '|a b| '|a b|)) + (test #t (symbol=? 'a 'a)) + (test #f (symbol=? 'a 'b)) + (test #t (symbol=? 'a 'a 'a)) + (test #f (symbol=? 'a 'a 'b)) + (test #f (symbol=? 'a 'b 'b)) + (test #t (symbol=? 'a 'a 'a 'a)) + (test #f (symbol=? 'a 'a 'a 'b)) + (test #f (symbol=? 'a 'a 'b 'b)) + (test #f (symbol=? 'a 'b 'b 'b)))) + (test-group "6.6: characters" (test-group "char*?" (test-error "arity" (char=? #\a)) @@ -334,6 +375,7 @@ (test #f (char>=? #\b #\a #\b)))) (test-group "6.7: strings" + (test-group "string*?" (test-error "arity" (string=? "a")) (test-error "type check" (string=? "a" "a" 1)) @@ -355,7 +397,87 @@ (test #t (string>? "c" "b" "a")) (test #f (string>? "c" "b" "b")) (test #t (string>=? "b" "b" "a")) - (test #f (string>=? "b" "a" "b")))) + (test #f (string>=? "b" "a" "b"))) + + (test-group "string->list" + (test-error (string->list "" 1)) + (test-error (string->list "a" 1 2)) + (test '(#\a) (string->list "a")) + (test '() (string->list "a" 1)) + (test '(#\b) (string->list "abc" 1 2)) + (test '() (string->list "abc" 2 2))) + + (test-group "string->vector" + (test-error (string->vector "" 1)) + (test-error (string->vector "a" 0 2)) + (test #(#\a) (string->vector "a")) + (test #() (string->vector "a" 1 1)) + (test #(#\b) (string->vector "abc" 1 2)) + (test #() (string->vector "abc" 2 2))) + + (test-group "vector->string" + (test-error (vector->string #() 1)) + (test-error (vector->string #(1))) + (test-error (vector->string #(#\a) 0 2)) + (test "a" (vector->string #(#\a))) + (test "" (vector->string #(#\a) 1 1)) + (test "b" (vector->string #(#\a #\b #\c) 1 2)) + (test "" (vector->string #(#\a #\b #\c) 2 2)))) + +(test-group "6.8: vectors" + + (test-group "vector-copy" + (test-error (vector-copy "")) + (test-error (vector-copy #() #())) + (test-error (vector-copy #() 1)) + (test-error (vector-copy #(0) -1)) + (test-error (vector-copy #(0) 0 2)) + (test #() (vector-copy #())) + (test #(0 1 2) (vector-copy #(0 1 2))) + (test #(1 2) (vector-copy #(0 1 2) 1)) + (test #(1) (vector-copy #(0 1 2) 1 2)) + (test #() (vector-copy #(0 1 2) 1 1))) + + (test-group "vector-copy!" + (test-error (vector-copy! "")) + (test-error (vector-copy! #(0) 0 "")) + (test-error (vector-copy! #() #() 0)) + (test-error (vector-copy! #() 0 #(0))) + (test-error (vector-copy! #(0) 1 #(0))) + (test-error (vector-copy! #(0) 1 #(0) 0)) + (test-error (vector-copy! #(0) 0 #(0) 0 2)) + (test-error (vector-copy! #(0) 0 #(0 1) 1 0)) + (test-assert (vector-copy! #() 0 #())) + (let ((t #(0 1 2)) + (f #(3 4 5 6))) + (vector-copy! t 0 f 1 1) + (test "(vector-copy! t 1 f 1 1)" #(0 1 2) t) + (vector-copy! t 0 f 0 1) + (test "(vector-copy! t 0 f 0 1)" #(3 1 2) t) + (vector-copy! t 0 f 1 3) + (test "(vector-copy! t 0 f 1 3)" #(4 5 2) t) + (vector-copy! t 1 f 2) + (test "(vector-copy! t 1 f 1)" #(4 5 6) t) + (vector-copy! t 0 f 1) + (test "(vector-copy! t 0 f)" #(4 5 6) t))) + + (test-group "vector-append" + (test-error (vector-append "")) + (test-error (vector-append #() 1)) + (test #() (vector-append)) + (test #(0) (vector-append #(0))) + (test #() (vector-append #() #())) + (test #(0 1) (vector-append #(0) #(1))) + (test #(0 1 2 3 4 5) (vector-append #(0 1) #(2 3) #(4 5)))) + + (test-group "vector->list" + (test-error (vector->list "")) + (test-error (vector->list #() 1)) + (test '() (vector->list #())) + (test '(0 1 2) (vector->list #(0 1 2))) + (test '(1 2) (vector->list #(0 1 2) 1)) + (test '(1) (vector->list #(0 1 2) 1 2)) + (test '() (vector->list #(0 1 2) 2 2)))) (test-group "6.9: bytevectors" @@ -402,6 +524,75 @@ (test #u8(0 1) (bytevector-append #u8(0) #u8(1))) (test #u8(0 1 2 3 4 5) (bytevector-append #u8(0 1) #u8(2 3) #u8(4 5))))) +(test-group "6.10: Control features" + + (define (1st . a) (first a)) + (define (2nd . a) (second a)) + (define (acc proc f . rest) ; accumulate results of `f` + (let ((a '())) + (apply proc (lambda args (set! a (cons (apply f args) a))) rest) + (reverse a))) + + (define char-add1 + (compose integer->char add1 char->integer)) + + (test-group "string-map" + (test-error (string-map "abc")) + (test-error (string-map values)) + (test-error (string-map values '(1 2 3))) + (test-error (string-map (constantly 1) "abc")) + (test "" (string-map values "")) + (test "abc" (string-map values "abc")) + (test "aaa" (string-map (constantly #\a) "abc")) + (test "bcd" (string-map char-add1 "abc")) + (test "abc" (string-map 1st "abc" "123")) + (test "123" (string-map 2nd "abc" "123")) + (test "abc" (string-map 1st "abc" "123456")) + (test "123" (string-map 2nd "abc" "123456"))) + + (test-group "string-for-each" + (test-error (string-for-each "abc")) + (test-error (string-for-each values)) + (test-error (string-for-each values '(1 2 3))) + (test '() (acc string-for-each values "")) + (test '(#\a #\b #\c) (acc string-for-each values "abc")) + (test '(#\b #\c #\d) (acc string-for-each char-add1 "abc")) + (test '((#\a #\1) (#\b #\2) (#\c #\3)) (acc string-for-each list "abc" "123")) + (test '(#\1 #\2 #\3) (acc string-for-each 2nd "abc" "123")) + (test '(#\a #\b #\c) (acc string-for-each 1st "abc" "123456")) + (test '(#\1 #\2 #\3) (acc string-for-each 2nd "abc" "123456"))) + + (test-group "vector-map" + (test-error (vector-map #(1 2 3))) + (test-error (vector-map values)) + (test-error (vector-map values '(1 2 3))) + (test #() (vector-map values #())) + (test #(1 2 3) (vector-map values #(1 2 3))) + (test #(1 1 1) (vector-map (constantly 1) #(1 2 3))) + (test #(2 3 4) (vector-map add1 #(1 2 3))) + (test #(1 2 3) (vector-map 1st #(1 2 3) #(4 5 6))) + (test #(4 5 6) (vector-map 2nd #(1 2 3) #(4 5 6))) + (test #(1 2 3) (vector-map 1st #(1 2 3) #(4 5 6 7 8 9))) + (test #(4 5 6) (vector-map 2nd #(1 2 3) #(4 5 6 7 8 9)))) + + (test-group "vector-for-each" + (test-error (vector-for-each #(1 2 3))) + (test-error (vector-for-each values)) + (test-error (vector-for-each values '(1 2 3))) + (test '() (acc vector-for-each values #())) + (test '(1 2 3) (acc vector-for-each values #(1 2 3))) + (test '(2 3 4) (acc vector-for-each add1 #(1 2 3))) + (test '((1 4) (2 5) (3 6)) (acc vector-for-each list #(1 2 3) #(4 5 6))) + (test '(4 5 6) (acc vector-for-each 2nd #(1 2 3) #(4 5 6))) + (test '(1 2 3) (acc vector-for-each 1st #(1 2 3) #(4 5 6 7 8 9))) + (test '(4 5 6) (acc vector-for-each 2nd #(1 2 3) #(4 5 6 7 8 9))))) + +(test-group "6.13: Input" + (test-assert "read-string returns eof-object for empty string" + (eof-object? (with-input-from-string "" (lambda () (read-string 1))))) + (test-assert "read-bytevector returns eof-object for empty string" + (eof-object? (with-input-from-string "" (lambda () (read-bytevector 1)))))) + (define-syntax catch (syntax-rules () ((_ . body) (handle-exceptions e e . body))))Trap