2023-11-07 21:59:05 -06:00
|
|
|
use vasm_core::assemble_snippet;
|
|
|
|
|
use vcore::memory::{Memory, PeekPokeExt};
|
|
|
|
|
use vcore::word::Word;
|
|
|
|
|
use vcore::CPU;
|
|
|
|
|
|
|
|
|
|
fn run_forge(src: &str) -> CPU {
|
|
|
|
|
let asm = forge_core::compiler::build_boot(src).unwrap();
|
|
|
|
|
let bin = assemble_snippet(asm).unwrap();
|
|
|
|
|
let mut cpu = CPU::new(Memory::with_program(bin));
|
|
|
|
|
cpu.run_to_halt();
|
|
|
|
|
cpu
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn main_return(src: &str) -> i32 {
|
|
|
|
|
let mut cpu = run_forge(src);
|
|
|
|
|
cpu.pop_data().into()
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-08 23:12:53 -06:00
|
|
|
fn error_message(src: &str) -> Option<String> {
|
|
|
|
|
match forge_core::compiler::build_boot(src) {
|
|
|
|
|
Ok(_) => None,
|
|
|
|
|
Err(forge_core::compiler::CompileError(_, _, s)) => Some(s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-07 21:59:05 -06:00
|
|
|
#[test]
|
|
|
|
|
fn basic_forge_test() {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
main_return("fn main() { return 2 + 3; }"),
|
|
|
|
|
5
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-08 22:06:35 -06:00
|
|
|
#[test]
|
|
|
|
|
fn loop_test() {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
main_return(
|
|
|
|
|
"fn triangle(rows) {
|
|
|
|
|
var total = 0;
|
|
|
|
|
repeat (rows) n {
|
|
|
|
|
total = total + (n + 1);
|
|
|
|
|
}
|
|
|
|
|
return total;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn main() { return triangle(5); }"),
|
|
|
|
|
15
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn arg_test() {
|
|
|
|
|
// Send in two args where the order matters, to ensure that args are being captured correctly
|
|
|
|
|
assert_eq!(
|
|
|
|
|
main_return(
|
|
|
|
|
"fn sub(a, b) { return a - b; }
|
|
|
|
|
fn main() { return sub(5, 3); }"),
|
|
|
|
|
2
|
|
|
|
|
)
|
2023-11-08 23:12:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn scope_test() {
|
|
|
|
|
// Refer to a var that's now out of scope, to ensure block scoping works
|
|
|
|
|
assert_eq!(
|
|
|
|
|
error_message(
|
|
|
|
|
"fn main() {
|
|
|
|
|
if (1) { var a = 3; } // scoped to the block!
|
|
|
|
|
return a; // should error!
|
|
|
|
|
}"),
|
|
|
|
|
Some("Unknown name a".into())
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Refer to a var that's still in scope, to ensure we're not wiping too much out
|
|
|
|
|
assert_eq!(
|
|
|
|
|
error_message(
|
|
|
|
|
"fn main(a) {
|
|
|
|
|
if (1) { var b = 3; } // scoped to the block!
|
|
|
|
|
return a; // should work, we didn't remove the thing that dropped
|
|
|
|
|
}"),
|
|
|
|
|
None
|
|
|
|
|
)
|
2023-11-08 22:06:35 -06:00
|
|
|
}
|