From 44199781dc0c349bf4553f442d1e444becc956e1 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Mon, 18 Apr 2022 04:51:15 +0800 Subject: [PATCH] nac3standalone: add tests for operators --- nac3standalone/demo/src/operators.py | 257 +++++++++++++++++++++++++++ nac3standalone/src/main.rs | 8 + 2 files changed, 265 insertions(+) create mode 100644 nac3standalone/demo/src/operators.py diff --git a/nac3standalone/demo/src/operators.py b/nac3standalone/demo/src/operators.py new file mode 100644 index 000000000..0470b9698 --- /dev/null +++ b/nac3standalone/demo/src/operators.py @@ -0,0 +1,257 @@ +from __future__ import annotations + +@extern +def output_int32(x: int32): + ... +@extern +def output_uint32(x: uint32): + ... +@extern +def output_int64(x: int64): + ... +@extern +def output_uint64(x: uint64): + ... +@extern +def output_float64(x: float): + ... + +def run() -> int32: + test_int32() + test_uint32() + test_int64() + test_uint64() + test_A() + test_B() + return 0 + +def test_int32(): + a = 17 + b = 3 + output_int32(a + b) + output_int32(a - b) + output_int32(a * b) + output_int32(a // b) + output_int32(a % b) + output_int32(a | b) + output_int32(a ^ b) + output_int32(a & b) + output_int32(a << b) + output_int32(a >> b) + output_float64(a / b) + a += b + output_int32(a) + a -= b + output_int32(a) + a *= b + output_int32(a) + a //= b + output_int32(a) + a %= b + output_int32(a) + a |= b + output_int32(a) + a ^= b + output_int32(a) + a &= b + output_int32(a) + a <<= b + output_int32(a) + a >>= b + output_int32(a) + # fail because (a / b) is float + # a /= b + +def test_uint32(): + a = uint32(17) + b = uint32(3) + output_uint32(a + b) + output_uint32(a - b) + output_uint32(a * b) + output_uint32(a // b) + output_uint32(a % b) + output_uint32(a | b) + output_uint32(a ^ b) + output_uint32(a & b) + output_uint32(a << b) + output_uint32(a >> b) + output_float64(a / b) + a += b + output_uint32(a) + a -= b + output_uint32(a) + a *= b + output_uint32(a) + a //= b + output_uint32(a) + a %= b + output_uint32(a) + a |= b + output_uint32(a) + a ^= b + output_uint32(a) + a &= b + output_uint32(a) + a <<= b + output_uint32(a) + a >>= b + output_uint32(a) + +def test_int64(): + a = int64(17) + b = int64(3) + output_int64(a + b) + output_int64(a - b) + output_int64(a * b) + output_int64(a // b) + output_int64(a % b) + output_int64(a | b) + output_int64(a ^ b) + output_int64(a & b) + output_int64(a << b) + output_int64(a >> b) + output_float64(a / b) + a += b + output_int64(a) + a -= b + output_int64(a) + a *= b + output_int64(a) + a //= b + output_int64(a) + a %= b + output_int64(a) + a |= b + output_int64(a) + a ^= b + output_int64(a) + a &= b + output_int64(a) + a <<= b + output_int64(a) + a >>= b + output_int64(a) + +def test_uint64(): + a = uint64(17) + b = uint64(3) + output_uint64(a + b) + output_uint64(a - b) + output_uint64(a * b) + output_uint64(a // b) + output_uint64(a % b) + output_uint64(a | b) + output_uint64(a ^ b) + output_uint64(a & b) + output_uint64(a << b) + output_uint64(a >> b) + output_float64(a / b) + a += b + output_uint64(a) + a -= b + output_uint64(a) + a *= b + output_uint64(a) + a //= b + output_uint64(a) + a %= b + output_uint64(a) + a |= b + output_uint64(a) + a ^= b + output_uint64(a) + a &= b + output_uint64(a) + a <<= b + output_uint64(a) + a >>= b + output_uint64(a) + +class A: + a: int32 + def __init__(self, a: int32): + self.a = a + + def __add__(self, other: A) -> A: + output_int32(self.a + other.a) + return A(self.a + other.a) + + def __sub__(self, other: A) -> A: + output_int32(self.a - other.a) + return A(self.a - other.a) + +def test_A(): + a = A(17) + b = A(3) + + c = a + b + # fail due to alloca in __add__ function + # output_int32(c.a) + + a += b + # fail due to alloca in __add__ function + # output_int32(a.a) + + a = A(17) + b = A(3) + d = a - b + # fail due to alloca in __add__ function + # output_int32(c.a) + + a -= b + # fail due to alloca in __add__ function + # output_int32(a.a) + + a = A(17) + b = A(3) + a.__add__(b) + a.__sub__(b) + + +class B: + a: int32 + def __init__(self, a: int32): + self.a = a + + def __add__(self, other: B) -> B: + output_int32(self.a + other.a) + return B(self.a + other.a) + + def __sub__(self, other: B) -> B: + output_int32(self.a - other.a) + return B(self.a - other.a) + + def __iadd__(self, other: B) -> B: + output_int32(self.a + other.a + 24) + return B(self.a + other.a + 24) + + def __isub__(self, other: B) -> B: + output_int32(self.a - other.a - 24) + return B(self.a - other.a - 24) + +def test_B(): + a = B(17) + b = B(3) + + c = a + b + # fail due to alloca in __add__ function + # output_int32(c.a) + + a += b + # fail due to alloca in __add__ function + # output_int32(a.a) + + a = B(17) + b = B(3) + d = a - b + # fail due to alloca in __add__ function + # output_int32(c.a) + + a -= b + # fail due to alloca in __add__ function + # output_int32(a.a) + + a = B(17) + b = B(3) + a.__add__(b) + a.__sub__(b) \ No newline at end of file diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs index 37925157a..6b624aa62 100644 --- a/nac3standalone/src/main.rs +++ b/nac3standalone/src/main.rs @@ -205,6 +205,14 @@ fn main() { continue; } + // still needs to skip this `from __future__ import annotations` because this seems to be + // magic in python and there seems no way to patch it from another module.. + if matches!( + &stmt.node, + StmtKind::ImportFrom { module, names, .. } + if module == &Some("__future__".into()) && names[0].name == "annotations".into() + ) { continue; } + let (name, def_id, ty) = composer.register_top_level(stmt, Some(resolver.clone()), "__main__".into()).unwrap();