master
c 288 lines 7.73 KB
Raw
1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2
3 /*
4 * 1. build netdata (as normally)
5 * 2. cd profile/
6 * 3. compile with:
7 * gcc -O1 -ggdb -Wall -Wextra -I ../src/ -I ../ -o test-eval test-eval.c ../src/log.o ../src/eval.o ../src/common.o ../src/clocks.o ../src/web_buffer.o ../src/storage_number.o -pthread -lm
8 */
9
10 #include "config.h"
11 #include "libnetdata/libnetdata.h"
12 #include "health/rrdcalc.h"
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 NETDATA_DOUBLE evaluate(EVAL_NODE *op, int depth);
61
62 NETDATA_DOUBLE 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 NETDATA_DOUBLE evaluate(EVAL_NODE *op, int depth) {
83 NETDATA_DOUBLE 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 netdata_log_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 NETDATA_DOUBLE 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 main(int argc, char **argv) {
263 if(argc != 2) {
264 fprintf(stderr, "I need an expression (enclose it in single-quotes (') as a single parameter)\n");
265 exit(1);
266 }
267
268 const char *failed_at = NULL;
269 int error;
270
271 EVAL_EXPRESSION *exp = expression_parse(argv[1], &failed_at, &error);
272 if(!exp)
273 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));
274
275 else {
276 printf("\nPARSING OK\nExpression: '%s'\nParsed as : '%s'\nParsing error code: %d (%s)\n", argv[1], exp->parsed_as, error, expression_strerror(error));
277
278 if(expression_evaluate(exp)) {
279 printf("\nEvaluates to: %Lf\n\n", exp->result);
280 }
281 else {
282 printf("\nEvaluation failed with code %d and message: %s\n\n", exp->error, buffer_tostring(exp->error_msg));
283 }
284 expression_free(exp);
285 }
286
287 return 0;
288 }