pub fn inline_expressions(&mut self) {
        // Local copy of input_arity to avoid borrowing `self` in closures.
        let input_arity = self.input_arity;
        // Reference counts track the number of places that a reference occurs.
        let mut reference_count = vec![0; input_arity + self.expressions.len()];
        // Increment reference counts for each use
        for expr in self.expressions.iter() {
            for col in expr.support().into_iter() {
                reference_count[col] += 1;
            }
        }
        for (_, pred) in self.predicates.iter() {
            for col in pred.support().into_iter() {
                reference_count[col] += 1;
            }
        }
        for proj in self.projection.iter() {
            reference_count[*proj] += 1;
        }

        // Determine which expressions should be inlined because they reference temporal expressions.
        let mut is_temporal = vec![false; input_arity];
        for expr in self.expressions.iter() {
            // An express may contain a temporal expression, or reference a column containing such.
            is_temporal.push(
                expr.contains_temporal() || expr.support().into_iter().any(|col| is_temporal[col]),
            );
        }

        // Inline only those columns that 1. are expressions not inputs, and
        // 2a. are column references or literals or 2b. have a refcount of 1,
        // or 2c. reference temporal expressions (which cannot be evaluated).
        let mut should_inline = vec![false; reference_count.len()];
        for i in (input_arity..reference_count.len()).rev() {
            if let MirScalarExpr::Column(c) = self.expressions[i - input_arity] {
                should_inline[i] = true;
                // The reference count of the referenced column should be
                // incremented with the number of references
                // `self.expressions[i - input_arity]` has.
                // Subtract 1 because `self.expressions[i - input_arity]` is
                // itself a reference.
                reference_count[c] += reference_count[i] - 1;
            } else {
                should_inline[i] = reference_count[i] == 1 || is_temporal[i];
            }
        }
        // Inline expressions per `should_inline`.
        for index in 0..self.expressions.len() {
            let (prior, expr) = self.expressions.split_at_mut(index);
            expr[0].visit_mut_post(&mut |e| {
                if let MirScalarExpr::Column(i) = e {
                    if should_inline[*i] {
                        *e = prior[*i - input_arity].clone();
                    }
                }
            });
        }
        for (_index, pred) in self.predicates.iter_mut() {
            let expressions = &self.expressions;
            pred.visit_mut_post(&mut |e| {
                if let MirScalarExpr::Column(i) = e {
                    if should_inline[*i] {
                        *e = expressions[*i - input_arity].clone();
                    }
                }
            });
        }
        // We can only inline column references in `self.projection`, but we should.
        for proj in self.projection.iter_mut() {
            if *proj >= self.input_arity {
                if let MirScalarExpr::Column(i) = self.expressions[*proj - self.input_arity] {
                    *proj = i;
                }
            }
        }
    }
