cairo-native 0.9.0-rc.3

A compiler to convert Cairo's IR Sierra code to MLIR and execute it.
#[derive(Drop, Copy)]
struct S1 {
    a: usize,
    b: felt252,
}

#[derive(Drop, Copy)]
struct S2 {
    inner: S1,
    a: usize,
}

#[derive(Drop, Copy)]
struct S3 {
    inner: S2,
}

#[generate_trait]
impl MyImpl of MyTrait {
    fn foo(self: @S1) {}
}

impl S2Deref of crate::ops::Deref<S2> {
    type Target = S1;
    fn deref(self: S2) -> S1 {
        self.inner
    }
}

impl S3Deref of crate::ops::Deref<S3> {
    type Target = S2;
    fn deref(self: S3) -> S2 {
        self.inner
    }
}

#[test]
fn test_simple_deref() {
    let s1 = S1 { a: 1, b: 2 };
    let s2 = S2 { inner: s1, a: 3 };
    let s3 = S3 { inner: s2 };
    assert_eq!(s1.a, 1);
    assert_eq!(s2.a, 3);
    assert_eq!(s3.a, 3);
    assert_eq!(s3.inner.a, 3);
    assert_eq!(s3.inner.inner.a, 1);
    assert_eq!(s3.b, 2);
    assert_eq!(s3.inner.b, 2);
    assert_eq!(s3.foo(), ());
}

#[derive(Drop, Copy)]
enum E1 {
    V1: S1,
    V2: S1,
}

impl E1Deref of crate::ops::Deref<E1> {
    type Target = S1;
    fn deref(self: E1) -> S1 {
        match self {
            E1::V1(s) => s,
            E1::V2(s) => s,
        }
    }
}

#[test]
fn test_simple_enum_deref() {
    let s1 = S1 { a: 1, b: 2 };
    let e1 = E1::V1(s1);
    assert_eq!(e1.a, 1);
    assert_eq!(e1.b, 2);
}

#[derive(Drop, Copy)]
enum E3 {
    V1: S3,
    V2: S3,
}

impl E3Deref of crate::ops::Deref<E3> {
    type Target = S3;
    fn deref(self: E3) -> S3 {
        match self {
            E3::V1(s) => s,
            E3::V2(s) => s,
        }
    }
}

#[test]
fn test_nested_enum_deref() {
    let s1 = S1 { a: 1, b: 2 };
    let s2 = S2 { inner: s1, a: 3 };
    let s3 = S3 { inner: s2 };
    let e3 = E3::V1(s3);
    assert_eq!(e3.a, 3);
    assert_eq!(e3.inner.a, 3);
    assert_eq!(e3.inner.inner.a, 1);
    assert_eq!(e3.b, 2);
    assert_eq!(e3.inner.b, 2);
}

#[derive(Drop, Copy)]
struct S4 {
    e3: E3,
    a: usize,
}

impl S4Deref of crate::ops::Deref<S4> {
    type Target = E3;
    fn deref(self: S4) -> E3 {
        self.e3
    }
}

#[test]
fn test_struct_enum_deref() {
    let s1 = S1 { a: 1, b: 2 };
    let s2 = S2 { inner: s1, a: 3 };
    let s3 = S3 { inner: s2 };
    let e3 = E3::V1(s3);
    let s4 = S4 { e3: e3, a: 4 };
    assert_eq!(s4.a, 4);
    assert_eq!(s4.e3.a, 3);
    assert_eq!(s4.e3.inner.a, 3);
    assert_eq!(s4.e3.inner.inner.a, 1);
    assert_eq!(s4.e3.b, 2);
    assert_eq!(s4.e3.inner.b, 2);
}