git.delta.rocks / jrsonnet / refs/commits / bb0b90247386

difftreelog

refactor use stack for first object field add

kypurvtmYaroslav Bolyukin2026-03-23parent: #258e351.patch.diff
in: master

1 file changed

modifiedcrates/jrsonnet-evaluator/src/obj/mod.rsdiffbeforeafterboth
231struct ObjValueInner {231struct ObjValueInner {
232 cores: Vec<CcObjectCore>,232 cores: Vec<CcObjectCore>,
233 assertions_ran: Cell<bool>,233 assertions_ran: Cell<bool>,
234 #[trace(skip)]
234 has_assertions: bool,235 has_assertions: bool,
235 value_cache: RefCell<FxHashMap<(IStr, CoreIdx), CacheValue>>,236 value_cache: RefCell<FxHashMap<(IStr, CoreIdx), CacheValue>>,
236}237}
475476
476 #[must_use]477 #[must_use]
477 pub fn extend_from(&self, sup: Self) -> Self {478 pub fn extend_from(&self, sup: Self) -> Self {
478 let mut cores = sup.0.cores.clone();479 let mut cores = Vec::with_capacity(sup.0.cores.len() + self.0.cores.len());
480 cores.extend(sup.0.cores.iter().cloned());
479 cores.extend(self.0.cores.iter().cloned());481 cores.extend(self.0.cores.iter().cloned());
480 let has_assertions = sup.0.has_assertions || self.0.has_assertions;482 let has_assertions = sup.0.has_assertions || self.0.has_assertions;
481 ObjValue(Cc::new(ObjValueInner {483 ObjValue(Cc::new(ObjValueInner {
603 }605 }
604 fn get_idx_uncached(&self, key: IStr, core: CoreIdx) -> Result<Option<Val>> {606 fn get_idx_uncached(&self, key: IStr, core: CoreIdx) -> Result<Option<Val>> {
605 self.run_assertions()?;607 self.run_assertions()?;
608 let mut first_add = None;
606 let mut add_stack = Vec::with_capacity(2);609 let mut add_stack: Vec<Val> = Vec::new();
607 let mut skip = Saturating(0);610 let mut skip = Saturating(0);
608 for (sup, core) in self.0.cores[..core.idx].iter().enumerate().rev() {611 for (sup, core) in self.0.cores[..core.idx].iter().enumerate().rev() {
609 let sup_this = SupThis {612 let sup_this = SupThis {
610 sup: CoreIdx { idx: sup },613 sup: CoreIdx { idx: sup },
611 this: self.clone(),614 this: self.clone(),
612 };615 };
613 match core.0.get_for_core(key.clone(), sup_this, skip.0 != 0)? {616 match core.0.get_for_core(key.clone(), sup_this, skip.0 != 0)? {
614 GetFor::Final(val) if add_stack.is_empty() => {617 GetFor::Final(val) if first_add.is_none() => {
615 if skip.0 == 0 {618 if skip.0 == 0 {
616 return Ok(Some(val));619 return Ok(Some(val));
617 }620 }
624 }627 }
625 GetFor::SuperPlus(val) => {628 GetFor::SuperPlus(val) => {
626 if skip.0 == 0 {629 if skip.0 == 0 {
630 if first_add.is_none() {
631 first_add = Some(val);
632 } else {
627 add_stack.push(val);633 add_stack.push(val);
628 }634 }
635 }
629 }636 }
630 GetFor::Omit(new_skip) => {637 GetFor::Omit(new_skip) => {
631 // +1 including this core
632 skip = skip.max(new_skip + Saturating(1));638 skip = skip.max(new_skip + Saturating(1));
633 }639 }
634 GetFor::NotFound => {}640 GetFor::NotFound => {}
635 }641 }
636 skip -= 1;642 skip -= 1;
637 }643 }
644 let Some(first) = first_add else {
638 if add_stack.is_empty() {645 if add_stack.is_empty() {
639 // None of layers had this field
640 return Ok(None);646 return Ok(None);
641 } else if add_stack.len() == 1 {647 }
642 // A layer had this field, but it wanted this field to be added with super.
643 // However, no super had this field, fail-safe
644 return Ok(Some(add_stack.pop().expect("single element on stack")));648 return Ok(Some(add_stack.pop().expect("single element on stack")));
645 }649 };
650 if add_stack.is_empty() {
651 return Ok(Some(first));
652 }
653 add_stack.insert(0, first);
646 let mut values = add_stack.into_iter().rev();654 let mut values = add_stack.into_iter().rev();
647 let init = values.next().expect("at least 2 elements");655 let init = values.next().expect("at least 2 elements");
648656
649 values657 values
650 .try_fold(init, |a, b| evaluate_add_op(&a, &b))658 .try_fold(init, |a, b| evaluate_add_op(&a, &b))
651 .map(Some)659 .map(Some)
652
653 // self.0.get_raw(key, this)
654 }660 }
655661
656 pub fn get_or_bail(&self, key: IStr) -> Result<Val> {662 pub fn get_or_bail(&self, key: IStr) -> Result<Val> {