slj 0.6.6

Programski jezik v slovenščini | A programming language in Slovenian
Documentation
use slj::{parser::{tokenizer::{Tokenize, Token::*, L}, Parse}, program::ToProgram};
use std::io::Cursor;

fn test(program: &str, vhod: &str) -> String {
    let mut izhod = Vec::<u8>::new();

    program.tokenize().parse().unwrap().to_program().zaženi_z_io(&mut Cursor::new(vhod), &mut izhod);
    return String::from_utf8(izhod).unwrap();
}

#[test]
fn natisni_znak() {
    let program = r#"
        natisni('z')
        natisni('v')
        natisni('e')
        natisni('r')
        "#;

    assert_eq!(test(program, ""), "zver");
}

#[test]
fn natisni_bool() {
    let program = r#"natisni(resnica)"#;
    assert_eq!(test(program, ""), "resnica");

    let program = r#"natisni(laž)"#;
    assert_eq!(test(program, ""), "laž");
}

#[test]
fn natisni_niz() {
    let program = r#"natisni("zver")"#;
    assert_eq!(test(program, ""), "zver");
}

#[test]
fn natisni_število() {
    let program = r#"natisni(42)"#;
    assert_eq!(program.tokenize(), [Ime("natisni", 1, 1), Ločilo("(", 1, 8), Literal(L::Celo("42", 1, 9)), Ločilo(")", 1, 11)]);
    assert_eq!(test(program, ""), "42");

    let program = r#"natisni(0)"#;
    assert_eq!(program.tokenize(), [Ime("natisni", 1, 1), Ločilo("(", 1, 8), Literal(L::Celo("0", 1, 9)), Ločilo(")", 1, 10)]);
    assert_eq!(test(program, ""), "0");

    let program = r#"natisni(0.02)"#;
    assert_eq!(test(program, ""), "0.02");

    let program = r#"natisni(0.5)"#;
    assert_eq!(test(program, ""), "0.5");

    let program = r#"natisni(3.141592653589793)"#;
    assert_eq!(test(program, ""), "3.141592");
}

#[test]
fn natisni_izraz() {
    let program = r#"natisni(3+2*4**2)"#;
    assert_eq!(test(program, ""), "35");
}

#[test]
fn one_liner() {
    let program = r#"naj x=1;če x-1==0{natisni("x=1")}else{natisni("x!=1")}"#;
    assert_eq!(test(program, ""), "x=1");
}

#[test]
fn preveč_vrstic() {
    let program = r#"
        naj x = 1
        ;

        če x - 1 == 0
        {
            natisni
            (
                "x=1"
            )
        }

        čene
        {
            natisni
            (

                "x!=1"
            )
        }
    "#;
    assert_eq!(test(program, ""), "x=1");
}

#[test]
fn praštevil_do_1000() {
    let program = r#"
        naj praštevila: [celo; 1000]
        naj praštevil = 2
        praštevila[0] = 2
        praštevila[1] = 3

        za kandidat = 5, kandidat <= praštevila.dolžina, kandidat += 2 {
            naj praštevilo = resnica

            za i = 0, praštevila[i]**2 <= kandidat && praštevilo, i += 1 {
                če kandidat % praštevila[i] == 0 {
                    praštevilo = laž
                }
            }

            če praštevilo {
                praštevila[praštevil] = kandidat
                praštevil += 1
            }
        }

        natisni!("praštevil do ", praštevila.dolžina, ": ", praštevil, "\n")
    "#;
    assert_eq!(test(program, ""), "praštevil do 1000: 168\n");
}

#[test]
fn rekurzija() {
    let program = r#"
        funkcija faktoriela(a: celo) -> celo {
            če a <= 1 {
                vrni 1
            }
            vrni a * faktoriela(a - 1)
        }
        natisni!("7! = ", faktoriela(7), "\n")
    "#;
    assert_eq!(test(program, ""), "7! = 5040\n");
}

