root/trunk/compiler/cppAst/ast/DeepCloneVisitor.cpp
| 7 | krennw | /**
 | |
|   *
 | |||
|   *                  OOAS Compiler - C++ AST
 | |||
|   *
 | |||
|   * Copyright 2015, AIT Austrian Institute of Technology.
 | |||
|   * All rights reserved.
 | |||
|   *
 | |||
|   * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
 | |||
|   *
 | |||
|   * If you modify the file please update the list of contributors below to in-
 | |||
|   * clude your name. Please also stick to the coding convention of using TABs
 | |||
|   * to do the basic (block-level) indentation and spaces for anything after
 | |||
|   * that. (Enable the display of special chars and it should be pretty obvious
 | |||
|   * what this means.) Also, remove all trailing whitespace.
 | |||
|   *
 | |||
|   * Contributors:
 | |||
|   *               Willibald Krenn (AIT)
 | |||
|   *               Stephan Zimmerer (AIT)
 | |||
|   *               Christoph Czurda (AIT)
 | |||
|   *
 | |||
|   */
 | |||
| 2 | krennw | ||
| /*
 | |||
|  * DeepCloneVisitor.cpp
 | |||
|  *
 | |||
|  *  Created on: Feb 12, 2014
 | |||
|  *      Author: willibald
 | |||
|  */
 | |||
| #include "DeepCloneVisitor.hpp"
 | |||
| #include <list>
 | |||
| #include <ast/identifiers/NamedActionIdentifier.hpp>
 | |||
| #include <ast/statements/SeqBlock.hpp>
 | |||
| #include <ast/expressions/BinaryOperator.hpp>
 | |||
| #include <ast/statements/Assignment.hpp>
 | |||
| #include <ast/identifiers/AttributeIdentifier.hpp>
 | |||
| #include <ast/statements/Call.hpp>
 | |||
| #include <ast/expressions/CallExpression.hpp>
 | |||
| #include <ast/statements/GuardedCommand.hpp>
 | |||
| #include <ast/expressions/IdentifierExpression.hpp>
 | |||
| #include <ast/expressions/ListConstructor.hpp>
 | |||
| #include <ast/expressions/SetConstructor.hpp>
 | |||
| #include <ast/expressions/TernaryOperator.hpp>
 | |||
| #include <ast/expressions/TupleConstructor.hpp>
 | |||
| #include <ast/expressions/TupleMapAccessExpression.hpp>
 | |||
