3 # Copyright (C) 2006-2008, The Perl Foundation.
6 # the following lines re-execute this as a tcl script
7 # the \ at the end of these lines makes them a comment in tcl \
8 use lib qw(languages/tcl/lib tcl/lib lib ../lib ../../lib); # \
12 source lib/test_more.tcl
16 namespace eval test { variable x 5 }
17 is [namespace eval test {expr {$x}}] 5 {correct namespace}
21 is [expr 4.2] 4.2 {float}
22 is [expr 4.0] 4.0 {float stays float}
23 is [expr 3e2] 300.0 {scientific}
24 is [expr 3e0] 3.0 {scientific with 0 exponent}
25 is [expr 2.3e2] 230.0 {scientific with float base}
26 is [expr 2.3E2] 230.0 {scientific with float base (upper E)}
27 is [expr 2e17] 2e+17 {scientific in, scientific out}
28 eval_is {expr 3e2.0} \
29 {missing operator at _@_
30 in expression "3e2_@_.0"} \
31 {can only e with an integer exponent} \
32 {TODO {new behavior in tcl 8.5.1}}
35 is [expr TrUe] TrUe {true}
36 is [expr !!TrUe] 1 {true}
37 is [expr !!TrU] 1 {tru}
40 is [expr !!FaLsE] 0 {false}
41 is [expr !!FaLs] 0 {fals}
42 is [expr !!FaL] 0 {fal}
46 is [expr !!OfF] 0 {off}
48 is [expr !!YeS] 1 {yes}
54 eval_is {expr trues} \
55 {invalid bareword "trues"
56 in expression "trues";
57 should be "$trues" or "{trues}" or "trues(...)" or ...} {trues} \
58 {TODO {new behavior in tcl 8.5.1}}
59 eval_is {expr falses} \
60 {invalid bareword "falses"
61 in expression "falses";
62 should be "$falses" or "{falses}" or "falses(...)" or ...} {falses} \
63 {TODO {new behavior in tcl 8.5.1}}
65 is [expr 0b1001] 9 {binary}
66 is [expr 0b10] 2 {binary}
67 is [expr 0b101010] 42 {binary}
69 eval_is {expr {}} {empty expression
70 in expression ""} {empty expr}
73 is [expr -2] -2 {unary -}
74 is [expr +2] 2 {unary +}
75 is [expr +2.0] 2.0 {unary + (float)}
76 is [expr ~0] -1 {unary ~}
77 is [expr !2] 0 {unary !}
78 is [expr !true] 0 {unary ! - boolean}
79 is [expr !!2] 1 {double unary !}
81 # simple unary ops - stringified args
82 is [expr {-"2"}] -2 {unary -}
83 is [expr {+"2"}] 2 {unary +}
84 is [expr {~"0"}] -1 {unary ~}
85 is [expr {!"2"}] 0 {unary !}
86 is [expr {!!"2"}] 1 {double unary !}
88 # simple unary ops - octal
90 # simple binary ops - integer
91 is [expr 2 ** 3] 8 {pow}
92 is [expr 0 ** 1] 0 {pow}
93 is [expr 0 ** 0] 1 {pow}
94 eval_is {expr 0 ** -1} {exponentiation of zero by negative power} \
95 {pow of 0 with neg exp}
96 is [expr 2 * 3] 6 {mul}
97 is [expr 6 / 2] 3 {times}
98 is [expr 3 % 2] 1 {remainder}
99 is [expr 2 + 3] 5 {plus}
100 is [expr 2 - 3] -1 {minus}
101 is [expr 16 << 2] 64 {left shift}
102 is [expr 16 >> 2] 4 {right shift}
103 is [expr 5 & 6] 4 {&}
104 is [expr 5 | 6] 7 {|}
105 is [expr 5 ^ 6] 3 {^}
108 is [expr {${j}}] 7 {braced variable names}
109 is [expr {"$j"}] 7 {variables in quotes}
110 is [expr {"#$j"}] #7 {variables in quotes after literal}
111 is [expr {"$"}] $ {dollar-sign in quotes}
112 is [expr {"[set j]"}] 7 {commands in quotes}
116 expr {$hash(${foo}bar)}
117 ] 5 {variables - complex array index}
119 is [expr {1 ? 14 : [expr {}]}] 14 \
120 {make sure expr errors happen at runtime}
123 is [expr {"foo"}] foo {non-numeric string}
124 is [expr {"0001234"}] 668 {string octal}
125 is [expr {"0o1234"}] 668 {string 0o octal}
127 is [expr {$j}] 668 {variable octal}
129 # simple binary ops - stringified integers
130 is [expr {2 ** "3"}] 8 {pow "}
131 is [expr {"2" ** 3}] 8 {pow "}
132 is [expr {2 * "3"}] 6 {mul "}
133 is [expr {"2" * 3}] 6 {mul "}
134 is [expr {6 / "2"}] 3 {times "}
135 is [expr {"6" / 2}] 3 {times "}
136 is [expr {3 % "2"}] 1 {remainder "}
137 is [expr {"3" % 2}] 1 {remainder "}
138 is [expr {2 + "3"}] 5 {plus "}
139 is [expr {"2" + 3}] 5 {plus "}
140 is [expr {2 - "3"}] -1 {minus "}
141 is [expr {"2" - 3}] -1 {minus "}
142 is [expr {16 << "2"}] 64 {left shift "}
143 is [expr {"16" << 2}] 64 {left shift "}
144 is [expr {16 >> "2"}] 4 {right shift "}
145 is [expr {"16" >> 2}] 4 {right shift "}
146 is [expr {5 & "6"}] 4 {& "}
147 is [expr {"5" & 6}] 4 {& "}
148 is [expr {5 | "6"}] 7 {| "}
149 is [expr {"5" | 6}] 7 {| "}
150 is [expr {5 ^ "6"}] 3 {^ "}
151 is [expr {"5" ^ 6}] 3 {^ "}
154 is [expr 10<9] 0 {lt, numeric, not alpha}
155 is [expr 2<3] 1 {lt, true}
156 is [expr 3<2] 0 {lt, false}
157 is [expr 3>2] 1 {gt, true}
158 is [expr 2>3] 0 {gt, false}
159 is [expr 2<=3] 1 {lte, lt}
160 is [expr 3<=2] 0 {lte, gt}
161 is [expr 3<=3] 1 {lte, eq}
162 is [expr 3>=2] 1 {gte, gt}
163 is [expr 2>=3] 0 {gte, lt}
164 is [expr 3>=3] 1 {gte, eq}
165 is [expr 2==2] 1 {==, eq}
166 is [expr 2==1] 0 {==, ne}
167 is [expr 1!=1] 0 {!=, eq}
168 is [expr 2!=1] 1 {!=, ne}
170 is [expr {[list \;] == {{;}}}] 1 {==, string and list}
171 is [expr {[list \;] != {{;}}}] 0 {!=, string and list}
173 # short circuting ops
174 is [expr 2&&2] 1 {&&}
175 is [expr {2>=2 && 2>=2}] 1 {&&}
176 is [expr 2&&0] 0 {&&}
177 is [expr 0&&2] 0 {&&}
178 is [expr 0&&0] 0 {&&}
179 is [expr 2||2] 1 {||}
180 is [expr 2||0] 1 {||}
181 is [expr 0||2] 1 {||}
182 is [expr 0||0] 0 {||}
184 # invalid (string) operands for some unary ops
185 set ops_list [list - + ~ !]
186 foreach operator $ops_list {
187 eval_is "expr {${operator}\"a\"}" \
188 "can't use non-numeric string as operand of \"$operator\"" \
189 "string unary $operator"
190 eval_is "expr {${operator}\"\"}" \
191 "can't use empty string as operand of \"$operator\"" \
192 "string unary $operator"
195 # invalid (string) operands for some binary ops
196 set ops_list [list ** * / % + - << >> & | ^]
197 foreach operator $ops_list {
198 eval_is "expr {\"a\" $operator \"b\"}" \
199 "can't use non-numeric string as operand of \"$operator\"" \
201 eval_is "expr {\"\" $operator \"\"}" \
202 "can't use empty string as operand of \"$operator\"" \
206 # invalid (string) operands for logical ops
207 set logic_ops_list [list && ||]
208 foreach operator $logic_ops_list {
209 eval_is "expr {\"a\" $operator \"b\"}" \
210 {expected boolean value but got "a"} \
212 eval_is "expr {\"\" $operator \"\"}" \
213 {expected boolean value but got ""} \
217 is [expr bool(4)] 1 {bool - true}
218 is [expr bool("yes")] 1 {bool - yes}
219 is [expr bool(0)] 0 {bool - false}
220 is [expr bool("no")] 0 {bool - no}
221 eval_is {expr bool("foo")} {expected boolean value but got "foo"} {bool - bad value}
222 eval_is {expr entier("foo")} {expected number but got "foo"} {entier - bad value}
224 set TODO {TODO "correct precision"}
226 # math functions, happy path
229 is [expr abs(1.0)] 1.0
230 is [expr abs(-1.0)] 1.0
231 is [expr acos(0)] 1.5707963267948966 {} $TODO
232 is [expr asin(1)] 1.5707963267948966 {} $TODO
233 is [expr atan(1)] 0.7853981633974483
234 is [expr atan2(4,5)] 0.6747409422235526
235 is [expr ceil(4.6)] 5.0
236 is [expr ceil(-1.6)] -1.0
238 is [expr cosh(1)] 1.5430806348152437 {} $TODO
239 is [expr double(5)] 5.0
240 is [expr entier(3)] 3
241 is [expr entier(3.5)] 3
242 is [expr exp(1)] 2.718281828459045
243 is [expr floor(0.1)] 0.0
244 is [expr floor(0.0)] 0.0
245 is [expr floor(-0.1)] -1.0
246 is [expr fmod(3,2)] 1.0
247 is [expr fmod(-4, -1)] -0.0 {} $TODO
248 is [expr hypot(3,4)] 5.0
249 is [expr hypot(-3,4)] 5.0
251 is [expr log(32)] 3.4657359027997265 {} $TODO
252 is [expr log10(32)] 1.505149978319906
253 is [expr max(1,4,2)] 4
254 is [expr min(1,4,2)] 1
255 is [expr pow(2,10)] 1024.0
256 is [expr round(4.5)] 5
257 is [expr round(5.5)] 6
258 is [expr round(4.4)] 4
260 is [expr sin(1)] 0.8414709848078965
261 is [expr sinh(1)] 1.1752011936438014 {} $TODO
262 is [expr sqrt(64)] 8.0
263 is [expr tan(1)] 1.5574077246549023 {} $TODO
264 is [expr tanh(1)] 0.7615941559557649
266 # math functions, stringified numeric args
267 is [expr abs("-1")] 1
268 is [expr acos("0")] 1.5707963267948966 {} $TODO
269 is [expr asin("1")] 1.5707963267948966 {} $TODO
270 is [expr atan("1")] 0.7853981633974483
271 is [expr atan2("4",5)] 0.6747409422235526
272 is [expr atan2(4,"5")] 0.6747409422235526
273 is [expr atan2("4","5")] 0.6747409422235526
274 is [expr ceil("4.6")] 5.0
275 is [expr ceil("-1.6")] -1.0
276 is [expr cos("0")] 1.0
277 is [expr cosh("1")] 1.5430806348152437 {} $TODO
278 is [expr double("5")] 5.0
279 is [expr entier("3.4")] 3
280 is [expr exp("1")] 2.718281828459045
281 is [expr fmod("3",2)] 1.0
282 is [expr fmod(3,"2")] 1.0
283 is [expr fmod("3","2")] 1.0
284 is [expr hypot("3",4)] 5.0
285 is [expr hypot(3,"4")] 5.0
286 is [expr hypot("3","4")] 5.0
287 is [expr int("4.6")] 4
288 is [expr log("32")] 3.4657359027997265 {} $TODO
289 is [expr log10("32")] 1.505149978319906
290 is [expr pow("2",10)] 1024.0
291 is [expr pow(2,"10")] 1024.0
292 is [expr pow("2","10")] 1024.0
293 is [expr round("4.5")] 5
294 is [expr sin("1")] 0.8414709848078965
295 is [expr sinh("1")] 1.1752011936438014 {} $TODO
296 is [expr sqrt("64")] 8.0
297 is [expr tan("1")] 1.5574077246549023 {} $TODO
298 is [expr tanh("1")] 0.7615941559557649
300 eval_is {expr exp(exp(50))} Inf Inf {TODO unimplemented}
302 # unary math functions, invalid string ops.
304 [list acos asin atan cos cosh exp floor log log10 sin sinh sqrt tan tanh]
305 foreach function $function_list {
306 eval_is "expr ${function}(\"a\")" \
307 {expected floating-point number but got "a"} \
310 eval_is {expr {~2.0}} {can't use floating-point value as operand of "~"} \
311 {can't use floating-point value as operand of "~"}
313 # test namespaces with operators
314 is [namespace eval lib {if {+2} {}}] {} {[expr] in a namespace}
317 set TODO {TODO "pending Inf implementation"}
319 eval_is {expr inf} Inf {infinity lc} $TODO
320 eval_is {expr iNf} Inf {infinity mixed case} $TODO
321 eval_is {expr inf + inf} Inf {infinity add} $TODO
322 eval_is {expr inf - inf} \
323 {domain error: argument not in valid range} {infinity subtract} \
325 eval_is {expr sin(inf)} \
326 {domain error: argument not in valid range} {infinity function} \
328 eval_is {expr inf/0} Inf {infinity trumps div by 0} $TODO
329 eval_is {expr 0/inf} 0.0 {div by infinity} $TODO
330 eval_is {expr 0 < inf} 1 {infinite comparison} $TODO
332 eval_is {expr 3/0} {divide by zero} {divide by zero}
335 # not a number tests.
336 set TODO {TODO "pending NaN implementation"}
339 {domain error: argument not in valid range} {NaN lc} \
342 {domain error: argument not in valid range} {NaN mixed case} \
344 eval_is {expr nan/0} \
345 {can't use non-numeric floating-point value as operand of "/"} \
346 {nan trumps div by 0} \
348 foreach function $function_list {
349 eval_is "expr ${function}(nan)" \
350 {floating point value is Not a Number} \
354 foreach operator $ops_list {
355 eval_is "expr nan $operator nan" \
356 "can't use non-numeric floating-point value as operand of \"$operator\"" \
357 "nan $operator nan" \
362 # variable expansions..
366 ] 2 {array variables}
370 ] 3 {_, 0 in varnames}
373 is [expr {[]}] {} {empty command}
375 expr {[list a] eq [list a]}
376 ] 1 {command expansion inside, list types.}
378 expr {[set a a] eq [set b a]}
379 ] 1 {command expansion inside, string types}
382 # XXX add tests for ::tcl::mathfunc
385 is [set tcl_precision 3; expr 1/3.] 0.333 { precision 3}
386 is [set tcl_precision 7; expr 1/3.] 0.3333333 { precision 7}
387 is [set tcl_precision 12; expr 1/3.] 0.333333333333 { precision 12}
389 # blocker bugs for t_tcl/expr.t parsing.
390 set TODO {TODO "awaiting real bigint support"}
391 eval_is {expr (1<<63)-1} 9223372036854775807 {expr-32.4} $TODO
392 eval_is {expr -2147483648} -2147483648 {expr-46.17} $TODO
393 eval_is {expr 9223372036854775808} 9223372036854775808 {expr-46.19} $TODO