#[test]
fn spr_pred_funkcijo() {
    let program = r#"
        funkcija init() -> celo {
            vrni 0
        }
        naj spr = init()
        funkcija inkrement() -> brez {
            spr += 1
        }
        naj i = 0; dokler i < 3 {
            inkrement()
            i += 1
        }
        natisni(spr)
    "#;
    assert_eq!(test(program, ""), "3");
}

#[test]
fn multi_funkcija() {
    let program = r#"
        naj a = 0; naj b = 0.0
        funkcija prištej(x: celo) -> brez {
            a += x
        }
        funkcija prištej(x: real) -> brez {
            b += x
        }

        prištej!(42, 3.14)
        natisni!(a, ", ", b)
    "#;
    assert_eq!(test(program, ""), "42, 3.14");
}

#[test]
fn referenca() {
    let program = r#"
        funkcija naloži(ref: @real) {
            natisni!(ref@, " ")
        }
        funkcija naloži(ref: @celo) {
            natisni!(ref@, " ")
            naloži(@3.14)
        }

        naj a = 13
        naj b = @a
        naloži(@a)
        naloži(@42)
        natisni(b@)
        "#;
    assert_eq!(test(program, ""), "13 3.14 42 3.14 13");

    let program = r#"
        funkcija spremeni(ref: @celo, val: celo) {
            ref@ = val;
        }
        funkcija povečaj(ref: @celo, val: celo) {
            ref@ += val
        }

        naj a = 7
        natisni!(a, " ")
        spremeni(@a, 13)
        natisni!(a, " ")
        povečaj(@a, 4)
        natisni(a)
        "#;
    assert_eq!(test(program, ""), "7 13 17");
}

#[test]
fn indeksiranje() {
    let program = r#"
        naj seznam: [real; 3]
        naj ref = @seznam
        naj dolžina = 0
    
        funkcija dodaj(seznam: @[real], št: real) {
            seznam[dolžina] = št
            dolžina += 1
        }

        funkcija dodaj(seznam: @[real], št: @real) {
            seznam[dolžina] = št@
            dolžina += 1
        }

        dodaj(@seznam, @1.0)
        dodaj(@seznam, 2.0)
        dodaj(ref, 3.0)

        natisni!(seznam[0], " ", seznam[1], " ", ref[2], "\n")
        naj i = 0; dokler i < seznam.dolžina {
            seznam[i] = (ref.dolžina - i) kot real
            natisni!(ref[i], " ")
            i += 1
        }
    "#;
    assert_eq!(test(program, ""), "1 2 3\n3 2 1 ");
}

#[test]
fn fake_natisni() {
    let program = r#"
        funkcija _natisni(niz: @[znak]) {
            naj dolžina = niz.dolžina
            naj i = 0; dokler i < dolžina {
                natisni(niz[i])
                i += 1
            }
        }

        _natisni(@"žibje")
    "#;
    assert_eq!(test(program, ""), "žibje");
}

#[test]
fn zanke() {
    let program = r#"
        naj i = 1; dokler i <= 3 {
            natisni(i)
            i += 1
        }
    "#;
    assert_eq!(test(program, ""), "123");

    let program = r#"
        za i = 1, i <= 3, i += 1 {
            natisni(i)
        }
        naj i = 123
    "#;
    assert_eq!(test(program, ""), "123");

    let program = r#"
        naj i = 1
        za , i <= 3, i += 1 {
            natisni(i)
        }
        i = 1
        za , i <= 3, {
            natisni(i)
            i += 1
        }
    "#;
    assert_eq!(test(program, ""), "123123");
}

#[test]
fn pretvorbe() {
    let program = r#"
        natisni(v_celo("1312"))
    "#;
    assert_eq!(test(program, ""), "1312");
}

#[test]
fn vhod() {
    let program = r#"
        natisni(preberi())
        natisni(preberi())
        natisni(preberi())
        natisni(preberi())
    "#;
    assert_eq!(test(program, "zver"), "zver");

    let program = r#"
        naj medp: [znak; 128]
        naj dolžina = preberi(@medp)
        natisni(@medp, dolžina)
    "#;
    assert_eq!(test(program, "🥝Hard liquor mixed with a bit of intellect🥝\n"), "🥝Hard liquor mixed with a bit of intellect🥝\n");
}