MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / insert_expression

Method insert_expression

src/transform/src/cse/anf.rs:129–313  ·  view source on GitHub ↗

Ensures `self` contains bindings for all of `relation`'s subexpressions, including itself, and replaces `relation` with a reference to its corresponding identifier. The algorithm performs a post-order traversal of the expression tree, binding each distinct expression to a new local identifier and replacing each expression with a reference to the identifier for the expression. It maintains the inv

(
        &mut self,
        id_gen: &mut IdGen,
        relation: &mut MirRelationExpr,
    )

Source from the content-addressed store, hash-verified

127 /// can break if `body` acquires a reference to an arranged term, as that arrangement is not
128 /// available outside the loop).
129 fn insert_expression(
130 &mut self,
131 id_gen: &mut IdGen,
132 relation: &mut MirRelationExpr,
133 ) -> Result<(), crate::TransformError> {
134 self.checked_recur_mut(|this| {
135 match relation {
136 MirRelationExpr::LetRec {
137 ids,
138 values,
139 body,
140 limits,
141 } => {
142 // Used for `zip_eq`.
143 use itertools::Itertools;
144
145 // Introduce a new copy of `self`, which will be specific to this scope.
146 // This makes expressions used in the outer scope available for re-use.
147 // We will discard `scoped_anf` once we have processed the `LetRec`.
148 let mut scoped_anf = this.clone();
149
150 // Used to distinguish new bindings from old bindings.
151 // This is needed to extract from `scoped_anf` only the bindings added
152 // in this block, and not those inherited from `self`.
153 let id_boundary = id_gen.allocate_id();
154
155 // Each identifier in `ids` will be given *two* new identifiers,
156 // initially one "before" and then once bound another one "after".
157 // The two identifiers are important to distinguish references to the
158 // binding "before" it is refreshed, and "after" it is refreshed.
159 // We can equate two "before" references and two "after" references,
160 // but we must not equate a "before" and an "after" reference.
161
162 // For each bound identifier from `ids`, a temporary identifier for the "before" version.
163 let before_ids = ids
164 .iter()
165 .map(|_id| LocalId::new(id_gen.allocate_id()))
166 .collect::<Vec<_>>();
167 let mut after_ids = Vec::new();
168
169 // Install the "before" rebindings to start.
170 // These rebindings will be used for each binding until we process the binding.
171 scoped_anf
172 .rebindings
173 .extend(ids.iter().zip_eq(before_ids.iter()).map(|(x, y)| (*x, *y)));
174
175 // Convert each bound expression into a sequence of let bindings, which are appended
176 // to the sequence of let bindings from prior bound expressions.
177 // After visiting the expression, we'll update the binding for the `id` to its "after"
178 // identifier.
179 for (index, value) in values.iter_mut().enumerate() {
180 scoped_anf.insert_expression(id_gen, value)?;
181 // Update the binding for `ids[index]` from its "before" id to a new "after" id.
182 let new_id = id_gen.allocate_id();
183 after_ids.push(new_id);
184 scoped_anf
185 .rebindings
186 .insert(ids[index].clone(), LocalId::new(new_id));

Callers 1

Calls 15

checked_recur_mutMethod · 0.80
enumerateMethod · 0.80
populate_expressionMethod · 0.80
sortMethod · 0.80
contains_keyMethod · 0.80
take_dangerousMethod · 0.80
cloneMethod · 0.45
allocate_idMethod · 0.45
mapMethod · 0.45
iterMethod · 0.45
extendMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected