~ chicken-core (master) /r7lib.scm
Trap1;;;; r7lib.scm - R7RS library code2;3; Copyright (c) 2022, The CHICKEN Team4; All rights reserved.5;6; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following7; conditions are met:8;9; Redistributions of source code must retain the above copyright notice, this list of conditions and the following10; disclaimer.11; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following12; disclaimer in the documentation and/or other materials provided with the distribution.13; Neither the name of the author nor the names of its contributors may be used to endorse or promote14; products derived from this software without specific prior written permission.15;16; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS17; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY18; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR19; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR20; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY22; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR23; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE24; POSSIBILITY OF SUCH DAMAGE.2526(declare27 (unit r7lib)28 (disable-interrupts))2930(include "common-declarations.scm")3132(module scheme.write (display33 write34 write-shared35 write-simple)36 (import (rename scheme (display display-simple) (write write-simple))37 (only chicken.base foldl when optional)38 (only chicken.fixnum fx+ fx= fx<= fx-))3940 (define (interesting? o)41 (or (pair? o)42 (and (vector? o)43 (fx<= 1 (##sys#size o)))))4445 (define (uninteresting? o)46 (not (interesting? o)))4748 (define (display-char c p)49 ((##sys#slot (##sys#slot p 2) 2) p c))5051 (define (display-string s p)52 (let ((bv (##sys#slot s 0)))53 ((##sys#slot (##sys#slot p 2) 3) p bv 0 (fx- (##sys#size bv) 1))))5455 ;; Build an alist mapping `interesting?` objects to boolean values56 ;; indicating whether those objects occur shared in `o`.57 (define (find-shared o cycles-only?)5859 (define seen '())60 (define (seen? x) (assq x seen))61 (define (seen! x) (set! seen (cons (cons x 1) seen)))6263 ;; Walk the form, tallying the number of times each object is64 ;; encountered. This has the effect of filling `seen` with65 ;; occurence counts for all objects satisfying `interesting?`.66 (let walk! ((o o))67 (when (interesting? o)68 (cond ((seen? o) =>69 (lambda (p)70 (##sys#setslot p 1 (fx+ (cdr p) 1))))71 ((pair? o)72 (seen! o)73 (walk! (car o))74 (walk! (cdr o)))75 ((vector? o)76 (seen! o)77 (let ((len (##sys#size o)))78 (do ((i 0 (fx+ i 1)))79 ((fx= i len))80 (walk! (##sys#slot o i))))))81 ;; If we're only interested in cycles and this object isn't82 ;; self-referential, discount it (resulting in `write` rather83 ;; than `write-shared` behavior).84 (when cycles-only?85 (let ((p (seen? o)))86 (when (fx<= (cdr p) 1)87 (##sys#setslot p 1 0))))))8889 ;; Mark shared objects #t, unshared objects #f.90 (foldl (lambda (a p)91 (if (fx<= (cdr p) 1)92 (cons (cons (car p) #f) a)93 (cons (cons (car p) #t) a)))94 '()95 seen))9697 (define (write-with-shared-structure writer obj cycles-only? port)9899 (define label 0)100 (define (assign-label! pair)101 (##sys#setslot pair 1 label)102 (set! label (fx+ label 1)))103104 (define shared105 (find-shared obj cycles-only?))106107 (define (write-interesting/shared o)108 (cond ((pair? o)109 (display-char #\( port)110 (write/shared (car o))111 (let loop ((o (cdr o)))112 (cond ((null? o)113 (display-char #\) port))114 ((and (pair? o)115 (not (cdr (assq o shared))))116 (display-char #\space port)117 (write/shared (car o))118 (loop (cdr o)))119 (else120 (display-string " . " port)121 (write/shared o)122 (display-char #\) port)))))123 ((vector? o)124 (display-string "#(" port)125 (write/shared (##sys#slot o 0))126 (let ((len (##sys#size o)))127 (do ((i 1 (fx+ i 1)))128 ((fx= i len)129 (display-char #\) port))130 (display-char #\space port)131 (write/shared (##sys#slot o i)))))))132133 (define (write/shared o)134 (if (uninteresting? o)135 (writer o port)136 (let* ((p (assq o shared))137 (d (cdr p)))138 (cond ((not d)139 (write-interesting/shared o))140 ((number? d)141 (display-char #\# port)142 (writer d port)143 (display-char #\# port))144 (else145 (display-char #\# port)146 (writer label port)147 (display-char #\= port)148 (assign-label! p)149 (write-interesting/shared o))))))150151 (write/shared obj))152153 (define (display o #!optional (p ##sys#standard-output))154 (write-with-shared-structure155 display-simple156 o157 #t158 p))159160 (define (write o #!optional (p ##sys#standard-output))161 (write-with-shared-structure162 write-simple163 o164 #t165 p))166167 (define (write-shared o #!optional (p ##sys#standard-output))168 (write-with-shared-structure169 write-simple170 o171 #f172 p))173174)175176(module scheme.time (current-second177 current-jiffy178 jiffies-per-second)179 (import (only chicken.base define-constant)180 (chicken foreign)181 (only chicken.time current-seconds)182 (only scheme + define inexact->exact))183184 ;; As of 2012-06-30.185 (define-constant tai-offset 35.)186187 (define (current-second) (+ (current-seconds) tai-offset))188189 (define current-jiffy (foreign-lambda long "C_current_jiffy"))190191 (define jiffies-per-second (foreign-lambda long "C_jiffies_per_second"))192193)194195(module scheme.file (file-exists? delete-file196 open-input-file open-binary-input-file197 open-output-file open-binary-output-file198 call-with-input-file call-with-output-file199 with-input-from-file with-output-to-file)200 (import (only scheme and define quote let apply open-input-file open-output-file call-with-input-file201 call-with-output-file with-input-from-file with-output-to-file)202 (rename (only (chicken file) delete-file file-exists?) (file-exists? file-exists?/base)))203204 (define (open-binary-input-file fname . args)205 (let ((p (apply open-input-file fname #:binary args)))206 (##sys#setslot p 14 'binary)207 p))208209 (define (open-binary-output-file fname . args)210 (let ((p (apply open-output-file fname #:binary args)))211 (##sys#setslot p 14 'binary)212 p))213214 (define (file-exists? fname)215 (and (file-exists?/base fname) #t))216217)218219(module scheme.process-context (command-line220 emergency-exit221 exit222 get-environment-variable223 get-environment-variables)224 (import scheme225 chicken.process-context226 chicken.type227 (rename chicken.base (exit chicken-exit)))228229(define (command-line)230 ;; Don't cache these; they may be parameterized at any time!231 (cons (program-name) (command-line-arguments)))232233(define (->exit-status obj)234 (cond ((integer? obj) obj)235 ((eq? obj #f) 1)236 (else 0)))237238(define (exit #!optional (obj 0))239 ;; ##sys#dynamic-unwind is hidden, have to unwind manually.240 ; (##sys#dynamic-unwind '() (length ##sys#dynamic-winds))241 (let unwind ()242 (unless (null? ##sys#dynamic-winds)243 (let ((after (cdar ##sys#dynamic-winds)))244 (set! ##sys#dynamic-winds (cdr ##sys#dynamic-winds))245 (after)246 (unwind))))247 ;; The built-in exit runs cleanup handlers for us.248 (chicken-exit (->exit-status obj)))249250)251