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 }