1 module m3.Stack;
2 
3 private:
4 
5 static import m3.m3;
6 
7 debug(m3) {
8     static import core.stdc.stdio;
9     alias printf = core.stdc.stdio.printf;
10 }
11 
12 static import std.traits;
13 alias isArray = std.traits.isArray;
14 
15 public:
16 
17 struct Stack(T) {
18     static assert(!isArray!(T), "Stack cannot be used with an array");
19 
20 static struct Node {
21     T value;
22     Node* previous = null;
23 }
24 
25 private:
26     Node* _end;
27     size_t _length;
28 
29 public:
30     @nogc
31     ~this() {
32         Node* cur = _end;
33         while (cur) {
34             debug(m3) printf("Destroy Stack\n");
35             
36             Node* tmp = cur;
37             cur = tmp.previous;
38             m3.m3.destruct(tmp);
39         }
40     }
41 
42     @safe
43     @nogc
44     @property
45     size_t length() const pure nothrow {
46         return _length;
47     }
48 
49     @nogc
50     @property
51     inout(Node*) top() inout pure nothrow {
52         return _end;
53     }
54 
55     @nogc
56     void push(U : T)(auto ref U item) nothrow {
57         Node* newEnd = m3.m3.make!(Node);
58         newEnd.value = item;
59         newEnd.previous = _end;
60 
61         _end = newEnd;
62         _length++;
63     }
64 
65     @nogc
66     void pop() nothrow {
67         if (_end) {
68             Node* oldEnd = _end;
69             _end = _end.previous;
70             m3.m3.destruct(oldEnd);
71 
72             _length--;
73         }
74     }
75 }
76 
77 @nogc
78 unittest {
79     Stack!(char) stack;
80 
81     stack.push('H');
82     assert(stack.top.value == 'H');
83 
84     stack.push('a');
85     assert(stack.top.value == 'a');
86 
87     stack.pop();
88     assert(stack.top.value == 'H');
89 
90     stack.pop();
91     assert(!stack.top);
92 }