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 }