use super::*;
fn assemble_library_with_num_locals(
context: &TestContext,
num_locals: u16,
) -> Result<Box<Package>, Report> {
let source = source_file!(
&context,
" namespace test::repro
@locals(1)
pub proc foo
loc_load.0
drop
end
"
);
let mut module = context.parse_module(source)?;
for proc in module.procedures_mut() {
proc.set_num_locals(num_locals);
}
Assembler::new(context.source_manager()).assemble_library("test", module, None::<Box<Module>>)
}
#[test]
fn test_num_locals_above_max_is_rejected() {
let context = TestContext::default();
let err = assemble_library_with_num_locals(&context, 65535)
.expect_err("assembling a procedure with 65535 locals should fail, not panic");
assert_diagnostic!(&err, "number of procedure locals 65535 exceeds the maximum of 65532");
}
#[test]
fn test_num_locals_at_max_is_accepted() {
let context = TestContext::default();
assemble_library_with_num_locals(&context, MAX_PROC_LOCALS)
.expect("assembling a procedure with MAX_PROC_LOCALS should succeed");
}
#[test]
fn test_num_locals_one_above_max_is_rejected() {
let context = TestContext::default();
let err = assemble_library_with_num_locals(&context, MAX_PROC_LOCALS + 1)
.expect_err("assembling a procedure with MAX_PROC_LOCALS + 1 should fail");
assert_diagnostic!(&err, "number of procedure locals 65533 exceeds the maximum of 65532");
}
#[test]
#[should_panic(expected = "program entrypoint cannot have locals")]
fn test_entrypoint_with_locals_via_setter_panics() {
let context = TestContext::default();
let source = source_file!(&context, "begin push.1 drop end");
let mut program = context.parse_program(source).expect("failed to parse executable module");
for proc in program.procedures_mut() {
proc.set_num_locals(4);
}
}
#[test]
#[should_panic(expected = "program entrypoint cannot have locals")]
fn test_entrypoint_with_locals_via_constructor_panics() {
let context = TestContext::default();
let body = Block::new(
SourceSpan::default(),
Vec::from([Op::Inst(Span::unknown(Instruction::Assertz))]),
);
let main =
Procedure::new(SourceSpan::default(), Visibility::Public, ProcedureName::main(), 4, body);
let mut module = Module::new_executable();
module
.define_procedure(main, context.source_manager())
.expect("failed to define entrypoint");
let _ = Assembler::new(context.source_manager()).assemble_program("test", module);
}