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.argscope;
9 
10 import std.conv;
11 import std.random;
12 import std.algorithm;
13 import std.stream;
14 import std.array;
15 
16 import devol.std.container;
17 import devol.std.random;
18 import devol.std.typescope;
19 import devol.typemng;
20 import devol.std.line;
21 
22 import dyaml.all;
23 
24 class ArgScope : Container
25 {
26 	private Line[] lines;
27 	
28 	this(Type t)
29 	{
30 		lines = new Line[0];
31 		super( t );
32 	}
33 
34 	override @property string tostring(uint depth=0)
35 	{
36 		string ret = "";
37 		
38 		foreach( l; lines )
39 		{
40 			ret ~= l.tostring(depth) ~ to!char(0x0A);
41 		}
42 		
43 		return ret;
44 	}
45 
46 	override void randomChange()
47 	{
48 		
49 	}
50 	
51 	override void randomChange(string maxChange)
52 	{
53 		
54 	}
55 	
56 	override Argument getRandomElement()
57 	{
58 		return lines[uniform(0, lines.length)];
59 	}
60 	
61 	override Argument getRandomElement(double[] chances)
62 	{
63 		Argument ret;
64 		randomRange!(
65 			(int k)
66 			{
67 				ret = lines[k];
68 			}
69 			)(chances[0..lines.length]);
70 		return ret;
71 	}
72 	
73 	override void replaceRandomElement(Argument narg)
74 	{
75 		if (cast(Line)(narg) is null) return;
76 		lines[uniform(0, lines.length)] = cast(Line)(narg);
77 	}
78 	
79 	override void replaceRandomElement(double[] chances, Argument narg)
80 	{
81 		if (cast(Line)(narg) is null) return;
82 		randomRange!(
83 			(int k)
84 			{
85 				lines[k] = cast(Line)(narg);
86 			}
87 			)(chances[0..lines.length]);		
88 	}
89 	
90 	override void replaceRandomElement(Argument delegate(Type t) del)
91 	{
92 		auto i = uniform(0, lines.length);
93 		Line l = cast(Line)del( lines[i].operator.rtype );
94 		if (l !is null)
95 			lines[ i ] = l;
96 	}
97 	
98 	override void replaceRandomElement(Argument delegate(Type t) del, double[] chances)
99 	{
100 		randomRange!((int k)
101 			{
102 				Line l = cast(Line)del( lines[k].operator.rtype );
103 				if (l !is null)
104 					lines[k] = l;
105 			})(chances[0..lines.length]);		
106 	}
107 	
108 	override Argument getRandomLeaf()
109 	{
110 		return null;
111 	}
112 	
113 	override Argument getRandomLeaf(double[] chances)
114 	{
115 		return null;
116 	}
117 	
118 	override uint getLeafCount()
119 	{
120 		return 0;
121 	}
122 	
123 	override void addElement( Argument arg )
124 	{
125 		auto l = cast(Line)arg;
126 		if (l is null) return;
127 		lines ~= l;
128 	}
129 	
130 	override void removeElement(size_t i)
131 	{
132 		if (i>0 && i<lines.length) return;
133 		lines.remove(i);
134 	}
135 	
136 	override void removeAll()
137 	{
138 		lines.clear();
139 	}
140 
141 
142 	override Line opIndex( size_t i )
143 	{
144 		return lines[i];
145 	}
146 	
147 	int opApply(int delegate(Line) dg)
148 	{
149 		int result = 0;
150 		
151 		foreach( i, l; lines)
152 		{
153 			result = dg(l);
154 			if (result) break;
155 		}
156 		return result;
157 	}
158 	
159 	override int opApply(int delegate(Argument) dg)
160 	{
161 		int result = 0;
162 		
163 		foreach( i, l; lines)
164 		{
165 			result = dg(l);
166 			if (result) break;
167 		}
168 		return result;
169 	}
170 	
171 	override @property ulong children()
172 	{
173 		ulong res = 1;
174 		foreach( l; lines)
175 			res+=l.children;
176 		return res;
177 	}
178 	
179 	override @property ulong leafs()
180 	{
181 	    if(lines.length == 0) return 1;
182 	    
183 		ulong res = 0;
184 		foreach( l; lines)
185 			res+=l.children;
186 		return res;
187 	}
188 	
189 	override @property Argument dup()
190 	{
191 		auto dscope = new ArgScope(type);
192 		
193 		foreach(l; lines)
194 			dscope.lines ~= l.dup();
195 			
196 		return dscope;
197 	}
198 	
199 	override void opIndexAssign( Argument val, size_t i )
200 	{
201 		auto l = cast(Line)(val);
202 		if (l !is null)
203 			lines[i] = l;
204 	}
205 	
206 	override Argument[] opSlice( size_t a, size_t b )
207 	{
208 		return cast(Argument[])lines[a .. b];
209 	}
210 	
211 	override size_t opDollar()
212 	{
213 		return lines.length;
214 	}
215 	
216 	override @property size_t length()
217 	{
218 		return lines.length;
219 	}
220 	
221 	static ArgScope loadBinary(InputStream stream)
222 	{
223 	    ulong length;
224 	    stream.read(length);
225 	    
226 	    auto ascope = new ArgScope(TypeMng.getSingleton().getType("TypeVoid"));
227 	    
228 	    foreach(i; 0..cast(size_t)length)
229 	    {
230 	        char[] mark;
231 	        stream.read(mark);
232 	        assert(mark.idup == "line");
233 	        
234 	        ascope.addElement(Line.loadBinary(stream));
235 	    }
236 	    return ascope;
237 	}
238 	
239 	static Argument loadYaml(Node node)
240 	{
241 	    auto ascope = new ArgScope(TypeMng.getSingleton().getType("TypeVoid"));
242 	    
243 	    foreach(Node subnode; node["lines"])
244 	    {
245 	        ascope.addElement(Line.loadYaml(subnode));
246 	    }
247 	    return ascope;
248 	}
249 	
250 	void saveBinary(OutputStream stream)
251 	{
252 	    stream.write("scope");
253 	    
254 	    stream.write(cast(ulong)lines.length);
255 	    foreach(line; lines)
256 	    {
257 	        line.saveBinary(stream);
258 	    }
259 	}
260 	
261 	override Node saveYaml()
262 	{
263 	    auto builder = appender!(Node[]);
264 	    foreach(line; lines)
265 	    {
266 	        builder.put(line.saveYaml());
267 	    }
268 	    
269 	    auto map = [
270             "class": Node("scope")
271             ];
272             
273         if(builder.data.length > 0)
274         {
275             map["lines"] = Node(builder.data);
276         }
277         
278 	    return Node(map);
279 	}
280 	
281 	override string genDot(ref size_t nameIndex, out string nodeName)
282 	{
283 		auto builder = appender!string;
284 		
285 		nodeName = "p"~to!string(nameIndex++);
286 		
287 		builder.put(nodeName);
288 		builder.put("; \n");
289 		
290 		builder.put(nodeName);
291 		builder.put("[label=\"");
292 		builder.put("scope");
293 		builder.put("\"] ;\n");
294 		
295 		foreach(line; lines)
296 		{
297 			string lineNode;
298 			builder.put(line.genDot(nameIndex, lineNode));
299 			
300 			builder.put(nodeName);
301 			builder.put(" -> ");
302 			builder.put(lineNode);
303 			builder.put(";\n");
304 		}
305 		
306 		return builder.data;
307 	}
308 }