-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rkt
180 lines (168 loc) · 4.87 KB
/
main.rkt
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#lang racket
(require (planet dvanhorn/fector:1:1))
(provide create-datastore)
(define (wrong type wanted)
(λ (cmd)
(raise-argument-error type wanted cmd)))
(define (create-datastore (rs #f) (is #f))
(define relations (or rs (hash)))
(define indexes (or is (hash)))
(define wtf
(wrong 'datastore
"relations indexes get_relation add_relation create read read-row read-col read-val update delete"))
(define (unroll-relations)
(make-immutable-hash
(map (λ (k) (cons k ((hash-ref relations k))))
(hash-keys relations))))
(define (serialize)
(hash
'relations (unroll-relations)
'indexes indexes))
(define (relvar name)
(hash-ref relations name))
(define (rebuild name noob)
(create-datastore
(hash-set relations name noob) indexes))
(define (add-relation name fields (tuples empty))
(rebuild name (relation name fields tuples)))
(define (add-tuples relname tupz)
(rebuild relname ((relvar relname) 'create tupz)))
(define (rm-tuples relname where)
(rebuild relname ((relvar relname) 'delete where)))
(define (update-tuples relname where put)
(rebuild relname ((relvar relname) 'update where put)))
(define (query result-type relname where want)
((relvar relname) result-type where want))
(case-lambda
(() (serialize))
((cmd)
(case cmd
('relations (unroll-relations))
('indexes indexes)
(else (wtf cmd))))
((cmd x)
(case cmd
('get_relation (hash-ref relations x))
(else (wtf cmd))))
((cmd x y)
(case cmd
('add_relation (add-relation x y))
('create (add-tuples x y))
('delete (rm-tuples x y))
(else (wtf cmd))))
((cmd x y z)
(case cmd
('add_relation (add-relation x y z))
((read read-row read-col read-val) (query cmd x y z))
('update (update-tuples x y z))
(else (wtf cmd))))))
(define (list->fector lst)
(apply fector lst))
(define (fector->list fv)
(for/list ((i (in-range 0 (fector-length fv))))
(fector-ref fv i)))
(define (fector->vector fv)
(for/vector ((i (in-range 0 (fector-length fv))))
(fector-ref fv i)))
(define (make-lookup fields)
(define index
(for/list ((i (in-range (length fields))) (f (in-list fields)))
(cons f i)))
(λ (f) (cdr (assoc f index))))
(define (tuple lookup seq)
(define fvec
(if (list? seq)
(list->fector seq)
seq))
(define (get f)
(fector-ref fvec (lookup f)))
(define (put f val)
(tuple lookup (fector-set fvec (lookup f) val)))
(λ ((key #f) (val #f))
(cond
(val (put key val))
(key (get key))
(else (fector->list fvec)))))
(define (tuple-factory fields)
(define lookup (make-lookup fields))
(λ (fv) (tuple lookup fv)))
(define (relation name fields (tuples empty))
(define lookup (make-lookup fields))
(define (convert lss) (map list->fector lss))
(define wtf
(wrong name
"name fields create read read-row read-col read-val update delete"))
(define (get t f)
(fector-ref t (lookup f)))
(define (wrapper fv) (tuple lookup fv))
(define (caller where)
(λ (t) (let ((tup (wrapper t)))
(where tup))))
(define (mk-matcher where)
(if (procedure? where)
(caller where)
(λ (t) (andmap
(λ (x) (eq? (get t (car x)) (cadr x)))
where))))
(define (mk-relation ts)
(define (create tups)
(mk-relation (append ts (convert tups))))
(define (read where wanted)
(define is-match? (mk-matcher where))
(define t-fact (tuple-factory wanted))
(define (grab v)
(t-fact
(apply fector
(map (λ (f) (get v f)) wanted))))
(map grab (filter is-match? ts)))
(define (read-row where xs) (car (read where xs)))
(define (read-col where xs)
(define colname (car xs))
(for/list ((tup (in-list (read where xs))))
(tup colname)))
(define (read-val where xs) ((read-row where xs) (car xs)))
(define (update where put)
(define is-match? (mk-matcher where))
(define updater
(if (procedure? put)
(caller put)
(λ (row)
(for/list ((f (in-list fields)))
(let ((key (assoc f put)))
(if key
(cadr key)
(get row f)))))))
(define (do-write row)
(if (is-match? row)
(apply fector (updater row))
row))
(mk-relation (map do-write ts)))
(define (delete where)
(define is-match? (mk-matcher where))
(mk-relation (filter-not is-match? ts)))
(define (serialize)
(hash
'name name
'fields fields
'tuples (map fector->vector ts)))
(case-lambda
(() (serialize))
((cmd)
(case cmd
('name name)
('fields fields)
(else (wtf cmd))))
((cmd args)
(case cmd
('create (create args))
('delete (delete args))
(else (wtf cmd))))
((cmd where xs)
(case cmd
('read (read where xs))
('read-row (read-row where xs))
('read-col (read-col where xs))
('read-val (read-val where xs))
('update (update where xs))
(else (wtf cmd))))))
(mk-relation (convert tuples)))