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