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