Mercurial > hg > dmlib
changeset 761:7be7c7c5deaa
Large cleanup, breaking everything. Yay.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 09 May 2013 06:21:36 +0300 |
parents | d345a898bda1 |
children | 49e96e581ac8 |
files | dmeval.c dmeval.h dmevalw.c dmevalw.h tests/evaltest.c tools/auval.c |
diffstat | 6 files changed, 227 insertions(+), 489 deletions(-) [+] |
line wrap: on
line diff
--- a/dmeval.c Thu May 09 06:18:52 2013 +0300 +++ b/dmeval.c Thu May 09 06:21:36 2013 +0300 @@ -1,9 +1,39 @@ #include "dmeval.h" #include <math.h> -#define DM_MAX_ID_LEN 16 #define DM_MAX_BUF 512 -#define DM_STACK_SIZE 512 + + +const DMEvalOper dmEvalOpers[OP_NOPERS] = +{ + { "-" , OT_UNARY }, + { "~" , OT_UNARY }, + + { "+" , OT_LEFT }, + { "-" , OT_LEFT }, + { "*" , OT_LEFT }, + { "/" , OT_LEFT }, + { "%" , OT_LEFT }, + + + { "<<", OT_LEFT }, + { ">>", OT_LEFT }, + + { "&" , OT_LEFT }, + { "|" , OT_LEFT }, + { "^" , OT_LEFT }, + + { ">" , OT_LEFT }, + { "<" , OT_LEFT }, + { ">=", OT_LEFT }, + { "<=", OT_LEFT }, + + { "FUNC" , OT_NONE }, + { "VAR" , OT_NONE }, + { "CONST" , OT_NONE }, + + { "SUBEXPR", OT_NONE }, +}; /* Function definitions @@ -34,7 +64,7 @@ /* Some basic functions */ -static const DMEvalId dm_eval_basic[] = +static const DMEvalSymbol dmEvalBasicFuncs[] = { { "sin", ID_FUNC, 1, func_sin, NULL, 0 }, { "cos", ID_FUNC, 1, func_cos, NULL, 0 }, @@ -44,10 +74,10 @@ { "pi", ID_CVAR, 0, NULL, NULL, DM_PI }, }; -static const int ndm_eval_basic = sizeof(dm_eval_basic) / sizeof(dm_eval_basic[0]); +static const int ndmEvalBasicFuncs = sizeof(dmEvalBasicFuncs) / sizeof(dmEvalBasicFuncs[0]); -void dm_eval_err_v(DMEvalContext *ev, const char *fmt, va_list ap) +void dmEvalErrorV(DMEvalContext *ev, const char *fmt, va_list ap) { #if 1 char *tmp = dm_strdup_vprintf(fmt, ap); @@ -67,46 +97,46 @@ } -void dm_eval_err(DMEvalContext *ev, const char *fmt, ...) +void dmEvalError(DMEvalContext *ev, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - dm_eval_err_v(ev, fmt, ap); + dmEvalErrorV(ev, fmt, ap); va_end(ap); } -DMEvalId *dm_eval_find_id(DMEvalContext *ev, const char *name) +DMEvalSymbol *dmEvalContextFindSymbol(DMEvalContext *ev, const char *name) { int i; - if (ev->ids == NULL) + if (ev->symbols == NULL) return NULL; - for (i = 0; i < ev->nids; i++) + for (i = 0; i < ev->nsymbols; i++) { - if (strcmp(ev->ids[i].name, name) == 0) - return &(ev->ids[i]); + if (strcmp(ev->symbols[i].name, name) == 0) + return &(ev->symbols[i]); } return NULL; } -static DMEvalId *dm_eval_add_id(DMEvalContext *ev, const char *name, const int type) +static DMEvalSymbol *dmEvalContextAddSymbol(DMEvalContext *ev, const char *name, const int type) { - DMEvalId *id = dm_eval_find_id(ev, name); + DMEvalSymbol *id = dmEvalContextFindSymbol(ev, name); if (id != NULL) return NULL; - ev->ids = dmRealloc(ev->ids, sizeof(DMEvalId) * (ev->nids + 1)); - if (ev->ids == NULL) + ev->symbols = dmRealloc(ev->symbols, sizeof(DMEvalSymbol) * (ev->nsymbols + 1)); + if (ev->symbols == NULL) { - dm_eval_err(ev, "Could not reallocate eval ids array (#%d). Fatal error.\n", ev->nids + 1); + dmEvalError(ev, "Could not reallocate eval symbols array (#%d). Fatal error.\n", ev->nsymbols + 1); return NULL; } - id = &(ev->ids[ev->nids]); - ev->nids++; + id = &(ev->symbols[ev->nsymbols]); + ev->nsymbols++; id->name = dm_strdup(name); id->type = type; @@ -117,9 +147,9 @@ } -DMEvalId *dm_eval_add_var(DMEvalContext *ev, const char *name, DMValue *var) +DMEvalSymbol *dmEvalContextAddVar(DMEvalContext *ev, const char *name, DMValue *var) { - DMEvalId *id = dm_eval_add_id(ev, name, ID_VAR); + DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_VAR); if (id == NULL) return NULL; @@ -128,9 +158,9 @@ } -DMEvalId *dm_eval_add_const(DMEvalContext *ev, const char *name, DMValue value) +DMEvalSymbol *dmEvalContextAddConst(DMEvalContext *ev, const char *name, DMValue value) { - DMEvalId *id = dm_eval_add_id(ev, name, ID_CVAR); + DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_CVAR); if (id == NULL) return NULL; @@ -139,9 +169,9 @@ } -DMEvalId *dm_eval_add_func(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs) +DMEvalSymbol *dmEvalContextAddFunc(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs) { - DMEvalId *id = dm_eval_add_id(ev, name, ID_VAR); + DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_VAR); if (id == NULL) return NULL; @@ -151,7 +181,7 @@ } -DMEvalContext *dm_eval_new(void) +DMEvalContext *dmEvalContextNew(void) { int i; DMEvalContext *ev = dmCalloc(1, sizeof(DMEvalContext)); @@ -159,10 +189,10 @@ if (ev == NULL) return NULL; - for (i = 0; i < ndm_eval_basic; i++) + for (i = 0; i < ndmEvalBasicFuncs; i++) { - const DMEvalId *id = &dm_eval_basic[i]; - DMEvalId *nid = dm_eval_add_id(ev, id->name, id->type); + const DMEvalSymbol *id = &dmEvalBasicFuncs[i]; + DMEvalSymbol *nid = dmEvalContextAddSymbol(ev, id->name, id->type); nid->nargs = id->nargs; nid->func = id->func; nid->var = id->var; @@ -173,7 +203,7 @@ } -void dm_eval_free(DMEvalNode *node) +void dmEvalTreeFree(DMEvalNode *node) { while (node != NULL) { @@ -182,11 +212,11 @@ for (i = 0; i < DM_MAX_ARGS; i++) { - dm_eval_free(node->args[i]); + dmEvalTreeFree(node->args[i]); node->args[i] = NULL; } - dm_eval_free(node->subexpr); + dmEvalTreeFree(node->subexpr); node->subexpr = NULL; dmFree(node); node = next; @@ -194,7 +224,7 @@ } -void dm_eval_clear_err(DMEvalContext *ev) +void dmEvalContextClear(DMEvalContext *ev) { if (ev == NULL) return; @@ -205,44 +235,23 @@ } -void dm_eval_close(DMEvalContext *ev) +void dmEvalContextClose(DMEvalContext *ev) { int i; if (ev == NULL) return; - for (i = 0; i < ev->nids; i++) - dmFree(ev->ids[i].name); + for (i = 0; i < ev->nsymbols; i++) + dmFree(ev->symbols[i].name); - dmFree(ev->ids); - dm_eval_clear_err(ev); + dmFree(ev->symbols); + dmEvalContextClear(ev); dmFree(ev); } -static DMEvalNode *dm_eval_pop_node(DMEvalNode **list) -{ - DMEvalNode *node; - - if (*list == NULL) - return NULL; - - node = (*list)->prev; - - if (*list != node) - { - node->prev->next = NULL; - (*list)->prev = node->prev; - } - else - *list = NULL; - - return node; -} - - -static DMEvalNode *dm_eval_insert_node(DMEvalNode **list, DMEvalNode *node) +static DMEvalNode *dmEvalInsertNode(DMEvalNode **list, DMEvalNode *node) { if (*list != NULL) { @@ -261,39 +270,7 @@ } -static DMEvalNode *dm_eval_push_node(DMEvalNode **list, const DMEvalNode *src) -{ - DMEvalNode *tmp, *node = dmCalloc(1, sizeof(DMEvalNode)); - int i; - - if (node == NULL) - return NULL; - - node->op = src->op; - node->val = src->val; - node->id = src->id; - node->ok = src->ok; - - if (src->op == OP_SUBEXPR) - { - for (tmp = src->subexpr; tmp != NULL; tmp = tmp->next) - dm_eval_push_node(&(node->subexpr), tmp); - } - - if (src->op == OP_FUNC) - { - for (i = 0; i < src->id->nargs; i++) - { - for (tmp = src->args[i]; tmp != NULL; tmp = tmp->next) - dm_eval_push_node(&(node->args[i]), tmp); - } - } - - return dm_eval_insert_node(list, node); -} - - -static DMEvalNode *dm_eval_add_node(DMEvalNode **list, const int op) +static DMEvalNode *dmEvalAddNode(DMEvalNode **list, const int op) { DMEvalNode *node = dmCalloc(1, sizeof(DMEvalNode)); if (node == NULL) @@ -301,7 +278,7 @@ node->op = op; - return dm_eval_insert_node(list, node); + return dmEvalInsertNode(list, node); } @@ -325,7 +302,7 @@ #define DM_CHECK(x) { if (mode & PARSE_ ## x ) { if (str[0]) strcat(str, " or "); strcat(str, # x ); } } -static char *dm_get_mode(int mode) +static char *dmEvalGetMode(int mode) { char str[128] = ""; @@ -343,17 +320,17 @@ } -static void dm_set_mode(DMEvalContext *ev, const int mode) +static void dmEvalSetMode(DMEvalContext *ev, const int mode) { if (mode != PARSE_ERROR && mode != PARSE_START && ev->expect != PARSE_NONE && (mode & ev->expect) == 0) { - char *tmp1 = dm_get_mode(ev->expect), - *tmp2 = dm_get_mode(mode); + char *tmp1 = dmEvalGetMode(ev->expect), + *tmp2 = dmEvalGetMode(mode); - dm_eval_err(ev, "Expected [%s], got %s.\n", tmp1, tmp2); + dmEvalError(ev, "Expected [%s], got %s.\n", tmp1, tmp2); dmFree(tmp1); dmFree(tmp2); } @@ -363,7 +340,7 @@ } -static int dm_eval_parse_expr_do(DMEvalContext *ev, DMEvalNode **list, char **str, int depth) +static int dmEvalTokenizeExpr(DMEvalContext *ev, DMEvalNode **list, char **str, int depth) { char *c = *str; char tmpStr[DM_MAX_BUF + 2]; @@ -383,18 +360,18 @@ ev->expect = PARSE_NORMAL; - if ((node = dm_eval_add_node(list, OP_SUBEXPR)) == NULL) - dm_set_mode(ev, PARSE_ERROR); + if ((node = dmEvalAddNode(list, OP_SUBEXPR)) == NULL) + dmEvalSetMode(ev, PARSE_ERROR); else - if (dm_eval_parse_expr_do(ev, &(node->subexpr), &tmp, depth + 1) != 0) + if (dmEvalTokenizeExpr(ev, &(node->subexpr), &tmp, depth + 1) != 0) { - dm_eval_err(ev, "Subexpression starting at '%s' contained errors.\n", c); - dm_set_mode(ev, PARSE_ERROR); + dmEvalError(ev, "Subexpression starting at '%s' contained errors.\n", c); + dmEvalSetMode(ev, PARSE_ERROR); } if (ev->mode != PARSE_ERROR) { - dm_set_mode(ev, PARSE_START); + dmEvalSetMode(ev, PARSE_START); ev->expect = PARSE_OPER | PARSE_SUBEXPR_END; c = tmp; } @@ -406,10 +383,10 @@ char *tmp = c + 1; for (argIndex = 0; argIndex < func->id->nargs; argIndex++) { - if (dm_eval_parse_expr_do(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0) + if (dmEvalTokenizeExpr(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0) { - dm_eval_err(ev, "Function argument subexpression starting at '%s' contained errors.\n", c); - dm_set_mode(ev, PARSE_ERROR); + dmEvalError(ev, "Function argument subexpression starting at '%s' contained errors.\n", c); + dmEvalSetMode(ev, PARSE_ERROR); } } @@ -417,7 +394,7 @@ if (ev->mode != PARSE_ERROR) { - dm_set_mode(ev, PARSE_START); + dmEvalSetMode(ev, PARSE_START); ev->expect = PARSE_OPER | PARSE_END; c = tmp; } @@ -427,7 +404,7 @@ case PARSE_START: // Start if (*c == 0) - dm_set_mode(ev, PARSE_END); + dmEvalSetMode(ev, PARSE_END); // Skip whitespace else if (isspace(*c)) @@ -436,37 +413,37 @@ else if (*c == ')' || *c == ',') { if (depth > 0) - dm_set_mode(ev, PARSE_END); + dmEvalSetMode(ev, PARSE_END); else { - dm_eval_err(ev, "Invalid nesting near '%s' (depth %d).\n", c, depth); - dm_set_mode(ev, PARSE_ERROR); + dmEvalError(ev, "Invalid nesting near '%s' (depth %d).\n", c, depth); + dmEvalSetMode(ev, PARSE_ERROR); } c++; } else if (*c == '(') - dm_set_mode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR_START); + dmEvalSetMode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR_START); else if (*c == '-') - dm_set_mode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER || ev->prev == PARSE_OPER_UNARY) ? PARSE_OPER_UNARY : PARSE_OPER); + dmEvalSetMode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER || ev->prev == PARSE_OPER_UNARY) ? PARSE_OPER_UNARY : PARSE_OPER); else if (*c == '~') - dm_set_mode(ev, PARSE_OPER_UNARY); + dmEvalSetMode(ev, PARSE_OPER_UNARY); else if (strchr("+*/<>%&|!^", *c)) - dm_set_mode(ev, PARSE_OPER); + dmEvalSetMode(ev, PARSE_OPER); else if (isdigit(*c) || *c == '.') - dm_set_mode(ev, PARSE_CONST); + dmEvalSetMode(ev, PARSE_CONST); else if (isalpha(*c) || *c == '_') - dm_set_mode(ev, PARSE_IDENT); + dmEvalSetMode(ev, PARSE_IDENT); else { - dm_eval_err(ev, "Syntax error near '%s' (depth %d).\n", c, depth); - dm_set_mode(ev, PARSE_ERROR); + dmEvalError(ev, "Syntax error near '%s' (depth %d).\n", c, depth); + dmEvalSetMode(ev, PARSE_ERROR); } first = TRUE; @@ -487,8 +464,8 @@ } else { - dm_eval_err(ev, "Invalid constant expression near '%s'.\n", c); - dm_set_mode(ev, PARSE_ERROR); + dmEvalError(ev, "Invalid constant expression near '%s'.\n", c); + dmEvalSetMode(ev, PARSE_ERROR); } } else @@ -507,22 +484,22 @@ } else { - dm_eval_err(ev, "Invalid constant expression near '%s'.\n", c); - dm_set_mode(ev, PARSE_ERROR); + dmEvalError(ev, "Invalid constant expression near '%s'.\n", c); + dmEvalSetMode(ev, PARSE_ERROR); } } else { tmpStr[tmpStrLen] = 0; - if ((node = dm_eval_add_node(list, OP_CONST)) == NULL) + if ((node = dmEvalAddNode(list, OP_CONST)) == NULL) { - dm_set_mode(ev, PARSE_ERROR); + dmEvalSetMode(ev, PARSE_ERROR); } else { node->val = atof(tmpStr); - dm_set_mode(ev, PARSE_START); + dmEvalSetMode(ev, PARSE_START); ev->expect = PARSE_OPER | PARSE_END; } } @@ -531,7 +508,7 @@ case PARSE_OPER_UNARY: { - int op = OP_NONE; + int op = OP_INVALID; switch (*c) { @@ -539,22 +516,22 @@ case '~': op = OP_BIT_COMPLEMENT; c++; break; } - if (op != OP_NONE) + if (op != OP_INVALID) { - if ((node = dm_eval_add_node(list, op)) != NULL) + if ((node = dmEvalAddNode(list, op)) != NULL) { ev->expect = PARSE_NORMAL; - dm_set_mode(ev, PARSE_START); + dmEvalSetMode(ev, PARSE_START); } else - dm_set_mode(ev, PARSE_ERROR); + dmEvalSetMode(ev, PARSE_ERROR); } } break; case PARSE_OPER: { - int op = OP_NONE; + int op = OP_INVALID; switch (*c) { @@ -594,19 +571,19 @@ break; default: - dm_eval_err(ev, "Unknown operator '%c' at %s\n", *c, c); - dm_set_mode(ev, PARSE_ERROR); + dmEvalError(ev, "Unknown operator '%c' at %s\n", *c, c); + dmEvalSetMode(ev, PARSE_ERROR); } - if (op != OP_NONE) + if (op != OP_INVALID) { - if ((node = dm_eval_add_node(list, op)) != NULL) + if ((node = dmEvalAddNode(list, op)) != NULL) { ev->expect = PARSE_NORMAL | PARSE_OPER_UNARY; - dm_set_mode(ev, PARSE_START); + dmEvalSetMode(ev, PARSE_START); } else - dm_set_mode(ev, PARSE_ERROR); + dmEvalSetMode(ev, PARSE_ERROR); } } break; @@ -620,21 +597,21 @@ first = FALSE; } - if (tmpStrLen < DM_MAX_ID_LEN) + if (tmpStrLen < DM_MAX_BUF) tmpStr[tmpStrLen++] = *c++; else { tmpStr[tmpStrLen] = 0; - dm_eval_err(ev, "Identifier too long! ('%s') near %s\n", tmpStr, c); + dmEvalError(ev, "Identifier too long! ('%s') near %s\n", tmpStr, c); } } else { tmpStr[tmpStrLen] = 0; - DMEvalId *id = dm_eval_find_id(ev, tmpStr); + DMEvalSymbol *id = dmEvalContextFindSymbol(ev, tmpStr); if (id != NULL) { - if ((node = dm_eval_add_node(list, id->type == ID_FUNC ? OP_FUNC : OP_VAR)) != NULL) + if ((node = dmEvalAddNode(list, id->type == ID_FUNC ? OP_FUNC : OP_VAR)) != NULL) { node->id = id; if (id->type == ID_FUNC) @@ -645,15 +622,15 @@ else ev->expect = PARSE_END | PARSE_OPER; - dm_set_mode(ev, PARSE_START); + dmEvalSetMode(ev, PARSE_START); } else - dm_set_mode(ev, PARSE_ERROR); + dmEvalSetMode(ev, PARSE_ERROR); } else { - dm_eval_err(ev, "No such identifier '%s'.\n", tmpStr); - dm_set_mode(ev, PARSE_ERROR); + dmEvalError(ev, "No such identifier '%s'.\n", tmpStr); + dmEvalSetMode(ev, PARSE_ERROR); } } break; @@ -665,7 +642,7 @@ } -int dm_eval_parse_expr(DMEvalContext *ev, char *expr, DMEvalNode **result) +int dmEvalParseExpr(DMEvalContext *ev, char *expr, DMEvalNode **result) { int ret; @@ -673,210 +650,17 @@ return -1; ev->prev = PARSE_START; - ret = dm_eval_parse_expr_do(ev, result, &expr, 0); + ret = dmEvalTokenizeExpr(ev, result, &expr, 0); return ret; } -/* - operator precedence: - HIGHEST - "()" - - "*" - "/" - "%" - - "+" - "-" - - "<<" - ">>" - - "&" - "^" - "|" - LOWEST -*/ -static int dm_eval_reorder_pass0(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result) -{ - DMEvalNode *tmp; - int i, res; - - for (; node != NULL; node = node->next) - switch (node->op) - { - case OP_FUNC: - if ((tmp = dm_eval_add_node(result, OP_FUNC)) == NULL) - return -1; - - tmp->id = node->id; - - for (i = 0; i < node->id->nargs; i++) - { - if ((res = dm_eval_reorder(ev, node->args[i], &(tmp->args[i]))) != 0) - return res; - } - break; - - case OP_SUBEXPR: - if ((tmp = dm_eval_add_node(result, OP_SUBEXPR)) == NULL) - return -1; - - if ((res = dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr))) != 0) - return res; - break; - - default: - if (dm_eval_push_node(result, node) == NULL) - return -32; - break; - } - - return 0; -} - - -static int dm_eval_reorder_pass1(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result, - const int op1, const int op2, const int op3) -{ - DMEvalNode *sub; - - for (; node != NULL; node = node->next) - { - if (!node->ok && node->op == op1 && - (node->prev == NULL || node->prev->op < OP_FUNC)) - { - if (node->next == NULL || node->next->op == op2) - { - if (dm_eval_push_node(result, node) == NULL) - return -32; - } - else - { - // Add subexpression node - if ((sub = dm_eval_add_node(result, 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; - - dm_eval_push_node(&(sub->subexpr), node); - } - } - else - if (dm_eval_push_node(result, node) == NULL) - return -32; - } - return 0; -} - -static int dm_eval_reorder_passN(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result, - const int op1, const int op2, const int op3) -{ - DMEvalNode *tmp, *sub, *foo; - - for (; node != NULL; node = node->next) - { - if (!node->ok && (node->op == op1 || node->op == op2 || node->op == op3)) - { - // Pop previous node, f.e. 5*3 -> 5 - if ((tmp = dm_eval_pop_node(result)) == NULL) - return -24; - - // Add subexpression node - if ((sub = dm_eval_add_node(result, OP_SUBEXPR)) == NULL) - return DMERR_MALLOC; - - // Add popped node into subexpression - dm_eval_push_node(&(sub->subexpr), tmp); - - // Add this operator into subexpression - if ((foo = dm_eval_add_node(&(sub->subexpr), node->op)) == NULL) - return DMERR_MALLOC; - - foo->ok = TRUE; - - // Next node - node = node->next; - if (node == NULL) - return -72; - - dm_eval_push_node(&(sub->subexpr), node); - } - else - if (dm_eval_push_node(result, node) == NULL) - return -32; - } - - return 0; -} - - -#if 1 -#define RO_DEBUG(x, y) do { fprintf(stderr, x); dm_print_optree(stderr, ev, y); } while (0) -#else -#define RO_DEBUG(x, y) /* stub */ -#endif - - -int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result) -{ - DMEvalNode *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL, *tmp5 = NULL; - int res; - - RO_DEBUG("REORD: ", node); - - // Pass 0 - if ((res = dm_eval_reorder_pass0(ev, node, &tmp1)) != 0) - goto out; - RO_DEBUG("PASS0: ", tmp1); - - // Pass 1 - if ((res = dm_eval_reorder_pass1(ev, tmp1, &tmp2, OP_BIT_COMPLEMENT, -1, -1)) != 0) - goto out; - RO_DEBUG("PASS1: ", tmp2); - - // Pass 2 - if ((res = dm_eval_reorder_pass1(ev, tmp2, &tmp3, OP_SUB_UNARY, -1, -1)) != 0) - goto out; - RO_DEBUG("PASS2: ", tmp2); - - // Pass 2 - if ((res = dm_eval_reorder_passN(ev, tmp3, &tmp4, OP_MUL, OP_DIV, OP_MOD)) != 0) - goto out; - RO_DEBUG("PASS3: ", tmp2); - - // Pass 3 - if ((res = dm_eval_reorder_passN(ev, tmp4, &tmp5, OP_SUB, OP_ADD, -1)) != 0) - goto out; - RO_DEBUG("PASS4: ", tmp3); - - res = dm_eval_reorder_passN(ev, tmp5, result, OP_BIT_LSHIFT, OP_BIT_RSHIFT, -1); - RO_DEBUG("PASS5: ", *result); - -out: - dm_eval_free(tmp1); - dm_eval_free(tmp2); - dm_eval_free(tmp3); - dm_eval_free(tmp4); - dm_eval_free(tmp5); - - return res; -} - - -static int dm_eval_get(DMEvalContext *ev, const DMEvalNode *node, DMValue *result) +static int dmEvalGet(DMEvalContext *ev, const DMEvalNode *node, DMValue *result) { if (node == NULL) return -32; @@ -895,7 +679,7 @@ break; case OP_SUBEXPR: - return dm_eval_exec(ev, node->subexpr, result); + return dmEvalTreeExecute(ev, node->subexpr, result); case OP_FUNC: { @@ -903,7 +687,7 @@ int i; for (i = 0; i < node->id->nargs; i++) { - if (dm_eval_exec(ev, node->args[i], &tmp[i]) != 0) + if (dmEvalTreeExecute(ev, node->args[i], &tmp[i]) != 0) return -1; } @@ -919,7 +703,7 @@ } -int dm_eval_exec(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult) +int dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult) { DMValue result = 0; DMEvalNode *node = tree; @@ -940,7 +724,7 @@ case OP_MUL: case OP_DIV: case OP_MOD: - if (dm_eval_get(ev, node->next, &tmp) != 0) + if (dmEvalGet(ev, node->next, &tmp) != 0) return -6; switch (node->op) @@ -948,7 +732,7 @@ case OP_DIV: if (tmp == 0) { - dm_eval_err(ev, "Division by zero.\n"); + dmEvalError(ev, "Division by zero.\n"); return -1; } result /= tmp; @@ -959,7 +743,7 @@ case OP_MOD: if (tmp == 0) { - dm_eval_err(ev, "Division by zero.\n"); + dmEvalError(ev, "Division by zero.\n"); return -1; } result = DMCONVTYPE result % DMCONVTYPE tmp; @@ -967,12 +751,12 @@ case OP_BIT_LSHIFT: if (tmp > 31) - dm_eval_err(ev, "Left shift count >= width of type"); + dmEvalError(ev, "Left shift count >= width of type"); result = DMCONVTYPE result << DMCONVTYPE tmp; break; case OP_BIT_RSHIFT: if (tmp > 31) - dm_eval_err(ev, "Right shift count >= width of type"); + dmEvalError(ev, "Right shift count >= width of type"); result = DMCONVTYPE result >> DMCONVTYPE tmp; break; case OP_BIT_AND: result = DMCONVTYPE result & DMCONVTYPE tmp; break; @@ -987,7 +771,7 @@ case OP_SUB: case OP_SUB_UNARY: case OP_BIT_COMPLEMENT: - if (dm_eval_get(ev, node->next, &tmp) != 0) + if (dmEvalGet(ev, node->next, &tmp) != 0) return -6; switch (node->op) @@ -1002,9 +786,9 @@ break; default: - if (dm_eval_get(ev, node, &result) != 0) + if (dmEvalGet(ev, node, &result) != 0) { - dm_eval_err(ev, "Invalid opcode %d in node %p.\n", node->op, node); + dmEvalError(ev, "Invalid opcode %d in node %p.\n", node->op, node); return -4; } }
--- a/dmeval.h Thu May 09 06:18:52 2013 +0300 +++ b/dmeval.h Thu May 09 06:21:36 2013 +0300 @@ -2,6 +2,7 @@ #define DMEVAL_H #include "dmlib.h" +#include <stdio.h> typedef double DMValue; @@ -11,8 +12,8 @@ enum { - // No-op - OP_NONE, + OP_SUB_UNARY, + OP_BIT_COMPLEMENT, OP_ADD, OP_SUB, @@ -20,9 +21,6 @@ OP_DIV, OP_MOD, - OP_SUB_UNARY, - OP_BIT_COMPLEMENT, - OP_BIT_LSHIFT, OP_BIT_RSHIFT, @@ -38,20 +36,31 @@ // Special ops OP_FUNC, OP_VAR, + OP_CONST, OP_SUBEXPR, - OP_CONST, // Total number of operators - OP_NOPERS -} DMOper; + OP_NOPERS, + + OP_INVALID +} DMEvalOperId; enum { + OT_NONE, + OT_LEFT, // Left-associative OT_RIGHT, // Right-associative OT_UNARY, -} DMOperType; +} DMEvalOperType; + + +typedef struct +{ + char *name; + int type; +} DMEvalOper; enum @@ -59,7 +68,7 @@ ID_FUNC, ID_VAR, ID_CVAR, -} DMEvalIdType; +} DMEvalSymbolType; typedef struct @@ -69,7 +78,7 @@ int nargs; DMValue (*func)(DMValue arg[DM_MAX_ARGS]); DMValue *var, cvalue; -} DMEvalId; +} DMEvalSymbol; typedef struct DMEvalNode @@ -77,9 +86,10 @@ BOOL ok; int op; DMValue val; - DMEvalId *id; + DMEvalSymbol *id; struct DMEvalNode *args[DM_MAX_ARGS]; + struct DMEvalNode *subexpr, *next, *prev; } DMEvalNode; @@ -89,26 +99,35 @@ BOOL err; char *errStr; - int nids; - DMEvalId *ids; + int nsymbols; + DMEvalSymbol *symbols; int mode, prev, expect; } DMEvalContext; -DMEvalId *dm_eval_find_id(DMEvalContext *ev, const char *name); -DMEvalId *dm_eval_add_var(DMEvalContext *ev, const char *name, DMValue *var); -DMEvalId *dm_eval_add_const(DMEvalContext *ev, const char *name, DMValue value); -DMEvalId *dm_eval_add_func(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs); +// Evaluation context management +DMEvalContext * dmEvalContextNew(void); +void dmEvalContextClose(DMEvalContext *ev); +void dmEvalContextClear(DMEvalContext *ev); + -DMEvalContext *dm_eval_new(void); -void dm_eval_close(DMEvalContext *ev); -void dm_eval_free(DMEvalNode *node); -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_exec(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult); +// Symbol management +DMEvalSymbol * dmEvalContextFindSymbol(DMEvalContext *ev, const char *name); +DMEvalSymbol * dmEvalContextAddVar(DMEvalContext *ev, const char *name, DMValue *var); +DMEvalSymbol * dmEvalContextAddConst(DMEvalContext *ev, const char *name, DMValue value); +DMEvalSymbol * dmEvalContextAddFunc(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs); +// Evaluation trees, tokenization, parsing +int dmEvalParseExpr(DMEvalContext *ev, char *expr, DMEvalNode **plist); +int dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult); +void dmEvalTreeFree(DMEvalNode *node); + + +void dmEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node); + + +extern const DMEvalOper dmEvalOpers[OP_NOPERS]; + #endif // DMEVAL_H
--- a/dmevalw.c Thu May 09 06:18:52 2013 +0300 +++ b/dmevalw.c Thu May 09 06:21:36 2013 +0300 @@ -1,38 +1,7 @@ -#include "dmevalw.h" +#include "dmeval.h" -static const char *dm_oper_names[OP_NOPERS] = -{ - "NONE", - "+", - "-", - "*", - "/", - "%", - - "#", - "~", - - "<<", - ">>", - - "&", - "|", - "^", - - ">", - "<", - ">=", - "<=", - - "FUNC", - "VAR", - "SUBEXPR", - "CONST", -}; - - -static void dm_print_optree_do(FILE *out, DMEvalContext *ev, DMEvalNode *node, const int level) +void dmDoEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node, int level) { int i; while (node != NULL) @@ -43,7 +12,7 @@ fprintf(out, "%s(", node->id != NULL ? node->id->name : "?ERROR"); for (i = 0; i < node->id->nargs; i++) { - dm_print_optree_do(out, ev, node->args[i], level + 1); + dmDoEvalPrintOpTree(out, ev, node->args[i], level + 1); if (i < node->id->nargs - 1) fprintf(out, ","); } @@ -61,15 +30,15 @@ case OP_SUBEXPR: fprintf(out, "("); if (node->subexpr != NULL) - dm_print_optree_do(out, ev, node->subexpr, level + 1); + dmDoEvalPrintOpTree(out, ev, node->subexpr, level + 1); else fprintf(out, "?ERROR"); fprintf(out, ")"); break; default: - if (node->op > 0 && node->op < OP_NOPERS) - fprintf(out, "%s", dm_oper_names[node->op]); + if (node->op >= 0 && node->op < OP_NOPERS) + fprintf(out, "%s", dmEvalOpers[node->op].name); else fprintf(out, "ERROR!"); break; @@ -79,8 +48,8 @@ } -void dm_print_optree(FILE *out, DMEvalContext *ev, DMEvalNode *node) +void dmEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node) { - dm_print_optree_do(out, ev, node, 0); + dmDoEvalPrintOpTree(out, ev, node, 0); fprintf(out, "\n"); }
--- a/dmevalw.h Thu May 09 06:18:52 2013 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#ifndef DMEVALW_H -#define DMEVALW_H - -#include "dmeval.h" -#include <stdio.h> - -void dm_print_optree(FILE *out, DMEvalContext *ev, DMEvalNode *node); - - -#endif // DMEVALW_H
--- a/tests/evaltest.c Thu May 09 06:18:52 2013 +0300 +++ b/tests/evaltest.c Thu May 09 06:21:36 2013 +0300 @@ -1,12 +1,11 @@ #include "dmlib.h" #include "dmeval.h" -#include "dmevalw.h" #include "dmargs.h" BOOL optBenchmark = FALSE, optFloor = FALSE; -char * optFormula = ""; +char * optExpression = ""; DMOptArg optList[] = @@ -14,7 +13,7 @@ { 0, '?', "help", "Show this help", OPT_NONE }, { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, { 2, 'b', "benchmark", "Run in benchmark mode", OPT_NONE }, - { 3, 'e', "expression", "Next argument is the expression/formula", OPT_ARGREQ }, + { 3, 'e', "expression", "Next argument is the expression", OPT_ARGREQ }, { 4, 'f', "floor", "Clamp/floor the result value", OPT_NONE }, }; @@ -23,7 +22,7 @@ void argShowHelp() { - dmPrintBanner(stdout, dmProgName, "[options] [-e] '<formula>'"); + dmPrintBanner(stdout, dmProgName, "[options] [-e] '<expression>'"); dmArgsPrintHelp(stdout, optList, optListN); } @@ -46,7 +45,7 @@ break; case 3: - optFormula = optArg; + optExpression = optArg; break; case 4: @@ -64,15 +63,15 @@ BOOL argHandleNonOpt(char *currArg) { - optFormula = currArg; + optExpression = currArg; return TRUE; } int main(int argc, char *argv[]) { - DMEvalContext *ev = dm_eval_new(); - DMEvalNode *parsed = NULL, *ordered = NULL; + DMEvalContext *ev = dmEvalContextNew(); + DMEvalNode *expr = NULL; DMValue result, t, f = 44100.0f; int ret; @@ -85,54 +84,41 @@ // Register some variables - dm_eval_add_var(ev, "t", &t); - dm_eval_add_var(ev, "f", &f); + dmEvalContextAddVar(ev, "t", &t); + dmEvalContextAddVar(ev, "f", &f); // Parse expression - ret = dm_eval_parse_expr(ev, optFormula, &parsed); + ret = dmEvalParseExpr(ev, optExpression, &expr); dmMsg(1, "parse ret=%d\n", ret); if (ev->err) dmError("%s\n", ev->errStr); if (dmVerbosity > 0) - dm_print_optree(stdout, ev, parsed); + dmEvalPrintOpTree(stdout, ev, expr); if (ret != 0) return -1; + + // Benchmark or execute + dmEvalContextClear(ev); - // Perform reordering - dm_eval_clear_err(ev); - - ret = dm_eval_reorder(ev, parsed, &ordered); - dmMsg(1, "reorder ret=%d\n", ret); - if (ev->err) - dmError("%s\n", ev->errStr); - - if (dmVerbosity > 0) - dm_print_optree(stdout, ev, ordered); - - if (ret != 0) - return -2; - - // Benchmark or execute if (optBenchmark) { dmMsg(0, "Benchmarking ...\n"); for (t = 0; t < 12500000; t++) - ret = dm_eval_exec(ev, ordered, &result); + ret = dmEvalTreeExecute(ev, expr, &result); } else { - ret = dm_eval_exec(ev, ordered, &result); + ret = dmEvalTreeExecute(ev, expr, &result); printf("%1.5f\n", optFloor ? (int) result : result); } dmMsg(1, "eval ret=%d\n", ret); - dm_eval_close(ev); - dm_eval_free(parsed); - dm_eval_free(ordered); + dmEvalContextClose(ev); + dmEvalTreeFree(expr); return 0; }
--- a/tools/auval.c Thu May 09 06:18:52 2013 +0300 +++ b/tools/auval.c Thu May 09 06:21:36 2013 +0300 @@ -24,10 +24,7 @@ typedef struct { DMEvalNode *expr; - DMEvalContext *engine; - - char *errStr; - int err; + DMEvalContext *ctx; double varTime, varFreq, varKeyTime, varKeyTimeRev, varKeyFreq, varUnit; @@ -557,7 +554,7 @@ data->avail = 0; - if (data->err == 0) + if (!data->ctx->err) { while (data->avail < len && data->avail < data->bufsize) { @@ -565,7 +562,7 @@ data->varKeyTimeRev = 1.0f - data->varKeyTime; - if (dm_eval_exec(data->engine, data->expr, &value) != 0) + if (dmEvalTreeExecute(data->ctx, data->expr, &value) != 0) break; if (optScale) @@ -591,7 +588,7 @@ data->varKeyTime = 1.0f; } - if (data->avail >= len && data->err == 0) + if (data->avail >= len && !data->ctx->err) { memcpy(buf, data->buf, len); data->pos += len; @@ -640,14 +637,14 @@ au_read_history(AUVAL_HISTORY_FILE, histBuf, optHistoryLen, &histMax); - /* Initialize evaluator engine */ - audata.engine = dm_eval_new(); + /* Initialize evaluator ctx */ + audata.ctx = dmEvalContextNew(); audata.expr = NULL; - dm_eval_add_var(audata.engine, "t", &audata.varTime); - dm_eval_add_var(audata.engine, "k", &audata.varKeyTime); - dm_eval_add_var(audata.engine, "q", &audata.varKeyTimeRev); - dm_eval_add_var(audata.engine, "f", &audata.varUnit); + dmEvalContextAddVar(audata.ctx, "t", &audata.varTime); + dmEvalContextAddVar(audata.ctx, "k", &audata.varKeyTime); + dmEvalContextAddVar(audata.ctx, "q", &audata.varKeyTimeRev); + dmEvalContextAddVar(audata.ctx, "f", &audata.varUnit); /* Initialize SDL */ @@ -1004,18 +1001,11 @@ dmMutexLock(audata.mutex); - dm_eval_free(audata.expr); - DMEvalNode *tmp = NULL; + dmEvalTreeFree(audata.expr); audata.expr = NULL; - - audata.err = dm_eval_parse_expr(audata.engine, editBuf->data, &tmp); - if (audata.err == 0) - audata.err = dm_eval_reorder(audata.engine, tmp, &audata.expr); - - dm_print_optree(stdout, audata.engine, tmp); - dm_print_optree(stdout, audata.engine, audata.expr); + audata.ctx->err = dmEvalParseExpr(audata.ctx, editBuf->data, &audata.expr); + dmEvalPrintOpTree(stdout, audata.ctx, audata.expr); printf("--\n"); - dm_eval_free(tmp); audata.pos = 0; audata.varTime = 0; @@ -1100,14 +1090,14 @@ dmMutexLock(audata.mutex); dmFillBox3D(screen, 0, eh - 15, screen->w - 1, screen->h - 1, - audata.err ? dmMapRGB(screen, 255, 0, 0) : dmMapRGB(screen, 0, 128, 64), + audata.ctx->err ? dmMapRGB(screen, 255, 0, 0) : dmMapRGB(screen, 0, 128, 64), dmMapRGB(screen, 200, 255, 200), 100); au_draw_editbuf(screen, font, fontcol, 5, eh - 10, screen->w - 10, eh - 15, editBuf, dmMapRGB(screen, 0, 0, 150)); - if (audata.errStr != NULL) - dmDrawTTFTextConst(screen, font, fontcol, 5, screen->h - fh, audata.errStr); + if (audata.ctx->err && audata.ctx->errStr != NULL) + dmDrawTTFTextConst(screen, font, fontcol, 5, screen->h - fh, audata.ctx->errStr); dmMutexUnlock(audata.mutex); }