]> arthur.barton.de Git - netdata.git/blob - profile/test-eval.c
operational evaluator for expressions
[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 -pthread
7  *
8  */
9
10 #include "common.h"
11
12 void netdata_cleanup_and_exit(int ret) { exit(ret); }
13
14 void indent(int level, int show) {
15         int i = level;
16         while(i--) printf(" |  ");
17         if(show) printf(" \\_ ");
18         else printf(" \\_  ");
19 }
20
21 void print_operand(EVAL_OPERAND *op, int level);
22
23 void print_value(EVAL_VALUE *v, int level) {
24         indent(level, 0);
25
26         switch(v->type) {
27                 case EVAL_VALUE_INVALID:
28                         printf("VALUE (NOP)\n");
29                         break;
30
31                 case EVAL_VALUE_NUMBER:
32                         printf("VALUE %Lf (NUMBER)\n", v->number);
33                         break;
34
35                 case EVAL_VALUE_EXPRESSION:
36                         printf("VALUE (SUB-EXPRESSION)\n");
37                         print_operand(v->expression, level+1);
38                         break;
39
40                 default:
41                         printf("VALUE (INVALID type %d)\n", v->type);
42                         break;
43
44         }
45 }
46
47 void print_operand(EVAL_OPERAND *op, int level) {
48
49 //      if(op->operator != EVAL_OPERATOR_NOP) {
50                 indent(level, 1);
51                 if(op->operator) printf("%c (OPERATOR %d, prec: %d)\n", op->operator, op->id, op->precedence);
52                 else printf("NOP (OPERATOR %d, prec: %d)\n", op->id, op->precedence);
53 //      }
54
55         int i = op->count;
56         while(i--) print_value(&op->ops[i], level + 1);
57 }
58
59 calculated_number evaluate(EVAL_OPERAND *op, int depth);
60
61 calculated_number evaluate_value(EVAL_VALUE *v, int depth) {
62         switch(v->type) {
63                 case EVAL_VALUE_NUMBER:
64                         return v->number;
65
66                 case EVAL_VALUE_EXPRESSION:
67                         return evaluate(v->expression, depth);
68
69                 default:
70                         fatal("I don't know how to handle EVAL_VALUE type %d", v->type);
71         }
72 }
73
74 void print_depth(int depth) {
75         static int count = 0;
76
77         printf("%d. ", ++count);
78         while(depth--) printf("    ");
79 }
80
81 calculated_number evaluate(EVAL_OPERAND *op, int depth) {
82         calculated_number n1, n2, r;
83
84         switch(op->operator) {
85                 case EVAL_OPERATOR_SIGN_PLUS:
86                         r = evaluate_value(&op->ops[0], depth);
87                         break;
88
89                 case EVAL_OPERATOR_SIGN_MINUS:
90                         r = -evaluate_value(&op->ops[0], depth);
91                         break;
92
93                 case EVAL_OPERATOR_PLUS:
94                         if(op->count != 2)
95                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
96                         n1 = evaluate_value(&op->ops[0], depth);
97                         n2 = evaluate_value(&op->ops[1], depth);
98                         r = n1 + n2;
99                         print_depth(depth);
100                         printf("%Lf = %Lf + %Lf\n", r, n1, n2);
101                         break;
102
103                 case EVAL_OPERATOR_MINUS:
104                         if(op->count != 2)
105                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
106                         n1 = evaluate_value(&op->ops[0], depth);
107                         n2 = evaluate_value(&op->ops[1], depth);
108                         r = n1 - n2;
109                         print_depth(depth);
110                         printf("%Lf = %Lf - %Lf\n", r, n1, n2);
111                         break;
112
113                 case EVAL_OPERATOR_MULTIPLY:
114                         if(op->count != 2)
115                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
116                         n1 = evaluate_value(&op->ops[0], depth);
117                         n2 = evaluate_value(&op->ops[1], depth);
118                         r = n1 * n2;
119                         print_depth(depth);
120                         printf("%Lf = %Lf * %Lf\n", r, n1, n2);
121                         break;
122
123                 case EVAL_OPERATOR_DIVIDE:
124                         if(op->count != 2)
125                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
126                         n1 = evaluate_value(&op->ops[0], depth);
127                         n2 = evaluate_value(&op->ops[1], depth);
128                         r = n1 / n2;
129                         print_depth(depth);
130                         printf("%Lf = %Lf / %Lf\n", r, n1, n2);
131                         break;
132
133                 case EVAL_OPERATOR_NOT:
134                         n1 = evaluate_value(&op->ops[0], depth);
135                         r = !n1;
136                         print_depth(depth);
137                         printf("%Lf = NOT %Lf\n", r, n1);
138                         break;
139
140                 case EVAL_OPERATOR_AND:
141                         if(op->count != 2)
142                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
143                         n1 = evaluate_value(&op->ops[0], depth);
144                         n2 = evaluate_value(&op->ops[1], depth);
145                         r = n1 && n2;
146                         print_depth(depth);
147                         printf("%Lf = %Lf AND %Lf\n", r, n1, n2);
148                         break;
149
150                 case EVAL_OPERATOR_OR:
151                         if(op->count != 2)
152                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
153                         n1 = evaluate_value(&op->ops[0], depth);
154                         n2 = evaluate_value(&op->ops[1], depth);
155                         r = n1 || n2;
156                         print_depth(depth);
157                         printf("%Lf = %Lf OR %Lf\n", r, n1, n2);
158                         break;
159
160                 case EVAL_OPERATOR_GREATER_THAN_OR_EQUAL:
161                         if(op->count != 2)
162                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
163                         n1 = evaluate_value(&op->ops[0], depth);
164                         n2 = evaluate_value(&op->ops[1], depth);
165                         r = n1 >= n2;
166                         print_depth(depth);
167                         printf("%Lf = %Lf >= %Lf\n", r, n1, n2);
168                         break;
169
170                 case EVAL_OPERATOR_LESS_THAN_OR_EQUAL:
171                         if(op->count != 2)
172                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
173                         n1 = evaluate_value(&op->ops[0], depth);
174                         n2 = evaluate_value(&op->ops[1], depth);
175                         r = n1 <= n2;
176                         print_depth(depth);
177                         printf("%Lf = %Lf <= %Lf\n", r, n1, n2);
178                         break;
179
180                 case EVAL_OPERATOR_GREATER:
181                         if(op->count != 2)
182                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
183                         n1 = evaluate_value(&op->ops[0], depth);
184                         n2 = evaluate_value(&op->ops[1], depth);
185                         r = n1 > n2;
186                         print_depth(depth);
187                         printf("%Lf = %Lf > %Lf\n", r, n1, n2);
188                         break;
189
190                 case EVAL_OPERATOR_LESS:
191                         if(op->count != 2)
192                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
193                         n1 = evaluate_value(&op->ops[0], depth);
194                         n2 = evaluate_value(&op->ops[1], depth);
195                         r = n1 < n2;
196                         print_depth(depth);
197                         printf("%Lf = %Lf < %Lf\n", r, n1, n2);
198                         break;
199
200                 case EVAL_OPERATOR_NOT_EQUAL:
201                         if(op->count != 2)
202                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
203                         n1 = evaluate_value(&op->ops[0], depth);
204                         n2 = evaluate_value(&op->ops[1], depth);
205                         r = n1 != n2;
206                         print_depth(depth);
207                         printf("%Lf = %Lf <> %Lf\n", r, n1, n2);
208                         break;
209
210                 case EVAL_OPERATOR_EQUAL:
211                         if(op->count != 2)
212                                 fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
213                         n1 = evaluate_value(&op->ops[0], depth);
214                         n2 = evaluate_value(&op->ops[1], depth);
215                         r = n1 == n2;
216                         print_depth(depth);
217                         printf("%Lf = %Lf == %Lf\n", r, n1, n2);
218                         break;
219
220                 case EVAL_OPERATOR_EXPRESSION_OPEN:
221                         printf("BEGIN SUB-EXPRESSION\n");
222                         r = evaluate_value(&op->ops[0], depth + 1);
223                         printf("END SUB-EXPRESSION\n");
224                         break;
225
226                 case EVAL_OPERATOR_NOP:
227                 case EVAL_OPERATOR_VALUE:
228                         r = evaluate_value(&op->ops[0], depth);
229                         break;
230
231                 default:
232                         error("I don't know how to handle operator '%c'", op->operator);
233                         r = 0;
234                         break;
235         }
236
237         return r;
238 }
239
240 void print_expression(EVAL_OPERAND *op, const char *failed_at, int error) {
241         if(op) {
242                 printf("expression tree:\n");
243                 print_operand(op, 0);
244
245                 printf("\nevaluation steps:\n");
246                 evaluate(op, 0);
247                 
248                 int error;
249                 calculated_number ret = evaluate_expression(op, &error);
250                 printf("\ninternal evaluator:\nSTATUS: %d, RESULT = %Lf\n", error, ret);
251
252                 free_expression(op);
253         }
254         else {
255                 printf("error: %d, failed_at: '%s'\n", error, (failed_at)?failed_at:"<NONE>");
256         }
257 }
258
259
260 int main(int argc, char **argv) {
261         if(argc != 2) {
262                 fprintf(stderr, "I need an epxression\n");
263                 exit(1);
264         }
265
266         const char *failed_at = NULL;
267         int error;
268         EVAL_OPERAND *op = parse_expression(argv[1], &failed_at, &error);
269         print_expression(op, failed_at, error);
270         return 0;
271 }