| namespace Ast {
 | |||
| void DeepCloneVisitor::updateScope(IScope* aScope) {
 | |||
| 	IScope* parentScope = aScope->getParentScope();
 | |||
| 	if (parentScope != nullptr) {
 | |||
| 		if(m_mapping.count(parentScope) == 0) {
 | |||
| 			if (!m_allowLinksToNonClonedParents) {
 | |||
| 				m_context->logError("Internal Error. Scope update failed.");
 | |||
| 				abort();
 | |||
| 			}
 | |||
| 			return;
 | |||
| 		}
 | |||
| 		aScope->setParentScope((IScope*)m_mapping[parentScope]);
 | |||
| 	}
 | |||
| }
 | |||
| void DeepCloneVisitor::checkScope(IScope* aScope) {
 | |||
| 	if (aScope->getParentScope() == nullptr)
 | |||
| 		return;
 | |||
| 	if (m_mapping.count(aScope->getParentScope()) > 0) {
 | |||
| 		m_context->logError("Internal Error. Scope check failed.");
 | |||
| 		abort();
 | |||
| 	}
 | |||
| }
 | |||
| Expression* DeepCloneVisitor::eClone(Expression* anExpr) {
 | |||
| 	Expression* result = nullptr;
 | |||
| 	if (anExpr != nullptr)
 | |||
| 	{
 | |||
| 		result = m_cloneAst->createExpression(*anExpr);
 | |||
| 		if (anExpr->asScope() != nullptr)
 | |||
| 		{
 | |||
| 			m_mapping[anExpr] = result;
 | |||
| 			updateScope(result->asScope());
 | |||
| 		}
 | |||
| 		result->accept(*this);
 | |||
| 	}
 | |||
| 	return result;
 | |||
| }
 | |||
| Statement* DeepCloneVisitor::sClone(Statement* aStatement) {
 | |||
| 	Statement* result = nullptr;
 | |||
| 	if (aStatement != nullptr)
 | |||
| 	{
 | |||
| 		result = m_cloneAst->createStatement(*aStatement);
 | |||
| 		if (aStatement->asScope() != nullptr)
 | |||
| 		{
 | |||
| 			m_mapping[aStatement] = result;
 | |||
| 			updateScope(result->asScope());
 | |||
| 		}
 | |||
| 		result->accept(*this);
 | |||
| 	}
 | |||
| 	return result;
 | |||
| }
 | |||
| void DeepCloneVisitor::symTabClone(SymbolTable* aTable) {
 | |||
| 	if (aTable != nullptr && aTable->size() > 0)
 | |||
| 	{
 | |||
| 		std::list<Identifier*> newList;
 | |||
| 		for (auto& x: *aTable)
 | |||
| 		{
 | |||
| 			if (m_mapping.count(x.second) == 0) {
 | |||
| 				Identifier* newid = m_cloneAst->createIdentifier(*x.second);
 | |||
| 				newList.push_back(newid);
 | |||
| 				m_mapping[x.second] = newid;
 | |||
| 			} else {
 | |||
| 				newList.push_back((Identifier*) m_mapping[x.second]);
 | |||
| 			}
 | |||
| 		}
 | |||
| 		aTable->setSymbolList(newList);
 | |||
| 	}
 | |||
| }
 | |||
| void DeepCloneVisitor::cloneBlock(Block* aBlock) {
 | |||
| 	symTabClone(aBlock->symbols());
 | |||
| 	StatementList& statements = aBlock->statements();
 | |||
| 	for (std::size_t cntr = 0; cntr < statements.size(); cntr++) {
 | |||
| 		statements[cntr] = sClone(statements[cntr]);
 | |||
| 	}
 | |||
| }
 | |||
| void DeepCloneVisitor::cloneQuantifier(Quantifier* qf) {
 | |||
| 	symTabClone(qf->symbols());
 | |||
| 	bool oldQunatifierState = m_quantifierState;
 | |||
| 	m_quantifierState = true;
 | |||
| 	visit(qf);
 | |||
| 	m_quantifierState = oldQunatifierState;
 | |||
| }
 | |||
| void DeepCloneVisitor::cloneExpressionList(ExpressionList& aList) {
 | |||
| 	for (std::size_t cntr =0; cntr < aList.size(); cntr ++)
 | |||
| 		aList[cntr] = eClone(aList[cntr]);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(NamedActionIdentifier* namedActionIdentifier)
 | |||
| {
 | |||
| 	namedActionIdentifier->setBody(sClone(namedActionIdentifier->body()));
 | |||
| 	// we do not clone the parameters..
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(ObjectConstructor* )
 | |||
| {
 | |||
| 	//CompleteAstTraversalVisitor::visit(objectConstructor);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(NondetBlock* nondetBlock)
 | |||
| {
 | |||
| 	cloneBlock((Block*)nondetBlock);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(SeqBlock* seqBlock)
 | |||
| {
 | |||
| 	seqBlock->setFilter(eClone(seqBlock->filter()));
 | |||
| 	cloneBlock((Block*)seqBlock);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(PrioBlock* prioBlock)
 | |||
| {
 | |||
| 	cloneBlock((Block*)prioBlock);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(AccessExpression* accessExpression)
 | |||
| {
 | |||
| 	visit((BinaryOperator*)accessExpression);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(BinaryOperator* binaryOperator)
 | |||
| {
 | |||
| 	Expression* left  = eClone(binaryOperator->left());
 | |||
| 	Expression* right = eClone(binaryOperator->right());
 | |||
| 	binaryOperator->setLeftChild(left);
 | |||
| 	binaryOperator->setRightChild(right);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(Assignment* assignment)
 | |||
| {
 | |||
| 	symTabClone(assignment->symbols());
 | |||
| 	cloneExpressionList(assignment->places());
 | |||
| 	cloneExpressionList(assignment->values());
 | |||
| 	assignment->setNondetExpression(eClone(assignment->nondetExpression()));
 | |||
| 	checkScope(assignment);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(AttributeIdentifier* attributeIdentifier)
 | |||
| {
 | |||
| 	attributeIdentifier->setInitializer(eClone(attributeIdentifier->initializer()));
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(Call* call)
 | |||
| {
 | |||
| 	call->setCallExpression(eClone(call->callExpression()));
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(CallExpression* callExpression)
 | |||
| {
 | |||
| 	cloneExpressionList(callExpression->arguments());
 | |||
| 	visit((UnaryOperator*)callExpression);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(ExistsQuantifier* quantifier)
 | |||
| {
 | |||
| 	cloneQuantifier((Quantifier*)quantifier);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(ForallQuantifier* quantifier)
 | |||
| {
 | |||
| 	cloneQuantifier((Quantifier*)quantifier);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(GuardedCommand* guardedCommand)
 | |||
| {
 | |||
| 	Statement*  newblock = sClone(guardedCommand->body());
 | |||
| 	Expression* newguard = eClone(guardedCommand->guard());
 | |||
| 	guardedCommand->setBody(newblock);
 | |||
| 	guardedCommand->setGuard(newguard);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(IdentifierExpression* identifierExpression)
 | |||
| {
 | |||
| 	if (identifierExpression->isSelf() && m_selfreplacement != nullptr)
 | |||
| 		identifierExpression->setIdentifier(m_selfreplacement);
 | |||
| 	else if (m_mapping.count(identifierExpression->identifier()) > 0
 | |||
| 	         && identifierExpression->identifier()->kind() != IdentifierKind::MethodIdentifier)
 | |||
| 	{
 | |||
| 		/* we do NOT replace method calls here, since they are prefixed by self if it's a
 | |||
| 		 * method in the current object or by some field/method access if it's another
 | |||
| 		 * object.
 | |||
| 		 */
 | |||
| 		identifierExpression->setIdentifier((Identifier*)m_mapping[identifierExpression->identifier()]);
 | |||
| 	}
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(ListConstructor* listConstructor)
 | |||
| {
 | |||
| 	symTabClone(listConstructor->comprehensionVariables());
 | |||
| 	cloneExpressionList(listConstructor->elements());
 | |||
| 	listConstructor->setComprehension(eClone(listConstructor->comprehension()));
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(SetConstructor* setConstructor)
 | |||
| {
 | |||
| 	symTabClone(setConstructor->comprehensionVariables());
 | |||
| 	cloneExpressionList(setConstructor->items());
 | |||
| 	setConstructor->setComprehension(eClone(setConstructor->comprehension()));
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(TernaryOperator* ternaryOperator)
 | |||
| {
 | |||
| 	ternaryOperator->setLeftChild(eClone(ternaryOperator->left()));
 | |||
| 	ternaryOperator->setMidChild(eClone(ternaryOperator->mid()));
 | |||
| 	ternaryOperator->setRightChild(eClone(ternaryOperator->right()));
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(TupleConstructor* tupleConstructor)
 | |||
| {
 | |||
| 	cloneExpressionList(tupleConstructor->values());
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(TupleMapAccessExpression* tupleMapAccessExpression)
 | |||
| {
 | |||
| 	tupleMapAccessExpression->setArgument(eClone(tupleMapAccessExpression->argument()));
 | |||
| 	visit((UnaryOperator*)tupleMapAccessExpression);
 | |||
| }
 | |||
| void DeepCloneVisitor::visit(UnaryOperator* unaryOperator)
 | |||
| {
 | |||
| 	unaryOperator->setChild(eClone(unaryOperator->child()));
 | |||
| }
 | |||
| } /* namespace Ast */
 |