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 }