difftreelog
refactor use stack for first object field add
in: master
1 file changed
crates/jrsonnet-evaluator/src/obj/mod.rsdiffbeforeafterboth231struct 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}475476476 #[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 core632 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 field640 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-safe644 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");648656649 values657 values650 .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)652653 // self.0.get_raw(key, this)654 }660 }655661656 pub fn get_or_bail(&self, key: IStr) -> Result<Val> {662 pub fn get_or_bail(&self, key: IStr) -> Result<Val> {