Support for __radd__ feature.
I wrote this snippet for voc.
class myint(object):
"""docstring for myint"""
def __init__(self, arg):
self.arg = arg
def __radd__(self, operand):
return self.__add__(operand)
def __add__(self, operand):
return self.arg + operand
str1 = myint(10)
a = 5
print(a+str1)
python gives output of 15 as expected but voc gives this,
Exception in thread "main" TypeError: unsupported operand type(s) for +: 'int' and 'myint'
at org.python.types.Int.__add__(Int.java:221)
There aren't any tests for the above the problem. I am first time contributor here. I want to work on this functionality for voc. Any suggestions regarding the same @freakboy3742 @eliasdorneles .
Thanks
As you probably know already, __radd__ on a type is called when a type does not implement (usually by returning NotImplemented) its __add__ to handle the right-hand type. The problem is that VOC’s __add__ of int does not do that. It simply raises a TypeError (the one you saw) if the right hand operand is not one of int, float, bool, or complex.
To fix that, those magic methods either need to return NotImplemented, or explicit delegate to their r variants. I’m not sure if VOC already handles the NotImplemented mechanism, so you’ll need to do some digging on your own (or wait for someone else to clarify).
I also suspect many built-in types have this same problem on many operator methods.
I'm aware of this problem, but I haven't really dug much on it yet so far.
I figure for these cases, after exhausting the list of known basic types, we would use the Java Reflection APIs to check if the object has the method and then call it. For solving this problem, you'd probably want to dive into this Function class to see how Python function calling works w/ VOC.
Refs: #653
To do a 100% match, the magic methods would need to return NotImplemented instead of delegating to the reverse operand methods, and the logic to handle whether to call __radd__ before or after __add__ etc should be abstracted out of the individual datatypes implementations.
However, if we follow that assumption, the BinOp is being directly translated to the left.__add__(right) invocation, so that will have to change:
https://github.com/pybee/voc/blob/428af9370adc49216f147e830742d9ec0729f540/voc/python/ast.py#L888-L911
I was poking at this in #583 but:
It's largely possible to get the direct
__add__(),__radd__()methods correct by simplifying them and usually changing them to return NotImplemented, but generating the appropriate TypeError messages is a problem. Different datatypes all have edge cases for different operators, like how Bytes has a different message for + as it's internally a concat instead of addition operation.
I guess that brings us back to implementing the logic and error message generation in the datatypes... but ideally if most datatypes are similar, we'd have these in some class/interface and then let the datatypes inherit and override if necessary.