1 module orelang.operator.DynamicOperator; 2 import orelang.operator.IOperator, orelang.Engine, orelang.Value; 3 import kontainer.orderedAssocArray; 4 5 /** 6 * Dynamic Operator 7 */ 8 9 class DynamicOperator : IOperator { 10 private { 11 string[] funcArgs; 12 Value funcBody; 13 OrderedAssocArray!(string, Value) optionArgs; 14 } 15 16 this(string[] funcArgs, Value funcBody) { 17 this.funcArgs = funcArgs; 18 this.funcBody = funcBody; 19 this.optionArgs = new OrderedAssocArray!(string, Value); 20 } 21 22 this(string[] funcArgs, Value funcBody, OrderedAssocArray!(string, Value) optionArgs) { 23 this.funcArgs = funcArgs; 24 this.funcBody = funcBody; 25 this.optionArgs = optionArgs; 26 } 27 28 public Value call(Engine engine, Value[] args) { 29 size_t i = 0; 30 Engine _engine = engine.clone; 31 32 size_t allFuncArgs = this.optionArgs.length + this.funcArgs.length; 33 34 if (this.funcArgs.length < args.length && args.length <= allFuncArgs) { 35 size_t j; 36 size_t orders = args.length - this.funcArgs.length; 37 foreach (arg; this.optionArgs) { 38 if (j < orders) { 39 _engine.defineVariable(arg.key, engine.eval(args[i++])); 40 } else { 41 _engine.defineVariable(arg.key, engine.eval(arg.value)); 42 } 43 j++; 44 } 45 } else { 46 foreach (arg; this.optionArgs) { 47 _engine.defineVariable(arg.key, engine.eval(arg.value)); 48 } 49 } 50 51 foreach (arg; this.funcArgs) { 52 // variadic args 53 if (arg[0] == '&') { 54 Value[] arr; 55 56 arr = args[i .. $]; 57 58 _engine.defineVariable(arg[1 .. $], new Value(arr)); 59 break; 60 } else { 61 _engine.defineVariable(arg, engine.eval(args[i++])); 62 } 63 } 64 65 return _engine.eval(this.funcBody); 66 } 67 68 override string toString() { 69 string base = "orelang.operator.DynamicOperator.DynamicOperator {"; 70 import std..string; 71 72 string _body = "[funcArgs : [" ~ funcArgs.join( 73 ", ") ~ "], " ~ "funcBody : " ~ funcBody.toString ~ "]"; 74 75 return base ~ _body ~ "}"; 76 } 77 }