pub fn expand_aliased_string_literals_if_appropriate<F>(
        &mut self,
        target_path: &Rc<Path>,
        value: &Rc<AbstractValue>,
        str_val: &str,
        update: F,
    ) where
        F: Fn(&mut Self, Rc<Path>, Rc<AbstractValue>, Rc<AbstractValue>),
    {
        let collection_path = Path::new_computed(value.clone());
        // Create index elements
        for (i, ch) in str_val.as_bytes().iter().enumerate() {
            let index = Rc::new((i as u128).into());
            let ch_const: Rc<AbstractValue> = Rc::new((*ch as u128).into());
            let path = Path::new_index(collection_path.clone(), index);
            update(self, path, ch_const.clone(), ch_const);
        }
        // Arrays have a length field
        let length_val: Rc<AbstractValue> = Rc::new((str_val.len() as u128).into());
        let str_length_path = Path::new_length(collection_path);
        update(
            self,
            str_length_path,
            length_val.clone(),
            length_val.clone(),
        );
        // The target path is a fat pointer, initialize it.
        let thin_pointer_path = Path::new_field(target_path.clone(), 0);
        let thin_pointer_to_str = AbstractValue::make_reference(Path::get_as_path(value.clone()));
        update(
            self,
            thin_pointer_path,
            thin_pointer_to_str.clone(),
            thin_pointer_to_str,
        );
        let slice_length_path = Path::new_length(target_path.clone());
        update(self, slice_length_path, length_val.clone(), length_val);
    }
// Most of the time, references to string values are just moved around from one memory location
// to another and sometimes their lengths are taken. For such things there is no need to track
// the value of each character as a separate (path, char) tuple in the environment. That just
// slows things down and makes debugging more of chore.
// As soon as a string value manages to flow into a variable of type &[u8], however, we can
// expect expressions that look up individual characters and so we must enhance the current
// environment with (path, char) tuples. The root of the path part of such a tuple is the
// string literal itself, not the variable, which holds a pointer to the string.
Most of the time, references to string values are just moved around from one memory location
to another and sometimes their lengths are taken. For such things there is no need to track
the value of each character as a separate (path, char) tuple in the environment. That just
slows things down and makes debugging more of chore.
As soon as a string value manages to flow into a variable of type &[u8], however, we can
expect expressions that look up individual characters and so we must enhance the current
environment with (path, char) tuples. The root of the path part of such a tuple is the
string literal itself, not the variable, which holds a pointer to the string.
Most of the time references to string values are just moved around from one memory location to another and sometimes their lengths are taken . For such things there is no need to track the value of each character as a separate ( path char ) tuple in the environment . That just slows things down and makes debugging more of chore . As soon as a string value manages to flow into a variable of type & [ u8 ] however we can expect expressions that look up individual characters and so we must enhance the current environment with ( path char ) tuples . The root of the path part of such a tuple is the string literal itself not the variable which holds a pointer to the string .
pub fn expand_aliased_string_literals_if_appropriate<F>(
        &mut self,
        target_path: &Rc<Path>,
        value: &Rc<AbstractValue>,
        str_val: &str,
        update: F,
    ) where
        F: Fn(&mut Self, Rc<Path>, Rc<AbstractValue>, Rc<AbstractValue>),
    {
        let collection_path = Path::new_computed(value.clone());
        // Create index elements
        for (i, ch) in str_val.as_bytes().iter().enumerate() {
            let index = Rc::new((i as u128).into());
            let ch_const: Rc<AbstractValue> = Rc::new((*ch as u128).into());
            let path = Path::new_index(collection_path.clone(), index);
            update(self, path, ch_const.clone(), ch_const);
        }
        // Arrays have a length field
        let length_val: Rc<AbstractValue> = Rc::new((str_val.len() as u128).into());
        let str_length_path = Path::new_length(collection_path);
        update(
            self,
            str_length_path,
            length_val.clone(),
            length_val.clone(),
        );
        // The target path is a fat pointer, initialize it.
        let thin_pointer_path = Path::new_field(target_path.clone(), 0);
        let thin_pointer_to_str = AbstractValue::make_reference(Path::get_as_path(value.clone()));
        update(
            self,
            thin_pointer_path,
            thin_pointer_to_str.clone(),
            thin_pointer_to_str,
        );
        let slice_length_path = Path::new_length(target_path.clone());
        update(self, slice_length_path, length_val.clone(), length_val);
    }
pub fn expand_aliased_string_literals_if_appropriate < F > ( & mut self , target_path : & Rc < Path > , value : & Rc < AbstractValue > , str_val : & str , update : F , ) where F : Fn ( & mut Self , Rc < Path > , Rc < AbstractValue > , Rc < AbstractValue > ) , { let collection_path = Path :: new_computed ( value . clone ( ) ) ; // Create index elements for ( i , ch ) in str_val . as_bytes ( ) . iter ( ) . enumerate ( ) { let index = Rc :: new ( ( i as u128 ) . into ( ) ) ; let ch_const : Rc < AbstractValue > = Rc :: new ( ( * ch as u128 ) . into ( ) ) ; let path = Path :: new_index ( collection_path . clone ( ) , index ) ; update ( self , path , ch_const . clone ( ) , ch_const ) ; } // Arrays have a length field let length_val : Rc < AbstractValue > = Rc :: new ( ( str_val . len ( ) as u128 ) . into ( ) ) ; let str_length_path = Path :: new_length ( collection_path ) ; update ( self , str_length_path , length_val . clone ( ) , length_val . clone ( ) , ) ; // The target path is a fat pointer, initialize it. let thin_pointer_path = Path :: new_field ( target_path . clone ( ) , 0 ) ; let thin_pointer_to_str = AbstractValue :: make_reference ( Path :: get_as_path ( value . clone ( ) ) ) ; update ( self , thin_pointer_path , thin_pointer_to_str . clone ( ) , thin_pointer_to_str , ) ; let slice_length_path = Path :: new_length ( target_path . clone ( ) ) ; update ( self , slice_length_path , length_val . clone ( ) , length_val ) ; }
Most of the time, references to string values are just moved around from one memory location
to another and sometimes their lengths are taken.
Most of the time references to string values are just moved around from one memory location to another and sometimes their lengths are taken .
&mut self
target_path
&Rc<Path>
value
&Rc<AbstractValue>
str_val
&str
update
F
&mut self
target_path
&Rc<Path>
value
&Rc<AbstractValue>
str_val
&str
update
F