1 module orelang.operator.ArrayOperators;
2 import orelang.expression.ImmediateValue,
3        orelang.operator.IOperator,
4        orelang.Engine,
5        orelang.Value;
6 import std.algorithm,
7        std..string,
8        std.array,
9        std.conv;
10 
11 /**
12  * revese given array 
13  */
14 class ArrayReverseOperator : IOperator {
15   /**
16    * call
17    */
18   public Value call(Engine engine, Value[] args) {
19     Value[] ret;
20     Value eargs0 = engine.eval(args[0]);
21 
22     if (eargs0.type == ValueType.Array) {
23       foreach_reverse (elem; eargs0.getArray) {
24         ret ~= elem;
25       }
26     } else if (eargs0.type == ValueType.ImmediateValue && eargs0.getImmediateValue.value.type == ValueType.Array) {
27       foreach_reverse (elem; eargs0.getImmediateValue.value.getArray) {
28         ret ~= elem;
29       }
30     } else {
31       throw new Exception("[number-to-string] Invalid argument was given.");
32     }
33 
34     return new Value(ret);
35   }
36 }
37 
38 /**
39  * Set a value into the order of the array
40  */
41 class ArraySetNOperator : IOperator {
42   /**
43    * call
44    */
45   public Value call(Engine engine, Value[] args) {
46     Value[] arr;
47     Value eargs0 = engine.eval(args[0]);
48 
49     if (eargs0.type == ValueType.ImmediateValue) {
50       arr = eargs0.getImmediateValue.value.getArray;
51     } else {
52       arr = eargs0.getArray;
53     }
54     
55     long  idx   = engine.eval(args[1]).getNumeric.to!long;
56     Value value = engine.eval(args[2]);
57 
58     if (0 <= idx && idx < arr.length) {
59       arr[idx] = value;
60 
61       return new Value(arr);
62     } else {
63       throw new Exception("Invalid");
64     }
65   }
66 }
67 
68 /**
69  * Get a value from the order of the array
70  */
71 class ArrayGetNOperator : IOperator {
72   /**
73    * call
74    */
75   public Value call(Engine engine, Value[] args) {
76     Value[] arr;
77     Value eargs0 = engine.eval(args[0]);
78 
79     if (eargs0.type == ValueType.ImmediateValue) {
80       arr = eargs0.getImmediateValue.value.getArray;
81     } else {
82       arr = eargs0.getArray;
83     }
84     
85     long  idx   = engine.eval(args[1]).getNumeric.to!long;
86 
87     if (0 <= idx && idx < arr.length) {
88       return arr[idx];
89     } else {
90       throw new Exception("[get] Invalid");
91     }
92   }
93 }
94 
95 /**
96  * Append a value from the order of the array
97  */
98 class ArrayAppendOperator : IOperator {
99   /**
100    * call
101    */
102   public Value call(Engine engine, Value[] args) {
103     Value[] arr;
104     Value eargs0 = engine.eval(args[0]);
105 
106     if (eargs0.type == ValueType.ImmediateValue) {
107       arr = eargs0.getImmediateValue.value.getArray;
108     } else {
109       arr = eargs0.getArray;
110     }
111     
112     foreach (arg; args[1..$]) {
113       arr ~= engine.eval(arg);
114     }
115 
116     return new Value(arr);
117   }
118 }
119 
120 /**
121  * Tak a slice from the range of the array
122  */
123 class ArraySliceOperator : IOperator {
124   /**
125    * call
126    */
127   public Value call(Engine engine, Value[] args) {
128     Value[] arr;
129     Value eargs0 = engine.eval(args[0]);
130 
131     if (eargs0.type == ValueType.ImmediateValue) {
132       arr = eargs0.getImmediateValue.value.getArray;
133     } else {
134       arr = eargs0.getArray;
135     }
136     
137     long slice1  = engine.eval(args[1]).getNumeric.to!long,
138          slice2  = engine.eval(args[2]).getNumeric.to!long;
139 
140     if ((0 <= slice1 && 0 <= slice2) && (slice1 <= arr.length && slice2 <= arr.length)) {
141       return new Value(arr[slice1..slice2]);
142     } else {
143       throw new Exception("[get] Invalid");
144     }
145   }
146 }
147 
148 /**
149  * concat arrays
150  */
151 class ArrayConcatOperator : IOperator {
152   /**
153    * call
154    */
155   public Value call(Engine engine, Value[] args) {
156     Value[] arr;
157 
158     foreach (arg; args) {
159       Value earg = engine.eval(arg);
160       Value[] tarr;
161 
162       if (earg.type == ValueType.ImmediateValue) {
163         tarr = earg.getImmediateValue.value.getArray;
164       } else {
165         tarr = earg.getArray;
166       }
167 
168       foreach (t; tarr) {
169         arr ~= t;
170       }
171     }
172 
173     return new Value(arr);
174   }
175 }
176 
177 /**
178  * return the length of the array
179  */
180 class ArrayLengthOperator : IOperator {
181   /**
182    * call
183    */
184   public Value call(Engine engine, Value[] args) {
185     Value[] arr;
186     Value eargs0 = engine.eval(args[0]);
187 
188     if (eargs0.type == ValueType.ImmediateValue) {
189       arr = eargs0.getImmediateValue.value.getArray;
190     } else {
191       arr = eargs0.getArray;
192     }
193 
194     return new Value(arr.length.to!double);
195   }
196 }
197 
198 /**
199  * make a new array 
200  */
201 class ArrayNewOperator : IOperator {
202   /**
203    * call
204    */
205   public Value call(Engine engine, Value[] args) {
206     Value[] ret;
207 
208     foreach (arg; args) {
209       ret ~= engine.eval(arg);
210     }
211 
212     return new Value(ret);
213   }
214 }
215 
216 /**
217  * return flattend array of the given array 
218  */
219 class ArrayFlattenOperator : IOperator {
220   /**
221    * call
222    */
223   public Value call(Engine engine, Value[] args) {
224     Value[] ret;
225 
226     foreach (arg; args) {
227       if (arg.type == ValueType.Array) {
228         foreach (elem; engine.eval(arg).getArray) {
229           foreach (ee; elem.getArray) {
230             ret ~= ee;
231           }
232         }
233       } else {
234         Value earg = engine.eval(arg);
235         ret ~= earg;
236       }
237     }
238 
239     return new Value(ret);
240   }
241 }