1 #include "ml_map.h"
2 #include "minilang.h"
3 #include "ml_macros.h"
4 #include "ml_iterfns.h"
5 #include <string.h>
6 
7 ML_TYPE(MLMapT, (MLIteratableT), "map",
8 // A map of key-value pairs.
9 // Keys can be of any type supporting hashing and comparison.
10 // Insert order is preserved.
11 );
12 
ml_map_node_deref(ml_map_node_t * Node)13 static ml_value_t *ml_map_node_deref(ml_map_node_t *Node) {
14 	return Node->Value;
15 }
16 
ml_map_node_assign(ml_map_node_t * Node,ml_value_t * Value)17 static ml_value_t *ml_map_node_assign(ml_map_node_t *Node, ml_value_t *Value) {
18 	return (Node->Value = Value);
19 }
20 
ml_map_node_call(ml_state_t * Caller,ml_map_node_t * Node,int Count,ml_value_t ** Args)21 static void ml_map_node_call(ml_state_t *Caller, ml_map_node_t *Node, int Count, ml_value_t **Args) {
22 	return ml_call(Caller, Node->Value, Count, Args);
23 }
24 
25 ML_TYPE(MLMapNodeT, (), "map-node",
26 // A node in a :mini:`map`.
27 // Dereferencing a :mini:`mapnode` returns the corresponding value from the :mini:`map`.
28 // Assigning to a :mini:`mapnode` updates the corresponding value in the :mini:`map`.
29 	.deref = (void *)ml_map_node_deref,
30 	.assign = (void *)ml_map_node_assign,
31 	.call = (void *)ml_map_node_call
32 );
33 
ml_map()34 ml_value_t *ml_map() {
35 	ml_map_t *Map = new(ml_map_t);
36 	Map->Type = MLMapT;
37 	return (ml_value_t *)Map;
38 }
39 
ML_METHOD(MLMapT)40 ML_METHOD(MLMapT) {
41 	return ml_map();
42 }
43 
ML_METHODV(MLMapT,MLNamesT)44 ML_METHODV(MLMapT, MLNamesT) {
45 	ml_value_t *Map = ml_map();
46 	ml_value_t **Values = Args + 1;
47 	ML_NAMES_FOREACH(Args[0], Iter) ml_map_insert(Map, Iter->Value, *Values++);
48 	return Map;
49 }
50 
51 static void map_iterate(ml_iter_state_t *State, ml_value_t *Value);
52 
map_iter_value(ml_iter_state_t * State,ml_value_t * Value)53 static void map_iter_value(ml_iter_state_t *State, ml_value_t *Value) {
54 	Value = ml_deref(Value);
55 	if (ml_is_error(Value)) ML_CONTINUE(State->Base.Caller, Value);
56 	ml_map_insert(State->Values[0], State->Values[1], Value);
57 	State->Base.run = (void *)map_iterate;
58 	return ml_iter_next((ml_state_t *)State, State->Iter);
59 }
60 
map_iter_key(ml_iter_state_t * State,ml_value_t * Value)61 static void map_iter_key(ml_iter_state_t *State, ml_value_t *Value) {
62 	Value = ml_deref(Value);
63 	if (ml_is_error(Value)) ML_CONTINUE(State->Base.Caller, Value);
64 	if (Value == MLNil) Value = ml_integer(ml_map_size(State->Values[0]) + 1);
65 	State->Values[1] = Value;
66 	State->Base.run = (void *)map_iter_value;
67 	return ml_iter_value((ml_state_t *)State, State->Iter);
68 }
69 
map_iterate(ml_iter_state_t * State,ml_value_t * Value)70 static void map_iterate(ml_iter_state_t *State, ml_value_t *Value) {
71 	if (ml_is_error(Value)) ML_CONTINUE(State->Base.Caller, Value);
72 	if (Value == MLNil) ML_CONTINUE(State->Base.Caller, State->Values[0]);
73 	State->Base.run = (void *)map_iter_key;
74 	return ml_iter_key((ml_state_t *)State, State->Iter = Value);
75 }
76 
ML_METHOD(MLIterCount,MLMapT)77 ML_METHOD(MLIterCount, MLMapT) {
78 //!internal
79 	return ml_integer(ml_map_size(Args[0]));
80 }
81 
ML_METHODVX(MLMapT,MLIteratableT)82 ML_METHODVX(MLMapT, MLIteratableT) {
83 //<Iteratable
84 //>map
85 // Returns a map of all the key and value pairs produced by :mini:`Iteratable`.
86 	ml_iter_state_t *State = xnew(ml_iter_state_t, 2, ml_value_t *);
87 	State->Base.Caller = Caller;
88 	State->Base.run = (void *)map_iterate;
89 	State->Base.Context = Caller->Context;
90 	State->Values[0] = ml_map();
91 	return ml_iterate((ml_state_t *)State, ml_chained(Count, Args));
92 }
93 
94 extern ml_value_t *CompareMethod;
95 
ml_map_find_node(ml_map_t * Map,ml_value_t * Key)96 static ml_map_node_t *ml_map_find_node(ml_map_t *Map, ml_value_t *Key) {
97 	ml_map_node_t *Node = Map->Root;
98 	long Hash = ml_typeof(Key)->hash(Key, NULL);
99 	while (Node) {
100 		int Compare;
101 		if (Hash < Node->Hash) {
102 			Compare = -1;
103 		} else if (Hash > Node->Hash) {
104 			Compare = 1;
105 		} else {
106 			ml_value_t *Args[2] = {Key, Node->Key};
107 			ml_value_t *Result = ml_simple_call(CompareMethod, 2, Args);
108 			if (ml_is_error(Result)) return NULL;
109 			Compare = ml_integer_value(Result);
110 		}
111 		if (!Compare) {
112 			return Node;
113 		} else {
114 			Node = Compare < 0 ? Node->Left : Node->Right;
115 		}
116 	}
117 	return NULL;
118 }
119 
ml_map_search(ml_value_t * Map0,ml_value_t * Key)120 ml_value_t *ml_map_search(ml_value_t *Map0, ml_value_t *Key) {
121 	ml_map_node_t *Node = ml_map_find_node((ml_map_t *)Map0, Key);
122 	return Node ? Node->Value : MLNil;
123 }
124 
ml_map_search0(ml_value_t * Map0,ml_value_t * Key)125 ml_value_t *ml_map_search0(ml_value_t *Map0, ml_value_t *Key) {
126 	ml_map_node_t *Node = ml_map_find_node((ml_map_t *)Map0, Key);
127 	return Node ? Node->Value : NULL;
128 }
129 
ml_map_balance(ml_map_node_t * Node)130 static int ml_map_balance(ml_map_node_t *Node) {
131 	int Delta = 0;
132 	if (Node->Left) Delta = Node->Left->Depth;
133 	if (Node->Right) Delta -= Node->Right->Depth;
134 	return Delta;
135 }
136 
ml_map_update_depth(ml_map_node_t * Node)137 static void ml_map_update_depth(ml_map_node_t *Node) {
138 	int Depth = 0;
139 	if (Node->Left) Depth = Node->Left->Depth;
140 	if (Node->Right && Depth < Node->Right->Depth) Depth = Node->Right->Depth;
141 	Node->Depth = Depth + 1;
142 }
143 
ml_map_rotate_left(ml_map_node_t ** Slot)144 static void ml_map_rotate_left(ml_map_node_t **Slot) {
145 	ml_map_node_t *Ch = Slot[0]->Right;
146 	Slot[0]->Right = Slot[0]->Right->Left;
147 	Ch->Left = Slot[0];
148 	ml_map_update_depth(Slot[0]);
149 	Slot[0] = Ch;
150 	ml_map_update_depth(Slot[0]);
151 }
152 
ml_map_rotate_right(ml_map_node_t ** Slot)153 static void ml_map_rotate_right(ml_map_node_t **Slot) {
154 	ml_map_node_t *Ch = Slot[0]->Left;
155 	Slot[0]->Left = Slot[0]->Left->Right;
156 	Ch->Right = Slot[0];
157 	ml_map_update_depth(Slot[0]);
158 	Slot[0] = Ch;
159 	ml_map_update_depth(Slot[0]);
160 }
161 
ml_map_rebalance(ml_map_node_t ** Slot)162 static void ml_map_rebalance(ml_map_node_t **Slot) {
163 	int Delta = ml_map_balance(Slot[0]);
164 	if (Delta == 2) {
165 		if (ml_map_balance(Slot[0]->Left) < 0) ml_map_rotate_left(&Slot[0]->Left);
166 		ml_map_rotate_right(Slot);
167 	} else if (Delta == -2) {
168 		if (ml_map_balance(Slot[0]->Right) > 0) ml_map_rotate_right(&Slot[0]->Right);
169 		ml_map_rotate_left(Slot);
170 	}
171 }
172 
ml_map_node(ml_map_t * Map,ml_map_node_t ** Slot,long Hash,ml_value_t * Key)173 static ml_map_node_t *ml_map_node(ml_map_t *Map, ml_map_node_t **Slot, long Hash, ml_value_t *Key) {
174 	if (!Slot[0]) {
175 		++Map->Size;
176 		ml_map_node_t *Node = Slot[0] = new(ml_map_node_t);
177 		Node->Type = MLMapNodeT;
178 		ml_map_node_t *Prev = Map->Tail;
179 		if (Prev) {
180 			Prev->Next = Node;
181 			Node->Prev = Prev;
182 		} else {
183 			Map->Head = Node;
184 		}
185 		Map->Tail = Node;
186 		Node->Depth = 1;
187 		Node->Hash = Hash;
188 		Node->Key = Key;
189 		return Node;
190 	}
191 	int Compare;
192 	if (Hash < Slot[0]->Hash) {
193 		Compare = -1;
194 	} else if (Hash > Slot[0]->Hash) {
195 		Compare = 1;
196 	} else {
197 		ml_value_t *Args[2] = {Key, Slot[0]->Key};
198 		ml_value_t *Result = ml_simple_call(CompareMethod, 2, Args);
199 		Compare = ml_integer_value(Result);
200 	}
201 	if (!Compare) {
202 		return Slot[0];
203 	} else {
204 		ml_map_node_t *Node = ml_map_node(Map, Compare < 0 ? &Slot[0]->Left : &Slot[0]->Right, Hash, Key);
205 		ml_map_rebalance(Slot);
206 		ml_map_update_depth(Slot[0]);
207 		return Node;
208 	}
209 }
210 
ml_map_slot(ml_value_t * Map0,ml_value_t * Key)211 ml_map_node_t *ml_map_slot(ml_value_t *Map0, ml_value_t *Key) {
212 	ml_map_t *Map = (ml_map_t *)Map0;
213 	return ml_map_node(Map, &Map->Root, ml_typeof(Key)->hash(Key, NULL), Key);
214 }
215 
ml_map_insert(ml_value_t * Map0,ml_value_t * Key,ml_value_t * Value)216 ml_value_t *ml_map_insert(ml_value_t *Map0, ml_value_t *Key, ml_value_t *Value) {
217 	ml_map_t *Map = (ml_map_t *)Map0;
218 	ml_map_node_t *Node = ml_map_node(Map, &Map->Root, ml_typeof(Key)->hash(Key, NULL), Key);
219 	ml_value_t *Old = Node->Value ?: MLNil;
220 	Node->Value = Value;
221 #ifdef ML_GENERICS
222 	if (Map->Size == 1 && Map->Type == MLMapT) {
223 		ml_type_t *Types[] = {MLMapT, ml_typeof(Key), ml_typeof(Value)};
224 		Map->Type = ml_generic_type(3, Types);
225 	} else if (Map->Type->Type == MLGenericTypeT) {
226 		ml_type_t *KeyType = ml_generic_type_args(Map->Type)[1];
227 		ml_type_t *ValueType = ml_generic_type_args(Map->Type)[2];
228 		if (KeyType != ml_typeof(Key) || ValueType != ml_typeof(Value)) {
229 			ml_type_t *KeyType2 = ml_type_max(KeyType, ml_typeof(Key));
230 			ml_type_t *ValueType2 = ml_type_max(ValueType, ml_typeof(Value));
231 			if (KeyType != KeyType2 || ValueType != ValueType2) {
232 				ml_type_t *Types[] = {MLMapT, KeyType2, ValueType2};
233 				Map->Type = ml_generic_type(3, Types);
234 			}
235 		}
236 	}
237 #endif
238 	return Old;
239 }
240 
ml_map_remove_depth_helper(ml_map_node_t * Node)241 static void ml_map_remove_depth_helper(ml_map_node_t *Node) {
242 	if (Node) {
243 		ml_map_remove_depth_helper(Node->Right);
244 		ml_map_update_depth(Node);
245 	}
246 }
247 
ml_map_remove_internal(ml_map_t * Map,ml_map_node_t ** Slot,long Hash,ml_value_t * Key)248 static ml_value_t *ml_map_remove_internal(ml_map_t *Map, ml_map_node_t **Slot, long Hash, ml_value_t *Key) {
249 	if (!Slot[0]) return MLNil;
250 	ml_map_node_t *Node = Slot[0];
251 	int Compare;
252 	if (Hash < Node->Hash) {
253 		Compare = -1;
254 	} else if (Hash > Node->Hash) {
255 		Compare = 1;
256 	} else {
257 		ml_value_t *Args[2] = {Key, Node->Key};
258 		ml_value_t *Result = ml_simple_call(CompareMethod, 2, Args);
259 		Compare = ml_integer_value(Result);
260 	}
261 	ml_value_t *Removed = MLNil;
262 	if (!Compare) {
263 		--Map->Size;
264 		Removed = Node->Value;
265 		if (Node->Prev) Node->Prev->Next = Node->Next; else Map->Head = Node->Next;
266 		if (Node->Next) Node->Next->Prev = Node->Prev; else Map->Tail = Node->Prev;
267 		if (Node->Left && Node->Right) {
268 			ml_map_node_t **Y = &Node->Left;
269 			while (Y[0]->Right) Y = &Y[0]->Right;
270 			ml_map_node_t *Node2 = Y[0];
271 			Y[0] = Node2->Left;
272 			Node2->Left = Node->Left;
273 			Node2->Right = Node->Right;
274 			Slot[0] = Node2;
275 			ml_map_remove_depth_helper(Node2->Left);
276 		} else if (Node->Left) {
277 			Slot[0] = Node->Left;
278 		} else if (Node->Right) {
279 			Slot[0] = Node->Right;
280 		} else {
281 			Slot[0] = 0;
282 		}
283 	} else {
284 		Removed = ml_map_remove_internal(Map, Compare < 0 ? &Node->Left : &Node->Right, Hash, Key);
285 	}
286 	if (Slot[0]) {
287 		ml_map_update_depth(Slot[0]);
288 		ml_map_rebalance(Slot);
289 	}
290 	return Removed;
291 }
292 
ml_map_delete(ml_value_t * Map0,ml_value_t * Key)293 ml_value_t *ml_map_delete(ml_value_t *Map0, ml_value_t *Key) {
294 	ml_map_t *Map = (ml_map_t *)Map0;
295 	return ml_map_remove_internal(Map, &Map->Root, ml_typeof(Key)->hash(Key, NULL), Key);
296 }
297 
ml_map_foreach(ml_value_t * Value,void * Data,int (* callback)(ml_value_t *,ml_value_t *,void *))298 int ml_map_foreach(ml_value_t *Value, void *Data, int (*callback)(ml_value_t *, ml_value_t *, void *)) {
299 	ml_map_t *Map = (ml_map_t *)Value;
300 	for (ml_map_node_t *Node = Map->Head; Node; Node = Node->Next) {
301 		if (callback(Node->Key, Node->Value, Data)) return 1;
302 	}
303 	return 0;
304 }
305 
306 ML_METHOD("size", MLMapT) {
307 //<Map
308 //>integer
309 // Returns the number of entries in :mini:`Map`.
310 	ml_map_t *Map = (ml_map_t *)Args[0];
311 	return ml_integer(Map->Size);
312 }
313 
314 ML_METHOD("count", MLMapT) {
315 //<Map
316 //>integer
317 // Returns the number of entries in :mini:`Map`.
318 	ml_map_t *Map = (ml_map_t *)Args[0];
319 	return ml_integer(Map->Size);
320 }
321 
ml_map_index_deref(ml_map_node_t * Index)322 static ml_value_t *ml_map_index_deref(ml_map_node_t *Index) {
323 	return MLNil;
324 }
325 
326 
ml_map_insert_node(ml_map_t * Map,ml_map_node_t ** Slot,long Hash,ml_map_node_t * Index)327 static ml_map_node_t *ml_map_insert_node(ml_map_t *Map, ml_map_node_t **Slot, long Hash, ml_map_node_t *Index) {
328 	if (!Slot[0]) {
329 		++Map->Size;
330 		ml_map_node_t *Node = Slot[0] = Index;
331 		Node->Type = MLMapNodeT;
332 		ml_map_node_t *Prev = Map->Tail;
333 		if (Prev) {
334 			Prev->Next = Node;
335 			Node->Prev = Prev;
336 		} else {
337 			Map->Head = Node;
338 		}
339 		Map->Tail = Node;
340 		Node->Depth = 1;
341 		Node->Hash = Hash;
342 		return Node;
343 	}
344 	int Compare;
345 	if (Hash < Slot[0]->Hash) {
346 		Compare = -1;
347 	} else if (Hash > Slot[0]->Hash) {
348 		Compare = 1;
349 	} else {
350 		ml_value_t *Args[2] = {Index->Key, Slot[0]->Key};
351 		ml_value_t *Result = ml_simple_call(CompareMethod, 2, Args);
352 		Compare = ml_integer_value(Result);
353 	}
354 	if (!Compare) {
355 		return Slot[0];
356 	} else {
357 		ml_map_node_t *Node = ml_map_insert_node(Map, Compare < 0 ? &Slot[0]->Left : &Slot[0]->Right, Hash, Index);
358 		ml_map_rebalance(Slot);
359 		ml_map_update_depth(Slot[0]);
360 		return Node;
361 	}
362 }
363 
ml_map_index_assign(ml_map_node_t * Index,ml_value_t * Value)364 static ml_value_t *ml_map_index_assign(ml_map_node_t *Index, ml_value_t *Value) {
365 	ml_map_t *Map = (ml_map_t *)Index->Value;
366 	ml_map_node_t *Node = ml_map_insert_node(Map, &Map->Root, ml_typeof(Index->Key)->hash(Index->Key, NULL), Index);
367 	return Node->Value = Value;
368 }
369 
ml_map_index_call(ml_state_t * Caller,ml_map_node_t * Index,int Count,ml_value_t ** Args)370 static void ml_map_index_call(ml_state_t *Caller, ml_map_node_t *Index, int Count, ml_value_t **Args) {
371 	return ml_call(Caller, MLNil, Count, Args);
372 }
373 
374 ML_TYPE(MLMapIndexT, (), "map-index",
375 //!internal
376 	.deref = (void *)ml_map_index_deref,
377 	.assign = (void *)ml_map_index_assign,
378 	.call = (void *)ml_map_index_call
379 );
380 
381 ML_METHOD("[]", MLMapT, MLAnyT) {
382 //<Map
383 //<Key
384 //>mapnode
385 // Returns the node corresponding to :mini:`Key` in :mini:`Map`. If :mini:`Key` is not in :mini:`Map` then a new floating node is returned with value :mini:`nil`. This node will insert :mini:`Key` into :mini:`Map` if assigned.
386 	ml_map_node_t *Node = ml_map_find_node((ml_map_t *)Args[0], Args[1]);
387 	if (!Node) {
388 		Node = new(ml_map_node_t);
389 		Node->Type = MLMapIndexT;
390 		Node->Value = Args[0];
391 		Node->Key = Args[1];
392 	}
393 	return (ml_value_t *)Node;
394 }
395 
396 typedef struct {
397 	ml_state_t Base;
398 	ml_value_t *Key;
399 	ml_map_node_t *Node;
400 } ml_ref_state_t;
401 
ml_node_state_run(ml_ref_state_t * State,ml_value_t * Value)402 static void ml_node_state_run(ml_ref_state_t *State, ml_value_t *Value) {
403 	if (ml_is_error(Value)) {
404 		ML_CONTINUE(State->Base.Caller, Value);
405 	} else {
406 		State->Node->Value = Value;
407 		ML_CONTINUE(State->Base.Caller, State->Node);
408 	}
409 }
410 
411 ML_METHODX("[]", MLMapT, MLAnyT, MLFunctionT) {
412 //<Map
413 //<Key
414 //<Default
415 //>mapnode
416 // Returns the node corresponding to :mini:`Key` in :mini:`Map`. If :mini:`Key` is not in :mini:`Map` then :mini:`Default(Key)` is called and the result inserted into :mini:`Map`.
417 	ml_map_t *Map = (ml_map_t *)Args[0];
418 	ml_value_t *Key = Args[1];
419 	ml_map_node_t *Node = ml_map_node(Map, &Map->Root, ml_typeof(Key)->hash(Key, NULL), Key);
420 	if (!Node->Value) {
421 		Node->Value = MLNil;
422 		ml_ref_state_t *State = new(ml_ref_state_t);
423 		State->Base.Caller = Caller;
424 		State->Base.Context = Caller->Context;
425 		State->Base.run = (void *)ml_node_state_run;
426 		State->Key = Key;
427 		State->Node = Node;
428 		ml_value_t *Function = Args[2];
429 		return ml_call(State, Function, 1, &State->Key);
430 	} else {
431 		ML_RETURN(Node);
432 	}
433 }
434 
435 ML_METHOD("::", MLMapT, MLStringT) {
436 //<Map
437 //<Key
438 //>mapnode
439 // Same as :mini:`Map[Key]`. This method allows maps to be used as modules.
440 	ml_map_node_t *Node = ml_map_find_node((ml_map_t *)Args[0], Args[1]);
441 	if (!Node) {
442 		Node = new(ml_map_node_t);
443 		Node->Type = MLMapIndexT;
444 		Node->Value = Args[0];
445 		Node->Key = Args[1];
446 	}
447 	return (ml_value_t *)Node;
448 }
449 
450 ML_METHOD("insert", MLMapT, MLAnyT, MLAnyT) {
451 //<Map
452 //<Key
453 //<Value
454 //>any | nil
455 // Inserts :mini:`Key` into :mini:`Map` with corresponding value :mini:`Value`.
456 // Returns the previous value associated with :mini:`Key` if any, otherwise :mini:`nil`.
457 	ml_value_t *Map = (ml_value_t *)Args[0];
458 	ml_value_t *Key = Args[1];
459 	ml_value_t *Value = Args[2];
460 	return ml_map_insert(Map, Key, Value);
461 }
462 
463 ML_METHOD("delete", MLMapT, MLAnyT) {
464 //<Map
465 //<Key
466 //>any | nil
467 // Removes :mini:`Key` from :mini:`Map` and returns the corresponding value if any, otherwise :mini:`nil`.
468 	ml_value_t *Map = (ml_value_t *)Args[0];
469 	ml_value_t *Key = Args[1];
470 	return ml_map_delete(Map, Key);
471 }
472 
ml_map_fn(void * Data,int Count,ml_value_t ** Args)473 ml_value_t *ml_map_fn(void *Data, int Count, ml_value_t **Args) {
474 	ml_map_t *Map = new(ml_map_t);
475 	Map->Type = MLMapT;
476 	for (int I = 0; I < Count; I += 2) ml_map_insert((ml_value_t *)Map, Args[I], Args[I + 1]);
477 	return (ml_value_t *)Map;
478 }
479 
480 ML_METHOD("missing", MLMapT, MLAnyT) {
481 //<Map
482 //<Key
483 //>any | nil
484 // Inserts :mini:`Key` into :mini:`Map` with corresponding value :mini:`Value`.
485 // Returns the previous value associated with :mini:`Key` if any, otherwise :mini:`nil`.
486 	ml_map_t *Map = (ml_map_t *)Args[0];
487 	ml_value_t *Key = Args[1];
488 	ml_map_node_t *Node = ml_map_node(Map, &Map->Root, ml_typeof(Key)->hash(Key, NULL), Key);
489 	if (!Node->Value) return Node->Value = MLSome;
490 	return MLNil;
491 }
492 
493 ML_METHOD("append", MLStringBufferT, MLMapT) {
494 	ml_stringbuffer_t *Buffer = (ml_stringbuffer_t *)Args[0];
495 	ml_stringbuffer_add(Buffer, "{", 1);
496 	ml_map_t *Map = (ml_map_t *)Args[1];
497 	ml_map_node_t *Node = Map->Head;
498 	if (Node) {
499 		ml_stringbuffer_append(Buffer, Node->Key);
500 		if (Node->Value != MLSome) {
501 			ml_stringbuffer_add(Buffer, " is ", 4);
502 			ml_stringbuffer_append(Buffer, Node->Value);
503 		}
504 		while ((Node = Node->Next)) {
505 			ml_stringbuffer_add(Buffer, ", ", 2);
506 			ml_stringbuffer_append(Buffer, Node->Key);
507 			if (Node->Value != MLSome) {
508 				ml_stringbuffer_add(Buffer, " is ", 4);
509 				ml_stringbuffer_append(Buffer, Node->Value);
510 			}
511 		}
512 	}
513 	ml_stringbuffer_add(Buffer, "}", 1);
514 	return (ml_value_t *)Buffer;
515 }
516 
ML_TYPED_FN(ml_iter_next,MLMapNodeT,ml_state_t * Caller,ml_map_node_t * Node)517 static void ML_TYPED_FN(ml_iter_next, MLMapNodeT, ml_state_t *Caller, ml_map_node_t *Node) {
518 	ML_RETURN((ml_value_t *)Node->Next ?: MLNil);
519 }
520 
ML_TYPED_FN(ml_iter_key,MLMapNodeT,ml_state_t * Caller,ml_map_node_t * Node)521 static void ML_TYPED_FN(ml_iter_key, MLMapNodeT, ml_state_t *Caller, ml_map_node_t *Node) {
522 	ML_RETURN(Node->Key);
523 }
524 
ML_TYPED_FN(ml_iter_value,MLMapNodeT,ml_state_t * Caller,ml_map_node_t * Node)525 static void ML_TYPED_FN(ml_iter_value, MLMapNodeT, ml_state_t *Caller, ml_map_node_t *Node) {
526 	ML_RETURN(Node);
527 }
528 
ML_TYPED_FN(ml_iterate,MLMapT,ml_state_t * Caller,ml_map_t * Map)529 static void ML_TYPED_FN(ml_iterate, MLMapT, ml_state_t *Caller, ml_map_t *Map) {
530 	ML_RETURN((ml_value_t *)Map->Head ?: MLNil);
531 }
532 
533 ML_METHOD("+", MLMapT, MLMapT) {
534 //<Map/1
535 //<Map/2
536 //>map
537 // Returns a new map combining the entries of :mini:`Map/1` and :mini:`Map/2`.
538 // If the same key is in both :mini:`Map/1` and :mini:`Map/2` then the corresponding value from :mini:`Map/2` is chosen.
539 	ml_value_t *Map = ml_map();
540 	ML_MAP_FOREACH(Args[0], Node) ml_map_insert(Map, Node->Key, Node->Value);
541 	ML_MAP_FOREACH(Args[1], Node) ml_map_insert(Map, Node->Key, Node->Value);
542 	return Map;
543 }
544 
545 ML_METHOD("*", MLMapT, MLMapT) {
546 //<Map/1
547 //<Map/2
548 //>map
549 // Returns a new map containing the entries of :mini:`Map/1` which are also in :mini:`Map/2`. The values are chosen from :mini:`Map/1`.
550 	ml_value_t *Map = ml_map();
ML_MAP_FOREACH(Args[0],Node)551 	ML_MAP_FOREACH(Args[0], Node) {
552 		if (ml_map_search0(Args[1], Node->Key)) ml_map_insert(Map, Node->Key, Node->Value);
553 	}
554 	return Map;
555 }
556 
557 ML_METHOD("/", MLMapT, MLMapT) {
558 //<Map/1
559 //<Map/2
560 //>map
561 // Returns a new map containing the entries of :mini:`Map/1` which are not in :mini:`Map/2`.
562 	ml_value_t *Map = ml_map();
ML_MAP_FOREACH(Args[0],Node)563 	ML_MAP_FOREACH(Args[0], Node) {
564 		if (!ml_map_search0(Args[1], Node->Key)) ml_map_insert(Map, Node->Key, Node->Value);
565 	}
566 	return Map;
567 }
568 
569 typedef struct ml_map_stringer_t {
570 	const char *Seperator, *Equals;
571 	ml_stringbuffer_t Buffer[1];
572 	int SeperatorLength, EqualsLength, First;
573 	ml_value_t *Error;
574 } ml_map_stringer_t;
575 
ml_map_stringer(ml_value_t * Key,ml_value_t * Value,ml_map_stringer_t * Stringer)576 static int ml_map_stringer(ml_value_t *Key, ml_value_t *Value, ml_map_stringer_t *Stringer) {
577 	if (!Stringer->First) {
578 		ml_stringbuffer_add(Stringer->Buffer, Stringer->Seperator, Stringer->SeperatorLength);
579 	} else {
580 		Stringer->First = 0;
581 	}
582 	Stringer->Error = ml_stringbuffer_append(Stringer->Buffer, Key);
583 	if (ml_is_error(Stringer->Error)) return 1;
584 	ml_stringbuffer_add(Stringer->Buffer, Stringer->Equals, Stringer->EqualsLength);
585 	Stringer->Error = ml_stringbuffer_append(Stringer->Buffer, Value);
586 	if (ml_is_error(Stringer->Error)) return 1;
587 	return 0;
588 }
589 
ML_METHOD(MLStringT,MLMapT)590 ML_METHOD(MLStringT, MLMapT) {
591 //<Map
592 //>string
593 // Returns a string containing the entries of :mini:`Map` surrounded by :mini:`"{"`, :mini:`"}"` with :mini:`" is "` between keys and values and :mini:`", "` between entries.
594 	ml_map_stringer_t Stringer[1] = {{
595 		", ", " is ",
596 		{ML_STRINGBUFFER_INIT},
597 		2, 4,
598 		1
599 	}};
600 	ml_stringbuffer_add(Stringer->Buffer, "{", 1);
601 	if (ml_map_foreach(Args[0], Stringer, (void *)ml_map_stringer)) {
602 		return Stringer->Error;
603 	}
604 	ml_stringbuffer_add(Stringer->Buffer, "}", 1);
605 	return ml_string(ml_stringbuffer_get(Stringer->Buffer), -1);
606 }
607 
ML_METHOD(MLStringT,MLMapT,MLStringT,MLStringT)608 ML_METHOD(MLStringT, MLMapT, MLStringT, MLStringT) {
609 //<Map
610 //<Seperator
611 //<Connector
612 //>string
613 // Returns a string containing the entries of :mini:`Map` with :mini:`Connector` between keys and values and :mini:`Seperator` between entries.
614 	ml_map_stringer_t Stringer[1] = {{
615 		ml_string_value(Args[1]), ml_string_value(Args[2]),
616 		{ML_STRINGBUFFER_INIT},
617 		ml_string_length(Args[1]), ml_string_length(Args[2]),
618 		1
619 	}};
620 	if (ml_map_foreach(Args[0], Stringer, (void *)ml_map_stringer)) return Stringer->Error;
621 	return ml_stringbuffer_value(Stringer->Buffer);
622 }
623 
624 typedef struct {
625 	ml_state_t Base;
626 	ml_map_t *Map;
627 	ml_value_t *Compare;
628 	ml_value_t *Args[4];
629 	ml_map_node_t *Head, *Tail;
630 	ml_map_node_t *P, *Q;
631 	int Count, Size;
632 	int InSize, NMerges;
633 	int PSize, QSize;
634 } ml_map_sort_state_t;
635 
ml_map_sort_state_run(ml_map_sort_state_t * State,ml_value_t * Result)636 static void ml_map_sort_state_run(ml_map_sort_state_t *State, ml_value_t *Result) {
637 	if (Result) goto resume;
638 	for (;;) {
639 		State->P = State->Head;
640 		State->Tail = State->Head = NULL;
641 		State->NMerges = 0;
642 		while (State->P) {
643 			State->NMerges++;
644 			State->Q = State->P;
645 			State->PSize = 0;
646 			for (int I = 0; I < State->InSize; I++) {
647 				State->PSize++;
648 				State->Q = State->Q->Next;
649 				if (!State->Q) break;
650 			}
651 			State->QSize = State->InSize;
652 			while (State->PSize > 0 || (State->QSize > 0 && State->Q)) {
653 				ml_map_node_t *E;
654 				if (State->PSize == 0) {
655 					E = State->Q; State->Q = State->Q->Next; State->QSize--;
656 				} else if (State->QSize == 0 || !State->Q) {
657 					E = State->P; State->P = State->P->Next; State->PSize--;
658 				} else {
659 					State->Args[0] = State->P->Key;
660 					State->Args[1] = State->Q->Key;
661 					State->Args[2] = State->P->Value;
662 					State->Args[3] = State->Q->Value;
663 					return ml_call((ml_state_t *)State, State->Compare, State->Count, State->Args);
664 				resume:
665 					if (ml_is_error(Result)) {
666 						ml_map_node_t *Node = State->P, *Next;
667 						if (State->Tail) {
668 							State->Tail->Next = Node;
669 						} else {
670 							State->Head = Node;
671 						}
672 						Node->Prev = State->Tail;
673 						for (int Size = State->PSize; --Size > 0;) {
674 							Next = Node->Next; Next->Prev = Node; Node = Next;
675 						}
676 						Next = State->Q;
677 						Node->Next = Next;
678 						Next->Prev = Node;
679 						Node = Next;
680 						while (Node->Next) {
681 							Next = Node->Next; Next->Prev = Node; Node = Next;
682 						}
683 						Node->Next = NULL;
684 						State->Tail = Node;
685 						goto finished;
686 					} else if (Result == MLNil) {
687 						E = State->Q; State->Q = State->Q->Next; State->QSize--;
688 					} else {
689 						E = State->P; State->P = State->P->Next; State->PSize--;
690 					}
691 				}
692 				if (State->Tail) {
693 					State->Tail->Next = E;
694 				} else {
695 					State->Head = E;
696 				}
697 				E->Prev = State->Tail;
698 				State->Tail = E;
699 			}
700 			State->P = State->Q;
701 		}
702 		State->Tail->Next = 0;
703 		if (State->NMerges <= 1) {
704 			Result = (ml_value_t *)State->Map;
705 			goto finished;
706 		}
707 		State->InSize *= 2;
708 	}
709 finished:
710 	State->Map->Head = State->Head;
711 	State->Map->Tail = State->Tail;
712 	State->Map->Size = State->Size;
713 	ML_CONTINUE(State->Base.Caller, Result);
714 }
715 
716 extern ml_value_t *LessMethod;
717 
718 ML_METHODX("sort", MLMapT) {
719 //<Map
720 //>Map
721 	if (!ml_map_size(Args[0])) ML_RETURN(Args[0]);
722 	ml_map_sort_state_t *State = new(ml_map_sort_state_t);
723 	State->Base.Caller = Caller;
724 	State->Base.Context = Caller->Context;
725 	State->Base.run = (ml_state_fn)ml_map_sort_state_run;
726 	ml_map_t *Map = (ml_map_t *)Args[0];
727 	State->Map = Map;
728 	State->Count = 2;
729 	State->Compare = LessMethod;
730 	State->Head = State->Map->Head;
731 	State->Size = Map->Size;
732 	State->InSize = 1;
733 	// TODO: Improve ml_map_sort_state_run so that List is still valid during sort
734 	Map->Head = Map->Tail = NULL;
735 	Map->Size = 0;
736 	return ml_map_sort_state_run(State, NULL);
737 }
738 
739 ML_METHODX("sort", MLMapT, MLFunctionT) {
740 //<Map
741 //<Compare
742 //>Map
743 	if (!ml_map_size(Args[0])) ML_RETURN(Args[0]);
744 	ml_map_sort_state_t *State = new(ml_map_sort_state_t);
745 	State->Base.Caller = Caller;
746 	State->Base.Context = Caller->Context;
747 	State->Base.run = (ml_state_fn)ml_map_sort_state_run;
748 	ml_map_t *Map = (ml_map_t *)Args[0];
749 	State->Map = Map;
750 	State->Count = 2;
751 	State->Compare = Args[1];
752 	State->Head = State->Map->Head;
753 	State->Size = Map->Size;
754 	State->InSize = 1;
755 	// TODO: Improve ml_map_sort_state_run so that List is still valid during sort
756 	Map->Head = Map->Tail = NULL;
757 	Map->Size = 0;
758 	return ml_map_sort_state_run(State, NULL);
759 }
760 
761 ML_METHODX("sort2", MLMapT, MLFunctionT) {
762 //<Map
763 //<Compare
764 //>Map
765 	if (!ml_map_size(Args[0])) ML_RETURN(Args[0]);
766 	ml_map_sort_state_t *State = new(ml_map_sort_state_t);
767 	State->Base.Caller = Caller;
768 	State->Base.Context = Caller->Context;
769 	State->Base.run = (ml_state_fn)ml_map_sort_state_run;
770 	ml_map_t *Map = (ml_map_t *)Args[0];
771 	State->Map = Map;
772 	State->Count = 4;
773 	State->Compare = Args[1];
774 	State->Head = State->Map->Head;
775 	State->Size = Map->Size;
776 	State->InSize = 1;
777 	// TODO: Improve ml_map_sort_state_run so that List is still valid during sort
778 	Map->Head = Map->Tail = NULL;
779 	Map->Size = 0;
780 	return ml_map_sort_state_run(State, NULL);
781 }
782 
ml_map_init()783 void ml_map_init() {
784 #include "ml_map_init.c"
785 #ifdef ML_GENERICS
786 	ml_type_add_rule(MLMapT, MLIteratableT, ML_TYPE_ARG(1), ML_TYPE_ARG(2), NULL);
787 #endif
788 }
789