~ chicken-core (master) /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)60(import (only (scheme base) open-output-string get-output-string))6162(include "common-declarations.scm")63(include "mini-srfi-1.scm")646566;;; Convert string into valid C-identifier:6768(define (string->c-identifier str)69 (let ((out (open-output-string))70 (n (string-length str)))71 (do ((i 0 (fx+ i 1)))72 ((fx>= i n) (get-output-string out))73 (let ((c (string-ref str i)))74 (if (and (not (char-alphabetic? c))75 (or (not (char-numeric? c)) (fx= i 0)))76 (let ((i (char->integer c)))77 (write-char #\_ out)78 (when (fx< i 16) (write-char #\0 out))79 (display (number->string i 16) out))80 (write-char c out))))))818283;;; Parse library specifications:8485(define (valid-library-specifier? x)86 (or (symbol? x)87 (and (list? x)88 (not (null? x))89 (every (lambda (x) (or (symbol? x) (fixnum? x))) x))))9091(define (library-id lib)92 (define (fail)93 (##sys#error "invalid library specifier" lib))94 (define (srfi? x)95 (and (pair? (cdr x))96 (null? (cddr x))97 (eq? 'srfi (car x))98 (fixnum? (cadr x))))99 (define (library-part->string x)100 (cond ((symbol? x) (##sys#symbol->string/shared x))101 ((fixnum? x) (##sys#number->string x))102 (else (fail))))103 (cond104 ((symbol? lib) lib)105 ((null? lib) (fail))106 ((not (list? lib)) (fail))107 ((srfi? lib)108 (##sys#string->symbol109 (##sys#string-append "srfi-" (##sys#number->string (cadr lib)))))110 (else111 (do ((lst (cdr lib) (cdr lst))112 (str (library-part->string (car lib))113 (string-append str "." (library-part->string (car lst)))))114 ((null? lst)115 (##sys#string->symbol str))))))116117118;;; Requirement identifier for modules:119120(define (module-requirement id)121 (##sys#string->symbol122 (##sys#string-append (##sys#symbol->string/shared id) "#")))123124125;;; Check for multiple bindings in "let"-style constructs:126127(define (check-for-multiple-bindings bindings form loc)128 ;; assumes correct syntax129 (let loop ((bs bindings) (seen '()) (warned '()))130 (cond ((null? bs))131 ((and (memq (caar bs) seen)132 (not (memq (caar bs) warned)))133 (##sys#warn134 (string-append "variable bound multiple times in " loc " construct")135 (caar bs)136 form)137 (loop (cdr bs) seen (cons (caar bs) warned)))138 (else (loop (cdr bs) (cons (caar bs) seen) warned)))))139140141;;; Macro environment manipulation:142(define (macro-subset me0 #!optional parent-env)143 (let ((se (let loop ((me (##sys#macro-environment)))144 (if (or (null? me) (eq? me me0))145 '()146 (cons (car me) (loop (cdr me)))))))147 (fixup-macro-environment se parent-env)))148149;;XXX clarify what this does!150(define (fixup-macro-environment se #!optional parent-env)151 (let ((se2 (if parent-env (##sys#append se parent-env) se)))152 (for-each ; fixup se153 (lambda (sdef)154 (when (pair? (cdr sdef))155 (set-car!156 (cdr sdef)157 (if (null? (cadr sdef))158 se2159 (##sys#append (cadr sdef) se2)))))160 se)161 se))162163164;;; Low-level hashtable support:165166(define hash-symbol167 (let ((cache-s #f)168 (cache-h #f)169 ;; NOTE: All low-level hash tables share the same randomization factor170 (rand (##core#inline "C_rand" #x10000)))171 (lambda (s n)172 (if (eq? s cache-s)173 (##core#inline "C_fixnum_modulo" cache-h n)174 (let ((bv (##sys#slot s 1)))175 (set! cache-s s)176 (set! cache-h (##core#inline "C_u_i_bytevector_hash" bv 0 (fx- (##sys#size bv) 1) rand))177 (##core#inline "C_fixnum_modulo" cache-h n))))))178179(define (make-hash-table #!optional (size 301))180 (make-vector size '()))181182(define (hash-table-ref ht key)183 (let loop ((bucket (##sys#slot ht (hash-symbol key (##sys#size ht)))))184 (and (not (eq? '() bucket))185 (if (eq? key (##sys#slot (##sys#slot bucket 0) 0))186 (##sys#slot (##sys#slot bucket 0) 1)187 (loop (##sys#slot bucket 1))))))188189(define (hash-table-set! ht key val)190 (let* ((k (hash-symbol key (##sys#size ht)))191 (ib (##sys#slot ht k)))192 (let loop ((bucket ib))193 (if (eq? '() bucket)194 (##sys#setslot ht k (cons (cons key val) ib))195 (if (eq? key (##sys#slot (##sys#slot bucket 0) 0))196 (##sys#setslot (##sys#slot bucket 0) 1 val)197 (loop (##sys#slot bucket 1)))))))198199(define (hash-table-update! ht key updtfunc valufunc)200 (hash-table-set! ht key (updtfunc (or (hash-table-ref ht key) (valufunc)))))201202(define (hash-table-for-each p ht)203 (let ((len (##core#inline "C_block_size" ht)))204 (do ((i 0 (fx+ i 1)))205 ((fx>= i len))206 (##sys#for-each (lambda (bucket) (p (##sys#slot bucket 0) (##sys#slot bucket 1)))207 (##sys#slot ht i)))))208209(define (hash-table-size ht)210 (let loop ((len (##sys#size ht)) (bkt 0) (size 0))211 (if (fx= bkt len)212 size213 (loop len (fx+ bkt 1) (fx+ size (##sys#length (##sys#slot ht bkt)))))))214215;;; Modules that are made available to code by default:216217;; WARNING: These import libs must all exist. They cannot be emitted,218;; because the compiler itself needs them to expand macros!219;; WARNING: These also need to be built into modules.scm, so that220;; statically linked programs can eval the imports for these modules.221222(define default-imports '(scheme chicken.base chicken.syntax))223(define default-syntax-imports '(scheme chicken.base chicken.syntax))224225) ; chicken.internal