-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A prototype for solve dividing two integers #66
base: main
Are you sure you want to change the base?
Changes from 6 commits
a97fc32
6617969
d02ee92
f5f8bf8
44daba6
a7f7624
8e7eed1
a946a50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,91 @@ | |
__all__ = ['win_defs', 'CParser'] | ||
|
||
|
||
def wrap_int(t): | ||
logger.debug('wrap_int: {} {}'.format(t.dump(), type(t))) | ||
t[0] = "CInt({})".format(int(t[0], 0)) | ||
return t | ||
|
||
class CInt(int): | ||
def __new__(cls, base=10, *args, **kwargs): | ||
return super(CInt, cls).__new__(cls, base, *args, **kwargs) | ||
|
||
def __truediv__(self, other): | ||
if isinstance(other, CInt): | ||
is_positive = self >= 0 and other >= 0 | ||
return CInt(int(self) // int(other)) if is_positive else -CInt(-int(self) // int(other)) | ||
else: | ||
return super(CInt, self).__truediv__(other) | ||
|
||
def __rtruediv__(self, other): | ||
if isinstance(other, CInt): | ||
is_positive = self >= 0 and other >= 0 | ||
return CInt(int(other) // int(self)) if is_positive else -CInt(-int(other) // int(self)) | ||
else: | ||
return super(CInt, self).__rtruediv__(other) | ||
|
||
def __mod__(self, other): | ||
if isinstance(other, CInt): | ||
is_positive = self >= 0 and other >= 0 | ||
return CInt(int(self) % int(other)) if is_positive else -CInt(-int(self) % int(other)) | ||
else: | ||
return super(CInt, self).__mod__(other) | ||
|
||
def __rmod__(self, other): | ||
if isinstance(other, CInt): | ||
is_positive = self >= 0 and other >= 0 | ||
return CInt(int(other) % int(self)) if is_positive else -CInt(-int(other) % int(self)) | ||
else: | ||
return super(CInt, self).__rmod__(other) | ||
|
||
def __sub__(self, other): | ||
if isinstance(other, CInt): | ||
return CInt(int(self) - int(other)) | ||
else: | ||
return super(CInt, self).__sub__(other) | ||
|
||
def __rsub__(self, other): | ||
if isinstance(other, CInt): | ||
return CInt(int(other) - int(self)) | ||
else: | ||
return super(CInt, self).__rsub__(other) | ||
|
||
def __add__(self, other): | ||
if isinstance(other, CInt): | ||
return CInt(int(self) + int(other)) | ||
else: | ||
return super(CInt, self).__add__(other) | ||
|
||
def __radd__(self, other): | ||
if isinstance(other, CInt): | ||
return CInt(int(other) + int(self)) | ||
else: | ||
return super(CInt, self).__radd__(other) | ||
|
||
def __mul__(self, other): | ||
if isinstance(other, CInt): | ||
return CInt(int(self) * int(other)) | ||
else: | ||
return super(CInt, self).__mul__(other) | ||
|
||
def __rmul__(self, other): | ||
if isinstance(other, CInt): | ||
return CInt(int(other) * int(self)) | ||
else: | ||
return super(CInt, self).__rmul__(other) | ||
|
||
def __str__(self): | ||
return "CInt({})".format(super(CInt, self).__str__()) | ||
|
||
def __repr__(self): | ||
return "CInt({})".format(super(CInt, self).__repr__()) | ||
|
||
def __neg__(self): | ||
return CInt(-int(self)) | ||
|
||
def __pos__(self): | ||
return CInt(+int(self)) | ||
|
||
class Type(tuple): | ||
""" | ||
Representation of a C type. CParser uses this class to store the parsed | ||
|
@@ -1508,7 +1593,7 @@ def eval(self, expr, *args): | |
expr = expr.strip() | ||
cast = (lparen + self.type_spec + self.abstract_declarator + | ||
rparen).suppress() | ||
expr = (quotedString | number | cast).transformString(expr) | ||
expr = (quotedString | number_in_expr | cast).transformString(expr) | ||
if expr == '': | ||
return None | ||
return eval(expr, *args) | ||
|
@@ -1650,11 +1735,16 @@ def print_parse_results(pr, depth=0, name=''): | |
int_strip = lambda t: t[0].rstrip('UL') | ||
hexint = Regex(r'[+-]?\s*0[xX][{}]+[UL]*'.format(hexnums)).setParseAction(int_strip) | ||
decint = Regex(r'[+-]?\s*[0-9]+[UL]*').setParseAction(int_strip) | ||
integer = (hexint | decint) | ||
octal = Regex(r'[+-]?\s*0[0-7]+[UL]*').setParseAction(lambda t: int_strip(t).replace('0', '0o', 1)) | ||
integer = (hexint | octal | decint) | ||
integer.setParseAction(wrap_int) | ||
# in eval expr would not match identifier, it would match a number cause error | ||
integer_in_expr = (hexint | octal | decint) | ||
# The floating regex is ugly but it is because we do not want to match | ||
# integer to it. | ||
floating = Regex(r'[+-]?\s*((((\d(\.\d*)?)|(\.\d+))[eE][+-]?\d+)|((\d\.\d*)|(\.\d+)))') | ||
number = (floating | integer) | ||
number = (floating |integer) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. coding style: use spaces around binary operators |
||
number_in_expr = (floating |integer_in_expr) | ||
|
||
# Miscelaneous | ||
bi_operator = oneOf("+ - / * | & || && ! ~ ^ % == != > < >= <= -> . :: << >> = ? :") | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -290,6 +290,17 @@ def test_values(self): | |||||
macros['MACRO_H3'] == '0X000002UL' and | ||||||
values['MACRO_H3'] == 2) | ||||||
|
||||||
# Octal integer | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. great tests! |
||||||
assert ('MACRO_OCT1' in macros and | ||||||
macros['MACRO_OCT1'] == '+ 010' and | ||||||
values['MACRO_OCT1'] == 0o10) | ||||||
assert ('MACRO_OCT2' in macros and | ||||||
macros['MACRO_OCT2'] == '-03000U' and | ||||||
values['MACRO_OCT2'] == -0o3000) | ||||||
assert ('MACRO_OCT3' in macros and | ||||||
macros['MACRO_OCT3'] == '02UL' and | ||||||
values['MACRO_OCT3'] == 0o2) | ||||||
|
||||||
# Bit shifted hexadecimal integer | ||||||
assert ('MACRO_SH1' in macros and | ||||||
macros['MACRO_SH1'] == '(0x000000 << 1)' and | ||||||
|
@@ -566,6 +577,24 @@ def test_variables(self): | |||||
assert ('x2' in variables and | ||||||
variables['x2'] == (88342528, Type('int'))) | ||||||
|
||||||
# Test int div 9 / 2 should be 4 | ||||||
assert ('x3' in variables and | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
the indexing will anyway if the key does not exist in the dict. No need to test it separately. |
||||||
variables['x3'] == (4.5, Type('float'))) | ||||||
assert ('x4' in variables and | ||||||
variables['x4'] == (4, Type('int'))) | ||||||
assert ('x5' in variables and | ||||||
variables['x5'] == (4., Type('float'))) | ||||||
assert ('x6' in variables and | ||||||
variables['x6'] == (4., Type('float'))) | ||||||
assert ('x7' in variables and | ||||||
variables['x7'] == (4.5, Type('float'))) | ||||||
assert ('x8' in variables and | ||||||
variables['x8'] == (9., Type('float'))) | ||||||
assert ('x9' in variables and | ||||||
variables['x9'] == (-4, Type('int'))) | ||||||
assert ('x10' in variables and | ||||||
variables['x10'] == (-1, Type('int'))) | ||||||
|
||||||
# Test array handling | ||||||
assert ('array' in variables and | ||||||
variables['array'] == ([1, 3141500.0], Type('float', [2]))) | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we return a string from here? I would expect this function to return a CInt instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realise this should be part of a bigger rewrite, so no need to change in this PR.