Initial commit
This commit is contained in:
commit
3db2796c95
|
@ -0,0 +1,303 @@
|
|||
(define-library (scheme-deps)
|
||||
|
||||
(export main)
|
||||
|
||||
(import (except (scheme base) features)
|
||||
(scheme file)
|
||||
(scheme read)
|
||||
(scheme write)
|
||||
(only (srfi 1) append-map append-reverse fold any every remove)
|
||||
(srfi 193))
|
||||
|
||||
(cond-expand
|
||||
(chibi
|
||||
(import (chibi show)
|
||||
(chibi show pretty)))
|
||||
(gauche
|
||||
(import (only (gauche base) pprint)))
|
||||
(else))
|
||||
|
||||
(cond-expand
|
||||
(chibi
|
||||
(begin
|
||||
(define (pretty-print obj)
|
||||
(show #t (pretty obj)))))
|
||||
(gauche
|
||||
(begin
|
||||
(define (pretty-print obj)
|
||||
(pprint obj))))
|
||||
(else
|
||||
(begin
|
||||
(define (pretty-print obj)
|
||||
(write obj)
|
||||
(newline)))))
|
||||
|
||||
(begin
|
||||
|
||||
(define edisp
|
||||
(lambda objs
|
||||
(for-each (lambda (obj) (display obj (current-error-port)))
|
||||
objs)
|
||||
(newline (current-error-port))))
|
||||
|
||||
(define (read-all)
|
||||
(let loop ((xs '()))
|
||||
(let ((x (read)))
|
||||
(if (eof-object? x) (reverse xs) (loop (cons x xs))))))
|
||||
|
||||
;;
|
||||
|
||||
(define (natural? obj)
|
||||
(and (integer? obj) (exact? obj) (not (negative? obj))))
|
||||
|
||||
;;
|
||||
|
||||
(define first car)
|
||||
(define second cadr)
|
||||
|
||||
(define rest cdr)
|
||||
|
||||
(define (list<? < a b)
|
||||
(cond ((null? a) (not (null? b)))
|
||||
((null? b) #f)
|
||||
((< (first a) (first b)) #t)
|
||||
((< (first b) (first a)) #f)
|
||||
(else (list<? < (rest a) (rest b)))))
|
||||
|
||||
(define (sorted-insert-unique < elem list)
|
||||
(let loop ((before '()) (tail list))
|
||||
(cond ((or (not (pair? tail))
|
||||
(< elem (first tail)))
|
||||
(append-reverse before (cons elem tail)))
|
||||
((< (first tail) elem)
|
||||
(loop (cons (first tail) before)
|
||||
(rest tail)))
|
||||
(else
|
||||
list))))
|
||||
|
||||
(define (sort-unique < list)
|
||||
(let loop ((sorted '()) (list list))
|
||||
(if (null? list)
|
||||
sorted
|
||||
(loop (sorted-insert-unique < (first list) sorted)
|
||||
(rest list)))))
|
||||
|
||||
(define (nonnull-list? obj)
|
||||
(and (list? obj)
|
||||
(not (null? obj))))
|
||||
|
||||
(define (head? form head)
|
||||
(and (nonnull-list? form)
|
||||
(equal? head (first form))))
|
||||
|
||||
(define (dehead form head)
|
||||
(if (head? form head)
|
||||
(rest form)
|
||||
(error "Mismatch" form head)))
|
||||
|
||||
(define (if-nonnull head tail)
|
||||
(if (null? tail) '() `((,head ,@tail))))
|
||||
|
||||
;;
|
||||
|
||||
(define (string-join parts delim)
|
||||
(if (null? parts)
|
||||
""
|
||||
(fold (lambda (parts whole) (string-append whole delim parts))
|
||||
(first parts)
|
||||
(rest parts))))
|
||||
|
||||
;;
|
||||
|
||||
(define (valid-library-name-part? obj)
|
||||
(or (symbol? obj) (natural? obj)))
|
||||
|
||||
(define (valid-library-name? obj)
|
||||
(and (nonnull-list? obj)
|
||||
(every valid-library-name-part? obj)))
|
||||
|
||||
(define (library-name-part->string part)
|
||||
(cond ((symbol? part) (symbol->string part))
|
||||
((number? part) (number->string part))
|
||||
(else (error "Bad library name part" part))))
|
||||
|
||||
(define (library-name-part<? a b)
|
||||
(string<? (library-name-part->string a)
|
||||
(library-name-part->string b)))
|
||||
|
||||
(define (library-name<? a b)
|
||||
(list<? library-name-part<? a b))
|
||||
|
||||
(define (format-library-name library-name separator extension)
|
||||
(string-append (string-join (map library-name-part->string library-name)
|
||||
separator)
|
||||
extension))
|
||||
|
||||
(define (library-name->filename library-name)
|
||||
(format-library-name library-name "/" ".sld"))
|
||||
|
||||
;;
|
||||
|
||||
(define (no-consumer value) (error "No consumer"))
|
||||
(define (producer consumer) (lambda (value) ((consumer) value)))
|
||||
|
||||
(define consume-name (make-parameter no-consumer))
|
||||
(define consume-import (make-parameter no-consumer))
|
||||
(define consume-include (make-parameter no-consumer))
|
||||
|
||||
(define produce-name (producer consume-name))
|
||||
(define produce-import (producer consume-import))
|
||||
(define produce-include (producer consume-include))
|
||||
|
||||
(define features (make-parameter '()))
|
||||
(define libraries (make-parameter '()))
|
||||
|
||||
;;
|
||||
|
||||
(define (requirement-satisfied? exp)
|
||||
(cond ((symbol? exp)
|
||||
(not (not (member exp (features)))))
|
||||
((head? exp 'library)
|
||||
(if (= 2 (length exp))
|
||||
(not (not (member (second exp) (libraries))))
|
||||
(error "Bad (library ...) requirement")))
|
||||
((head? exp 'not)
|
||||
(if (= 2 (length exp))
|
||||
(not (requirement-satisfied? (second exp)))
|
||||
(error "Bad (not ...) requirement" exp)))
|
||||
((head? exp 'and)
|
||||
(every requirement-satisfied? exp))
|
||||
((head? exp 'or)
|
||||
(any requirement-satisfied? exp))
|
||||
(else
|
||||
(error "Bad cond-expand requirement" exp))))
|
||||
|
||||
(define (walk-cond-expand form)
|
||||
(let loop ((clauses (dehead form 'cond-expand)))
|
||||
(if (null? clauses)
|
||||
(error "No cond-expand clause matches these features" (features))
|
||||
(let ((clause (first clauses)))
|
||||
(cond ((not (nonnull-list? clause))
|
||||
(error "Bad cond-expand clause" clause))
|
||||
((or (equal? 'else (first clause))
|
||||
(requirement-satisfied? (first clause)))
|
||||
(walk-library-declarations (rest clause)))
|
||||
(else
|
||||
(loop (rest clauses))))))))
|
||||
|
||||
(define (walk-include form)
|
||||
(if (and (head? form 'include) (= 2 (length form)))
|
||||
(produce-include (second form))
|
||||
(error "Bad include" form)))
|
||||
|
||||
(define (walk-import-set import-set)
|
||||
(cond ((or (head? import-set 'except)
|
||||
(head? import-set 'only)
|
||||
(head? import-set 'prefix)
|
||||
(head? import-set 'rename))
|
||||
(walk-import-set (second import-set)))
|
||||
((list? import-set)
|
||||
(produce-import import-set))
|
||||
(else
|
||||
(error "Bad import set" import-set))))
|
||||
|
||||
(define (walk-import form)
|
||||
(for-each walk-import-set (dehead form 'import)))
|
||||
|
||||
(define ignored-declarations
|
||||
'(begin export))
|
||||
|
||||
(define (walk-library-declaration decl)
|
||||
(cond ((head? decl 'cond-expand)
|
||||
(walk-cond-expand decl))
|
||||
((head? decl 'include)
|
||||
(walk-include decl))
|
||||
((head? decl 'import)
|
||||
(walk-import decl))
|
||||
((and (nonnull-list? decl)
|
||||
(member (first decl) ignored-declarations))
|
||||
(values))
|
||||
(else
|
||||
(edisp "warning: ignoring unknown library declaration " decl)
|
||||
(values))))
|
||||
|
||||
(define (walk-library-declarations decls)
|
||||
(for-each walk-library-declaration decls))
|
||||
|
||||
(define (walk-define-library exp)
|
||||
(unless (and (head? exp 'define-library) (>= (length exp) 3))
|
||||
(error "Bad define-library" exp))
|
||||
(let ((name (second exp))
|
||||
(decls (rest (rest exp))))
|
||||
(unless (valid-library-name? name)
|
||||
(error "Bad library name" name))
|
||||
(produce-name name)
|
||||
(walk-library-declarations decls)))
|
||||
|
||||
(define (walk-sld-file sld-file)
|
||||
(for-each walk-define-library
|
||||
(with-input-from-file sld-file read-all)))
|
||||
|
||||
(define-record-type <library>
|
||||
(make-library name source-file imports includes)
|
||||
library?
|
||||
(name library-name)
|
||||
(source-file library-source-file)
|
||||
(imports library-imports)
|
||||
(includes library-includes))
|
||||
|
||||
(define (standard-or-implementation-library? library-name)
|
||||
(member (first library-name)
|
||||
'(chicken rnrs scheme srfi)))
|
||||
|
||||
(define (library->chicken-extension library)
|
||||
(define (library-name->chicken library-name)
|
||||
(string->symbol (format-library-name library-name "." "")))
|
||||
`(extension
|
||||
,(library-name->chicken (library-name library))
|
||||
(source ,(library-source-file library))
|
||||
,@(if-nonnull 'source-dependencies
|
||||
(library-includes library))
|
||||
,@(if-nonnull 'component-dependencies
|
||||
(map library-name->chicken
|
||||
(remove standard-or-implementation-library?
|
||||
(library-imports library))))
|
||||
(csc-options "-R" "r7rs"
|
||||
"-X" "r7rs")))
|
||||
|
||||
(define-syntax add-to
|
||||
(syntax-rules ()
|
||||
((add-to lis <)
|
||||
(lambda (elem)
|
||||
(set! lis (sorted-insert-unique < elem lis))))))
|
||||
|
||||
(define (process-sld-file sld-file)
|
||||
(let ((name '())
|
||||
(imports '())
|
||||
(includes '()))
|
||||
(parameterize ((consume-name (lambda (x) (set! name x)))
|
||||
(consume-import (add-to imports library-name<?))
|
||||
(consume-include (add-to includes string<?)))
|
||||
(walk-sld-file sld-file))
|
||||
(make-library name sld-file imports includes)))
|
||||
|
||||
(define (print-chicken libs)
|
||||
(for-each
|
||||
pretty-print
|
||||
`((distribution-files
|
||||
,@(sort-unique
|
||||
string<?
|
||||
(append-map (lambda (lib)
|
||||
(cons (library-source-file lib)
|
||||
(library-includes lib)))
|
||||
libs)))
|
||||
(components
|
||||
,@(map library->chicken-extension
|
||||
libs)))))
|
||||
|
||||
(define main
|
||||
(lambda ignored
|
||||
(parameterize ((features '(chicken))
|
||||
(libraries '((srfi 13))))
|
||||
(let ((libs (map process-sld-file (command-args))))
|
||||
(print-chicken libs)))))))
|
Loading…
Reference in New Issue