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) | |
5835f45b | 32 | (equal? (->list o1) (->list o2))) |
dc656104 | 33 | |
be17d0a6 NG |
34 | (define (pr-str . args) |
35 | (define (pr x) (pr_str x #t)) | |
36 | (string-join (map pr args) " ")) | |
37 | ||
dc656104 NG |
38 | (define (str . args) |
39 | (define (pr x) (pr_str x #f)) | |
40 | (string-join (map pr args) "")) | |
41 | ||
42 | (define (prn . args) | |
43 | (format #t "~a~%" (apply pr-str args)) | |
98cd78e4 | 44 | nil) |
dc656104 NG |
45 | |
46 | (define (println . args) | |
47 | (define (pr x) (pr_str x #f)) | |
98cd78e4 | 48 | (format #t "~{~a~^ ~}~%" (map pr args)) |
dc656104 NG |
49 | nil) |
50 | ||
f040d9fb NG |
51 | (define (slurp filename) |
52 | (when (not (file-exists? filename)) | |
53 | (throw 'mal-error "File/dir doesn't exist" filename)) | |
54 | (call-with-input-file filename get-string-all)) | |
55 | ||
5835f45b NG |
56 | (define (_cons x y) |
57 | (cons x (->list y))) | |
58 | ||
59 | (define (concat . args) | |
60 | (apply append (map ->list args))) | |
61 | ||
e658ffd2 NG |
62 | (define (_nth lst n) |
63 | (define ll (->list lst)) | |
64 | (when (>= n (length ll)) | |
65 | (throw 'mal-error "nth: index out of range")) | |
66 | (list-ref ll n)) | |
67 | ||
68 | (define (_first lst) | |
69 | (define ll (->list lst)) | |
70 | (if (null? ll) | |
71 | nil | |
72 | (car ll))) | |
73 | ||
74 | (define (_rest lst) | |
75 | (define ll (->list lst)) | |
76 | (if (null? ll) | |
77 | '() | |
78 | (cdr ll))) | |
79 | ||
98cd78e4 NG |
80 | (define (_map f lst) (map (callable-closure f) (->list lst))) |
81 | ||
82 | (define (_apply f . args) | |
83 | (define ll | |
84 | (let lp((next (->list args)) (ret '())) | |
85 | (cond | |
86 | ((null? next) (reverse ret)) | |
87 | (else | |
88 | (let ((n (->list (car next)))) | |
89 | (lp (cdr next) (if (list? n) | |
90 | (append (reverse n) ret) | |
91 | (cons n ret)))))))) | |
92 | (apply (callable-closure f) ll)) | |
93 | ||
94 | (define (->symbol x) | |
95 | ((if (symbol? x) identity string->symbol) x)) | |
96 | ||
97 | (define (->keyword x) | |
98 | ((if (_keyword? x) identity string->keyword) x)) | |
99 | ||
100 | (define* (list->hash-map lst #:optional (ht (make-hash-table))) | |
101 | (cond | |
102 | ((null? lst) ht) | |
103 | (else | |
104 | (let lp((next lst)) | |
105 | (cond | |
106 | ((null? next) ht) | |
107 | (else | |
108 | (when (null? (cdr next)) | |
109 | (throw 'mal-error | |
110 | (format #f "hash-map: '~a' lack of value" (car next)))) | |
111 | (let ((k (car next)) | |
112 | (v (cadr next))) | |
113 | (hash-set! ht k v) | |
114 | (lp (cddr next))))))))) | |
115 | ||
116 | (define (_hash-map . lst) (list->hash-map lst)) | |
117 | ||
118 | (define (_assoc ht . lst) (list->hash-map lst (hash-table-clone ht))) | |
119 | ||
120 | (define (_get ht k) | |
121 | (if (_nil? ht) | |
122 | nil | |
123 | (hash-ref ht k nil))) | |
124 | ||
125 | (define (_dissoc ht . lst) | |
126 | (define ht2 (hash-table-clone ht)) | |
127 | (for-each (lambda (k) (hash-remove! ht2 k)) lst) | |
128 | ht2) | |
129 | ||
130 | (define (_keys ht) (hash-map->list (lambda (k v) k) ht)) | |
131 | ||
132 | (define (_vals ht) (hash-map->list (lambda (k v) v) ht)) | |
133 | ||
134 | (define (_contains? ht k) (if (hash-ref ht k) #t #f)) | |
135 | ||
136 | (define (_sequential? o) (or (list? o) (vector? o))) | |
137 | ||
9f3c0995 NG |
138 | (define (_meta c) |
139 | (if (callable? c) | |
140 | (callable-meta-info c) | |
141 | (or (object-property c 'meta) nil))) | |
142 | ||
143 | (define (_with-meta c ht) | |
144 | (cond | |
145 | ((callable? c) | |
146 | (let ((cc (make-callable ht | |
147 | (callable-unbox c) | |
148 | (callable-is_macro c) | |
149 | (callable-closure c)))) | |
150 | cc)) | |
151 | (else | |
152 | (let ((cc (box c))) | |
153 | (set-object-property! cc 'meta ht) | |
154 | cc)))) | |
155 | ||
156 | ;; Apply closure 'c' with atom-val as one of arguments, then | |
157 | ;; set the result as the new val of atom. | |
158 | (define (_swap! atom c . rest) | |
159 | (let* ((args (cons (atom-val atom) rest)) | |
160 | (val (callable-apply c args))) | |
161 | (atom-val-set! atom val) | |
162 | val)) | |
163 | ||
164 | (define (_conj lst . args) | |
165 | (cond | |
166 | ((vector? lst) | |
167 | (list->vector (append (->list lst) args))) | |
168 | ((list? lst) | |
169 | (append (reverse args) (->list lst))) | |
170 | (else (throw 'mal-error (format #f "conj: '~a' is not list/vector" lst))))) | |
171 | ||
be17d0a6 | 172 | (define *primitives* |
f040d9fb NG |
173 | `((list ,list) |
174 | (list? ,list?) | |
175 | (empty? ,_empty?) | |
176 | (count ,_count) | |
177 | (= ,_equal?) | |
178 | (< ,<) | |
179 | (<= ,<=) | |
180 | (> ,>) | |
181 | (>= ,>=) | |
182 | (+ ,+) | |
183 | (- ,-) | |
184 | (* ,*) | |
185 | (/ ,/) | |
186 | (not ,not) | |
187 | (pr-str ,pr-str) | |
188 | (str ,str) | |
189 | (prn ,prn) | |
190 | (println ,println) | |
191 | (read-string ,read_str) | |
192 | (slurp ,slurp) | |
5835f45b NG |
193 | (cons ,_cons) |
194 | (concat ,concat) | |
e658ffd2 NG |
195 | (nth ,_nth) |
196 | (first ,_first) | |
197 | (rest ,_rest) | |
98cd78e4 NG |
198 | (map ,_map) |
199 | (apply ,_apply) | |
200 | (nil? ,_nil?) | |
201 | (true? ,(lambda (x) (eq? x #t))) | |
202 | (false? ,(lambda (x) (eq? x #f))) | |
203 | (symbol? ,symbol?) | |
204 | (symbol ,->symbol) | |
205 | (keyword ,->keyword) | |
206 | (keyword? ,_keyword?) | |
207 | (vector? ,vector?) | |
208 | (vector ,vector) | |
209 | (hash-map ,_hash-map) | |
210 | (map? ,hash-table?) | |
211 | (assoc ,_assoc) | |
212 | (get ,_get) | |
213 | (dissoc ,_dissoc) | |
214 | (keys ,_keys) | |
215 | (vals ,_vals) | |
216 | (contains? ,_contains?) | |
217 | (sequential? ,_sequential?) | |
94a0943a | 218 | (readline ,_readline) |
9f3c0995 NG |
219 | (meta ,_meta) |
220 | (with-meta ,_with-meta) | |
221 | (atom ,make-atom) | |
222 | (deref ,atom-val) | |
223 | (reset! ,atom-val-set!) | |
224 | (swap! ,_swap!) | |
225 | (conj ,_conj))) | |
be17d0a6 NG |
226 | |
227 | ;; Well, we have to rename it to this strange name... | |
228 | (define core.ns *primitives*) |