-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreader.sld
96 lines (80 loc) · 3.38 KB
/
reader.sld
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
(define-library (reader)
(export get-string get-string-optional read-files)
(import (scheme base) (scheme char) (scheme read) (srfi 1))
(import (solver))
(begin
(define (get-one-from-entry valid? entry)
(let ((tail (cdr entry)))
(if (and (= 1 (length tail)) (valid? (car tail)))
(car tail)
(error "Bad alist entry"))))
(define (get-one-optional valid? key alist)
(let ((entry (assoc key alist)))
(if entry (get-one-from-entry valid? entry) #f)))
(define (get-one valid? key alist)
(let ((entry (assoc key alist)))
(if entry
(get-one-from-entry valid? entry)
(error "Missing key" key))))
(define (get-string key alist)
(get-one string? key alist))
(define (get-string-optional key alist)
(get-one-optional string? key alist))
(define (version-string-split s)
(define (split-off a b fields)
(if (= a b) fields (cons (substring s a b) fields)))
(let loop ((a 0) (b 0) (fields '()))
(cond ((= b (string-length s))
(reverse (split-off a b fields)))
((or (char=? #\. (string-ref s b))
(char=? #\- (string-ref s b))
(char=? #\_ (string-ref s b)))
(loop b (+ b 1) (split-off a b fields)))
(else
(loop a (+ b 1) fields)))))
(define (string-list-compare a b)
(cond ((null? a) (if (null? b) 0 -1))
((null? b) 1)
((string-ci<? (car a) (car b)) -1)
((string-ci>? (car a) (car b)) 1)
(else (string-list-compare (cdr a) (cdr b)))))
(define known-extensions '(".gz" ".pdf" ".tar" ".tgz" ".zip"))
(define (remove-ext lis)
(let loop ((lis (reverse lis)))
(if (and (not (null? lis)) (member (car lis) known-extensions))
(loop (cdr lis))
(reverse lis))))
(define (version-string-compare a b)
(string-list-compare (remove-ext (version-string-split a))
(remove-ext (version-string-split b))))
(define (assert-version-order names)
(or (null? names)
(let loop ((a (car names)) (bs (cdr names)))
(if (null? bs) #f
(let ((b (car bs)))
(cond ((string-ci=? a b)
(error "Filenames are duplicate" a b))
((> (version-string-compare a b) 0)
(error "Filenames are not in alphabetical order"
a b))
(else (loop b (cdr bs)))))))))
(define (list->pair list)
(if (= 2 (length list))
(cons (car list) (cadr list))
(error "Malformed entry")))
(define (pair->list pair) (list (car pair) (cdr pair)))
(define (read-all)
(let loop ((forms '()))
(let ((form (read)))
(if (eof-object? form) (reverse forms) (loop (cons form forms))))))
(define (read-files/raw)
(map cdr (filter (lambda (form)
(and (pair? form) (eq? 'file (car form))))
(read-all))))
(define (read-files)
(let ((files (map (lambda (file)
(map pair->list (solve (map list->pair file))))
(read-files/raw))))
(let ((names (map (lambda (file) (get-string 'name file)) files)))
(assert-version-order names))
files))))