fn assemble(&mut self, monad: &BitCodeMonad) -> Result<CellRef, RuntimeError> {
        // Append the initial bitcode
        self.append_bitcode(&monad.bitcode);

        // Work out the value depending on the content of the monad
        let result = match &monad.value {
            // Simple value
            BitCodeValue::Value(value)                      => Ok(value.clone()),

            // Allocates a new label
            BitCodeValue::AllocLabel                        => Err(RuntimeError::CannotAllocateLabelsDuringAssembly),

            // Looks up a label value (or prepares a second pass if the label has no value yet)
            BitCodeValue::LabelValue(value)                 => self.get_label_value(value),

            // Updates the value of a label, uses the value to map to the next monad
            BitCodeValue::SetLabelValue(label, value)       => self.set_label_value(label, value.clone()),

            // Map based on the current bit position
            BitCodeValue::BitPos                            => {
                let pos     = self.bit_pos;
                let offset  = self.bit_offset;

                if offset < 0 && (-offset as u64) > pos {
                    Err(RuntimeError::BeforeStartOfFile)
                } else {
                    let pos = (pos as i64) + offset;

                    Ok(SafasCell::Number(SafasNumber::BitNumber(64, pos as u128)).into())
                }
            },

            BitCodeValue::SetBitPos(value)                  => {
                // Value must be a number
                let value       = value.number_value().ok_or(RuntimeError::NotANumber(value.clone()))?;
                let value       = value.to_usize() as u64;

                // Update the offset
                let offset      = (value as i64) - (self.bit_pos as i64);

                self.bit_offset = offset;

                Ok(NIL.clone())
            },

            // Value is the result of applying the mapping function to the specified monad, and then trying again with the current monad
            BitCodeValue::FlatMap(monad, mappings)          => {
                // About to call assemble recursively: create a new set of changed labels
                let mut our_labels  = HashSet::new();
                mem::swap(&mut our_labels, &mut self.changed_labels);

                // Loop until the labels in the flat_mapped section acquire stable values
                let initial_bit_pos     = self.bit_pos;
                let initial_code_len    = self.bitcode.len();
                let mut passes          = 0;
                let mut value;
                loop {
                    // The initial value comes from the initial monad
                    value               = self.assemble(monad)?;

                    // Evaluate each mapping in turn
                    for mapping in mappings.iter() {
                        let next_monad  = mapping(value)?;
                        value           = self.assemble(&next_monad)?;
                    }

                    // If there are no changed labels, stop running passes
                    if self.changed_labels.len() == 0 { break; }

                    // Any labels changed here should be merged into our_labels
                    our_labels.extend(self.changed_labels.iter().cloned());

                    // Limit the number of passes we can perform
                    passes += 1;
                    if passes > self.max_passes {
                        return Err(RuntimeError::TooManyPasses(self.max_passes));
                    }

                    // Reset for the next pass
                    self.changed_labels = HashSet::new();
                    self.bit_pos        = initial_bit_pos;
                    self.bitcode.truncate(initial_code_len);
                }

                // Reset with the labels from this level of recursion
                mem::swap(&mut our_labels, &mut self.changed_labels);

                // Final value from the final monad
                Ok(value)
            }
        };

        // Append the following bitcode if there is any
        self.append_bitcode(&monad.following_bitcode);

        // Return the value we generated
        result
    }
///
/// Assembles a single monad using this assembler, returning the monad's value
///
Assembles a single monad using this assembler, returning the monad's value
Assembles a single monad using this assembler returning the monad ' s value
fn assemble(&mut self, monad: &BitCodeMonad) -> Result<CellRef, RuntimeError> {
        // Append the initial bitcode
        self.append_bitcode(&monad.bitcode);
        // Work out the value depending on the content of the monad
        let result = match &monad.value {
            // Simple value
            BitCodeValue::Value(value)                      => Ok(value.clone()),
            // Allocates a new label
            BitCodeValue::AllocLabel                        => Err(RuntimeError::CannotAllocateLabelsDuringAssembly),
            // Looks up a label value (or prepares a second pass if the label has no value yet)
            BitCodeValue::LabelValue(value)                 => self.get_label_value(value),
            // Updates the value of a label, uses the value to map to the next monad
            BitCodeValue::SetLabelValue(label, value)       => self.set_label_value(label, value.clone()),
            // Map based on the current bit position
            BitCodeValue::BitPos                            => {
                let pos     = self.bit_pos;
                let offset  = self.bit_offset;
                if offset < 0 && (-offset as u64) > pos {
                    Err(RuntimeError::BeforeStartOfFile)
                } else {
                    let pos = (pos as i64) + offset;
                    Ok(SafasCell::Number(SafasNumber::BitNumber(64, pos as u128)).into())
                }
            },
            BitCodeValue::SetBitPos(value)                  => {
                // Value must be a number
                let value       = value.number_value().ok_or(RuntimeError::NotANumber(value.clone()))?;
                let value       = value.to_usize() as u64;
                // Update the offset
                let offset      = (value as i64) - (self.bit_pos as i64);
                self.bit_offset = offset;
                Ok(NIL.clone())
            },
            // Value is the result of applying the mapping function to the specified monad, and then trying again with the current monad
            BitCodeValue::FlatMap(monad, mappings)          => {
                // About to call assemble recursively: create a new set of changed labels
                let mut our_labels  = HashSet::new();
                mem::swap(&mut our_labels, &mut self.changed_labels);
                // Loop until the labels in the flat_mapped section acquire stable values
                let initial_bit_pos     = self.bit_pos;
                let initial_code_len    = self.bitcode.len();
                let mut passes          = 0;
                let mut value;
                loop {
                    // The initial value comes from the initial monad
                    value               = self.assemble(monad)?;
                    // Evaluate each mapping in turn
                    for mapping in mappings.iter() {
                        let next_monad  = mapping(value)?;
                        value           = self.assemble(&next_monad)?;
                    }
                    // If there are no changed labels, stop running passes
                    if self.changed_labels.len() == 0 { break; }
                    // Any labels changed here should be merged into our_labels
                    our_labels.extend(self.changed_labels.iter().cloned());
                    // Limit the number of passes we can perform
                    passes += 1;
                    if passes > self.max_passes {
                        return Err(RuntimeError::TooManyPasses(self.max_passes));
                    }
                    // Reset for the next pass
                    self.changed_labels = HashSet::new();
                    self.bit_pos        = initial_bit_pos;
                    self.bitcode.truncate(initial_code_len);
                }
                // Reset with the labels from this level of recursion
                mem::swap(&mut our_labels, &mut self.changed_labels);
                // Final value from the final monad
                Ok(value)
            }
        };
        // Append the following bitcode if there is any
        self.append_bitcode(&monad.following_bitcode);
        // Return the value we generated
        result
    }
