use crate::register_intrinsic;
use crate::types::{TypeId, TypeManager};
use crate::value::insn::Intrinsic;
struct TakeWhile;
impl Intrinsic for TakeWhile {
fn name(&self) -> &'static str {
"take_while"
}
fn arity(&self) -> usize {
1
}
fn result_type(&self, types: &TypeManager, args: &[TypeId]) -> TypeId {
if let Some((elem, len, _is_list)) = types.seq_of(args[0]) {
types
.get_list(elem, Some(len))
.expect("take_while result bounded-list type must be published")
} else {
let i8 = types.get_int(1);
types
.get_list(i8, None)
.expect("take_while result unbounded-list type must be published")
}
}
fn eval(&self, _args: &[(u128, usize)], _out_size: usize) -> Option<u128> {
None
}
}
register_intrinsic!(TakeWhile);
#[cfg(test)]
mod tests {
use crate::types::TypeRequest;
use crate::value::insn::IntrinsicId;
#[test]
fn take_while_registered_and_resolves() {
let id = IntrinsicId::from_name("take_while").expect("take_while registered");
assert_eq!(id.name(), "take_while");
assert_eq!(id.desc().arity(), 1);
}
#[test]
fn result_type_is_a_list_with_the_source_bound() {
let mut types = crate::types::TypeManager::default();
let i8 = types.get_or_make_int(1);
let arr = types.get_or_make_array(i8, 7);
types.create_requested_types(&[TypeRequest::list(i8, Some(7))]);
let id = IntrinsicId::from_name("take_while").unwrap();
let result = id.desc().result_type(&types, &[arr]);
assert_eq!(types.array_of(result), None, "result is not a fixed array");
let (elem, bound) = types.list_of(result).expect("result is a list");
assert_eq!(elem, i8);
assert_eq!(bound, Some(7));
assert_eq!(types.size_of(result), 7);
}
#[test]
fn result_type_of_a_pointer_is_an_unbounded_list() {
let mut types = crate::types::TypeManager::default();
let i8 = types.get_or_make_int(1);
let ptr = types.get_or_make_int(8); types.create_requested_types(&[TypeRequest::list(i8, None)]);
let id = IntrinsicId::from_name("take_while").unwrap();
let result = id.desc().result_type(&types, &[ptr]);
assert_eq!(types.array_of(result), None, "result is not a fixed array");
let (elem, bound) = types.list_of(result).expect("result is a list");
assert_eq!((elem, bound), (i8, None), "an unbounded List<i8>");
assert_eq!(types.size_of(result), 0, "no materialized footprint");
}
#[test]
fn take_while_accepts_a_list() {
let types = crate::types::TypeManager::default();
let i8 = types.get_or_make_int(1);
let list = types.get_or_make_list(i8, 5);
let id = IntrinsicId::from_name("take_while").unwrap();
let result = id.desc().result_type(&types, &[list]);
let (elem, bound) = types.list_of(result).expect("result is a list");
assert_eq!((elem, bound), (i8, Some(5)));
}
#[test]
fn take_while_is_not_foldable() {
let id = IntrinsicId::from_name("take_while").unwrap();
assert_eq!(id.desc().eval(&[(0x4142, 4)], 4), None);
}
}