README: make NalaGinrut user name into a link.
[jackhill/mal.git] / make / types.mk
CommitLineData
31690700 1#
ea81a808 2# mal (Make a Lisp) object types
31690700
JM
3#
4
5ifndef __mal_types_included
6__mal_types_included := true
7
8_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
f4c8a091 9include $(_TOP_DIR)gmsl.mk
31690700 10include $(_TOP_DIR)util.mk
f4c8a091 11include $(_TOP_DIR)numbers.mk
31690700 12
ea81a808
JM
13
14# Low-level type implemenation
15
31690700
JM
16# magic is \u2344 \u204a
17__obj_magic = ⍄⁊
18# \u2256
19__equal = ≛
b8ee29b2 20__keyword = ʞ
31690700
JM
21__obj_hash_code = 0
22
f4c8a091 23__new_obj_hash_code = $(eval __obj_hash_code := $(call int_add,1,$(__obj_hash_code)))$(__obj_hash_code)
31690700
JM
24
25__new_obj = $(__obj_magic)_$(1)_$(call __new_obj_hash_code)
26
27__new_obj_like = $(foreach type,$(word 2,$(subst _, ,$(1))),$(__obj_magic)_$(type)_$(__new_obj_hash_code))
28
29__get_obj_values = $(strip \
30 $(if $(filter $(__obj_magic)_hmap_%,$(1)),\
31 $(sort $(foreach v,$(filter %_value,$(filter $(1)_%,$(.VARIABLES))),$(if $(call _undefined?,$(v)),,$(v)))),\
32 $($(1)_value)))
33
ea81a808
JM
34
35# Visualize Objects in memory
36__var_name = $(word 2,$(subst _, ,$(1)))_$(word 3,$(subst _, ,$(1)))
37__var_idx := 0
38__var_print = $(foreach v,$(1),\
39 $(foreach var,$(call __var_name,$(v)),\
40 $(if $(or $(call _list?,$(v)),$(call _vector?,$(v))),\
41 $(info $(2)$(var):)\
f4c8a091 42 $(eval __var_idx := $(call int_add,1,$(__var_idx)))\
ea81a808
JM
43 $(foreach lidx,__lidx_$(__var_idx),\
44 $(eval $(lidx) := 0)\
45 $(foreach val,$($(v)_value),\
46 $(call __var_print,$(val),$(2)$(SPACE)$(SPACE)$($(lidx)): )\
f4c8a091 47 $(eval $(lidx) := $(call int_add,1,$($(lidx)))))),\
ea81a808
JM
48 $(if $(call _hash_map?,$(v)),\
49 $(info $(2)$(var):)\
50 $(foreach vkey,$(filter $(v)_%,$(.VARIABLES)),\
51 $(foreach key,$(word 4,$(subst _, ,$(vkey))),\
52 $(info $(2)$(SPACE)$(SPACE)$(subst $(__equal),=,$(key)): )\
53 $(call __var_print,$($(vkey)),$(2)$(SPACE)$(SPACE)$(SPACE)$(SPACE)))),\
54 $(if $(call _symbol?,$(v)),\
55 $(info $(2)$(var): $($(v)_value)),\
b8ee29b2
JM
56 $(if $(call _keyword?,$(v)),\
57 $(info $(2)$(var): $($(v)_value)),\
ea81a808
JM
58 $(if $(call _number?,$(v)),\
59 $(info $(2)$(var): $(call int_decode,$($(v)_value))),\
60 $(if $(call _nil?,$(v)),\
61 $(info $(2)nil),\
62 $(if $(call _function?,$(v)),\
63 $(if $(word 6,$(value $(v)_value)),\
64 $(info $(2)$(var): $(wordlist 1,5,$(value $(v)_value))...),\
65 $(info $(2)$(var): $(value $(v)_value))),\
b8ee29b2 66 $(info $(2)$(var): ...))))))))))
ea81a808
JM
67
68_visualize_memory = $(foreach var,$(sort $(foreach vv,$(filter $(__obj_magic)_%,$(.VARIABLES)),$(call __var_name,$(vv)))),$(call __var_print,$(__obj_magic)_$(var)))
69
70
71# Errors/Exceptions
31690700 72__ERROR :=
ea81a808
JM
73_error = $(eval __ERROR := $(call _string,$(1)))
74
75
76# Constant atomic values
77__undefined = $(__obj_magic)_undf_0
78__nil = $(__obj_magic)__nil_0
79__true = $(__obj_magic)_true_0
80__false = $(__obj_magic)_fals_0
81
31690700 82
31690700 83# General functions
31690700
JM
84
85# Return the type of the object (or "make" if it's not a object
86_obj_type = $(strip \
87 $(if $(filter $(__obj_magic)_symb_%,$(1)),symbol,\
88 $(if $(filter $(__obj_magic)_list_%,$(1)),list,\
89 $(if $(filter $(__obj_magic)_numb_%,$(1)),number,\
90 $(if $(filter $(__obj_magic)_func_%,$(1)),function,\
b8ee29b2
JM
91 $(if $(filter $(__obj_magic)_strn_%,$(1)),\
92 $(if $(filter $(__keyword)%,$($(1)_value)),keyword,string),\
31690700
JM
93 $(if $(filter $(__obj_magic)__nil_%,$(1)),nil,\
94 $(if $(filter $(__obj_magic)_true_%,$(1)),true,\
95 $(if $(filter $(__obj_magic)_fals_%,$(1)),false,\
96 $(if $(filter $(__obj_magic)_vect_%,$(1)),vector,\
97 $(if $(filter $(__obj_magic)_atom_%,$(1)),atom,\
98 $(if $(filter $(__obj_magic)_hmap_%,$(1)),hash_map,\
99 $(if $(filter $(__obj_magic)_undf_%,$(1)),undefined,\
100 make)))))))))))))
31690700
JM
101
102_clone_obj = $(strip \
103 $(foreach new_hcode,$(call __new_obj_hash_code),\
104 $(foreach new_obj,$(foreach type,$(word 2,$(subst _, ,$(1))),$(__obj_magic)_$(type)_$(new_hcode)),\
105 $(if $(filter $(__obj_magic)_hmap_%,$(1)),\
106 $(foreach v,$(call __get_obj_values,$(1)),\
107 $(eval $(v:$(1)_%=$(new_obj)_%) := $($(v))))\
108 $(eval $(new_obj)_size := $($(1)_size)),\
109 $(if $(filter $(__obj_magic)_func_%,$(1)),\
110 $(eval $(new_obj)_value = $(value $(1)_value)),\
111 $(eval $(new_obj)_value := $(strip $($(1)_value)))))\
112 $(new_obj))))
113
ea81a808
JM
114_equal? = $(strip \
115 $(foreach ot1,$(call _obj_type,$(1)),$(foreach ot2,$(call _obj_type,$(2)),\
116 $(if $(or $(call _EQ,$(ot1),$(ot2)),\
117 $(and $(call _sequential?,$(1)),$(call _sequential?,$(2)))),\
b8ee29b2 118 $(if $(or $(call _string?,$(1)),$(call _symbol?,$(1)),$(call _keyword?,$(1)),$(call _number?,$(1))),\
ea81a808
JM
119 $(call _EQ,$($(1)_value),$($(2)_value)),\
120 $(if $(or $(call _vector?,$(1)),$(call _list?,$(1)),$(call _hash_map?,$(1))),\
121 $(if $(and $(call _EQ,$(call _count,$(1)),$(call _count,$(2))),\
122 $(call _EQ,$(call _count,$(1)),$(words $(call gmsl_pairmap,_equal?,$(call __get_obj_values,$(1)),$(call __get_obj_values,$(2)))))),$(__true),),\
123 $(call _EQ,$(1),$(2))))))))
31690700
JM
124
125_undefined? = $(or $(call _EQ,undefined,$(origin $(1))),$(filter $(__undefined),$($(1))))
31690700
JM
126
127_nil? = $(if $(filter $(__obj_magic)__nil_%,$(1)),$(__true),)
31690700
JM
128
129_true? = $(if $(filter $(__obj_magic)_true_%,$(1)),$(__true),)
31690700
JM
130
131_false? = $(if $(filter $(__obj_magic)_fals_%,$(1)),$(__true),)
31690700
JM
132
133
ea81a808
JM
134# Symbols
135_symbol = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_symb_$(hcode)$(eval $(__obj_magic)_symb_$(hcode)_value := $(1)))
136_symbol? = $(if $(filter $(__obj_magic)_symb_%,$(1)),$(__true),)
31690700 137
31690700 138
b8ee29b2
JM
139# Keywords
140_keyword = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_strn_$(hcode)$(eval $(__obj_magic)_strn_$(hcode)_value := $(__keyword)$(1)))
141_keyword? = $(if $(filter $(__obj_magic)_strn_%,$(1)),$(if $(filter $(__keyword)%,$($(1)_value)),$(__true),))
142
143
ea81a808
JM
144# Numbers
145_pnumber = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_numb_$(hcode)$(eval $(__obj_magic)_numb_$(hcode)_value := $(1)))
146_number = $(call _pnumber,$(call int_encode,$(1)))
31690700 147_number? = $(if $(filter $(__obj_magic)_numb_%,$(1)),$(__true),)
31690700 148
31690700 149
31690700 150# Strings
ea81a808
JM
151__string = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_strn_$(hcode)$(eval $(__obj_magic)_strn_$(hcode)_value := $(1)))
152_string = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_strn_$(hcode)$(eval $(__obj_magic)_strn_$(hcode)_value := $(call str_encode,$(1))))
31690700 153_string? = $(if $(filter $(__obj_magic)_strn_%,$(1)),$(__true),)
31690700 154
ea81a808 155# Functions
31690700
JM
156
157# Return a function object. The first parameter is the
158# function/macro 'source'. Note that any $ must be escaped as $$ to be
159# preserved and become positional arguments for when the
160# function/macro is later invoked.
ea81a808 161_function = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_func_$(hcode)$(eval $(__obj_magic)_func_$(hcode)_value = $(1)))
31690700 162_function? = $(if $(filter $(__obj_magic)_func_%,$(1)),$(__true),)
31690700
JM
163
164# Takes a function name and a list object of arguments and invokes
165# the function with space separated arguments
166_apply = $(call $(1),$($(2)_value))
167
168# Takes a function object and a list object of arguments and invokes
169# the function with space separated arguments
170apply = $(call $(1)_value,$($(2)_value))
171
31690700 172
ea81a808
JM
173# Lists
174_list = $(word 1,$(foreach new_list,$(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_list_$(hcode)),$(new_list) $(eval $(new_list)_value := $1)))
175_list? = $(if $(filter $(__obj_magic)_list_%,$(1)),$(__true),)
31690700 176
31690700 177
ea81a808
JM
178# Vectors (same as lists for now)
179_vector = $(word 1,$(foreach new_vect,$(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_vect_$(hcode)),$(new_vect) $(eval $(new_vect)_value := $1)))
180_vector? = $(if $(filter $(__obj_magic)_vect_%,$(1)),$(__true),)
181
31690700 182
ea81a808
JM
183# Hash maps (associative arrays)
184_hash_map = $(word 1,$(foreach hcode,$(call __new_obj_hash_code),$(foreach new_hmap,$(__obj_magic)_hmap_$(hcode),$(new_hmap) $(eval $(new_hmap)_size := 0) $(if $(1),$(call _assoc_seq!,$(new_hmap),$(1))))))
185_hash_map? = $(if $(filter $(__obj_magic)_hmap_%,$(1)),$(__true),)
31690700
JM
186
187# Set multiple key/values in a map
188_assoc_seq! = $(call _assoc!,$(1),$(call str_decode,$($(word 1,$(2))_value)),$(word 2,$(2)))$(if $(word 3,$(2)),$(call _assoc_seq!,$(1),$(wordlist 3,$(words $(2)),$(2))),)
189
b8ee29b2
JM
190_dissoc_seq! = $(foreach key,$(2),\
191 $(call _dissoc!,$(1),$(call str_decode,$($(key)_value))))
192
31690700 193# set a key/value in the hash map
f4c8a091 194_assoc! = $(foreach k,$(subst =,$(__equal),$(2)),$(if $(call _undefined?,$(1)_$(k)_value),$(eval $(1)_size := $(call int_add,$($(1)_size),1)),)$(eval $(1)_$(k)_value := $(3))$(1))
31690700 195
31690700 196# unset a key in the hash map
f4c8a091 197_dissoc! = $(foreach k,$(subst =,$(__equal),$(2)),$(if $(call _undefined?,$(1)_$(k)_value),,$(eval $(1)_$(k)_value := $(__undefined))$(eval $(1)_size := $(call int_sub,$($(1)_size),1))))$(1)
31690700 198
31690700
JM
199# Hash map and vector functions
200
201# retrieve the value of a plain string key from the hash map, or
202# retrive a vector by plain index
203_get = $(strip \
204 $(if $(call _hash_map?,$(1)),\
205 $(foreach k,$(subst =,$(__equal),$(2)),$(if $(call _undefined?,$(1)_$(k)_value),,$($(1)_$(k)_value))),\
206 $(if $(call _vector?,$(1)),\
f4c8a091 207 $(word $(call int_add,1,$(2)),$($(1)_value)),\
31690700
JM
208 ,)))
209
31690700
JM
210_contains? = $(strip \
211 $(if $(call _hash_map?,$(1)),\
212 $(foreach k,$(subst =,$(__equal),$(2)),$(if $(call _undefined?,$(1)_$(k)_value),,$(__true))),\
213 $(if $(call _vector?,$(1)),\
f4c8a091 214 $(if $(word $(call int_add,1,$(2)),$($(1)_value)),$(__true),),\
31690700 215 ,)))
31690700
JM
216
217
31690700 218# sequence operations
31690700
JM
219
220_sequential? = $(if $(filter $(__obj_magic)_list_% $(__obj_magic)_vect_%,$(1)),$(__true),)
31690700 221
f4c8a091 222_nth = $(word $(call int_add,1,$(2)),$($(1)_value))
31690700 223
31690700
JM
224# conj that mutates a sequence in-place to append the call arguments
225_conj! = $(eval $(1)_value := $(strip $($(1)_value) $2 $3 $4 $5 $6 $7 $8 $9 $(10) $(11) $(12) $(13) $(14) $(15) $(16) $(17) $(18) $(19) $(20)))$(1)
226
227_count = $(strip \
228 $(if $(call _hash_map?,$(1)),\
229 $($(1)_size),\
230 $(words $($(1)_value))))
31690700
JM
231
232# Creates a new vector/list of the everything after but the first
233# element
9528bb14
JM
234srest = $(word 1,$(foreach new_list,$(call _list),\
235 $(new_list) \
236 $(eval $(new_list)_value := $(wordlist 2,$(words $($(1)_value)),$($(1)_value)))))
31690700
JM
237
238# maps a make function over a list object, using mutating _conj!
239_smap = $(word 1,\
240 $(foreach new_list,$(call _list),\
241 $(new_list)\
242 $(foreach v,$(call __get_obj_values,$(2)),\
243 $(call _conj!,$(new_list),$(call $(1),$(v),$(3),$(4))))))
244
245# Same as _smap but returns a vector
246_smap_vec = $(word 1,\
ea81a808 247 $(foreach new_vector,$(call _vector),\
31690700
JM
248 $(new_vector)\
249 $(foreach v,$(call __get_obj_values,$(2)),\
250 $(call _conj!,$(new_vector),$(call $(1),$(v),$(3),$(4))))))
251
31690700 252
ea81a808 253# atoms
31690700 254
ea81a808 255_atom? = $(if $(filter $(__obj_magic)_atom_%,$(1)),$(__true),)
31690700 256
31690700
JM
257
258endif