~ chicken-r7rs (master) f26fa02acd5737e0b872cd1dd3a63b77f37f4179
commit f26fa02acd5737e0b872cd1dd3a63b77f37f4179 Author: Evan Hanson <evhan@foldling.org> AuthorDate: Mon May 26 19:53:42 2014 +0000 Commit: Evan Hanson <evhan@foldling.org> CommitDate: Mon May 26 19:53:42 2014 +0000 Generative d-r-t, remove ports dep, misc cleanup diff --git a/NOTES.org b/NOTES.org index 65f8931..100b899 100644 --- a/NOTES.org +++ b/NOTES.org @@ -1,12 +1,5 @@ NOTES - -* Redefinition of "import" may be tricky, as it is implicit and not in any module. - - 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. @@ -23,10 +16,9 @@ NOTES * 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 + - this seems to be the standard amongst other Schemes that support R7RS-style libs - 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-module.scm b/r7rs-compile-time-module.scm index 0ff9be8..5f004d3 100644 --- a/r7rs-compile-time-module.scm +++ b/r7rs-compile-time-module.scm @@ -3,6 +3,7 @@ process-cond-expand fixup-import/export-spec parse-library-name + wrap-er-macro-transformer import-transformer read-forms register-r7rs-module diff --git a/r7rs-compile-time.scm b/r7rs-compile-time.scm index 854df7d..cc4eba4 100644 --- a/r7rs-compile-time.scm +++ b/r7rs-compile-time.scm @@ -80,19 +80,26 @@ (else (syntax-error loc "invalid import/export specifier" spec)))) -(define (import-transformer type) +(define (wrap-er-macro-transformer name handler) (er-macro-transformer - (let ((%import (caddr (assq type (##sys#macro-environment))))) ; XXX safe? + (let ((orig (caddr (assq name (##sys#macro-environment))))) (lambda (x r c) - `(##core#begin - ,@(map (lambda (spec) - (let ((spec (fixup-import/export-spec spec type)) - (name (import/export-spec-feature-name spec type))) - (%import (list type spec) '() (##sys#current-environment)) - (if (memq name '(scheme foreign)) ; XXX others? - '(##core#undefined) - `(##core#require-extension (,name) #f)))) - (strip-syntax (cdr x)))))))) + (let ((e (##sys#current-environment))) + (handler x r c (lambda (x*) (orig x* '() e)))))))) + +(define (import-transformer type) + (wrap-er-macro-transformer + type + (lambda (x r c import) + `(##core#begin + ,@(map (lambda (spec) + (let ((spec (fixup-import/export-spec spec type)) + (name (import/export-spec-feature-name spec type))) + (import (list type spec)) + (if (memq name '(scheme foreign)) ; XXX others? + '(##core#undefined) + `(##core#require-extension (,name) #f)))) + (strip-syntax (cdr x))))))) (define (read-forms filename ci?) (parameterize ((case-sensitive (not ci?))) @@ -162,7 +169,7 @@ (##core#module ,real-name ((,dummy-export)) ;; gruesome hack: we add a dummy export for adding indirect exports - (##core#define-syntax ,dummy-export (##core#lambda () #f)) + (##core#define-syntax ,dummy-export (##core#lambda _ '(##core#undefined))) ;; Another gruesome hack: provide feature so "use" works properly (##sys#provide (##core#quote ,real-name)) ;; Set up an R7RS environment for the module's body. @@ -172,7 +179,7 @@ (_ (syntax-error 'define-library "invalid library definition" form)))) (define (register-r7rs-module name) - (let ((dummy (string->symbol (string-append (symbol->string name) "-dummy-export")))) + (let ((dummy (string->symbol (conc "\x04r7rs" name)))) (put! name '##r7rs#module dummy) dummy)) diff --git a/scheme.base-interface.scm b/scheme.base-interface.scm index 9f9cc5a..0dd0025 100644 --- a/scheme.base-interface.scm +++ b/scheme.base-interface.scm @@ -7,7 +7,7 @@ apply assoc assq assv begin - binary-port? ; XXX + binary-port? boolean? boolean=? bytevector bytevector-append @@ -33,9 +33,9 @@ cons current-input-port current-output-port current-error-port define - define-record-type ; TODO + define-record-type define-syntax - define-values ; TODO + define-values denominator numerator do dynamic-wind @@ -143,7 +143,7 @@ #| syntax-rules ; provided by the "r7rs" module |# - textual-port? ; XXX + textual-port? truncate truncate/ truncate-quotient truncate-remainder u8-ready? diff --git a/scheme.base.scm b/scheme.base.scm index 3074371..f87b183 100644 --- a/scheme.base.scm +++ b/scheme.base.scm @@ -6,8 +6,7 @@ assoc list-set! list-tail member char=? char<? char>? char<=? char>=? string=? string<? string>? string<=? string>=? - string-copy string->list - vector->list)) + string-copy string->list vector->list)) (import (prefix (only scheme char=? char<? char>? char<=? char>=? string=? string<? string>? string<=? string>=?) %)) @@ -23,8 +22,6 @@ (make-u8vector make-bytevector) (write-u8vector write-bytevector))) -(import (only ports make-input-port make-output-port)) - (%include "scheme.base-interface.scm") ;; For syntax definition helpers. @@ -53,6 +50,9 @@ (import (prefix (only srfi-13 string-for-each string-map) %)) (import (only srfi-13 string-copy string-copy! string-fill! string->list)) +;; For d-r-t redefinition. +(import-for-syntax (only chicken define-record-type)) + ;;; ;;; 4.1.7. Inclusion ;;; @@ -143,6 +143,26 @@ (lambda () (apply values args)))))))))))))) +;;; +;;; 5.5 Record-type definitions +;;; + +;; Rewrite the standard d-r-t expansion so that each newly-defined +;; record type has a unique type tag. This is every kind of hacky. +(define-syntax define-record-type + (wrap-er-macro-transformer + 'define-record-type + (lambda (e r c define-record-type) + (let ((name (cadr e)) + (tag (gensym "\x04r7rsrecord-type-tag"))) + `(##core#begin + (##core#set! ,(r tag) + (##sys#make-symbol ,(symbol->string name))) + ,(let lp ((x (define-record-type e))) + (cond ((equal? x `(##core#quote ,name)) (r tag)) + ((pair? x) (cons (lp (car x)) (lp (cdr x)))) + (else x)))))))) + ;;; ;;; 6.2.6 Numerical operations ;;; @@ -155,21 +175,9 @@ ;;; 6.3 Booleans ;;; -;(: boolean=? ((procedure #:enforce) (boolean boolean #!rest boolean) boolean)) (: boolean=? (boolean boolean #!rest boolean -> boolean)) -(define (boolean=? b1 b2 . rest) - (##sys#check-boolean b1 'boolean=?) - ;; Loop across all args, checking for booleans. Don't shortcut and - ;; stop when we find nonequality. - (let lp ((b1 b1) - (b2 b2) - (rest rest) - (result (eq? b1 b2))) - (##sys#check-boolean b2 'boolean=?) - (if (null? rest) - (and result (eq? b1 b2)) - (lp b2 (car rest) (cdr rest) (and result (eq? b1 b2)))))) +(define-extended-arity-comparator boolean=? eq? ##sys#check-boolean) ;;; @@ -647,7 +655,7 @@ (: error-object-message ((struct condition) -> string)) (: error-object-irritants ((struct condition) -> list)) -(define error-object? condition?) +(define (error-object? o) (condition? o)) (define error-object-message (condition-property-accessor 'exn 'message)) (define error-object-irritants (condition-property-accessor 'exn 'arguments)) @@ -675,7 +683,7 @@ ;;; 6.13. Input and Output ;;; -(: binary-port? (* --> boolean)) +(: binary-port? (* --> boolean : port?)) (: call-with-port (port (port -> . *) -> . *)) (: close-port (port -> void)) (: eof-object (--> eof)) @@ -686,15 +694,14 @@ (: 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)) +(: textual-port? (* --> boolean : port?)) (: 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?) +;; CHICKEN's ports can handle both. +(define (binary-port? port) (port? port)) +(define (textual-port? port) (port? port)) (define (call-with-port port proc) (receive ret @@ -713,6 +720,7 @@ (define (output-port-open? port) (##sys#check-output-port port #f 'output-port-open?) (not (port-closed? port))) + (define (input-port-open? port) (##sys#check-input-port port #f 'input-port-open?) (not (port-closed? port))) @@ -787,22 +795,33 @@ (read-u8vector!/eof (fx- end start) bv port start))))) (define (open-input-bytevector bv) - (let ((index 0) - (bv-len (bytevector-length bv))) - (make-input-port - (lambda () ; read-char - (if (= index bv-len) - (eof-object) - (let ((c (bytevector-u8-ref bv index))) - (set! index (+ index 1)) - (integer->char c)))) - (lambda () ; char-ready? - (not (= index bv-len))) - (lambda () #t) ; close - (lambda () ; peek-char - (if (= index bv-len) - (eof-object) - (bytevector-u8-ref bv index)))))) + (let ((port (##sys#make-port #t #f "(bytevector)" 'custom))) + (##sys#setslot + port + 2 + (let ((index 0) + (bv-len (bytevector-length bv))) + (vector (lambda (_) ; read-char + (if (fx= index bv-len) + (eof-object) + (let ((c (bytevector-u8-ref bv index))) + (set! index (fx+ index 1)) + (integer->char c)))) + (lambda (_) ; peek-char + (if (fx= index bv-len) + (eof-object) + (bytevector-u8-ref bv index))) + #f ; write-char + #f ; write-string + (lambda (_) ; close + (##sys#setislot port 8 #t)) + #f ; flush-output + (lambda (_) ; char-ready? + (not (fx= index bv-len))) + #f ; read-string! + #f ; read-line + #f))) ; read-buffered + port)) (define (open-output-bytevector) (open-output-string)) diff --git a/tests/run.scm b/tests/run.scm index 66e93b4..e6abac7 100644 --- a/tests/run.scm +++ b/tests/run.scm @@ -973,6 +973,12 @@ (import (scheme base)) (begin (eq? numbers#+ +))))) +(test-group "define-record-type" + (define-record-type foo (make-foo) foo?) + (define foo (make-foo)) + (test-assert "Record instances satisfy their predicates" (foo? foo)) + (define-record-type foo (make-foo) foo?) + (test-assert "Record type definitions are generative" (not (foo? foo)))) (test-group "open-input-bytevector" (test (bytevector 0 1 2 10 13 40 41 42 128 140 240 255)Trap