use crate::{Error, Result};
use anyhow::anyhow;
use core::str::FromStr;
use opcodes::{OpCode as _, ShangHai as OpCode};
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum HostFunc {
Evm(OpCode),
NoOp,
EmitABI,
AddressEq,
U256MAX,
Revert(usize),
Label(CompilerLabel),
}
impl HostFunc {
pub fn stack_in(&self) -> u8 {
match self {
Self::Evm(op) => op.stack_in() as u8,
_ => 0,
}
}
pub fn stack_out(&self) -> u8 {
match self {
Self::Evm(op) => op.stack_out() as u8,
_ => 0,
}
}
}
impl TryFrom<(&str, &str)> for HostFunc {
type Error = Error;
fn try_from(import: (&str, &str)) -> Result<Self> {
let (module, name) = import;
match import {
("asm", name) => {
if name.starts_with("sload") {
Ok(Self::Evm(OpCode::SLOAD))
} else if name.starts_with("revert") {
let count = name.trim_start_matches("revert");
Ok(Self::Revert(count.parse().map_err(|e| anyhow!("{e}"))?))
} else {
Ok(Self::NoOp)
}
}
("evm", name) => Ok(Self::Evm(OpCode::from_str(name).map_err(|_| {
tracing::error!("Failed to load host function: {:?}", import);
Error::HostFuncNotFound(module.into(), name.into())
})?)),
("zinkc", "emit_abi") => Ok(Self::EmitABI),
("zinkc", "address_eq") => Ok(Self::Evm(OpCode::EQ)),
("zinkc", "u256_add") => Ok(Self::Evm(OpCode::ADD)),
("zinkc", "u256_sub") => Ok(Self::Evm(OpCode::SUB)),
("zinkc", "u256_lt") => Ok(Self::Evm(OpCode::LT)),
("zinkc", "u256_max") => Ok(Self::U256MAX),
("zinkc", "label_reserve_mem_32") => Ok(Self::Label(CompilerLabel::ReserveMemory32)),
("zinkc", "label_reserve_mem_64") => Ok(Self::Label(CompilerLabel::ReserveMemory64)),
_ => {
tracing::warn!("Failed to load host function: {:?}", import);
Err(Error::HostFuncNotFound(module.into(), name.into()))
}
}
}
}
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum CompilerLabel {
ReserveMemory32,
ReserveMemory64,
}