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