fn assemble ( & mut self , monad : & BitCodeMonad ) -> Result < CellRef , RuntimeError > { // Append the initial bitcode self . append_bitcode ( & monad . bitcode ) ; // Work out the value depending on the content of the monad let result = match & monad . value { // Simple value BitCodeValue :: Value ( value ) => Ok ( value . clone ( ) ) , // Allocates a new label BitCodeValue :: AllocLabel => Err ( RuntimeError :: CannotAllocateLabelsDuringAssembly ) , // Looks up a label value (or prepares a second pass if the label has no value yet) BitCodeValue :: LabelValue ( value ) => self . get_label_value ( value ) , // Updates the value of a label, uses the value to map to the next monad BitCodeValue :: SetLabelValue ( label , value ) => self . set_label_value ( label , value . clone ( ) ) , // Map based on the current bit position BitCodeValue :: BitPos => { let pos = self . bit_pos ; let offset = self . bit_offset ; if offset < 0 && ( - offset as u64 ) > pos { Err ( RuntimeError :: BeforeStartOfFile ) } else { let pos = ( pos as i64 ) + offset ; Ok ( SafasCell :: Number ( SafasNumber :: BitNumber ( 64 , pos as u128 ) ) . into ( ) ) } } , BitCodeValue :: SetBitPos ( value ) => { // Value must be a number let value = value . number_value ( ) . ok_or ( RuntimeError :: NotANumber ( value . clone ( ) ) ) ? ; let value = value . to_usize ( ) as u64 ; // Update the offset let offset = ( value as i64 ) - ( self . bit_pos as i64 ) ; self . bit_offset = offset ; Ok ( NIL . clone ( ) ) } , // Value is the result of applying the mapping function to the specified monad, and then trying again with the current monad BitCodeValue :: FlatMap ( monad , mappings ) => { // About to call assemble recursively: create a new set of changed labels let mut our_labels = HashSet :: new ( ) ; mem :: swap ( & mut our_labels , & mut self . changed_labels ) ; // Loop until the labels in the flat_mapped section acquire stable values let initial_bit_pos = self . bit_pos ; let initial_code_len = self . bitcode . len ( ) ; let mut passes = 0 ; let mut value ; loop { // The initial value comes from the initial monad value = self . assemble ( monad ) ? ; // Evaluate each mapping in turn for mapping in mappings . iter ( ) { let next_monad = mapping ( value ) ? ; value = self . assemble ( & next_monad ) ? ; } // If there are no changed labels, stop running passes if self . changed_labels . len ( ) == 0 { break ; } // Any labels changed here should be merged into our_labels our_labels . extend ( self . changed_labels . iter ( ) . cloned ( ) ) ; // Limit the number of passes we can perform passes += 1 ; if passes > self . max_passes { return Err ( RuntimeError :: TooManyPasses ( self . max_passes ) ) ; } // Reset for the next pass self . changed_labels = HashSet :: new ( ) ; self . bit_pos = initial_bit_pos ; self . bitcode . truncate ( initial_code_len ) ; } // Reset with the labels from this level of recursion mem :: swap ( & mut our_labels , & mut self . changed_labels ) ; // Final value from the final monad Ok ( value ) } } ; // Append the following bitcode if there is any self . append_bitcode ( & monad . following_bitcode ) ; // Return the value we generated result }
Assembles a single monad using this assembler, returning the monad's value
Assembles a single monad using this assembler returning the monad ' s value
&mut self
monad
&BitCodeMonad
&mut self
monad
&BitCodeMonad