QUERY · ISSUE
Viper bug: integers > 0x3fffffff appear as python objects
bug
The bug presumably is a result of the same logic as the now closed #8956 (perhaps the fix is also as simple).
Integers outside the mpy small int range ( > 0x3fffffff) are handled as python objects in viper.
This rather should happen with integers > 0xffffffff.
Code to illustrate the issue:
# @micropython.viper
# def largeint(a) -> int:
# b = a & 0xfffffffe
# return b # -> ViperTypeError: return expected 'int' but got 'object'
# print(largeint(3))
@micropython.viper
def largeint2(a):
b = a & 0xfffffffe # works, but b is now a python object rather than a viper integer
return b
print(largeint2(3))
gv = b'\x03\x00\x00\x00'
@micropython.viper
def and32(p:ptr32):
p[0] = p[0] & 0xfffffffe # -> ViperTypeError: can't do binary op between 'int' and 'object'
# but works with 0x3ffffffe and with int(0xfffffffe)
print('Before: ', int.from_bytes(gv, 'little')) # -> 3
and32(gv)
print('After: ', int.from_bytes(gv, 'little')) # should be 2, but does not work
CANDIDATE · ISSUE
Bug in viper code calculations involving two operands which are indexed values
bugpy-core
I found the following code to produce wrong results, both on the pyboard and the unix version (mpy v1.17).
@micropython.viper
def vtest1(gv:ptr16) -> int:
gv[0] += gv[1]<<1 # does gv[0] = gv[1] * 3 instead
return gv[0] # the same error occurs with gv:ptr18 and gv:ptr32 in vtest1
gv = b'\x03\x00\x02\x01'
print('vtest1(gv): ', vtest1(gv), ' correct: 519')
Output:
vtest1(gv): 774 correct: 519
A followup investigation revealed that the core of the issue seems to be the combination of two operands like gv[0] and gv[1]. Where
@micropython.viper
def vtest2(a:int, b:int) -> int:
c = a-b # correct
return c
print('vtest2(19, 5): ', vtest2(19, 5), ' correct: 14')
print('vtest2(5, 19): ', vtest2(5, 19), ' correct: -14')
@micropython.viper
def vtest3(gv:ptr16, a:int) -> int:
c = gv[1] - a # correct
return c
@micropython.viper
def vtest4(gv:ptr16, a:int) -> int:
c = a - gv[1] # correct
return c
gv = b'\x03\x00\x02\x01'
print('vtest3(gv, 19): ', vtest3(gv, 19), ' correct: 239')
gv = b'\x03\x00\x02\x01'
print('vtest4(gv, 19): ', vtest4(gv, 19), ' correct: -239')
produce the correct results: Output:
vtest2(19, 5): 14 correct: 14
vtest2(5, 19): -14 correct: -14
vtest3(gv, 19): 239 correct: 239
vtest4(gv, 19): -239 correct: -239
The combination of two indexed values seems to deliver wrong results:
@micropython.viper
def vtest5(gv:ptr16) -> int:
c = gv[0] - gv[1] # wrong: 0
return c
@micropython.viper
def vtest6(gv:ptr16) -> int:
c = gv[1] - gv[0] # wrong: 0
return c
gv = b'\x03\x00\x02\x01'
print('vtest5(gv): ', vtest5(gv), ' correct: -255')
gv = b'\x03\x00\x02\x01'
print('vtest6(gv): ', vtest6(gv), ' correct: 255')
@micropython.viper
def vtest7(gv:ptr16) -> int:
c = gv[0] + gv[1] # wrong
return c
@micropython.viper
def vtest8(gv:ptr16) -> int:
c = gv[1] + gv[0] # wrong
return c
gv = b'\x03\x00\x02\x01'
print('vtest7(gv): ', vtest7(gv), ' correct: 261')
gv = b'\x03\x00\x02\x01'
print('vtest8(gv): ', vtest8(gv), ' correct: 261')
Output:
vtest5(gv): 0 correct: -255
vtest6(gv): 0 correct: 255
vtest7(gv): 516 correct: 261
vtest8(gv): 6 correct: 261