-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.mal
271 lines (219 loc) · 7.72 KB
/
init.mal
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
;;global settings
(defmacro! type
(fn* (atom)
(cond (symbol? atom) (prn "symbol")
(string? atom) (prn "string")
(list? atom) (prn "list")
(map? atom) (prn "map")
(vector? atom) (prn "vector")
(sequential? atom) (prn "sequential")
(atom? atom) (prn "atom")
(else (prn "unknown")))))
(defmacro! use
(fn* (& x)
(let* [env (eval (first x)) msg (nth x 1)]
(if (> (count x) 2)
(send-msg env msg (nth x 2))
(send-msg env msg)))))
(defmacro! use-to-mal
(fn* (& x)
(let* [env (eval (first x)) msg (nth x 1)]
(read-string (send-msg env msg)))))
(def! pr-list
(fn* (x)
(if (> (count x) 0)
(do
(prn (first x))
(pr-list (rest x))))))
(defmacro! dotimes
(fn* (xs & body)
(if (> xs 0)
(do
(eval (cons 'do body))
(eval (cons 'dotimes (conj body (- xs 1))))))))
(def! bind-env (fn* [env b e]
(if (empty? b)
env
(let* [b0 (first b)]
(if (= '& b0)
(assoc env (str (nth b 1)) e)
(bind-env (assoc env (str b0) (first e)) (rest b) (rest e)))))))
(def! new-env (fn* [& args]
(if (<= (count args) 1)
(atom {:outer (first args)})
(atom (apply bind-env {:outer (first args)} (rest args))))))
(def! env-find (fn* [env k]
(env-find-str env (str k))))
;; Private helper for env-find and env-get.
(def! env-find-str (fn* [env ks]
(if env
(let* [data @env]
(if (contains? data ks)
env
(env-find-str (get data :outer) ks))))))
(def! env-get (fn* [env k]
(let* [ks (str k)
e (env-find-str env ks)]
(if e
(get @e ks)
(str "'" ks "' not found")))))
(def! env-set (fn* [env k v]
(do
(swap! env assoc (str k) v)
v)))
(def! car first)
(def! cdr rest)
(def! global (new-env))
;;set remote server address
(def! remote '(localhost 1234))
(def! global-symbols
(fn* []
(map (fn* [x] (read-string x)) (global-symbols-string))))
(def! contains?
(fn* [lst x]
(if (<= (count lst) 0)
false
(if (= (first lst) x)
true
(contains? (rest lst) x)))))
;;download remote servers map
;;(def! servers-map (read-string (use remote servers-map)))
;;core.lisp
;; (def! _macro? (fn* [x]
;; (if (map? x)
;; (contains? x :__MAL_MACRO__)
;; false)))
;; (def! core_ns '[* + - / < <= = > >= apply assoc atom atom? concat conj
;; cons contains? count deref dissoc empty? false? first fn? get
;; hash-map keys keyword keyword? list list? map map? meta nil?
;; nth number? pr-str println prn read-string readline reset! rest seq
;; sequential? slurp str string? swap! symbol symbol? throw time-ms
;; true? vals vec vector vector? with-meta])
;; (def! trace (atom ""))
;; ;; read
;; (def! READ read-string)
;; ;; eval
;; (def! qq-loop (fn* [elt acc]
;; (if (if (list? elt) (= (first elt) 'splice-unquote)) ; 2nd 'if' means 'and'
;; (list 'concat (nth elt 1) acc)
;; (list 'cons (QUASIQUOTE elt) acc))))
;; (def! qq-foldr (fn* [xs]
;; (if (empty? xs)
;; ()
;; (qq-loop (first xs) (qq-foldr (rest xs))))))
;; (def! QUASIQUOTE (fn* [ast]
;; (cond
;; (vector? ast) (list 'vec (qq-foldr ast))
;; (map? ast) (list 'quote ast)
;; (symbol? ast) (list 'quote ast)
;; (not (list? ast)) ast
;; (= (first ast) 'unquote) (nth ast 1)
;; "else" (qq-foldr ast))))
;; (def! MACROEXPAND (fn* [ast env]
;; (let* [a0 (if (list? ast) (first ast))
;; e (if (symbol? a0) (env-find env a0))
;; m (if e (env-get e a0))]
;; (if (_macro? m)
;; (MACROEXPAND (apply (get m :__MAL_MACRO__) (rest ast)) env)
;; ast))))
;; (def! eval-ast (fn* [ast env]
;; ;; (do (prn "eval-ast" ast "/" (keys @env)) )
;; (cond
;; (symbol? ast) (env-get env ast)
;; (list? ast) (map (fn* [exp] (EVAL exp env)) ast)
;; (vector? ast) (vec (map (fn* [exp] (EVAL exp env)) ast))
;; (map? ast) (apply hash-map
;; (apply concat
;; (map (fn* [k] [k (EVAL (get ast k) env)])
;; (keys ast))))
;; "else" ast)))
;; (def! LET (fn* [env binds form]
;; (if (empty? binds)
;; (EVAL form env)
;; (do
;; (env-set env (first binds) (EVAL (nth binds 1) env))
;; (LET env (rest (rest binds)) form)))))
;; (def! EVAL (fn* [ast env]
;; ;; (do (prn "EVAL" ast "/" (keys @env)) )
;; (try*
;; (let* [ast (MACROEXPAND ast env)]
;; (if (not (list? ast))
;; (eval-ast ast env)
;; ;; apply list
;; (let* [a0 (first ast)]
;; (cond
;; (empty? ast)
;; ast
;; (= 'def! a0)
;; (env-set env (nth ast 1) (EVAL (nth ast 2) env))
;; (= 'let* a0)
;; (LET (new-env env) (nth ast 1) (nth ast 2))
;; (= 'quote a0)
;; (nth ast 1)
;; (= 'quasiquoteexpand a0)
;; (QUASIQUOTE (nth ast 1))
;; (= 'quasiquote a0)
;; (EVAL (QUASIQUOTE (nth ast 1)) env)
;; (= 'defmacro! a0)
;; (env-set env (nth ast 1) (hash-map :__MAL_MACRO__
;; (EVAL (nth ast 2) env)))
;; (= 'macroexpand a0)
;; (MACROEXPAND (nth ast 1) env)
;; (= 'try* a0)
;; (if (< (count ast) 3)
;; (EVAL (nth ast 1) env)
;; (try*
;; (EVAL (nth ast 1) env)
;; (catch* exc
;; (do
;; (reset! trace "")
;; (let* [a2 (nth ast 2)]
;; (EVAL (nth a2 2) (new-env env [(nth a2 1)] [exc])))))))
;; (= 'do a0)
;; (nth (eval-ast (rest ast) env) (- (count ast) 2))
;; (= 'if a0)
;; (if (EVAL (nth ast 1) env)
;; (EVAL (nth ast 2) env)
;; (if (> (count ast) 3)
;; (EVAL (nth ast 3) env)))
;; (= 'fn* a0)
;; (fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
;; "else"
;; (let* [el (eval-ast ast env)]
;; (apply (first el) (rest el)))))))
;; (catch* exc
;; (do
;; (swap! trace str "\n in mal EVAL: " ast)
;; (throw exc))))))
;; ;; print
;; (def! PRINT pr-str)
;; ;; repl
;; (def! repl-env (new-env))
;; (def! rep (fn* [strng]
;; (PRINT (EVAL (READ strng) repl-env))))
;; ;; core.mal: defined directly using mal
;; (map (fn* [sym] (env-set repl-env sym (eval sym))) core_ns)
;; (env-set repl-env 'macro? _macro?)
;; (env-set repl-env 'eval (fn* [ast] (EVAL ast repl-env)))
;; (env-set repl-env '*ARGV* (rest *ARGV*))
;; ;; core.mal: defined using the new language itself
;; (rep (str "(def! *host-language* \"" *host-language* "-mal\")"))
;; (rep "(def! not (fn* [a] (if a false true)))")
;; (rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))")
;; (rep "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))")
;; ;; repl loop
;; (def! repl-loop (fn* [line]
;; (if line
;; (do
;; (if (not (= "" line))
;; (try*
;; (println (rep line))
;; (catch* exc
;; (do
;; (println "Uncaught exception:" exc @trace)
;; (reset! trace "")))))
;; (repl-loop (readline "mal-user> "))))))
;; ;; main
;; ;; (if (empty? *ARGV*)
;; ;; (repl-loop "(println (str \"Mal [\" *host-language* \"]\"))")
;; ;; (rep (str "(load-file \"" (first *ARGV*) "\")")))