ada.2: typo
[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
90
91# Hash map (associative array) functions
92hash_map? = $(if $(call _hash_map?,$(1)),$(__true),$(__false))
93
94# set a key/value in a copy of the hash map
95assoc = $(word 1,\
96 $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\
97 $(hm) \
98 $(call _assoc_seq!,$(hm),$(wordlist 2,$(words $(1)),$(1)))))
99
100# unset keys in a copy of the hash map
101# TODO: this could be made more efficient by copying only the
102# keys that not being removed.
103dissoc = $(word 1,\
104 $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\
105 $(hm) \
b8ee29b2 106 $(call _dissoc_seq!,$(hm),$(wordlist 2,$(words $(1)),$(1)))))
ea81a808 107
b8ee29b2 108keys = $(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
109
110vals = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$($(v)))))
111
112# Hash map and vector functions
113
114# retrieve the value of a string key object from the hash map, or
115# retrive a vector by number object index
116get = $(strip \
7e9a2883
JM
117 $(if $(call _nil?,$(word 1,$(1))),\
118 $(__nil),\
119 $(if $(call _hash_map?,$(word 1,$(1))),\
120 $(call _get,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),\
121 $(call _get,$(word 1,$(1)),$(call int_decode,$($(word 2,$(1))_value))))))
ea81a808
JM
122
123contains? = $(if $(call _contains?,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),$(__true),$(__false))
124
125
126# sequence operations
127
128sequential? = $(if $(call _sequential?,$(1)),$(__true),$(__false))
129
130cons = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(word 1,$(1)) $(call __get_obj_values,$(word 2,$(1)))))))
131
132concat = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(foreach lst,$1,$(call __get_obj_values,$(lst)))))))
133
b8ee29b2
JM
134nth = $(strip \
135 $(if $(call int_lt,$($(word 2,$(1))_value),$(call int_encode,$(call _count,$(word 1,$(1))))),\
f4c8a091 136 $(word $(call int_add,1,$(call int_decode,$($(word 2,$(1))_value))),$($(word 1,$(1))_value)),\
b8ee29b2 137 $(call _error,nth: index out of range)))
ea81a808
JM
138
139sfirst = $(word 1,$($(1)_value))
140
141slast = $(word $(words $($(1)_value)),$($(1)_value))
142
143empty? = $(if $(call _EQ,0,$(if $(call _hash_map?,$(1)),$($(1)_size),$(words $($(1)_value)))),$(__true),$(__false))
144
145count = $(call _number,$(call _count,$(1)))
146
ea81a808
JM
147# Creates a new vector/list of the everything after but the first
148# element
149srest = $(word 1,$(foreach new_list,$(call _list),\
150 $(new_list) \
151 $(eval $(new_list)_value := $(wordlist 2,$(words $($(1)_value)),$($(1)_value)))))
152
153# Takes a space separated arguments and invokes the first argument
154# (function object) using the remaining arguments.
edda92c8
JM
155sapply = $(call $(word 1,$(1))_value,$(strip \
156 $(wordlist 2,$(call int_sub,$(words $(1)),1),$(1)) \
a968e287 157 $($(word $(words $(1)),$(1))_value)))
ea81a808
JM
158
159# Map a function object over a list object
160smap = $(strip\
161 $(foreach func,$(word 1,$(1)),\
162 $(foreach lst,$(word 2,$(1)),\
dbac60df 163 $(foreach type,list,\
ea81a808
JM
164 $(foreach new_hcode,$(call __new_obj_hash_code),\
165 $(foreach sz,$(words $(call __get_obj_values,$(lst))),\
166 $(eval $(__obj_magic)_$(type)_$(new_hcode)_value := $(strip \
167 $(foreach val,$(call __get_obj_values,$(lst)),\
168 $(call $(func)_value,$(val))))))\
169 $(__obj_magic)_$(type)_$(new_hcode))))))
170
a968e287
JM
171conj = $(word 1,$(foreach new_list,$(call __new_obj_like,$(word 1,$(1))),\
172 $(new_list) \
173 $(eval $(new_list)_value := $(strip $($(word 1,$(1))_value))) \
174 $(if $(call _list?,$(new_list)),\
175 $(foreach elem,$(wordlist 2,$(words $(1)),$(1)),\
176 $(eval $(new_list)_value := $(strip $(elem) $($(new_list)_value)))),\
177 $(eval $(new_list)_value := $(strip $($(new_list)_value) $(wordlist 2,$(words $(1)),$(1)))))))
178
179seq = $(strip\
180 $(if $(call _list?,$(1)),\
181 $(if $(call _EQ,0,$(call _count,$(1))),$(__nil),$(1)),\
182 $(if $(call _vector?,$(1)),\
183 $(if $(call _EQ,0,$(call _count,$(1))),\
184 $(__nil),\
185 $(word 1,$(foreach new_list,$(call _list),\
186 $(new_list) \
187 $(eval $(new_list)_value := $(strip $($(word 1,$(1))_value)))))),\
188 $(if $(call _EQ,string,$(call _obj_type,$(1))),\
189 $(if $(call _EQ,0,$(call _count,$(1))),\
190 $(__nil),\
191 $(word 1,$(foreach new_list,$(call _list),\
192 $(new_list) \
193 $(eval $(new_list)_value := $(strip \
194 $(foreach c,$($(word 1,$(1))_value),\
195 $(call _string,$(c)))))))),\
196 $(if $(call _nil?,$(1)),\
197 $(__nil),\
198 $(call _error,seq: called on non-sequence))))))
ea81a808
JM
199
200# Metadata functions
201
202with_meta = $(strip \
203 $(foreach new_obj,$(call _clone_obj,$(word 1,$(1))),\
204 $(eval $(new_obj)_meta := $(strip $(word 2,$(1))))\
205 $(new_obj)))
206
207meta = $(strip $($(1)_meta))
208
209
210# Atom functions
211
212atom = $(strip \
213 $(foreach hcode,$(call __new_obj_hash_code),\
214 $(foreach new_atom,$(__obj_magic)_atom_$(hcode),\
215 $(new_atom)\
216 $(eval $(new_atom)_value := $(1)))))
217atom? = $(if $(call _atom?,$(1)),$(__true),$(__false))
218
219deref = $($(1)_value)
220
221reset! = $(eval $(word 1,$(1))_value := $(word 2,$(1)))$(word 2,$(1))
222
223swap! = $(foreach resp,$(call $(word 2,$(1))_value,$($(word 1,$(1))_value) $(wordlist 3,$(words $(1)),$(1))),\
224 $(eval $(word 1,$(1))_value := $(resp))\
225 $(resp))
226
227
228
229
230# Namespace of core functions
231
232core_ns = type obj_type \
233 = equal? \
234 throw throw \
235 nil? nil? \
236 true? true? \
237 false? false? \
a968e287 238 string? string? \
b8ee29b2 239 symbol symbol \
ea81a808 240 symbol? symbol? \
b8ee29b2
JM
241 keyword keyword \
242 keyword? keyword? \
b156d1f1
JM
243 number? number? \
244 fn? fn? \
245 macro? macro? \
8cb5cda4 246 \
ea81a808
JM
247 pr-str pr_str \
248 str str \
249 prn prn \
250 println println \
8cb5cda4
JM
251 readline readline \
252 read-string read_str \
253 slurp slurp \
ea81a808 254 subs subs \
ea81a808
JM
255 < number_lt \
256 <= number_lte \
257 > number_gt \
258 >= number_gte \
259 + number_plus \
260 - number_subtract \
261 * number_multiply \
262 / number_divide \
f4c8a091 263 time-ms time_ms \
ea81a808
JM
264 \
265 list _list \
266 list? list? \
267 vector _vector \
268 vector? vector? \
269 hash-map _hash_map \
270 map? hash_map? \
271 assoc assoc \
272 dissoc dissoc \
273 get get \
274 contains? contains? \
275 keys keys \
276 vals vals \
277 \
278 sequential? sequential? \
279 cons cons \
280 concat concat \
281 nth nth \
282 first sfirst \
283 rest srest \
284 last slast \
285 empty? empty? \
286 count count \
ea81a808
JM
287 apply sapply \
288 map smap \
289 \
a968e287
JM
290 conj conj \
291 seq seq \
292 \
ea81a808
JM
293 with-meta with_meta \
294 meta meta \
295 atom atom \
296 atom? atom? \
297 deref deref \
298 reset! reset! \
299 swap! swap!
300
301endif