1 module navm.defs;
2 
3 import utils.misc;
4 
5 /// to store data from script at runtime
6 public union NaData{
7 	union{
8 		bool boolVal; /// boolean value
9 		dchar dcharVal; /// dchar value
10 		integer intVal; /// integer value
11 		double doubleVal; /// double/float value
12 		NaData* ptrVal; /// to store references
13 	}
14 	/// constructor
15 	/// data can be any of the type which it can store
16 	this (T)(T data){
17 		static if (is (T == int) || is (T == long) || is (T == uint) || is (T == ulong)){
18 			intVal = data;
19 		}else static if (is (T == double) || is (T == float)){
20 			doubleVal = data;
21 		}else static if (is (T == NaData[])){
22 			arrayVal = data;
23 		}else static if (is (T == NaData*)){
24 			ptrVal = data;
25 		}else static if (is (T == dchar)){
26 			dcharVal = data;
27 		}else static if (is (T == dchar[]) || is (T == dstring)){
28 			strVal = cast(dchar[])data;
29 		}else static if (is (T == bool)){
30 			boolVal = data;
31 		}else{
32 			throw new Exception("cannot store "~T.stringof~" in NaData");
33 		}
34 	}
35 	/// makes this NaData into an array
36 	void makeArray(uinteger length){
37 		NaData[] array;
38 		array.length = length+1;
39 		array[0].intVal = length;
40 		ptrVal = array.ptr+1;
41 	}
42 	/// Returns: array value, read from ptrVal
43 	@property NaData[] arrayVal(){
44 		return ptrVal[0 .. (*(ptrVal-1)).intVal];
45 	}
46 	/// ditto
47 	@property NaData[] arrayVal(NaData[] newVal){
48 		NaData[] array = NaData(newVal.length) ~ newVal;
49 		ptrVal = array.ptr + 1;
50 		return array[1 .. $];
51 	}
52 	/// Returns: array length.
53 	/// 
54 	/// Do NOT use this to initialize array, use `makeArray`
55 	@property uinteger arrayValLength(){
56 		return (*(ptrVal - 1)).intVal;
57 	}
58 	/// ditto
59 	@property uinteger arrayValLength(uinteger length){
60 		NaData[] array;
61 		array.length = length + 1;
62 		array[0].intVal = length;
63 		immutable uinteger sliceLength = length > arrayValLength ? arrayValLength : length;
64 		array[1 .. sliceLength+1] = arrayVal[0 .. sliceLength];
65 		ptrVal = array.ptr+1;
66 		return length;
67 	}
68 	/// Returns: string value stored as NaData[] (in arrayVal)
69 	@property dchar[] strVal(){
70 		dchar[] r;
71 		r.length = arrayValLength;
72 		foreach (i, ch; arrayVal){
73 			r[i] = ch.dcharVal;
74 		}
75 		return r;
76 	}
77 	/// Setter for strVal
78 	@property dchar[] strVal(dchar[] newVal){
79 		makeArray(newVal.length);
80 		foreach (i, ch; newVal){
81 			arrayVal[i].dcharVal = ch;
82 		}
83 		return newVal;
84 	}
85 }
86 
87 /// for storing a stack frame in stack
88 struct StackFrame{
89 	void delegate()* instruction; /// instruction
90 	NaData* argument; /// argument for that instruction
91 	uinteger stackIndex; /// stack index relative to which some instructions will pushFrom/writeTo
92 }
93 
94 /// a simple array based stack
95 /// 
96 /// no bound checking is done, so be careful
97 public class ArrayStack(T){
98 private:
99 	T[] _array;
100 	T* _peekPtr;
101 	T* _curPtr;
102 public:
103 	/// constructor (set the stack length here)
104 	this(uinteger length=65_536){
105 		_array.length = length;
106 		_peekPtr = _array.ptr;
107 		_curPtr = _array.ptr;
108 	}
109 	/// the index which is treated at start of array
110 	void setIndex(uinteger newInd){
111 		_curPtr = _array.ptr + newInd;
112 	}
113 	/// Pops an element from stack
114 	/// 
115 	/// Returns: popped element
116 	T pop(){
117 		_peekPtr --;
118 		return *_peekPtr;
119 	}
120 	/// pushes an element to stack
121 	void push(T element){
122 		*_peekPtr = element;
123 		_peekPtr++;
124 	}
125 	/// number of elements in stack
126 	@property uinteger count(){
127 		return cast(uinteger)(_peekPtr - _array.ptr);
128 	}
129 	/// Reads n number of elements from stack, in reverse order (i.e: [nth-last pushed, (n-1)th-last pushed, ..., last pushed])
130 	/// 
131 	/// Returns: the elements read
132 	T[] pop(uinteger n){
133 		_peekPtr -= n;
134 		return _peekPtr[0 .. n];
135 	}
136 	/// pushes elements to stack. First in array is pushed first
137 	void push(T[] elements){
138 		_peekPtr[0 .. elements.length] = elements;
139 		_peekPtr += elements.length;
140 	}
141 	/// Returns: element at index
142 	T read(uinteger index){
143 		return _curPtr[index];
144 	}
145 	/// Returns: pointer to element at index
146 	T* readPtr(uinteger index){
147 		return &(_curPtr[index]);
148 	}
149 	/// Writes a value to index
150 	void write(uinteger index, T value){
151 		_curPtr[index] = value;
152 	}
153 	/// Returns: element at index
154 	T readAbs(uinteger index){
155 		return _array[index];
156 	}
157 	/// Returns: pointer to element at index
158 	T* readPtrAbs(uinteger index){
159 		return &(_array[index]);
160 	}
161 	/// Writes a value to index
162 	void writeAbs(uinteger index, T value){
163 		_array[index] = value;
164 	}
165 	/// Moves peek pointer to index
166 	void peek(uinteger index){
167 		_peekPtr = _curPtr + index;
168 	}
169 }