ergotree_interpreter/eval/
collection.rs1use std::sync::Arc;
2
3use ergotree_ir::mir::collection::Collection;
4use ergotree_ir::mir::constant::TryExtractFromError;
5use ergotree_ir::mir::constant::TryExtractInto;
6use ergotree_ir::mir::value::CollKind;
7use ergotree_ir::mir::value::NativeColl;
8use ergotree_ir::mir::value::Value;
9use ergotree_ir::types::stype::SType;
10
11use crate::eval::env::Env;
12use crate::eval::Context;
13use crate::eval::EvalError;
14use crate::eval::Evaluable;
15
16impl Evaluable for Collection {
17 fn eval<'ctx>(
18 &self,
19 env: &mut Env<'ctx>,
20 ctx: &Context<'ctx>,
21 ) -> Result<Value<'ctx>, EvalError> {
22 Ok(match self {
23 Collection::BoolConstants(bools) => bools.clone().into(),
24 Collection::Exprs { elem_tpe, items } => {
25 let items_v: Result<Arc<[Value]>, EvalError> =
26 items.iter().map(|i| i.eval(env, ctx)).collect();
27 match elem_tpe {
28 SType::SByte => {
29 let bytes: Result<Arc<[i8]>, TryExtractFromError> = items_v?
30 .iter()
31 .cloned()
32 .map(|i| i.try_extract_into::<i8>())
33 .collect();
34 Value::Coll(CollKind::NativeColl(NativeColl::CollByte(bytes?)))
35 }
36 _ => Value::Coll(CollKind::WrappedColl {
37 elem_tpe: elem_tpe.clone(),
38 items: items_v?,
39 }),
40 }
41 }
42 })
43 }
44}
45
46#[allow(clippy::unwrap_used)]
47#[allow(clippy::panic)]
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use crate::eval::tests::eval_out_wo_ctx;
52 use ergotree_ir::mir::expr::Expr;
53 use proptest::prelude::*;
54
55 proptest! {
56
57 #[test]
58 fn eval_byte_coll(bytes in any::<Vec<i8>>()) {
59 let value: Value = bytes.clone().into();
60 let exprs: Vec<Expr> = bytes.into_iter().map(|b| Expr::Const(b.into())).collect();
61 let coll: Expr = Collection::new(SType::SByte, exprs).unwrap().into();
62 let res = eval_out_wo_ctx::<Value>(&coll);
63 prop_assert_eq!(res, value);
64 }
65
66 #[test]
67 fn eval_bool_coll(bools in any::<Vec<bool>>()) {
68 let exprs: Vec<Expr> = bools.clone().into_iter().map(|b| Expr::Const(b.into())).collect();
69 let coll: Expr = Collection::new(SType::SBoolean, exprs).unwrap().into();
70 let res = eval_out_wo_ctx::<Vec<bool>>(&coll);
71 prop_assert_eq!(res, bools);
72 }
73
74 #[test]
75 fn eval_long_coll(longs in any::<Vec<i64>>()) {
76 let exprs: Vec<Expr> = longs.clone().into_iter().map(|b| Expr::Const(b.into())).collect();
77 let coll: Expr = Collection::new(SType::SLong, exprs).unwrap().into();
78 let res = eval_out_wo_ctx::<Vec<i64>>(&coll);
79 prop_assert_eq!(res, longs);
80 }
81
82 #[test]
83 fn eval_bytes_coll_coll(bb in any::<Vec<Vec<i8>>>()) {
84 let exprs: Vec<Expr> = bb.clone().into_iter().map(|b| Expr::Const(b.into())).collect();
85 let coll: Expr = Collection::new(SType::SColl(SType::SByte.into()), exprs).unwrap().into();
86 let res = eval_out_wo_ctx::<Vec<Vec<i8>>>(&coll);
87 prop_assert_eq!(res, bb);
88 }
89 }
90}