~ chicken-core (chicken-5) /internal.scm
Trap1;;;; internal.scm - Runtime support module for CHICKEN2;3; Copyright (c) 2008-2022, The CHICKEN Team4; Copyright (c) 2000-2007, Felix L. Winkelmann5; All rights reserved.6;7; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following8; conditions are met:9;10; Redistributions of source code must retain the above copyright notice, this list of conditions and the following11; disclaimer.12; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following13; disclaimer in the documentation and/or other materials provided with the distribution.14; Neither the name of the author nor the names of its contributors may be used to endorse or promote15; products derived from this software without specific prior written permission.16;17; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS18; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY19; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR20; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR21; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR22; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY23; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR24; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE25; POSSIBILITY OF SUCH DAMAGE.2627(declare28 (unit internal)29 (disable-interrupts)30 (fixnum))3132;; This is a bit of a grab-bag of stuff that's used in various places33;; in the runtime and the compiler, but which is not supposed to be34;; used by the user, and doesn't strictly belong anywhere in35;; particular.36(module chicken.internal37 (;; Convert string into valid C-identifier38 string->c-identifier3940 ;; Parse library specifications41 library-id valid-library-specifier?4243 ;; Requirement identifier for modules44 module-requirement4546 ;;; Check for multiple bindings in "let"-style constructs47 check-for-multiple-bindings4849 ;;; Macro environment manipulation50 macro-subset fixup-macro-environment5152 ;; Low-level hash table support53 make-hash-table hash-table-ref hash-table-set! hash-table-update!54 hash-table-for-each hash-table-size5556 ;; Modules that are made available to code by default57 default-imports default-syntax-imports)5859(import scheme chicken.base chicken.fixnum)6061(include "common-declarations.scm")62(include "mini-srfi-1.scm")636465;;; Convert string into valid C-identifier:6667(define (string->c-identifier str)68 (let ((out (open-output-string))69 (n (string-length str)))70 (do ((i 0 (fx+ i 1)))71 ((fx>= i n) (get-output-string out))72 (let ((c (string-ref str i)))73 (if (and (not (char-alphabetic? c))74 (or (not (char-numeric? c)) (fx= i 0)))75 (let ((i (char->integer c)))76 (write-char #\_ out)77 (when (fx< i 16) (write-char #\0 out))78 (display (number->string i 16) out))79 (write-char c out))))))808182;;; Parse library specifications:8384(define (valid-library-specifier? x)85 (or (symbol? x)86 (and (list? x)87 (not (null? x))88 (every (lambda (x) (or (symbol? x) (fixnum? x))) x))))8990(define (library-id lib)91 (define (fail)92 (##sys#error "invalid library specifier" lib))93 (define (srfi? x)94 (and (pair? (cdr x))95 (null? (cddr x))96 (eq? 'srfi (car x))97 (fixnum? (cadr x))))98 (define (library-part->string x)99 (cond ((symbol? x) (##sys#symbol->string x))100 ((fixnum? x) (##sys#number->string x))101 (else (fail))))102 (cond103 ((symbol? lib) lib)104 ((null? lib) (fail))105 ((not (list? lib)) (fail))106 ((srfi? lib)107 (##sys#intern-symbol108 (##sys#string-append "srfi-" (##sys#number->string (cadr lib)))))109 (else110 (do ((lst (cdr lib) (cdr lst))111 (str (library-part->string (car lib))112 (string-append str "." (library-part->string (car lst)))))113 ((null? lst)114 (##sys#intern-symbol str))))))115116117;;; Requirement identifier for modules:118119(define (module-requirement id)120 (##sys#string->symbol121 (##sys#string-append (##sys#slot id 1) "#")))122123124;;; Check for multiple bindings in "let"-style constructs:125126(define (check-for-multiple-bindings bindings form loc)127 ;; assumes correct syntax128 (let loop ((bs bindings) (seen '()) (warned '()))129 (cond ((null? bs))130 ((and (memq (caar bs) seen)131 (not (memq (caar bs) warned)))132 (##sys#warn133 (string-append "variable bound multiple times in " loc " construct")134 (caar bs)135 form)136 (loop (cdr bs) seen (cons (caar bs) warned)))137 (else (loop (cdr bs) (cons (caar bs) seen) warned)))))138139140;;; Macro environment manipulation:141(define (macro-subset me0 #!optional parent-env)142 (let ((se (let loop ((me (##sys#macro-environment)))143 (if (or (null? me) (eq? me me0))144 '()145 (cons (car me) (loop (cdr me)))))))146 (fixup-macro-environment se parent-env)))147148(define (fixup-macro-environment se #!optional parent-env)149 (let ((se2 (if parent-env (##sys#append se parent-env) se)))150 (for-each ; fixup se151 (lambda (sdef)152 (when (pair? (cdr sdef))153 (set-car!154 (cdr sdef)155 (if (null? (cadr sdef))156 se2157 (##sys#append (cadr sdef) se2)))))158 se)159 se))160161162;;; Low-level hashtable support:163164(define hash-symbol165 (let ((cache-s #f)166 (cache-h #f)167 ;; NOTE: All low-level hash tables share the same randomization factor168 (rand (##core#inline "C_rand" #x10000)))169 (lambda (s n)170 (if (eq? s cache-s)171 (##core#inline "C_fixnum_modulo" cache-h n)172 (begin173 (set! cache-s s)174 (set! cache-h (##core#inline "C_u_i_string_hash" (##sys#slot s 1) rand))175 (##core#inline "C_fixnum_modulo" cache-h n))))))176177(define (make-hash-table #!optional (size 301))178 (make-vector size '()))179180(define (hash-table-ref ht key)181 (let loop ((bucket (##sys#slot ht (hash-symbol key (##core#inline "C_block_size" ht)))))182 (and (not (eq? '() bucket))183 (if (eq? key (##sys#slot (##sys#slot bucket 0) 0))184 (##sys#slot (##sys#slot bucket 0) 1)185 (loop (##sys#slot bucket 1))))))186187(define (hash-table-set! ht key val)188 (let* ((k (hash-symbol key (##core#inline "C_block_size" ht)))189 (ib (##sys#slot ht k)))190 (let loop ((bucket ib))191 (if (eq? '() bucket)192 (##sys#setslot ht k (cons (cons key val) ib))193 (if (eq? key (##sys#slot (##sys#slot bucket 0) 0))194 (##sys#setslot (##sys#slot bucket 0) 1 val)195 (loop (##sys#slot bucket 1)))))))196197(define (hash-table-update! ht key updtfunc valufunc)198 (hash-table-set! ht key (updtfunc (or (hash-table-ref ht key) (valufunc)))))199200(define (hash-table-for-each p ht)201 (let ((len (##core#inline "C_block_size" ht)))202 (do ((i 0 (fx+ i 1)))203 ((fx>= i len))204 (##sys#for-each (lambda (bucket) (p (##sys#slot bucket 0) (##sys#slot bucket 1)))205 (##sys#slot ht i)))))206207(define (hash-table-size ht)208 (let loop ((len (##sys#size ht)) (bkt 0) (size 0))209 (if (fx= bkt len)210 size211 (loop len (fx+ bkt 1) (fx+ size (##sys#length (##sys#slot ht bkt)))))))212213;;; Modules that are made available to code by default:214215;; WARNING: These import libs must all exist. They cannot be emitted,216;; because the compiler itself needs them to expand macros!217;; WARNING: These also need to be built into modules.scm, so that218;; statically linked programs can eval the imports for these modules.219220(define default-imports '(scheme chicken.base chicken.syntax))221(define default-syntax-imports '(scheme chicken.base chicken.syntax))222223) ; chicken.internal