neural/trident/tests/imported_generics.rs

use trident::CompileOptions;
fn load(arena: &mut nox::Reduction<16384>, text: &[u8], offset: &mut usize) -> nox::Order {
    if text[*offset] == b'[' {
        *offset += 1;
        let head = load(arena, text, offset);
        *offset += 1;
        let tail = load(arena, text, offset);
        *offset += 1;
        arena.pair(head, tail).unwrap()
    } else {
        let start = *offset;
        while *offset < text.len() && text[*offset].is_ascii_digit() {
            *offset += 1;
        }
        arena
            .atom(nebu::Goldilocks::new(
                std::str::from_utf8(&text[start..*offset])
                    .unwrap()
                    .parse()
                    .unwrap(),
            ))
            .unwrap()
    }
}
fn execute(assembly: &str, subject: &str) -> u64 {
    let mut arena = nox::Reduction::<16384>::new();
    let formula = load(&mut arena, assembly.as_bytes(), &mut 0);
    let subject = load(&mut arena, subject.as_bytes(), &mut 0);
    match nox::reduce(
        &mut arena,
        subject,
        formula,
        1_000_000,
        &nox::NullCalls,
        &mut nox::NoTrace,
    ) {
        nox::Outcome::Ok(value, _) => arena.atom_value(value).unwrap().as_u64(),
        other => panic!("{other:?}"),
    }
}
#[test]
fn imported_generics_keep_lexical_sizes_and_nested_entry_layout() {
    let dir = tempfile::tempdir().unwrap();
    std::fs::write(dir.path().join("shapes.tri"),"module shapes\nconst N:U32=9\nconst K:U32=2\npub struct Pair {a:Field,b:Field}\nfn helper(x:Field)->Field{x+7}\npub fn first<M>(x:[Field;M])->Field{helper(x[0])}\npub fn outer<N>(x:[Field;N])->Field{first([11,13,17])+first(x)}\npub fn padded<N>(x:[Field;N+K])->Field{x[0]*100+x[2]}\n").unwrap();
    let entry = dir.path().join("entry.tri");
    std::fs::write(&entry,"program entry\nuse shapes\nconst K:U32=17\nfn main(x:[shapes.Pair;2])->Field{shapes.first<3>([101,103,107])+shapes.outer([19,23])+shapes.padded<1>([3,5,7])+x[1].b}").unwrap();
    for profile in ["debug", "release"] {
        let options = CompileOptions::for_profile(profile);
        let bundle = trident::compile_to_bundle(&entry, &options).unwrap();
        assert_eq!(execute(&bundle.assembly, "[13 [11 [7 [5 0]]]]"), 472);
        assert_eq!(
            bundle.assembly,
            trident::compile_to_bundle(&entry, &options)
                .unwrap()
                .assembly
        );
    }
}
#[test]
fn generic_calls_reject_bad_arity_shapes_bodies_and_dimensions() {
    let dir = tempfile::tempdir().unwrap();
    let entry = dir.path().join("entry.tri");
    for (definition, call) in [
        ("pub fn f<N,N>(x:[Field;N])->Field{x[0]}", "f<2,2>([1,2])"),
        ("pub fn f<N>(x:[Field;N])->Field{f<N+1>(x)}", "f<2>([1,2])"),
        ("pub fn f<N>(x:[Field;N])->Field{x[0]}", "f<2,3>([1,2])"),
        ("pub fn f<N>(x:[Field;N])->Field{x[0]}", "f<3>([1,2])"),
        ("pub fn f<N>(x:[Field;N])->Field{x[0]}", "f<0>([])"),
        ("pub fn f<N>(x:[Field;N])->Field{true}", "f<2>([1,2])"),
        (
            "pub fn f<N>(x:[Field;N])->Field{return true}",
            "f<2>([1,2])",
        ),
        ("pub fn f<N>(x:[Field;N])->Field{x[0]}", "f<MISSING>([1,2])"),
        (
            "pub fn f<N>(x:[Field;N])->Field{x[0]}",
            "f<18446744073709551615+1>([1,2])",
        ),
        (
            "pub fn f<N>(x:[Field;N])->Field{let y:Bool=x[0]\n0}",
            "f<2>([1,2])",
        ),
    ] {
        std::fs::write(
            dir.path().join("generic.tri"),
            format!("module generic\n{definition}"),
        )
        .unwrap();
        std::fs::write(
            &entry,
            format!("program entry\nuse generic\nfn main()->Field{{generic.{call}}}"),
        )
        .unwrap();
        assert!(
            trident::compile_to_bundle(&entry, &CompileOptions::default()).is_err(),
            "accepted {definition}: {call}"
        );
    }
}
#[test]
fn ordinary_return_contracts_reject_wrong_types_and_missing_paths() {
    for body in [
        "fn main()->Field{true}",
        "fn main()->U32{4294967296}",
        "fn main(x:Field)->Field{if x==0{return 7}}",
        "fn main()->Field{for i in 0..0{return 7}}",
        "fn main()->Field{if true{return false}\n7}",
        "fn main()->Field{return}",
        "fn main(){return 1}",
        "const flag:Field=0\nfn main(flag:Field)->Field{if flag{return 7}}",
        "const flag:Field=0\nfn main(x:Field)->Field{let flag=x\nif flag{return 7}}",
    ] {
        let source = format!("program entry\n{body}");
        assert!(
            trident::check(&source, "entry.tri").is_err(),
            "accepted {body}"
        );
        assert!(
            trident::compile_with_options(&source, "entry.tri", &CompileOptions::default())
                .is_err()
        );
    }
    for body in [
        "fn main()->Field{for i in 0..1{return 7}}",
        "fn main(x:Bool)->Field{if x{return 7}else{return 9}}",
        "fn main()->Field{if true{return 7}}",
        "fn main(x:Field)->Field{if x==0{7}else{9}}",
        "fn main(x:Field)->Field{if x==0{return 7}else{9}}",
        "fn main(x:Bool)->Field{match x{true=>{7} false=>{9}}}",
        "fn main()->Field{for i in 0..0{return 9}\n7}",
        "fn main(){return}",
    ] {
        assert!(
            trident::check(&format!("program entry\n{body}"), "entry.tri").is_ok(),
            "rejected {body}"
        );
    }
}
#[test]
fn standalone_generics_are_checked_after_concrete_substitution() {
    let source = "program entry\nfn f<N>(x:[Field;N])->Field{true}\nfn main()->Field{f<2>([1,2])}";
    assert!(trident::check(source, "entry.tri").is_err());
    assert!(trident::check_silent(source, "entry.tri").is_err());
    assert!(
        trident::compile_with_options(source, "entry.tri", &CompileOptions::default()).is_err()
    );
    let good = source.replace("->Field{true}", "->Field{x[0]}");
    assert_eq!(
        execute(
            &trident::compile_with_options(&good, "entry.tri", &CompileOptions::default()).unwrap(),
            "0"
        ),
        1
    );
}

