Bit shifting
This commit is contained in:
parent
75d7e05519
commit
d051160244
@ -82,7 +82,7 @@ _CRC32_Table: u32[256] = [
|
||||
]
|
||||
|
||||
def _crc32_f(crc: u32, byt: u8) -> u32:
|
||||
return (crc >> 8) ^ _CRC32_Table[(crc & 0xFF) ^ byt]
|
||||
return (crc >> 8) ^ _CRC32_Table[(crc & 0xFF) ^ u32(byt)]
|
||||
|
||||
@exported
|
||||
def crc32(data: bytes) -> u32:
|
||||
|
||||
@ -77,8 +77,11 @@ OPERATOR_MAP = {
|
||||
|
||||
U8_OPERATOR_MAP = {
|
||||
# Under the hood, this is an i32
|
||||
# Implementing XOR, OR, AND is fine since the 3 remaining
|
||||
# Implementing Right Shift XOR, OR, AND is fine since the 3 remaining
|
||||
# bytes stay zero after this operation
|
||||
# Since it's unsigned an unsigned value, Logical or Arithmetic shift right
|
||||
# are the same operation
|
||||
'>>': 'shr_u',
|
||||
'^': 'xor',
|
||||
'|': 'or',
|
||||
'&': 'and',
|
||||
@ -89,6 +92,8 @@ U32_OPERATOR_MAP = {
|
||||
'>': 'gt_u',
|
||||
'<=': 'le_u',
|
||||
'>=': 'ge_u',
|
||||
'<<': 'shl',
|
||||
'>>': 'shr_u',
|
||||
'^': 'xor',
|
||||
'|': 'or',
|
||||
'&': 'and',
|
||||
@ -99,6 +104,8 @@ U64_OPERATOR_MAP = {
|
||||
'>': 'gt_u',
|
||||
'<=': 'le_u',
|
||||
'>=': 'ge_u',
|
||||
'<<': 'shl',
|
||||
'>>': 'shr_u',
|
||||
'^': 'xor',
|
||||
'|': 'or',
|
||||
'&': 'and',
|
||||
|
||||
@ -244,6 +244,10 @@ class OurVisitor:
|
||||
operator = '-'
|
||||
elif isinstance(node.op, ast.Mult):
|
||||
operator = '*'
|
||||
elif isinstance(node.op, ast.LShift):
|
||||
operator = '<<'
|
||||
elif isinstance(node.op, ast.RShift):
|
||||
operator = '>>'
|
||||
elif isinstance(node.op, ast.BitOr):
|
||||
operator = '|'
|
||||
elif isinstance(node.op, ast.BitXor):
|
||||
@ -433,16 +437,14 @@ class OurVisitor:
|
||||
if func.returns.__class__ != func.posonlyargs[0][1].__class__:
|
||||
_raise_static_error(node, f'Expected a foldable function, {func.name} returns a {codestyle.type_(func.returns)} but expects a {codestyle.type_(func.posonlyargs[0][1])}')
|
||||
|
||||
t_u8 = module.types['u8']
|
||||
|
||||
if t_u8.__class__ != func.posonlyargs[1][1].__class__:
|
||||
if module.types['u8'].__class__ != func.posonlyargs[1][1].__class__:
|
||||
_raise_static_error(node, 'Only folding over bytes (u8) is supported at this time')
|
||||
|
||||
return Fold(
|
||||
exp_type,
|
||||
Fold.Direction.LEFT,
|
||||
func,
|
||||
self.visit_Module_FunctionDef_expr(module, function, our_locals, t_u8, node.args[1]),
|
||||
self.visit_Module_FunctionDef_expr(module, function, our_locals, func.returns, node.args[1]),
|
||||
self.visit_Module_FunctionDef_expr(module, function, our_locals, module.types['bytes'], node.args[2]),
|
||||
)
|
||||
else:
|
||||
@ -550,7 +552,7 @@ class OurVisitor:
|
||||
_raise_static_error(node, 'Expected integer value')
|
||||
|
||||
if node.value < 0 or node.value > 255:
|
||||
_raise_static_error(node, 'Integer value out of range')
|
||||
_raise_static_error(node, f'Integer value out of range; expected 0..255, actual {node.value}')
|
||||
|
||||
return ConstantUInt8(exp_type, node.value)
|
||||
|
||||
|
||||
@ -60,6 +60,34 @@ def testEntry() -> {type_}:
|
||||
assert 7 == result.returned_value
|
||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', ['u32', 'u64']) # FIXME: Support u8, requires an extra AND operation
|
||||
def test_logical_left_shift(type_):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry() -> {type_}:
|
||||
return 10 << 3
|
||||
"""
|
||||
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert 80 == result.returned_value
|
||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64'])
|
||||
def test_logical_right_shift(type_):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry() -> {type_}:
|
||||
return 10 >> 3
|
||||
"""
|
||||
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert 1 == result.returned_value
|
||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64'])
|
||||
def test_bitwise_or(type_):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user