Change quasiquote algorithm
[jackhill/mal.git] / impls / make / core.mk
CommitLineData
ea81a808
JM
1#
2# mal (Make a Lisp) Core functions
3#
4
5ifndef __mal_core_included
6__mal_core_included := true
7
8_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
9include $(_TOP_DIR)util.mk
10include $(_TOP_DIR)types.mk
8cb5cda4
JM
11include $(_TOP_DIR)readline.mk
12include $(_TOP_DIR)reader.mk
ea81a808
JM
13include $(_TOP_DIR)printer.mk
14
15
16# Errors/Exceptions
17throw = $(eval __ERROR := $(1))
18
19
20# General functions
21
22# Return the type of the object (or "make" if it's not a object
23obj_type = $(call _string,$(call _obj_type,$(1)))
24
25equal? = $(if $(call _equal?,$(word 1,$(1)),$(word 2,$(1))),$(__true),$(__false))
26
27
28# Scalar functions
29nil? = $(if $(call _nil?,$(1)),$(__true),$(__false))
30true? = $(if $(call _true?,$(1)),$(__true),$(__false))
31false? = $(if $(call _false?,$(1)),$(__true),$(__false))
32
33
34# Symbol functions
b8ee29b2 35symbol = $(call _symbol,$(call str_decode,$($(1)_value)))
ea81a808
JM
36symbol? = $(if $(call _symbol?,$(1)),$(__true),$(__false))
37
b8ee29b2
JM
38# Keyword functions
39keyword = $(call _keyword,$(call str_decode,$($(1)_value)))
40keyword? = $(if $(call _keyword?,$(1)),$(__true),$(__false))
41
ea81a808
JM
42
43# Number functions
44number? = $(if $(call _number?,$(1)),$(__true),$(__false))
45
f4c8a091
JM
46number_lt = $(if $(call int_lt_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
47number_lte = $(if $(call int_lte_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
48number_gt = $(if $(call int_gt_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
49number_gte = $(if $(call int_gte_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
ea81a808 50
f4c8a091
JM
51number_plus = $(call _pnumber,$(call int_add_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
52number_subtract = $(call _pnumber,$(call int_sub_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
53number_multiply = $(call _pnumber,$(call int_mult_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
54number_divide = $(call _pnumber,$(call int_div_encoded,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
db4c329a 55
f4c8a091 56time_ms = $(call _number,$(shell echo $$(date +%s%3N)))
ea81a808
JM
57
58# String functions
59
a968e287 60string? = $(if $(call _string?,$(1)),$(if $(call _keyword?,$(1)),$(__false),$(__true)),$(__false))
8cb5cda4 61
ea81a808
JM
62pr_str = $(call _string,$(call _pr_str_mult,$(1),yes, ))
63str = $(call _string,$(call _pr_str_mult,$(1),,))
64prn = $(info $(call _pr_str_mult,$(1),yes, ))
65println = $(info $(subst \n,$(NEWLINE),$(call _pr_str_mult,$(1),, )))
66
92474a1b 67readline= $(foreach res,$(call _string,$(call READLINE,"$(call str_decode,$($(1)_value))")),$(if $(READLINE_EOF),$(eval READLINE_EOF :=)$(__nil),$(res)))
8cb5cda4
JM
68read_str= $(call READ_STR,$(1))
69slurp = $(call _string,$(call _read_file,$(call str_decode,$($(1)_value))))
ea81a808
JM
70
71subs = $(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
79fn? = $(if $(call _function?,$(1)),$(if $(_macro_$(1)),$(__false),$(__true)),$(__false))
80macro? = $(if $(_macro_$(1)),$(__true),$(__false))
ea81a808
JM
81
82
83# List functions
84list? = $(if $(call _list?,$(1)),$(__true),$(__false))
85
86
87# Vector functions
88vector? = $(if $(call _vector?,$(1)),$(__true),$(__false))
89
fbfe6784
NB
90vec = $(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
94hash_map? = $(if $(call _hash_map?,$(1)),$(__true),$(__false))
95
96# set a key/value in a copy of the hash map
97assoc = $(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.
105dissoc = $(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 110keys = $(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
112vals = $(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
118get = $(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
125contains? = $(if $(call _contains?,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),$(__true),$(__false))
126
127
128# sequence operations
129
130sequential? = $(if $(call _sequential?,$(1)),$(__true),$(__false))
131
132cons = $(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
134concat = $(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
136nth = $(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
141sfirst = $(word 1,$($(1)_value))
142
143slast = $(word $(words $($(1)_value)),$($(1)_value))
144
fbfe6784 145empty? = $(if $(_empty?),$(__true),$(__false))
ea81a808
JM
146
147count = $(call _number,$(call _count,$(1)))
148
ea81a808
JM
149# Creates a new vector/list of the everything after but the first
150# element
151srest = $(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
157sapply = $(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
162smap = $(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
173conj = $(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
181seq = $(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
204with_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
209meta = $(strip $($(1)_meta))
210
211
212# Atom functions
213
214atom = $(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)))))
219atom? = $(if $(call _atom?,$(1)),$(__true),$(__false))
220
221deref = $($(1)_value)
222
223reset! = $(eval $(word 1,$(1))_value := $(word 2,$(1)))$(word 2,$(1))
224
225swap! = $(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
234core_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
304endif