Skip to content

Commit b29803e

Browse files
committed
lpython.py: Enhance support for UnsignedInteger
Implement operations on UnsignedInteger for CPython
1 parent f4b4062 commit b29803e

File tree

1 file changed

+146
-4
lines changed

1 file changed

+146
-4
lines changed

src/runtime/lpython/lpython.py

Lines changed: 146 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,158 @@
1414

1515
# data-types
1616

17+
class UnsignedInteger:
18+
def __init__(self, bit_width, value):
19+
if isinstance(value, UnsignedInteger):
20+
if bit_width != value.bit_width:
21+
raise ValueError(f"Bit width mismatch: {bit_width} vs {value.bit_width}")
22+
value = value.value
23+
24+
if not (0 <= value < 2**bit_width):
25+
raise ValueError(f"Value should be in range 0 to {2**bit_width-1} for a {bit_width}-bit unsigned integer.")
26+
self.bit_width = bit_width
27+
self.value = value
28+
29+
def __add__(self, other):
30+
if isinstance(other, self.__class__):
31+
return UnsignedInteger(self.bit_width, (self.value + other.value) % (2**self.bit_width))
32+
else:
33+
raise TypeError("Unsupported operand type")
34+
35+
def __sub__(self, other):
36+
if isinstance(other, self.__class__):
37+
# if self.value < other.value:
38+
# raise ValueError("Result of subtraction cannot be negative")
39+
return UnsignedInteger(self.bit_width, (self.value - other.value) % (2**self.bit_width))
40+
else:
41+
raise TypeError("Unsupported operand type")
42+
43+
def __mul__(self, other):
44+
if isinstance(other, self.__class__):
45+
return UnsignedInteger(self.bit_width, (self.value * other.value) % (2**self.bit_width))
46+
else:
47+
raise TypeError("Unsupported operand type")
48+
49+
def __div__(self, other):
50+
if isinstance(other, self.__class__):
51+
if other.value == 0:
52+
raise ValueError("Division by zero")
53+
return UnsignedInteger(self.bit_width, self.value / other.value)
54+
else:
55+
raise TypeError("Unsupported operand type")
56+
57+
def __floordiv__(self, other):
58+
if isinstance(other, self.__class__):
59+
if other.value == 0:
60+
raise ValueError("Division by zero")
61+
return UnsignedInteger(self.bit_width, self.value // other.value)
62+
else:
63+
raise TypeError("Unsupported operand type")
64+
65+
def __mod__(self, other):
66+
if isinstance(other, self.__class__):
67+
if other.value == 0:
68+
raise ValueError("Modulo by zero")
69+
return UnsignedInteger(self.bit_width, self.value % other.value)
70+
else:
71+
raise TypeError("Unsupported operand type")
72+
73+
def __pow__(self, other):
74+
if isinstance(other, self.__class__):
75+
return UnsignedInteger(self.bit_width, (self.value ** other.value) % (2**self.bit_width))
76+
else:
77+
raise TypeError("Unsupported operand type")
78+
79+
def __and__(self, other):
80+
if isinstance(other, self.__class__):
81+
return UnsignedInteger(self.bit_width, self.value & other.value)
82+
else:
83+
raise TypeError("Unsupported operand type")
84+
85+
def __or__(self, other):
86+
if isinstance(other, self.__class__):
87+
return UnsignedInteger(self.bit_width, self.value | other.value)
88+
else:
89+
raise TypeError("Unsupported operand type")
90+
91+
# unary operators
92+
def __neg__(self):
93+
return UnsignedInteger(self.bit_width, -self.value % (2**self.bit_width))
94+
95+
def __pos__(self):
96+
return UnsignedInteger(self.bit_width, self.value)
97+
98+
def __abs__(self):
99+
return UnsignedInteger(self.bit_width, abs(self.value))
100+
101+
def __invert__(self):
102+
return UnsignedInteger(self.bit_width, ~self.value % (2**self.bit_width))
103+
104+
# comparator operators
105+
def __eq__(self, other):
106+
if isinstance(other, self.__class__):
107+
return self.value == other.value
108+
else:
109+
try:
110+
return self.value == other
111+
except:
112+
raise TypeError("Unsupported operand type")
113+
114+
def __ne__(self, other):
115+
if isinstance(other, self.__class__):
116+
return self.value != other.value
117+
else:
118+
raise TypeError("Unsupported operand type")
119+
120+
def __lt__(self, other):
121+
if isinstance(other, self.__class__):
122+
return self.value < other.value
123+
else:
124+
raise TypeError("Unsupported operand type")
125+
126+
def __le__(self, other):
127+
if isinstance(other, self.__class__):
128+
return self.value <= other.value
129+
else:
130+
raise TypeError("Unsupported operand type")
131+
132+
def __gt__(self, other):
133+
if isinstance(other, self.__class__):
134+
return self.value > other.value
135+
else:
136+
raise TypeError("Unsupported operand type")
137+
138+
def __ge__(self, other):
139+
if isinstance(other, self.__class__):
140+
return self.value >= other.value
141+
else:
142+
raise TypeError("Unsupported operand type")
143+
144+
# conversion to integer
145+
def __int__(self):
146+
return self.value
147+
148+
def __str__(self):
149+
return str(self.value)
150+
151+
def __repr__(self):
152+
return f'UnsignedInteger({self.bit_width}, {str(self)})'
153+
154+
def __index__(self):
155+
return self.value
156+
157+
158+
17159
type_to_convert_func = {
18160
"i1": bool,
19161
"i8": int,
20162
"i16": int,
21163
"i32": int,
22164
"i64": int,
23-
"u8": lambda x: x,
24-
"u16": lambda x: x,
25-
"u32": lambda x: x,
26-
"u64": lambda x: x,
165+
"u8": lambda x: UnsignedInteger(8, x),
166+
"u16": lambda x: UnsignedInteger(16, x),
167+
"u32": lambda x: UnsignedInteger(32, x),
168+
"u64": lambda x: UnsignedInteger(64, x),
27169
"f32": float,
28170
"f64": float,
29171
"c32": complex,

0 commit comments

Comments
 (0)