Project

General

Profile

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



/*
* 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 */
(10-10/23)