mod conversion;
mod op;
use super::*;
use crate::core::{TrapCode, UntypedVal};
use std::fmt::Display;
use wasm_type::WasmTy;
fn conversion_reg_with<I, O, E>(wasm_op: &str, expected: E)
where
I: WasmTy,
O: WasmTy,
E: IntoIterator<Item = Instruction>,
{
let param_ty = <I as WasmTy>::NAME;
let result_ty = <O as WasmTy>::NAME;
let wasm = format!(
r#"
(module
(func (param {param_ty}) (result {result_ty})
local.get 0
{result_ty}.{wasm_op}
)
)
"#,
);
TranslationTest::from_wat(&wasm)
.expect_func_instrs(expected)
.run();
}
fn conversion_reg<I, O>(
wasm_op: &str,
make_instr: fn(result: Register, input: Register) -> Instruction,
) where
I: WasmTy,
O: WasmTy,
{
let expected = [
make_instr(Register::from_i16(1), Register::from_i16(0)),
Instruction::return_reg(1),
];
conversion_reg_with::<I, O, _>(wasm_op, expected)
}
fn unary_reg<T>(wasm_op: &str, make_instr: fn(result: Register, input: Register) -> Instruction)
where
T: WasmTy,
{
conversion_reg::<T, T>(wasm_op, make_instr)
}
fn conversion_imm<I, O>(wasm_op: &str, input: I, eval: fn(input: I) -> O)
where
I: WasmTy,
O: WasmTy,
DisplayWasm<I>: Display,
{
let param_ty = <I as WasmTy>::NAME;
let result_ty = <O as WasmTy>::NAME;
let wasm_input = DisplayWasm::from(input);
let wasm = format!(
r#"
(module
(func (result {result_ty})
{param_ty}.const {wasm_input}
{result_ty}.{wasm_op}
)
)
"#,
);
let result = eval(input);
let instr = <O as WasmTy>::return_imm_instr(&result);
let mut testcase = TranslationTest::from_wat(&wasm);
if let Instruction::ReturnReg { value } = &instr {
assert!(value.is_const());
testcase.expect_func(ExpectedFunc::new([instr]).consts([result]));
} else {
testcase.expect_func_instrs([instr]);
}
testcase.run();
}
fn unary_imm<T>(wasm_op: &str, input: T, eval: fn(input: T) -> T)
where
T: WasmTy,
DisplayWasm<T>: Display,
{
conversion_imm::<T, T>(wasm_op, input, eval)
}
fn fallible_conversion_imm_err<I, O>(wasm_op: &str, input: I, eval: fn(input: I) -> TrapCode)
where
I: WasmTy,
O: WasmTy,
DisplayWasm<I>: Display,
{
let param_ty = <I as WasmTy>::NAME;
let result_ty = <O as WasmTy>::NAME;
let wasm_input = DisplayWasm::from(input);
let wasm = format!(
r#"
(module
(func (result {result_ty})
{param_ty}.const {wasm_input}
{result_ty}.{wasm_op}
)
)
"#,
);
let trap_code = eval(input);
TranslationTest::from_wat(&wasm)
.expect_func_instrs([Instruction::Trap(trap_code)])
.run();
}