Commit | Line | Data |
---|---|---|
ea81a808 JM |
1 | # |
2 | # mal (Make a Lisp) Core functions | |
3 | # | |
4 | ||
5 | ifndef __mal_core_included | |
6 | __mal_core_included := true | |
7 | ||
8 | _TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST))) | |
9 | include $(_TOP_DIR)util.mk | |
10 | include $(_TOP_DIR)types.mk | |
8cb5cda4 JM |
11 | include $(_TOP_DIR)readline.mk |
12 | include $(_TOP_DIR)reader.mk | |
ea81a808 JM |
13 | include $(_TOP_DIR)printer.mk |
14 | ||
15 | ||
16 | # Errors/Exceptions | |
17 | throw = $(eval __ERROR := $(1)) | |
18 | ||
19 | ||
20 | # General functions | |
21 | ||
22 | # Return the type of the object (or "make" if it's not a object | |
23 | obj_type = $(call _string,$(call _obj_type,$(1))) | |
24 | ||
25 | equal? = $(if $(call _equal?,$(word 1,$(1)),$(word 2,$(1))),$(__true),$(__false)) | |
26 | ||
27 | ||
28 | # Scalar functions | |
29 | nil? = $(if $(call _nil?,$(1)),$(__true),$(__false)) | |
30 | true? = $(if $(call _true?,$(1)),$(__true),$(__false)) | |
31 | false? = $(if $(call _false?,$(1)),$(__true),$(__false)) | |
32 | ||
33 | ||
34 | # Symbol functions | |
b8ee29b2 | 35 | symbol = $(call _symbol,$(call str_decode,$($(1)_value))) |
ea81a808 JM |
36 | symbol? = $(if $(call _symbol?,$(1)),$(__true),$(__false)) |
37 | ||
b8ee29b2 JM |
38 | # Keyword functions |
39 | keyword = $(call _keyword,$(call str_decode,$($(1)_value))) | |
40 | keyword? = $(if $(call _keyword?,$(1)),$(__true),$(__false)) | |
41 | ||
ea81a808 JM |
42 | |
43 | # Number functions | |
44 | number? = $(if $(call _number?,$(1)),$(__true),$(__false)) | |
45 | ||
f4c8a091 JM |
46 | number_lt = $(if $(call int_lt_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false)) |
47 | number_lte = $(if $(call int_lte_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false)) | |
48 | number_gt = $(if $(call int_gt_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false)) | |
49 | number_gte = $(if $(call int_gte_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false)) | |
ea81a808 | 50 | |
f4c8a091 JM |
51 | number_plus = $(call _pnumber,$(call int_add_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value))) |
52 | number_subtract = $(call _pnumber,$(call int_sub_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value))) | |
53 | number_multiply = $(call _pnumber,$(call int_mult_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value))) | |
54 | number_divide = $(call _pnumber,$(call int_div_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value))) | |
db4c329a | 55 | |
f4c8a091 | 56 | time_ms = $(call _number,$(shell echo $$(date +%s%3N))) |
ea81a808 JM |
57 | |
58 | # String functions | |
59 | ||
a968e287 | 60 | string? = $(if $(call _string?,$(1)),$(if $(call _keyword?,$(1)),$(__false),$(__true)),$(__false)) |
8cb5cda4 | 61 | |
ea81a808 JM |
62 | pr_str = $(call _string,$(call _pr_str_mult,$(1),yes, )) |
63 | str = $(call _string,$(call _pr_str_mult,$(1),,)) | |
64 | prn = $(info $(call _pr_str_mult,$(1),yes, )) | |
65 | println = $(info $(subst \n,$(NEWLINE),$(call _pr_str_mult,$(1),, ))) | |
66 | ||
92474a1b | 67 | readline= $(foreach res,$(call _string,$(call READLINE,"$(call str_decode,$($(1)_value))")),$(if $(READLINE_EOF),$(eval READLINE_EOF :=)$(__nil),$(res))) |
8cb5cda4 JM |
68 | read_str= $(call READ_STR,$(1)) |
69 | slurp = $(call _string,$(call _read_file,$(call str_decode,$($(1)_value)))) | |
ea81a808 JM |
70 | |
71 | subs = $(strip \ | |
f4c8a091 | 72 | $(foreach start,$(call int_add,1,$(call int_decode,$($(word 2,$(1))_value))),\ |
ea81a808 JM |
73 | $(foreach end,$(if $(3),$(call int_decode,$($(3)_value)),$(words $($(word 1,$(1))_value))),\ |
74 | $(call _string,$(wordlist $(start),$(end),$($(word 1,$(1))_value)))))) | |
75 | ||
76 | ||
77 | ||
78 | # Function functions | |
b156d1f1 JM |
79 | fn? = $(if $(call _function?,$(1)),$(if $(_macro_$(1)),$(__false),$(__true)),$(__false)) |
80 | macro? = $(if $(_macro_$(1)),$(__true),$(__false)) | |
ea81a808 JM |
81 | |
82 | ||
83 | # List functions | |
84 | list? = $(if $(call _list?,$(1)),$(__true),$(__false)) | |
85 | ||
86 | ||
87 | # Vector functions | |
88 | vector? = $(if $(call _vector?,$(1)),$(__true),$(__false)) | |
89 | ||
fbfe6784 NB |
90 | vec = $(if $(_list?),$(call _vector,$($1_value)),$(if $(_vector?),$1,$(call _error,vec: called on non-sequence))) |
91 | ||
ea81a808 JM |
92 | |
93 | # Hash map (associative array) functions | |
94 | hash_map? = $(if $(call _hash_map?,$(1)),$(__true),$(__false)) | |
95 | ||
96 | # set a key/value in a copy of the hash map | |
97 | assoc = $(word 1,\ | |
98 | $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\ | |
99 | $(hm) \ | |
100 | $(call _assoc_seq!,$(hm),$(wordlist 2,$(words $(1)),$(1))))) | |
101 | ||
102 | # unset keys in a copy of the hash map | |
103 | # TODO: this could be made more efficient by copying only the | |
104 | # keys that not being removed. | |
105 | dissoc = $(word 1,\ | |
106 | $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\ | |
107 | $(hm) \ | |
b8ee29b2 | 108 | $(call _dissoc_seq!,$(hm),$(wordlist 2,$(words $(1)),$(1))))) |
ea81a808 | 109 | |
b8ee29b2 | 110 | keys = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$(foreach vval,$(word 4,$(subst _, ,$(v))),$(if $(filter $(__keyword)%,$(vval)),$(call _keyword,$(patsubst $(__keyword)%,%,$(vval))),$(call _string,$(vval))))))) |
ea81a808 JM |
111 | |
112 | vals = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$($(v))))) | |
113 | ||
114 | # Hash map and vector functions | |
115 | ||
116 | # retrieve the value of a string key object from the hash map, or | |
117 | # retrive a vector by number object index | |
118 | get = $(strip \ | |
7e9a2883 JM |
119 | $(if $(call _nil?,$(word 1,$(1))),\ |
120 | $(__nil),\ | |
121 | $(if $(call _hash_map?,$(word 1,$(1))),\ | |
122 | $(call _get,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),\ | |
123 | $(call _get,$(word 1,$(1)),$(call int_decode,$($(word 2,$(1))_value)))))) | |
ea81a808 JM |
124 | |
125 | contains? = $(if $(call _contains?,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),$(__true),$(__false)) | |
126 | ||
127 | ||
128 | # sequence operations | |
129 | ||
130 | sequential? = $(if $(call _sequential?,$(1)),$(__true),$(__false)) | |
131 | ||
132 | cons = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(word 1,$(1)) $(call __get_obj_values,$(word 2,$(1))))))) | |
133 | ||
134 | concat = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(foreach lst,$1,$(call __get_obj_values,$(lst))))))) | |
135 | ||
b8ee29b2 JM |
136 | nth = $(strip \ |
137 | $(if $(call int_lt,$($(word 2,$(1))_value),$(call int_encode,$(call _count,$(word 1,$(1))))),\ | |
f4c8a091 | 138 | $(word $(call int_add,1,$(call int_decode,$($(word 2,$(1))_value))),$($(word 1,$(1))_value)),\ |
b8ee29b2 | 139 | $(call _error,nth: index out of range))) |
ea81a808 JM |
140 | |
141 | sfirst = $(word 1,$($(1)_value)) | |
142 | ||
143 | slast = $(word $(words $($(1)_value)),$($(1)_value)) | |
144 | ||
fbfe6784 | 145 | empty? = $(if $(_empty?),$(__true),$(__false)) |
ea81a808 JM |
146 | |
147 | count = $(call _number,$(call _count,$(1))) | |
148 | ||
ea81a808 JM |
149 | # Creates a new vector/list of the everything after but the first |
150 | # element | |
151 | srest = $(word 1,$(foreach new_list,$(call _list),\ | |
152 | $(new_list) \ | |
153 | $(eval $(new_list)_value := $(wordlist 2,$(words $($(1)_value)),$($(1)_value))))) | |
154 | ||
155 | # Takes a space separated arguments and invokes the first argument | |
156 | # (function object) using the remaining arguments. | |
edda92c8 JM |
157 | sapply = $(call $(word 1,$(1))_value,$(strip \ |
158 | $(wordlist 2,$(call int_sub,$(words $(1)),1),$(1)) \ | |
a968e287 | 159 | $($(word $(words $(1)),$(1))_value))) |
ea81a808 JM |
160 | |
161 | # Map a function object over a list object | |
162 | smap = $(strip\ | |
163 | $(foreach func,$(word 1,$(1)),\ | |
164 | $(foreach lst,$(word 2,$(1)),\ | |
dbac60df | 165 | $(foreach type,list,\ |
ea81a808 JM |
166 | $(foreach new_hcode,$(call __new_obj_hash_code),\ |
167 | $(foreach sz,$(words $(call __get_obj_values,$(lst))),\ | |
168 | $(eval $(__obj_magic)_$(type)_$(new_hcode)_value := $(strip \ | |
169 | $(foreach val,$(call __get_obj_values,$(lst)),\ | |
170 | $(call $(func)_value,$(val))))))\ | |
171 | $(__obj_magic)_$(type)_$(new_hcode)))))) | |
172 | ||
a968e287 JM |
173 | conj = $(word 1,$(foreach new_list,$(call __new_obj_like,$(word 1,$(1))),\ |
174 | $(new_list) \ | |
175 | $(eval $(new_list)_value := $(strip $($(word 1,$(1))_value))) \ | |
176 | $(if $(call _list?,$(new_list)),\ | |
177 | $(foreach elem,$(wordlist 2,$(words $(1)),$(1)),\ | |
178 | $(eval $(new_list)_value := $(strip $(elem) $($(new_list)_value)))),\ | |
179 | $(eval $(new_list)_value := $(strip $($(new_list)_value) $(wordlist 2,$(words $(1)),$(1))))))) | |
180 | ||
181 | seq = $(strip\ | |
182 | $(if $(call _list?,$(1)),\ | |
183 | $(if $(call _EQ,0,$(call _count,$(1))),$(__nil),$(1)),\ | |
184 | $(if $(call _vector?,$(1)),\ | |
185 | $(if $(call _EQ,0,$(call _count,$(1))),\ | |
186 | $(__nil),\ | |
187 | $(word 1,$(foreach new_list,$(call _list),\ | |
188 | $(new_list) \ | |
189 | $(eval $(new_list)_value := $(strip $($(word 1,$(1))_value)))))),\ | |
190 | $(if $(call _EQ,string,$(call _obj_type,$(1))),\ | |
191 | $(if $(call _EQ,0,$(call _count,$(1))),\ | |
192 | $(__nil),\ | |
193 | $(word 1,$(foreach new_list,$(call _list),\ | |
194 | $(new_list) \ | |
195 | $(eval $(new_list)_value := $(strip \ | |
196 | $(foreach c,$($(word 1,$(1))_value),\ | |
197 | $(call _string,$(c)))))))),\ | |
198 | $(if $(call _nil?,$(1)),\ | |
199 | $(__nil),\ | |
200 | $(call _error,seq: called on non-sequence)))))) | |
ea81a808 JM |
201 | |
202 | # Metadata functions | |
203 | ||
204 | with_meta = $(strip \ | |
205 | $(foreach new_obj,$(call _clone_obj,$(word 1,$(1))),\ | |
206 | $(eval $(new_obj)_meta := $(strip $(word 2,$(1))))\ | |
207 | $(new_obj))) | |
208 | ||
209 | meta = $(strip $($(1)_meta)) | |
210 | ||
211 | ||
212 | # Atom functions | |
213 | ||
214 | atom = $(strip \ | |
215 | $(foreach hcode,$(call __new_obj_hash_code),\ | |
216 | $(foreach new_atom,$(__obj_magic)_atom_$(hcode),\ | |
217 | $(new_atom)\ | |
218 | $(eval $(new_atom)_value := $(1))))) | |
219 | atom? = $(if $(call _atom?,$(1)),$(__true),$(__false)) | |
220 | ||
221 | deref = $($(1)_value) | |
222 | ||
223 | reset! = $(eval $(word 1,$(1))_value := $(word 2,$(1)))$(word 2,$(1)) | |
224 | ||
225 | swap! = $(foreach resp,$(call $(word 2,$(1))_value,$($(word 1,$(1))_value) $(wordlist 3,$(words $(1)),$(1))),\ | |
226 | $(eval $(word 1,$(1))_value := $(resp))\ | |
227 | $(resp)) | |
228 | ||
229 | ||
230 | ||
231 | ||
232 | # Namespace of core functions | |
233 | ||
234 | core_ns = type obj_type \ | |
235 | = equal? \ | |
236 | throw throw \ | |
237 | nil? nil? \ | |
238 | true? true? \ | |
239 | false? false? \ | |
a968e287 | 240 | string? string? \ |
b8ee29b2 | 241 | symbol symbol \ |
ea81a808 | 242 | symbol? symbol? \ |
b8ee29b2 JM |
243 | keyword keyword \ |
244 | keyword? keyword? \ | |
b156d1f1 JM |
245 | number? number? \ |
246 | fn? fn? \ | |
247 | macro? macro? \ | |
8cb5cda4 | 248 | \ |
ea81a808 JM |
249 | pr-str pr_str \ |
250 | str str \ | |
251 | prn prn \ | |
252 | println println \ | |
8cb5cda4 JM |
253 | readline readline \ |
254 | read-string read_str \ | |
255 | slurp slurp \ | |
ea81a808 | 256 | subs subs \ |
ea81a808 JM |
257 | < number_lt \ |
258 | <= number_lte \ | |
259 | > number_gt \ | |
260 | >= number_gte \ | |
261 | + number_plus \ | |
262 | - number_subtract \ | |
263 | * number_multiply \ | |
264 | / number_divide \ | |
f4c8a091 | 265 | time-ms time_ms \ |
ea81a808 JM |
266 | \ |
267 | list _list \ | |
268 | list? list? \ | |
269 | vector _vector \ | |
270 | vector? vector? \ | |
271 | hash-map _hash_map \ | |
272 | map? hash_map? \ | |
273 | assoc assoc \ | |
274 | dissoc dissoc \ | |
275 | get get \ | |
276 | contains? contains? \ | |
277 | keys keys \ | |
278 | vals vals \ | |
279 | \ | |
280 | sequential? sequential? \ | |
281 | cons cons \ | |
282 | concat concat \ | |
fbfe6784 | 283 | vec vec \ |
ea81a808 JM |
284 | nth nth \ |
285 | first sfirst \ | |
286 | rest srest \ | |
287 | last slast \ | |
288 | empty? empty? \ | |
289 | count count \ | |
ea81a808 JM |
290 | apply sapply \ |
291 | map smap \ | |
292 | \ | |
a968e287 JM |
293 | conj conj \ |
294 | seq seq \ | |
295 | \ | |
ea81a808 JM |
296 | with-meta with_meta \ |
297 | meta meta \ | |
298 | atom atom \ | |
299 | atom? atom? \ | |
300 | deref deref \ | |
301 | reset! reset! \ | |
302 | swap! swap! | |
303 | ||
304 | endif |