1use std::fmt::Display;
2use std::mem;
3use std::path::Path;
4
5use erg_common::dict::Dict;
6#[allow(unused_imports)]
7use erg_common::log;
8use erg_common::traits::Stream;
9use erg_common::{dict, set, set_recursion_limit};
10
11use crate::context::eval::UndoableLinkedList;
12use crate::context::initialize::closed_range;
13use crate::context::Context;
14use crate::feature_error;
15use crate::ty::constructors::{and, dict_mut, list_mut, mono, tuple_t, v_enum};
16use crate::ty::value::{EvalValueError, EvalValueResult, GenTypeObj, TypeObj, ValueObj};
17use crate::ty::{Field, TyParam, Type, ValueArgs};
18use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
19use erg_common::style::{Color, StyledStr, StyledString, THEME};
20
21const ERR: Color = THEME.colors.error;
22const WARN: Color = THEME.colors.warning;
23
24fn not_passed(t: impl Display) -> EvalValueError {
25 let text = t.to_string();
26 let param = StyledStr::new(&text, Some(ERR), None);
27 ErrorCore::new(
28 vec![SubMessage::only_loc(Location::Unknown)],
29 format!("{param} is not passed"),
30 line!() as usize,
31 ErrorKind::KeyError,
32 Location::Unknown,
33 )
34 .into()
35}
36
37fn no_key(slf: impl Display, key: impl Display) -> EvalValueError {
38 ErrorCore::new(
39 vec![SubMessage::only_loc(Location::Unknown)],
40 format!("{slf} has no key {key}"),
41 line!() as usize,
42 ErrorKind::KeyError,
43 Location::Unknown,
44 )
45 .into()
46}
47
48fn type_mismatch(expected: impl Display, got: impl Display, param: &str) -> EvalValueError {
49 let got = StyledString::new(format!("{got}"), Some(ERR), None);
50 let param = StyledStr::new(param, Some(WARN), None);
51 ErrorCore::new(
52 vec![SubMessage::only_loc(Location::Unknown)],
53 format!("non-{expected} object {got} is passed to {param}"),
54 line!() as usize,
55 ErrorKind::TypeError,
56 Location::Unknown,
57 )
58 .into()
59}
60
61fn todo(msg: &str) -> EvalValueError {
62 ErrorCore::new(
63 vec![SubMessage::only_loc(Location::Unknown)],
64 format!("{msg} is not supported yet in const context"),
65 line!() as usize,
66 ErrorKind::FeatureError,
67 Location::Unknown,
68 )
69 .into()
70}
71
72pub(crate) fn class_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
74 let base = args.remove_left_or_key("Base");
75 let impls = args.remove_left_or_key("Impl");
76 let impls = impls.and_then(|v| v.as_type(ctx));
77 let t = mono(ctx.name.clone());
78 match base {
79 Some(value) => {
80 if let Some(base) = value.as_type(ctx) {
81 Ok(ValueObj::gen_t(GenTypeObj::class(t, Some(base), impls, true)).into())
82 } else {
83 Err(type_mismatch("type", value, "Base"))
84 }
85 }
86 None => Ok(ValueObj::gen_t(GenTypeObj::class(t, None, impls, true)).into()),
87 }
88}
89
90pub(crate) fn inherit_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
92 let sup = args
93 .remove_left_or_key("Super")
94 .ok_or_else(|| not_passed("Super"))?;
95 let Some(sup) = sup.as_type(ctx) else {
96 return Err(type_mismatch("class", sup, "Super"));
97 };
98 let impls = args.remove_left_or_key("Impl");
99 let impls = impls.and_then(|v| v.as_type(ctx));
100 let additional = args.remove_left_or_key("Additional");
101 let additional = additional.and_then(|v| v.as_type(ctx));
102 let t = mono(ctx.name.clone());
103 Ok(ValueObj::gen_t(GenTypeObj::inherited(t, sup, impls, additional)).into())
104}
105
106pub(crate) fn inheritable_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
109 let class = args
110 .remove_left_or_key("Class")
111 .ok_or_else(|| not_passed("Class"))?;
112 match class {
113 ValueObj::Type(TypeObj::Generated(mut gen)) => {
114 if let Some(typ) = gen.impls_mut() {
115 match typ.as_mut().map(|x| x.as_mut()) {
116 Some(TypeObj::Generated(gen)) => {
117 *gen.typ_mut() = and(mem::take(gen.typ_mut()), mono("InheritableType"));
118 }
119 Some(TypeObj::Builtin { t, .. }) => {
120 *t = and(mem::take(t), mono("InheritableType"));
121 }
122 _ => {
123 *typ = Some(Box::new(TypeObj::builtin_trait(mono("InheritableType"))));
124 }
125 }
126 }
127 Ok(ValueObj::Type(TypeObj::Generated(gen)).into())
128 }
129 other => feature_error!(
130 EvalValueError,
131 _ctx,
132 Location::Unknown,
133 &format!("Inheritable {other}")
134 ),
135 }
136}
137
138pub(crate) fn override_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
139 let func = args
140 .remove_left_or_key("func")
141 .ok_or_else(|| not_passed("func"))?;
142 Ok(func.into())
143}
144
145pub(crate) fn trait_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
147 let req = args
148 .remove_left_or_key("Requirement")
149 .ok_or_else(|| not_passed("Requirement"))?;
150 let Some(req) = req.as_type(ctx) else {
151 return Err(type_mismatch("type", req, "Requirement"));
152 };
153 let impls = args.remove_left_or_key("Impl");
154 let impls = impls.and_then(|v| v.as_type(ctx));
155 let t = mono(ctx.name.clone());
156 Ok(ValueObj::gen_t(GenTypeObj::trait_(t, req, impls, true)).into())
157}
158
159pub(crate) fn patch_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
161 let base = args
162 .remove_left_or_key("Base")
163 .ok_or_else(|| not_passed("Base"))?;
164 let Some(base) = base.as_type(ctx) else {
165 return Err(type_mismatch("type", base, "Base"));
166 };
167 let impls = args.remove_left_or_key("Impl");
168 let impls = impls.and_then(|v| v.as_type(ctx));
169 let t = mono(ctx.name.clone());
170 Ok(ValueObj::gen_t(GenTypeObj::patch(t, base, impls)).into())
171}
172
173pub(crate) fn subsume_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
175 let sup = args
176 .remove_left_or_key("Super")
177 .ok_or_else(|| not_passed("Super"))?;
178 let Some(sup) = sup.as_type(ctx) else {
179 return Err(type_mismatch("trait", sup, "Super"));
180 };
181 let impls = args.remove_left_or_key("Impl");
182 let impls = impls.and_then(|v| v.as_type(ctx));
183 let additional = args.remove_left_or_key("Additional");
184 let additional = additional.and_then(|v| v.as_type(ctx));
185 let t = mono(ctx.name.clone());
186 Ok(ValueObj::gen_t(GenTypeObj::subsumed(t, sup, impls, additional)).into())
187}
188
189pub(crate) fn structural_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
190 let type_ = args
191 .remove_left_or_key("Type")
192 .ok_or_else(|| not_passed("Type"))?;
193 let Some(base) = type_.as_type(ctx) else {
194 return Err(type_mismatch("type", type_, "Type"));
195 };
196 let t = base.typ().clone().structuralize();
197 Ok(ValueObj::gen_t(GenTypeObj::structural(t, base)).into())
198}
199
200pub(crate) fn __list_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
201 let slf = args
202 .remove_left_or_key("Self")
203 .ok_or_else(|| not_passed("Self"))?;
204 let slf = match ctx.convert_value_into_list(slf) {
205 Ok(slf) => slf,
206 Err(val) => {
207 return Err(type_mismatch("List", val, "Self"));
208 }
209 };
210 let index = args
211 .remove_left_or_key("Index")
212 .ok_or_else(|| not_passed("Index"))?;
213 let Ok(index) = usize::try_from(&index) else {
214 return Err(type_mismatch("Nat", index, "Index"));
215 };
216 if let Some(v) = slf.get(index) {
217 Ok(v.clone().into())
218 } else {
219 Err(ErrorCore::new(
220 vec![SubMessage::only_loc(Location::Unknown)],
221 format!(
222 "[{}] has {} elements, but accessed {}th element",
223 erg_common::fmt_vec(&slf),
224 slf.len(),
225 index
226 ),
227 line!() as usize,
228 ErrorKind::IndexError,
229 Location::Unknown,
230 )
231 .into())
232 }
233}
234
235pub(crate) fn sub_vdict_get<'d>(
236 dict: &'d Dict<ValueObj, ValueObj>,
237 key: &ValueObj,
238 ctx: &Context,
239) -> Option<&'d ValueObj> {
240 set_recursion_limit!(None, 64);
241 let mut matches = vec![];
242 for (k, v) in dict.iter() {
243 if key == k {
244 return Some(v);
245 }
246 match (
247 ctx.convert_value_into_type(key.clone()),
248 ctx.convert_value_into_type(k.clone()),
249 ) {
250 (Ok(idx), Ok(kt))
251 if dict.len() == 1 || ctx.subtype_of(&idx.lower_bounded(), &kt.lower_bounded()) =>
252 {
253 matches.push((idx, kt, v));
254 }
255 _ => {}
256 }
257 }
258 for (idx, kt, v) in matches.into_iter() {
259 let list = UndoableLinkedList::new();
260 match ctx.undoable_sub_unify(&idx, &kt, &(), &list, None) {
261 Ok(_) => {
262 return Some(v);
263 }
264 Err(_err) => {
265 erg_common::log!(err "{idx} <!: {kt} => {v}");
266 }
267 }
268 }
269 None
270}
271
272pub(crate) fn sub_tpdict_get<'d>(
273 dict: &'d Dict<TyParam, TyParam>,
274 key: &TyParam,
275 ctx: &Context,
276) -> Option<&'d TyParam> {
277 let mut matches = vec![];
278 for (k, v) in dict.iter() {
279 if key == k {
280 return Some(v);
281 }
282 match (
283 ctx.convert_tp_into_type(key.clone()),
284 ctx.convert_tp_into_type(k.clone()),
285 ) {
286 (Ok(idx), Ok(kt))
287 if dict.len() == 1 || ctx.subtype_of(&idx.lower_bounded(), &kt.lower_bounded()) =>
288 {
289 matches.push((idx, kt, v));
290 }
291 _ => {}
292 }
293 }
294 for (idx, kt, v) in matches.into_iter() {
295 let list = UndoableLinkedList::new();
296 match ctx.undoable_sub_unify(&idx, &kt, &(), &list, None) {
297 Ok(_) => {
298 return Some(v);
299 }
300 Err(_err) => {
301 erg_common::log!(err "{idx} <!: {kt} => {v}");
302 }
303 }
304 }
305 None
306}
307
308fn homogenize_dict_type(dict: &Dict<Type, Type>, ctx: &Context) -> Dict<Type, Type> {
310 let mut union_key = Type::Never;
311 let mut union_value = Type::Never;
312 for (k, v) in dict.iter() {
313 union_key = ctx.union(&union_key, k);
314 union_value = ctx.union(&union_value, v);
315 }
316 dict! { union_key => union_value }
317}
318
319fn homogenize_dict(dict: &Dict<ValueObj, ValueObj>, ctx: &Context) -> Dict<ValueObj, ValueObj> {
321 let mut type_dict = Dict::new();
322 for (k, v) in dict.iter() {
323 match (k, v) {
324 (ValueObj::Type(k), ValueObj::Type(v)) => {
325 type_dict.insert(k.typ().clone(), v.typ().clone());
326 }
327 _ => {
328 return dict.clone();
329 }
330 }
331 }
332 let dict_t = homogenize_dict_type(&type_dict, ctx);
333 let mut value_dict = Dict::new();
334 for (k, v) in dict_t.iter() {
335 let k = ValueObj::builtin_type(k.clone());
336 let v = ValueObj::builtin_type(v.clone());
337 value_dict.insert(k, v);
338 }
339 value_dict
340}
341
342pub(crate) fn __dict_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
343 let slf = args
344 .remove_left_or_key("Self")
345 .ok_or_else(|| not_passed("Self"))?;
346 let Ok(slf) = ctx.convert_value_to_dict(&slf) else {
347 return Err(type_mismatch("Dict", slf, "Self"));
348 };
349 let index = args
350 .remove_left_or_key("Index")
351 .ok_or_else(|| not_passed("Index"))?;
352 if let Some(v) = slf
353 .linear_get(&index)
354 .or_else(|| sub_vdict_get(&slf, &index, ctx))
355 {
356 Ok(v.clone().into())
357 } else if let Some(v) = sub_vdict_get(&homogenize_dict(&slf, ctx), &index, ctx).cloned() {
358 Ok(v.into())
359 } else {
360 let index = if let ValueObj::Type(t) = &index {
361 ValueObj::builtin_type(ctx.readable_type(t.typ().clone()))
362 } else {
363 index
364 };
365 Err(no_key(slf, index))
366 }
367}
368
369pub(crate) fn dict_keys(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
374 let slf = args
375 .remove_left_or_key("Self")
376 .ok_or_else(|| not_passed("Self"))?;
377 let Ok(slf) = ctx.convert_value_to_dict(&slf) else {
378 return Err(type_mismatch("Dict", slf, "Self"));
379 };
380 let dict_type = slf
381 .iter()
382 .map(|(k, v)| {
383 let k = ctx.convert_value_into_type(k.clone())?;
384 let v = ctx.convert_value_into_type(v.clone())?;
385 Ok((k, v))
386 })
387 .collect::<Result<Dict<_, _>, ValueObj>>();
388 if let Ok(slf) = dict_type {
389 let union = slf
390 .keys()
391 .fold(Type::Never, |union, t| ctx.union(&union, t));
392 Ok(ValueObj::builtin_type(union).into())
394 } else {
395 Ok(ValueObj::List(slf.into_keys().collect::<Vec<_>>().into()).into())
396 }
397}
398
399pub(crate) fn dict_values(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
404 let slf = args
405 .remove_left_or_key("Self")
406 .ok_or_else(|| not_passed("Self"))?;
407 let Ok(slf) = ctx.convert_value_to_dict(&slf) else {
408 return Err(type_mismatch("Dict", slf, "Self"));
409 };
410 let dict_type = slf
411 .iter()
412 .map(|(k, v)| {
413 let k = ctx.convert_value_into_type(k.clone())?;
414 let v = ctx.convert_value_into_type(v.clone())?;
415 Ok((k, v))
416 })
417 .collect::<Result<Dict<_, _>, ValueObj>>();
418 if let Ok(slf) = dict_type {
419 let union = slf
420 .values()
421 .fold(Type::Never, |union, t| ctx.union(&union, t));
422 Ok(ValueObj::builtin_type(union).into())
424 } else {
425 Ok(ValueObj::List(slf.into_values().collect::<Vec<_>>().into()).into())
426 }
427}
428
429pub(crate) fn dict_items(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
434 let slf = args
435 .remove_left_or_key("Self")
436 .ok_or_else(|| not_passed("Self"))?;
437 let Ok(slf) = ctx.convert_value_to_dict(&slf) else {
438 return Err(type_mismatch("Dict", slf, "Self"));
439 };
440 let dict_type = slf
441 .iter()
442 .map(|(k, v)| {
443 let k = ctx.convert_value_into_type(k.clone())?;
444 let v = ctx.convert_value_into_type(v.clone())?;
445 Ok((k, v))
446 })
447 .collect::<Result<Dict<_, _>, ValueObj>>();
448 if let Ok(slf) = dict_type {
449 let union = slf.into_iter().fold(Type::Never, |union, (k, v)| {
450 ctx.union(&union, &tuple_t(vec![k, v]))
451 });
452 Ok(ValueObj::builtin_type(union).into())
454 } else {
455 Ok(ValueObj::List(
456 slf.into_iter()
457 .map(|(k, v)| ValueObj::Tuple(vec![k, v].into()))
458 .collect::<Vec<_>>()
459 .into(),
460 )
461 .into())
462 }
463}
464
465pub(crate) fn dict_concat(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
468 let slf = args
469 .remove_left_or_key("Self")
470 .ok_or_else(|| not_passed("Self"))?;
471 let Ok(slf) = ctx.convert_value_to_dict(&slf) else {
472 return Err(type_mismatch("Dict", slf, "Self"));
473 };
474 let other = args
475 .remove_left_or_key("Other")
476 .ok_or_else(|| not_passed("Other"))?;
477 let ValueObj::Dict(other) = other else {
478 return Err(type_mismatch("Dict", other, "Other"));
479 };
480 Ok(ValueObj::Dict(slf.concat(other)).into())
481}
482
483pub(crate) fn dict_diff(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
484 let slf = args
485 .remove_left_or_key("Self")
486 .ok_or_else(|| not_passed("Self"))?;
487 let Ok(slf) = ctx.convert_value_to_dict(&slf) else {
488 return Err(type_mismatch("Dict", slf, "Self"));
489 };
490 let other = args
491 .remove_left_or_key("Other")
492 .ok_or_else(|| not_passed("Other"))?;
493 let ValueObj::Dict(other) = other else {
494 return Err(type_mismatch("Dict", other, "Other"));
495 };
496 Ok(ValueObj::Dict(slf.diff(&other)).into())
497}
498
499pub(crate) fn list_constructor(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
500 let _cls = args
501 .remove_left_or_key("Cls")
502 .ok_or_else(|| not_passed("Cls"))?;
503 let elem = args
504 .remove_left_or_key("elem")
505 .ok_or_else(|| not_passed("elem"))?;
506 let Ok(elem_t) = ctx.convert_value_into_type(elem.clone()) else {
507 return Err(type_mismatch("Type", elem, "elem"));
508 };
509 let len = args
510 .remove_left_or_key("len")
511 .map(TyParam::value)
512 .unwrap_or(TyParam::erased(Type::Nat));
513 Ok(ValueObj::builtin_class(list_mut(elem_t, len)).into())
514}
515
516pub(crate) fn dict_constructor(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
517 let _cls = args
518 .remove_left_or_key("Cls")
519 .ok_or_else(|| not_passed("Cls"))?;
520 let key_value = args
521 .remove_left_or_key("key_value")
522 .ok_or_else(|| not_passed("key_value"))?;
523 let (key_t, value_t) = match key_value {
524 ValueObj::Tuple(ts) | ValueObj::List(ts) => {
525 let key = ts.first().ok_or_else(|| not_passed("key"))?;
526 let value = ts.get(1).ok_or_else(|| not_passed("value"))?;
527 let Ok(key_t) = ctx.convert_value_into_type(key.clone()) else {
528 return Err(type_mismatch("Type", key, "key"));
529 };
530 let Ok(value_t) = ctx.convert_value_into_type(value.clone()) else {
531 return Err(type_mismatch("Type", value, "value"));
532 };
533 (key_t, value_t)
534 }
535 _ => return Err(type_mismatch("Tuple", key_value, "key_value")),
536 };
537 Ok(ValueObj::builtin_class(dict_mut(dict! { key_t => value_t }.into())).into())
538}
539
540pub(crate) fn list_union(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
542 let slf = args
543 .remove_left_or_key("Self")
544 .ok_or_else(|| not_passed("Self"))?;
545 let ValueObj::List(slf) = slf else {
546 return Err(type_mismatch("List", slf, "Self"));
547 };
548 let slf = slf
549 .iter()
550 .flat_map(|t| ctx.convert_value_into_type(t.clone()))
551 .collect::<Vec<_>>();
552 if slf.iter().any(|t| t.has_proj() || t.has_proj_call()) {
554 return Ok(TyParam::t(Type::Obj));
555 }
556 let union = slf
557 .iter()
558 .fold(Type::Never, |union, t| ctx.union(&union, t));
559 Ok(ValueObj::builtin_type(union).into())
560}
561
562fn _lis_shape(arr: ValueObj, ctx: &Context) -> Result<Vec<TyParam>, String> {
563 let mut shape = vec![];
564 let mut arr = arr;
565 loop {
566 match arr {
567 ValueObj::List(a) => {
568 shape.push(ValueObj::from(a.len()).into());
569 match a.first() {
570 Some(arr_ @ (ValueObj::List(_) | ValueObj::Type(_))) => {
571 arr = arr_.clone();
572 }
573 _ => {
574 break;
575 }
576 }
577 }
578 ValueObj::Type(ref t) if &t.typ().qual_name()[..] == "List" => {
579 let mut tps = t.typ().typarams();
580 let elem = match ctx.convert_tp_into_type(tps.remove(0)) {
581 Ok(elem) => elem,
582 Err(err) => {
583 return Err(err.to_string());
584 }
585 };
586 let len = tps.remove(0);
587 shape.push(len);
588 arr = ValueObj::builtin_type(elem);
589 }
590 _ => {
591 break;
592 }
593 }
594 }
595 Ok(shape)
596}
597
598pub(crate) fn list_shape(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
605 let val = args
606 .remove_left_or_key("Self")
607 .ok_or_else(|| not_passed("Self"))?;
608 let res = _lis_shape(val, ctx).unwrap();
609 let lis = TyParam::List(res);
610 Ok(lis)
611}
612
613fn _list_scalar_type(mut typ: Type, ctx: &Context) -> Result<Type, String> {
614 loop {
615 if matches!(&typ.qual_name()[..], "List" | "List!" | "UnsizedList") {
616 let tp = typ.typarams().remove(0);
617 match ctx.convert_tp_into_type(tp) {
618 Ok(typ_) => {
619 typ = typ_;
620 }
621 Err(err) => {
622 return Err(format!("Cannot convert {err} into type"));
623 }
624 }
625 } else {
626 return Ok(typ);
627 }
628 }
629}
630
631pub(crate) fn list_scalar_type(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
632 let slf = args
633 .remove_left_or_key("Self")
634 .ok_or_else(|| not_passed("Self"))?;
635 let Ok(slf) = ctx.convert_value_into_type(slf.clone()) else {
636 return Err(type_mismatch("Type", slf, "Self"));
637 };
638 let res = _list_scalar_type(slf, ctx).unwrap();
639 Ok(TyParam::t(res))
640}
641
642fn _scalar_type(mut value: ValueObj, _ctx: &Context) -> Result<Type, String> {
643 loop {
644 match value {
645 ValueObj::List(a) => match a.first() {
646 Some(elem) => {
647 value = elem.clone();
648 }
649 None => {
650 return Ok(Type::Never);
651 }
652 },
653 ValueObj::Set(s) => match s.iter().next() {
654 Some(elem) => {
655 value = elem.clone();
656 }
657 None => {
658 return Ok(Type::Never);
659 }
660 },
661 ValueObj::Tuple(t) => match t.first() {
662 Some(elem) => {
663 value = elem.clone();
664 }
665 None => {
666 return Ok(Type::Never);
667 }
668 },
669 ValueObj::UnsizedList(a) => {
670 value = *a.clone();
671 }
672 other => {
673 return Ok(other.class());
674 }
675 }
676 }
677}
678
679#[allow(unused)]
684pub(crate) fn scalar_type(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
685 let val = args
686 .remove_left_or_key("Self")
687 .ok_or_else(|| not_passed("Self"))?;
688 let res = _scalar_type(val, ctx).unwrap();
689 let lis = TyParam::t(res);
690 Ok(lis)
691}
692
693fn _list_sum(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
694 match arr {
695 ValueObj::List(a) => {
696 let mut sum = 0f64;
697 for v in a.iter() {
698 match v {
699 ValueObj::Nat(n) => {
700 sum += *n as f64;
701 }
702 ValueObj::Int(n) => {
703 sum += *n as f64;
704 }
705 ValueObj::Float(n) => {
706 sum += **n;
707 }
708 ValueObj::Inf => {
709 return Ok(ValueObj::Inf);
710 }
711 ValueObj::NegInf => {
712 return Ok(ValueObj::NegInf);
713 }
714 _ => {
715 return Err(format!("Cannot sum {v}"));
716 }
717 }
718 }
719 if sum.round() == sum && sum >= 0.0 {
720 Ok(ValueObj::Nat(sum as u64))
721 } else if sum.round() == sum {
722 Ok(ValueObj::Int(sum as i32))
723 } else {
724 Ok(ValueObj::from(sum))
725 }
726 }
727 _ => Err(format!("Cannot sum {arr}")),
728 }
729}
730
731pub(crate) fn list_sum(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
735 let val = args
736 .remove_left_or_key("Self")
737 .ok_or_else(|| not_passed("Self"))?;
738 let res = _list_sum(val, ctx).unwrap();
739 let lis = TyParam::Value(res);
740 Ok(lis)
741}
742
743fn _list_prod(lis: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
744 match lis {
745 ValueObj::List(a) => {
746 let mut prod = 1f64;
747 for v in a.iter() {
748 match v {
749 ValueObj::Nat(n) => {
750 prod *= *n as f64;
751 }
752 ValueObj::Int(n) => {
753 prod *= *n as f64;
754 }
755 ValueObj::Float(n) => {
756 prod *= **n;
757 }
758 ValueObj::Inf => {
759 return Ok(ValueObj::Inf);
760 }
761 ValueObj::NegInf => {
762 return Ok(ValueObj::NegInf);
763 }
764 _ => {
765 return Err(format!("Cannot prod {v}"));
766 }
767 }
768 }
769 if prod.round() == prod && prod >= 0.0 {
770 Ok(ValueObj::Nat(prod as u64))
771 } else if prod.round() == prod {
772 Ok(ValueObj::Int(prod as i32))
773 } else {
774 Ok(ValueObj::from(prod))
775 }
776 }
777 _ => Err(format!("Cannot prod {lis}")),
778 }
779}
780
781pub(crate) fn list_prod(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
785 let val = args
786 .remove_left_or_key("Self")
787 .ok_or_else(|| not_passed("Self"))?;
788 let res = _list_prod(val, ctx).unwrap();
789 let lis = TyParam::Value(res);
790 Ok(lis)
791}
792
793fn _list_reversed(lis: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
794 match lis {
795 ValueObj::List(a) => {
796 let mut vec = a.to_vec();
797 vec.reverse();
798 Ok(ValueObj::List(vec.into()))
799 }
800 _ => Err(format!("Cannot reverse {lis}")),
801 }
802}
803
804pub(crate) fn list_reversed(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
805 let val = args
806 .remove_left_or_key("Self")
807 .ok_or_else(|| not_passed("Self"))?;
808 let res = _list_reversed(val, ctx).unwrap();
809 let lis = TyParam::Value(res);
810 Ok(lis)
811}
812
813fn _list_insert_at(
814 lis: ValueObj,
815 index: usize,
816 value: ValueObj,
817 _ctx: &Context,
818) -> Result<ValueObj, String> {
819 match lis {
820 ValueObj::List(a) => {
821 let mut a = a.to_vec();
822 if index > a.len() {
823 return Err(format!("Index out of range: {index}"));
824 }
825 a.insert(index, value);
826 Ok(ValueObj::List(a.into()))
827 }
828 _ => Err(format!("Cannot insert into {lis}")),
829 }
830}
831
832pub(crate) fn list_insert_at(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
833 let lis = args
834 .remove_left_or_key("Self")
835 .ok_or_else(|| not_passed("Self"))?;
836 let index = args
837 .remove_left_or_key("Index")
838 .ok_or_else(|| not_passed("Index"))?;
839 let value = args
840 .remove_left_or_key("Value")
841 .ok_or_else(|| not_passed("Value"))?;
842 let Ok(index) = usize::try_from(&index) else {
843 return Err(type_mismatch("Nat", index, "Index"));
844 };
845 let res = _list_insert_at(lis, index, value, ctx).unwrap();
846 let lis = TyParam::Value(res);
847 Ok(lis)
848}
849
850fn _list_remove_at(lis: ValueObj, index: usize, _ctx: &Context) -> Result<ValueObj, String> {
851 match lis {
852 ValueObj::List(a) => {
853 let mut a = a.to_vec();
854 if index >= a.len() {
855 return Err(format!("Index out of range: {index}"));
856 }
857 a.remove(index);
858 Ok(ValueObj::List(a.into()))
859 }
860 _ => Err(format!("Cannot remove from {lis}")),
861 }
862}
863
864pub(crate) fn list_remove_at(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
865 let val = args
866 .remove_left_or_key("Self")
867 .ok_or_else(|| not_passed("Self"))?;
868 let index = args
869 .remove_left_or_key("Index")
870 .ok_or_else(|| not_passed("Index"))?;
871 let Ok(index) = usize::try_from(&index) else {
872 return Err(type_mismatch("Nat", index, "Index"));
873 };
874 let res = _list_remove_at(val, index, ctx).unwrap();
875 let lis = TyParam::Value(res);
876 Ok(lis)
877}
878
879fn _list_remove_all(lis: ValueObj, value: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
880 match lis {
881 ValueObj::List(a) => {
882 let mut a = a.to_vec();
883 a.retain(|v| v != &value);
884 Ok(ValueObj::List(a.into()))
885 }
886 _ => Err(format!("Cannot remove from {lis}")),
887 }
888}
889
890pub(crate) fn list_remove_all(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
891 let val = args
892 .remove_left_or_key("Self")
893 .ok_or_else(|| not_passed("Self"))?;
894 let value = args
895 .remove_left_or_key("Value")
896 .ok_or_else(|| not_passed("Value"))?;
897 let res = _list_remove_all(val, value, ctx).unwrap();
898 let lis = TyParam::Value(res);
899 Ok(lis)
900}
901
902pub(crate) fn __range_getitem__(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
903 let slf = args
904 .remove_left_or_key("Self")
905 .ok_or_else(|| not_passed("Self"))?;
906 let ValueObj::DataClass { name: _, fields } = slf else {
907 return Err(type_mismatch("Range", slf, "Self"));
908 };
909 let index = args
910 .remove_left_or_key("Index")
911 .ok_or_else(|| not_passed("Index"))?;
912 let Ok(index) = usize::try_from(&index) else {
913 return Err(type_mismatch("Nat", index, "Index"));
914 };
915 let start = fields
916 .get("start")
917 .ok_or_else(|| no_key(&fields, "start"))?;
918 let Ok(start) = usize::try_from(start) else {
919 return Err(type_mismatch("Nat", start, "start"));
920 };
921 let end = fields.get("end").ok_or_else(|| no_key(&fields, "end"))?;
922 let Ok(end) = usize::try_from(end) else {
923 return Err(type_mismatch("Nat", end, "end"));
924 };
925 if start + index < end {
927 Ok(ValueObj::Nat((start + index) as u64).into())
928 } else {
929 Err(ErrorCore::new(
930 vec![SubMessage::only_loc(Location::Unknown)],
931 format!("Index out of range: {index}"),
932 line!() as usize,
933 ErrorKind::IndexError,
934 Location::Unknown,
935 )
936 .into())
937 }
938}
939
940pub(crate) fn __named_tuple_getitem__(
941 mut args: ValueArgs,
942 ctx: &Context,
943) -> EvalValueResult<TyParam> {
944 let slf = args
945 .remove_left_or_key("Self")
946 .ok_or_else(|| not_passed("Self"))?;
947 let fields = match ctx.convert_value_into_type(slf) {
948 Ok(Type::NamedTuple(fields)) => fields,
949 Ok(other) => {
950 return Err(type_mismatch("NamedTuple", other, "Self"));
951 }
952 Err(val) => {
953 return Err(type_mismatch("NamedTuple", val, "Self"));
954 }
955 };
956 let index = args
957 .remove_left_or_key("Index")
958 .ok_or_else(|| not_passed("Index"))?;
959 let Ok(index) = usize::try_from(&index) else {
960 return Err(type_mismatch("Nat", index, "Index"));
961 };
962 if let Some((_, t)) = fields.get(index) {
963 Ok(TyParam::t(t.clone()))
964 } else {
965 Err(no_key(Type::NamedTuple(fields), index))
966 }
967}
968
969pub(crate) fn named_tuple_union(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
972 let slf = args
973 .remove_left_or_key("Self")
974 .ok_or_else(|| not_passed("Self"))?;
975 let fields = match ctx.convert_value_into_type(slf) {
976 Ok(Type::NamedTuple(fields)) => fields,
977 Ok(Type::Mono(n)) if &n == "GenericNamedTuple" => {
978 return Ok(ValueObj::builtin_type(Type::Obj).into());
979 }
980 Ok(other) => {
981 return Err(type_mismatch("NamedTuple", other, "Self"));
982 }
983 Err(val) => {
984 return Err(type_mismatch("NamedTuple", val, "Self"));
985 }
986 };
987 let union = fields
988 .iter()
989 .fold(Type::Never, |union, (_, t)| ctx.union(&union, t));
990 Ok(ValueObj::builtin_type(union).into())
991}
992
993pub(crate) fn as_dict(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
996 let slf = args
997 .remove_left_or_key("Self")
998 .ok_or_else(|| not_passed("Self"))?;
999 let fields = match ctx.convert_value_into_type(slf) {
1000 Ok(Type::Record(fields)) => fields,
1001 Ok(Type::Mono(n)) if &n == "Record" => {
1002 let dict = dict! { Type::Obj => Type::Obj };
1003 return Ok(ValueObj::builtin_type(Type::from(dict)).into());
1004 }
1005 Ok(other) => {
1006 return Err(type_mismatch("Record", other, "Self"));
1007 }
1008 Err(val) => {
1009 return Err(type_mismatch("Record", val, "Self"));
1010 }
1011 };
1012 let dict = fields
1013 .into_iter()
1014 .map(|(k, v)| (v_enum(set! { k.symbol.into() }), v))
1015 .collect::<Dict<_, _>>();
1016 Ok(ValueObj::builtin_type(Type::from(dict)).into())
1017}
1018
1019pub(crate) fn as_record(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
1021 let slf = args
1022 .remove_left_or_key("Self")
1023 .ok_or_else(|| not_passed("Self"))?;
1024 let fields = match ctx.convert_value_into_type(slf) {
1025 Ok(Type::Poly { name, params }) if &name == "Dict" => {
1026 Dict::try_from(params[0].clone()).unwrap()
1027 }
1028 Ok(other) => {
1029 return Err(type_mismatch("Dict", other, "Self"));
1030 }
1031 Err(val) => {
1032 return Err(type_mismatch("Dict", val, "Self"));
1033 }
1034 };
1035 let mut dict = Dict::new();
1036 for (k, v) in fields {
1037 match (ctx.convert_tp_into_type(k), ctx.convert_tp_into_type(v)) {
1038 (Ok(k_t), Ok(v_t)) => {
1039 if let Some(values) = k_t.refinement_values() {
1040 for value in values {
1041 if let TyParam::Value(ValueObj::Str(field)) = value {
1042 dict.insert(Field::public(field.clone()), v_t.clone());
1043 } else {
1044 return Err(type_mismatch("Str", value, "Key"));
1045 }
1046 }
1047 } else {
1048 return Err(type_mismatch("Str refinement type", k_t, "Key"));
1049 }
1050 }
1051 (Ok(_), Err(err)) | (Err(err), Ok(_)) => {
1052 return Err(type_mismatch("Type", err, "Self"));
1053 }
1054 (Err(k), Err(_v)) => {
1055 return Err(type_mismatch("Type", k, "Self"));
1056 }
1057 };
1058 }
1059 Ok(ValueObj::builtin_type(Type::Record(dict)).into())
1060}
1061
1062pub(crate) fn int_abs(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1063 let slf = args
1064 .remove_left_or_key("self")
1065 .ok_or_else(|| not_passed("self"))?;
1066 let Some(slf) = slf.as_int() else {
1067 return Err(type_mismatch("Int", slf, "self"));
1068 };
1069 Ok(ValueObj::Int(slf.abs()).into())
1070}
1071
1072pub(crate) fn str_endswith(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1073 let slf = args
1074 .remove_left_or_key("self")
1075 .ok_or_else(|| not_passed("self"))?;
1076 let suffix = args
1077 .remove_left_or_key("suffix")
1078 .ok_or_else(|| not_passed("suffix"))?;
1079 let Some(slf) = slf.as_str() else {
1080 return Err(type_mismatch("Str", slf, "self"));
1081 };
1082 let Some(suffix) = suffix.as_str() else {
1083 return Err(type_mismatch("Str", suffix, "suffix"));
1084 };
1085 Ok(ValueObj::Bool(slf.ends_with(&suffix[..])).into())
1086}
1087
1088pub(crate) fn str_find(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1089 let slf = args
1090 .remove_left_or_key("self")
1091 .ok_or_else(|| not_passed("self"))?;
1092 let sub = args
1093 .remove_left_or_key("sub")
1094 .ok_or_else(|| not_passed("sub"))?;
1095 let Some(slf) = slf.as_str() else {
1096 return Err(type_mismatch("Str", slf, "self"));
1097 };
1098 let Some(sub) = sub.as_str() else {
1099 return Err(type_mismatch("Str", sub, "sub"));
1100 };
1101 Ok(ValueObj::Int(slf.find(&sub[..]).map_or(-1, |i| i as i32)).into())
1102}
1103
1104pub(crate) fn str_isalpha(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1105 let slf = args
1106 .remove_left_or_key("self")
1107 .ok_or_else(|| not_passed("self"))?;
1108 let Some(slf) = slf.as_str() else {
1109 return Err(type_mismatch("Str", slf, "self"));
1110 };
1111 Ok(ValueObj::Bool(slf.chars().all(|c| c.is_alphabetic())).into())
1112}
1113
1114pub(crate) fn str_isascii(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1115 let slf = args
1116 .remove_left_or_key("self")
1117 .ok_or_else(|| not_passed("self"))?;
1118 let Some(slf) = slf.as_str() else {
1119 return Err(type_mismatch("Str", slf, "self"));
1120 };
1121 Ok(ValueObj::Bool(slf.is_ascii()).into())
1122}
1123
1124pub(crate) fn str_isdecimal(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1125 let slf = args
1126 .remove_left_or_key("self")
1127 .ok_or_else(|| not_passed("self"))?;
1128 let Some(slf) = slf.as_str() else {
1129 return Err(type_mismatch("Str", slf, "self"));
1130 };
1131 Ok(ValueObj::Bool(slf.chars().all(|c| c.is_ascii_digit())).into())
1132}
1133
1134pub(crate) fn str_join(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1135 let slf = args
1136 .remove_left_or_key("self")
1137 .ok_or_else(|| not_passed("self"))?;
1138 let iterable = args
1139 .remove_left_or_key("iterable")
1140 .ok_or_else(|| not_passed("iterable"))?;
1141 let Some(slf) = slf.as_str() else {
1142 return Err(type_mismatch("Str", slf, "self"));
1143 };
1144 let arr = match iterable {
1145 ValueObj::List(a) => a.to_vec(),
1146 ValueObj::Tuple(t) => t.to_vec(),
1147 ValueObj::Set(s) => s.into_iter().collect(),
1148 ValueObj::Dict(d) => d.into_keys().collect(),
1149 _ => {
1150 return Err(type_mismatch("Iterable(Str)", iterable, "iterable"));
1151 }
1152 };
1153 let mut joined = String::new();
1154 for v in arr.iter() {
1155 let Some(v) = v.as_str() else {
1156 return Err(type_mismatch("Str", v, "arr.next()"));
1157 };
1158 joined.push_str(&v[..]);
1159 joined.push_str(&slf[..]);
1160 }
1161 joined.pop();
1162 Ok(ValueObj::Str(joined.into()).into())
1163}
1164
1165pub(crate) fn str_replace(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1166 let slf = args
1167 .remove_left_or_key("self")
1168 .ok_or_else(|| not_passed("self"))?;
1169 let old = args
1170 .remove_left_or_key("old")
1171 .ok_or_else(|| not_passed("old"))?;
1172 let new = args
1173 .remove_left_or_key("new")
1174 .ok_or_else(|| not_passed("new"))?;
1175 let Some(slf) = slf.as_str() else {
1176 return Err(type_mismatch("Str", slf, "self"));
1177 };
1178 let Some(old) = old.as_str() else {
1179 return Err(type_mismatch("Str", old, "old"));
1180 };
1181 let Some(new) = new.as_str() else {
1182 return Err(type_mismatch("Str", new, "new"));
1183 };
1184 Ok(ValueObj::Str(slf.replace(&old[..], new).into()).into())
1185}
1186
1187pub(crate) fn str_startswith(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1188 let slf = args
1189 .remove_left_or_key("self")
1190 .ok_or_else(|| not_passed("self"))?;
1191 let prefix = args
1192 .remove_left_or_key("prefix")
1193 .ok_or_else(|| not_passed("prefix"))?;
1194 let Some(slf) = slf.as_str() else {
1195 return Err(type_mismatch("Str", slf, "self"));
1196 };
1197 let Some(prefix) = prefix.as_str() else {
1198 return Err(type_mismatch("Str", prefix, "prefix"));
1199 };
1200 Ok(ValueObj::Bool(slf.starts_with(&prefix[..])).into())
1201}
1202
1203pub(crate) fn abs_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1204 let num = args
1205 .remove_left_or_key("num")
1206 .ok_or_else(|| not_passed("num"))?;
1207 match num {
1208 ValueObj::Nat(n) => Ok(ValueObj::Nat(n).into()),
1209 ValueObj::Int(n) => Ok(ValueObj::Nat(n.unsigned_abs() as u64).into()),
1210 ValueObj::Bool(b) => Ok(ValueObj::Nat(b as u64).into()),
1211 ValueObj::Float(n) => Ok(ValueObj::from(n.abs()).into()),
1212 ValueObj::Inf => Ok(ValueObj::Inf.into()),
1213 ValueObj::NegInf => Ok(ValueObj::Inf.into()),
1214 _ => Err(type_mismatch("Num", num, "num")),
1215 }
1216}
1217
1218pub(crate) fn all_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1219 let iterable = args
1220 .remove_left_or_key("iterable")
1221 .ok_or_else(|| not_passed("iterable"))?;
1222 let arr = match iterable {
1223 ValueObj::List(a) => a.to_vec(),
1224 ValueObj::Tuple(t) => t.to_vec(),
1225 ValueObj::Set(s) => s.into_iter().collect(),
1226 _ => {
1227 return Err(type_mismatch("Iterable(Bool)", iterable, "iterable"));
1228 }
1229 };
1230 let mut all = true;
1231 for v in arr.iter() {
1232 match v {
1233 ValueObj::Bool(b) => {
1234 all &= *b;
1235 }
1236 _ => {
1237 return Err(type_mismatch("Bool", v, "iterable.next()"));
1238 }
1239 }
1240 }
1241 Ok(ValueObj::Bool(all).into())
1242}
1243
1244pub(crate) fn any_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1245 let iterable = args
1246 .remove_left_or_key("iterable")
1247 .ok_or_else(|| not_passed("iterable"))?;
1248 let arr = match iterable {
1249 ValueObj::List(a) => a.to_vec(),
1250 ValueObj::Tuple(t) => t.to_vec(),
1251 ValueObj::Set(s) => s.into_iter().collect(),
1252 _ => {
1253 return Err(type_mismatch("Iterable(Bool)", iterable, "iterable"));
1254 }
1255 };
1256 let mut any = false;
1257 for v in arr.iter() {
1258 match v {
1259 ValueObj::Bool(b) => {
1260 any |= *b;
1261 }
1262 _ => {
1263 return Err(type_mismatch("Bool", v, "iterable.next()"));
1264 }
1265 }
1266 }
1267 Ok(ValueObj::Bool(any).into())
1268}
1269
1270pub(crate) fn filter_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
1271 let func = args
1272 .remove_left_or_key("func")
1273 .ok_or_else(|| not_passed("func"))?;
1274 let iterable = args
1275 .remove_left_or_key("iterable")
1276 .ok_or_else(|| not_passed("iterable"))?;
1277 let arr = match iterable {
1278 ValueObj::List(a) => a.to_vec(),
1279 ValueObj::Tuple(t) => t.to_vec(),
1280 ValueObj::Set(s) => s.into_iter().collect(),
1281 _ => {
1282 return Err(type_mismatch("Iterable(T)", iterable, "iterable"));
1283 }
1284 };
1285 let subr = match func {
1286 ValueObj::Subr(f) => f,
1287 _ => {
1288 return Err(type_mismatch("Subr", func, "func"));
1289 }
1290 };
1291 let mut filtered = vec![];
1292 for v in arr.into_iter() {
1293 let args = ValueArgs::pos_only(vec![v.clone()]);
1294 match ctx.call(subr.clone(), args, Location::Unknown) {
1295 Ok(res) => match ctx.convert_tp_into_value(res) {
1296 Ok(res) => {
1297 if res.is_true() {
1298 filtered.push(v);
1299 }
1300 }
1301 Err(tp) => {
1302 return Err(type_mismatch("Bool", tp, "func"));
1303 }
1304 },
1305 Err((_res, mut err)) => {
1306 return Err(EvalValueError::from(*err.remove(0).core));
1307 }
1308 }
1309 }
1310 Ok(TyParam::Value(ValueObj::List(filtered.into())))
1311}
1312
1313pub(crate) fn len_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1314 let container = args
1315 .remove_left_or_key("iterable")
1316 .ok_or_else(|| not_passed("iterable"))?;
1317 let len = match container {
1318 ValueObj::List(a) => a.len(),
1319 ValueObj::Tuple(t) => t.len(),
1320 ValueObj::Set(s) => s.len(),
1321 ValueObj::Dict(d) => d.len(),
1322 ValueObj::Record(r) => r.len(),
1323 ValueObj::Str(s) => s.len(),
1324 _ => {
1325 return Err(type_mismatch("Container", container, "container"));
1326 }
1327 };
1328 Ok(ValueObj::Nat(len as u64).into())
1329}
1330
1331pub(crate) fn map_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
1332 let func = args
1333 .remove_left_or_key("func")
1334 .ok_or_else(|| not_passed("func"))?;
1335 let iterable = args
1336 .remove_left_or_key("iterable")
1337 .ok_or_else(|| not_passed("iterable"))?;
1338 let arr = match iterable {
1339 ValueObj::List(a) => a.to_vec(),
1340 ValueObj::Tuple(t) => t.to_vec(),
1341 ValueObj::Set(s) => s.into_iter().collect(),
1342 _ => {
1343 return Err(type_mismatch("Iterable(Bool)", iterable, "iterable"));
1344 }
1345 };
1346 let subr = match func {
1347 ValueObj::Subr(f) => f,
1348 _ => {
1349 return Err(type_mismatch("Subr", func, "func"));
1350 }
1351 };
1352 let mut mapped = vec![];
1353 for v in arr.into_iter() {
1354 let args = ValueArgs::pos_only(vec![v]);
1355 match ctx.call(subr.clone(), args, Location::Unknown) {
1356 Ok(res) => {
1357 mapped.push(res);
1358 }
1359 Err((_res, mut err)) => {
1360 return Err(EvalValueError::from(*err.remove(0).core));
1361 }
1362 }
1363 }
1364 Ok(TyParam::List(mapped))
1365}
1366
1367pub(crate) fn max_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1368 let iterable = args
1369 .remove_left_or_key("iterable")
1370 .ok_or_else(|| not_passed("iterable"))?;
1371 let arr = match iterable {
1372 ValueObj::List(a) => a.to_vec(),
1373 ValueObj::Tuple(t) => t.to_vec(),
1374 ValueObj::Set(s) => s.into_iter().collect(),
1375 _ => {
1376 return Err(type_mismatch("Iterable(Ord)", iterable, "iterable"));
1377 }
1378 };
1379 let mut max = ValueObj::NegInf;
1380 if arr.is_empty() {
1381 return Err(ErrorCore::new(
1382 vec![SubMessage::only_loc(Location::Unknown)],
1383 "max() arg is an empty sequence",
1384 line!() as usize,
1385 ErrorKind::ValueError,
1386 Location::Unknown,
1387 )
1388 .into());
1389 }
1390 for v in arr.into_iter() {
1391 if v.is_num() {
1392 if max.clone().try_lt(v.clone()).is_some_and(|b| b.is_true()) {
1393 max = v;
1394 }
1395 } else {
1396 return Err(type_mismatch("Ord", v, "iterable.next()"));
1397 }
1398 }
1399 Ok(max.into())
1400}
1401
1402pub(crate) fn min_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1403 let iterable = args
1404 .remove_left_or_key("iterable")
1405 .ok_or_else(|| not_passed("iterable"))?;
1406 let arr = match iterable {
1407 ValueObj::List(a) => a.to_vec(),
1408 ValueObj::Tuple(t) => t.to_vec(),
1409 ValueObj::Set(s) => s.into_iter().collect(),
1410 _ => {
1411 return Err(type_mismatch("Iterable(Ord)", iterable, "iterable"));
1412 }
1413 };
1414 let mut min = ValueObj::Inf;
1415 if arr.is_empty() {
1416 return Err(ErrorCore::new(
1417 vec![SubMessage::only_loc(Location::Unknown)],
1418 "min() arg is an empty sequence",
1419 line!() as usize,
1420 ErrorKind::ValueError,
1421 Location::Unknown,
1422 )
1423 .into());
1424 }
1425 for v in arr.into_iter() {
1426 if v.is_num() {
1427 if min.clone().try_gt(v.clone()).is_some_and(|b| b.is_true()) {
1428 min = v;
1429 }
1430 } else {
1431 return Err(type_mismatch("Ord", v, "iterable.next()"));
1432 }
1433 }
1434 Ok(min.into())
1435}
1436
1437pub(crate) fn not_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1438 let val = args
1439 .remove_left_or_key("val")
1440 .ok_or_else(|| not_passed("val"))?;
1441 match val {
1442 ValueObj::Bool(b) => Ok(ValueObj::Bool(!b).into()),
1443 _ => Err(type_mismatch("Bool", val, "val")),
1444 }
1445}
1446
1447pub(crate) fn reversed_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1448 let reversible = args
1449 .remove_left_or_key("reversible")
1450 .ok_or_else(|| not_passed("reversible"))?;
1451 let arr = match reversible {
1452 ValueObj::List(a) => a.to_vec(),
1453 ValueObj::Tuple(t) => t.to_vec(),
1454 _ => {
1455 return Err(type_mismatch("Reversible", reversible, "reversible"));
1456 }
1457 };
1458 let mut reversed = vec![];
1459 for v in arr.into_iter().rev() {
1460 reversed.push(v);
1461 }
1462 Ok(TyParam::Value(ValueObj::List(reversed.into())))
1463}
1464
1465pub(crate) fn str_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1466 let val = args
1467 .remove_left_or_key("val")
1468 .ok_or_else(|| not_passed("val"))?;
1469 if let Some(_encoding) = args.remove_left_or_key("encoding") {
1470 return Err(todo("encoding"));
1471 }
1472 Ok(ValueObj::Str(val.to_string().into()).into())
1473}
1474
1475pub(crate) fn sum_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1476 let iterable = args
1477 .remove_left_or_key("iterable")
1478 .ok_or_else(|| not_passed("iterable"))?;
1479 let arr = match iterable {
1480 ValueObj::List(a) => a.to_vec(),
1481 ValueObj::Tuple(t) => t.to_vec(),
1482 ValueObj::Set(s) => s.into_iter().collect(),
1483 ValueObj::Dict(d) => d.into_keys().collect(),
1484 ValueObj::Record(r) => r.into_values().collect(),
1485 _ => {
1486 return Err(type_mismatch("Iterable(Add)", iterable, "iterable"));
1487 }
1488 };
1489 let mut sum = ValueObj::Nat(0);
1490 for v in arr.into_iter() {
1491 if v.is_num() {
1492 sum = sum.try_add(v).unwrap();
1493 } else {
1494 return Err(type_mismatch("Add", v, "iterable.next()"));
1495 }
1496 }
1497 Ok(sum.into())
1498}
1499
1500pub(crate) fn resolve_path_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
1501 let path = args
1502 .remove_left_or_key("Path")
1503 .ok_or_else(|| not_passed("Path"))?;
1504 let path = match &path {
1505 ValueObj::Str(s) => Path::new(&s[..]),
1506 other => {
1507 return Err(type_mismatch("Str", other, "Path"));
1508 }
1509 };
1510 let Some(path) = ctx.cfg.input.resolve_path(path, &ctx.cfg) else {
1511 return Err(ErrorCore::new(
1512 vec![SubMessage::only_loc(Location::Unknown)],
1513 format!("Path {} is not found", path.display()),
1514 line!() as usize,
1515 ErrorKind::IoError,
1516 Location::Unknown,
1517 )
1518 .into());
1519 };
1520 Ok(ValueObj::Str(path.to_string_lossy().into()).into())
1521}
1522
1523pub(crate) fn resolve_decl_path_func(
1524 mut args: ValueArgs,
1525 ctx: &Context,
1526) -> EvalValueResult<TyParam> {
1527 let path = args
1528 .remove_left_or_key("Path")
1529 .ok_or_else(|| not_passed("Path"))?;
1530 let path = match &path {
1531 ValueObj::Str(s) => Path::new(&s[..]),
1532 other => {
1533 return Err(type_mismatch("Str", other, "Path"));
1534 }
1535 };
1536 let Some(path) = ctx.cfg.input.resolve_decl_path(path, &ctx.cfg) else {
1537 return Err(ErrorCore::new(
1538 vec![SubMessage::only_loc(Location::Unknown)],
1539 format!("Path {} is not found", path.display()),
1540 line!() as usize,
1541 ErrorKind::IoError,
1542 Location::Unknown,
1543 )
1544 .into());
1545 };
1546 Ok(ValueObj::Str(path.to_string_lossy().into()).into())
1547}
1548
1549pub(crate) fn succ_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1550 let val = args
1551 .remove_left_or_key("Value")
1552 .ok_or_else(|| not_passed("Value"))?;
1553 let val = match &val {
1554 ValueObj::Bool(b) => ValueObj::Nat(*b as u64 + 1),
1555 ValueObj::Nat(n) => ValueObj::Nat(n + 1),
1556 ValueObj::Int(n) => ValueObj::Int(n + 1),
1557 ValueObj::Float(n) => ValueObj::from(**n + f64::EPSILON),
1558 v @ (ValueObj::Inf | ValueObj::NegInf) => v.clone(),
1559 _ => {
1560 return Err(type_mismatch("Number", val, "Value"));
1561 }
1562 };
1563 Ok(val.into())
1564}
1565
1566pub(crate) fn pred_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1567 let val = args
1568 .remove_left_or_key("Value")
1569 .ok_or_else(|| not_passed("Value"))?;
1570 let val = match &val {
1571 ValueObj::Bool(b) => ValueObj::Nat((*b as u64).saturating_sub(1)),
1572 ValueObj::Nat(n) => ValueObj::Nat(n.saturating_sub(1)),
1573 ValueObj::Int(n) => ValueObj::Int(n - 1),
1574 ValueObj::Float(n) => ValueObj::from(**n - f64::EPSILON),
1575 v @ (ValueObj::Inf | ValueObj::NegInf) => v.clone(),
1576 _ => {
1577 return Err(type_mismatch("Number", val, "Value"));
1578 }
1579 };
1580 Ok(val.into())
1581}
1582
1583pub(crate) fn zip_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1585 let iterable1 = args
1586 .remove_left_or_key("iterable1")
1587 .ok_or_else(|| not_passed("iterable1"))?;
1588 let iterable2 = args
1589 .remove_left_or_key("iterable2")
1590 .ok_or_else(|| not_passed("iterable2"))?;
1591 let iterable1 = match iterable1 {
1592 ValueObj::List(a) => a.to_vec(),
1593 ValueObj::Tuple(t) => t.to_vec(),
1594 ValueObj::Set(s) => s.into_iter().collect(),
1595 _ => {
1596 return Err(type_mismatch("Iterable(T)", iterable1, "iterable1"));
1597 }
1598 };
1599 let iterable2 = match iterable2 {
1600 ValueObj::List(a) => a.to_vec(),
1601 ValueObj::Tuple(t) => t.to_vec(),
1602 ValueObj::Set(s) => s.into_iter().collect(),
1603 _ => {
1604 return Err(type_mismatch("Iterable(T)", iterable2, "iterable2"));
1605 }
1606 };
1607 let mut zipped = vec![];
1608 for (v1, v2) in iterable1.into_iter().zip(iterable2.into_iter()) {
1609 zipped.push(ValueObj::Tuple(vec![v1, v2].into()));
1610 }
1611 Ok(TyParam::Value(ValueObj::List(zipped.into())))
1612}
1613
1614pub(crate) fn derefine_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
1620 let val = args
1621 .remove_left_or_key("T")
1622 .ok_or_else(|| not_passed("T"))?;
1623 let t = match ctx.convert_value_into_type(val) {
1624 Ok(t) => t.derefine(),
1625 Err(val) => {
1626 return Err(type_mismatch("Type", val, "T"));
1627 }
1628 };
1629 Ok(TyParam::t(t))
1630}
1631
1632pub(crate) fn fill_ord_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
1637 let val = args
1638 .remove_left_or_key("T")
1639 .ok_or_else(|| not_passed("T"))?;
1640 let t = match ctx.convert_value_into_type(val) {
1641 Ok(t) => {
1642 let coerced = ctx.coerce(t.clone(), &()).unwrap_or(t);
1643 let inf = ctx.inf(&coerced);
1644 let sup = ctx.sup(&coerced);
1645 let der = coerced.derefine();
1646 match (inf, sup) {
1647 (Some(inf), Some(sup)) => closed_range(der, inf, sup),
1648 _ => coerced,
1649 }
1650 }
1651 Err(val) => {
1652 return Err(type_mismatch("Type", val, "T"));
1653 }
1654 };
1655 Ok(TyParam::t(t))
1656}
1657
1658pub(crate) fn classof_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
1663 let val = args
1664 .remove_left_or_key("obj")
1665 .ok_or_else(|| not_passed("obj"))?;
1666 Ok(TyParam::t(val.class()))
1667}
1668
1669#[cfg(test)]
1670mod tests {
1671 use erg_common::config::ErgConfig;
1672
1673 use crate::module::SharedCompilerResource;
1674 use crate::ty::constructors::*;
1675
1676 use super::*;
1677
1678 #[test]
1679 fn test_dict_items() {
1680 let cfg = ErgConfig::default();
1681 let shared = SharedCompilerResource::default();
1682 Context::init_builtins(cfg, shared.clone());
1683 let ctx = &shared.raw_ref_builtins_ctx().unwrap().context;
1684
1685 let a = singleton(Type::Str, TyParam::value("a"));
1686 let b = singleton(Type::Str, TyParam::value("b"));
1687 let c = singleton(Type::Str, TyParam::value("c"));
1688 let k_union = ctx.union(&ctx.union(&c, &a), &b);
1690 let g_dic = singleton(Type::Type, TyParam::t(mono("GenericDict")));
1691 let g_lis = singleton(Type::Type, TyParam::t(mono("GenericList")));
1692 let sub = func0(singleton(Type::NoneType, TyParam::value(ValueObj::None)));
1693 let v_union = ctx.union(&ctx.union(&g_lis, &sub), &g_dic);
1694 let dic = dict! {
1695 a.clone() => sub.clone(),
1696 b.clone() => g_dic.clone(),
1697 c.clone() => g_lis.clone(),
1698 };
1699 match ctx.eval_proj_call_t(dic.clone().into(), "items".into(), vec![], 1, &()) {
1700 Ok(t) => {
1701 let items = tuple_t(vec![k_union, v_union]);
1702 assert_eq!(t, items, "{t} != {items}");
1703 }
1704 Err(e) => {
1705 panic!("ERR: {e}");
1706 }
1707 }
1708 }
1709}