/// This method inlines expressions with a single use.
///
/// This method only inlines expressions; it does not delete expressions
/// that are no longer referenced. The `remove_undemanded()` method does
/// that, and should likely be used after this method.
///
/// Inlining replaces column references when the refered-to item is either
/// another column reference, or the only referrer of its referent. This
/// is most common after memoization has atomized all expressions to seek
/// out re-use: inlining re-assembles expressions that were not helpfully
/// shared with other expressions.
///
/// # Example
///
/// In this example, we see that with only a single reference to columns
/// 0 and 2, their parsing can each be inlined. Similarly, column references
/// can be cleaned up among expressions, and in the final projection.
///
/// Also notice the remaining expressions, which can be cleaned up in a later
/// pass (the `remove_undemanded` method).
///
/// ```rust
/// use expr::{func, MapFilterProject, MirScalarExpr, UnaryFunc, BinaryFunc};
/// // Use the output from first `memoize_expression` example.
/// let mut map_filter_project = MapFilterProject::new(5)
///     .map(vec![
///         MirScalarExpr::column(0).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
///         MirScalarExpr::column(1).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
///         MirScalarExpr::column(5).call_binary(MirScalarExpr::column(6), BinaryFunc::AddInt64),
///         MirScalarExpr::column(7),
///         MirScalarExpr::column(2).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
///         MirScalarExpr::column(6).call_binary(MirScalarExpr::column(9), BinaryFunc::AddInt64),
///         MirScalarExpr::column(10),
///     ])
///     .project(vec![3,4,8,11]);
///
/// let mut expected_optimized = MapFilterProject::new(5)
///     .map(vec![
///         MirScalarExpr::column(0).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
///         MirScalarExpr::column(1).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
///         MirScalarExpr::column(0).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)).call_binary(MirScalarExpr::column(6), BinaryFunc::AddInt64),
///         MirScalarExpr::column(0).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)).call_binary(MirScalarExpr::column(6), BinaryFunc::AddInt64),
///         MirScalarExpr::column(2).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
///         MirScalarExpr::column(6).call_binary(MirScalarExpr::column(2).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)), BinaryFunc::AddInt64),
///         MirScalarExpr::column(6).call_binary(MirScalarExpr::column(2).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)), BinaryFunc::AddInt64),
///     ])
///     .project(vec![3,4,8,11]);
///
/// // Inline expressions that are referenced only once.
/// map_filter_project.inline_expressions();
///
/// assert_eq!(
///     map_filter_project,
///     expected_optimized,
/// );
/// ```
This method inlines expressions with a single use.
This method only inlines expressions; it does not delete expressions
that are no longer referenced. The `remove_undemanded()` method does
that, and should likely be used after this method.

Inlining replaces column references when the refered-to item is either
another column reference, or the only referrer of its referent. This
is most common after memoization has atomized all expressions to seek
out re-use: inlining re-assembles expressions that were not helpfully
shared with other expressions.
This method inlines expressions with a single use . This method only inlines expressions ; it does not delete expressions that are no longer referenced . The ` remove_undemanded () ` method does that and should likely be used after this method . Inlining replaces column references when the refered - to item is either another column reference or the only referrer of its referent . This is most common after memoization has atomized all expressions to seek out re - use : inlining re - assembles expressions that were not helpfully shared with other expressions .
pub fn inline_expressions(&mut self) {
        // Local copy of input_arity to avoid borrowing `self` in closures.
        let input_arity = self.input_arity;
        // Reference counts track the number of places that a reference occurs.
        let mut reference_count = vec![0; input_arity + self.expressions.len()];
        // Increment reference counts for each use
        for expr in self.expressions.iter() {
            for col in expr.support().into_iter() {
                reference_count[col] += 1;
            }
        }
        for (_, pred) in self.predicates.iter() {
            for col in pred.support().into_iter() {
                reference_count[col] += 1;
            }
        }
        for proj in self.projection.iter() {
            reference_count[*proj] += 1;
        }
        // Determine which expressions should be inlined because they reference temporal expressions.
        let mut is_temporal = vec![false; input_arity];
        for expr in self.expressions.iter() {
            // An express may contain a temporal expression, or reference a column containing such.
            is_temporal.push(
                expr.contains_temporal() || expr.support().into_iter().any(|col| is_temporal[col]),
            );
        }
        // Inline only those columns that 1. are expressions not inputs, and
        // 2a. are column references or literals or 2b. have a refcount of 1,
        // or 2c. reference temporal expressions (which cannot be evaluated).
        let mut should_inline = vec![false; reference_count.len()];
        for i in (input_arity..reference_count.len()).rev() {
            if let MirScalarExpr::Column(c) = self.expressions[i - input_arity] {
                should_inline[i] = true;
                // The reference count of the referenced column should be
                // incremented with the number of references
                // `self.expressions[i - input_arity]` has.
                // Subtract 1 because `self.expressions[i - input_arity]` is
                // itself a reference.
                reference_count[c] += reference_count[i] - 1;
            } else {
                should_inline[i] = reference_count[i] == 1 || is_temporal[i];
            }
        }
        // Inline expressions per `should_inline`.
        for index in 0..self.expressions.len() {
            let (prior, expr) = self.expressions.split_at_mut(index);
            expr[0].visit_mut_post(&mut |e| {
                if let MirScalarExpr::Column(i) = e {
                    if should_inline[*i] {
                        *e = prior[*i - input_arity].clone();
                    }
                }
            });
        }
        for (_index, pred) in self.predicates.iter_mut() {
            let expressions = &self.expressions;
            pred.visit_mut_post(&mut |e| {
                if let MirScalarExpr::Column(i) = e {
                    if should_inline[*i] {
                        *e = expressions[*i - input_arity].clone();
                    }
                }
            });
        }
        // We can only inline column references in `self.projection`, but we should.
        for proj in self.projection.iter_mut() {
            if *proj >= self.input_arity {
                if let MirScalarExpr::Column(i) = self.expressions[*proj - self.input_arity] {
                    *proj = i;
                }
            }
        }
    }
