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 }