test-eval.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /* SPDX-License-Identifier: GPL-3.0-or-later */
  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/clocks.o ../src/web_buffer.o ../src/storage_number.o -pthread -lm
  7. */
  8. #include "config.h"
  9. #include "libnetdata/libnetdata.h"
  10. #include "libnetdata/required_dummies.h"
  11. #include "health/rrdcalc.h"
  12. /*
  13. void indent(int level, int show) {
  14. int i = level;
  15. while(i--) printf(" | ");
  16. if(show) printf(" \\_ ");
  17. else printf(" \\_ ");
  18. }
  19. void print_node(EVAL_NODE *op, int level);
  20. void print_value(EVAL_VALUE *v, int level) {
  21. indent(level, 0);
  22. switch(v->type) {
  23. case EVAL_VALUE_INVALID:
  24. printf("value (NOP)\n");
  25. break;
  26. case EVAL_VALUE_NUMBER:
  27. printf("value %Lf (NUMBER)\n", v->number);
  28. break;
  29. case EVAL_VALUE_EXPRESSION:
  30. printf("value (SUB-EXPRESSION)\n");
  31. print_node(v->expression, level+1);
  32. break;
  33. default:
  34. printf("value (INVALID type %d)\n", v->type);
  35. break;
  36. }
  37. }
  38. void print_node(EVAL_NODE *op, int level) {
  39. // if(op->operator != EVAL_OPERATOR_NOP) {
  40. indent(level, 1);
  41. if(op->operator) printf("%c (node %d, precedence: %d)\n", op->operator, op->id, op->precedence);
  42. else printf("NOP (node %d, precedence: %d)\n", op->id, op->precedence);
  43. // }
  44. int i = op->count;
  45. while(i--) print_value(&op->ops[i], level + 1);
  46. }
  47. NETDATA_DOUBLE evaluate(EVAL_NODE *op, int depth);
  48. NETDATA_DOUBLE evaluate_value(EVAL_VALUE *v, int depth) {
  49. switch(v->type) {
  50. case EVAL_VALUE_NUMBER:
  51. return v->number;
  52. case EVAL_VALUE_EXPRESSION:
  53. return evaluate(v->expression, depth);
  54. default:
  55. fatal("I don't know how to handle EVAL_VALUE type %d", v->type);
  56. }
  57. }
  58. void print_depth(int depth) {
  59. static int count = 0;
  60. printf("%d. ", ++count);
  61. while(depth--) printf(" ");
  62. }
  63. NETDATA_DOUBLE evaluate(EVAL_NODE *op, int depth) {
  64. NETDATA_DOUBLE n1, n2, r;
  65. switch(op->operator) {
  66. case EVAL_OPERATOR_SIGN_PLUS:
  67. r = evaluate_value(&op->ops[0], depth);
  68. break;
  69. case EVAL_OPERATOR_SIGN_MINUS:
  70. r = -evaluate_value(&op->ops[0], depth);
  71. break;
  72. case EVAL_OPERATOR_PLUS:
  73. if(op->count != 2)
  74. fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
  75. n1 = evaluate_value(&op->ops[0], depth);
  76. n2 = evaluate_value(&op->ops[1], depth);
  77. r = n1 + n2;
  78. print_depth(depth);
  79. printf("%Lf = %Lf + %Lf\n", r, n1, n2);
  80. break;
  81. case EVAL_OPERATOR_MINUS:
  82. if(op->count != 2)
  83. fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
  84. n1 = evaluate_value(&op->ops[0], depth);
  85. n2 = evaluate_value(&op->ops[1], depth);
  86. r = n1 - n2;
  87. print_depth(depth);
  88. printf("%Lf = %Lf - %Lf\n", r, n1, n2);
  89. break;
  90. case EVAL_OPERATOR_MULTIPLY:
  91. if(op->count != 2)
  92. fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
  93. n1 = evaluate_value(&op->ops[0], depth);
  94. n2 = evaluate_value(&op->ops[1], depth);
  95. r = n1 * n2;
  96. print_depth(depth);
  97. printf("%Lf = %Lf * %Lf\n", r, n1, n2);
  98. break;
  99. case EVAL_OPERATOR_DIVIDE:
  100. if(op->count != 2)
  101. fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
  102. n1 = evaluate_value(&op->ops[0], depth);
  103. n2 = evaluate_value(&op->ops[1], depth);
  104. r = n1 / n2;
  105. print_depth(depth);
  106. printf("%Lf = %Lf / %Lf\n", r, n1, n2);
  107. break;
  108. case EVAL_OPERATOR_NOT:
  109. n1 = evaluate_value(&op->ops[0], depth);
  110. r = !n1;
  111. print_depth(depth);
  112. printf("%Lf = NOT %Lf\n", r, n1);
  113. break;
  114. case EVAL_OPERATOR_AND:
  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 AND %Lf\n", r, n1, n2);
  122. break;
  123. case EVAL_OPERATOR_OR:
  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 OR %Lf\n", r, n1, n2);
  131. break;
  132. case EVAL_OPERATOR_GREATER_THAN_OR_EQUAL:
  133. if(op->count != 2)
  134. fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
  135. n1 = evaluate_value(&op->ops[0], depth);
  136. n2 = evaluate_value(&op->ops[1], depth);
  137. r = n1 >= n2;
  138. print_depth(depth);
  139. printf("%Lf = %Lf >= %Lf\n", r, n1, n2);
  140. break;
  141. case EVAL_OPERATOR_LESS_THAN_OR_EQUAL:
  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 <= %Lf\n", r, n1, n2);
  149. break;
  150. case EVAL_OPERATOR_GREATER:
  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 > %Lf\n", r, n1, n2);
  158. break;
  159. case EVAL_OPERATOR_LESS:
  160. if(op->count != 2)
  161. fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
  162. n1 = evaluate_value(&op->ops[0], depth);
  163. n2 = evaluate_value(&op->ops[1], depth);
  164. r = n1 < n2;
  165. print_depth(depth);
  166. printf("%Lf = %Lf < %Lf\n", r, n1, n2);
  167. break;
  168. case EVAL_OPERATOR_NOT_EQUAL:
  169. if(op->count != 2)
  170. fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
  171. n1 = evaluate_value(&op->ops[0], depth);
  172. n2 = evaluate_value(&op->ops[1], depth);
  173. r = n1 != n2;
  174. print_depth(depth);
  175. printf("%Lf = %Lf <> %Lf\n", r, n1, n2);
  176. break;
  177. case EVAL_OPERATOR_EQUAL:
  178. if(op->count != 2)
  179. fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
  180. n1 = evaluate_value(&op->ops[0], depth);
  181. n2 = evaluate_value(&op->ops[1], depth);
  182. r = n1 == n2;
  183. print_depth(depth);
  184. printf("%Lf = %Lf == %Lf\n", r, n1, n2);
  185. break;
  186. case EVAL_OPERATOR_EXPRESSION_OPEN:
  187. printf("BEGIN SUB-EXPRESSION\n");
  188. r = evaluate_value(&op->ops[0], depth + 1);
  189. printf("END SUB-EXPRESSION\n");
  190. break;
  191. case EVAL_OPERATOR_NOP:
  192. case EVAL_OPERATOR_VALUE:
  193. r = evaluate_value(&op->ops[0], depth);
  194. break;
  195. default:
  196. netdata_log_error("I don't know how to handle operator '%c'", op->operator);
  197. r = 0;
  198. break;
  199. }
  200. return r;
  201. }
  202. void print_expression(EVAL_NODE *op, const char *failed_at, int error) {
  203. if(op) {
  204. printf("expression tree:\n");
  205. print_node(op, 0);
  206. printf("\nevaluation steps:\n");
  207. evaluate(op, 0);
  208. int error;
  209. NETDATA_DOUBLE ret = expression_evaluate(op, &error);
  210. printf("\ninternal evaluator:\nSTATUS: %d, RESULT = %Lf\n", error, ret);
  211. expression_free(op);
  212. }
  213. else {
  214. printf("error: %d, failed_at: '%s'\n", error, (failed_at)?failed_at:"<NONE>");
  215. }
  216. }
  217. */
  218. int main(int argc, char **argv) {
  219. if(argc != 2) {
  220. fprintf(stderr, "I need an expression (enclose it in single-quotes (') as a single parameter)\n");
  221. exit(1);
  222. }
  223. const char *failed_at = NULL;
  224. int error;
  225. EVAL_EXPRESSION *exp = expression_parse(argv[1], &failed_at, &error);
  226. if(!exp)
  227. 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));
  228. else {
  229. printf("\nPARSING OK\nExpression: '%s'\nParsed as : '%s'\nParsing error code: %d (%s)\n", argv[1], exp->parsed_as, error, expression_strerror(error));
  230. if(expression_evaluate(exp)) {
  231. printf("\nEvaluates to: %Lf\n\n", exp->result);
  232. }
  233. else {
  234. printf("\nEvaluation failed with code %d and message: %s\n\n", exp->error, buffer_tostring(exp->error_msg));
  235. }
  236. expression_free(exp);
  237. }
  238. return 0;
  239. }