<commit_before>extern crate boxx;

#[cfg(test)]
mod tests {
  extern crate boxx;
  use boxx::expr::{Expr, boxx};
  extern crate env_logger;

  #[test]
  pub fn test_if_else() {
    let _ = env_logger::init();

    assert_eq!(
      Expr::Int(34),
      boxx("if (true && false) { 32 } else if (!true && true) { 33 } else { 34 }")
    );

    
    assert_eq!(
      Expr::Int(32),
      boxx("if (true || false) { 32 } else if (!true && true) { 33 } else { 34 }")
    );

    assert_eq!(
      Expr::Int(30),
      boxx("if (true && false) { 32 } else { 30 }")
    );

    assert_eq!(
      Expr::Int(52),
      boxx("if (let x = 4; x > 3) { 52 } else { 30 }")
    );

    assert_eq!(
      Expr::Int(22),
      boxx("if (true) { 11 } else { 0 }; 22")
    );
  }

  #[test]
  pub fn test_func() {
    let _ = env_logger::init();

    assert_eq!(Expr::Int(2), boxx("let x = 4; fn foo() { let x = 1; x + 1 }; foo()"));
    assert_eq!(Expr::Int(6), boxx("let x = 5; fn foo() { x + 1 }; foo()"));
    assert_eq!(Expr::Int(60), boxx("fn foo() { 5 }; fn bar() { fn foo() { 6 }; foo() * 10 }; bar()"));
    assert_eq!(Expr::Int(50), boxx("fn foo() { 5 }; fn bar() { foo() * 10 }; bar()"));

    assert_eq!(Expr::Int(12), boxx("fn sum(a, b) { a + b }; sum(sum(3, 4), 5)"));
    assert_eq!(Expr::Int(12), boxx("fn tx_two(a) { 2 * a }; tx_two(tx_two(3))"));

    assert_eq!(
      Expr::Int(41),
      boxx("
        fn foo(a) {
          a < 40 ? foo(a + 3) : a
        };

        foo(20)
      ")
    );

    assert_eq!(
      Expr::Int(21),
      boxx("
        fn fib(n) {
          n == 0 ? 0 : (n == 1 ? 1 : fib(n - 1) + fib(n - 2))
        };

        fib(8)
      ")
    );

    assert_eq!(
      Expr::Int(28),
      boxx("
        fn foo(a) {
          1 + a
        };

        fn bar(b) {
          5 * b
        };
        
        foo(bar(4)) + 7
      ")
    );

    assert_eq!(Expr::Int(12), boxx("fn foo(a) { 1 + a }; foo(4) + 7"));
    assert_eq!(Expr::Int(12), boxx("let foo = fn(a) { 1 + a }; foo(4) + 7"));

    assert_eq!(Expr::Int(2), boxx("fn foo() { 1 + 1 }; foo()"));
    assert_eq!(Expr::Int(7), boxx("fn foo() { 1 + 3 }; foo() + 3"));
    assert_eq!(Expr::Int(9), boxx("fn foo() { 1 + 3 }; fn bar() { foo() + 1}; 4 + bar()"));

    assert_eq!(Expr::Int(2), boxx("let foo = fn() { 1 + 1 }; foo()"));
    assert_eq!(Expr::Int(7), boxx("let foo = fn() { 1 + 3 }; foo() + 3"));
    assert_eq!(Expr::Int(9), boxx("let foo = fn() { 1 + 3 }; let bar = fn() { foo() + 1}; 4 + bar()"));
    // TODO: this should be parsed as a fn call assert_eq!(Expr::Int(4), boxx("fn() { 1 + 3 }()"));
    // TODO: have better failure message when ending a fn block with a semicolon
    // assert_eq!(Expr::Int(12), boxx("fn foo(a) { 1 + a; }; foo(4) + 7"));
    // TODO: recursion
  }

  #[test]
  pub fn test_const_decl() {
    let _ = env_logger::init();
    assert_eq!(Expr::Int(3), boxx("let x = 1 + 2; x"));
    assert_eq!(Expr::Int(1), boxx("let x = 1; x"));
    assert_eq!(Expr::Int(8), boxx("let x = 5; let y = 3; let z = x + y; z"));
<commit_msg>test for reusing let rebinds value<commit_after>extern crate boxx;

#[cfg(test)]
mod tests {
  extern crate boxx;
  use boxx::expr::{Expr, boxx};
  extern crate env_logger;

  #[test]
  pub fn test_if_else() {
    let _ = env_logger::init();

    assert_eq!(
      Expr::Int(34),
      boxx("if (true && false) { 32 } else if (!true && true) { 33 } else { 34 }")
    );

    
    assert_eq!(
      Expr::Int(32),
      boxx("if (true || false) { 32 } else if (!true && true) { 33 } else { 34 }")
    );

    assert_eq!(
      Expr::Int(30),
      boxx("if (true && false) { 32 } else { 30 }")
    );

    assert_eq!(
      Expr::Int(52),
      boxx("if (let x = 4; x > 3) { 52 } else { 30 }")
    );

    assert_eq!(
      Expr::Int(22),
      boxx("if (true) { 11 } else { 0 }; 22")
    );
  }

  #[test]
  pub fn test_func() {
    let _ = env_logger::init();

    assert_eq!(Expr::Int(2), boxx("let x = 4; fn foo() { let x = 1; x + 1 }; foo()"));
    assert_eq!(Expr::Int(6), boxx("let x = 5; fn foo() { x + 1 }; foo()"));
    assert_eq!(Expr::Int(60), boxx("fn foo() { 5 }; fn bar() { fn foo() { 6 }; foo() * 10 }; bar()"));
    assert_eq!(Expr::Int(50), boxx("fn foo() { 5 }; fn bar() { foo() * 10 }; bar()"));

    assert_eq!(Expr::Int(12), boxx("fn sum(a, b) { a + b }; sum(sum(3, 4), 5)"));
    assert_eq!(Expr::Int(12), boxx("fn tx_two(a) { 2 * a }; tx_two(tx_two(3))"));

    assert_eq!(
      Expr::Int(41),
      boxx("
        fn foo(a) {
          a < 40 ? foo(a + 3) : a
        };

        foo(20)
      ")
    );

    assert_eq!(
      Expr::Int(21),
      boxx("
        fn fib(n) {
          n == 0 ? 0 : (n == 1 ? 1 : fib(n - 1) + fib(n - 2))
        };

        fib(8)
      ")
    );

    assert_eq!(
      Expr::Int(28),
      boxx("
        fn foo(a) {
          1 + a
        };

        fn bar(b) {
          5 * b
        };
        
        foo(bar(4)) + 7
      ")
    );

    assert_eq!(Expr::Int(12), boxx("fn foo(a) { 1 + a }; foo(4) + 7"));
    assert_eq!(Expr::Int(12), boxx("let foo = fn(a) { 1 + a }; foo(4) + 7"));

    assert_eq!(Expr::Int(2), boxx("fn foo() { 1 + 1 }; foo()"));
    assert_eq!(Expr::Int(7), boxx("fn foo() { 1 + 3 }; foo() + 3"));
    assert_eq!(Expr::Int(9), boxx("fn foo() { 1 + 3 }; fn bar() { foo() + 1}; 4 + bar()"));

    assert_eq!(Expr::Int(2), boxx("let foo = fn() { 1 + 1 }; foo()"));
    assert_eq!(Expr::Int(7), boxx("let foo = fn() { 1 + 3 }; foo() + 3"));
    assert_eq!(Expr::Int(9), boxx("let foo = fn() { 1 + 3 }; let bar = fn() { foo() + 1}; 4 + bar()"));
    // TODO: this should be parsed as a fn call assert_eq!(Expr::Int(4), boxx("fn() { 1 + 3 }()"));
    // TODO: have better failure message when ending a fn block with a semicolon
    // assert_eq!(Expr::Int(12), boxx("fn foo(a) { 1 + a; }; foo(4) + 7"));
    // TODO: recursion
  }

  #[test]
  pub fn test_const_decl() {
    let _ = env_logger::init();
    assert_eq!(Expr::Int(3), boxx("let x = 1 + 2; x"));
    assert_eq!(Expr::Int(1), boxx("let x = 1; x"));
    assert_eq!(Expr::Int(8), boxx("let x = 5; let y = 3; let z = x + y; z"));

    // using let keyword again re-binds value
    assert_eq!(Expr::Int(5), boxx("let x = 2; let x = 3; x + 2"));

{'fraction_non_alphanumeric': 0.23688853247794708, 'fraction_numerical': 0.04426623897353649, 'mean_word_length': 2.259801359121798, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3266379', 'n_tokens_mistral': 2678, 'n_tokens_neox': 2427, 'n_words': 636}