1 | # If the number of args is odd then the last arg is the default result.
|
2 |
|
3 |
|
4 |
|
5 | Eval_test = ->
|
6 | orig = p1
|
7 | p1 = cdr(p1)
|
8 | while (iscons(p1))
|
9 |
|
10 | # odd number of parameters means that the
|
11 | # last argument becomes the default case
|
12 | # i.e. the one without a test.
|
13 | if (cdr(p1) == symbol(NIL))
|
14 | push(car(p1)); # default case
|
15 | Eval()
|
16 | return
|
17 |
|
18 | # load the next test and eval it
|
19 | push(car(p1))
|
20 | Eval_predicate()
|
21 | p2 = pop()
|
22 | if isone(p2)
|
23 | # test succesful, we found out output
|
24 | push(cadr(p1))
|
25 | Eval()
|
26 | return
|
27 | else if !iszero(p2)
|
28 | # we couldn't determine the result
|
29 | # of a test. This means we can't conclude
|
30 | # anything about the result of the
|
31 | # overall test, so we must bail
|
32 | # with the unevalled test
|
33 | push orig
|
34 | return
|
35 |
|
36 | # test unsuccessful, continue to the
|
37 | # next pair of test,value
|
38 | p1 = cddr(p1)
|
39 |
|
40 | # no test matched and there was no
|
41 | # catch-all case, so we return zero.
|
42 | push_integer 0
|
43 |
|
44 | # we test A==B by first subtracting and checking if we symbolically
|
45 | # get zero. If not, we evaluate to float and check if we get a zero.
|
46 | # If we get another NUMBER then we know they are different.
|
47 | # If we get something else, then we don't know and we return the
|
48 | # unaveluated test, which is the same as saying "maybe".
|
49 | Eval_testeq = ->
|
50 | # first try without simplifyng both sides
|
51 | orig = p1
|
52 | push(cadr(p1))
|
53 | Eval()
|
54 | push(caddr(p1))
|
55 | Eval()
|
56 | subtract()
|
57 | subtractionResult = pop()
|
58 | if (iszero(subtractionResult))
|
59 | p1 = subtractionResult
|
60 | push_integer(1)
|
61 | else
|
62 | # they don't seem equal but
|
63 | # let's try again after doing
|
64 | # a simplification on both sides
|
65 | push(cadr(p1))
|
66 | Eval()
|
67 | simplify()
|
68 | push(caddr(p1))
|
69 | Eval()
|
70 | simplify()
|
71 | subtract()
|
72 | p1 = pop()
|
73 |
|
74 | if (iszero(p1))
|
75 | # if we get symbolically to a zero
|
76 | # then we have perfect equivalence.
|
77 | push_integer(1)
|
78 | else
|
79 | # let's try to evaluate to a float
|
80 | push p1
|
81 | yyfloat()
|
82 | p1 = pop()
|
83 | if (iszero(p1))
|
84 | # if we got to zero then fine
|
85 | push_integer(1)
|
86 | else if isnum(p1)
|
87 | # if we got to any other number then
|
88 | # we know they are different
|
89 | push_integer(0)
|
90 | else
|
91 | # if we didn't get to a number then we
|
92 | # don't know whether the quantities are
|
93 | # different so do nothing
|
94 | push orig
|
95 |
|
96 | # Relational operators expect a numeric result for operand difference.
|
97 |
|
98 | Eval_testge = ->
|
99 | orig = p1
|
100 | comparison = cmp_args()
|
101 |
|
102 | if !comparison?
|
103 | push orig
|
104 | return
|
105 |
|
106 | if ( comparison >= 0)
|
107 | push_integer(1)
|
108 | else
|
109 | push_integer(0)
|
110 |
|
111 | Eval_testgt = ->
|
112 | orig = p1
|
113 | comparison = cmp_args()
|
114 |
|
115 | if !comparison?
|
116 | push orig
|
117 | return
|
118 |
|
119 | if ( comparison > 0)
|
120 | push_integer(1)
|
121 | else
|
122 | push_integer(0)
|
123 |
|
124 | Eval_testle = ->
|
125 | orig = p1
|
126 | comparison = cmp_args()
|
127 |
|
128 | if !comparison?
|
129 | push orig
|
130 | return
|
131 |
|
132 | if ( comparison <= 0)
|
133 | push_integer(1)
|
134 | else
|
135 | push_integer(0)
|
136 |
|
137 | Eval_testlt = ->
|
138 | orig = p1
|
139 | comparison = cmp_args()
|
140 |
|
141 | if !comparison?
|
142 | push orig
|
143 | return
|
144 |
|
145 | if ( comparison < 0)
|
146 | push_integer(1)
|
147 | else
|
148 | push_integer(0)
|
149 |
|
150 | # not definition
|
151 | Eval_not = ->
|
152 | push(cadr(p1))
|
153 | Eval_predicate()
|
154 | p1 = pop()
|
155 | if (iszero(p1))
|
156 | push_integer(1)
|
157 | else
|
158 | push_integer(0)
|
159 |
|
160 | ### and =====================================================================
|
161 |
|
162 | Tags
|
163 | ----
|
164 | scripting, JS, internal, treenode, general concept
|
165 |
|
166 | Parameters
|
167 | ----------
|
168 | a,b,...
|
169 |
|
170 | General description
|
171 | -------------------
|
172 | Logical-and of predicate expressions.
|
173 |
|
174 | ###
|
175 |
|
176 | # and definition
|
177 | Eval_and = ->
|
178 | p1 = cdr(p1)
|
179 | while (iscons(p1))
|
180 | push(car(p1))
|
181 | Eval_predicate()
|
182 | p2 = pop()
|
183 | if (iszero(p2))
|
184 | push_integer(0)
|
185 | return
|
186 | p1 = cdr(p1)
|
187 | push_integer(1)
|
188 |
|
189 | # or definition
|
190 | Eval_or = ->
|
191 | p1 = cdr(p1)
|
192 | while (iscons(p1))
|
193 | push(car(p1))
|
194 | Eval_predicate()
|
195 | p2 = pop()
|
196 | if (!iszero(p2))
|
197 | push_integer(1)
|
198 | return
|
199 | p1 = cdr(p1)
|
200 | push_integer(0)
|
201 |
|
202 | # use subtract for cases like A < A + 1
|
203 |
|
204 | # TODO you could be smarter here and
|
205 | # simplify both sides only in the case
|
206 | # of "relational operator: cannot determine..."
|
207 | # a bit like we do in Eval_testeq
|
208 | cmp_args = ->
|
209 | t = 0
|
210 |
|
211 | push(cadr(p1))
|
212 | Eval()
|
213 | simplify()
|
214 | push(caddr(p1))
|
215 | Eval()
|
216 | simplify()
|
217 | subtract()
|
218 | p1 = pop()
|
219 |
|
220 | # try floating point if necessary
|
221 |
|
222 | if (p1.k != NUM && p1.k != DOUBLE)
|
223 | push(p1)
|
224 | yyfloat()
|
225 | Eval()
|
226 | p1 = pop()
|
227 |
|
228 | if (iszero(p1))
|
229 | return 0
|
230 |
|
231 | switch (p1.k)
|
232 | when NUM
|
233 | if (MSIGN(p1.q.a) == -1)
|
234 | t = -1
|
235 | else
|
236 | t = 1
|
237 | when DOUBLE
|
238 | if (p1.d < 0.0)
|
239 | t = -1
|
240 | else
|
241 | t = 1
|
242 | else
|
243 | t = null
|
244 |
|
245 | return t
|
246 |
|
247 |
|