]> arthur.barton.de Git - netdata.git/blob - profile/test-eval.c
Merge pull request #2021 from ktsaou/master
[netdata.git] / profile / test-eval.c
1
2 /*
3  * 1. build netdata (as normally)
4  * 2. cd profile/
5  * 3. compile with:
6  *    gcc -O1 -ggdb -Wall -Wextra -I ../src/ -I ../ -o test-eval test-eval.c ../src/log.o ../src/eval.o ../src/common.o ../src/web_buffer.o ../src/storage_number.o -pthread -lm
7  *
8  */
9
10 #include "common.h"
11
12 void netdata_cleanup_and_exit(int ret) { exit(ret); }
13
14 /*
15 void indent(int level, int show) {
16         int i = level;
17         while(i--) printf(" |  ");
18         if(show) printf(" \\_ ");
19         else printf(" \\_  ");
20 }
21
22 void print_node(EVAL_NODE *op, int level);
23
24 void print_value(EVAL_VALUE *v, int level) {
25         indent(level, 0);
26
27         switch(v->type) {
28                 case EVAL_VALUE_INVALID:
29                         printf("value (NOP)\n");
30                         break;
31
32                 case EVAL_VALUE_NUMBER:
33                         printf("value %Lf (NUMBER)\n", v->number);
34                         break;
35
36                 case EVAL_VALUE_EXPRESSION:
37                         printf("value (SUB-EXPRESSION)\n");
38                         print_node(v->expression, level+1);
39                         break;
40
41                 default:
42                         printf("value (INVALID type %d)\n", v->type);
43                         break;
44
45         }
46 }
47
48 void print_node(EVAL_NODE *op, int level) {
49
50 //      if(op->operator != EVAL_OPERATOR_NOP) {
51                 indent(level, 1);
52                 if(op->operator) printf("%c (node %d, precedence: %d)\n", op->operator, op->id, op->precedence);
53                 else printf("NOP (node %d, precedence: %d)\n", op->id, op->precedence);
54 //      }
55
56         int i = op->count;
57         while(i--) print_value(&op->ops[i], level + 1);
58 }
59
60 calculated_number evaluate(EVAL_NODE *op, int depth);
61
62 calculated_number evaluate_value(EVAL_VALUE *v, int depth) {
63         switch(v->type) {
64                 case EVAL_VALUE_NUMBER:
65                         return v->number;
66
67                 case EVAL_VALUE_EXPRESSION:
68                         return evaluate(v->expression, depth);
69
70                 default:
71                         fatal("I don't know how to handle EVAL_VALUE type %d", v->type);
72         }
73 }
74
75 void print_depth(int depth) {
76         static int count = 0;
77
78         printf("%d. ", ++count);
79         while(depth--) printf("    ");
80 }
81
82 calculated_number evaluate(EVAL_NODE *op, int depth) {
83         calculated_number n1, n2, r;
84
85         switch(op->operator) {
86                 case EVAL_OPERATOR_SIGN_PLUS:
87                         r = evaluate_value(&op->ops[0], depth);
88                         break;
89
90                 case EVAL_OPERATOR_SIGN_MINUS:
91                         r = -evaluate_value(&op->ops[0], depth);
92                         break;
93
94                 case EVAL_OPERATOR_PLUS:
95                         if(op->count != 2)
96                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
97                         n1 = evaluate_value(&op->ops[0], depth);
98                         n2 = evaluate_value(&op->ops[1], depth);
99                         r = n1 + n2;
100                         print_depth(depth);
101                         printf("%Lf = %Lf + %Lf\n", r, n1, n2);
102                         break;
103
104                 case EVAL_OPERATOR_MINUS:
105                         if(op->count != 2)
106                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
107                         n1 = evaluate_value(&op->ops[0], depth);
108                         n2 = evaluate_value(&op->ops[1], depth);
109                         r = n1 - n2;
110                         print_depth(depth);
111                         printf("%Lf = %Lf - %Lf\n", r, n1, n2);
112                         break;
113
114                 case EVAL_OPERATOR_MULTIPLY:
115                         if(op->count != 2)
116                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
117                         n1 = evaluate_value(&op->ops[0], depth);
118                         n2 = evaluate_value(&op->ops[1], depth);
119                         r = n1 * n2;
120                         print_depth(depth);
121                         printf("%Lf = %Lf * %Lf\n", r, n1, n2);
122                         break;
123
124                 case EVAL_OPERATOR_DIVIDE:
125                         if(op->count != 2)
126                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
127                         n1 = evaluate_value(&op->ops[0], depth);
128                         n2 = evaluate_value(&op->ops[1], depth);
129                         r = n1 / n2;
130                         print_depth(depth);
131                         printf("%Lf = %Lf / %Lf\n", r, n1, n2);
132                         break;
133
134                 case EVAL_OPERATOR_NOT:
135                         n1 = evaluate_value(&op->ops[0], depth);
136                         r = !n1;
137                         print_depth(depth);
138                         printf("%Lf = NOT %Lf\n", r, n1);
139                         break;
140
141                 case EVAL_OPERATOR_AND:
142                         if(op->count != 2)
143                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
144                         n1 = evaluate_value(&op->ops[0], depth);
145                         n2 = evaluate_value(&op->ops[1], depth);
146                         r = n1 && n2;
147                         print_depth(depth);
148                         printf("%Lf = %Lf AND %Lf\n", r, n1, n2);
149                         break;
150
151                 case EVAL_OPERATOR_OR:
152                         if(op->count != 2)
153                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
154                         n1 = evaluate_value(&op->ops[0], depth);
155                         n2 = evaluate_value(&op->ops[1], depth);
156                         r = n1 || n2;
157                         print_depth(depth);
158                         printf("%Lf = %Lf OR %Lf\n", r, n1, n2);
159                         break;
160
161                 case EVAL_OPERATOR_GREATER_THAN_OR_EQUAL:
162                         if(op->count != 2)
163                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
164                         n1 = evaluate_value(&op->ops[0], depth);
165                         n2 = evaluate_value(&op->ops[1], depth);
166                         r = n1 >= n2;
167                         print_depth(depth);
168                         printf("%Lf = %Lf >= %Lf\n", r, n1, n2);
169                         break;
170
171                 case EVAL_OPERATOR_LESS_THAN_OR_EQUAL:
172                         if(op->count != 2)
173                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
174                         n1 = evaluate_value(&op->ops[0], depth);
175                         n2 = evaluate_value(&op->ops[1], depth);
176                         r = n1 <= n2;
177                         print_depth(depth);
178                         printf("%Lf = %Lf <= %Lf\n", r, n1, n2);
179                         break;
180
181                 case EVAL_OPERATOR_GREATER:
182                         if(op->count != 2)
183                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
184                         n1 = evaluate_value(&op->ops[0], depth);
185                         n2 = evaluate_value(&op->ops[1], depth);
186                         r = n1 > n2;
187                         print_depth(depth);
188                         printf("%Lf = %Lf > %Lf\n", r, n1, n2);
189                         break;
190
191                 case EVAL_OPERATOR_LESS:
192                         if(op->count != 2)
193                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
194                         n1 = evaluate_value(&op->ops[0], depth);
195                         n2 = evaluate_value(&op->ops[1], depth);
196                         r = n1 < n2;
197                         print_depth(depth);
198                         printf("%Lf = %Lf < %Lf\n", r, n1, n2);
199                         break;
200
201                 case EVAL_OPERATOR_NOT_EQUAL:
202                         if(op->count != 2)
203                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
204                         n1 = evaluate_value(&op->ops[0], depth);
205                         n2 = evaluate_value(&op->ops[1], depth);
206                         r = n1 != n2;
207                         print_depth(depth);
208                         printf("%Lf = %Lf <> %Lf\n", r, n1, n2);
209                         break;
210
211                 case EVAL_OPERATOR_EQUAL:
212                         if(op->count != 2)
213                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
214                         n1 = evaluate_value(&op->ops[0], depth);
215                         n2 = evaluate_value(&op->ops[1], depth);
216                         r = n1 == n2;
217                         print_depth(depth);
218                         printf("%Lf = %Lf == %Lf\n", r, n1, n2);
219                         break;
220
221                 case EVAL_OPERATOR_EXPRESSION_OPEN:
222                         printf("BEGIN SUB-EXPRESSION\n");
223                         r = evaluate_value(&op->ops[0], depth + 1);
224                         printf("END SUB-EXPRESSION\n");
225                         break;
226
227                 case EVAL_OPERATOR_NOP:
228                 case EVAL_OPERATOR_VALUE:
229                         r = evaluate_value(&op->ops[0], depth);
230                         break;
231
232                 default:
233                         error("I don't know how to handle operator '%c'", op->operator);
234                         r = 0;
235                         break;
236         }
237
238         return r;
239 }
240
241
242 void print_expression(EVAL_NODE *op, const char *failed_at, int error) {
243         if(op) {
244                 printf("expression tree:\n");
245                 print_node(op, 0);
246
247                 printf("\nevaluation steps:\n");
248                 evaluate(op, 0);
249                 
250                 int error;
251                 calculated_number ret = expression_evaluate(op, &error);
252                 printf("\ninternal evaluator:\nSTATUS: %d, RESULT = %Lf\n", error, ret);
253
254                 expression_free(op);
255         }
256         else {
257                 printf("error: %d, failed_at: '%s'\n", error, (failed_at)?failed_at:"<NONE>");
258         }
259 }
260 */
261
262 int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result) {
263         (void)variable;
264         (void)hash;
265         (void)rc;
266         (void)result;
267
268         return 0;
269 }
270
271 int main(int argc, char **argv) {
272         if(argc != 2) {
273                 fprintf(stderr, "I need an epxression (enclose it in single-quotes (') as a single parameter)\n");
274                 exit(1);
275         }
276
277         const char *failed_at = NULL;
278         int error;
279
280         EVAL_EXPRESSION *exp = expression_parse(argv[1], &failed_at, &error);
281         if(!exp)
282                 printf("\nPARSING FAILED\nExpression: '%s'\nParsing stopped at: '%s'\nParsing error code: %d (%s)\n", argv[1], (failed_at)?((*failed_at)?failed_at:"<END OF EXPRESSION>"):"<NONE>", error, expression_strerror(error));
283         
284         else {
285                 printf("\nPARSING OK\nExpression: '%s'\nParsed as : '%s'\nParsing error code: %d (%s)\n", argv[1], exp->parsed_as, error, expression_strerror(error));
286
287                 if(expression_evaluate(exp)) {
288                         printf("\nEvaluates to: %Lf\n\n", exp->result);
289                 }
290                 else {
291                         printf("\nEvaluation failed with code %d and message: %s\n\n", exp->error, buffer_tostring(exp->error_msg));
292                 }
293                 expression_free(exp);
294         }
295
296         return 0;
297 }