holey-bytes/hbasm/src/data.rs

102 lines
3.4 KiB
Rust
Raw Normal View History

2024-02-22 16:57:29 -06:00
//! Data section inserts
2023-10-27 20:29:02 -05:00
use {
crate::{object::SymbolRef, SharedObject},
2024-02-22 16:57:29 -06:00
rhai::{CustomType, Engine, FuncRegistration, ImmutableString, Module},
2023-10-27 20:29:02 -05:00
};
2024-02-22 16:57:29 -06:00
/// Generate insertions for data types
///
/// `gen_data_instructions!($module, $obj, [$type, …]);`
/// - `$module`: Rhai module
/// - `$obj`: Code object
/// - `$type`: Type of single array item
2023-10-27 20:29:02 -05:00
macro_rules! gen_data_insertions {
($module:expr, $obj:expr, [$($ty:ident),* $(,)?] $(,)?) => {{
let (module, obj) = ($module, $obj);
$({
2024-02-22 16:57:29 -06:00
// Clone object to each function
2023-10-27 20:29:02 -05:00
let obj = ::std::rc::Rc::clone(obj);
2024-02-14 04:45:58 -06:00
FuncRegistration::new(stringify!($ty))
.with_namespace(rhai::FnNamespace::Global)
.set_into_module::<_, 1, false, _, true, _>(module, move |arr: ::rhai::Array| {
let obj = &mut *obj.borrow_mut();
let symbol = obj.symbol($crate::object::Section::Data);
2023-10-27 20:29:02 -05:00
2024-02-22 16:57:29 -06:00
// Reserve space for object so we don't resize it
// all the time
2024-02-14 04:45:58 -06:00
obj.sections
.data
.reserve(arr.len() * ::std::mem::size_of::<$ty>());
2023-10-27 20:29:02 -05:00
2024-02-22 16:57:29 -06:00
// For every item…
2024-02-14 04:45:58 -06:00
for item in arr {
2024-02-22 16:57:29 -06:00
// … try do conversions from i32 to desired type
// and insert it.
2024-02-14 04:45:58 -06:00
obj.sections.data.extend(
match item.as_int() {
Ok(num) => $ty::try_from(num).map_err(|_| "i64".to_owned()),
Err(ty) => Err(ty.to_owned()),
}
.map_err(|err| {
2024-02-22 16:57:29 -06:00
2024-02-14 04:45:58 -06:00
::rhai::EvalAltResult::ErrorMismatchDataType(
stringify!($ty).to_owned(),
err,
::rhai::Position::NONE,
)
})?
.to_le_bytes(),
);
}
2023-10-27 20:29:02 -05:00
2024-02-14 04:45:58 -06:00
Ok(DataRef {
symbol,
len: obj.sections.data.len() - symbol.0,
})
});
2023-10-27 20:29:02 -05:00
})*
}};
}
2024-02-22 16:57:29 -06:00
/// Reference to entry in data section
2023-10-27 20:29:02 -05:00
#[derive(Clone, Copy, Debug)]
pub struct DataRef {
pub symbol: SymbolRef,
pub len: usize,
}
impl CustomType for DataRef {
fn build(mut builder: rhai::TypeBuilder<Self>) {
builder
.with_name("DataRef")
.with_get("symbol", |this: &mut Self| this.symbol)
.with_get("len", |this: &mut Self| this.len as u64 as i64);
}
}
pub fn module(engine: &mut Engine, obj: SharedObject) -> Module {
let mut module = Module::new();
2024-02-14 04:45:58 -06:00
2023-10-27 20:29:02 -05:00
gen_data_insertions!(&mut module, &obj, [i8, i16, i32, i64]);
2024-02-22 16:57:29 -06:00
// Specialisation for strings, they should be
// inserted as plain UTF-8 arrays
2024-02-14 04:45:58 -06:00
FuncRegistration::new("str")
.with_namespace(rhai::FnNamespace::Global)
.set_into_module::<_, 1, false, _, true, _>(&mut module, move |s: ImmutableString| {
2023-10-27 20:29:02 -05:00
let obj = &mut *obj.borrow_mut();
let symbol = obj.symbol(crate::object::Section::Data);
obj.sections.data.extend(s.as_bytes());
Ok(DataRef {
symbol,
len: s.len(),
})
});
engine.build_type::<DataRef>();
module
}