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