| /* |
| Copyright 2019 Alain Dargelas |
| |
| 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. |
| */ |
| |
| /* |
| * File: LoopCheck.cpp |
| * Author: alain |
| * |
| * Created on May 2, 2017, 8:14 PM |
| */ |
| |
| #include <queue> |
| #include <set> |
| #include "SourceCompile/SymbolTable.h" |
| #include "SourceCompile/LoopCheck.h" |
| |
| using namespace SURELOG; |
| |
| LoopCheck::LoopCheck() {} |
| |
| LoopCheck::LoopCheck(const LoopCheck& orig) {} |
| |
| LoopCheck::~LoopCheck() { |
| for (auto itr : m_nodes) { |
| delete itr.second; |
| } |
| } |
| |
| void LoopCheck::clear() { |
| for (auto itr : m_nodes) { |
| delete itr.second; |
| } |
| m_nodes.clear(); |
| } |
| |
| bool LoopCheck::addEdge(SymbolId from, SymbolId to) { |
| // Create Graph |
| std::map<SymbolId, Node*>::iterator fromIt = m_nodes.find(from); |
| std::map<SymbolId, Node*>::iterator toIt = m_nodes.find(to); |
| Node* nodeFrom = NULL; |
| Node* nodeTo = NULL; |
| if (fromIt == m_nodes.end()) { |
| nodeFrom = new Node(from); |
| m_nodes.insert(std::make_pair(from, nodeFrom)); |
| } else { |
| nodeFrom = (*fromIt).second; |
| } |
| if (toIt == m_nodes.end()) { |
| nodeTo = new Node(to); |
| m_nodes.insert(std::make_pair(to, nodeTo)); |
| } else { |
| nodeTo = (*toIt).second; |
| } |
| nodeFrom->m_toList.insert(nodeTo); |
| |
| for (auto itr : m_nodes) { |
| itr.second->m_visited = false; |
| } |
| |
| // BFS |
| std::queue<Node*> queue; |
| queue.push(nodeTo); |
| nodeTo->m_visited = true; |
| while (!queue.empty()) { |
| Node* tmp = queue.front(); |
| queue.pop(); |
| tmp->m_visited = true; |
| for (auto next : tmp->m_toList) { |
| if (next->m_visited) |
| return true; |
| else { |
| queue.push(next); |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| std::vector<SymbolId> LoopCheck::reportLoop() { |
| std::vector<SymbolId> loop; |
| for (auto itr : m_nodes) { |
| if (itr.second->m_visited) { |
| loop.push_back(itr.first); |
| } |
| } |
| return loop; |
| } |