You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

654 lines
21KB

  1. /*
  2. * TINYEXPR - Tiny recursive descent parser and evaluation engine in C
  3. *
  4. * Copyright (c) 2015-2018 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. /* COMPILE TIME OPTIONS */
  25. /* Exponentiation associativity:
  26. For a^b^c = (a^b)^c and -a^b = (-a)^b do nothing.
  27. For a^b^c = a^(b^c) and -a^b = -(a^b) uncomment the next line.*/
  28. /* #define TE_POW_FROM_RIGHT */
  29. /* Logarithms
  30. For log = base 10 log do nothing
  31. For log = natural log uncomment the next line. */
  32. /* #define TE_NAT_LOG */
  33. #include "tinyexpr.h"
  34. #include <stdlib.h>
  35. #include <math.h>
  36. #include <string.h>
  37. #include <stdio.h>
  38. #include <limits.h>
  39. #ifndef NAN
  40. #define NAN (0.0/0.0)
  41. #endif
  42. #ifndef INFINITY
  43. #define INFINITY (1.0/0.0)
  44. #endif
  45. typedef double (*te_fun2)(double, double);
  46. enum {
  47. TOK_NULL = TE_CLOSURE7+1, TOK_ERROR, TOK_END, TOK_SEP,
  48. TOK_OPEN, TOK_CLOSE, TOK_NUMBER, TOK_VARIABLE, TOK_INFIX
  49. };
  50. enum {TE_CONSTANT = 1};
  51. typedef struct state {
  52. const char *start;
  53. const char *next;
  54. int type;
  55. union {double value; const double *bound; const void *function;};
  56. void *context;
  57. const te_variable *lookup;
  58. int lookup_len;
  59. } state;
  60. #define TYPE_MASK(TYPE) ((TYPE)&0x0000001F)
  61. #define IS_PURE(TYPE) (((TYPE) & TE_FLAG_PURE) != 0)
  62. #define IS_FUNCTION(TYPE) (((TYPE) & TE_FUNCTION0) != 0)
  63. #define IS_CLOSURE(TYPE) (((TYPE) & TE_CLOSURE0) != 0)
  64. #define ARITY(TYPE) ( ((TYPE) & (TE_FUNCTION0 | TE_CLOSURE0)) ? ((TYPE) & 0x00000007) : 0 )
  65. #define NEW_EXPR(type, ...) new_expr((type), (const te_expr*[]){__VA_ARGS__})
  66. static te_expr *new_expr(const int type, const te_expr *parameters[]) {
  67. const int arity = ARITY(type);
  68. const int psize = sizeof(void*) * arity;
  69. const int size = (sizeof(te_expr) - sizeof(void*)) + psize + (IS_CLOSURE(type) ? sizeof(void*) : 0);
  70. te_expr *ret = malloc(size);
  71. memset(ret, 0, size);
  72. if (arity && parameters) {
  73. memcpy(ret->parameters, parameters, psize);
  74. }
  75. ret->type = type;
  76. ret->bound = 0;
  77. return ret;
  78. }
  79. void te_free_parameters(te_expr *n) {
  80. if (!n) return;
  81. switch (TYPE_MASK(n->type)) {
  82. case TE_FUNCTION7: case TE_CLOSURE7: te_free(n->parameters[6]); /* Falls through. */
  83. case TE_FUNCTION6: case TE_CLOSURE6: te_free(n->parameters[5]); /* Falls through. */
  84. case TE_FUNCTION5: case TE_CLOSURE5: te_free(n->parameters[4]); /* Falls through. */
  85. case TE_FUNCTION4: case TE_CLOSURE4: te_free(n->parameters[3]); /* Falls through. */
  86. case TE_FUNCTION3: case TE_CLOSURE3: te_free(n->parameters[2]); /* Falls through. */
  87. case TE_FUNCTION2: case TE_CLOSURE2: te_free(n->parameters[1]); /* Falls through. */
  88. case TE_FUNCTION1: case TE_CLOSURE1: te_free(n->parameters[0]);
  89. }
  90. }
  91. void te_free(te_expr *n) {
  92. if (!n) return;
  93. te_free_parameters(n);
  94. free(n);
  95. }
  96. static double pi(void) {return 3.14159265358979323846;}
  97. static double e(void) {return 2.71828182845904523536;}
  98. static double fac(double a) {/* simplest version of fac */
  99. if (a < 0.0)
  100. return NAN;
  101. if (a > UINT_MAX)
  102. return INFINITY;
  103. unsigned int ua = (unsigned int)(a);
  104. unsigned long int result = 1, i;
  105. for (i = 1; i <= ua; i++) {
  106. if (i > ULONG_MAX / result)
  107. return INFINITY;
  108. result *= i;
  109. }
  110. return (double)result;
  111. }
  112. static double ncr(double n, double r) {
  113. if (n < 0.0 || r < 0.0 || n < r) return NAN;
  114. if (n > UINT_MAX || r > UINT_MAX) return INFINITY;
  115. unsigned long int un = (unsigned int)(n), ur = (unsigned int)(r), i;
  116. unsigned long int result = 1;
  117. if (ur > un / 2) ur = un - ur;
  118. for (i = 1; i <= ur; i++) {
  119. if (result > ULONG_MAX / (un - ur + i))
  120. return INFINITY;
  121. result *= un - ur + i;
  122. result /= i;
  123. }
  124. return result;
  125. }
  126. static double npr(double n, double r) {return ncr(n, r) * fac(r);}
  127. static const te_variable functions[] = {
  128. /* must be in alphabetical order */
  129. {"abs", fabs, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  130. {"acos", acos, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  131. {"asin", asin, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  132. {"atan", atan, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  133. {"atan2", atan2, TE_FUNCTION2 | TE_FLAG_PURE, 0},
  134. {"ceil", ceil, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  135. {"cos", cos, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  136. {"cosh", cosh, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  137. {"e", e, TE_FUNCTION0 | TE_FLAG_PURE, 0},
  138. {"exp", exp, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  139. {"fac", fac, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  140. {"floor", floor, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  141. {"ln", log, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  142. #ifdef TE_NAT_LOG
  143. {"log", log, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  144. #else
  145. {"log", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  146. #endif
  147. {"log10", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  148. {"ncr", ncr, TE_FUNCTION2 | TE_FLAG_PURE, 0},
  149. {"npr", npr, TE_FUNCTION2 | TE_FLAG_PURE, 0},
  150. {"pi", pi, TE_FUNCTION0 | TE_FLAG_PURE, 0},
  151. {"pow", pow, TE_FUNCTION2 | TE_FLAG_PURE, 0},
  152. {"sin", sin, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  153. {"sinh", sinh, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  154. {"sqrt", sqrt, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  155. {"tan", tan, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  156. {"tanh", tanh, TE_FUNCTION1 | TE_FLAG_PURE, 0},
  157. {0, 0, 0, 0}
  158. };
  159. static const te_variable *find_builtin(const char *name, int len) {
  160. int imin = 0;
  161. int imax = sizeof(functions) / sizeof(te_variable) - 2;
  162. /*Binary search.*/
  163. while (imax >= imin) {
  164. const int i = (imin + ((imax-imin)/2));
  165. int c = strncmp(name, functions[i].name, len);
  166. if (!c) c = '\0' - functions[i].name[len];
  167. if (c == 0) {
  168. return functions + i;
  169. } else if (c > 0) {
  170. imin = i + 1;
  171. } else {
  172. imax = i - 1;
  173. }
  174. }
  175. return 0;
  176. }
  177. static const te_variable *find_lookup(const state *s, const char *name, int len) {
  178. int iters;
  179. const te_variable *var;
  180. if (!s->lookup) return 0;
  181. for (var = s->lookup, iters = s->lookup_len; iters; ++var, --iters) {
  182. if (strncmp(name, var->name, len) == 0 && var->name[len] == '\0') {
  183. return var;
  184. }
  185. }
  186. return 0;
  187. }
  188. static double add(double a, double b) {return a + b;}
  189. static double sub(double a, double b) {return a - b;}
  190. static double mul(double a, double b) {return a * b;}
  191. static double divide(double a, double b) {return a / b;}
  192. static double negate(double a) {return -a;}
  193. static double comma(double a, double b) {(void)a; return b;}
  194. void next_token(state *s) {
  195. s->type = TOK_NULL;
  196. do {
  197. if (!*s->next){
  198. s->type = TOK_END;
  199. return;
  200. }
  201. /* Try reading a number. */
  202. if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') {
  203. s->value = strtod(s->next, (char**)&s->next);
  204. s->type = TOK_NUMBER;
  205. } else {
  206. /* Look for a variable or builtin function call. */
  207. if (s->next[0] >= 'a' && s->next[0] <= 'z') {
  208. const char *start;
  209. start = s->next;
  210. while ((s->next[0] >= 'a' && s->next[0] <= 'z') || (s->next[0] >= '0' && s->next[0] <= '9') || (s->next[0] == '_')) s->next++;
  211. const te_variable *var = find_lookup(s, start, s->next - start);
  212. if (!var) var = find_builtin(start, s->next - start);
  213. if (!var) {
  214. s->type = TOK_ERROR;
  215. } else {
  216. switch(TYPE_MASK(var->type))
  217. {
  218. case TE_VARIABLE:
  219. s->type = TOK_VARIABLE;
  220. s->bound = var->address;
  221. break;
  222. case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: /* Falls through. */
  223. case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: /* Falls through. */
  224. s->context = var->context; /* Falls through. */
  225. case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3: /* Falls through. */
  226. case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: /* Falls through. */
  227. s->type = var->type;
  228. s->function = var->address;
  229. break;
  230. }
  231. }
  232. } else {
  233. /* Look for an operator or special character. */
  234. switch (s->next++[0]) {
  235. case '+': s->type = TOK_INFIX; s->function = add; break;
  236. case '-': s->type = TOK_INFIX; s->function = sub; break;
  237. case '*': s->type = TOK_INFIX; s->function = mul; break;
  238. case '/': s->type = TOK_INFIX; s->function = divide; break;
  239. case '^': s->type = TOK_INFIX; s->function = pow; break;
  240. case '%': s->type = TOK_INFIX; s->function = fmod; break;
  241. case '(': s->type = TOK_OPEN; break;
  242. case ')': s->type = TOK_CLOSE; break;
  243. case ',': s->type = TOK_SEP; break;
  244. case ' ': case '\t': case '\n': case '\r': break;
  245. default: s->type = TOK_ERROR; break;
  246. }
  247. }
  248. }
  249. } while (s->type == TOK_NULL);
  250. }
  251. static te_expr *list(state *s);
  252. static te_expr *expr(state *s);
  253. static te_expr *power(state *s);
  254. static te_expr *base(state *s) {
  255. /* <base> = <constant> | <variable> | <function-0> {"(" ")"} | <function-1> <power> | <function-X> "(" <expr> {"," <expr>} ")" | "(" <list> ")" */
  256. te_expr *ret;
  257. int arity;
  258. switch (TYPE_MASK(s->type)) {
  259. case TOK_NUMBER:
  260. ret = new_expr(TE_CONSTANT, 0);
  261. ret->value = s->value;
  262. next_token(s);
  263. break;
  264. case TOK_VARIABLE:
  265. ret = new_expr(TE_VARIABLE, 0);
  266. ret->bound = s->bound;
  267. next_token(s);
  268. break;
  269. case TE_FUNCTION0:
  270. case TE_CLOSURE0:
  271. ret = new_expr(s->type, 0);
  272. ret->function = s->function;
  273. if (IS_CLOSURE(s->type)) ret->parameters[0] = s->context;
  274. next_token(s);
  275. if (s->type == TOK_OPEN) {
  276. next_token(s);
  277. if (s->type != TOK_CLOSE) {
  278. s->type = TOK_ERROR;
  279. } else {
  280. next_token(s);
  281. }
  282. }
  283. break;
  284. case TE_FUNCTION1:
  285. case TE_CLOSURE1:
  286. ret = new_expr(s->type, 0);
  287. ret->function = s->function;
  288. if (IS_CLOSURE(s->type)) ret->parameters[1] = s->context;
  289. next_token(s);
  290. ret->parameters[0] = power(s);
  291. break;
  292. case TE_FUNCTION2: case TE_FUNCTION3: case TE_FUNCTION4:
  293. case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7:
  294. case TE_CLOSURE2: case TE_CLOSURE3: case TE_CLOSURE4:
  295. case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
  296. arity = ARITY(s->type);
  297. ret = new_expr(s->type, 0);
  298. ret->function = s->function;
  299. if (IS_CLOSURE(s->type)) ret->parameters[arity] = s->context;
  300. next_token(s);
  301. if (s->type != TOK_OPEN) {
  302. s->type = TOK_ERROR;
  303. } else {
  304. int i;
  305. for(i = 0; i < arity; i++) {
  306. next_token(s);
  307. ret->parameters[i] = expr(s);
  308. if(s->type != TOK_SEP) {
  309. break;
  310. }
  311. }
  312. if(s->type != TOK_CLOSE || i != arity - 1) {
  313. s->type = TOK_ERROR;
  314. } else {
  315. next_token(s);
  316. }
  317. }
  318. break;
  319. case TOK_OPEN:
  320. next_token(s);
  321. ret = list(s);
  322. if (s->type != TOK_CLOSE) {
  323. s->type = TOK_ERROR;
  324. } else {
  325. next_token(s);
  326. }
  327. break;
  328. default:
  329. ret = new_expr(0, 0);
  330. s->type = TOK_ERROR;
  331. ret->value = NAN;
  332. break;
  333. }
  334. return ret;
  335. }
  336. static te_expr *power(state *s) {
  337. /* <power> = {("-" | "+")} <base> */
  338. int sign = 1;
  339. while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) {
  340. if (s->function == sub) sign = -sign;
  341. next_token(s);
  342. }
  343. te_expr *ret;
  344. if (sign == 1) {
  345. ret = base(s);
  346. } else {
  347. ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
  348. ret->function = negate;
  349. }
  350. return ret;
  351. }
  352. #ifdef TE_POW_FROM_RIGHT
  353. static te_expr *factor(state *s) {
  354. /* <factor> = <power> {"^" <power>} */
  355. te_expr *ret = power(s);
  356. int neg = 0;
  357. te_expr *insertion = 0;
  358. if (ret->type == (TE_FUNCTION1 | TE_FLAG_PURE) && ret->function == negate) {
  359. te_expr *se = ret->parameters[0];
  360. free(ret);
  361. ret = se;
  362. neg = 1;
  363. }
  364. while (s->type == TOK_INFIX && (s->function == pow)) {
  365. te_fun2 t = s->function;
  366. next_token(s);
  367. if (insertion) {
  368. /* Make exponentiation go right-to-left. */
  369. te_expr *insert = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, insertion->parameters[1], power(s));
  370. insert->function = t;
  371. insertion->parameters[1] = insert;
  372. insertion = insert;
  373. } else {
  374. ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s));
  375. ret->function = t;
  376. insertion = ret;
  377. }
  378. }
  379. if (neg) {
  380. ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, ret);
  381. ret->function = negate;
  382. }
  383. return ret;
  384. }
  385. #else
  386. static te_expr *factor(state *s) {
  387. /* <factor> = <power> {"^" <power>} */
  388. te_expr *ret = power(s);
  389. while (s->type == TOK_INFIX && (s->function == pow)) {
  390. te_fun2 t = s->function;
  391. next_token(s);
  392. ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s));
  393. ret->function = t;
  394. }
  395. return ret;
  396. }
  397. #endif
  398. static te_expr *term(state *s) {
  399. /* <term> = <factor> {("*" | "/" | "%") <factor>} */
  400. te_expr *ret = factor(s);
  401. while (s->type == TOK_INFIX && (s->function == mul || s->function == divide || s->function == fmod)) {
  402. te_fun2 t = s->function;
  403. next_token(s);
  404. ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, factor(s));
  405. ret->function = t;
  406. }
  407. return ret;
  408. }
  409. static te_expr *expr(state *s) {
  410. /* <expr> = <term> {("+" | "-") <term>} */
  411. te_expr *ret = term(s);
  412. while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) {
  413. te_fun2 t = s->function;
  414. next_token(s);
  415. ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, term(s));
  416. ret->function = t;
  417. }
  418. return ret;
  419. }
  420. static te_expr *list(state *s) {
  421. /* <list> = <expr> {"," <expr>} */
  422. te_expr *ret = expr(s);
  423. while (s->type == TOK_SEP) {
  424. next_token(s);
  425. ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, expr(s));
  426. ret->function = comma;
  427. }
  428. return ret;
  429. }
  430. #define TE_FUN(...) ((double(*)(__VA_ARGS__))n->function)
  431. #define M(e) te_eval(n->parameters[e])
  432. double te_eval(const te_expr *n) {
  433. if (!n) return NAN;
  434. switch(TYPE_MASK(n->type)) {
  435. case TE_CONSTANT: return n->value;
  436. case TE_VARIABLE: return *n->bound;
  437. case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3:
  438. case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7:
  439. switch(ARITY(n->type)) {
  440. case 0: return TE_FUN(void)();
  441. case 1: return TE_FUN(double)(M(0));
  442. case 2: return TE_FUN(double, double)(M(0), M(1));
  443. case 3: return TE_FUN(double, double, double)(M(0), M(1), M(2));
  444. case 4: return TE_FUN(double, double, double, double)(M(0), M(1), M(2), M(3));
  445. case 5: return TE_FUN(double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4));
  446. case 6: return TE_FUN(double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5));
  447. 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));
  448. default: return NAN;
  449. }
  450. case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3:
  451. case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
  452. switch(ARITY(n->type)) {
  453. case 0: return TE_FUN(void*)(n->parameters[0]);
  454. case 1: return TE_FUN(void*, double)(n->parameters[1], M(0));
  455. case 2: return TE_FUN(void*, double, double)(n->parameters[2], M(0), M(1));
  456. case 3: return TE_FUN(void*, double, double, double)(n->parameters[3], M(0), M(1), M(2));
  457. case 4: return TE_FUN(void*, double, double, double, double)(n->parameters[4], M(0), M(1), M(2), M(3));
  458. case 5: return TE_FUN(void*, double, double, double, double, double)(n->parameters[5], M(0), M(1), M(2), M(3), M(4));
  459. 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));
  460. 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));
  461. default: return NAN;
  462. }
  463. default: return NAN;
  464. }
  465. }
  466. #undef TE_FUN
  467. #undef M
  468. static void optimize(te_expr *n) {
  469. /* Evaluates as much as possible. */
  470. if (n->type == TE_CONSTANT) return;
  471. if (n->type == TE_VARIABLE) return;
  472. /* Only optimize out functions flagged as pure. */
  473. if (IS_PURE(n->type)) {
  474. const int arity = ARITY(n->type);
  475. int known = 1;
  476. int i;
  477. for (i = 0; i < arity; ++i) {
  478. optimize(n->parameters[i]);
  479. if (((te_expr*)(n->parameters[i]))->type != TE_CONSTANT) {
  480. known = 0;
  481. }
  482. }
  483. if (known) {
  484. const double value = te_eval(n);
  485. te_free_parameters(n);
  486. n->type = TE_CONSTANT;
  487. n->value = value;
  488. }
  489. }
  490. }
  491. te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error) {
  492. state s;
  493. s.start = s.next = expression;
  494. s.lookup = variables;
  495. s.lookup_len = var_count;
  496. next_token(&s);
  497. te_expr *root = list(&s);
  498. if (s.type != TOK_END) {
  499. te_free(root);
  500. if (error) {
  501. *error = (s.next - s.start);
  502. if (*error == 0) *error = 1;
  503. }
  504. return 0;
  505. } else {
  506. optimize(root);
  507. if (error) *error = 0;
  508. return root;
  509. }
  510. }
  511. double te_interp(const char *expression, int *error) {
  512. te_expr *n = te_compile(expression, 0, 0, error);
  513. double ret;
  514. if (n) {
  515. ret = te_eval(n);
  516. te_free(n);
  517. } else {
  518. ret = NAN;
  519. }
  520. return ret;
  521. }
  522. static void pn (const te_expr *n, int depth) {
  523. int i, arity;
  524. printf("%*s", depth, "");
  525. switch(TYPE_MASK(n->type)) {
  526. case TE_CONSTANT: printf("%f\n", n->value); break;
  527. case TE_VARIABLE: printf("bound %p\n", n->bound); break;
  528. case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3:
  529. case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7:
  530. case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3:
  531. case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
  532. arity = ARITY(n->type);
  533. printf("f%d", arity);
  534. for(i = 0; i < arity; i++) {
  535. printf(" %p", n->parameters[i]);
  536. }
  537. printf("\n");
  538. for(i = 0; i < arity; i++) {
  539. pn(n->parameters[i], depth + 1);
  540. }
  541. break;
  542. }
  543. }
  544. void te_print(const te_expr *n) {
  545. pn(n, 0);
  546. }