use std::rc::Rc;
use crate::{yamrb::{helpers::{mrb_define_cmethod, mrb_funcall}, value::*, vm::VM}, Error};
pub(crate) fn initialize_object(vm: &mut VM) {
let object_class = vm.object_class.clone();
vm.consts.insert("Object".to_string(), Rc::new(RObject {
tt: RType::Class,
value: RValue::Class(object_class.clone()),
}));
vm.builtin_class_table.insert("Object", object_class.clone());
#[cfg(feature = "wasi")]
{
mrb_define_cmethod(vm, object_class.clone(), "puts", Box::new(mrb_kernel_puts));
mrb_define_cmethod(vm, object_class.clone(), "debug", Box::new(mrb_kernel_debug));
}
mrb_define_cmethod(vm, object_class.clone(), "initialize", Box::new(mrb_object_initialize));
mrb_define_cmethod(vm, object_class.clone(), "===", Box::new(mrb_object_triple_eq));
vm.consts.insert("RUBY_VERSION".to_string(), Rc::new(RObject::string(crate::yamrb::vm::VERSION.to_string())));
vm.consts.insert("MRUBY_VERSION".to_string(), Rc::new(RObject::string(crate::yamrb::vm::VERSION.to_string())));
vm.consts.insert("MRUBY_EDGE_VERSION".to_string(), Rc::new(RObject::string(crate::yamrb::vm::VERSION.to_string())));
vm.consts.insert("RUBY_ENGINE".to_string(), Rc::new(RObject::string(crate::yamrb::vm::ENGINE.to_string())));
}
#[cfg(feature = "wasi")]
pub fn mrb_kernel_puts(_vm: &mut VM, args: &[Rc<RObject>]) -> Result<Rc<RObject>, Error> {
let msg = args[0].clone();
match &msg.value {
RValue::String(s) => {
println!("{}", String::from_utf8_lossy(&s.borrow()));
}
RValue::Integer(i) => {
println!("{}", i);
}
_ => {
dbg!(&msg);
return Err(Error::RuntimeError("puts only accept string".to_string()));
}
}
Ok(Rc::new(RObject::nil()))
}
#[cfg(feature = "wasi")]
pub fn mrb_kernel_debug(_vm: &mut VM, args: &[Rc<RObject>]) -> Result<Rc<RObject>, Error> {
for (i, obj) in args.iter().enumerate() {
dbg!(i, obj.clone());
}
Ok(Rc::new(RObject::nil()))
}
pub fn mrb_object_triple_eq(vm: &mut VM, args: &[Rc<RObject>]) -> Result<Rc<RObject>, Error> {
let lhs = vm.getself();
let rhs = args[0].clone();
match (&lhs.value, &rhs.value) {
(RValue::Integer(i1), RValue::Integer(i2)) => {
Ok(Rc::new(RObject::boolean(*i1 == *i2)))
}
(RValue::Float(f1), RValue::Float(f2)) => {
Ok(Rc::new(RObject::boolean(*f1 == *f2)))
}
(RValue::Symbol(sym1), RValue::Symbol(sym2)) => {
Ok(Rc::new(RObject::boolean(sym1 == sym2)))
}
(RValue::String(s1), RValue::String(s2)) => {
Ok(Rc::new(RObject::boolean(s1 == s2)))
}
(RValue::Class(c1), _) => {
match &lhs.value {
RValue::Class(c2) => {
Ok(Rc::new(RObject::boolean(c1.sym_id == c2.sym_id)))
}
_ => {
let c2 = lhs.get_class(vm);
Ok(Rc::new(RObject::boolean(c1.sym_id == c2.sym_id)))
}
}
}
(RValue::Range(_s, _e, _v), _) => {
let arg = vec![rhs];
mrb_funcall(vm, Some(lhs), "include?", &arg)
}
_ => {
Ok(Rc::new(RObject::boolean(false)))
}
}
}
pub fn mrb_object_initialize(_vm: &mut VM, _args: &[Rc<RObject>]) -> Result<Rc<RObject>, Error> {
Ok(Rc::new(RObject::nil()))
}