#[test]
fn constants_keep_nominal_types_and_check_u32_range() {
    assert!(
        trident::check(
            "program entry\nfn main(x:[Field;N])->Field{x[0]}\nconst N:U32=2",
            "entry.tri"
        )
        .is_ok()
    );

    let good = "program entry\nconst C:U32=4294967295\nfn main()->U32{C}";
    assert!(trident::check(good, "entry.tri").is_ok());
    assert_eq!(
        execute(
            &trident::compile_with_options(good, "entry.tri", &CompileOptions::default()).unwrap(),
            "0"
        ),
        4294967295
    );
    assert!(trident::check(&good.replace("4294967295", "4294967296"), "entry.tri").is_err());
    assert!(trident::check(&good.replace("main()->U32", "main()->Field"), "entry.tri").is_err());
    let dir = tempfile::tempdir().unwrap();
    std::fs::write(
        dir.path().join("values.tri"),
        "module values\nconst C:U32=7\npub fn value<N>(x:[Field;N])->U32{C}",
    )
    .unwrap();
    let path = dir.path().join("entry.tri");
    std::fs::write(
        &path,
        "program entry\nuse values\nconst C:Field=99\nfn main()->U32{values.value<2>([1,2])}",
    )
    .unwrap();
    assert_eq!(
        execute(
            &trident::compile_to_bundle(&path, &CompileOptions::default())
                .unwrap()
                .assembly,
            "0"
        ),
        7
    );
}

Homonyms

warriors/trisha/rs/tests/imported_generics.rs

Graph