1 /**
2 *   Copyright: © 2012-2014 Anton Gushcha
3 *   License: Subject to the terms of the MIT license, as written in the included LICENSE file.
4 *   Authors:  NCrashed <ncrashed@gmail.com>,
5 *             LeMarwin <lemarwin42@gmail.com>,
6 *             Nazgull09 <nazgull90@gmail.com>
7 */
8 module devol.line;
9 
10 import std.stdio;
11 import std.array;
12 import std.conv;
13 import std.random;
14 import std.algorithm;
15 
16 import devol.typemng;
17 
18 public
19 {
20 	import devol.operator;
21 	import devol.individ;
22 	import devol.world;
23 	
24 	import devol.std.container;
25 	import devol.std.random;
26 }
27 
28 class Line : Container
29 {
30 	this()
31 	{
32 		super(TypeMng.getSingleton().getType("TypeLine"));
33 	}
34 	
35 	@property Operator operator()
36 	{
37 		return pOp;
38 	}
39 	
40 	override void randomChange()
41 	{
42 		
43 	}
44 	
45 	override void randomChange(string maxChange)
46 	{
47 		
48 	}
49 
50 	override Argument getRandomElement()
51 	{
52 		return args[ uniform(0, args.length) ];
53 	}
54 	
55 	override Argument getRandomElement(double[] chances)
56 	{
57 		Argument ret;
58 		randomRange!((int k){ret = args[k];})(chances[0..args.length]);
59 		return ret;
60 	}
61 	
62 	override void replaceRandomElement(Argument narg)
63 	{
64 		args[ uniform(0, args.length) ] = narg;
65 	}
66 	
67 	override void replaceRandomElement(double[] chances, Argument narg)
68 	{
69 		randomRange!((int k){args[k] = narg;})(chances[0..args.length]);
70 	}
71 	
72 	override void replaceRandomElement(Argument delegate(Type t) del)
73 	{
74 		auto i = uniform(0, args.length);
75 		args[ i ] = del( args[i].type );
76 	}
77 	
78 	override void replaceRandomElement(Argument delegate(Type t) del, double[] chances)
79 	{
80 		randomRange!((int k){args[k] = del(args[k].type);})(chances[0..args.length]);
81 	}
82 	
83 	override Argument getRandomLeaf()
84 	{
85 		auto temp =  new Argument[0];
86 		foreach(arg; args)
87 			if (cast(Container)arg is null)
88 				temp ~= arg;
89 		
90 		return temp[ uniform(0, temp.length) ];
91 	}
92 	
93 	override Argument getRandomLeaf(double[] chances)
94 	{
95 		auto temp =  new Argument[0];
96 		foreach(arg; args)
97 			if (cast(Container)arg is null)
98 				temp ~= arg;
99 		
100 		Argument ret;
101 		randomRange!((int k){ret = temp[k];})(chances[0..temp.length]);	
102 		return ret;
103 	}
104 	
105 	override uint getLeafCount()
106 	{
107 		auto temp =  new Argument[0];
108 		foreach(arg; args)
109 			if (cast(Container)arg is null)
110 				temp ~= arg;		
111 		return cast(uint)temp.length;
112 	}
113 	
114 	override void addElement(Argument arg)
115 	{
116 		if (args.length < pOp.argsNumber)
117 		{
118 			assert(arg.type == pOp[cast(int)args.length].type, "Argument type isn't coresponed operator argument type!");
119 			args ~= arg;
120 		}
121 	}
122 	
123 	override void removeElement(int i)
124 	{
125 		if ( i > 0 && i < args.length )
126 			args.remove(i);
127 	}
128 	
129 	override void removeAll()
130 	{
131 		args.clear();
132 	}
133 	
134 	@property void operator(Operator op)
135 	{
136 		if (op is null)
137 		{
138 			clear();
139 			return;
140 		}
141 		
142 		args = new Argument[op.argsNumber];
143 		
144 		foreach(uint i,ref arg; args)
145 		{
146 			arg = op.generateArg(i);
147 		}
148 		
149 		pOp = op;
150 	}
151 	
152 	override @property string tostring(uint depth=0)
153 	{
154 		final switch(pOp.style)
155 		{
156 			case ArgsStyle.CLASSIC_STYLE:
157 				return formClassic(depth);
158 			case ArgsStyle.MASS_STYLE:
159 				return formMass(depth);
160 			case ArgsStyle.UNAR_STYLE:
161 				return formUnar(depth);
162 			case ArgsStyle.BINAR_STYLE:
163 				return formBinar(depth);
164 			case ArgsStyle.NULAR_STYLE:
165 				return formNular(depth);
166 			case ArgsStyle.CONTROL_STYLE:
167 				return formControl(depth);
168 		}
169 	}
170 	
171 	void clear()
172 	{
173 		pOp = null;
174 		args = null;
175 	}
176 	
177 	bool isSubline( uint i )
178 	{
179 		if ( i >= args.length ) return false;
180 		
181 		return cast(Line)(args[i]) !is null;
182 	}
183 	
184 	Line getSubline( uint i )
185 	{
186 		if ( i >= args.length ) return null;
187 		
188 		return cast(Line)(args[i]);
189 	}
190 	
191 	bool isScope( uint i)
192 	{
193 		if ( i >= args.length ) return false;
194 		
195 		return cast(ArgScope)(args[i]) !is null;
196 	}
197 	
198 	ArgScope getScope( uint i )
199 	{
200 		if ( i >= args.length ) return null;
201 		
202 		return cast(ArgScope)(args[i]);
203 	}
204 	
205 	Argument compile(IndAbstract ind, WorldAbstract world)
206 	{
207 		writeln("Compling line");
208 		Line dline = this.dup;
209 		for( int i=0; i < dline.length; i++)
210 		{
211 			writeln("Compiling arg ", i);
212 			if ( pOp.style != ArgsStyle.CONTROL_STYLE || i==0 )
213 			{
214 				auto ascope = dline.getScope(i);
215 				if (ascope !is null)
216 				{
217 					foreach(Line l; ascope )
218 					{
219 						(cast(Line)(l)).compile(ind,world);
220 					}
221 					dline[i] = pOp[i].type.getNewArg();
222 				}
223 				else
224 				{
225 					Line aline = dline.getSubline(i);
226 					if (aline !is null)
227 						dline[i] = aline.compile(ind, world);
228 					else
229 					{
230 						writeln("Search convertors for ", dline[i].type.name, " and ", dline.operator[i].type.name);
231 						if (dline[i].type.name != dline.operator[i].type.name)
232 						{
233 							Argument convarg = dline.operator[i].type.convert( dline[1] );
234 							if (convarg is null)
235 								throw new Exception("Compilation error! Types not convertable:"
236 									~dline[i].type.name ~" and "~ dline.operator[i].type.name~"!");
237 							dline[i] = convarg;
238 						}
239 					}
240 				}
241 			}
242 		}
243 		assert(pOp);
244 		writeln("Applying op ", pOp.name);
245 		return pOp.apply(ind, dline, world);		
246 	}
247 	
248 	override @property Line dup()
249 	{
250 		Line nline = new Line();
251 		nline.pOp = pOp;
252 		nline.args = new Argument[args.length];
253 		foreach( i,arg; args)
254 		{
255 			nline.args[i] = arg.dup;
256 		}
257 
258 		return nline;
259 	}
260 	
261 	override Argument opIndex( uint i )
262 	{
263 		return args[i];
264 	}
265 	
266 	override void opIndexAssign( Argument val, uint i )
267 	{
268 		if (i >= args.length) return;
269 		args[i] = val;
270 	}
271 	
272 	override Argument[] opSlice( uint a, uint b )
273 	{
274 		return args[a..b];
275 	}
276 	
277 	override uint opDollar()
278 	{
279 		return cast(uint)(args.length);
280 	}
281 	
282 	override @property uint length()
283 	{
284 		return cast(uint)(args.length);
285 	}
286 	
287 	override @property ulong children()
288 	{
289 		ulong length = 1;
290 		foreach(arg; args)
291 			length += arg.children;
292 		return length;
293 	}
294 	
295 	override @property ulong leafs()
296 	{
297 		ulong length = 0;
298 		foreach(arg; args)
299 			length += arg.leafs;
300 		return length;
301 	}
302 	
303 	@property bool empty()
304 	{
305 		return args.empty;
306 	}
307 	
308 	override int opApply(int delegate(Argument) dg)
309 	{
310 		int result = 0;
311 		
312 		foreach( i,arg; args)
313 		{
314 			result = dg(arg);
315 			if (result) break;
316 		}
317 		return result;
318 	}
319 	
320 	int opApply(int delegate(int, ref Argument) dg)
321 	{
322 		int result = 0;
323 		
324 		foreach( int i, ref arg; args)
325 		{
326 			result = dg(i,arg);
327 			if (result) break;
328 		}
329 		return result;
330 	}
331 	
332 	@property Argument front()
333 	{
334 		return args.front;
335 	}
336 	
337 	@property Argument back()
338 	{
339 		return args.back;
340 	}
341 	
342 	private static string getTabs(uint c)
343 	{
344 		if (c==0) return "";
345 		
346 		auto buff = new char[c];
347 		foreach( ref cc; buff)
348 			cc = to!char(0x09);
349 		return buff.idup;
350 	}
351 	
352 	string formClassic(uint depth=0)
353 	{
354 		string s = getTabs(depth) ~ pOp.name ~ "(";
355 		
356 		foreach(i,arg; args)
357 		{
358 			s ~= arg.tostring;
359 			if (i != args.length-1)
360 				s~= " , ";
361 		}
362 		return s ~ ")";
363 	}
364 	
365 	string formMass(uint depth=0)
366 	{
367 		string s = getTabs(depth) ~ pOp.name ~ "[";
368 		
369 		foreach(i,arg; args)
370 		{
371 			s ~= arg.tostring;
372 			if (i != args.length-1)
373 				s~= " , ";
374 		}
375 		return s ~ "]";		
376 	}
377 	
378 	string formBinar(uint depth=0)
379 	{
380 		if (args.length != 2) 
381 			return "(Invalid args count "~to!string(args.length)~" )";
382 		
383 		return getTabs(depth) ~ "("~args[0].tostring ~ " " ~ pOp.name ~ " "
384 			~ args[1].tostring ~ ")";
385 	}
386 	
387 	string formUnar(uint depth=0)
388 	{
389 		if (args.length != 1) 
390 			return "(Invalid args count)";
391 		
392 		return getTabs(depth) ~ pOp.name ~ args[0].tostring;
393 	}
394 	
395 	string formNular(uint depth=0)
396 	{
397 		if(args.length != 0)
398 			return "(Invalid args count)";
399 		
400 		return getTabs(depth) ~ pOp.name;
401 	}
402 	
403 	string formControl(uint depth=0)
404 	{
405 		if (args.length < 1) 
406 			return "(Invalid args count)";
407 		
408 		string ret = getTabs(depth) ~ pOp.name ~ "(" ~ args[0].tostring ~ ")\n";
409 		foreach(arg; args[1..$])
410 		{
411 			ret ~= getTabs(depth) ~ "{\n";
412 			ret ~= arg.tostring(depth+1)~ "\n";
413 			ret ~= getTabs(depth) ~ "}\n";
414 		}
415 		return ret;
416 	}
417 	
418 	private Argument[] args;
419 	private Operator pOp;
420 }
421 
422 unittest
423 {
424 	class VoidOp : Operator
425 	{
426 		this()
427 		{
428 			mRetType = new TypeVoid;
429 			super("v","",ArgsStyle.BINAR_STYLE);
430 			
431 			ArgInfo a1;
432 			a1.type = mRetType;
433 			a1.min = "-1000";
434 			a1.max = "+1000";
435 			
436 			args ~= a1;
437 			args ~= a1;
438 		}
439 	
440 		Argument apply(IndAbstract ind, Line line, WorldAbstract world)
441 		{
442 			return mRetType.getNewArg();
443 		}	
444 	
445 	}
446 		auto tm = new TypeMng;
447 		
448 	    auto aline = new Line;
449 	    auto op = new VoidOp;
450 	    auto nline = new Line;
451 	    auto mline = new Line;
452 	    
453 	    mline.operator = op;
454 	    nline.operator = op;
455 		aline.operator = op;
456 		
457 		aline[0] = nline;
458 		aline[1] = mline;
459 		
460 		auto  i = aline.children;
461 		assert( i== 7, text("Children doesn't work! ",i));
462 }