Skip to content

Commit 283f471

Browse files
Added Core Tests (Register/Compiler)
1 parent 0f2d73f commit 283f471

1 file changed

Lines changed: 118 additions & 0 deletions

File tree

tundra/tests/core.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// tests/test_suite.rs
2+
3+
use std::cell::RefCell;
4+
use std::rc::Rc;
5+
6+
use tundra::bytecode::chunk::Chunk;
7+
use tundra::bytecode::value::Value;
8+
use tundra::compiler::compiler::Compiler;
9+
use tundra::compiler::register::RegisterAllocator;
10+
use tundra::lexer::scanner::Scanner;
11+
12+
/// Helper to compile source and return whether it compiled successfully.
13+
fn compile_src(src: &str) -> bool {
14+
let tokens = Scanner::new(src.to_string()).scan_tokens();
15+
let chunk = Rc::new(RefCell::new(Chunk::new()));
16+
let mut comp = Compiler::new(chunk.clone());
17+
comp.parser.tokens = tokens;
18+
comp.parser.current_idx = 0;
19+
comp.parser.advance_token();
20+
comp.compile(src)
21+
}
22+
23+
// ---------- RegisterAllocator tests ----------
24+
25+
#[test]
26+
fn reg_alloc_store_and_retrieve() {
27+
let mut alloc = RegisterAllocator::new();
28+
let r = alloc.allocate(Value::int(42)).expect("should allocate");
29+
assert_eq!(*alloc.get_value(r), Value::int(42));
30+
}
31+
32+
#[test]
33+
fn reg_alloc_last_allocated_and_free() {
34+
let mut alloc = RegisterAllocator::new();
35+
let r1 = alloc.allocate(Value::int(1)).unwrap();
36+
let r2 = alloc.allocate(Value::int(2)).unwrap();
37+
assert_eq!(alloc.last_allocated(), Some(r2));
38+
alloc.free(r2);
39+
assert_eq!(alloc.last_allocated(), Some(r1));
40+
}
41+
42+
#[test]
43+
fn reg_alloc_reuse_freed() {
44+
let mut alloc = RegisterAllocator::new();
45+
let r = alloc.allocate(Value::none()).unwrap();
46+
alloc.free(r);
47+
let r2 = alloc.allocate(Value::none()).unwrap();
48+
assert_eq!(r2, r, "freed register should be reused first");
49+
}
50+
51+
#[test]
52+
fn reg_alloc_reserve() {
53+
let mut alloc = RegisterAllocator::new();
54+
// reserve register 0
55+
alloc.reserve(0);
56+
// now allocate once; should never get 0
57+
let r = alloc.allocate(Value::none()).unwrap();
58+
assert_ne!(r, 0, "reserved register 0 should not be allocated");
59+
}
60+
61+
#[test]
62+
fn reg_alloc_out_of_registers() {
63+
let mut alloc = RegisterAllocator::new();
64+
// exhaust all 1024 registers
65+
let mut regs = Vec::with_capacity(1024);
66+
for _ in 0..1024 {
67+
regs.push(alloc.allocate(Value::none()).unwrap());
68+
}
69+
// next allocation must error
70+
assert!(alloc.allocate(Value::none()).is_err());
71+
// free one and allocate again
72+
alloc.free(regs[512]);
73+
assert!(alloc.allocate(Value::none()).is_ok());
74+
}
75+
76+
// ---------- Basic Tundra code compilation tests ----------
77+
78+
#[test]
79+
fn compile_simple_print_sum() {
80+
assert!(compile_src("print(1+2)"));
81+
}
82+
83+
#[test]
84+
fn compile_var_and_print() {
85+
let src = "var x = 7\nprint(x)";
86+
assert!(compile_src(src));
87+
}
88+
89+
#[test]
90+
fn compile_syntax_error() {
91+
// missing '=' should fail
92+
assert!(!compile_src("var x 7"));
93+
}
94+
95+
#[test]
96+
fn compile_if_else() {
97+
let code = r#"if(true):
98+
print(5)
99+
else:
100+
print(6)"#;
101+
assert!(compile_src(code));
102+
}
103+
104+
#[test]
105+
fn compile_for_loop() {
106+
let code = r#"for i in range(3):
107+
print(i)"#;
108+
assert!(compile_src(code));
109+
}
110+
111+
#[test]
112+
fn compile_while_loop() {
113+
let code = r#"var i = 0
114+
while(i < 2):
115+
print(i)
116+
i = i + 1"#;
117+
assert!(compile_src(code));
118+
}

0 commit comments

Comments
 (0)