| 196 | } |
| 197 | |
| 198 | void Subexpression::Flatten() { |
| 199 | struct Record { |
| 200 | Subexpression* subexpr; |
| 201 | size_t offset; |
| 202 | }; |
| 203 | |
| 204 | if (IsFlattened()) { |
| 205 | return; |
| 206 | } |
| 207 | |
| 208 | std::vector<std::unique_ptr<const ExpressionStep>> flat; |
| 209 | |
| 210 | std::vector<Record> flatten_stack; |
| 211 | |
| 212 | flatten_stack.push_back({this, 0}); |
| 213 | while (!flatten_stack.empty()) { |
| 214 | Record top = flatten_stack.back(); |
| 215 | flatten_stack.pop_back(); |
| 216 | size_t offset = top.offset; |
| 217 | auto* subexpr = top.subexpr; |
| 218 | if (subexpr->IsFlattened()) { |
| 219 | auto& elements = subexpr->flattened_elements(); |
| 220 | absl::c_move(elements, std::back_inserter(flat)); |
| 221 | elements.clear(); |
| 222 | continue; |
| 223 | } else if (subexpr->IsRecursive()) { |
| 224 | flat.push_back(std::make_unique<WrappedDirectStep>( |
| 225 | std::move(subexpr->ExtractRecursiveProgram().step), |
| 226 | subexpr->self_->id())); |
| 227 | continue; |
| 228 | } |
| 229 | auto& elements = subexpr->elements(); |
| 230 | size_t size = elements.size(); |
| 231 | size_t i = offset; |
| 232 | for (; i < size; ++i) { |
| 233 | auto& element = elements[i]; |
| 234 | if (auto* child = absl::get_if<Subexpression*>(&element); |
| 235 | child != nullptr) { |
| 236 | // push resume then child so child elements are processed first. |
| 237 | flatten_stack.push_back({subexpr, i + 1}); |
| 238 | flatten_stack.push_back({*child, 0}); |
| 239 | break; |
| 240 | } else if (auto* step = |
| 241 | absl::get_if<std::unique_ptr<ExpressionStep>>(&element); |
| 242 | step != nullptr) { |
| 243 | flat.push_back(std::move(*step)); |
| 244 | } else { |
| 245 | ABSL_UNREACHABLE(); |
| 246 | } |
| 247 | } |
| 248 | if (i == size) { |
| 249 | elements.clear(); |
| 250 | } |
| 251 | } |
| 252 | program_ = std::move(flat); |
| 253 | } |
| 254 | |
| 255 | Subexpression::RecursiveProgram Subexpression::ExtractRecursiveProgram() { |