1 /// Thin wrapper around `tern.experimental.ds_allocator` that allows for allocating a type in the data segment.
2 module tern.experimental.constexpr;
3 
4 import tern.experimental.ds_allocator;
5 import tern.object : store;
6 import std.traits;
7 import std.conv;
8 
9 /// Allocates `T` in the data segment when `T` is *not* a dynamic array, this is used identically to `T` normally.
10 public struct constexpr(T, uint R0 = __LINE__, string R1 = __TIMESTAMP__, string R2 = __FILE_FULL_PATH__, string R3 = __FUNCTION__)
11     if (!isDynamicArray!T)
12 {
13     T value = dsNew!(T, R0, R1, R2, R3);
14     alias value this;
15 
16 public:
17 final:
18     auto opAssign(T)(T ahs)
19     {
20         static if (isBuiltinType!T && !isArray!T)
21             value = ahs;
22         else
23             value.store(ahs);
24         return this;
25     }
26 
27     auto opAssign(T)(T ahs) shared
28     {
29         static if (isBuiltinType!T && !isArray!T)
30             value = ahs;
31         else
32             value.store(ahs);
33         return this;
34     }
35 
36     string toString() const
37     {
38         return value.to!string;
39     }
40 
41     string toString() const shared
42     {
43         return value.to!string;
44     }
45 }
46 
47 /** 
48  * Allocates `T` in the data segment when `T` is a dynamic array, this is used identically to `T` normally.
49  *
50  * Remarks:
51  *  Does not provide an initializer, must reserve initially.
52  */
53 public struct constexpr(T : U[], U)
54     if (isDynamicArray!T)
55 {
56 private:
57 final:
58     T arr;
59 
60 public:
61 final:
62     string toString() const
63     {
64         return arr.to!string;
65     }
66 
67 @nogc:
68     void reserve(uint R0 = __LINE__, string R1 = __TIMESTAMP__, string R2 = __FILE_FULL_PATH__, string R3 = __FUNCTION__)(size_t length)
69     {
70         if (arr is null)
71             arr = dsNew!(T, R0, R1, R2, R3)(length);
72         else
73             dsResize(arr, length);
74     }
75 
76     size_t length() const => arr.length;
77     const(U)* ptr() const => arr.ptr;
78 
79     bool empty()
80     {
81         return length == 0;
82     }
83 
84     U opIndex(size_t index) const
85     {
86         return arr[index];
87     }
88 
89     ref U opIndex(size_t index)
90     {
91         return arr[index];
92     }
93 
94     auto opSlice(size_t from, size_t to) const
95     {
96         return arr[from..to];
97     }
98 
99     ref auto opSlice(size_t from, size_t to)
100     {
101         return arr[from..to];
102     }
103 
104     void opSliceAssign(T slice, size_t from, size_t to)
105     {
106         arr[from..to] = slice;
107     }
108 
109     auto opDollar() const
110     {
111         return arr.length;
112     }
113 
114     T opDollar(string op)() const
115     {
116         static if (op == "front")
117             return arr[0 .. 1];
118         else static if (op == "back")
119             return arr[$-1 .. $];
120         else
121             static assert(0, "Unknown opDollar operation");
122     }
123 
124     ref auto opAssign(T)(T val)
125     {
126         arr = val;
127         return this;
128     }
129 
130     U front() const
131     {
132         return arr[0];
133     }
134 
135     U back() const
136     {
137         return arr[$-1];
138     }
139 
140     void popFront()
141     {
142         if (arr.length != 0)
143             dsResizeBeneath(arr, arr.length - 1);
144     }
145 
146     void popBack()
147     {
148         if (arr.length != 0)
149             dsResize(arr, arr.length - 1);
150     }
151 
152     U opOpAssign(string op, uint R0 = __LINE__, string R1 = __TIMESTAMP__, string R2 = __FILE_FULL_PATH__, string R3 = __FUNCTION__)(U val)
153         if (op == "~") 
154     {
155         if (arr is null)
156             arr = dsNew!(T, R0, R1, R2, R3)(1);
157         else
158             dsResize(arr, arr.length + 1);
159         arr[$-1] = val;
160         return val;
161     }
162 }
163 
164 /// Helper function to create a constexpr
165 pragma(inline)
166 constexpr!T constexpr(T)(T val)
167 {
168     return constexpr!T(val);
169 }