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.std.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 import devol.serializable;
18 
19 import dyaml.all;    
20 
21 public
22 {
23 	import devol.operator;
24 	import devol.individ;
25 	import devol.world;
26 	
27 	import devol.std.container;
28 	import devol.std.random;
29 }
30 
31 class Line : Container, ISerializable
32 {
33 	this()
34 	{
35 		super(TypeMng.getSingleton().getType("TypeLine"));
36 	}
37 	
38 	@property Operator operator()
39 	{
40 		return pOp;
41 	}
42 	
43 	override void randomChange()
44 	{
45 		
46 	}
47 	
48 	override void randomChange(string maxChange)
49 	{
50 		
51 	}
52 
53 	override Argument getRandomElement()
54 	{
55 		return args[ uniform(0, args.length) ];
56 	}
57 	
58 	override Argument getRandomElement(double[] chances)
59 	{
60 		Argument ret;
61 		randomRange!((int k){ret = args[k];})(chances[0..args.length]);
62 		return ret;
63 	}
64 	
65 	override void replaceRandomElement(Argument narg)
66 	{
67 		args[ uniform(0, args.length) ] = narg;
68 	}
69 	
70 	override void replaceRandomElement(double[] chances, Argument narg)
71 	{
72 		randomRange!((int k){args[k] = narg;})(chances[0..args.length]);
73 	}
74 	
75 	override void replaceRandomElement(Argument delegate(Type t) del)
76 	{
77 		auto i = uniform(0, args.length);
78 		args[ i ] = del( args[i].type );
79 	}
80 	
81 	override void replaceRandomElement(Argument delegate(Type t) del, double[] chances)
82 	{
83 		randomRange!((int k){args[k] = del(args[k].type);})(chances[0..args.length]);
84 	}
85 	
86 	override Argument getRandomLeaf()
87 	{
88 		auto temp =  new Argument[0];
89 		foreach(arg; args)
90 			if (cast(Container)arg is null)
91 				temp ~= arg;
92 		
93 		return temp[ uniform(0, temp.length) ];
94 	}
95 	
96 	override Argument getRandomLeaf(double[] chances)
97 	{
98 		auto temp =  new Argument[0];
99 		foreach(arg; args)
100 			if (cast(Container)arg is null)
101 				temp ~= arg;
102 		
103 		Argument ret;
104 		randomRange!((int k){ret = temp[k];})(chances[0..temp.length]);	
105 		return ret;
106 	}
107 	
108 	override uint getLeafCount()
109 	{
110 		auto temp =  new Argument[0];
111 		foreach(arg; args)
112 			if (cast(Container)arg is null)
113 				temp ~= arg;		
114 		return cast(uint)temp.length;
115 	}
116 	
117 	override void addElement(Argument arg)
118 	{
119 		if (args.length < pOp.argsNumber)
120 		{
121 			assert(arg.type == pOp[cast(int)args.length].type, "Argument type isn't coresponed operator argument type!");
122 			args ~= arg;
123 		}
124 	}
125 	
126 	override void removeElement(size_t i)
127 	{
128 		if ( i > 0 && i < args.length )
129 			args.remove(i);
130 	}
131 	
132 	override void removeAll()
133 	{
134 		args.clear();
135 	}
136 	
137 	@property void operator(Operator op)
138 	{
139 		if (op is null)
140 		{
141 			clear();
142 			return;
143 		}
144 		
145 		args = new Argument[op.argsNumber];
146 		
147 		foreach(uint i,ref arg; args)
148 		{
149 			arg = op.generateArg(i);
150 		}
151 		
152 		pOp = op;
153 	}
154 	
155 	override @property string tostring(uint depth=0)
156 	{
157 		final switch(pOp.style)
158 		{
159 			case ArgsStyle.CLASSIC_STYLE:
160 				return formClassic(depth);
161 			case ArgsStyle.MASS_STYLE:
162 				return formMass(depth);
163 			case ArgsStyle.UNAR_STYLE:
164 				return formUnar(depth);
165 			case ArgsStyle.BINAR_STYLE:
166 				return formBinar(depth);
167 			case ArgsStyle.NULAR_STYLE:
168 				return formNular(depth);
169 			case ArgsStyle.CONTROL_STYLE:
170 				return formControl(depth);
171 		}
172 	}
173 	
174 	void clear()
175 	{
176 		pOp = null;
177 		args = null;
178 	}
179 	
180 	bool isSubline( size_t i )
181 	{
182 		if ( i >= args.length ) return false;
183 		
184 		return cast(Line)(args[i]) !is null;
185 	}
186 	
187 	Line getSubline( size_t i )
188 	{
189 		if ( i >= args.length ) return null;
190 		
191 		return cast(Line)(args[i]);
192 	}
193 	
194 	bool isScope( size_t i)
195 	{
196 		if ( i >= args.length ) return false;
197 		
198 		return cast(ArgScope)(args[i]) !is null;
199 	}
200 	
201 	ArgScope getScope( size_t i )
202 	{
203 		if ( i >= args.length ) return null;
204 		
205 		return cast(ArgScope)(args[i]);
206 	}
207 	
208 	Argument compile(IndAbstract ind, WorldAbstract world)
209 	{
210 		//writeln("Compling line");
211 		Line dline = this.dup;
212 		for( int i=0; i < dline.length; i++)
213 		{
214 			//writeln("Compiling arg ", i);
215 			if ( pOp[i].eval )
216 			{
217 				auto ascope = dline.getScope(i);
218 				if (ascope !is null)
219 				{
220 					foreach(Line l; ascope )
221 					{
222 						(cast(Line)(l)).compile(ind,world);
223 					}
224 					dline[i] = pOp[i].type.getNewArg();
225 				}
226 				else
227 				{
228 					Line aline = dline.getSubline(i);
229 					if (aline !is null)
230 						dline[i] = aline.compile(ind, world);
231 					else
232 					{
233 						//writeln("Search convertors for ", dline[i].type.name, " and ", dline.operator[i].type.name);
234 						if (dline[i].type.name != dline.operator[i].type.name)
235 						{
236 							Argument convarg = dline.operator[i].type.convert( dline[1] );
237 							if (convarg is null)
238 								throw new Exception("Compilation error! Types not convertable:"
239 									~dline[i].type.name ~" and "~ dline.operator[i].type.name~"!");
240 							dline[i] = convarg;
241 						}
242 					}
243 				}
244 			}
245 		}
246 		assert(pOp);
247 		//writeln("Applying op ", pOp.name);
248 		return pOp.apply(ind, dline, world);		
249 	}
250 	
251 	override @property Line dup()
252 	{
253 		Line nline = new Line();
254 		nline.pOp = pOp;
255 		nline.args = new Argument[args.length];
256 		foreach( i,arg; args)
257 		{
258 			nline.args[i] = arg.dup;
259 		}
260 
261 		return nline;
262 	}
263 	
264 	override Argument opIndex( size_t i )
265 	{
266 		return args[i];
267 	}
268 	
269 	override void opIndexAssign( Argument val, size_t i )
270 	{
271 		if (i >= args.length) return;
272 		args[i] = val;
273 	}
274 	
275 	override Argument[] opSlice( size_t a, size_t b )
276 	{
277 		return args[a..b];
278 	}
279 	
280 	override size_t opDollar()
281 	{
282 		return args.length;
283 	}
284 	
285 	override @property size_t length()
286 	{
287 		return args.length;
288 	}
289 	
290 	override @property ulong children()
291 	{
292 		ulong length = 1;
293 		foreach(arg; args)
294 			length += arg.children;
295 		return length;
296 	}
297 	
298 	override @property ulong leafs()
299 	{
300 	    if(args.length == 0) return 1;
301 	    
302 		ulong length = 0;
303 		foreach(arg; args)
304 			length += arg.leafs;
305 		return length;
306 	}
307 	
308 	@property bool empty()
309 	{
310 		return args.empty;
311 	}
312 	
313 	override int opApply(int delegate(Argument) dg)
314 	{
315 		int result = 0;
316 		
317 		foreach( i,arg; args)
318 		{
319 			result = dg(arg);
320 			if (result) break;
321 		}
322 		return result;
323 	}
324 	
325 	int opApply(int delegate(int, ref Argument) dg)
326 	{
327 		int result = 0;
328 		
329 		foreach( int i, ref arg; args)
330 		{
331 			result = dg(i,arg);
332 			if (result) break;
333 		}
334 		return result;
335 	}
336 	
337 	@property Argument front()
338 	{
339 		return args.front;
340 	}
341 	
342 	@property Argument back()
343 	{
344 		return args.back;
345 	}
346 	
347 	private static string getTabs(uint c)
348 	{
349 		if (c==0) return "";
350 		
351 		auto buff = new char[c];
352 		foreach( ref cc; buff)
353 			cc = to!char(0x09);
354 		return buff.idup;
355 	}
356 	
357 	string formClassic(uint depth=0)
358 	{
359 		string s = getTabs(depth) ~ pOp.name ~ "(";
360 		
361 		foreach(i,arg; args)
362 		{
363 			s ~= arg.tostring;
364 			if (i != args.length-1)
365 				s~= " , ";
366 		}
367 		return s ~ ")";
368 	}
369 	
370 	string formMass(uint depth=0)
371 	{
372 		string s = getTabs(depth) ~ pOp.name ~ "[";
373 		
374 		foreach(i,arg; args)
375 		{
376 			s ~= arg.tostring;
377 			if (i != args.length-1)
378 				s~= " , ";
379 		}
380 		return s ~ "]";		
381 	}
382 	
383 	string formBinar(uint depth=0)
384 	{
385 		if (args.length != 2) 
386 			return "(Invalid args count "~to!string(args.length)~" )";
387 		
388 		return getTabs(depth) ~ "("~args[0].tostring ~ " " ~ pOp.name ~ " "
389 			~ args[1].tostring ~ ")";
390 	}
391 	
392 	string formUnar(uint depth=0)
393 	{
394 		if (args.length != 1) 
395 			return "(Invalid args count)";
396 		
397 		return getTabs(depth) ~ pOp.name ~ args[0].tostring;
398 	}
399 	
400 	string formNular(uint depth=0)
401 	{
402 		if(args.length != 0)
403 			return "(Invalid args count)";
404 		
405 		return getTabs(depth) ~ pOp.name;
406 	}
407 	
408 	string formControl(uint depth=0)
409 	{
410 		if (args.length < 1) 
411 			return "(Invalid args count)";
412 		
413 		string ret = getTabs(depth) ~ pOp.name ~ "(" ~ args[0].tostring ~ ")\n";
414 		foreach(arg; args[1..$])
415 		{
416 			ret ~= getTabs(depth) ~ "{\n";
417 			ret ~= arg.tostring(depth+1)~ "\n";
418 			ret ~= getTabs(depth) ~ "}\n";
419 		}
420 		return ret;
421 	}
422 	
423 	static Line loadBinary(InputStream stream)
424 	{
425 	    auto line = new Line();
426 	    
427 	    line.pOp = Operator.loadBinary(stream);
428 	    
429 	    ulong argsLength;
430 	    auto builder = appender!(Argument[]);
431 	    
432 	    foreach(i; 0..cast(size_t)argsLength)
433 	    {
434 	        char[] mark;
435 	        stream.read(mark);
436 	        
437 	        if(mark == "line")
438 	        {
439 	            builder.put(Line.loadBinary(stream));
440 	        } else if(mark == "scope")
441 	        {
442 	            builder.put(ArgScope.loadBinary(stream));
443 	        } else if(mark == "plain")
444 	        {
445 	            auto type = line.pOp[i].type; 
446 	            builder.put(type.loadArgument(stream));
447 	        } else
448 	        {
449 	            assert(false, "Failed to load! Unknown label!");
450 	        }
451 	    }
452 	    line.args = builder.data;
453 	    
454 	    return line;
455 	}
456 	
457 	static Line loadYaml(Node node)
458 	{
459 	    auto ret = new Line;
460 	    ret.pOp = Operator.loadYaml(node["operator"]);
461 	    
462 	    auto builder = appender!(Argument[]); 
463 	    if(node.containsKey("arguments"))
464 	    {
465 	        size_t i = 0;
466     	    foreach(Node subnode; node["arguments"])
467     	    {
468     	        builder.put(Argument.loadYaml(ret.pOp[i++].type, subnode));
469     	    }
470 	    }
471 	    ret.args = builder.data;
472 	    
473 	    return ret;
474 	}
475 	
476 	void saveBinary(OutputStream stream)
477 	{
478 	    stream.write("line");
479 	    
480 	    pOp.saveBinary(stream);
481 	    stream.write(cast(ulong)args.length);
482 	    foreach(arg; args)
483 	    {
484 	        if(cast(Line)arg is null && cast(ArgScope)arg is null)
485 	        {
486 	            stream.write("plain");
487             }
488 	        arg.saveBinary(stream);
489 	    }
490 	}
491 	
492 	override Node saveYaml()
493 	{
494 	    auto builder = appender!(Node[]);
495 	    
496 	    foreach(arg; args)
497 	    {
498 	        builder.put(arg.saveYaml);
499 	    }
500 	    
501 	    auto map = [
502             "class": Node("line"),
503             "operator": pOp.saveYaml,
504             ];
505             
506         if(builder.data.length > 0)
507         {
508             map["arguments"] = Node(builder.data);
509         }
510         
511         return Node(map);
512 	}
513 	
514 	override string genDot(ref size_t nameIndex, out string nodeName)
515 	{
516 		auto builder = appender!string;
517 		
518 		builder.put(pOp.genDot(nameIndex, nodeName));
519 		
520 		foreach(arg; args)
521 		{
522 			string argNode;
523 			builder.put(arg.genDot(nameIndex, argNode));
524 			
525 			builder.put(nodeName);
526 			builder.put(" -> ");
527 			builder.put(argNode);
528 			builder.put(";\n");
529 		}
530 		
531 		return builder.data;
532 	}
533 	
534 	private Argument[] args;
535 	private Operator pOp;
536 }
537 
538 unittest
539 {
540 	class VoidOp : Operator
541 	{
542 		this()
543 		{
544 			mRetType = new TypeVoid;
545 			super("v","",ArgsStyle.BINAR_STYLE);
546 			
547 			ArgInfo a1;
548 			a1.type = mRetType;
549 			a1.min = "-1000";
550 			a1.max = "+1000";
551 			
552 			args ~= a1;
553 			args ~= a1;
554 		}
555 	
556 		override Argument apply(IndAbstract ind, Line line, WorldAbstract world)
557 		{
558 			return mRetType.getNewArg();
559 		}	
560 	
561 	}
562 		auto tm = new TypeMng;
563 		
564 	    auto aline = new Line;
565 	    auto op = new VoidOp;
566 	    auto nline = new Line;
567 	    auto mline = new Line;
568 	    
569 	    mline.operator = op;
570 	    nline.operator = op;
571 		aline.operator = op;
572 		
573 		aline[0] = nline;
574 		aline[1] = mline;
575 		
576 		auto  i = aline.children;
577 		assert( i== 7, text("Children doesn't work! ",i));
578 }