/* * 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 #include #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