| /* |
| * Copyright 2016 WebAssembly Community Group participants |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "wabt/binding-hash.h" |
| |
| #include <algorithm> |
| #include <vector> |
| |
| #include "wabt/ir.h" |
| |
| namespace wabt { |
| |
| void BindingHash::FindDuplicates(DuplicateCallback callback) const { |
| if (size() > 0) { |
| ValueTypeVector duplicates; |
| CreateDuplicatesVector(&duplicates); |
| SortDuplicatesVectorByLocation(&duplicates); |
| CallCallbacks(duplicates, callback); |
| } |
| } |
| |
| Index BindingHash::FindIndex(const Var& var) const { |
| if (var.is_name()) { |
| return FindIndex(var.name()); |
| } |
| return var.index(); |
| } |
| |
| void BindingHash::CreateDuplicatesVector( |
| ValueTypeVector* out_duplicates) const { |
| // This relies on the fact that in an unordered_multimap, all values with the |
| // same key are adjacent in iteration order. |
| auto first = begin(); |
| bool is_first = true; |
| for (auto iter = std::next(first); iter != end(); ++iter) { |
| if (first->first == iter->first) { |
| if (is_first) { |
| out_duplicates->push_back(&*first); |
| } |
| out_duplicates->push_back(&*iter); |
| is_first = false; |
| } else { |
| is_first = true; |
| first = iter; |
| } |
| } |
| } |
| |
| void BindingHash::SortDuplicatesVectorByLocation( |
| ValueTypeVector* duplicates) const { |
| std::sort( |
| duplicates->begin(), duplicates->end(), |
| [](const value_type* lhs, const value_type* rhs) -> bool { |
| return lhs->second.loc.line < rhs->second.loc.line || |
| (lhs->second.loc.line == rhs->second.loc.line && |
| lhs->second.loc.first_column < rhs->second.loc.first_column); |
| }); |
| } |
| |
| void BindingHash::CallCallbacks(const ValueTypeVector& duplicates, |
| DuplicateCallback callback) const { |
| // Loop through all duplicates in order, and call callback with first |
| // occurrence. |
| for (auto iter = duplicates.begin(), end = duplicates.end(); iter != end; |
| ++iter) { |
| auto first = std::find_if(duplicates.begin(), duplicates.end(), |
| [iter](const value_type* x) -> bool { |
| return x->first == (*iter)->first; |
| }); |
| if (first == iter) { |
| continue; |
| } |
| assert(first != duplicates.end()); |
| callback(**first, **iter); |
| } |
| } |
| |
| } // namespace wabt |