All: move some fns to core. Major cleanup.
[jackhill/mal.git] / 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
35symbol? = $(if $(call _symbol?,$(1)),$(__true),$(__false))
36
37
38# Number functions
39number? = $(if $(call _number?,$(1)),$(__true),$(__false))
40
41number_lt = $(if $(call int_lt,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
42number_lte = $(if $(call int_lte,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
43number_gt = $(if $(call int_gt,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
44number_gte = $(if $(call int_gte,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
45
46number_plus = $(call _pnumber,$(call int_plus,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
47number_subtract = $(call _pnumber,$(call int_subtract,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
48number_multiply = $(call _pnumber,$(call int_multiply,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
49number_divide = $(call _pnumber,$(call int_divide,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
50
51
52# String functions
53
8cb5cda4
JM
54string? = $(if $(call _string?,$(1)),$(__true),$(__false))
55
ea81a808
JM
56pr_str = $(call _string,$(call _pr_str_mult,$(1),yes, ))
57str = $(call _string,$(call _pr_str_mult,$(1),,))
58prn = $(info $(call _pr_str_mult,$(1),yes, ))
59println = $(info $(subst \n,$(NEWLINE),$(call _pr_str_mult,$(1),, )))
60
8cb5cda4
JM
61readline= $(foreach res,$(call _string,$(call READLINE,"$(call str_decode,$($(1)_value))")),$(if $(READLINE_EOF),$(__nil),$(res)))
62read_str= $(call READ_STR,$(1))
63slurp = $(call _string,$(call _read_file,$(call str_decode,$($(1)_value))))
ea81a808
JM
64
65subs = $(strip \
66 $(foreach start,$(call gmsl_plus,1,$(call int_decode,$($(word 2,$(1))_value))),\
67 $(foreach end,$(if $(3),$(call int_decode,$($(3)_value)),$(words $($(word 1,$(1))_value))),\
68 $(call _string,$(wordlist $(start),$(end),$($(word 1,$(1))_value))))))
69
70
71
72# Function functions
73function? = $(if $(call _function?,$(1)),$(__true),$(__false))
74
75
76# List functions
77list? = $(if $(call _list?,$(1)),$(__true),$(__false))
78
79
80# Vector functions
81vector? = $(if $(call _vector?,$(1)),$(__true),$(__false))
82
83
84# Hash map (associative array) functions
85hash_map? = $(if $(call _hash_map?,$(1)),$(__true),$(__false))
86
87# set a key/value in a copy of the hash map
88assoc = $(word 1,\
89 $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\
90 $(hm) \
91 $(call _assoc_seq!,$(hm),$(wordlist 2,$(words $(1)),$(1)))))
92
93# unset keys in a copy of the hash map
94# TODO: this could be made more efficient by copying only the
95# keys that not being removed.
96dissoc = $(word 1,\
97 $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\
98 $(hm) \
99 $(foreach key,$(wordlist 2,$(words $(1)),$(1)),\
100 $(call _dissoc!,$(hm),$(call str_decode,$($(key)_value))))))
101
102keys = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$(call _string,$(word 4,$(subst _, ,$(v)))))))
103
104vals = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$($(v)))))
105
106# Hash map and vector functions
107
108# retrieve the value of a string key object from the hash map, or
109# retrive a vector by number object index
110get = $(strip \
7e9a2883
JM
111 $(if $(call _nil?,$(word 1,$(1))),\
112 $(__nil),\
113 $(if $(call _hash_map?,$(word 1,$(1))),\
114 $(call _get,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),\
115 $(call _get,$(word 1,$(1)),$(call int_decode,$($(word 2,$(1))_value))))))
ea81a808
JM
116
117contains? = $(if $(call _contains?,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),$(__true),$(__false))
118
119
120# sequence operations
121
122sequential? = $(if $(call _sequential?,$(1)),$(__true),$(__false))
123
124cons = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(word 1,$(1)) $(call __get_obj_values,$(word 2,$(1)))))))
125
126concat = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(foreach lst,$1,$(call __get_obj_values,$(lst)))))))
127
128nth = $(word $(call gmsl_plus,1,$(call int_decode,$($(word 2,$(1))_value))),$($(word 1,$(1))_value))
129
130sfirst = $(word 1,$($(1)_value))
131
132slast = $(word $(words $($(1)_value)),$($(1)_value))
133
134empty? = $(if $(call _EQ,0,$(if $(call _hash_map?,$(1)),$($(1)_size),$(words $($(1)_value)))),$(__true),$(__false))
135
136count = $(call _number,$(call _count,$(1)))
137
138conj = $(word 1,$(foreach new_list,$(call __new_obj_like,$(word 1,$(1))),\
139 $(new_list) \
140 $(eval $(new_list)_value := $(strip $($(word 1,$(1))_value))) \
141 $(if $(call _list?,$(new_list)),\
142 $(foreach elem,$(wordlist 2,$(words $(1)),$(1)),\
143 $(eval $(new_list)_value := $(strip $(elem) $($(new_list)_value)))),\
144 $(eval $(new_list)_value := $(strip $($(new_list)_value) $(wordlist 2,$(words $(1)),$(1)))))))
145
146# Creates a new vector/list of the everything after but the first
147# element
148srest = $(word 1,$(foreach new_list,$(call _list),\
149 $(new_list) \
150 $(eval $(new_list)_value := $(wordlist 2,$(words $($(1)_value)),$($(1)_value)))))
151
152# Takes a space separated arguments and invokes the first argument
153# (function object) using the remaining arguments.
154sapply = $(call $(word 1,$(1))_value,\
155 $(strip \
156 $(wordlist 2,$(call gmsl_subtract,$(words $(1)),1),$(1)) \
157 $($(word $(words $(1)),$(1))_value)))
158
159# Map a function object over a list object
160smap = $(strip\
161 $(foreach func,$(word 1,$(1)),\
162 $(foreach lst,$(word 2,$(1)),\
163 $(foreach type,$(word 2,$(subst _, ,$(lst))),\
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
171
172# Metadata functions
173
174with_meta = $(strip \
175 $(foreach new_obj,$(call _clone_obj,$(word 1,$(1))),\
176 $(eval $(new_obj)_meta := $(strip $(word 2,$(1))))\
177 $(new_obj)))
178
179meta = $(strip $($(1)_meta))
180
181
182# Atom functions
183
184atom = $(strip \
185 $(foreach hcode,$(call __new_obj_hash_code),\
186 $(foreach new_atom,$(__obj_magic)_atom_$(hcode),\
187 $(new_atom)\
188 $(eval $(new_atom)_value := $(1)))))
189atom? = $(if $(call _atom?,$(1)),$(__true),$(__false))
190
191deref = $($(1)_value)
192
193reset! = $(eval $(word 1,$(1))_value := $(word 2,$(1)))$(word 2,$(1))
194
195swap! = $(foreach resp,$(call $(word 2,$(1))_value,$($(word 1,$(1))_value) $(wordlist 3,$(words $(1)),$(1))),\
196 $(eval $(word 1,$(1))_value := $(resp))\
197 $(resp))
198
199
200
201
202# Namespace of core functions
203
204core_ns = type obj_type \
205 = equal? \
206 throw throw \
207 nil? nil? \
208 true? true? \
209 false? false? \
210 symbol _symbol \
211 symbol? symbol? \
212 function? function? \
213 string? string? \
8cb5cda4 214 \
ea81a808
JM
215 pr-str pr_str \
216 str str \
217 prn prn \
218 println println \
8cb5cda4
JM
219 readline readline \
220 read-string read_str \
221 slurp slurp \
ea81a808
JM
222 subs subs \
223 number? number? \
224 < number_lt \
225 <= number_lte \
226 > number_gt \
227 >= number_gte \
228 + number_plus \
229 - number_subtract \
230 * number_multiply \
231 / number_divide \
232 \
233 list _list \
234 list? list? \
235 vector _vector \
236 vector? vector? \
237 hash-map _hash_map \
238 map? hash_map? \
239 assoc assoc \
240 dissoc dissoc \
241 get get \
242 contains? contains? \
243 keys keys \
244 vals vals \
245 \
246 sequential? sequential? \
247 cons cons \
248 concat concat \
249 nth nth \
250 first sfirst \
251 rest srest \
252 last slast \
253 empty? empty? \
254 count count \
255 conj conj \
256 apply sapply \
257 map smap \
258 \
259 with-meta with_meta \
260 meta meta \
261 atom atom \
262 atom? atom? \
263 deref deref \
264 reset! reset! \
265 swap! swap!
266
267endif