1# Tests of Starlark 'int'
2# option:float
3
4load("assert.star", "assert")
5
6# basic arithmetic
7assert.eq(0 - 1, -1)
8assert.eq(0 + 1, +1)
9assert.eq(1 + 1, 2)
10assert.eq(5 + 7, 12)
11assert.eq(5 * 7, 35)
12assert.eq(5 - 7, -2)
13
14# int boundaries
15maxint64 = (1 << 63) - 1
16minint64 = -1 << 63
17maxint32 = (1 << 31) - 1
18minint32 = -1 << 31
19assert.eq(maxint64, 9223372036854775807)
20assert.eq(minint64, -9223372036854775808)
21assert.eq(maxint32, 2147483647)
22assert.eq(minint32, -2147483648)
23
24
25# truth
26def truth():
27  assert.true(not 0)
28  for m in [1, maxint32]: # Test small/big ranges
29    assert.true(123*m)
30    assert.true(-1*m)
31
32truth()
33
34# floored division
35# (For real division, see float.star.)
36def division():
37  for m in [1, maxint32]: # Test small/big ranges
38    assert.eq((100*m) // (7*m), 14)
39    assert.eq((100*m) // (-7*m), -15)
40    assert.eq((-100*m) // (7*m), -15) # NB: different from Go/Java
41    assert.eq((-100*m) // (-7*m), 14) # NB: different from Go/Java
42    assert.eq((98*m) // (7*m), 14)
43    assert.eq((98*m) // (-7*m), -14)
44    assert.eq((-98*m) // (7*m), -14)
45    assert.eq((-98*m) // (-7*m), 14)
46
47division()
48
49# remainder
50def remainder():
51  for m in [1, maxint32]: # Test small/big ranges
52    assert.eq((100*m) % (7*m), 2*m)
53    assert.eq((100*m) % (-7*m), -5*m) # NB: different from Go/Java
54    assert.eq((-100*m) % (7*m), 5*m) # NB: different from Go/Java
55    assert.eq((-100*m) % (-7*m), -2*m)
56    assert.eq((98*m) % (7*m), 0)
57    assert.eq((98*m) % (-7*m), 0)
58    assert.eq((-98*m) % (7*m), 0)
59    assert.eq((-98*m) % (-7*m), 0)
60
61remainder()
62
63# compound assignment
64def compound():
65  x = 1
66  x += 1
67  assert.eq(x, 2)
68  x -= 3
69  assert.eq(x, -1)
70  x *= 39
71  assert.eq(x, -39)
72  x //= 4
73  assert.eq(x, -10)
74  x /= -2
75  assert.eq(x, 5)
76  x %= 3
77  assert.eq(x, 2)
78  # use resolve.AllowBitwise to enable the ops:
79  x = 2
80  x &= 1
81  assert.eq(x, 0)
82  x |= 2
83  assert.eq(x, 2)
84  x ^= 3
85  assert.eq(x, 1)
86  x <<= 2
87  assert.eq(x, 4)
88  x >>=2
89  assert.eq(x, 1)
90
91compound()
92
93# int conversion
94# See float.star for float-to-int conversions.
95# We follow Python 3 here, but I can't see the method in its madness.
96# int from bool/int/float
97assert.fails(int, 'missing argument')  # int()
98assert.eq(int(False), 0)
99assert.eq(int(True), 1)
100assert.eq(int(3), 3)
101assert.eq(int(3.1), 3)
102assert.fails(lambda: int(3, base=10), "non-string with explicit base")
103assert.fails(lambda: int(True, 10), "non-string with explicit base")
104# int from string, base implicitly 10
105assert.eq(int("100000000000000000000"), 10000000000 * 10000000000)
106assert.eq(int("-100000000000000000000"), -10000000000 * 10000000000)
107assert.eq(int("123"), 123)
108assert.eq(int("-123"), -123)
109assert.eq(int("0123"), 123) # not octal
110assert.eq(int("-0123"), -123)
111assert.fails(lambda: int("0x12"), "invalid literal with base 10")
112assert.fails(lambda: int("-0x12"), "invalid literal with base 10")
113assert.fails(lambda: int("0o123"), "invalid literal.*base 10")
114assert.fails(lambda: int("-0o123"), "invalid literal.*base 10")
115# int from string, explicit base
116assert.eq(int("0"), 0)
117assert.eq(int("00"), 0)
118assert.eq(int("0", base=10), 0)
119assert.eq(int("00", base=10), 0)
120assert.eq(int("0", base=8), 0)
121assert.eq(int("00", base=8), 0)
122assert.eq(int("-0"), 0)
123assert.eq(int("-00"), 0)
124assert.eq(int("-0", base=10), 0)
125assert.eq(int("-00", base=10), 0)
126assert.eq(int("-0", base=8), 0)
127assert.eq(int("-00", base=8), 0)
128assert.eq(int("+0"), 0)
129assert.eq(int("+00"), 0)
130assert.eq(int("+0", base=10), 0)
131assert.eq(int("+00", base=10), 0)
132assert.eq(int("+0", base=8), 0)
133assert.eq(int("+00", base=8), 0)
134assert.eq(int("11", base=9), 10)
135assert.eq(int("-11", base=9), -10)
136assert.eq(int("10011", base=2), 19)
137assert.eq(int("-10011", base=2), -19)
138assert.eq(int("123", 8), 83)
139assert.eq(int("-123", 8), -83)
140assert.eq(int("0123", 8), 83) # redundant zeros permitted
141assert.eq(int("-0123", 8), -83)
142assert.eq(int("00123", 8), 83)
143assert.eq(int("-00123", 8), -83)
144assert.eq(int("0o123", 8), 83)
145assert.eq(int("-0o123", 8), -83)
146assert.eq(int("123", 7), 66) # 1*7*7 + 2*7 + 3
147assert.eq(int("-123", 7), -66)
148assert.eq(int("12", 16), 18)
149assert.eq(int("-12", 16), -18)
150assert.eq(int("0x12", 16), 18)
151assert.eq(int("-0x12", 16), -18)
152assert.eq(0x1000000000000001 * 0x1000000000000001, 0x1000000000000002000000000000001)
153assert.eq(int("1010", 2), 10)
154assert.eq(int("111111101", 2), 509)
155assert.eq(int("0b0101", 0), 5)
156assert.eq(int("0b00000", 0), 0)
157assert.eq(1111111111111111 * 1111111111111111, 1234567901234567654320987654321)
158assert.fails(lambda: int("0x123", 8), "invalid literal.*base 8")
159assert.fails(lambda: int("-0x123", 8), "invalid literal.*base 8")
160assert.fails(lambda: int("0o123", 16), "invalid literal.*base 16")
161assert.fails(lambda: int("-0o123", 16), "invalid literal.*base 16")
162assert.fails(lambda: int("0x110", 2), "invalid literal.*base 2")
163# int from string, auto detect base
164assert.eq(int("123", 0), 123)
165assert.eq(int("+123", 0), +123)
166assert.eq(int("-123", 0), -123)
167assert.eq(int("0x12", 0), 18)
168assert.eq(int("+0x12", 0), +18)
169assert.eq(int("-0x12", 0), -18)
170assert.eq(int("0o123", 0), 83)
171assert.eq(int("+0o123", 0), +83)
172assert.eq(int("-0o123", 0), -83)
173assert.fails(lambda: int("0123", 0), "invalid literal.*base 0") # valid in Python 2.7
174assert.fails(lambda: int("-0123", 0), "invalid literal.*base 0")
175# github.com/google/starlark-go/issues/108
176assert.fails(lambda: int("0Oxa", 8), "invalid literal with base 8: 0Oxa")
177# follow-on bugs to issue 108
178assert.fails(lambda: int("--4"), "invalid literal with base 10: --4")
179assert.fails(lambda: int("++4"), "invalid literal with base 10: \+\+4")
180assert.fails(lambda: int("+-4"), "invalid literal with base 10: \+-4")
181assert.fails(lambda: int("0x-4", 16), "invalid literal with base 16: 0x-4")
182
183# bitwise union (int|int), intersection (int&int), XOR (int^int), unary not (~int),
184# left shift (int<<int), and right shift (int>>int).
185# use resolve.AllowBitwise to enable the ops.
186# TODO(adonovan): this is not yet in the Starlark spec,
187# but there is consensus that it should be.
188assert.eq(1|2, 3)
189assert.eq(3|6, 7)
190assert.eq((1|2) & (2|4), 2)
191assert.eq(1 ^ 2, 3)
192assert.eq(2 ^ 2, 0)
193assert.eq(1 | 0 ^ 1, 1) # check | and ^ operators precedence
194assert.eq(~1, -2)
195assert.eq(~-2, 1)
196assert.eq(~0, -1)
197assert.eq(1 << 2, 4)
198assert.eq(2 >> 1, 1)
199assert.fails(lambda: 2 << -1, "negative shift count")
200assert.fails(lambda: 1 << 512, "shift count too large")
201
202# comparisons
203# TODO(adonovan): test: < > == != etc
204def comparisons():
205  for m in [1, maxint32/2, maxint32]: # Test small/big ranges
206    assert.lt(-2*m, -1*m)
207    assert.lt(-1*m, 0*m)
208    assert.lt(0*m, 1*m)
209    assert.lt(1*m, 2*m)
210    assert.true(2*m >= 2*m)
211    assert.true(2*m > 1*m)
212    assert.true(1*m >= 1*m)
213    assert.true(1*m > 0*m)
214    assert.true(0*m >= 0*m)
215    assert.true(0*m > -1*m)
216    assert.true(-1*m >= -1*m)
217    assert.true(-1*m > -2*m)
218
219comparisons()
220
221# precision
222assert.eq(str(maxint64), "9223372036854775807")
223assert.eq(str(maxint64+1), "9223372036854775808")
224assert.eq(str(minint64), "-9223372036854775808")
225assert.eq(str(minint64-1), "-9223372036854775809")
226assert.eq(str(minint64 * minint64), "85070591730234615865843651857942052864")
227assert.eq(str(maxint32+1), "2147483648")
228assert.eq(str(minint32-1), "-2147483649")
229assert.eq(str(minint32 * minint32), "4611686018427387904")
230assert.eq(str(minint32 | maxint32), "-1")
231assert.eq(str(minint32 & minint32), "-2147483648")
232assert.eq(str(minint32 ^ maxint32), "-1")
233assert.eq(str(minint32 // -1), "2147483648")
234
235# string formatting
236assert.eq("%o %x %d" % (0o755, 0xDEADBEEF, 42), "755 deadbeef 42")
237nums = [-95, -1, 0, +1, +95]
238assert.eq(' '.join(["%o" % x for x in nums]), "-137 -1 0 1 137")
239assert.eq(' '.join(["%d" % x for x in nums]), "-95 -1 0 1 95")
240assert.eq(' '.join(["%i" % x for x in nums]), "-95 -1 0 1 95")
241assert.eq(' '.join(["%x" % x for x in nums]), "-5f -1 0 1 5f")
242assert.eq(' '.join(["%X" % x for x in nums]), "-5F -1 0 1 5F")
243assert.eq("%o %x %d" % (123, 123, 123), "173 7b 123")
244assert.eq("%o %x %d" % (123.1, 123.1, 123.1), "173 7b 123") # non-int operands are acceptable
245assert.fails(lambda: "%d" % True, "cannot convert bool to int")
246