~ chicken-r7rs (master) /r7rs-compile-time.scm
Trap1;;;; compile-time support code (mostly for modules)23(import-syntax matchable)4(import chicken.base chicken.file chicken.plist)5(import chicken.syntax chicken.platform)6(import srfi-1)7(import r7rs-library r7rs-support)89(define (locate-library name loc) ; must be stripped10 ;;XXX scan include-path?11 (let* ((name2 (parse-library-name name loc))12 (sname2 (symbol->string name2)))13 (or (##sys#find-module name2 #f)14 (memq name2 ##sys#core-library-modules)15 (memq name2 ##sys#core-syntax-modules)16 (file-exists? (string-append sname2 ".import.so"))17 (file-exists? (string-append sname2 ".import.scm")))))1819(define (process-cond-expand clauses)20 ;; returns list of forms of successful clause or #f21 (define (fail msg . args)22 (apply23 syntax-error24 msg25 (append args26 `((cond-expand27 ,@(map (lambda (clause) (cons (car clause) '(...))) clauses))))))28 (define (check test)29 (match test30 ('else #t)31 (('not test) (not (check test)))32 (('and tests ...) (every check tests))33 (('or tests ...) (any check tests))34 (('library name) (locate-library name 'cond-expand))35 ((? symbol? feature) (feature? feature))36 (_ (fail "invalid test expression in \"cond-expand\" form" test))))37 (let loop ((cs clauses))38 (match cs39 (() (fail "no clause applies in \"cond-expand\" form"))40 (((test body ...) . more)41 (if (check (strip-syntax test))42 body43 (loop more)))44 (else (fail "invalid \"cond-expand\" form")))))4546;; Dig e.g. foo.bar out of (only (foo bar) ...) ...47(define (import/export-spec-feature-name spec loc)48 (match spec49 ((? symbol? spec) spec)50 (((or 'only 'except 'rename 'prefix) name . more)51 (import/export-spec-feature-name name loc))52 ((name ...)53 (parse-library-name name loc))54 (else55 (syntax-error loc "invalid import/export specifier" spec))))5657(define (expand/begin e)58 (match (expand e '())59 (('##core#begin . rest)60 (cons '##core#begin (map expand/begin rest)))61 (e* e*)))6263(define (expand-toplevel-r7rs-library-forms exps)64 (parameterize ((##sys#macro-environment (r7rs-library-macro-environment)))65 (map expand/begin exps)))6667(define (read-forms filename ci?)68 (fluid-let ((##sys#default-read-info-hook69 (let ((name 'chicken.compiler.support#read-info-hook))70 (and (feature? 'compiling)71 (##sys#symbol-has-toplevel-binding? name)72 (##sys#slot name 0)))))73 (parameterize ((case-sensitive (not ci?)))74 (##sys#include-forms-from-file75 filename76 ##sys#current-source-filename77 expand-toplevel-r7rs-library-forms))))7879(define implicit-r7rs-library-bindings80 '(begin81 cond-expand82 export83 import84 import-for-syntax85 include86 include-ci87 syntax-rules))8889(define (parse-library-definition form dummy-export) ; expects stripped syntax90 (match form91 ((_ name decls ...)92 (let ((real-name (parse-library-name name 'define-library)))93 (define (parse-exports specs)94 (map (match-lambda95 ((and spec ('rename _ _))96 (syntax-error97 'define-library98 "\"rename\" export specifier currently not supported"99 name))100 ((? symbol? exp)101 `(export ,exp))102 (spec (syntax-error 'define-library "invalid export specifier" spec name)))103 specs))104 (define (parse-imports specs)105 ;; What R7RS calls IMPORT, we call USE (it imports *and* loads code)106 ;; XXX TODO: Should be import-for-syntax'ed as well?107 `(import ,@specs)) ; NOTE this is the r7rs module's IMPORT!108 (define (process-includes fnames ci?)109 `(##core#begin110 ,@(map (match-lambda111 ((? string? fname)112 `(##core#begin ,@(read-forms fname ci?)))113 (fname (syntax-error 'include "invalid include-filename" fname)))114 fnames)))115 (define (process-include-decls fnames)116 (parse-decls (append-map (lambda (fname) (read-forms fname #t)) fnames)))117 (define (parse-decls decls)118 (match decls119 (() '(##core#begin))120 ((('export specs ...) . more)121 `(##core#begin122 ,@(parse-exports specs)123 ,(parse-decls more)))124 ((('import specs ...) . more)125 `(##core#begin126 ,(parse-imports specs)127 ,(parse-decls more)))128 ((('include fnames ...) . more)129 `(##core#begin130 ,(process-includes fnames #f)131 ,(parse-decls more)))132 ((('include-ci fnames ...) . more)133 `(##core#begin134 ,(process-includes fnames #t)135 ,(parse-decls more)))136 ((('include-library-declarations fnames ...) . more)137 `(##core#begin138 ,(process-include-decls fnames)139 ,(parse-decls more)))140 ((('cond-expand decls ...) . more)141 `(##core#begin142 ,@(process-cond-expand decls)143 ,(parse-decls more)))144 ((('begin code ...) . more)145 `(##core#begin146 ,@code147 ,(parse-decls more)))148 (decl (syntax-error 'define-library "invalid library declaration" decl))))149 `(##core#module ,real-name ((,dummy-export))150 ;; gruesome hack: we add a dummy export for adding indirect exports151 (##core#define-syntax ,dummy-export152 (##sys#er-transformer (##core#lambda (x r c) (##core#undefined))))153 ;; Another gruesome hack: provide feature so "use" works properly154 (##sys#provide (##core#quote ,real-name))155 ;; Set up an R7RS environment for the module's body.156 (import-for-syntax (only r7rs ,@implicit-r7rs-library-bindings))157 (import (only r7rs ,@implicit-r7rs-library-bindings))158 ;; Now process all toplevel library declarations159 ,(parse-decls decls))))160 (_ (syntax-error 'define-library "invalid library definition" form))))161162(define (register-r7rs-module name)163 (let ((dummy (string->symbol (string-append "\x04r7rs" (symbol->string name)))))164 (put! name '##r7rs#module dummy)165 dummy))166167(set! ##sys#register-export168 (let ((register-export ##sys#register-export))169 (lambda (sym mod)170 (when mod171 (let-values (((explist ve se) (##sys#module-exports mod)))172 (and-let* ((dummy (get (##sys#module-name mod) '##r7rs#module)))173 (unless (eq? sym dummy)174 (cond ((memq sym explist))175 ((find (lambda (a) (and (pair? a) (eq? (car a) dummy))) explist) =>176 (lambda (dummylist)177 (set-cdr! dummylist (cons sym (cdr dummylist))))))))178 (register-export sym mod))))))179180(define r7rs-define-library181 (er-macro-transformer182 (lambda (x r c)183 (match (strip-syntax x)184 ((_ name decls ...)185 (let ((dummy (register-r7rs-module (parse-library-name name 'define-library))))186 (parse-library-definition x dummy)))187 (else188 (syntax-error 'define-library "invalid library definition" x))))))189190(define r7rs-cond-expand191 (er-macro-transformer192 (lambda (x r c)193 (cons (r 'begin)194 (process-cond-expand (cdr x))))))195196(define r7rs-include197 (er-macro-transformer198 (lambda (e r c)199 (cons (r 'begin)200 (append-map (cut read-forms <> #f) (cdr e))))))201202(define r7rs-include-ci203 (er-macro-transformer204 (lambda (e r c)205 (cons (r 'begin)206 (append-map (cut read-forms <> #t) (cdr e))))))207208;; NOTE Not really "r7rs" -- just the core begin rewrapped in209;; a transformer. Used when expanding toplevel library forms.210(define r7rs-begin211 (##sys#make-structure 'transformer (macro-handler 'begin)))212213(define (r7rs-library-macro-environment)214 (filter (lambda (p)215 (memv (caddr p)216 (map (cut ##sys#slot <> 1)217 (list r7rs-begin218 r7rs-cond-expand219 r7rs-define-library220 r7rs-include221 r7rs-include-ci))))222 (##sys#macro-environment)))