1 #include "ml_list.h"
2 #include "minilang.h"
3 #include "ml_macros.h"
4 #include "ml_iterfns.h"
5 #include <string.h>
6 
ml_list_index(ml_list_t * List,int Index)7 static ml_list_node_t *ml_list_index(ml_list_t *List, int Index) {
8 	int Length = List->Length;
9 	if (Index <= 0) Index += Length + 1;
10 	if (Index > Length) return NULL;
11 	if (Index == Length) return List->Tail;
12 	if (Index < 1) return NULL;
13 	if (Index == 1) return List->Head;
14 	int CachedIndex = List->CachedIndex;
15 	if (CachedIndex < 0) {
16 		CachedIndex = 0;
17 		List->CachedNode = List->Head;
18 	} else if (CachedIndex > Length) {
19 
20 	}
21 	switch (Index - CachedIndex) {
22 	case -1: {
23 		List->CachedIndex = Index;
24 		return (List->CachedNode = List->CachedNode->Prev);
25 	}
26 	case 0: return List->CachedNode;
27 	case 1: {
28 		List->CachedIndex = Index;
29 		return (List->CachedNode = List->CachedNode->Next);
30 	}
31 	}
32 	List->CachedIndex = Index;
33 	ml_list_node_t *Node;
34 	if (2 * Index < CachedIndex) {
35 		Node = List->Head;
36 		int Steps = Index - 1;
37 		do Node = Node->Next; while (--Steps);
38 	} else if (Index < CachedIndex) {
39 		Node = List->CachedNode;
40 		int Steps = CachedIndex - Index;
41 		do Node = Node->Prev; while (--Steps);
42 	} else if (2 * Index < CachedIndex + Length) {
43 		Node = List->CachedNode;
44 		int Steps = Index - CachedIndex;
45 		do Node = Node->Next; while (--Steps);
46 	} else {
47 		Node = List->Tail;
48 		int Steps = Length - Index;
49 		do Node = Node->Prev; while (--Steps);
50 	}
51 	return (List->CachedNode = Node);
52 }
53 
54 ML_TYPE(MLListT, (MLIteratableT), "list",
55 // A list of elements.
56 );
57 
ml_list_node_deref(ml_list_node_t * Node)58 static ml_value_t *ml_list_node_deref(ml_list_node_t *Node) {
59 	return Node->Value;
60 }
61 
ml_list_node_assign(ml_list_node_t * Node,ml_value_t * Value)62 static ml_value_t *ml_list_node_assign(ml_list_node_t *Node, ml_value_t *Value) {
63 	return (Node->Value = Value);
64 }
65 
ml_list_node_call(ml_state_t * Caller,ml_list_node_t * Node,int Count,ml_value_t ** Args)66 static void ml_list_node_call(ml_state_t *Caller, ml_list_node_t *Node, int Count, ml_value_t **Args) {
67 	return ml_call(Caller, Node->Value, Count, Args);
68 }
69 
70 ML_TYPE(MLListNodeT, (), "list-node",
71 // A node in a :mini:`list`.
72 // Dereferencing a :mini:`listnode` returns the corresponding value from the :mini:`list`.
73 // Assigning to a :mini:`listnode` updates the corresponding value in the :mini:`list`.
74 	.deref = (void *)ml_list_node_deref,
75 	.assign = (void *)ml_list_node_assign,
76 	.call = (void *)ml_list_node_call
77 );
78 
ML_TYPED_FN(ml_iter_next,MLListNodeT,ml_state_t * Caller,ml_list_node_t * Node)79 static void ML_TYPED_FN(ml_iter_next, MLListNodeT, ml_state_t *Caller, ml_list_node_t *Node) {
80 	ML_RETURN((ml_value_t *)Node->Next ?: MLNil);
81 }
82 
ML_TYPED_FN(ml_iter_key,MLListNodeT,ml_state_t * Caller,ml_list_node_t * Node)83 static void ML_TYPED_FN(ml_iter_key, MLListNodeT, ml_state_t *Caller, ml_list_node_t *Node) {
84 	ML_RETURN(ml_integer(Node->Index));
85 }
86 
ML_TYPED_FN(ml_iter_value,MLListNodeT,ml_state_t * Caller,ml_list_node_t * Node)87 static void ML_TYPED_FN(ml_iter_value, MLListNodeT, ml_state_t *Caller, ml_list_node_t *Node) {
88 	ML_RETURN(Node);
89 }
90 
ml_list()91 ml_value_t *ml_list() {
92 	ml_list_t *List = new(ml_list_t);
93 	List->Type = MLListT;
94 	List->Head = List->Tail = NULL;
95 	List->Length = 0;
96 	return (ml_value_t *)List;
97 }
98 
ML_METHOD(MLListT)99 ML_METHOD(MLListT) {
100 	return ml_list();
101 }
102 
ML_METHOD(MLListT,MLTupleT)103 ML_METHOD(MLListT, MLTupleT) {
104 	ml_value_t *List = ml_list();
105 	ml_tuple_t *Tuple = (ml_tuple_t *)Args[0];
106 	for (int I = 0; I < Tuple->Size; ++I) ml_list_put(List, Tuple->Values[I]);
107 	return List;
108 }
109 
110 static void list_iterate(ml_iter_state_t *State, ml_value_t *Value);
111 
list_iter_value(ml_iter_state_t * State,ml_value_t * Value)112 static void list_iter_value(ml_iter_state_t *State, ml_value_t *Value) {
113 	Value = ml_deref(Value);
114 	if (ml_is_error(Value)) ML_CONTINUE(State->Base.Caller, Value);
115 	ml_list_put(State->Values[0], Value);
116 	State->Base.run = (void *)list_iterate;
117 	return ml_iter_next((ml_state_t *)State, State->Iter);
118 }
119 
list_iterate(ml_iter_state_t * State,ml_value_t * Value)120 static void list_iterate(ml_iter_state_t *State, ml_value_t *Value) {
121 	if (ml_is_error(Value)) ML_CONTINUE(State->Base.Caller, Value);
122 	State->Base.run = (void *)list_iter_value;
123 	if (Value == MLNil) ML_CONTINUE(State->Base.Caller, State->Values[0]);
124 	return ml_iter_value((ml_state_t *)State, State->Iter = Value);
125 }
126 
ML_METHOD(MLIterCount,MLListT)127 ML_METHOD(MLIterCount, MLListT) {
128 //!internal
129 	return ml_integer(ml_list_length(Args[0]));
130 }
131 
ML_METHODVX(MLListT,MLIteratableT)132 ML_METHODVX(MLListT, MLIteratableT) {
133 //<Iteratable
134 //>list
135 // Returns a list of all of the values produced by :mini:`Iteratable`.
136 	ml_iter_state_t *State = xnew(ml_iter_state_t, 1, ml_value_t *);
137 	State->Base.Caller = Caller;
138 	State->Base.run = (void *)list_iterate;
139 	State->Base.Context = Caller->Context;
140 	State->Values[0] = ml_list();
141 	return ml_iterate((ml_state_t *)State, ml_chained(Count, Args));
142 }
143 
ml_list_from_array(ml_value_t ** Values,int Length)144 ml_value_t *ml_list_from_array(ml_value_t **Values, int Length) {
145 	ml_value_t *List = ml_list();
146 	for (int I = 0; I < Length; ++I) ml_list_put(List, Values[I]);
147 	return List;
148 }
149 
ml_list_to_array(ml_value_t * List,ml_value_t ** Values)150 void ml_list_to_array(ml_value_t *List, ml_value_t **Values) {
151 	int I = 0;
152 	for (ml_list_node_t *Node = ((ml_list_t *)List)->Head; Node; Node = Node->Next, ++I) {
153 		Values[I] = Node->Value;
154 	}
155 }
156 
ml_list_grow(ml_value_t * List0,int Count)157 void ml_list_grow(ml_value_t *List0, int Count) {
158 	ml_list_t *List = (ml_list_t *)List0;
159 	for (int I = 0; I < Count; ++I) ml_list_put(List0, MLNil);
160 	List->CachedIndex = 1;
161 	List->CachedNode = List->Head;
162 }
163 
ml_list_push(ml_value_t * List0,ml_value_t * Value)164 void ml_list_push(ml_value_t *List0, ml_value_t *Value) {
165 	ml_list_t *List = (ml_list_t *)List0;
166 	ml_list_node_t *Node = new(ml_list_node_t);
167 	Node->Type = MLListNodeT;
168 	Node->Value = Value;
169 	List->ValidIndices = 0;
170 	if ((Node->Next = List->Head)) {
171 		List->Head->Prev = Node;
172 #ifdef ML_GENERICS
173 		if (List->Type->Type == MLGenericTypeT) {
174 			ml_type_t *Type = ml_generic_type_args(List->Type)[1];
175 			if (Type != ml_typeof(Value)) {
176 				ml_type_t *Type2 = ml_type_max(Type, ml_typeof(Value));
177 				if (Type != Type2) {
178 					ml_type_t *Types[] = {MLListT, Type2};
179 					List->Type = ml_generic_type(2, Types);
180 				}
181 			}
182 		}
183 #endif
184 	} else {
185 		List->Tail = Node;
186 #ifdef ML_GENERICS
187 		if (List->Type == MLListT) {
188 			ml_type_t *Types[] = {MLListT, ml_typeof(Value)};
189 			List->Type = ml_generic_type(2, Types);
190 		}
191 #endif
192 	}
193 	List->CachedNode = List->Head = Node;
194 	List->CachedIndex = 1;
195 	++List->Length;
196 }
197 
ml_list_put(ml_value_t * List0,ml_value_t * Value)198 void ml_list_put(ml_value_t *List0, ml_value_t *Value) {
199 	ml_list_t *List = (ml_list_t *)List0;
200 	ml_list_node_t *Node = new(ml_list_node_t);
201 	Node->Type = MLListNodeT;
202 	Node->Value = Value;
203 	List->ValidIndices = 0;
204 	if ((Node->Prev = List->Tail)) {
205 		List->Tail->Next = Node;
206 #ifdef ML_GENERICS
207 		if (List->Type->Type == MLGenericTypeT) {
208 			ml_type_t *Type = ml_generic_type_args(List->Type)[1];
209 			if (Type != ml_typeof(Value)) {
210 				ml_type_t *Type2 = ml_type_max(Type, ml_typeof(Value));
211 				if (Type != Type2) {
212 					ml_type_t *Types[] = {MLListT, Type2};
213 					List->Type = ml_generic_type(2, Types);
214 				}
215 			}
216 		}
217 #endif
218 	} else {
219 		List->Head = Node;
220 #ifdef ML_GENERICS
221 		if (List->Type == MLListT) {
222 			ml_type_t *Types[] = {MLListT, ml_typeof(Value)};
223 			List->Type = ml_generic_type(2, Types);
224 		}
225 #endif
226 	}
227 	List->CachedNode = List->Tail = Node;
228 	List->CachedIndex = ++List->Length;
229 }
230 
ml_list_pop(ml_value_t * List0)231 ml_value_t *ml_list_pop(ml_value_t *List0) {
232 	ml_list_t *List = (ml_list_t *)List0;
233 	ml_list_node_t *Node = List->Head;
234 	List->ValidIndices = 0;
235 	if (Node) {
236 		if ((List->Head = Node->Next)) {
237 			List->Head->Prev = NULL;
238 		} else {
239 			List->Tail = NULL;
240 		}
241 		List->CachedNode = List->Head;
242 		List->CachedIndex = 1;
243 		--List->Length;
244 		return Node->Value;
245 	} else {
246 		return MLNil;
247 	}
248 }
249 
ml_list_pull(ml_value_t * List0)250 ml_value_t *ml_list_pull(ml_value_t *List0) {
251 	ml_list_t *List = (ml_list_t *)List0;
252 	ml_list_node_t *Node = List->Tail;
253 	List->ValidIndices = 0;
254 	if (Node) {
255 		if ((List->Tail = Node->Prev)) {
256 			List->Tail->Next = NULL;
257 		} else {
258 			List->Head = NULL;
259 		}
260 		List->CachedNode = List->Tail;
261 		List->CachedIndex = -List->Length;
262 		return Node->Value;
263 	} else {
264 		return MLNil;
265 	}
266 }
267 
ml_list_get(ml_value_t * List0,int Index)268 ml_value_t *ml_list_get(ml_value_t *List0, int Index) {
269 	ml_list_node_t *Node = ml_list_index((ml_list_t *)List0, Index);
270 	return Node ? Node->Value : NULL;
271 }
272 
ml_list_set(ml_value_t * List0,int Index,ml_value_t * Value)273 ml_value_t *ml_list_set(ml_value_t *List0, int Index, ml_value_t *Value) {
274 	ml_list_node_t *Node = ml_list_index((ml_list_t *)List0, Index);
275 	if (Node) {
276 		ml_value_t *Old = Node->Value;
277 		Node->Value = Value;
278 		return Old;
279 	} else {
280 		return NULL;
281 	}
282 }
283 
ml_list_foreach(ml_value_t * Value,void * Data,int (* callback)(ml_value_t *,void *))284 int ml_list_foreach(ml_value_t *Value, void *Data, int (*callback)(ml_value_t *, void *)) {
285 	ML_LIST_FOREACH(Value, Node) if (callback(Node->Value, Data)) return 1;
286 	return 0;
287 }
288 
289 ML_METHOD("count", MLListT) {
290 //<List
291 //>integer
292 // Returns the length of :mini:`List`
293 	ml_list_t *List = (ml_list_t *)Args[0];
294 	return ml_integer(List->Length);
295 }
296 
297 ML_METHOD("length", MLListT) {
298 //<List
299 //>integer
300 // Returns the length of :mini:`List`
301 	ml_list_t *List = (ml_list_t *)Args[0];
302 	return ml_integer(List->Length);
303 }
304 
305 typedef struct {
306 	ml_state_t Base;
307 	ml_value_t *Filter;
308 	ml_list_t *List, *Drop;
309 	ml_list_node_t *Node;
310 	ml_list_node_t **KeepSlot;
311 	ml_list_node_t *KeepTail;
312 	ml_list_node_t **DropSlot;
313 	ml_list_node_t *DropTail;
314 	int Length;
315 } ml_list_filter_state_t;
316 
ml_list_filter_state_run(ml_list_filter_state_t * State,ml_value_t * Result)317 static void ml_list_filter_state_run(ml_list_filter_state_t *State, ml_value_t *Result) {
318 	if (Result) {
319 		if (ml_is_error(Result)) {
320 			State->List->Head = State->List->Tail = NULL;
321 			State->List->Length = 0;
322 			ML_CONTINUE(State->Base.Caller, Result);
323 		}
324 		goto resume;
325 	}
326 	while (State->Node) {
327 		return ml_call((ml_state_t *)State, State->Filter, 1, &State->Node->Value);
328 	resume:
329 		if (Result == MLNil) {
330 			State->Node->Prev = State->DropSlot[0];
331 			State->DropSlot[0] = State->Node;
332 			State->DropSlot = &State->Node->Next;
333 			State->DropTail = State->Node;
334 		} else {
335 			State->Node->Prev = State->KeepSlot[0];
336 			State->KeepSlot[0] = State->Node;
337 			State->KeepSlot = &State->Node->Next;
338 			++State->Length;
339 			State->KeepTail = State->Node;
340 		}
341 		State->Node = State->Node->Next;
342 	}
343 	State->Drop->Tail = State->DropTail;
344 	if (State->DropTail) State->DropTail->Next = NULL;
345 	State->Drop->Length = State->List->Length - State->Length;
346 	State->Drop->CachedIndex = State->Drop->Length;
347 	State->Drop->CachedNode = State->DropTail;
348 	State->List->Tail = State->KeepTail;
349 	if (State->KeepTail) State->KeepTail->Next = NULL;
350 	State->List->Length = State->Length;
351 	State->List->CachedIndex = State->Length;
352 	State->List->CachedNode = State->KeepTail;
353 	State->List->ValidIndices = 0;
354 	ML_CONTINUE(State->Base.Caller, State->Drop);
355 }
356 
357 ML_METHODX("filter", MLListT, MLFunctionT) {
358 //<List
359 //<Filter
360 //>list
361 // Removes every :mini:`Value` from :mini:`List` for which :mini:`Function(Value)` returns :mini:`nil` and returns those values in a new list.
362 	ml_list_t *List = (ml_list_t *)Args[0];
363 	ml_list_filter_state_t *State = new(ml_list_filter_state_t);
364 	State->Base.Caller = Caller;
365 	State->Base.Context = Caller->Context;
366 	State->Base.run = (ml_state_fn)ml_list_filter_state_run;
367 	State->List = List;
368 	ml_list_t *Drop = State->Drop = new(ml_list_t);
369 	Drop->Type = MLListT;
370 	State->Filter = Args[1];
371 	State->Node = List->Head;
372 	State->KeepSlot = &List->Head;
373 	State->KeepTail = NULL;
374 	State->DropSlot = &Drop->Head;
375 	State->DropTail = NULL;
376 	List->Head = NULL;
377 	State->Length = 0;
378 	return ml_list_filter_state_run(State, NULL);
379 }
380 
381 ML_METHOD("[]", MLListT, MLIntegerT) {
382 //<List
383 //<Index
384 //>listnode | nil
385 // Returns the :mini:`Index`-th node in :mini:`List` or :mini:`nil` if :mini:`Index` is outside the range of :mini:`List`.
386 // Indexing starts at :mini:`1`. Negative indices are counted from the end of the list, with :mini:`-1` returning the last node.
387 	ml_list_t *List = (ml_list_t *)Args[0];
388 	int Index = ml_integer_value_fast(Args[1]);
389 	return (ml_value_t *)ml_list_index(List, Index) ?: MLNil;
390 }
391 
392 typedef struct {
393 	ml_type_t *Type;
394 	ml_list_node_t *Head;
395 	int Length;
396 } ml_list_slice_t;
397 
ml_list_slice_deref(ml_list_slice_t * Slice)398 static ml_value_t *ml_list_slice_deref(ml_list_slice_t *Slice) {
399 	ml_value_t *List = ml_list();
400 	ml_list_node_t *Node = Slice->Head;
401 	int Length = Slice->Length;
402 	while (Node && Length) {
403 		ml_list_put(List, Node->Value);
404 		Node = Node->Next;
405 		--Length;
406 	}
407 	return List;
408 }
409 
ml_list_slice_assign(ml_list_slice_t * Slice,ml_value_t * Packed)410 static ml_value_t *ml_list_slice_assign(ml_list_slice_t *Slice, ml_value_t *Packed) {
411 	ml_list_node_t *Node = Slice->Head;
412 	int Length = Slice->Length;
413 	int Index = 0;
414 	while (Node && Length) {
415 		ml_value_t *Value = ml_unpack(Packed, Index + 1);
416 		++Index;
417 		Node->Value = Value;
418 		Node = Node->Next;
419 		--Length;
420 	}
421 	return Packed;
422 }
423 
424 ML_TYPE(MLListSliceT, (), "list-slice",
425 // A slice of a list.
426 	.deref = (void *)ml_list_slice_deref,
427 	.assign = (void *)ml_list_slice_assign
428 );
429 
430 ML_METHOD("[]", MLListT, MLIntegerT, MLIntegerT) {
431 //<List
432 //<From
433 //<To
434 //>listslice
435 // Returns a slice of :mini:`List` starting at :mini:`From` (inclusive) and ending at :mini:`To` (exclusive).
436 // Indexing starts at :mini:`1`. Negative indices are counted from the end of the list, with :mini:`-1` returning the last node.
437 	ml_list_t *List = (ml_list_t *)Args[0];
438 	int Start = ml_integer_value_fast(Args[1]);
439 	int End = ml_integer_value_fast(Args[2]);
440 	if (Start <= 0) Start += List->Length + 1;
441 	if (End <= 0) End += List->Length + 1;
442 	if (Start <= 0 || End < Start || End > List->Length + 1) return MLNil;
443 	ml_list_slice_t *Slice = new(ml_list_slice_t);
444 	Slice->Type = MLListSliceT;
445 	Slice->Head = ml_list_index(List, Start);
446 	Slice->Length = End - Start;
447 	return (ml_value_t *)Slice;
448 }
449 
450 ML_METHOD("append", MLStringBufferT, MLListT) {
451 	ml_stringbuffer_t *Buffer = (ml_stringbuffer_t *)Args[0];
452 	ml_stringbuffer_add(Buffer, "[", 1);
453 	ml_list_t *List = (ml_list_t *)Args[1];
454 	ml_list_node_t *Node = List->Head;
455 	if (Node) {
456 		ml_stringbuffer_append(Buffer, Node->Value);
457 		while ((Node = Node->Next)) {
458 			ml_stringbuffer_add(Buffer, ", ", 2);
459 			ml_stringbuffer_append(Buffer, Node->Value);
460 		}
461 	}
462 	ml_stringbuffer_add(Buffer, "]", 1);
463 	return (ml_value_t *)Buffer;
464 }
465 
ML_TYPED_FN(ml_unpack,MLListT,ml_list_t * List,int Index)466 ml_value_t *ML_TYPED_FN(ml_unpack, MLListT, ml_list_t *List, int Index) {
467 	return (ml_value_t *)ml_list_index(List, Index) ?: MLNil;
468 }
469 
470 /*typedef struct ml_list_iterator_t {
471 	ml_type_t *Type;
472 	ml_list_node_t *Node;
473 	long Index;
474 } ml_list_iterator_t;
475 
476 static void ML_TYPED_FN(ml_iter_value, MLListIterT, ml_state_t *Caller, ml_list_iterator_t *Iter) {
477 	ML_RETURN(Iter->Node);
478 }
479 
480 static void ML_TYPED_FN(ml_iter_next, MLListIterT, ml_state_t *Caller, ml_list_iterator_t *Iter) {
481 	if ((Iter->Node = Iter->Node->Next)) {
482 		++Iter->Index;
483 		ML_RETURN(Iter);
484 	} else {
485 		ML_RETURN(MLNil);
486 	}
487 }
488 
489 static void ML_TYPED_FN(ml_iter_key, MLListIterT, ml_state_t *Caller, ml_list_iterator_t *Iter) {
490 	ML_RETURN(ml_integer(Iter->Index));
491 }
492 
493 ML_TYPE(MLListIterT, (), "list-iterator");
494 //!internal
495 */
496 
ML_TYPED_FN(ml_iterate,MLListT,ml_state_t * Caller,ml_list_t * List)497 static void ML_TYPED_FN(ml_iterate, MLListT, ml_state_t *Caller, ml_list_t *List) {
498 	if (List->Length) {
499 		if (!List->ValidIndices) {
500 			int I = 0;
501 			for (ml_list_node_t *Node = List->Head; Node; Node = Node->Next) {
502 				Node->Index = ++I;
503 			}
504 			List->ValidIndices = 1;
505 		}
506 		ML_RETURN(List->Head);
507 		/*ml_list_iterator_t *Iter = new(ml_list_iterator_t);
508 		Iter->Type = MLListIterT;
509 		Iter->Node = List->Head;
510 		Iter->Index = 1;
511 		ML_RETURN(Iter);*/
512 	} else {
513 		ML_RETURN(MLNil);
514 	}
515 }
516 
517 ML_METHODV("push", MLListT) {
518 //<List
519 //<Values...: any
520 //>list
521 // Pushes :mini:`Values` onto the start of :mini:`List` and returns :mini:`List`.
522 	ml_value_t *List = Args[0];
523 	for (int I = 1; I < Count; ++I) ml_list_push(List, Args[I]);
524 	return Args[0];
525 }
526 
527 ML_METHODV("put", MLListT) {
528 //<List
529 //<Values...: any
530 //>list
531 // Pushes :mini:`Values` onto the end of :mini:`List` and returns :mini:`List`.
532 	ml_value_t *List = Args[0];
533 	for (int I = 1; I < Count; ++I) ml_list_put(List, Args[I]);
534 	return Args[0];
535 }
536 
537 ML_METHOD("pop", MLListT) {
538 //<List
539 //>any | nil
540 // Removes and returns the first element of :mini:`List` or :mini:`nil` if the :mini:`List` is empty.
541 	return ml_list_pop(Args[0]) ?: MLNil;
542 }
543 
544 ML_METHOD("pull", MLListT) {
545 //<List
546 //>any | nil
547 // Removes and returns the last element of :mini:`List` or :mini:`nil` if the :mini:`List` is empty.
548 	return ml_list_pull(Args[0]) ?: MLNil;
549 }
550 
551 ML_METHOD("copy", MLListT) {
552 //<List
553 //>list
554 // Returns a (shallow) copy of :mini:`List`.
555 	ml_value_t *List = ml_list();
556 	ML_LIST_FOREACH(Args[0], Iter) ml_list_put(List, Iter->Value);
557 	return List;
558 }
559 
560 ML_METHOD("+", MLListT, MLListT) {
561 //<List/1
562 //<List/2
563 //>list
564 // Returns a new list with the elements of :mini:`List/1` followed by the elements of :mini:`List/2`.
565 	ml_value_t *List = ml_list();
566 	ML_LIST_FOREACH(Args[0], Iter) ml_list_put(List, Iter->Value);
567 	ML_LIST_FOREACH(Args[1], Iter) ml_list_put(List, Iter->Value);
568 	return List;
569 }
570 
571 ML_METHOD("splice", MLListT, MLIntegerT, MLIntegerT) {
572 //<List
573 //<Index
574 //<Count
575 //>list | nil
576 // Removes :mini:`Count` elements from :mini:`List` starting at :mini:`Index`. Returns the removed elements as a new list.
577 	ml_list_t *List = (ml_list_t *)Args[0];
578 	int Start = ml_integer_value_fast(Args[1]);
579 	if (Start <= 0) Start += List->Length + 1;
580 	if (Start <= 0) return MLNil;
581 	int Remove = ml_integer_value_fast(Args[2]);
582 	if (Remove < 0) return MLNil;
583 	ml_list_t *Removed = (ml_list_t *)ml_list();
584 	if (Remove == 0) {
585 		if (Start > List->Length + 1) return MLNil;
586 	} else {
587 		int End = Start + Remove - 1;
588 		if (End > List->Length) return MLNil;
589 		if (Start == 1) {
590 			if (End == List->Length) {
591 				*Removed = *List;
592 				List->Head = List->Tail = NULL;
593 				List->Length = 0;
594 			} else {
595 				ml_list_node_t *EndNode = ml_list_index(List, End);
596 				ml_list_node_t *NextNode = EndNode->Next;
597 				EndNode->Next = NULL;
598 				Removed->CachedNode = Removed->Head = List->Head;
599 				Removed->Tail = EndNode;
600 				Removed->Length = Remove;
601 				List->Head = NextNode;
602 				NextNode->Prev = NULL;
603 				List->CachedNode = List->Head;
604 				List->CachedIndex = 1;
605 				List->Length -= Remove;
606 			}
607 		} else {
608 			ml_list_node_t *StartNode = ml_list_index(List, Start);
609 			ml_list_node_t *PrevNode = StartNode->Prev;
610 			StartNode->Prev = NULL;
611 			if (End == List->Length) {
612 				Removed->CachedNode = Removed->Head = StartNode;
613 				Removed->Tail = List->Tail;
614 				Removed->Length = Remove;
615 				List->Tail = PrevNode;
616 				PrevNode->Next = NULL;
617 				List->CachedNode = List->Head;
618 				List->CachedIndex = 1;
619 				List->Length -= Remove;
620 			} else {
621 				ml_list_node_t *EndNode = ml_list_index(List, End);
622 				ml_list_node_t *NextNode = EndNode->Next;
623 				EndNode->Next = NULL;
624 				Removed->CachedNode = Removed->Head = StartNode;
625 				Removed->Tail = EndNode;
626 				Removed->Length = Remove;
627 				NextNode->Prev = PrevNode;
628 				PrevNode->Next = NextNode;
629 				List->CachedNode = List->Head;
630 				List->CachedIndex = 1;
631 				List->Length -= Remove;
632 			}
633 		}
634 	}
635 	return (ml_value_t *)Removed;
636 }
637 
638 ML_METHOD("splice", MLListT, MLIntegerT, MLIntegerT, MLListT) {
639 //<List
640 //<Index
641 //<Count
642 //<Source
643 //>list | nil
644 // Removes :mini:`Count` elements from :mini:`List` starting at :mini:`Index`, then inserts the elements from :mini:`Source`, leaving :mini:`Source` empty. Returns the removed elements as a new list.
645 	ml_list_t *List = (ml_list_t *)Args[0];
646 	int Start = ml_integer_value_fast(Args[1]);
647 	if (Start <= 0) Start += List->Length + 1;
648 	if (Start <= 0) return MLNil;
649 	int Remove = ml_integer_value_fast(Args[2]);
650 	if (Remove < 0) return MLNil;
651 	ml_list_t *Source = (ml_list_t *)Args[3];
652 	ml_list_t *Removed = (ml_list_t *)ml_list();
653 	if (Remove == 0) {
654 		if (Start > List->Length + 1) return MLNil;
655 		if (!Source->Length) return (ml_value_t *)Removed;
656 		if (Start == 1) {
657 			Source->Tail->Next = List->Head;
658 			if (List->Head) {
659 				List->Head->Prev = Source->Tail;
660 			} else {
661 				List->Tail = Source->Tail;
662 			}
663 			List->Head = Source->Head;
664 		} else if (Start == List->Length + 1) {
665 			Source->Head->Prev = List->Tail;
666 			if (List->Tail) {
667 				List->Tail->Next = Source->Head;
668 			} else {
669 				List->Head = Source->Head;
670 			}
671 			List->Tail = Source->Tail;
672 		} else {
673 			ml_list_node_t *StartNode = ml_list_index(List, Start);
674 			ml_list_node_t *PrevNode = StartNode->Prev;
675 			PrevNode->Next = Source->Head;
676 			Source->Head->Prev = PrevNode;
677 			StartNode->Prev = Source->Tail;
678 			Source->Tail->Next = StartNode;
679 		}
680 		List->CachedNode = List->Head;
681 		List->CachedIndex = 1;
682 	} else {
683 		int End = Start + Remove - 1;
684 		if (End > List->Length) return MLNil;
685 		if (Start == 1) {
686 			if (End == List->Length) {
687 				*Removed = *List;
688 				*List = *Source;
689 			} else {
690 				ml_list_node_t *EndNode = ml_list_index(List, End);
691 				ml_list_node_t *NextNode = EndNode->Next;
692 				EndNode->Next = NULL;
693 				Removed->CachedNode = Removed->Head = List->Head;
694 				Removed->Tail = EndNode;
695 				Removed->Length = Remove;
696 				if (Source->Length) {
697 					List->Head = Source->Head;
698 					Source->Tail->Next = NextNode;
699 					NextNode->Prev = Source->Tail;
700 				} else {
701 					List->Head = NextNode;
702 					NextNode->Prev = NULL;
703 				}
704 				List->CachedNode = List->Head;
705 				List->CachedIndex = 1;
706 				List->Length -= Remove;
707 			}
708 		} else {
709 			ml_list_node_t *StartNode = ml_list_index(List, Start);
710 			ml_list_node_t *PrevNode = StartNode->Prev;
711 			StartNode->Prev = NULL;
712 			if (End == List->Length) {
713 				Removed->CachedNode = Removed->Head = StartNode;
714 				Removed->Tail = List->Tail;
715 				Removed->Length = Remove;
716 				if (Source->Length) {
717 					List->Tail = Source->Tail;
718 					Source->Head->Prev = PrevNode;
719 					PrevNode->Next = Source->Head;
720 				} else {
721 					List->Tail = PrevNode;
722 					PrevNode->Next = NULL;
723 				}
724 				List->CachedNode = List->Head;
725 				List->CachedIndex = 1;
726 				List->Length -= Remove;
727 			} else {
728 				ml_list_node_t *EndNode = ml_list_index(List, End);
729 				ml_list_node_t *NextNode = EndNode->Next;
730 				EndNode->Next = NULL;
731 				Removed->CachedNode = Removed->Head = StartNode;
732 				Removed->Tail = EndNode;
733 				Removed->Length = Remove;
734 				if (Source->Length) {
735 					Source->Tail->Next = NextNode;
736 					NextNode->Prev = Source->Tail;
737 					Source->Head->Prev = PrevNode;
738 					PrevNode->Next = Source->Head;
739 				} else {
740 					NextNode->Prev = PrevNode;
741 					PrevNode->Next = NextNode;
742 				}
743 				List->CachedNode = List->Head;
744 				List->CachedIndex = 1;
745 				List->Length -= Remove;
746 			}
747 		}
748 	}
749 	List->Length += Source->Length;
750 	Source->Head = Source->Tail = NULL;
751 	Source->Length = 0;
752 	return (ml_value_t *)Removed;
753 }
754 
755 ML_METHOD("splice", MLListT, MLIntegerT, MLListT) {
756 //<List
757 //<Index
758 //<Source
759 //>nil
760 // Inserts the elements from :mini:`Source` into :mini:`List` starting at :mini:`Index`, leaving :mini:`Source` empty.
761 	ml_list_t *List = (ml_list_t *)Args[0];
762 	int Start = ml_integer_value_fast(Args[1]);
763 	if (Start <= 0) Start += List->Length + 1;
764 	if (Start <= 0) return MLNil;
765 	ml_list_t *Source = (ml_list_t *)Args[2];
766 	if (Start > List->Length + 1) return MLNil;
767 	if (!Source->Length) return MLNil;
768 	if (Start == 1) {
769 		Source->Tail->Next = List->Head;
770 		if (List->Head) {
771 			List->Head->Prev = Source->Tail;
772 		} else {
773 			List->Tail = Source->Tail;
774 		}
775 		List->Head = Source->Head;
776 	} else if (Start == List->Length + 1) {
777 		Source->Head->Prev = List->Tail;
778 		if (List->Tail) {
779 			List->Tail->Next = Source->Head;
780 		} else {
781 			List->Head = Source->Head;
782 		}
783 		List->Tail = Source->Tail;
784 	} else {
785 		ml_list_node_t *StartNode = ml_list_index(List, Start);
786 		ml_list_node_t *PrevNode = StartNode->Prev;
787 		PrevNode->Next = Source->Head;
788 		Source->Head->Prev = PrevNode;
789 		StartNode->Prev = Source->Tail;
790 		Source->Tail->Next = StartNode;
791 	}
792 	List->CachedNode = List->Head;
793 	List->CachedIndex = 1;
794 	List->Length += Source->Length;
795 	Source->Head = Source->Tail = NULL;
796 	Source->Length = 0;
797 	return MLNil;
798 }
799 
ML_METHOD(MLStringT,MLListT)800 ML_METHOD(MLStringT, MLListT) {
801 //<List
802 //>string
803 // Returns a string containing the elements of :mini:`List` surrounded by :mini:`"["`, :mini:`"]"` and seperated by :mini:`", "`.
804 	ml_list_t *List = (ml_list_t *)Args[0];
805 	if (!List->Length) return ml_cstring("[]");
806 	ml_stringbuffer_t Buffer[1] = {ML_STRINGBUFFER_INIT};
807 	const char *Seperator = "[";
808 	int SeperatorLength = 1;
809 	ML_LIST_FOREACH(List, Node) {
810 		ml_stringbuffer_add(Buffer, Seperator, SeperatorLength);
811 		ml_value_t *Result = ml_stringbuffer_append(Buffer, Node->Value);
812 		if (ml_is_error(Result)) return Result;
813 		Seperator = ", ";
814 		SeperatorLength = 2;
815 	}
816 	ml_stringbuffer_add(Buffer, "]", 1);
817 	return ml_stringbuffer_value(Buffer);
818 }
819 
ML_METHOD(MLStringT,MLListT,MLStringT)820 ML_METHOD(MLStringT, MLListT, MLStringT) {
821 //<List
822 //<Seperator
823 //>string
824 // Returns a string containing the elements of :mini:`List` seperated by :mini:`Seperator`.
825 	ml_list_t *List = (ml_list_t *)Args[0];
826 	ml_stringbuffer_t Buffer[1] = {ML_STRINGBUFFER_INIT};
827 	const char *Seperator = ml_string_value(Args[1]);
828 	size_t SeperatorLength = ml_string_length(Args[1]);
829 	ml_list_node_t *Node = List->Head;
830 	if (Node) {
831 		ml_value_t *Result = ml_stringbuffer_append(Buffer, Node->Value);
832 		if (ml_is_error(Result)) return Result;
833 		while ((Node = Node->Next)) {
834 			ml_stringbuffer_add(Buffer, Seperator, SeperatorLength);
835 			ml_value_t *Result = ml_stringbuffer_append(Buffer, Node->Value);
836 			if (ml_is_error(Result)) return Result;
837 		}
838 	}
839 	return ml_stringbuffer_value(Buffer);
840 }
841 
842 ML_METHOD("reverse", MLListT) {
843 	ml_list_t *List = (ml_list_t *)Args[0];
844 	ml_list_node_t *Prev = List->Head;
845 	if (!Prev) return (ml_value_t *)List;
846 	List->Tail = Prev;
847 	ml_list_node_t *Node = Prev->Next;
848 	Prev->Next = NULL;
849 	while (Node) {
850 		ml_list_node_t *Next = Node->Next;
851 		Node->Next = Prev;
852 		Prev->Prev = Node;
853 		Prev = Node;
854 		Node = Next;
855 	}
856 	Prev->Prev = NULL;
857 	List->Head = Prev;
858 	List->CachedIndex = 1;
859 	List->CachedNode = Prev;
860 	List->ValidIndices = 0;
861 	return (ml_value_t *)List;
862 }
863 
864 typedef struct {
865 	ml_state_t Base;
866 	ml_list_t *List;
867 	ml_value_t *Compare;
868 	ml_value_t *Args[2];
869 	ml_list_node_t *Head, *Tail;
870 	ml_list_node_t *P, *Q;
871 	int Length;
872 	int InSize, NMerges;
873 	int PSize, QSize;
874 } ml_list_sort_state_t;
875 
ml_list_sort_state_run(ml_list_sort_state_t * State,ml_value_t * Result)876 static void ml_list_sort_state_run(ml_list_sort_state_t *State, ml_value_t *Result) {
877 	if (Result) goto resume;
878 	for (;;) {
879 		State->P = State->Head;
880 		State->Tail = State->Head = NULL;
881 		State->NMerges = 0;
882 		while (State->P) {
883 			State->NMerges++;
884 			State->Q = State->P;
885 			State->PSize = 0;
886 			for (int I = 0; I < State->InSize; I++) {
887 				State->PSize++;
888 				State->Q = State->Q->Next;
889 				if (!State->Q) break;
890 			}
891 			State->QSize = State->InSize;
892 			while (State->PSize > 0 || (State->QSize > 0 && State->Q)) {
893 				ml_list_node_t *E;
894 				if (State->PSize == 0) {
895 					E = State->Q; State->Q = State->Q->Next; State->QSize--;
896 				} else if (State->QSize == 0 || !State->Q) {
897 					E = State->P; State->P = State->P->Next; State->PSize--;
898 				} else {
899 					State->Args[0] = State->P->Value;
900 					State->Args[1] = State->Q->Value;
901 					return ml_call((ml_state_t *)State, State->Compare, 2, State->Args);
902 				resume:
903 					if (ml_is_error(Result)) {
904 						ml_list_node_t *Node = State->P, *Next;
905 						if (State->Tail) {
906 							State->Tail->Next = Node;
907 						} else {
908 							State->Head = Node;
909 						}
910 						Node->Prev = State->Tail;
911 						for (int Size = State->PSize; --Size > 0;) {
912 							Next = Node->Next; Next->Prev = Node; Node = Next;
913 						}
914 						Next = State->Q;
915 						Node->Next = Next;
916 						Next->Prev = Node;
917 						Node = Next;
918 						while (Node->Next) {
919 							Next = Node->Next; Next->Prev = Node; Node = Next;
920 						}
921 						Node->Next = NULL;
922 						State->Tail = Node;
923 						goto finished;
924 					} else if (Result == MLNil) {
925 						E = State->Q; State->Q = State->Q->Next; State->QSize--;
926 					} else {
927 						E = State->P; State->P = State->P->Next; State->PSize--;
928 					}
929 				}
930 				if (State->Tail) {
931 					State->Tail->Next = E;
932 				} else {
933 					State->Head = E;
934 				}
935 				E->Prev = State->Tail;
936 				State->Tail = E;
937 			}
938 			State->P = State->Q;
939 		}
940 		State->Tail->Next = 0;
941 		if (State->NMerges <= 1) {
942 			Result = (ml_value_t *)State->List;
943 			goto finished;
944 		}
945 		State->InSize *= 2;
946 	}
947 finished:
948 	State->List->Head = State->Head;
949 	State->List->Tail = State->Tail;
950 	State->List->CachedIndex = 1;
951 	State->List->CachedNode = State->Head;
952 	State->List->Length = State->Length;
953 	ML_CONTINUE(State->Base.Caller, Result);
954 }
955 
956 extern ml_value_t *LessMethod;
957 
958 ML_METHODX("sort", MLListT) {
959 //<List
960 //>List
961 	if (!ml_list_length(Args[0])) ML_RETURN(Args[0]);
962 	ml_list_sort_state_t *State = new(ml_list_sort_state_t);
963 	State->Base.Caller = Caller;
964 	State->Base.Context = Caller->Context;
965 	State->Base.run = (ml_state_fn)ml_list_sort_state_run;
966 	ml_list_t *List = (ml_list_t *)Args[0];
967 	State->List = List;
968 	State->Compare = LessMethod;
969 	State->Head = State->List->Head;
970 	State->Length = List->Length;
971 	State->InSize = 1;
972 	// TODO: Improve ml_list_sort_state_run so that List is still valid during sort
973 	List->ValidIndices = 0;
974 	List->CachedNode = NULL;
975 	List->Head = List->Tail = NULL;
976 	List->Length = 0;
977 	return ml_list_sort_state_run(State, NULL);
978 }
979 
980 ML_METHODX("sort", MLListT, MLFunctionT) {
981 //<List
982 //<Compare
983 //>List
984 	if (!ml_list_length(Args[0])) ML_RETURN(Args[0]);
985 	ml_list_sort_state_t *State = new(ml_list_sort_state_t);
986 	State->Base.Caller = Caller;
987 	State->Base.Context = Caller->Context;
988 	State->Base.run = (ml_state_fn)ml_list_sort_state_run;
989 	ml_list_t *List = (ml_list_t *)Args[0];
990 	State->List = List;
991 	State->Compare = Args[1];
992 	State->Head = List->Head;
993 	State->Length = List->Length;
994 	State->InSize = 1;
995 	// TODO: Improve ml_list_sort_state_run so that List is still valid during sort
996 	List->ValidIndices = 0;
997 	List->CachedNode = NULL;
998 	List->Head = List->Tail = NULL;
999 	List->Length = 0;
1000 	return ml_list_sort_state_run(State, NULL);
1001 }
1002 
1003 ML_TYPE(MLNamesT, (), "names",
1004 //!internal
1005 );
1006 
ml_names()1007 ml_value_t *ml_names() {
1008 	ml_value_t *Names = ml_list();
1009 	Names->Type = MLNamesT;
1010 	return Names;
1011 }
1012 
ml_names_add(ml_value_t * Names,ml_value_t * Value)1013 void ml_names_add(ml_value_t *Names, ml_value_t *Value) {
1014 	ml_list_t *List = (ml_list_t *)Names;
1015 	ml_list_node_t *Node = new(ml_list_node_t);
1016 	Node->Type = MLListNodeT;
1017 	Node->Value = Value;
1018 	List->ValidIndices = 0;
1019 	if ((Node->Prev = List->Tail)) {
1020 		List->Tail->Next = Node;
1021 	} else {
1022 		List->Head = Node;
1023 	}
1024 	List->CachedNode = List->Tail = Node;
1025 	List->CachedIndex = ++List->Length;
1026 }
1027 
ml_list_init()1028 void ml_list_init() {
1029 #include "ml_list_init.c"
1030 #ifdef ML_GENERICS
1031 	ml_type_add_rule(MLListT, MLIteratableT, MLIntegerT, ML_TYPE_ARG(1), NULL);
1032 #endif
1033 }
1034