pub fn inline_expressions ( & mut self ) { // Local copy of input_arity to avoid borrowing `self` in closures. let input_arity = self . input_arity ; // Reference counts track the number of places that a reference occurs. let mut reference_count = vec ! [ 0 input_arity self expressions len ( ) ] ; // Increment reference counts for each use for expr in self . expressions . iter ( ) { for col in expr . support ( ) . into_iter ( ) { reference_count [ col ] += 1 ; } } for ( _ , pred ) in self . predicates . iter ( ) { for col in pred . support ( ) . into_iter ( ) { reference_count [ col ] += 1 ; } } for proj in self . projection . iter ( ) { reference_count [ * proj ] += 1 ; } // Determine which expressions should be inlined because they reference temporal expressions. let mut is_temporal = vec ! [ false input_arity ] ; for expr in self . expressions . iter ( ) { // An express may contain a temporal expression, or reference a column containing such. is_temporal . push ( expr . contains_temporal ( ) || expr . support ( ) . into_iter ( ) . any ( | col | is_temporal [ col ] ) , ) ; } // Inline only those columns that 1. are expressions not inputs, and // 2a. are column references or literals or 2b. have a refcount of 1, // or 2c. reference temporal expressions (which cannot be evaluated). let mut should_inline = vec ! [ false reference_count len ( ) ] ; for i in ( input_arity .. reference_count . len ( ) ) . rev ( ) { if let MirScalarExpr :: Column ( c ) = self . expressions [ i - input_arity ] { should_inline [ i ] = true ; // The reference count of the referenced column should be // incremented with the number of references // `self.expressions[i - input_arity]` has. // Subtract 1 because `self.expressions[i - input_arity]` is // itself a reference. reference_count [ c ] += reference_count [ i ] - 1 ; } else { should_inline [ i ] = reference_count [ i ] == 1 || is_temporal [ i ] ; } } // Inline expressions per `should_inline`. for index in 0 .. self . expressions . len ( ) { let ( prior , expr ) = self . expressions . split_at_mut ( index ) ; expr [ 0 ] . visit_mut_post ( & mut | e | { if let MirScalarExpr :: Column ( i ) = e { if should_inline [ * i ] { * e = prior [ * i - input_arity ] . clone ( ) ; } } } ) ; } for ( _index , pred ) in self . predicates . iter_mut ( ) { let expressions = & self . expressions ; pred . visit_mut_post ( & mut | e | { if let MirScalarExpr :: Column ( i ) = e { if should_inline [ * i ] { * e = expressions [ * i - input_arity ] . clone ( ) ; } } } ) ; } // We can only inline column references in `self.projection`, but we should. for proj in self . projection . iter_mut ( ) { if * proj >= self . input_arity { if let MirScalarExpr :: Column ( i ) = self . expressions [ * proj - self . input_arity ] { * proj = i ; } } } }
This method inlines expressions with a single use.
This method inlines expressions with a single use .
&mut self
&mut self
example
In this example, we see that with only a single reference to columns
0 and 2, their parsing can each be inlined. Similarly, column references
can be cleaned up among expressions, and in the final projection.

Also notice the remaining expressions, which can be cleaned up in a later
pass (the `remove_undemanded` method).

```rust
use expr::{func, MapFilterProject, MirScalarExpr, UnaryFunc, BinaryFunc};
Use the output from first `memoize_expression` example.
let mut map_filter_project = MapFilterProject::new(5)
.map(vec![
MirScalarExpr::column(0).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
MirScalarExpr::column(1).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
MirScalarExpr::column(5).call_binary(MirScalarExpr::column(6), BinaryFunc::AddInt64),
MirScalarExpr::column(7),
MirScalarExpr::column(2).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
MirScalarExpr::column(6).call_binary(MirScalarExpr::column(9), BinaryFunc::AddInt64),
MirScalarExpr::column(10),
])
.project(vec![3,4,8,11]).

let mut expected_optimized = MapFilterProject::new(5)
.map(vec![
MirScalarExpr::column(0).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
MirScalarExpr::column(1).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
MirScalarExpr::column(0).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)).call_binary(MirScalarExpr::column(6), BinaryFunc::AddInt64),
MirScalarExpr::column(0).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)).call_binary(MirScalarExpr::column(6), BinaryFunc::AddInt64),
MirScalarExpr::column(2).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)),
MirScalarExpr::column(6).call_binary(MirScalarExpr::column(2).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)), BinaryFunc::AddInt64),
MirScalarExpr::column(6).call_binary(MirScalarExpr::column(2).call_unary(UnaryFunc::CastStringToInt64(func::CastStringToInt64)), BinaryFunc::AddInt64),
])
.project(vec![3,4,8,11]).

Inline expressions that are referenced only once.


In this example we see that with only a single reference to columns 0 and 2 their parsing can each be inlined . Similarly column references can be cleaned up among expressions and in the final projection . Also notice the remaining expressions which can be cleaned up in a later pass ( the ` remove_undemanded ` method ) . ` ` ` rust use expr :: { func MapFilterProject MirScalarExpr UnaryFunc BinaryFunc } ; Use the output from first ` memoize_expression ` example . let mut map_filter_project = MapFilterProject :: new ( 5 ) . map ( vec! [ MirScalarExpr :: column ( 0 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) MirScalarExpr :: column ( 1 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) MirScalarExpr :: column ( 5 ) . call_binary ( MirScalarExpr :: column ( 6 ) BinaryFunc :: AddInt64 ) MirScalarExpr :: column ( 7 ) MirScalarExpr :: column ( 2 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) MirScalarExpr :: column ( 6 ) . call_binary ( MirScalarExpr :: column ( 9 ) BinaryFunc :: AddInt64 ) MirScalarExpr :: column ( 10 ) ] ) . project ( vec! [ 3 4 8 11 ] ) . let mut expected_optimized = MapFilterProject :: new ( 5 ) . map ( vec! [ MirScalarExpr :: column ( 0 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) MirScalarExpr :: column ( 1 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) MirScalarExpr :: column ( 0 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) . call_binary ( MirScalarExpr :: column ( 6 ) BinaryFunc :: AddInt64 ) MirScalarExpr :: column ( 0 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) . call_binary ( MirScalarExpr :: column ( 6 ) BinaryFunc :: AddInt64 ) MirScalarExpr :: column ( 2 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) MirScalarExpr :: column ( 6 ) . call_binary ( MirScalarExpr :: column ( 2 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) BinaryFunc :: AddInt64 ) MirScalarExpr :: column ( 6 ) . call_binary ( MirScalarExpr :: column ( 2 ) . call_unary ( UnaryFunc :: CastStringToInt64 ( func :: CastStringToInt64 )) BinaryFunc :: AddInt64 ) ] ) . project ( vec! [ 3 4 8 11 ] ) . Inline expressions that are referenced only once .