mirror of
				https://github.com/eledio-devices/thirdparty-tinyexpr.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	Context for closures is now stored separately for each closure.
This commit is contained in:
		
							
								
								
									
										24
									
								
								test.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								test.c
									
									
									
									
									
								
							| @@ -432,11 +432,14 @@ double cell(void *context, double a) { | |||||||
|  |  | ||||||
| void test_closure() { | void test_closure() { | ||||||
|  |  | ||||||
|  |     double extra; | ||||||
|  |     double c[] = {5,6,7,8,9}; | ||||||
|  |  | ||||||
|     te_variable lookup[] = { |     te_variable lookup[] = { | ||||||
|         {"c0", clo0, TE_CLOSURE0}, |         {"c0", clo0, TE_CLOSURE0, &extra}, | ||||||
|         {"c1", clo1, TE_CLOSURE1}, |         {"c1", clo1, TE_CLOSURE1, &extra}, | ||||||
|         {"c2", clo2, TE_CLOSURE2}, |         {"c2", clo2, TE_CLOSURE2, &extra}, | ||||||
|         {"cell", cell, TE_CLOSURE1}, |         {"cell", cell, TE_CLOSURE1, c}, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     test_case cases[] = { |     test_case cases[] = { | ||||||
| @@ -445,7 +448,6 @@ void test_closure() { | |||||||
|         {"c2 (10, 20)", 30}, |         {"c2 (10, 20)", 30}, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     double extra = 10; |  | ||||||
|     int i; |     int i; | ||||||
|     for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { |     for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { | ||||||
|         const char *expr = cases[i].expr; |         const char *expr = cases[i].expr; | ||||||
| @@ -454,13 +456,17 @@ void test_closure() { | |||||||
|         int err; |         int err; | ||||||
|         te_expr *ex = te_compile(expr, lookup, sizeof(lookup)/sizeof(te_variable), &err); |         te_expr *ex = te_compile(expr, lookup, sizeof(lookup)/sizeof(te_variable), &err); | ||||||
|         lok(ex); |         lok(ex); | ||||||
|         lfequal(te_eval(ex), answer); |  | ||||||
|         lfequal(te_eval_closure(ex, &extra), answer + extra); |         extra = 0; | ||||||
|  |         lfequal(te_eval(ex), answer + extra); | ||||||
|  |  | ||||||
|  |         extra = 10; | ||||||
|  |         lfequal(te_eval(ex), answer + extra); | ||||||
|  |  | ||||||
|         te_free(ex); |         te_free(ex); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     double c[] = {5,6,7,8,9}; |  | ||||||
|     test_case cases2[] = { |     test_case cases2[] = { | ||||||
|         {"cell 0", 5}, |         {"cell 0", 5}, | ||||||
|         {"cell 1", 6}, |         {"cell 1", 6}, | ||||||
| @@ -475,7 +481,7 @@ void test_closure() { | |||||||
|         int err; |         int err; | ||||||
|         te_expr *ex = te_compile(expr, lookup, sizeof(lookup)/sizeof(te_variable), &err); |         te_expr *ex = te_compile(expr, lookup, sizeof(lookup)/sizeof(te_variable), &err); | ||||||
|         lok(ex); |         lok(ex); | ||||||
|         lfequal(te_eval_closure(ex, c), answer); |         lfequal(te_eval(ex), answer); | ||||||
|         te_free(ex); |         te_free(ex); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								tinyexpr.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								tinyexpr.c
									
									
									
									
									
								
							| @@ -44,6 +44,7 @@ typedef struct state { | |||||||
|     const char *next; |     const char *next; | ||||||
|     int type; |     int type; | ||||||
|     union {double value; const double *bound; const void *function;}; |     union {double value; const double *bound; const void *function;}; | ||||||
|  |     void *context; | ||||||
|  |  | ||||||
|     const te_variable *lookup; |     const te_variable *lookup; | ||||||
|     int lookup_len; |     int lookup_len; | ||||||
| @@ -188,10 +189,12 @@ void next_token(state *s) { | |||||||
|                             s->bound = var->address; |                             s->bound = var->address; | ||||||
|                             break; |                             break; | ||||||
|  |  | ||||||
|                         case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3: |  | ||||||
|                         case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: |  | ||||||
|                         case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: |                         case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: | ||||||
|                         case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: |                         case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: | ||||||
|  |                             s->context = var->context; | ||||||
|  |  | ||||||
|  |                         case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3: | ||||||
|  |                         case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: | ||||||
|                             s->type = var->type; |                             s->type = var->type; | ||||||
|                             s->function = var->address; |                             s->function = var->address; | ||||||
|                             break; |                             break; | ||||||
| @@ -245,6 +248,7 @@ static te_expr *base(state *s) { | |||||||
|         case TE_CLOSURE0: |         case TE_CLOSURE0: | ||||||
|             ret = new_expr(s->type, 0); |             ret = new_expr(s->type, 0); | ||||||
|             ret->function = s->function; |             ret->function = s->function; | ||||||
|  |             ret->context = s->context; | ||||||
|             next_token(s); |             next_token(s); | ||||||
|             if (s->type == TOK_OPEN) { |             if (s->type == TOK_OPEN) { | ||||||
|                 next_token(s); |                 next_token(s); | ||||||
| @@ -260,6 +264,7 @@ static te_expr *base(state *s) { | |||||||
|         case TE_CLOSURE1: |         case TE_CLOSURE1: | ||||||
|             ret = new_expr(s->type, 0); |             ret = new_expr(s->type, 0); | ||||||
|             ret->function = s->function; |             ret->function = s->function; | ||||||
|  |             ret->context = s->context; | ||||||
|             next_token(s); |             next_token(s); | ||||||
|             ret->parameters[0] = power(s); |             ret->parameters[0] = power(s); | ||||||
|             break; |             break; | ||||||
| @@ -272,6 +277,7 @@ static te_expr *base(state *s) { | |||||||
|  |  | ||||||
|             ret = new_expr(s->type, 0); |             ret = new_expr(s->type, 0); | ||||||
|             ret->function = s->function; |             ret->function = s->function; | ||||||
|  |             ret->context = s->context; | ||||||
|             next_token(s); |             next_token(s); | ||||||
|  |  | ||||||
|             if (s->type != TOK_OPEN) { |             if (s->type != TOK_OPEN) { | ||||||
| @@ -396,15 +402,10 @@ static te_expr *list(state *s) { | |||||||
|  |  | ||||||
|  |  | ||||||
| double te_eval(const te_expr *n) { | double te_eval(const te_expr *n) { | ||||||
|     return te_eval_closure(n, 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| double te_eval_closure(const te_expr *n, void *context) { |  | ||||||
|     if (!n) return 0.0/0.0; |     if (!n) return 0.0/0.0; | ||||||
|  |  | ||||||
| #define TE_FUN(...) ((double(*)(__VA_ARGS__))n->function) | #define TE_FUN(...) ((double(*)(__VA_ARGS__))n->function) | ||||||
| #define M(e) te_eval_closure(n->parameters[e], context) | #define M(e) te_eval(n->parameters[e]) | ||||||
|  |  | ||||||
|     switch(n->type) { |     switch(n->type) { | ||||||
|         case TE_CONSTANT: return n->value; |         case TE_CONSTANT: return n->value; | ||||||
| @@ -427,14 +428,14 @@ double te_eval_closure(const te_expr *n, void *context) { | |||||||
|         case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: |         case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: | ||||||
|         case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: |         case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: | ||||||
|             switch(ARITY(n->type)) { |             switch(ARITY(n->type)) { | ||||||
|                 case 0: return TE_FUN(void*)(context); |                 case 0: return TE_FUN(void*)(n->context); | ||||||
|                 case 1: return TE_FUN(void*, double)(context, M(0)); |                 case 1: return TE_FUN(void*, double)(n->context, M(0)); | ||||||
|                 case 2: return TE_FUN(void*, double, double)(context, M(0), M(1)); |                 case 2: return TE_FUN(void*, double, double)(n->context, M(0), M(1)); | ||||||
|                 case 3: return TE_FUN(void*, double, double, double)(context, M(0), M(1), M(2)); |                 case 3: return TE_FUN(void*, double, double, double)(n->context, M(0), M(1), M(2)); | ||||||
|                 case 4: return TE_FUN(void*, double, double, double, double)(context, M(0), M(1), M(2), M(3)); |                 case 4: return TE_FUN(void*, double, double, double, double)(n->context, M(0), M(1), M(2), M(3)); | ||||||
|                 case 5: return TE_FUN(void*, double, double, double, double, double)(context, M(0), M(1), M(2), M(3), M(4)); |                 case 5: return TE_FUN(void*, double, double, double, double, double)(n->context, M(0), M(1), M(2), M(3), M(4)); | ||||||
|                 case 6: return TE_FUN(void*, double, double, double, double, double, double)(context, M(0), M(1), M(2), M(3), M(4), M(5)); |                 case 6: return TE_FUN(void*, double, double, double, double, double, double)(n->context, M(0), M(1), M(2), M(3), M(4), M(5)); | ||||||
|                 case 7: return TE_FUN(void*, double, double, double, double, double, double, double)(context, M(0), M(1), M(2), M(3), M(4), M(5), M(6)); |                 case 7: return TE_FUN(void*, double, double, double, double, double, double, double)(n->context, M(0), M(1), M(2), M(3), M(4), M(5), M(6)); | ||||||
|                 default: return 0.0/0.0; |                 default: return 0.0/0.0; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ extern "C" { | |||||||
| typedef struct te_expr { | typedef struct te_expr { | ||||||
|     int type; |     int type; | ||||||
|     union {double value; const double *bound; const void *function;}; |     union {double value; const double *bound; const void *function;}; | ||||||
|  |     void *context; | ||||||
|     struct te_expr *parameters[]; |     struct te_expr *parameters[]; | ||||||
| } te_expr; | } te_expr; | ||||||
|  |  | ||||||
| @@ -51,6 +52,7 @@ typedef struct te_variable { | |||||||
|     const char *name; |     const char *name; | ||||||
|     const void *address; |     const void *address; | ||||||
|     int type; |     int type; | ||||||
|  |     void *context; | ||||||
| } te_variable; | } te_variable; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -66,9 +68,6 @@ te_expr *te_compile(const char *expression, const te_variable *variables, int va | |||||||
| /* Evaluates the expression. */ | /* Evaluates the expression. */ | ||||||
| double te_eval(const te_expr *n); | double te_eval(const te_expr *n); | ||||||
|  |  | ||||||
| /* Evaluates the expression while passing a closure to any bound closure functions. */ |  | ||||||
| double te_eval_closure(const te_expr *n, void *context); |  | ||||||
|  |  | ||||||
| /* Prints debugging information on the syntax tree. */ | /* Prints debugging information on the syntax tree. */ | ||||||
| void te_print(const te_expr *n); | void te_print(const te_expr *n); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user