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 public:
102 	/// constructor (set the stack length here)
103 	this(uinteger length=65_536){
104 		_array.length = length;
105 		_peekPtr = _array.ptr;
106 	}
107 	/// Pops an element from stack
108 	/// 
109 	/// Returns: popped element
110 	T pop(){
111 		_peekPtr --;
112 		return *_peekPtr;
113 	}
114 	/// pushes an element to stack
115 	void push(T element){
116 		*_peekPtr = element;
117 		_peekPtr++;
118 	}
119 	/// number of elements in stack
120 	@property uinteger count(){
121 		return cast(uinteger)(_peekPtr - _array.ptr);
122 	}
123 	/// Reads n number of elements from stack, in reverse order (i.e: [nth-last pushed, (n-1)th-last pushed, ..., last pushed])
124 	/// 
125 	/// Returns: the elements read
126 	T[] pop(uinteger n){
127 		_peekPtr -= n;
128 		return _peekPtr[0 .. n];
129 	}
130 	/// pushes elements to stack. First in array is pushed first
131 	void push(T[] elements){
132 		_peekPtr[0 .. elements.length] = elements;
133 		_peekPtr += elements.length;
134 	}
135 	/// Returns: element at index
136 	T read(uinteger index){
137 		return _array[index];
138 	}
139 	/// Returns: pointer to element at index
140 	T* readPtr(uinteger index){
141 		return &(_array[index]);
142 	}
143 	/// Writes a value to index
144 	void write(uinteger index, T value){
145 		_array[index] = value;
146 	}
147 	/// Moves peek pointer to index
148 	void peek(uinteger index){
149 		_peekPtr = _array.ptr + index;
150 	}
151 }