Skip to content

Commit

Permalink
Add bitwise operators for i32 (#123)
Browse files Browse the repository at this point in the history
  • Loading branch information
antocuni authored Feb 22, 2025
2 parents 088f19d + 7d6de1a commit 0e4a909
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 0 deletions.
5 changes: 5 additions & 0 deletions spy/backend/c/cwriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ def fmt_expr_BinOp(self, binop: ast.BinOp) -> C.Expr:
FQN('operator::i32_mul'): '*',
FQN('operator::i32_div'): '/', # XXX: floor or int division?
FQN('operator::i32_mod'): '%',
FQN('operator::i32_lshift'): '<<',
FQN('operator::i32_rshift'): '>>',
FQN('operator::i32_and'): '&',
FQN('operator::i32_or'): '|',
FQN('operator::i32_xor'): '^',
FQN('operator::i32_eq') : '==',
FQN('operator::i32_ne') : '!=',
FQN('operator::i32_lt') : '<',
Expand Down
5 changes: 5 additions & 0 deletions spy/backend/spy.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ def fmt_expr_BinOp(self, binop: ast.BinOp) -> str:
fmt_expr_Mul = fmt_expr_BinOp
fmt_expr_Div = fmt_expr_BinOp
fmt_expr_Mod = fmt_expr_BinOp
fmt_expr_LShift = fmt_expr_BinOp
fmt_expr_RShift = fmt_expr_BinOp
fmt_expr_BitAnd = fmt_expr_BinOp
fmt_expr_BitOr = fmt_expr_BinOp
fmt_expr_BitXor = fmt_expr_BinOp
fmt_expr_Eq = fmt_expr_BinOp
fmt_expr_NotEq = fmt_expr_BinOp
fmt_expr_Lt = fmt_expr_BinOp
Expand Down
5 changes: 5 additions & 0 deletions spy/doppler.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ def shift_expr_BinOp(self, binop: ast.BinOp) -> ast.Expr:
shift_expr_Mul = shift_expr_BinOp
shift_expr_Div = shift_expr_BinOp
shift_expr_Mod = shift_expr_BinOp
shift_expr_LShift = shift_expr_BinOp
shift_expr_RShift = shift_expr_BinOp
shift_expr_BitAnd = shift_expr_BinOp
shift_expr_BitOr = shift_expr_BinOp
shift_expr_BitXor = shift_expr_BinOp
shift_expr_Eq = shift_expr_BinOp
shift_expr_NotEq = shift_expr_BinOp
shift_expr_Lt = shift_expr_BinOp
Expand Down
17 changes: 17 additions & 0 deletions spy/tests/compiler/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,23 @@ def mod(x: i32, y: i32) -> i32: return x % y
assert mod.div(10, 3) == 3
assert mod.mod(10, 3) == 1

def test_i32_BitwiseOp(self):
mod = self.compile("""
def shl(x: i32, y: i32) -> i32: return x << y
def shr(x: i32, y: i32) -> i32: return x >> y
def b_and(x: i32, y: i32) -> i32: return x & y
def b_or(x: i32, y: i32) -> i32: return x | y
def b_xor(x: i32, y: i32) -> i32: return x ^ y
""")
assert mod.shl(128, 4) == 128 << 4
assert mod.shr(128, 4) == 128 >> 4
assert mod.b_and(7, 3) == 7 & 3
assert mod.b_and(127, 7) == 127 & 7
assert mod.b_or(127, 123) == 127 | 123
assert mod.b_or(127, 0) == 127 | 0
assert mod.b_xor(16, 15) == 16 ^ 15
assert mod.b_xor(16, 0) == 16 ^ 0

def test_void_return(self):
mod = self.compile("""
var x: i32 = 0
Expand Down
10 changes: 10 additions & 0 deletions spy/tests/test_backend_spy.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ def foo() -> void:
a * b
a / b
a % b
a << b
a >> b
a & b
a | b
a ^ b
""")
self.assert_dump(r"""
def foo() -> void:
Expand All @@ -67,6 +72,11 @@ def foo() -> void:
a * b
a / b
a % b
a << b
a >> b
a & b
a | b
a ^ b
""")

def test_vardef(self):
Expand Down
5 changes: 5 additions & 0 deletions spy/vm/astframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,11 @@ def eval_expr_BinOp(self, binop: ast.BinOp) -> W_OpArg:
eval_expr_Mul = eval_expr_BinOp
eval_expr_Div = eval_expr_BinOp
eval_expr_Mod = eval_expr_BinOp
eval_expr_LShift = eval_expr_BinOp
eval_expr_RShift = eval_expr_BinOp
eval_expr_BitAnd = eval_expr_BinOp
eval_expr_BitOr = eval_expr_BinOp
eval_expr_BitXor = eval_expr_BinOp
eval_expr_Eq = eval_expr_BinOp
eval_expr_NotEq = eval_expr_BinOp
eval_expr_Lt = eval_expr_BinOp
Expand Down
5 changes: 5 additions & 0 deletions spy/vm/modules/operator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ def op_fast_call(vm: 'SPyVM', w_func: W_Func,
'*': OP.w_MUL,
'/': OP.w_DIV,
'%': OP.w_MOD,
'<<': OP.w_LSHIFT,
'>>': OP.w_RSHIFT,
'&': OP.w_AND,
'|': OP.w_OR,
'^': OP.w_XOR,
'==': OP.w_EQ,
'!=': OP.w_NE,
'<': OP.w_LT,
Expand Down
25 changes: 25 additions & 0 deletions spy/vm/modules/operator/binop.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
MM.register('*', 'i32', 'i32', OP.w_i32_mul)
MM.register('/', 'i32', 'i32', OP.w_i32_div)
MM.register('%', 'i32', 'i32', OP.w_i32_mod)
MM.register('<<', 'i32', 'i32', OP.w_i32_lshift)
MM.register('>>', 'i32', 'i32', OP.w_i32_rshift)
MM.register('&', 'i32', 'i32', OP.w_i32_and)
MM.register('|', 'i32', 'i32', OP.w_i32_or)
MM.register('^', 'i32', 'i32', OP.w_i32_xor)
MM.register('==', 'i32', 'i32', OP.w_i32_eq)
MM.register('!=', 'i32', 'i32', OP.w_i32_ne)
MM.register('<' , 'i32', 'i32', OP.w_i32_lt)
Expand Down Expand Up @@ -97,6 +102,26 @@ def w_DIV(vm: 'SPyVM', wop_l: W_OpArg, wop_r: W_OpArg) -> W_Func:
def w_MOD(vm: 'SPyVM', wop_l: W_OpArg, wop_r: W_OpArg) -> W_Func:
return MM.get_opimpl(vm, '%', wop_l, wop_r)

@OP.builtin_func(color='blue')
def w_LSHIFT(vm: 'SPyVM', wop_l: W_OpArg, wop_r: W_OpArg) -> W_Func:
return MM.get_opimpl(vm, '<<', wop_l, wop_r)

@OP.builtin_func(color='blue')
def w_RSHIFT(vm: 'SPyVM', wop_l: W_OpArg, wop_r: W_OpArg) -> W_Func:
return MM.get_opimpl(vm, '>>', wop_l, wop_r)

@OP.builtin_func(color='blue')
def w_AND(vm: 'SPyVM', wop_l: W_OpArg, wop_r: W_OpArg) -> W_Func:
return MM.get_opimpl(vm, '&', wop_l, wop_r)

@OP.builtin_func(color='blue')
def w_OR(vm: 'SPyVM', wop_l: W_OpArg, wop_r: W_OpArg) -> W_Func:
return MM.get_opimpl(vm, '|', wop_l, wop_r)

@OP.builtin_func(color='blue')
def w_XOR(vm: 'SPyVM', wop_l: W_OpArg, wop_r: W_OpArg) -> W_Func:
return MM.get_opimpl(vm, '^', wop_l, wop_r)

def can_use_reference_eq(vm: 'SPyVM', w_ltype: W_Type, w_rtype: W_Type) -> bool:
"""
We can use 'is' to implement 'eq' if:
Expand Down
20 changes: 20 additions & 0 deletions spy/vm/modules/operator/opimpl_i32.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ def w_i32_div(vm: 'SPyVM', w_a: W_I32, w_b: W_I32) -> W_I32:
def w_i32_mod(vm: 'SPyVM', w_a: W_I32, w_b: W_I32) -> W_I32:
return _i32_op(vm, w_a, w_b, lambda a, b: a % b)

@OP.builtin_func
def w_i32_lshift(vm: 'SPyVM', w_a: W_I32, w_b: W_I32) -> W_I32:
return _i32_op(vm, w_a, w_b, lambda a, b: a << b)

@OP.builtin_func
def w_i32_rshift(vm: 'SPyVM', w_a: W_I32, w_b: W_I32) -> W_I32:
return _i32_op(vm, w_a, w_b, lambda a, b: a >> b)

@OP.builtin_func
def w_i32_and(vm: 'SPyVM', w_a: W_I32, w_b: W_I32) -> W_I32:
return _i32_op(vm, w_a, w_b, lambda a, b: a & b)

@OP.builtin_func
def w_i32_or(vm: 'SPyVM', w_a: W_I32, w_b: W_I32) -> W_I32:
return _i32_op(vm, w_a, w_b, lambda a, b: a | b)

@OP.builtin_func
def w_i32_xor(vm: 'SPyVM', w_a: W_I32, w_b: W_I32) -> W_I32:
return _i32_op(vm, w_a, w_b, lambda a, b: a ^ b)

@OP.builtin_func
def w_i32_eq(vm: 'SPyVM', w_a: W_I32, w_b: W_I32) -> W_Bool:
return _i32_op(vm, w_a, w_b, lambda a, b: a == b)
Expand Down

0 comments on commit 0e4a909

Please sign in to comment.