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 | |
35 | symbol? = $(if $(call _symbol?,$(1)),$(__true),$(__false)) | |
36 | ||
37 | ||
38 | # Number functions | |
39 | number? = $(if $(call _number?,$(1)),$(__true),$(__false)) | |
40 | ||
41 | number_lt = $(if $(call int_lt,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false)) | |
42 | number_lte = $(if $(call int_lte,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false)) | |
43 | number_gt = $(if $(call int_gt,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false)) | |
44 | number_gte = $(if $(call int_gte,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false)) | |
45 | ||
46 | number_plus = $(call _pnumber,$(call int_plus,$($(word 1,$(1))_value),$($(word 2,$(1))_value))) | |
47 | number_subtract = $(call _pnumber,$(call int_subtract,$($(word 1,$(1))_value),$($(word 2,$(1))_value))) | |
48 | number_multiply = $(call _pnumber,$(call int_multiply,$($(word 1,$(1))_value),$($(word 2,$(1))_value))) | |
49 | number_divide = $(call _pnumber,$(call int_divide,$($(word 1,$(1))_value),$($(word 2,$(1))_value))) | |
50 | ||
51 | ||
52 | # String functions | |
53 | ||
8cb5cda4 JM |
54 | string? = $(if $(call _string?,$(1)),$(__true),$(__false)) |
55 | ||
ea81a808 JM |
56 | pr_str = $(call _string,$(call _pr_str_mult,$(1),yes, )) |
57 | str = $(call _string,$(call _pr_str_mult,$(1),,)) | |
58 | prn = $(info $(call _pr_str_mult,$(1),yes, )) | |
59 | println = $(info $(subst \n,$(NEWLINE),$(call _pr_str_mult,$(1),, ))) | |
60 | ||
8cb5cda4 JM |
61 | readline= $(foreach res,$(call _string,$(call READLINE,"$(call str_decode,$($(1)_value))")),$(if $(READLINE_EOF),$(__nil),$(res))) |
62 | read_str= $(call READ_STR,$(1)) | |
63 | slurp = $(call _string,$(call _read_file,$(call str_decode,$($(1)_value)))) | |
ea81a808 JM |
64 | |
65 | subs = $(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 | |
73 | function? = $(if $(call _function?,$(1)),$(__true),$(__false)) | |
74 | ||
75 | ||
76 | # List functions | |
77 | list? = $(if $(call _list?,$(1)),$(__true),$(__false)) | |
78 | ||
79 | ||
80 | # Vector functions | |
81 | vector? = $(if $(call _vector?,$(1)),$(__true),$(__false)) | |
82 | ||
83 | ||
84 | # Hash map (associative array) functions | |
85 | hash_map? = $(if $(call _hash_map?,$(1)),$(__true),$(__false)) | |
86 | ||
87 | # set a key/value in a copy of the hash map | |
88 | assoc = $(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. | |
96 | dissoc = $(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 | ||
102 | keys = $(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 | ||
104 | vals = $(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 | |
110 | get = $(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 | |
117 | contains? = $(if $(call _contains?,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),$(__true),$(__false)) | |
118 | ||
119 | ||
120 | # sequence operations | |
121 | ||
122 | sequential? = $(if $(call _sequential?,$(1)),$(__true),$(__false)) | |
123 | ||
124 | 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))))))) | |
125 | ||
126 | concat = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(foreach lst,$1,$(call __get_obj_values,$(lst))))))) | |
127 | ||
128 | nth = $(word $(call gmsl_plus,1,$(call int_decode,$($(word 2,$(1))_value))),$($(word 1,$(1))_value)) | |
129 | ||
130 | sfirst = $(word 1,$($(1)_value)) | |
131 | ||
132 | slast = $(word $(words $($(1)_value)),$($(1)_value)) | |
133 | ||
134 | empty? = $(if $(call _EQ,0,$(if $(call _hash_map?,$(1)),$($(1)_size),$(words $($(1)_value)))),$(__true),$(__false)) | |
135 | ||
136 | count = $(call _number,$(call _count,$(1))) | |
137 | ||
138 | conj = $(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 | |
148 | srest = $(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. | |
154 | sapply = $(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 | |
160 | smap = $(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 | ||
174 | with_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 | ||
179 | meta = $(strip $($(1)_meta)) | |
180 | ||
181 | ||
182 | # Atom functions | |
183 | ||
184 | atom = $(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))))) | |
189 | atom? = $(if $(call _atom?,$(1)),$(__true),$(__false)) | |
190 | ||
191 | deref = $($(1)_value) | |
192 | ||
193 | reset! = $(eval $(word 1,$(1))_value := $(word 2,$(1)))$(word 2,$(1)) | |
194 | ||
195 | swap! = $(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 | ||
204 | core_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 | ||
267 | endif |