Commit | Line | Data |
---|---|---|
be17d0a6 NG |
1 | ;; Copyright (C) 2015 |
2 | ;; "Mu Lei" known as "NalaGinrut" <NalaGinrut@gmail.com> | |
3 | ;; This file is free software: you can redistribute it and/or modify | |
4 | ;; it under the terms of the GNU General Public License as published by | |
5 | ;; the Free Software Foundation, either version 3 of the License, or | |
6 | ;; (at your option) any later version. | |
7 | ||
8 | ;; This file is distributed in the hope that it will be useful, | |
9 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | ;; GNU General Public License for more details. | |
12 | ||
13 | ;; You should have received a copy of the GNU General Public License | |
14 | ;; along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | ||
16 | (library (core) | |
5835f45b | 17 | (export core.ns ->list) |
9f3c0995 | 18 | (import (guile) (rnrs) (types) (reader) (printer) (ice-9 match) (readline))) |
5835f45b NG |
19 | |
20 | (define (->list o) ((if (vector? o) vector->list identity) o)) | |
be17d0a6 NG |
21 | |
22 | (define (_count obj) | |
23 | (cond | |
24 | ((_nil? obj) 0) | |
25 | ((vector? obj) (vector-length obj)) | |
26 | (else (length obj)))) | |
27 | ||
28 | (define (_empty? obj) (zero? (_count obj))) | |
29 | ||
dc656104 NG |
30 | ;; Well, strange spec... |
31 | (define (_equal? o1 o2) | |
d5995c72 DM |
32 | (define (equal-lists? lst1 lst2) |
33 | (and (= (length lst1) (length lst2)) | |
34 | (for-all _equal? lst1 lst2))) | |
35 | (define (equal-hash-tables? ht1 ht2) | |
36 | (define (equal-values? k) | |
37 | (_equal? (_get ht1 k) (_get ht2 k))) | |
38 | (let ((keys1 (_keys ht1))) | |
39 | (and (= (length keys1) (length (_keys ht2))) | |
40 | (for-all equal-values? keys1)))) | |
41 | (cond | |
42 | ((and (_sequential? o1) (_sequential? o2)) | |
43 | (equal-lists? (->list o1) (->list o2))) | |
44 | ((and (hash-table? o1) (hash-table? o2)) | |
45 | (equal-hash-tables? o1 o2)) | |
46 | (else | |
47 | (equal? o1 o2)))) | |
dc656104 | 48 | |
be17d0a6 NG |
49 | (define (pr-str . args) |
50 | (define (pr x) (pr_str x #t)) | |
51 | (string-join (map pr args) " ")) | |
52 | ||
dc656104 NG |
53 | (define (str . args) |
54 | (define (pr x) (pr_str x #f)) | |
55 | (string-join (map pr args) "")) | |
56 | ||
57 | (define (prn . args) | |
58 | (format #t "~a~%" (apply pr-str args)) | |
98cd78e4 | 59 | nil) |
dc656104 NG |
60 | |
61 | (define (println . args) | |
62 | (define (pr x) (pr_str x #f)) | |
98cd78e4 | 63 | (format #t "~{~a~^ ~}~%" (map pr args)) |
dc656104 NG |
64 | nil) |
65 | ||
f040d9fb NG |
66 | (define (slurp filename) |
67 | (when (not (file-exists? filename)) | |
0d9fb576 | 68 | (throw 'mal-error (format #f "File/dir '~a' doesn't exist" filename))) |
f040d9fb NG |
69 | (call-with-input-file filename get-string-all)) |
70 | ||
5835f45b NG |
71 | (define (_cons x y) |
72 | (cons x (->list y))) | |
73 | ||
74 | (define (concat . args) | |
75 | (apply append (map ->list args))) | |
76 | ||
e658ffd2 NG |
77 | (define (_nth lst n) |
78 | (define ll (->list lst)) | |
79 | (when (>= n (length ll)) | |
80 | (throw 'mal-error "nth: index out of range")) | |
81 | (list-ref ll n)) | |
82 | ||
83 | (define (_first lst) | |
84 | (define ll (->list lst)) | |
75048743 DM |
85 | (cond |
86 | ((_nil? lst) nil) | |
87 | ((null? ll) nil) | |
88 | (else (car ll)))) | |
e658ffd2 NG |
89 | |
90 | (define (_rest lst) | |
91 | (define ll (->list lst)) | |
75048743 DM |
92 | (cond |
93 | ((_nil? lst) '()) | |
94 | ((null? ll) '()) | |
95 | (else (cdr ll)))) | |
e658ffd2 | 96 | |
98cd78e4 NG |
97 | (define (_map f lst) (map (callable-closure f) (->list lst))) |
98 | ||
99 | (define (_apply f . args) | |
100 | (define ll | |
10bc1bce | 101 | (let lp((next args) (ret '())) |
98cd78e4 NG |
102 | (cond |
103 | ((null? next) (reverse ret)) | |
104 | (else | |
105 | (let ((n (->list (car next)))) | |
106 | (lp (cdr next) (if (list? n) | |
107 | (append (reverse n) ret) | |
108 | (cons n ret)))))))) | |
a6e59cf3 | 109 | (callable-apply f ll)) |
98cd78e4 NG |
110 | |
111 | (define (->symbol x) | |
112 | ((if (symbol? x) identity string->symbol) x)) | |
113 | ||
114 | (define (->keyword x) | |
115 | ((if (_keyword? x) identity string->keyword) x)) | |
116 | ||
98cd78e4 NG |
117 | (define (_hash-map . lst) (list->hash-map lst)) |
118 | ||
119 | (define (_assoc ht . lst) (list->hash-map lst (hash-table-clone ht))) | |
120 | ||
121 | (define (_get ht k) | |
122 | (if (_nil? ht) | |
123 | nil | |
124 | (hash-ref ht k nil))) | |
125 | ||
126 | (define (_dissoc ht . lst) | |
127 | (define ht2 (hash-table-clone ht)) | |
128 | (for-each (lambda (k) (hash-remove! ht2 k)) lst) | |
129 | ht2) | |
130 | ||
131 | (define (_keys ht) (hash-map->list (lambda (k v) k) ht)) | |
132 | ||
133 | (define (_vals ht) (hash-map->list (lambda (k v) v) ht)) | |
134 | ||
1c90c506 NG |
135 | (define (_contains? ht k) |
136 | (let ((v (hash-ref ht k '*mal-null*))) | |
137 | (if (eq? v '*mal-null*) | |
138 | #f | |
139 | #t))) | |
98cd78e4 NG |
140 | |
141 | (define (_sequential? o) (or (list? o) (vector? o))) | |
142 | ||
9f3c0995 NG |
143 | (define (_meta c) |
144 | (if (callable? c) | |
145 | (callable-meta-info c) | |
2a80d367 | 146 | (or (object-property c 'meta) nil))) |
9f3c0995 NG |
147 | |
148 | (define (_with-meta c ht) | |
149 | (cond | |
150 | ((callable? c) | |
151 | (let ((cc (make-callable ht | |
152 | (callable-unbox c) | |
aac5cf7b | 153 | #f |
9f3c0995 NG |
154 | (callable-closure c)))) |
155 | cc)) | |
156 | (else | |
157 | (let ((cc (box c))) | |
2a80d367 | 158 | (set-object-property! cc 'meta ht) |
9f3c0995 NG |
159 | cc)))) |
160 | ||
161 | ;; Apply closure 'c' with atom-val as one of arguments, then | |
162 | ;; set the result as the new val of atom. | |
163 | (define (_swap! atom c . rest) | |
164 | (let* ((args (cons (atom-val atom) rest)) | |
165 | (val (callable-apply c args))) | |
166 | (atom-val-set! atom val) | |
167 | val)) | |
168 | ||
169 | (define (_conj lst . args) | |
170 | (cond | |
171 | ((vector? lst) | |
172 | (list->vector (append (->list lst) args))) | |
173 | ((list? lst) | |
174 | (append (reverse args) (->list lst))) | |
175 | (else (throw 'mal-error (format #f "conj: '~a' is not list/vector" lst))))) | |
176 | ||
4e6ae3b7 DM |
177 | (define (_seq obj) |
178 | (cond | |
179 | ((_nil? obj) nil) | |
180 | ((_string? obj) | |
181 | (if (string-null? obj) nil (map string (string->list obj)))) | |
182 | ((_empty? obj) nil) | |
183 | (else (->list obj)))) | |
184 | ||
0d9fb576 NG |
185 | (define (__readline prompt) |
186 | (let ((str (_readline prompt))) | |
187 | (if (eof-object? str) | |
188 | #f | |
189 | str))) | |
190 | ||
2a80d367 NG |
191 | (define (_true? x) (eq? x #t)) |
192 | (define (_false? x) (eq? x #f)) | |
193 | ||
194 | ;; We need regular named procedure for better debug | |
195 | (define (_atom x) (make-atom x)) | |
196 | (define (_atom? x) (atom? x)) | |
197 | (define (_deref x) (atom-val x)) | |
198 | (define (_reset! x v) (atom-val-set! x v)) | |
199 | ||
4b3eaa74 NG |
200 | (define (time-ms) |
201 | (let ((t (gettimeofday))) | |
202 | (round | |
203 | (+ (* (car t) 1000.0) (/ (cdr t) 1000.0) 0.5)))) | |
204 | ||
be17d0a6 | 205 | (define *primitives* |
f040d9fb NG |
206 | `((list ,list) |
207 | (list? ,list?) | |
208 | (empty? ,_empty?) | |
209 | (count ,_count) | |
210 | (= ,_equal?) | |
211 | (< ,<) | |
212 | (<= ,<=) | |
213 | (> ,>) | |
214 | (>= ,>=) | |
215 | (+ ,+) | |
216 | (- ,-) | |
217 | (* ,*) | |
218 | (/ ,/) | |
f040d9fb NG |
219 | (pr-str ,pr-str) |
220 | (str ,str) | |
221 | (prn ,prn) | |
222 | (println ,println) | |
223 | (read-string ,read_str) | |
224 | (slurp ,slurp) | |
5835f45b NG |
225 | (cons ,_cons) |
226 | (concat ,concat) | |
e658ffd2 NG |
227 | (nth ,_nth) |
228 | (first ,_first) | |
229 | (rest ,_rest) | |
98cd78e4 NG |
230 | (map ,_map) |
231 | (apply ,_apply) | |
232 | (nil? ,_nil?) | |
2a80d367 NG |
233 | (true? ,_true?) |
234 | (false? ,_false?) | |
85657c96 | 235 | (number? ,number?) |
98cd78e4 NG |
236 | (symbol? ,symbol?) |
237 | (symbol ,->symbol) | |
4e6ae3b7 | 238 | (string? ,_string?) |
98cd78e4 NG |
239 | (keyword ,->keyword) |
240 | (keyword? ,_keyword?) | |
241 | (vector? ,vector?) | |
242 | (vector ,vector) | |
243 | (hash-map ,_hash-map) | |
244 | (map? ,hash-table?) | |
245 | (assoc ,_assoc) | |
246 | (get ,_get) | |
247 | (dissoc ,_dissoc) | |
248 | (keys ,_keys) | |
249 | (vals ,_vals) | |
250 | (contains? ,_contains?) | |
251 | (sequential? ,_sequential?) | |
85657c96 VS |
252 | (fn? ,is-func?) |
253 | (macro? ,is-macro?) | |
0d9fb576 | 254 | (readline ,__readline) |
9f3c0995 NG |
255 | (meta ,_meta) |
256 | (with-meta ,_with-meta) | |
2a80d367 NG |
257 | (atom ,_atom) |
258 | (atom? ,_atom?) | |
259 | (deref ,_deref) | |
260 | (reset! ,_reset!) | |
9f3c0995 | 261 | (swap! ,_swap!) |
2f60d14c | 262 | (conj ,_conj) |
4e6ae3b7 | 263 | (seq ,_seq) |
4b3eaa74 | 264 | (time-ms ,time-ms))) |
be17d0a6 NG |
265 | |
266 | ;; Well, we have to rename it to this strange name... | |
267 | (define core.ns *primitives*) |