Mercurial > hg > dmlib
changeset 679:1dc7bd5f99f7
Moar work.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 16 Apr 2013 15:13:37 +0300 |
parents | 4a08ce0997bc |
children | 4422a1880859 |
files | dmeval.c dmeval.h tests/evaltest.c |
diffstat | 3 files changed, 119 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/dmeval.c Tue Apr 16 15:06:43 2013 +0300 +++ b/dmeval.c Tue Apr 16 15:13:37 2013 +0300 @@ -242,6 +242,15 @@ } +static DMEvalNode *dm_eval_peek_node(DMEvalNode **list) +{ + if (*list == NULL) + return NULL; + + return (*list)->prev; +} + + static DMEvalNode *dm_eval_insert_node(DMEvalNode **list, DMEvalNode *node) { if (*list != NULL) @@ -735,15 +744,64 @@ LOWEST */ -int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result) + +int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result, int pass) { DMEvalNode *list = NULL; - int i; + int i, res; while (node != NULL) { - DMEvalNode *tmp; + DMEvalNode *tmp, *sub; + + if (pass == 0) + switch (node->op) + { + case OP_SUB: + if ((tmp = dm_eval_peek_node(&list)) == NULL || tmp->op <= OP_FUNC) + { + // Add subexpression node + if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL) + return -3; + + // Add this operator into subexpression + dm_eval_add_node(&(sub->subexpr), node->op); + + // Next node + node = node->next; + if (node == NULL) + return -72; + if (node->op == OP_FUNC || node->op == OP_SUBEXPR) + { + // It's a function or sub-expression + if ((tmp = dm_eval_push_node(&(sub->subexpr), node)) == NULL) + return -178; + + if ((res = dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr), pass)) != 0) + return res; + } + else + dm_eval_push_node(&(sub->subexpr), node); + } + else + { + if (dm_eval_push_node(&list, node) == NULL) + return -32; + } + + node = node->next; + break; + + default: + if (dm_eval_push_node(&list, node) == NULL) + return -32; + + node = node->next; + break; + } + else + if (pass == 1) switch (node->op) { case OP_FUNC: @@ -752,54 +810,79 @@ for (i = 0; i < DM_MAX_ARGS; i++) { - if (dm_eval_reorder(ev, node->args[i], &(tmp->args[i])) != 0) - return -2; + if ((res = dm_eval_reorder(ev, node->args[i], &(tmp->args[i]), pass)) != 0) + return res; } + node = node->next; break; case OP_SUBEXPR: if ((tmp = dm_eval_push_node(&list, node)) == NULL) return -1; - if (dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr)) != 0) - return -2; + if ((res = dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr), pass)) != 0) + return res; + node = node->next; break; + case OP_MUL: case OP_DIV: case OP_MOD: - if ((tmp = dm_eval_pop_node(&list)) != NULL) - { - DMEvalNode *sub; + // Pop previous node, f.e. 5*3 -> 5 + if ((tmp = dm_eval_pop_node(&list)) == NULL) + return -24; - if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL) - return -3; + // Add subexpression node + if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL) + return -3; + + // Add popped node into subexpression + dm_eval_push_node(&(sub->subexpr), tmp); + + // Add this operator into subexpression + dm_eval_add_node(&(sub->subexpr), node->op); - dm_eval_push_node(&(sub->subexpr), tmp); - dm_eval_add_node(&(sub->subexpr), node->op); - node = node->next; - if (node != NULL) - { - if (node->op == OP_FUNC || node->op == OP_SUBEXPR) - { - if ((tmp = dm_eval_push_node(&(sub->subexpr), node)) == NULL) - return -178; - - if (dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr)) != 0) - return -66; - } - else - dm_eval_push_node(&(sub->subexpr), node); - } - else - return -72; + // Next node + node = node->next; + if (node == NULL) + return -72; + + if (node->op == OP_FUNC || node->op == OP_SUBEXPR) + { + // It's a function or sub-expression + if ((tmp = dm_eval_push_node(&(sub->subexpr), node)) == NULL) + return -178; + + if ((res = dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr), pass)) != 0) + return res; } else - return -24; + dm_eval_push_node(&(sub->subexpr), node); + + node = node->next; break; case OP_LSHIFT: case OP_RSHIFT: + // Bitshift operator precedence is .. different + if (dm_eval_push_node(&list, node) == NULL) + return -32; + + if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL) + return -3; + + node = node->next; + if (node == NULL) + return -14; + + tmp = NULL; + if ((res = dm_eval_reorder(ev, node, &tmp, pass)) != 0) + return res; + + sub->subexpr = tmp; + node = NULL; + break; case OP_ADD: case OP_SUB: @@ -812,14 +895,14 @@ case OP_CONST: if (dm_eval_push_node(&list, node) == NULL) return -32; + + node = node->next; break; default: dm_eval_err(ev, "Invalid opcode %d in node %p.\n", node->op, node); return -4; } - - node = node->next; } *result = list;
--- a/dmeval.h Tue Apr 16 15:06:43 2013 +0300 +++ b/dmeval.h Tue Apr 16 15:13:37 2013 +0300 @@ -88,7 +88,7 @@ void dm_eval_clear_err(DMEvalContext *ev); int dm_eval_parse_expr(DMEvalContext *ev, char *expr, DMEvalNode **result); -int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result); +int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result, int pass); int dm_eval_exec(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult); void dm_print_optree(DMEvalContext *ev, DMEvalNode *node);
--- a/tests/evaltest.c Tue Apr 16 15:06:43 2013 +0300 +++ b/tests/evaltest.c Tue Apr 16 15:13:37 2013 +0300 @@ -67,8 +67,9 @@ DMEvalContext *ev = dm_eval_new(); DMEvalNode *parsed = NULL, *ordered = NULL; DMValue result, t, f = 44100.0f; - int ret; + int ret, i; + dmVerbosity = 2; optFormula = "-pi * -2"; dmInitProg("evaltest", "evaltest", "0.1", NULL, NULL);