use crate::ast::utils::{Type, Value};
use crate::error::NbclError;
use crate::registry::Registry;
pub(crate) fn register_builtin_functions(registry: &mut Registry) {
registry.add_native_fn("print", vec![Type::Any], Type::Null, |args| {
crate::print(format!("{}", args[0]));
Ok(Value::Null)
});
registry.add_native_fn("to_string", vec![Type::Any], Type::Str, |args| {
Ok(Value::Str(args[0].to_string()))
});
registry.add_native_fn("as_int", vec![Type::Any], Type::Int, |args| match args[0].as_int() {
Some(i) => Ok(Value::Int(i)),
None => {
return Err(NbclError::Runtime {
message: format!("as_float() not supported for type {}", args[0].type_name()),
hint: None,
span: None,
});
}
});
registry.add_native_fn("as_float", vec![Type::Any], Type::Float, |args| {
match args[0].as_float() {
Some(f) => Ok(Value::Float(f)),
None => {
return Err(NbclError::Runtime {
message: format!("as_float() not supported for type {}", args[0].type_name()),
hint: None,
span: None,
});
}
}
});
registry.add_native_fn("type_of", vec![Type::Any], Type::Str, |args| {
Ok(Value::Str(args[0].type_name().to_string()))
});
registry.add_native_fn("len", vec![Type::Any], Type::Int, |args| {
let length = match &args[0] {
Value::Str(s) => s.len() as i64,
Value::List(l) => l.len() as i64,
Value::Map(m) => m.len() as i64,
_ => {
return Err(NbclError::Runtime {
message: format!("len() not supported for type {}", args[0].type_name()),
hint: None,
span: None,
});
}
};
Ok(Value::Int(length))
});
registry.add_native_fn("contains", vec![Type::Any, Type::Any], Type::Bool, |args| {
match &args[0] {
Value::List(v) => Ok(Value::Bool(v.contains(&args[1]))),
Value::Str(s) => match &args[1] {
Value::Str(sub) => Ok(Value::Bool(s.contains(sub.as_str()))),
_ => Ok(Value::Bool(false))
},
_ => Err(NbclError::Runtime {
message: format!("contains() not supported for type {}", args[0].type_name()),
hint: None, span: None,
})
}
});
registry.add_native_fn("push", vec![Type::List, Type::Any], Type::List, |mut args| {
let val = args.remove(1);
match args.remove(0) {
Value::List(mut v) => { v.push(val); Ok(Value::List(v)) }
_ => unreachable!()
}
});
registry.add_native_fn("pop", vec![Type::List], Type::Any, |mut args| {
match args.remove(0) {
Value::List(mut v) => Ok(v.pop().unwrap_or(Value::Null)),
_ => unreachable!()
}
});
registry.add_native_fn("keys", vec![Type::Map], Type::List, |args| {
match &args[0] {
Value::Map(m) => Ok(Value::List(
m.iter().map(|(k, _)| Value::Str(k.clone())).collect()
)),
_ => unreachable!()
}
});
registry.add_native_fn("values", vec![Type::Map], Type::List, |args| {
match &args[0] {
Value::Map(m) => Ok(Value::List(
m.iter().map(|(_, v)| v.clone()).collect()
)),
_ => unreachable!()
}
});
}