annotate q/expr.c @ 18:f1e44afb41a3

WIP with control and DAC in sync and not hanging. Control data is wrong but baby steps.
author Daniel O'Connor <darius@dons.net.au>
date Tue, 25 Feb 2025 14:36:10 +1030
parents 388074ff9474
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
1 /* Project: Small Expression Evaluator for Q library
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
2 * Author: Richard James Howe
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
3 * License: The Unlicense
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
4 * See: <https://en.wikipedia.org/wiki/Shunting-yard_algorithm> */
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
5
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
6 #include <assert.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
7 #include <ctype.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
8 #include <limits.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
9 #include <stdarg.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
10 #include <stdio.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
11 #include <stdlib.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
12 #include <string.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
13 #include "q.h"
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
14
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
15 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
16 #define DEFAULT_STACK_SIZE (64)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
17
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
18 enum { ASSOCIATE_NONE, ASSOCIATE_LEFT, ASSOCIATE_RIGHT, };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
19 enum { LEX_NUMBER, LEX_OPERATOR, LEX_END, };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
20
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
21 static void expr_delete(qexpr_t *e) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
22 if (!e)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
23 return;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
24 free(e->ops);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
25 free(e->numbers);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
26 for (size_t i = 0; i < e->vars_max; i++) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
27 free(e->vars[i]->name);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
28 free(e->vars[i]);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
29 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
30 free(e->vars);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
31 free(e);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
32 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
33
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
34 static qexpr_t *expr_new(size_t max) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
35 max = max ? max : 64;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
36 qexpr_t *e = calloc(sizeof(*e), 1);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
37 if (!e)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
38 goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
39 e->ops = calloc(sizeof(*e->ops), max);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
40 e->numbers = calloc(sizeof(*(e->numbers)), max);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
41 if (!(e->ops) || !(e->numbers))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
42 goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
43 e->ops_max = max;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
44 e->numbers_max = max;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
45 qexpr_init(e);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
46 return e;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
47 fail:
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
48 expr_delete(e);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
49 return NULL;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
50 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
51
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
52 static qvariable_t *variable_lookup(qexpr_t *e, const char *name) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
53 assert(e);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
54 for (size_t i = 0; i < e->vars_max; i++) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
55 qvariable_t *v = e->vars[i];
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
56 if (!strcmp(v->name, name))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
57 return v;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
58 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
59 return NULL;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
60 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
61
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
62 static char *estrdup(const char *s) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
63 assert(s);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
64 const size_t l = strlen(s) + 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
65 char *r = malloc(l);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
66 return memcpy(r, s, l);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
67 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
68
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
69 static int variable_name_is_valid(const char *n) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
70 assert(n);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
71 if (!isalpha(*n) && !(*n == '_'))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
72 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
73 for (n++; *n; n++)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
74 if (!isalnum(*n) && !(*n == '_'))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
75 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
76 return 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
77 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
78
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
79 static qvariable_t *variable_add(qexpr_t *e, const char *name, q_t value) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
80 assert(e);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
81 assert(name);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
82 qvariable_t *v = variable_lookup(e, name), **vs = e->vars;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
83 if (v) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
84 v->value = value;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
85 return v;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
86 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
87 if (!variable_name_is_valid(name))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
88 return NULL;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
89 char *s = estrdup(name);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
90 vs = realloc(e->vars, (e->vars_max + 1) * sizeof(*vs));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
91 v = calloc(1, sizeof(*v));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
92 if (!vs || !v || !s)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
93 goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
94 v->name = s;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
95 v->value = value;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
96 vs[e->vars_max++] = v;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
97 e->vars = vs;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
98 return v;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
99 fail:
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
100 free(v);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
101 free(s);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
102 free(vs);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
103 if (vs != e->vars)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
104 free(e->vars);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
105 return NULL;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
106 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
107
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
108 static inline int tests(FILE *out) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
109 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
110 int report = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
111 static const struct test {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
112 int r;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
113 q_t result;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
114 const char *expr;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
115 } tests[] = { // NB. Variables defined later.
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
116 { -1, QINT( 0), "" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
117 { -1, QINT( 0), "(" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
118 { -1, QINT( 0), ")" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
119 { -1, QINT( 0), "2**3" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
120 { 0, QINT( 0), "0" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
121 { 0, QINT( 2), "1+1" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
122 { 0, -QINT( 1), "-1" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
123 { 0, QINT( 1), "--1" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
124 { 0, QINT(14), "2+(3*4)" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
125 { 0, QINT(23), "a+(b*5)" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
126 { -1, QINT(14), "(2+(3* 4)" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
127 { -1, QINT(14), "2+(3*4)(" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
128 { 0, QINT(14), "2+3*4" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
129 { 0, QINT( 0), " 2==3 " },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
130 { 0, QINT( 1), "2 ==2" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
131 { 0, QINT( 1), "2== (1+1)" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
132 //{ 0, QINT( 8), "2 pow 3" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
133 //{ -1, QINT( 0), "2pow3" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
134 { 0, QINT(20), "(2+3)*4" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
135 { 0, -QINT( 4), "(2+(-3))*4" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
136 { -1, QINT( 0), "1/0" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
137 { -1, QINT( 0), "1%0" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
138 { 0, QINT(50), "100/2" },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
139 { 0, QINT( 2), "1--1", },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
140 { 0, QINT( 0), "1---1", },
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
141 };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
142
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
143 if (fputs("Running Built In Self Tests:\n", out) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
144 report = -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
145 const size_t length = sizeof (tests) / sizeof (tests[0]);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
146 for (size_t i = 0; i < length; i++) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
147 qexpr_t *e = expr_new(64);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
148 const struct test *test = &tests[i];
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
149 if (!e) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
150 (void)fprintf(out, "test failed (unable to allocate)\n");
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
151 report = -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
152 goto end;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
153 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
154
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
155 qvariable_t *v1 = variable_add(e, "a", QINT(3));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
156 qvariable_t *v2 = variable_add(e, "b", QINT(4));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
157 qvariable_t *v3 = variable_add(e, "c", -QINT(5));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
158 if (!v1 || !v2 || !v3) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
159 (void)fprintf(out, "test failed (unable to assign variable)\n");
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
160 report = -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
161 goto end;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
162 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
163
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
164 const int r = qexpr(e, test->expr);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
165 const q_t tos = e->numbers[0];
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
166 const int pass = (r == test->r) && (r != 0 || tos == test->result);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
167 if (fprintf(out, "%s: r(%2d), eval(\"%s\") = %lg \n",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
168 pass ? " ok" : " FAIL", r, test->expr, (double)tos) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
169 report = -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
170 if (!pass) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
171 (void)fprintf(out, "\tExpected: r(%2d), %lg\n",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
172 test->r, (double)(test->result));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
173 report = -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
174 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
175 expr_delete(e);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
176 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
177 end:
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
178 if (fprintf(out, "Tests Complete: %s\n", report == 0 ? "pass" : "FAIL") < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
179 report = -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
180 return report;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
181 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
182
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
183 static qexpr_t *expr_new_with_vars(size_t max) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
184 qexpr_t *e = expr_new(max);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
185 if (!e) return NULL;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
186 if (!variable_add(e, "whole", qinfo.whole)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
187 if (!variable_add(e, "fractional", qinfo.fractional)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
188 if (!variable_add(e, "bit", qinfo.bit)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
189 if (!variable_add(e, "smallest", qinfo.min)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
190 if (!variable_add(e, "biggest", qinfo.max)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
191 if (!variable_add(e, "pi", qinfo.pi)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
192 if (!variable_add(e, "e", qinfo.e)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
193 if (!variable_add(e, "sqrt2", qinfo.sqrt2)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
194 if (!variable_add(e, "sqrt3", qinfo.sqrt3)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
195 if (!variable_add(e, "ln2", qinfo.ln2)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
196 if (!variable_add(e, "ln10", qinfo.ln10)) goto fail;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
197 return e;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
198 fail:
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
199 expr_delete(e);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
200 return NULL;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
201 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
202
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
203 static int usage(FILE *out, const char *arg0) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
204 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
205 assert(arg0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
206 return fprintf(out, "usage: %s expr\n", arg0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
207 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
208
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
209 int main(int argc, char *argv[]) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
210
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
211 if (argc == 1) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
212 if (usage(stderr, argv[0]) < 0) { return 1; }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
213 return tests(stderr);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
214 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
215
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
216 if (argc < 2) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
217 (void)fprintf(stderr, "usage: %s expr\n", argv[0]);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
218 return 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
219 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
220
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
221 int r = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
222
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
223 for (int i = 1; i < argc; i++) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
224 qexpr_t *e = expr_new_with_vars(0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
225 if (!e) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
226 (void)fprintf(stderr, "allocate failed\n");
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
227 r = 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
228 break;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
229 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
230 if (qexpr(e, argv[i]) == 0) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
231 char n[64 + 1] = { 0, };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
232 qsprint(e->numbers[0], n, sizeof n);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
233 if (printf("%s\n", n) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
234 r = 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
235 r = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
236 } else {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
237 (void)fprintf(stderr, "error: %s\n", e->error_string);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
238 r = 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
239 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
240 expr_delete(e);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
241 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
242 return r;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
243 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
244
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
245