;;;; type-checks-structured.scm -*- Scheme -*- ;;;; Kon Lovett, Jul '18 (declare (bound-to-procedure ##sys#structure?)) (module type-checks-structured (;export check-procedure check-closure check-input-port check-output-port check-list check-alist check-plist check-pair check-blob check-vector check-structure check-record check-record-type check-string ; define-check-structure) (import scheme) (import (chicken base)) ; for `include' (import (chicken type)) (import (chicken syntax)) (import (only (chicken blob) blob?)) (import type-errors-structured type-checks-basic) ;(import-for-syntax (only (chicken base) symbol-append)) (: check-structure (* 'a * #!optional * -> 'a)) (: check-record (* 'a * #!optional * -> 'a)) (: check-record-type (* 'a * #!optional * -> 'a)) (: check-string (* * #!optional * -> string)) (: check-procedure (* * #!optional * -> procedure)) (: check-closure (* * #!optional * -> procedure)) (: check-input-port (* * #!optional * -> input-port)) (: check-output-port (* * #!optional * -> output-port)) (: check-list (* * #!optional * -> list)) (: check-plist (* 'a #!optional * -> 'a)) (: check-alist (* 'a #!optional * -> 'a)) (: check-pair (* * #!optional * -> pair)) (: check-blob (* * #!optional * -> blob)) (: check-vector (* * #!optional * -> vector)) (cond-expand (unsafe (define alist? (lambda _ #t)) (define plist? (lambda _ #t)) (define (check-structure loc obj . _) obj) (define (check-record loc obj . _) obj) (define (check-record-type loc obj . _) obj) ) (else ;;These are weak predicates. Only check for structure. (define (alist? obj) (or (null? obj) (and (pair? obj) (let loop ((ls obj)) (or (null? ls) ;since anything can be a key no stronger check possible (and (pair? (car ls)) (loop (cdr ls) ) ) ) ) ) ) ) (define (plist? obj) ;since anything can be a key no stronger check possible (and (list? obj) (even? (length obj))) ) ;; ;NOTE the module must export the tag as a binding, not all do! (allows generated tags) (define (check-structure loc obj tag . args) (unless (##sys#structure? obj tag) (error-structure loc obj tag (optional args))) obj ) (define (check-record loc obj tag . args) (unless (##sys#structure? obj tag) (error-record loc obj tag (optional args))) obj ) (define (check-record-type loc obj tag . args) (unless (##sys#structure? obj tag) (error-record-type loc obj tag (optional args))) obj ) ) ) ;; (define-check-type string) (define-check-type procedure) (define check-closure check-procedure) (define-check-type input-port) (define-check-type output-port) (define-check-type list) (define-check-type plist) (define-check-type alist) (define-check-type pair) (define-check-type blob) (define-check-type vector) ;NOTE the module must export the tag as a binding, not all do! (allows generated tags) (define-syntax define-check-structure (er-macro-transformer (lambda (frm rnm cmp) (let ((_define (rnm 'define)) (_apply (rnm 'apply)) (_check-structure (rnm 'check-structure))) (let* ((tag-var (cadr frm)) (nam (symbol-append 'check- (strip-syntax tag-var))) ) ;FIXME apply for known, single, optional arg - #!optional needs rnm? `(,_define (,nam loc obj . args) (,_apply ,_check-structure loc obj ,tag-var args)) ) ) ) ) ) ) ;module type-checks-structured