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.operator;
9 
10 import std..string;
11 import std.conv;
12 import std.array;
13 
14 import devol.type;
15 import devol.argument;
16 import devol.std.line;
17 import devol.world;
18 import devol.individ;
19 import devol.serializable;
20 import devol.operatormng;
21 
22 import dyaml.all;    
23 
24 enum ArgsStyle
25 {
26 	CLASSIC_STYLE,
27 	MASS_STYLE,
28 	BINAR_STYLE,
29 	UNAR_STYLE,
30 	NULAR_STYLE,
31 	CONTROL_STYLE
32 }
33 
34 struct ArgInfo
35 {
36 	Type type;
37 	string[] exVals;
38 	string min;
39 	string max;
40 	bool eval = true;
41 }
42 
43 abstract class Operator : ISerializable
44 {
45 	this(string name, string discr, ArgsStyle style)
46 	{
47 		sName = name;
48 		sDiscr = discr;
49 		mStyle = style;
50 		
51 		args = new ArgInfo[0];
52 		
53 		assert(mRetType,"Return type isn't set!");
54 	}
55 	
56 	@property int argsNumber()
57 	{
58 		return cast(uint)(args.length);
59 	}
60 	
61 	@property ArgsStyle style()
62 	{
63 		return mStyle;
64 	}
65 	
66 	@property string name()
67 	{
68 		return sName;
69 	}
70 	
71 	@property string disrc()
72 	{
73 		return sDiscr;
74 	}
75 	
76 	@property Type rtype()
77 	{
78 		return mRetType;
79 	}
80 	
81 	ArgInfo opIndex( size_t i )
82 	{
83 		return args[i];
84 	}
85 	
86 	ArgInfo[] opSlice( size_t a, size_t b )
87 	{
88 		return args[a..b];
89 	}
90 	
91 	size_t opDollar()
92 	{
93 		return args.length;
94 	}
95 	
96 	int opApply(int delegate(ref ArgInfo) dg)
97 	{
98 		int result = 0;
99 		
100 		foreach( i, ref arg; args)
101 		{
102 			result = dg(arg);
103 			if (result) break;
104 		}
105 		return result;
106 	}
107 	
108 	Argument generateArg( size_t i )
109 	{	
110 		auto ainfo = args[i];
111 		return ainfo.type.getNewArg(ainfo.min, ainfo.max, ainfo.exVals);
112 	}
113 	
114 	Argument apply(IndAbstract ind, Line line, WorldAbstract world)
115 	in
116 	{
117 		assert( line.length == args.length, text("Critical error: operator ", name, ", got args count is ", line.length, " but needed ", args.length, "!"));
118 		foreach(i,ai; args)
119 		{
120 			assert( ai.type.name == line[0].type.name, text("Critical error: operator ", name, ", argument №", i, " is type of ", ai.type.name, " but needed ", line[0].type.name, "!"));
121 		}
122 	}
123 	out(result)
124 	{
125 		assert( result !is null, text("Critical error: operator ", name, ", return value is null! Forgotten to overload std apply?")); 
126 	}
127 	body
128 	{
129 		return null;
130 	}
131 	
132 	void saveBinary(OutputStream stream)
133 	{
134 	    assert(sName != "", "Operator name is empty string!");
135 	    stream.write(sName);
136 	}
137 	
138 	Node saveYaml()
139 	{
140 	    return Node(sName);
141 	}
142 	
143 	static Operator loadBinary(InputStream stream)
144 	{
145 	    char[] opname;
146 	    stream.read(opname);
147 	    
148 	    return OperatorMng.getSingleton().getOperator(opname.idup);
149 	}
150 	
151 	static Operator loadYaml(Node node)
152 	{
153 	    return OperatorMng.getSingleton().getOperator(node.as!string);
154 	}
155 	
156 	string genDot(ref size_t nameIndex, out string nodeName)
157 	{
158 		auto builder = appender!string;
159 		nodeName = "p"~to!string(nameIndex++);
160 		
161 		builder.put(nodeName);
162 		builder.put("; \n");
163 		
164 		builder.put(nodeName);
165 		builder.put("[label=\"");
166 		builder.put(sName);
167 		builder.put("\"] ;\n");
168 		
169 		return builder.data;
170 	}
171 	
172 protected:
173 	ArgInfo[] args;
174 	ArgsStyle mStyle;
175 	string sName;
176 	string sDiscr;
177 	Type mRetType;
178 }