i3lock-color

The world's most popular non-default computer lockscreen.
Index Commits Files Refs README LICENSE
tinyexpr.c (20847B)
   1 /*
   2  * TINYEXPR - Tiny recursive descent parser and evaluation engine in C
   3  *
   4  * Copyright (c) 2015, 2016 Lewis Van Winkle
   5  *
   6  * http://CodePlea.com
   7  *
   8  * This software is provided 'as-is', without any express or implied
   9  * warranty. In no event will the authors be held liable for any damages
  10  * arising from the use of this software.
  11  *
  12  * Permission is granted to anyone to use this software for any purpose,
  13  * including commercial applications, and to alter it and redistribute it
  14  * freely, subject to the following restrictions:
  15  *
  16  * 1. The origin of this software must not be misrepresented; you must not
  17  * claim that you wrote the original software. If you use this software
  18  * in a product, an acknowledgement in the product documentation would be
  19  * appreciated but is not required.
  20  * 2. Altered source versions must be plainly marked as such, and must not be
  21  * misrepresented as being the original software.
  22  * 3. This notice may not be removed or altered from any source distribution.
  23  */
  24 
  25 /* COMPILE TIME OPTIONS */
  26 
  27 /* Exponentiation associativity:
  28 For a^b^c = (a^b)^c and -a^b = (-a)^b do nothing.
  29 For a^b^c = a^(b^c) and -a^b = -(a^b) uncomment the next line.*/
  30 /* #define TE_POW_FROM_RIGHT */
  31 
  32 /* Logarithms
  33 For log = base 10 log do nothing
  34 For log = natural log uncomment the next line. */
  35 /* #define TE_NAT_LOG */
  36 
  37 #include "tinyexpr.h"
  38 #include <stdlib.h>
  39 #include <math.h>
  40 #include <string.h>
  41 #include <stdio.h>
  42 #include <limits.h>
  43 
  44 #ifndef NAN
  45 #define NAN (0.0/0.0)
  46 #endif
  47 
  48 #ifndef INFINITY
  49 #define INFINITY (1.0/0.0)
  50 #endif
  51 
  52 
  53 typedef double (*te_fun2)(double, double);
  54 
  55 enum {
  56     TOK_NULL = TE_CLOSURE7+1, TOK_ERROR, TOK_END, TOK_SEP,
  57     TOK_OPEN, TOK_CLOSE, TOK_NUMBER, TOK_VARIABLE, TOK_INFIX
  58 };
  59 
  60 
  61 enum {TE_CONSTANT = 1};
  62 
  63 
  64 typedef struct state {
  65     const char *start;
  66     const char *next;
  67     int type;
  68     union {double value; const double *bound; const void *function;};
  69     void *context;
  70 
  71     const te_variable *lookup;
  72     int lookup_len;
  73 } state;
  74 
  75 
  76 #define TYPE_MASK(TYPE) ((TYPE)&0x0000001F)
  77 
  78 #define IS_PURE(TYPE) (((TYPE) & TE_FLAG_PURE) != 0)
  79 #define IS_FUNCTION(TYPE) (((TYPE) & TE_FUNCTION0) != 0)
  80 #define IS_CLOSURE(TYPE) (((TYPE) & TE_CLOSURE0) != 0)
  81 #define ARITY(TYPE) ( ((TYPE) & (TE_FUNCTION0 | TE_CLOSURE0)) ? ((TYPE) & 0x00000007) : 0 )
  82 #define NEW_EXPR(type, ...) new_expr((type), (const te_expr*[]){__VA_ARGS__})
  83 
  84 static te_expr *new_expr(const int type, const te_expr *parameters[]) {
  85     const int arity = ARITY(type);
  86     const int psize = sizeof(void*) * arity;
  87     const int size = (sizeof(te_expr) - sizeof(void*)) + psize + (IS_CLOSURE(type) ? sizeof(void*) : 0);
  88     te_expr *ret = malloc(size);
  89     memset(ret, 0, size);
  90     if (arity && parameters) {
  91         memcpy(ret->parameters, parameters, psize);
  92     }
  93     ret->type = type;
  94     ret->bound = 0;
  95     return ret;
  96 }
  97 
  98 
  99 void te_free_parameters(te_expr *n) {
 100     if (!n) return;
 101     switch (TYPE_MASK(n->type)) {
 102         case TE_FUNCTION7: case TE_CLOSURE7: te_free(n->parameters[6]);
 103         case TE_FUNCTION6: case TE_CLOSURE6: te_free(n->parameters[5]);
 104         case TE_FUNCTION5: case TE_CLOSURE5: te_free(n->parameters[4]);
 105         case TE_FUNCTION4: case TE_CLOSURE4: te_free(n->parameters[3]);
 106         case TE_FUNCTION3: case TE_CLOSURE3: te_free(n->parameters[2]);
 107         case TE_FUNCTION2: case TE_CLOSURE2: te_free(n->parameters[1]);
 108         case TE_FUNCTION1: case TE_CLOSURE1: te_free(n->parameters[0]);
 109     }
 110 }
 111 
 112 
 113 void te_free(te_expr *n) {
 114     if (!n) return;
 115     te_free_parameters(n);
 116     free(n);
 117 }
 118 
 119 
 120 static double pi() {return 3.14159265358979323846;}
 121 static double e() {return 2.71828182845904523536;}
 122 static double fac(double a) {/* simplest version of fac */
 123     if (a < 0.0)
 124         return NAN;
 125     if (a > UINT_MAX)
 126         return INFINITY;
 127     unsigned int ua = (unsigned int)(a);
 128     unsigned long int result = 1, i;
 129     for (i = 1; i <= ua; i++) {
 130         if (i > ULONG_MAX / result)
 131             return INFINITY;
 132         result *= i;
 133     }
 134     return (double)result;
 135 }
 136 static double ncr(double n, double r) {
 137     if (n < 0.0 || r < 0.0 || n < r) return NAN;
 138     if (n > UINT_MAX || r > UINT_MAX) return INFINITY;
 139     unsigned long int un = (unsigned int)(n), ur = (unsigned int)(r), i;
 140     unsigned long int result = 1;
 141     if (ur > un / 2) ur = un - ur;
 142     for (i = 1; i <= ur; i++) {
 143         if (result > ULONG_MAX / (un - ur + i))
 144             return INFINITY;
 145         result *= un - ur + i;
 146         result /= i;
 147     }
 148     return result;
 149 }
 150 static double npr(double n, double r) {return ncr(n, r) * fac(r);}
 151 
 152 static const te_variable functions[] = {
 153     /* must be in alphabetical order */
 154     {"abs", fabs,     TE_FUNCTION1 | TE_FLAG_PURE, 0},
 155     {"acos", acos,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 156     {"asin", asin,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 157     {"atan", atan,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 158     {"atan2", atan2,  TE_FUNCTION2 | TE_FLAG_PURE, 0},
 159     {"ceil", ceil,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 160     {"cos", cos,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
 161     {"cosh", cosh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 162     {"e", e,          TE_FUNCTION0 | TE_FLAG_PURE, 0},
 163     {"exp", exp,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
 164     {"fac", fac,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
 165     {"floor", floor,  TE_FUNCTION1 | TE_FLAG_PURE, 0},
 166     {"ln", log,       TE_FUNCTION1 | TE_FLAG_PURE, 0},
 167 #ifdef TE_NAT_LOG
 168     {"log", log,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
 169 #else
 170     {"log", log10,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 171 #endif
 172     {"log10", log10,  TE_FUNCTION1 | TE_FLAG_PURE, 0},
 173     {"ncr", ncr,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
 174     {"npr", npr,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
 175     {"pi", pi,        TE_FUNCTION0 | TE_FLAG_PURE, 0},
 176     {"pow", pow,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
 177     {"sin", sin,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
 178     {"sinh", sinh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 179     {"sqrt", sqrt,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 180     {"tan", tan,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
 181     {"tanh", tanh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
 182     {0, 0, 0, 0}
 183 };
 184 
 185 static const te_variable *find_builtin(const char *name, int len) {
 186     int imin = 0;
 187     int imax = sizeof(functions) / sizeof(te_variable) - 2;
 188 
 189     /*Binary search.*/
 190     while (imax >= imin) {
 191         const int i = (imin + ((imax-imin)/2));
 192         int c = strncmp(name, functions[i].name, len);
 193         if (!c) c = '\0' - functions[i].name[len];
 194         if (c == 0) {
 195             return functions + i;
 196         } else if (c > 0) {
 197             imin = i + 1;
 198         } else {
 199             imax = i - 1;
 200         }
 201     }
 202 
 203     return 0;
 204 }
 205 
 206 static const te_variable *find_lookup(const state *s, const char *name, int len) {
 207     int iters;
 208     const te_variable *var;
 209     if (!s->lookup) return 0;
 210 
 211     for (var = s->lookup, iters = s->lookup_len; iters; ++var, --iters) {
 212         if (strncmp(name, var->name, len) == 0 && var->name[len] == '\0') {
 213             return var;
 214         }
 215     }
 216     return 0;
 217 }
 218 
 219 
 220 
 221 static double add(double a, double b) {return a + b;}
 222 static double sub(double a, double b) {return a - b;}
 223 static double mul(double a, double b) {return a * b;}
 224 static double divide(double a, double b) {return a / b;}
 225 static double negate(double a) {return -a;}
 226 static double comma(double a, double b) {(void)a; return b;}
 227 
 228 
 229 void next_token(state *s) {
 230     s->type = TOK_NULL;
 231 
 232     do {
 233 
 234         if (!*s->next){
 235             s->type = TOK_END;
 236             return;
 237         }
 238 
 239         /* Try reading a number. */
 240         if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') {
 241             s->value = strtod(s->next, (char**)&s->next);
 242             s->type = TOK_NUMBER;
 243         } else {
 244             /* Look for a variable or builtin function call. */
 245             if (s->next[0] >= 'a' && s->next[0] <= 'z') {
 246                 const char *start;
 247                 start = s->next;
 248                 while ((s->next[0] >= 'a' && s->next[0] <= 'z') || (s->next[0] >= '0' && s->next[0] <= '9') || (s->next[0] == '_')) s->next++;
 249 
 250                 const te_variable *var = find_lookup(s, start, s->next - start);
 251                 if (!var) var = find_builtin(start, s->next - start);
 252 
 253                 if (!var) {
 254                     s->type = TOK_ERROR;
 255                 } else {
 256                     switch(TYPE_MASK(var->type))
 257                     {
 258                         case TE_VARIABLE:
 259                             s->type = TOK_VARIABLE;
 260                             s->bound = var->address;
 261                             break;
 262 
 263                         case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3:
 264                         case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
 265                             s->context = var->context;
 266 
 267                         case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3:
 268                         case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7:
 269                             s->type = var->type;
 270                             s->function = var->address;
 271                             break;
 272                     }
 273                 }
 274 
 275             } else {
 276                 /* Look for an operator or special character. */
 277                 switch (s->next++[0]) {
 278                     case '+': s->type = TOK_INFIX; s->function = add; break;
 279                     case '-': s->type = TOK_INFIX; s->function = sub; break;
 280                     case '*': s->type = TOK_INFIX; s->function = mul; break;
 281                     case '/': s->type = TOK_INFIX; s->function = divide; break;
 282                     case '^': s->type = TOK_INFIX; s->function = pow; break;
 283                     case '%': s->type = TOK_INFIX; s->function = fmod; break;
 284                     case '(': s->type = TOK_OPEN; break;
 285                     case ')': s->type = TOK_CLOSE; break;
 286                     case ',': s->type = TOK_SEP; break;
 287                     case ' ': case '\t': case '\n': case '\r': break;
 288                     default: s->type = TOK_ERROR; break;
 289                 }
 290             }
 291         }
 292     } while (s->type == TOK_NULL);
 293 }
 294 
 295 
 296 static te_expr *list(state *s);
 297 static te_expr *expr(state *s);
 298 static te_expr *power(state *s);
 299 
 300 static te_expr *base(state *s) {
 301     /* <base>      =    <constant> | <variable> | <function-0> {"(" ")"} | <function-1> <power> | <function-X> "(" <expr> {"," <expr>} ")" | "(" <list> ")" */
 302     te_expr *ret;
 303     int arity;
 304 
 305     switch (TYPE_MASK(s->type)) {
 306         case TOK_NUMBER:
 307             ret = new_expr(TE_CONSTANT, 0);
 308             ret->value = s->value;
 309             next_token(s);
 310             break;
 311 
 312         case TOK_VARIABLE:
 313             ret = new_expr(TE_VARIABLE, 0);
 314             ret->bound = s->bound;
 315             next_token(s);
 316             break;
 317 
 318         case TE_FUNCTION0:
 319         case TE_CLOSURE0:
 320             ret = new_expr(s->type, 0);
 321             ret->function = s->function;
 322             if (IS_CLOSURE(s->type)) ret->parameters[0] = s->context;
 323             next_token(s);
 324             if (s->type == TOK_OPEN) {
 325                 next_token(s);
 326                 if (s->type != TOK_CLOSE) {
 327                     s->type = TOK_ERROR;
 328                 } else {
 329                     next_token(s);
 330                 }
 331             }
 332             break;
 333 
 334         case TE_FUNCTION1:
 335         case TE_CLOSURE1:
 336             ret = new_expr(s->type, 0);
 337             ret->function = s->function;
 338             if (IS_CLOSURE(s->type)) ret->parameters[1] = s->context;
 339             next_token(s);
 340             ret->parameters[0] = power(s);
 341             break;
 342 
 343         case TE_FUNCTION2: case TE_FUNCTION3: case TE_FUNCTION4:
 344         case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7:
 345         case TE_CLOSURE2: case TE_CLOSURE3: case TE_CLOSURE4:
 346         case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
 347             arity = ARITY(s->type);
 348 
 349             ret = new_expr(s->type, 0);
 350             ret->function = s->function;
 351             if (IS_CLOSURE(s->type)) ret->parameters[arity] = s->context;
 352             next_token(s);
 353 
 354             if (s->type != TOK_OPEN) {
 355                 s->type = TOK_ERROR;
 356             } else {
 357                 int i;
 358                 for(i = 0; i < arity; i++) {
 359                     next_token(s);
 360                     ret->parameters[i] = expr(s);
 361                     if(s->type != TOK_SEP) {
 362                         break;
 363                     }
 364                 }
 365                 if(s->type != TOK_CLOSE || i != arity - 1) {
 366                     s->type = TOK_ERROR;
 367                 } else {
 368                     next_token(s);
 369                 }
 370             }
 371 
 372             break;
 373 
 374         case TOK_OPEN:
 375             next_token(s);
 376             ret = list(s);
 377             if (s->type != TOK_CLOSE) {
 378                 s->type = TOK_ERROR;
 379             } else {
 380                 next_token(s);
 381             }
 382             break;
 383 
 384         default:
 385             ret = new_expr(0, 0);
 386             s->type = TOK_ERROR;
 387             ret->value = NAN;
 388             break;
 389     }
 390 
 391     return ret;
 392 }
 393 
 394 
 395 static te_expr *power(state *s) {
 396     /* <power>     =    {("-" | "+")} <base> */
 397     int sign = 1;
 398     while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) {
 399         if (s->function == sub) sign = -sign;
 400         next_token(s);
 401     }
 402 
 403     te_expr *ret;
 404 
 405     if (sign == 1) {
 406         ret = base(s);
 407     } else {
 408         ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
 409         ret->function = negate;
 410     }
 411 
 412     return ret;
 413 }
 414 
 415 #ifdef TE_POW_FROM_RIGHT
 416 static te_expr *factor(state *s) {
 417     /* <factor>    =    <power> {"^" <power>} */
 418     te_expr *ret = power(s);
 419 
 420     int neg = 0;
 421     te_expr *insertion = 0;
 422 
 423     if (ret->type == (TE_FUNCTION1 | TE_FLAG_PURE) && ret->function == negate) {
 424         te_expr *se = ret->parameters[0];
 425         free(ret);
 426         ret = se;
 427         neg = 1;
 428     }
 429 
 430     while (s->type == TOK_INFIX && (s->function == pow)) {
 431         te_fun2 t = s->function;
 432         next_token(s);
 433 
 434         if (insertion) {
 435             /* Make exponentiation go right-to-left. */
 436             te_expr *insert = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, insertion->parameters[1], power(s));
 437             insert->function = t;
 438             insertion->parameters[1] = insert;
 439             insertion = insert;
 440         } else {
 441             ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s));
 442             ret->function = t;
 443             insertion = ret;
 444         }
 445     }
 446 
 447     if (neg) {
 448         ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, ret);
 449         ret->function = negate;
 450     }
 451 
 452     return ret;
 453 }
 454 #else
 455 static te_expr *factor(state *s) {
 456     /* <factor>    =    <power> {"^" <power>} */
 457     te_expr *ret = power(s);
 458 
 459     while (s->type == TOK_INFIX && (s->function == pow)) {
 460         te_fun2 t = s->function;
 461         next_token(s);
 462         ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s));
 463         ret->function = t;
 464     }
 465 
 466     return ret;
 467 }
 468 #endif
 469 
 470 
 471 
 472 static te_expr *term(state *s) {
 473     /* <term>      =    <factor> {("*" | "/" | "%") <factor>} */
 474     te_expr *ret = factor(s);
 475 
 476     while (s->type == TOK_INFIX && (s->function == mul || s->function == divide || s->function == fmod)) {
 477         te_fun2 t = s->function;
 478         next_token(s);
 479         ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, factor(s));
 480         ret->function = t;
 481     }
 482 
 483     return ret;
 484 }
 485 
 486 
 487 static te_expr *expr(state *s) {
 488     /* <expr>      =    <term> {("+" | "-") <term>} */
 489     te_expr *ret = term(s);
 490 
 491     while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) {
 492         te_fun2 t = s->function;
 493         next_token(s);
 494         ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, term(s));
 495         ret->function = t;
 496     }
 497 
 498     return ret;
 499 }
 500 
 501 
 502 static te_expr *list(state *s) {
 503     /* <list>      =    <expr> {"," <expr>} */
 504     te_expr *ret = expr(s);
 505 
 506     while (s->type == TOK_SEP) {
 507         next_token(s);
 508         ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, expr(s));
 509         ret->function = comma;
 510     }
 511 
 512     return ret;
 513 }
 514 
 515 
 516 #define TE_FUN(...) ((double(*)(__VA_ARGS__))n->function)
 517 #define M(e) te_eval(n->parameters[e])
 518 
 519 
 520 double te_eval(const te_expr *n) {
 521     if (!n) return NAN;
 522 
 523     switch(TYPE_MASK(n->type)) {
 524         case TE_CONSTANT: return n->value;
 525         case TE_VARIABLE: return *n->bound;
 526 
 527         case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3:
 528         case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7:
 529             switch(ARITY(n->type)) {
 530                 case 0: return TE_FUN(void)();
 531                 case 1: return TE_FUN(double)(M(0));
 532                 case 2: return TE_FUN(double, double)(M(0), M(1));
 533                 case 3: return TE_FUN(double, double, double)(M(0), M(1), M(2));
 534                 case 4: return TE_FUN(double, double, double, double)(M(0), M(1), M(2), M(3));
 535                 case 5: return TE_FUN(double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4));
 536                 case 6: return TE_FUN(double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5));
 537                 case 7: return TE_FUN(double, double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5), M(6));
 538                 default: return NAN;
 539             }
 540 
 541         case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3:
 542         case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
 543             switch(ARITY(n->type)) {
 544                 case 0: return TE_FUN(void*)(n->parameters[0]);
 545                 case 1: return TE_FUN(void*, double)(n->parameters[1], M(0));
 546                 case 2: return TE_FUN(void*, double, double)(n->parameters[2], M(0), M(1));
 547                 case 3: return TE_FUN(void*, double, double, double)(n->parameters[3], M(0), M(1), M(2));
 548                 case 4: return TE_FUN(void*, double, double, double, double)(n->parameters[4], M(0), M(1), M(2), M(3));
 549                 case 5: return TE_FUN(void*, double, double, double, double, double)(n->parameters[5], M(0), M(1), M(2), M(3), M(4));
 550                 case 6: return TE_FUN(void*, double, double, double, double, double, double)(n->parameters[6], M(0), M(1), M(2), M(3), M(4), M(5));
 551                 case 7: return TE_FUN(void*, double, double, double, double, double, double, double)(n->parameters[7], M(0), M(1), M(2), M(3), M(4), M(5), M(6));
 552                 default: return NAN;
 553             }
 554 
 555         default: return NAN;
 556     }
 557 
 558 }
 559 
 560 #undef TE_FUN
 561 #undef M
 562 
 563 static void optimize(te_expr *n) {
 564     /* Evaluates as much as possible. */
 565     if (n->type == TE_CONSTANT) return;
 566     if (n->type == TE_VARIABLE) return;
 567 
 568     /* Only optimize out functions flagged as pure. */
 569     if (IS_PURE(n->type)) {
 570         const int arity = ARITY(n->type);
 571         int known = 1;
 572         int i;
 573         for (i = 0; i < arity; ++i) {
 574             optimize(n->parameters[i]);
 575             if (((te_expr*)(n->parameters[i]))->type != TE_CONSTANT) {
 576                 known = 0;
 577             }
 578         }
 579         if (known) {
 580             const double value = te_eval(n);
 581             te_free_parameters(n);
 582             n->type = TE_CONSTANT;
 583             n->value = value;
 584         }
 585     }
 586 }
 587 
 588 
 589 te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error) {
 590     state s;
 591     s.start = s.next = expression;
 592     s.lookup = variables;
 593     s.lookup_len = var_count;
 594 
 595     next_token(&s);
 596     te_expr *root = list(&s);
 597 
 598     if (s.type != TOK_END) {
 599         te_free(root);
 600         if (error) {
 601             *error = (s.next - s.start);
 602             if (*error == 0) *error = 1;
 603         }
 604         return 0;
 605     } else {
 606         optimize(root);
 607         if (error) *error = 0;
 608         return root;
 609     }
 610 }
 611 
 612 
 613 double te_interp(const char *expression, int *error) {
 614     te_expr *n = te_compile(expression, 0, 0, error);
 615     double ret;
 616     if (n) {
 617         ret = te_eval(n);
 618         te_free(n);
 619     } else {
 620         ret = NAN;
 621     }
 622     return ret;
 623 }
 624 
 625 static void pn (const te_expr *n, int depth) {
 626     int i, arity;
 627     printf("%*s", depth, "");
 628 
 629     switch(TYPE_MASK(n->type)) {
 630     case TE_CONSTANT: printf("%f\n", n->value); break;
 631     case TE_VARIABLE: printf("bound %p\n", n->bound); break;
 632 
 633     case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3:
 634     case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7:
 635     case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3:
 636     case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
 637          arity = ARITY(n->type);
 638          printf("f%d", arity);
 639          for(i = 0; i < arity; i++) {
 640              printf(" %p", n->parameters[i]);
 641          }
 642          printf("\n");
 643          for(i = 0; i < arity; i++) {
 644              pn(n->parameters[i], depth + 1);
 645          }
 646          break;
 647     }
 648 }
 649 
 650 
 651 void te_print(const te_expr *n) {
 652     pn(n, 0);
 653 }