<commit_before>/* Copyright 2017 QReal Research Group
 *
 * 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 "structuralControlFlowGenerator.h"

#include <QtCore/QQueue>

#include <QtCore/QDebug>

#include <algorithm>

using namespace qReal;
using namespace generatorBase;
using namespace semantics;

StructuralControlFlowGenerator::StructuralControlFlowGenerator(const qrRepo::RepoApi &repo
		, ErrorReporterInterface &errorReporter
		, GeneratorCustomizer &customizer
		, PrimaryControlFlowValidator &validator
		, const Id &diagramId
		, QObject *parent
		, bool isThisDiagramMain)
	: ControlFlowGeneratorBase(repo, errorReporter, customizer, validator, diagramId, parent, isThisDiagramMain)
	, mStructurizator(new Structurizator(this))
{
}

ControlFlowGeneratorBase *StructuralControlFlowGenerator::cloneFor(const Id &diagramId, bool cloneForNewDiagram)
{
	StructuralControlFlowGenerator * const copy = new StructuralControlFlowGenerator(mRepo
			, mErrorReporter, mCustomizer, (cloneForNewDiagram ? *mValidator.clone() : mValidator)
			, diagramId, parent(), false);

	return copy;
}

void StructuralControlFlowGenerator::beforeSearch()
{
}

void StructuralControlFlowGenerator::visit(const Id &id, QList<LinkInfo> &links)
{
	Q_UNUSED(links)
	mIds.insert(id);
}

void StructuralControlFlowGenerator::visitRegular(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::visitConditional(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::visitLoop(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::visitSwitch(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::visitUnknown(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::afterSearch()
{
}

bool StructuralControlFlowGenerator::cantBeGeneratedIntoStructuredCode() const
{
	return mCantBeGeneratedIntoStructuredCode;
}

SemanticTree *StructuralControlFlowGenerator::generate(const Id &initialNode, const QString &threadId)
{
	ControlFlowGeneratorBase::generate(initialNode, threadId);
	return mSemanticTree;
}

void StructuralControlFlowGenerator::performGeneration()
{
	//isPerformingGeneration = false;
	mCantBeGeneratedIntoStructuredCode = false;
	ControlFlowGeneratorBase::performGeneration();

	myUtils::IntermediateNode *tree = mStructurizator->performStructurization(&mRepo, mIds);
	if (tree) {
		obtainSemanticTree(tree);
	} else {
		mCantBeGeneratedIntoStructuredCode = true;
	}

	if (mCantBeGeneratedIntoStructuredCode) {
		mSemanticTree = nullptr;
	}
}

void StructuralControlFlowGenerator::obtainSemanticTree(myUtils::IntermediateNode *root)
{
	bool hasBreak = root->analyzeBreak();
	SemanticNode * semanticNode = transformNode(root);
	mSemanticTree->setRoot(new RootNode(semanticNode, mSemanticTree));
}

void StructuralControlFlowGenerator::checkAndAppendBlock(ZoneNode *zone, myUtils::IntermediateNode *node)
{
	if (node->type() == myUtils::IntermediateNode::simple) {
		myUtils::SimpleNode *simpleNode = static_cast<myUtils::SimpleNode *>(node);

		switch (semanticsOf(simpleNode->id())) {
		case enums::semantics::conditionalBlock:
		case enums::semantics::switchBlock:
			break;
		default:
			zone->appendChild(transformSimple(simpleNode));
		}

	} else {
		zone->appendChild(transformNode(node));
	}
}

// maybe use strategy to recursively handle this situation?
SemanticNode *StructuralControlFlowGenerator::transformNode(myUtils::IntermediateNode *node)
{
	switch (node->type()) {
	case myUtils::IntermediateNode::Type::simple: {
		myUtils::SimpleNode *simpleNode = static_cast<myUtils::SimpleNode *>(node);
		return transformSimple(simpleNode);
	}

	case myUtils::IntermediateNode::Type::block: {
		myUtils::BlockNode *blockNode = static_cast<myUtils::BlockNode *>(node);
		return transformBlock(blockNode);
	}

	case myUtils::IntermediateNode::Type::ifThenElseCondition: {
		myUtils::IfNode *ifNode = static_cast<myUtils::IfNode *>(node);
		return transformIfThenElse(ifNode);
	}

	case myUtils::IntermediateNode::Type::switchCondition: {
		myUtils::SwitchNode *switchNode = static_cast<myUtils::SwitchNode *>(node);
		return transformSwitch(switchNode);
	}

	case myUtils::IntermediateNode::Type::infiniteloop: {
		myUtils::SelfLoopNode *selfLoopNode = static_cast<myUtils::SelfLoopNode *>(node);
		return transformSelfLoop(selfLoopNode);
	}

	case myUtils::IntermediateNode::Type::whileloop: {
		myUtils::WhileNode *whileNode = static_cast<myUtils::WhileNode *>(node);
		return transformWhileLoop(whileNode);
	}

	case myUtils::IntermediateNode::Type::breakNode: {
		return transformBreakNode();
	}

	case myUtils::IntermediateNode::Type::fakeCycleHead: {
		return transformFakeCycleHead();
	}

	case myUtils::IntermediateNode::Type::nodeWithBreaks: {
		return createConditionWithBreaks(static_cast<myUtils::NodeWithBreaks *>(node));
	}

	default:
		qDebug() << "Undefined type of Intermediate node!";
		mCantBeGeneratedIntoStructuredCode = true;

		return nullptr;
	}
}

SemanticNode *StructuralControlFlowGenerator::transformSimple(myUtils::SimpleNode *simpleNode)
{
	return mSemanticTree->produceNodeFor(simpleNode->id());
}

SemanticNode *StructuralControlFlowGenerator::transformBlock(myUtils::BlockNode *blockNode)
{
	ZoneNode *zone = new ZoneNode(mSemanticTree);
	checkAndAppendBlock(zone, blockNode->firstNode());
	checkAndAppendBlock(zone, blockNode->secondNode());

	return zone;
}

SemanticNode *StructuralControlFlowGenerator::transformIfThenElse(myUtils::IfNode *ifNode)
{
	if (ifNode->condition()->type() == myUtils::IntermediateNode::nodeWithBreaks) {
		myUtils::NodeWithBreaks *nodeWithBreaks = static_cast<myUtils::NodeWithBreaks *>(ifNode->condition());
		nodeWithBreaks->setRestBranches({ifNode->thenBranch(), ifNode->elseBranch()});
		return createConditionWithBreaks(nodeWithBreaks);
	}

	const qReal::Id conditionId = ifNode->condition()->firstId();
	const qReal::Id thenId = ifNode->thenBranch()->firstId();

	switch (semanticsOf(conditionId)) {

	case enums::semantics::conditionalBlock: {
		return createSemanticIfNode(conditionId, ifNode->thenBranch(), ifNode->elseBranch());
	}

	case enums::semantics::switchBlock: {
		QList<myUtils::IntermediateNode *> branches = {ifNode->thenBranch()};

		if (ifNode->elseBranch()) {
			branches.append(ifNode->elseBranch());
		}

		return createSemanticSwitchNode(conditionId, branches, ifNode->hasBreakInside());
	}

	case enums::semantics::forkBlock: {

		if (!ifNode->elseBranch()) {
			qDebug() << "Fork should have all branches";
			mCantBeGeneratedIntoStructuredCode = true;
			return nullptr;
		}

		QList<myUtils::IntermediateNode *> branches = { ifNode->thenBranch(), ifNode->elseBranch() };
		return createSemanticForkNode(conditionId, branches);
	}

	default:
		break;
	}

	qDebug() << "Problem: couldn't transform if-then-else";
	mCantBeGeneratedIntoStructuredCode = true;

	return nullptr;
}

SemanticNode *StructuralControlFlowGenerator::transformSelfLoop(myUtils::SelfLoopNode *selfLoopNode)
{
	LoopNode *semanticLoop = new LoopNode(qReal::Id(), mSemanticTree);
	semanticLoop->bodyZone()->appendChild(transformNode(selfLoopNode->bodyNode()));
	return semanticLoop;
}

SemanticNode *StructuralControlFlowGenerator::transformWhileLoop(myUtils::WhileNode *whileNode)
{
	myUtils::IntermediateNode *headNode = whileNode->headNode();
	myUtils::IntermediateNode *bodyNode = whileNode->bodyNode();
	myUtils::IntermediateNode *exitNode = whileNode->exitNode();

	LoopNode *semanticLoop = nullptr;
	const qReal::Id conditionId = headNode->firstId();

	if (headNode->type() == myUtils::IntermediateNode::Type::simple) {
		switch(semanticsOf(conditionId)) {
		case enums::semantics::conditionalBlock:
		case enums::semantics::loopBlock: {
			semanticLoop = new LoopNode(conditionId, mSemanticTree);
			semanticLoop->bodyZone()->appendChild(transformNode(bodyNode));
			return semanticLoop;
		}

		case enums::semantics::switchBlock: {
			QList<myUtils::IntermediateNode *> exitBranches;
			exitBranches.append(new myUtils::BreakNode(exitNode->firstId(), mStructurizator));

			myUtils::NodeWithBreaks *nodeWithBreaks = new myUtils::NodeWithBreaks(headNode, exitBranches, mStructurizator);
			nodeWithBreaks->setRestBranches( { bodyNode } );

			semanticLoop = new LoopNode(qReal::Id(), mSemanticTree);
			semanticLoop->bodyZone()->appendChild(createConditionWithBreaks(nodeWithBreaks));
			return semanticLoop;
		}

		default:
			break;
		}
	}

	semanticLoop = new LoopNode(qReal::Id(), mSemanticTree);
	semanticLoop->bodyZone()->appendChild(transformNode(headNode));
	semanticLoop->bodyZone()->appendChild(transformNode(bodyNode));
	return semanticLoop;
}

SemanticNode *StructuralControlFlowGenerator::transformSwitch(myUtils::SwitchNode *switchNode)
{
	const qReal::Id &conditionId = switchNode->condition()->firstId();
	QList<myUtils::IntermediateNode *> branches = switchNode->branches();

	if (switchNode->condition()->type() == myUtils::IntermediateNode::nodeWithBreaks) {
		myUtils::NodeWithBreaks *nodeWithBreaks = static_cast<myUtils::NodeWithBreaks *>(switchNode->condition());
		nodeWithBreaks->setRestBranches(branches);
		return createConditionWithBreaks(nodeWithBreaks);
	}

	if (semanticsOf(conditionId) == enums::semantics::switchBlock) {
		return createSemanticSwitchNode(conditionId, branches, switchNode->hasBreakInside());
	} else if (semanticsOf(conditionId) == enums::semantics::forkBlock) {
		return createSemanticForkNode(conditionId, branches);
	}

	qDebug() << "Problem: couldn't identidy semantics id for switchNode";
	mCantBeGeneratedIntoStructuredCode = true;

	return nullptr;
}

SemanticNode *StructuralControlFlowGenerator::transformBreakNode()
{
	return semantics::SimpleNode::createBreakNode(mSemanticTree);
}

SemanticNode *StructuralControlFlowGenerator::transformFakeCycleHead()
{
	return new SimpleNode(qReal::Id(), mSemanticTree);
}

SemanticNode *StructuralControlFlowGenerator::createConditionWithBreaks(myUtils::NodeWithBreaks *nodeWithBreaks)
{
	const qReal::Id conditionId = nodeWithBreaks->firstId();

	QList<myUtils::IntermediateNode *> exitBranches = nodeWithBreaks->exitBranches();
	QList<myUtils::IntermediateNode *> restBranches = nodeWithBreaks->restBranches();

	switch(semanticsOf(conditionId)) {
	case enums::semantics::conditionalBlock: {
		return createSemanticIfNode(conditionId, exitBranches.first(), nullptr);
	}

	case enums::semantics::switchBlock: {
		QList<myUtils::IntermediateNode *> allBranches = restBranches + exitBranches;
		return createSemanticSwitchNode(conditionId, allBranches, true);
	}

	default:
		qDebug() << "Problem in createConditionWithBreaks";
		mCantBeGeneratedIntoStructuredCode = false;
		return nullptr;
	}

}

SemanticNode *StructuralControlFlowGenerator::createSemanticIfNode(const Id &conditionId, myUtils::IntermediateNode *thenNode, myUtils::IntermediateNode *elseNode)
{
	IfNode *semanticIf = new IfNode(conditionId, mSemanticTree);
	QPair<LinkInfo, LinkInfo> links = ifBranchesFor(conditionId);

	if (links.first.target != thenNode->firstId()) {
		semanticIf->invertCondition();
	}

	semanticIf->thenZone()->appendChild(transformNode(thenNode));

	if (elseNode) {
		semanticIf->elseZone()->appendChild(transformNode(elseNode));
	}

	return semanticIf;
}

SemanticNode *StructuralControlFlowGenerator::createSemanticSwitchNode(const Id &conditionId, const QList<myUtils::IntermediateNode *> &branches, bool generateIfs)
{
	SwitchNode *semanticSwitch = new SwitchNode(conditionId, mSemanticTree);

	QMap<qReal::Id, SemanticNode *> visitedBranch;

	for (const qReal::Id &link : mRepo.outgoingLinks(conditionId)) {
		const QString expression = mRepo.property(link, "Guard").toString();
		const qReal::Id otherVertex = mRepo.otherEntityFromLink(link, conditionId);

		if (visitedBranch.contains(otherVertex)) {
			NonZoneNode * const target = static_cast<NonZoneNode *>(visitedBranch[otherVertex]);
			semanticSwitch->mergeBranch(expression, target);
		} else {
			bool branchNodeWasFound = false;
			SemanticNode *semanticNodeForBranch = nullptr;
			for (myUtils::IntermediateNode *branchNode : branches) {
				if (branchNode->firstId() == otherVertex) {
					semanticNodeForBranch = transformNode(branchNode);
					branchNodeWasFound = true;
					break;
				}
			}

			if (!branchNodeWasFound) {
				semanticNodeForBranch = new SimpleNode(qReal::Id(), this);
			}

			semanticSwitch->addBranch(expression, semanticNodeForBranch);
			visitedBranch[otherVertex] = semanticNodeForBranch;
		}
	}

	if (generateIfs) {
		semanticSwitch->setGenerateIfs();
	}

	return semanticSwitch;
}

SemanticNode *StructuralControlFlowGenerator::createSemanticForkNode(const Id &conditionId, const QList<myUtils::IntermediateNode *> &branches)
{
	Q_UNUSED(branches)

	ForkNode *semanticFork = new ForkNode(conditionId, mSemanticTree);

	for (const qReal::Id &link : mRepo.outgoingLinks(conditionId)) {
		const QString expression = mRepo.property(link, "Expression").toString();
		const qReal::Id otherVertex = mRepo.otherEntityFromLink(link, conditionId);
		semanticFork->appendThread(otherVertex, expression);
	}

	return semanticFork;
}
<commit_msg>Remove unused variables<commit_after>/* Copyright 2017 QReal Research Group
 *
 * 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 "structuralControlFlowGenerator.h"

#include <QtCore/QQueue>

#include <QtCore/QDebug>

#include <algorithm>

using namespace qReal;
using namespace generatorBase;
using namespace semantics;

StructuralControlFlowGenerator::StructuralControlFlowGenerator(const qrRepo::RepoApi &repo
		, ErrorReporterInterface &errorReporter
		, GeneratorCustomizer &customizer
		, PrimaryControlFlowValidator &validator
		, const Id &diagramId
		, QObject *parent
		, bool isThisDiagramMain)
	: ControlFlowGeneratorBase(repo, errorReporter, customizer, validator, diagramId, parent, isThisDiagramMain)
	, mStructurizator(new Structurizator(this))
{
}

ControlFlowGeneratorBase *StructuralControlFlowGenerator::cloneFor(const Id &diagramId, bool cloneForNewDiagram)
{
	StructuralControlFlowGenerator * const copy = new StructuralControlFlowGenerator(mRepo
			, mErrorReporter, mCustomizer, (cloneForNewDiagram ? *mValidator.clone() : mValidator)
			, diagramId, parent(), false);

	return copy;
}

void StructuralControlFlowGenerator::beforeSearch()
{
}

void StructuralControlFlowGenerator::visit(const Id &id, QList<LinkInfo> &links)
{
	Q_UNUSED(links)
	mIds.insert(id);
}

void StructuralControlFlowGenerator::visitRegular(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::visitConditional(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::visitLoop(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::visitSwitch(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::visitUnknown(const Id &id, const QList<LinkInfo> &links)
{
	Q_UNUSED(id)
	Q_UNUSED(links)
}

void StructuralControlFlowGenerator::afterSearch()
{
}

bool StructuralControlFlowGenerator::cantBeGeneratedIntoStructuredCode() const
{
	return mCantBeGeneratedIntoStructuredCode;
}

SemanticTree *StructuralControlFlowGenerator::generate(const Id &initialNode, const QString &threadId)
{
	ControlFlowGeneratorBase::generate(initialNode, threadId);
	return mSemanticTree;
}

void StructuralControlFlowGenerator::performGeneration()
{
	//isPerformingGeneration = false;
	mCantBeGeneratedIntoStructuredCode = false;
	ControlFlowGeneratorBase::performGeneration();

	myUtils::IntermediateNode *tree = mStructurizator->performStructurization(&mRepo, mIds);
	if (tree) {
		obtainSemanticTree(tree);
	} else {
		mCantBeGeneratedIntoStructuredCode = true;
	}

	if (mCantBeGeneratedIntoStructuredCode) {
		mSemanticTree = nullptr;
	}
}

void StructuralControlFlowGenerator::obtainSemanticTree(myUtils::IntermediateNode *root)
{
	root->analyzeBreak();
	SemanticNode * semanticNode = transformNode(root);
	mSemanticTree->setRoot(new RootNode(semanticNode, mSemanticTree));
}

void StructuralControlFlowGenerator::checkAndAppendBlock(ZoneNode *zone, myUtils::IntermediateNode *node)
{
	if (node->type() == myUtils::IntermediateNode::simple) {
		myUtils::SimpleNode *simpleNode = static_cast<myUtils::SimpleNode *>(node);

		switch (semanticsOf(simpleNode->id())) {
		case enums::semantics::conditionalBlock:
		case enums::semantics::switchBlock:
			break;
		default:
			zone->appendChild(transformSimple(simpleNode));
		}

	} else {
		zone->appendChild(transformNode(node));
	}
}

// maybe use strategy to recursively handle this situation?
SemanticNode *StructuralControlFlowGenerator::transformNode(myUtils::IntermediateNode *node)
{
	switch (node->type()) {
	case myUtils::IntermediateNode::Type::simple: {
		myUtils::SimpleNode *simpleNode = static_cast<myUtils::SimpleNode *>(node);
		return transformSimple(simpleNode);
	}

	case myUtils::IntermediateNode::Type::block: {
		myUtils::BlockNode *blockNode = static_cast<myUtils::BlockNode *>(node);
		return transformBlock(blockNode);
	}

	case myUtils::IntermediateNode::Type::ifThenElseCondition: {
		myUtils::IfNode *ifNode = static_cast<myUtils::IfNode *>(node);
		return transformIfThenElse(ifNode);
	}

	case myUtils::IntermediateNode::Type::switchCondition: {
		myUtils::SwitchNode *switchNode = static_cast<myUtils::SwitchNode *>(node);
		return transformSwitch(switchNode);
	}

	case myUtils::IntermediateNode::Type::infiniteloop: {
		myUtils::SelfLoopNode *selfLoopNode = static_cast<myUtils::SelfLoopNode *>(node);
		return transformSelfLoop(selfLoopNode);
	}

	case myUtils::IntermediateNode::Type::whileloop: {
		myUtils::WhileNode *whileNode = static_cast<myUtils::WhileNode *>(node);
		return transformWhileLoop(whileNode);
	}

	case myUtils::IntermediateNode::Type::breakNode: {
		return transformBreakNode();
	}

	case myUtils::IntermediateNode::Type::fakeCycleHead: {
		return transformFakeCycleHead();
	}

	case myUtils::IntermediateNode::Type::nodeWithBreaks: {
		return createConditionWithBreaks(static_cast<myUtils::NodeWithBreaks *>(node));
	}

	default:
		qDebug() << "Undefined type of Intermediate node!";
		mCantBeGeneratedIntoStructuredCode = true;

		return nullptr;
	}
}

SemanticNode *StructuralControlFlowGenerator::transformSimple(myUtils::SimpleNode *simpleNode)
{
	return mSemanticTree->produceNodeFor(simpleNode->id());
}

SemanticNode *StructuralControlFlowGenerator::transformBlock(myUtils::BlockNode *blockNode)
{
	ZoneNode *zone = new ZoneNode(mSemanticTree);
	checkAndAppendBlock(zone, blockNode->firstNode());
	checkAndAppendBlock(zone, blockNode->secondNode());

	return zone;
}

SemanticNode *StructuralControlFlowGenerator::transformIfThenElse(myUtils::IfNode *ifNode)
{
	if (ifNode->condition()->type() == myUtils::IntermediateNode::nodeWithBreaks) {
		myUtils::NodeWithBreaks *nodeWithBreaks = static_cast<myUtils::NodeWithBreaks *>(ifNode->condition());
		nodeWithBreaks->setRestBranches({ifNode->thenBranch(), ifNode->elseBranch()});
		return createConditionWithBreaks(nodeWithBreaks);
	}

	const qReal::Id conditionId = ifNode->condition()->firstId();

	switch (semanticsOf(conditionId)) {

	case enums::semantics::conditionalBlock: {
		return createSemanticIfNode(conditionId, ifNode->thenBranch(), ifNode->elseBranch());
	}

	case enums::semantics::switchBlock: {
		QList<myUtils::IntermediateNode *> branches = {ifNode->thenBranch()};

		if (ifNode->elseBranch()) {
			branches.append(ifNode->elseBranch());
		}

		return createSemanticSwitchNode(conditionId, branches, ifNode->hasBreakInside());
	}

	case enums::semantics::forkBlock: {

		if (!ifNode->elseBranch()) {
			qDebug() << "Fork should have all branches";
			mCantBeGeneratedIntoStructuredCode = true;
			return nullptr;
		}

		QList<myUtils::IntermediateNode *> branches = { ifNode->thenBranch(), ifNode->elseBranch() };
		return createSemanticForkNode(conditionId, branches);
	}

	default:
		break;
	}

	qDebug() << "Problem: couldn't transform if-then-else";
	mCantBeGeneratedIntoStructuredCode = true;

	return nullptr;
}

SemanticNode *StructuralControlFlowGenerator::transformSelfLoop(myUtils::SelfLoopNode *selfLoopNode)
{
	LoopNode *semanticLoop = new LoopNode(qReal::Id(), mSemanticTree);
	semanticLoop->bodyZone()->appendChild(transformNode(selfLoopNode->bodyNode()));
	return semanticLoop;
}

SemanticNode *StructuralControlFlowGenerator::transformWhileLoop(myUtils::WhileNode *whileNode)
{
	myUtils::IntermediateNode *headNode = whileNode->headNode();
	myUtils::IntermediateNode *bodyNode = whileNode->bodyNode();
	myUtils::IntermediateNode *exitNode = whileNode->exitNode();

	LoopNode *semanticLoop = nullptr;
	const qReal::Id conditionId = headNode->firstId();

	if (headNode->type() == myUtils::IntermediateNode::Type::simple) {
		switch(semanticsOf(conditionId)) {
		case enums::semantics::conditionalBlock:
		case enums::semantics::loopBlock: {
			semanticLoop = new LoopNode(conditionId, mSemanticTree);
			semanticLoop->bodyZone()->appendChild(transformNode(bodyNode));
			return semanticLoop;
		}

		case enums::semantics::switchBlock: {
			QList<myUtils::IntermediateNode *> exitBranches;
			exitBranches.append(new myUtils::BreakNode(exitNode->firstId(), mStructurizator));

			myUtils::NodeWithBreaks *nodeWithBreaks = new myUtils::NodeWithBreaks(headNode, exitBranches, mStructurizator);
			nodeWithBreaks->setRestBranches( { bodyNode } );

			semanticLoop = new LoopNode(qReal::Id(), mSemanticTree);
			semanticLoop->bodyZone()->appendChild(createConditionWithBreaks(nodeWithBreaks));
			return semanticLoop;
		}

		default:
			break;
		}
	}

	semanticLoop = new LoopNode(qReal::Id(), mSemanticTree);
	semanticLoop->bodyZone()->appendChild(transformNode(headNode));
	semanticLoop->bodyZone()->appendChild(transformNode(bodyNode));
	return semanticLoop;
}

SemanticNode *StructuralControlFlowGenerator::transformSwitch(myUtils::SwitchNode *switchNode)
{
	const qReal::Id &conditionId = switchNode->condition()->firstId();
	QList<myUtils::IntermediateNode *> branches = switchNode->branches();

	if (switchNode->condition()->type() == myUtils::IntermediateNode::nodeWithBreaks) {
		myUtils::NodeWithBreaks *nodeWithBreaks = static_cast<myUtils::NodeWithBreaks *>(switchNode->condition());
		nodeWithBreaks->setRestBranches(branches);
		return createConditionWithBreaks(nodeWithBreaks);
	}

	if (semanticsOf(conditionId) == enums::semantics::switchBlock) {
		return createSemanticSwitchNode(conditionId, branches, switchNode->hasBreakInside());
	} else if (semanticsOf(conditionId) == enums::semantics::forkBlock) {
		return createSemanticForkNode(conditionId, branches);
	}

	qDebug() << "Problem: couldn't identidy semantics id for switchNode";
	mCantBeGeneratedIntoStructuredCode = true;

	return nullptr;
}

SemanticNode *StructuralControlFlowGenerator::transformBreakNode()
{
	return semantics::SimpleNode::createBreakNode(mSemanticTree);
}

SemanticNode *StructuralControlFlowGenerator::transformFakeCycleHead()
{
	return new SimpleNode(qReal::Id(), mSemanticTree);
}

SemanticNode *StructuralControlFlowGenerator::createConditionWithBreaks(myUtils::NodeWithBreaks *nodeWithBreaks)
{
	const qReal::Id conditionId = nodeWithBreaks->firstId();

	QList<myUtils::IntermediateNode *> exitBranches = nodeWithBreaks->exitBranches();
	QList<myUtils::IntermediateNode *> restBranches = nodeWithBreaks->restBranches();

	switch(semanticsOf(conditionId)) {
	case enums::semantics::conditionalBlock: {
		return createSemanticIfNode(conditionId, exitBranches.first(), nullptr);
	}

	case enums::semantics::switchBlock: {
		QList<myUtils::IntermediateNode *> allBranches = restBranches + exitBranches;
		return createSemanticSwitchNode(conditionId, allBranches, true);
	}

	default:
		qDebug() << "Problem in createConditionWithBreaks";
		mCantBeGeneratedIntoStructuredCode = false;
		return nullptr;
	}

}

SemanticNode *StructuralControlFlowGenerator::createSemanticIfNode(const Id &conditionId, myUtils::IntermediateNode *thenNode, myUtils::IntermediateNode *elseNode)
{
	IfNode *semanticIf = new IfNode(conditionId, mSemanticTree);
	QPair<LinkInfo, LinkInfo> links = ifBranchesFor(conditionId);

	if (links.first.target != thenNode->firstId()) {
		semanticIf->invertCondition();
	}

	semanticIf->thenZone()->appendChild(transformNode(thenNode));

	if (elseNode) {
		semanticIf->elseZone()->appendChild(transformNode(elseNode));
	}

	return semanticIf;
}

SemanticNode *StructuralControlFlowGenerator::createSemanticSwitchNode(const Id &conditionId, const QList<myUtils::IntermediateNode *> &branches, bool generateIfs)
{
	SwitchNode *semanticSwitch = new SwitchNode(conditionId, mSemanticTree);

	QMap<qReal::Id, SemanticNode *> visitedBranch;

	for (const qReal::Id &link : mRepo.outgoingLinks(conditionId)) {
		const QString expression = mRepo.property(link, "Guard").toString();
		const qReal::Id otherVertex = mRepo.otherEntityFromLink(link, conditionId);

		if (visitedBranch.contains(otherVertex)) {
			NonZoneNode * const target = static_cast<NonZoneNode *>(visitedBranch[otherVertex]);
			semanticSwitch->mergeBranch(expression, target);
		} else {
			bool branchNodeWasFound = false;
			SemanticNode *semanticNodeForBranch = nullptr;
			for (myUtils::IntermediateNode *branchNode : branches) {
				if (branchNode->firstId() == otherVertex) {
					semanticNodeForBranch = transformNode(branchNode);
					branchNodeWasFound = true;
					break;
				}
			}

			if (!branchNodeWasFound) {
				semanticNodeForBranch = new SimpleNode(qReal::Id(), this);
			}

			semanticSwitch->addBranch(expression, semanticNodeForBranch);
			visitedBranch[otherVertex] = semanticNodeForBranch;
		}
	}

	if (generateIfs) {
		semanticSwitch->setGenerateIfs();
	}

	return semanticSwitch;
}

SemanticNode *StructuralControlFlowGenerator::createSemanticForkNode(const Id &conditionId, const QList<myUtils::IntermediateNode *> &branches)
{
	Q_UNUSED(branches)

	ForkNode *semanticFork = new ForkNode(conditionId, mSemanticTree);

	for (const qReal::Id &link : mRepo.outgoingLinks(conditionId)) {
		const QString expression = mRepo.property(link, "Expression").toString();
		const qReal::Id otherVertex = mRepo.otherEntityFromLink(link, conditionId);
		semanticFork->appendThread(otherVertex, expression);
	}

	return semanticFork;
}
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:3; c-basic-offset:4; indent-tabs-mode:nil -*-

//Copyright: Universidad Carlos III de Madrid (C) 2016
//Authors: jgvictores, raulfdzbis, smorante

#include "CgdaIronFitnessFunction.hpp"

#define NTPOINTS 17
#define NFEATURES 6
#define NSQUARES 16

namespace teo
{

/************************************************************************/

void CgdaIronFitnessFunction::registerParameters(StateP state) {
	state->getRegistry()->registerEntry("function", (voidP) (new uint(1)), ECF::UINT);
}

/************************************************************************/

bool CgdaIronFitnessFunction::initialize(StateP state) {

    voidP sptr = state->getRegistry()->getEntry("function"); // get parameter value

	return true;
}

/************************************************************************/

FitnessP CgdaIronFitnessFunction::evaluate(IndividualP individual) {
    // Evaluation creates a new fitness object using a smart pointer
	// in our case, we try to minimize the function value, so we use FitnessMin fitness (for minimization problems)
	FitnessP fitness (new FitnessMin);

	// we define FloatingPoint as the only genotype (in the configuration file)
	FloatingPoint::FloatingPoint* gen = (FloatingPoint::FloatingPoint*) individual->getGenotype().get();

	// we implement the fitness function 'as is', without any translation
	// the number of variables is read from the genotype itself (size of 'realValue' vactor)

    double value =0;
    value= getCustomFitness(gen->realValue);
    fitness->setValue(value);
    return fitness;
}

/************************************************************************/

double CgdaIronFitnessFunction::getCustomFitness(vector <double> genPoints){

    //***********************Define the generalized feature trajectory**********************************************//

    std::vector<std::vector<double>> target;
    //double target[NFEATURES][NTPOINTS];

//    int a[3][4] = {
//       {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
//       {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
//       {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
//    };

    //This is sqFeatures

    //target.push_back(feature1T1,feature2T2,feature3T3...);

    //*****************************************OBSERVATION STEP*****************************************************//

    std::vector<double> observation;

    //READ FROM PsqFeatures
    for(int i=0;i<psqFeatures->size();i++)
    {
        observation.push_back(psqFeatures->operator [](i));
    }

    //Obtain TEO state
    //P:yarp::os::Bottle cmd3,res3;
    //P:cmd3.addString("reset");
    //P:pRpcClient->write(cmd3,res3);

    //P:double percentage;
    //P:double Npaint=0;

    //P:for(int i=0;i<psqFeatures->size();i++)
    //P:{
    //P:    Npaint += psqFeatures->operator [](i);
    //P: }

    //Percentage of the wall painted before evolution
    //P:printf("EL NPAINT ES::::::: %f \n",Npaint);
    //P:percentage=(Npaint/NSQUARES)*100;
    //P:printf("EL PERCENTAGE ES::::::: %f \n",percentage);

    //***************************************LOCALIZATION STEP******************************************************//

    //Serch the timeStep where we are (LOCALIZATION STEP)
    int timeStep;
    double diff=1000000;
    for(int i=0;i<NFEATURES;i++){
        double aux_dist=0;
        double aux_elem;
        for(int j=0;j<NTPOINTS;j++){ //We give priority to the elements at the last positions
            aux_elem=observation[i]-target[i][j];
            aux_elem=aux_elem*aux_elem;
            aux_dist=aux_dist+aux_elem;
        }
        //printf("Percentage: %d \n",percentage);
        //printf("Target: %d \n", Const_target[i]);
        //P:diff_aux=percentage-Const_target[i];

        //P:diff_aux=diff_aux*diff_aux;
        //P: diff_aux=sqrt(diff_aux);

        aux_dist=sqrt(aux_dist);

        if(aux_dist<diff){
            timeStep=i;
            diff=aux_dist;
            //printf("i -> %d", i);
            //printf("Time Step %d \n",timeStep);

        }
    }

    //********************************SIMULATED EXECUTION STEP******************************************************//

    //Set new positions of the robot using dEncRaw
    std::vector<double> dEncRaw(6);  // NUM_MOTORS
    dEncRaw[0] = genPoints[0];  // simple
    dEncRaw[1] = -genPoints[1];  // simple
    dEncRaw[3] = genPoints[2];  // simple

    dEncRaw[4] = 45; //TODO:This must be changed for IRON

    //Actually move the robot
    mentalPositionControl->positionMove(dEncRaw.data());

    //********************************SECOND OBSERVATION STEP*******************************************************//

    observation.clear();

    //FORCE

    yarp::os::Bottle* b = pForcePort->read(false);
    if(!b)
    {
        printf("No force yet\n");
    }
    printf("El parámetro del sensor de fuerza es %s\n", b->toString().c_str());
    for(size_t i=0; i<b->size(); i++)
    {
        observation.push_back( b->get(i).asDouble() );
        //std(observation[i]);
    }

    //POSITION

    yarp::os::Bottle cmd,res;
    cmd.addString("world");
    cmd.addString("whereis");
    cmd.addString("tcp");
    cmd.addString("rightArm");
    pRpcClientWorld->write(cmd,res);
    /*printf("El parámetro de posicion es %s\n", res.toString().c_str());
    for(size_t i=0; i<res.size(); i++)
    {
        observation.push_back( res.get(i).asDouble() );
        //std(observation[i]);
    }*/
    yarp::os::Bottle* pos = res.get(0).asList();
    printf("El parámetro de posicion es %s\n", pos->toString().c_str());
    for(size_t i=0; i<pos->size(); i++)
    {
        observation.push_back( pos->get(i).asDouble() );
        //std(observation[i]);
    }

    //P:Npaint=0;
    //P:yarp::os::Time::delay(DEFAULT_DELAY_S);
    //P:yarp::os::Bottle cmd2,res2;
    //P:cmd2.addString("get");
    //P:pRpcClient->write(cmd2,res2);
    //P:for(int i=0;i<res2.size();i++)
    //P:{
    //P:    if ( res2.get(i).asInt() || psqFeatures->operator [](i) )  // logic OR;
    //P:        Npaint ++;
    //P:}

    //********************************FITNESS CALCULATION STEP******************************************************//

    //Fitness of the actual point= percentage of the wall painted

    //P:percentage=(Npaint/NSQUARES)*100;

    //The fit is the L2 norm between the current features, and the t+1 feature environment.
    double fit;
    printf("EL TIME STEP ES EL SIGUIENTE:: %d \n",timeStep);
    //P:printf("El percentage es:: %f", percentage);
    //P:printf("El Consta target es:: %f \n", Const_target[timeStep+1]);
    //fit=sqrt(pow((percentage-Const_target[timeStep+1]),2)); //The fit is the euclidean distance between current feature and t+1. Since 1 dimension euclidean distance equals difference.

    for(int i=0;i<NFEATURES;i++){
        double aux_fit,aux_elem;
        aux_elem=observation[i]-target[timeStep][i];
        aux_fit=aux_elem*aux_elem;
        fit=fit+aux_fit;
    }

    fit=sqrt(fit);

    //featureTrajectories->compare(attempVectforSimpleDiscrepancy,fit);

    cout << std::endl << " fit: " << fit << " ";

    //GOING BACK TO INIT POSITION
    std::vector<double> dEncRaw2(6,0);  // NUM_MOTORS
    //Actually move the robot
    mentalPositionControl->positionMove(dEncRaw2.data());

    return fit;
}

/************************************************************************/

void CgdaIronFitnessFunction::individualExecution(vector<double> results){

    //GOAL: Execute the obtained values to obtain the executed trajectory

    //********************************EXECUTION STEP****************************************************************//

    std::vector<double> dEncRaw(6);  // NUM_MOTORS

    dEncRaw[0] = results[0];  // simple
    dEncRaw[1] = -results[1];  // simple
    dEncRaw[3] = results[2];  // simple

    dEncRaw[4] = 45;

    mentalPositionControl->positionMove(dEncRaw.data());

    //********************************FINAL OBSERVATION STEP********************************************************//

    //Obtain the actual state of the feature environment.

    std::vector<double> observation;

    //FORCE

    yarp::os::Bottle* b = pForcePort->read(false);
    if(!b)
    {
        printf("No force yet\n");
    }
    printf("El parámetro del sensor de fuerza es %s\n", b->toString().c_str());
    for(size_t i=0; i<b->size(); i++)
    {
        observation.push_back( b->get(i).asDouble() );
        //std(observation[i]);
    }

    //POSITION

    yarp::os::Bottle cmd,res;
    cmd.addString("world");
    cmd.addString("whereis");
    cmd.addString("tcp");
    cmd.addString("rightArm");
    pRpcClientWorld->write(cmd,res);
    /*printf("El parámetro de posicion es %s\n", res.toString().c_str());
    for(size_t i=0; i<res.size(); i++)
    {
        observation.push_back( res.get(i).asDouble() );
        //std(observation[i]);
    }*/
    yarp::os::Bottle* pos = res.get(0).asList();
    printf("El parámetro de posicion es %s\n", pos->toString().c_str());
    for(size_t i=0; i<pos->size(); i++)
    {
        observation.push_back( pos->get(i).asDouble() );
        //std(observation[i]);
    }

    //P:yarp::os::Time::delay(DEFAULT_DELAY_S);
    //yarp::os::Bottle cmd,res;
    //P:cmd.addString("get");
    //P:pRpcClient->write(cmd,res);
    //P:printf("got: %s\n",res.toString().c_str());
    //P:for(int i=0;i<res.size();i++)
    //P:{
        //std::cout << "past: ";
        //std::cout << psqFeatures->operator [](i);
        //std::cout << " present: ";
        //P:psqFeatures->operator [](i) |= res.get(i).asInt();  // logic OR
        //std::cout << psqFeatures->operator [](i);
        //std::cout << std::endl;
    //P:}

    //********************************MEMORY UPDATE STEP*******************************************************************//

    std::ofstream myfile1;
    myfile1.open("memoryOET.txt", std::ios_base::out );
    if (myfile1.is_open()){
        for(int i=0;i<observation.size();i++)
        {
            myfile1<<observation[i];
            //myfile1<<"1 ";
            //myfile1<< psqFeatures->operator[](i) << " ";
            //P myfile1<< psqFeatures->operator [](i);
            //Pmyfile1<< " ";
            //std::cout<<psqFeatures->operator[](i) << " ";
            //Pstd::cout<< psqFeatures->operator [](i);
            //Pstd::cout<< " ";
        }
        std::cout<<std::endl;
        //myfile1<<bestInd[0]->fitness->getValue()<<std::endl; //Fitness
    }
    myfile1.close();

    //********************************RESET STEP*******************************************************************//
    //-- Move the mental robot to 0 so env can be reset
    std::vector<double> dEncRaw2(6,0);  // NUM_MOTORS
    mentalPositionControl->positionMove(dEncRaw2.data());
    //-- Reset the wall
    //P:yarp::os::Bottle cmd3,res3;
    //P:cmd3.addString("reset");
    //P:pRpcClient->write(cmd3,res3);

}

/************************************************************************/

} // namespace teo
<commit_msg>Added target<commit_after>// -*- mode:C++; tab-width:3; c-basic-offset:4; indent-tabs-mode:nil -*-

//Copyright: Universidad Carlos III de Madrid (C) 2016
//Authors: jgvictores, raulfdzbis, smorante

#include "CgdaIronFitnessFunction.hpp"

#define NTPOINTS 17
#define NFEATURES 6
#define NSQUARES 16

namespace teo
{

/************************************************************************/

void CgdaIronFitnessFunction::registerParameters(StateP state) {
	state->getRegistry()->registerEntry("function", (voidP) (new uint(1)), ECF::UINT);
}

/************************************************************************/

bool CgdaIronFitnessFunction::initialize(StateP state) {

    voidP sptr = state->getRegistry()->getEntry("function"); // get parameter value

	return true;
}

/************************************************************************/

FitnessP CgdaIronFitnessFunction::evaluate(IndividualP individual) {
    // Evaluation creates a new fitness object using a smart pointer
	// in our case, we try to minimize the function value, so we use FitnessMin fitness (for minimization problems)
	FitnessP fitness (new FitnessMin);

	// we define FloatingPoint as the only genotype (in the configuration file)
	FloatingPoint::FloatingPoint* gen = (FloatingPoint::FloatingPoint*) individual->getGenotype().get();

	// we implement the fitness function 'as is', without any translation
	// the number of variables is read from the genotype itself (size of 'realValue' vactor)

    double value =0;
    value= getCustomFitness(gen->realValue);
    fitness->setValue(value);
    return fitness;
}

/************************************************************************/

double CgdaIronFitnessFunction::getCustomFitness(vector <double> genPoints){

    //***********************Define the generalized feature trajectory**********************************************//

    //std::vector<std::vector<double>> target;
    double target[NFEATURES][NTPOINTS] = {
        {0.272805, -0.500201, 0.012808, -2.705315, -1.320802, 5.775318},
        {0.272620, -0.502092, 0.012907, -2.733236, -1.338366, 5.918067},
        {0.266961, -0.508060, -0.000334, -2.957992, -2.483874, 8.253265},
        {0.251811, -0.514240, -0.034490, -0.639683, -4.632288, 15.243059},
        {0.238970, -0.514431, -0.067436, 2.434867, 2.338527, -6.968969},
        {0.275419, -0.523437, -0.045262, 5.214250, 4.780977, -30.054635},
        {0.319814, -0.541889, -0.003238, -5.554522, 0.992935, -11.918344},
        {0.334939, -0.561616, 0.015075, -2.510248, -1.748680, -1.851854},
        {0.340740, -0.560490, 0.019368, -2.510248, -1.748680, -1.851854}
    };

//    int a[3][4] = {
//       {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
//       {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
//       {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
//    };

    //This is sqFeatures

    //target.push_back(feature1T1,feature2T2,feature3T3...);

    //*****************************************OBSERVATION STEP*****************************************************//

    std::vector<double> observation;

    //READ FROM PsqFeatures
    for(int i=0;i<psqFeatures->size();i++)
    {
        observation.push_back(psqFeatures->operator [](i));
    }

    //Obtain TEO state
    //P:yarp::os::Bottle cmd3,res3;
    //P:cmd3.addString("reset");
    //P:pRpcClient->write(cmd3,res3);

    //P:double percentage;
    //P:double Npaint=0;

    //P:for(int i=0;i<psqFeatures->size();i++)
    //P:{
    //P:    Npaint += psqFeatures->operator [](i);
    //P: }

    //Percentage of the wall painted before evolution
    //P:printf("EL NPAINT ES::::::: %f \n",Npaint);
    //P:percentage=(Npaint/NSQUARES)*100;
    //P:printf("EL PERCENTAGE ES::::::: %f \n",percentage);

    //***************************************LOCALIZATION STEP******************************************************//

    //Serch the timeStep where we are (LOCALIZATION STEP)
    int timeStep;
    double diff=1000000;
    for(int i=0;i<NFEATURES;i++){
        double aux_dist=0;
        double aux_elem;
        for(int j=0;j<NTPOINTS;j++){ //We give priority to the elements at the last positions
            aux_elem=observation[i]-target[i][j];
            aux_elem=aux_elem*aux_elem;
            aux_dist=aux_dist+aux_elem;
        }
        //printf("Percentage: %d \n",percentage);
        //printf("Target: %d \n", Const_target[i]);
        //P:diff_aux=percentage-Const_target[i];

        //P:diff_aux=diff_aux*diff_aux;
        //P: diff_aux=sqrt(diff_aux);

        aux_dist=sqrt(aux_dist);

        if(aux_dist<diff){
            timeStep=i;
            diff=aux_dist;
            //printf("i -> %d", i);
            //printf("Time Step %d \n",timeStep);

        }
    }

    //********************************SIMULATED EXECUTION STEP******************************************************//

    //Set new positions of the robot using dEncRaw
    std::vector<double> dEncRaw(6);  // NUM_MOTORS
    dEncRaw[0] = genPoints[0];  // simple
    dEncRaw[1] = -genPoints[1];  // simple
    dEncRaw[3] = genPoints[2];  // simple

    dEncRaw[4] = 45; //TODO:This must be changed for IRON

    //Actually move the robot
    mentalPositionControl->positionMove(dEncRaw.data());

    //********************************SECOND OBSERVATION STEP*******************************************************//

    observation.clear();

    //FORCE

    yarp::os::Bottle* b = pForcePort->read(false);
    if(!b)
    {
        printf("No force yet\n");
    }
    printf("El parámetro del sensor de fuerza es %s\n", b->toString().c_str());
    for(size_t i=0; i<b->size(); i++)
    {
        observation.push_back( b->get(i).asDouble() );
        //std(observation[i]);
    }

    //POSITION

    yarp::os::Bottle cmd,res;
    cmd.addString("world");
    cmd.addString("whereis");
    cmd.addString("tcp");
    cmd.addString("rightArm");
    pRpcClientWorld->write(cmd,res);
    /*printf("El parámetro de posicion es %s\n", res.toString().c_str());
    for(size_t i=0; i<res.size(); i++)
    {
        observation.push_back( res.get(i).asDouble() );
        //std(observation[i]);
    }*/
    yarp::os::Bottle* pos = res.get(0).asList();
    printf("El parámetro de posicion es %s\n", pos->toString().c_str());
    for(size_t i=0; i<pos->size(); i++)
    {
        observation.push_back( pos->get(i).asDouble() );
        //std(observation[i]);
    }

    //P:Npaint=0;
    //P:yarp::os::Time::delay(DEFAULT_DELAY_S);
    //P:yarp::os::Bottle cmd2,res2;
    //P:cmd2.addString("get");
    //P:pRpcClient->write(cmd2,res2);
    //P:for(int i=0;i<res2.size();i++)
    //P:{
    //P:    if ( res2.get(i).asInt() || psqFeatures->operator [](i) )  // logic OR;
    //P:        Npaint ++;
    //P:}

    //********************************FITNESS CALCULATION STEP******************************************************//

    //Fitness of the actual point= percentage of the wall painted

    //P:percentage=(Npaint/NSQUARES)*100;

    //The fit is the L2 norm between the current features, and the t+1 feature environment.
    double fit;
    printf("EL TIME STEP ES EL SIGUIENTE:: %d \n",timeStep);
    //P:printf("El percentage es:: %f", percentage);
    //P:printf("El Consta target es:: %f \n", Const_target[timeStep+1]);
    //fit=sqrt(pow((percentage-Const_target[timeStep+1]),2)); //The fit is the euclidean distance between current feature and t+1. Since 1 dimension euclidean distance equals difference.

    for(int i=0;i<NFEATURES;i++){
        double aux_fit,aux_elem;
        aux_elem=observation[i]-target[timeStep][i];
        aux_fit=aux_elem*aux_elem;
        fit=fit+aux_fit;
    }

    fit=sqrt(fit);

    //featureTrajectories->compare(attempVectforSimpleDiscrepancy,fit);

    cout << std::endl << " fit: " << fit << " ";

    //GOING BACK TO INIT POSITION
    std::vector<double> dEncRaw2(6,0);  // NUM_MOTORS
    //Actually move the robot
    mentalPositionControl->positionMove(dEncRaw2.data());

    return fit;
}

/************************************************************************/

void CgdaIronFitnessFunction::individualExecution(vector<double> results){

    //GOAL: Execute the obtained values to obtain the executed trajectory

    //********************************EXECUTION STEP****************************************************************//

    std::vector<double> dEncRaw(6);  // NUM_MOTORS

    dEncRaw[0] = results[0];  // simple
    dEncRaw[1] = -results[1];  // simple
    dEncRaw[3] = results[2];  // simple

    dEncRaw[4] = 45;

    mentalPositionControl->positionMove(dEncRaw.data());

    //********************************FINAL OBSERVATION STEP********************************************************//

    //Obtain the actual state of the feature environment.

    std::vector<double> observation;

    //FORCE

    yarp::os::Bottle* b = pForcePort->read(false);
    if(!b)
    {
        printf("No force yet\n");
    }
    printf("El parámetro del sensor de fuerza es %s\n", b->toString().c_str());
    for(size_t i=0; i<b->size(); i++)
    {
        observation.push_back( b->get(i).asDouble() );
        //std(observation[i]);
    }

    //POSITION

    yarp::os::Bottle cmd,res;
    cmd.addString("world");
    cmd.addString("whereis");
    cmd.addString("tcp");
    cmd.addString("rightArm");
    pRpcClientWorld->write(cmd,res);
    /*printf("El parámetro de posicion es %s\n", res.toString().c_str());
    for(size_t i=0; i<res.size(); i++)
    {
        observation.push_back( res.get(i).asDouble() );
        //std(observation[i]);
    }*/
    yarp::os::Bottle* pos = res.get(0).asList();
    printf("El parámetro de posicion es %s\n", pos->toString().c_str());
    for(size_t i=0; i<pos->size(); i++)
    {
        observation.push_back( pos->get(i).asDouble() );
        //std(observation[i]);
    }

    //P:yarp::os::Time::delay(DEFAULT_DELAY_S);
    //yarp::os::Bottle cmd,res;
    //P:cmd.addString("get");
    //P:pRpcClient->write(cmd,res);
    //P:printf("got: %s\n",res.toString().c_str());
    //P:for(int i=0;i<res.size();i++)
    //P:{
        //std::cout << "past: ";
        //std::cout << psqFeatures->operator [](i);
        //std::cout << " present: ";
        //P:psqFeatures->operator [](i) |= res.get(i).asInt();  // logic OR
        //std::cout << psqFeatures->operator [](i);
        //std::cout << std::endl;
    //P:}

    //********************************MEMORY UPDATE STEP*******************************************************************//

    std::ofstream myfile1;
    myfile1.open("memoryOET.txt", std::ios_base::out );
    if (myfile1.is_open()){
        for(int i=0;i<observation.size();i++)
        {
            myfile1<<observation[i];
            //myfile1<<"1 ";
            //myfile1<< psqFeatures->operator[](i) << " ";
            //P myfile1<< psqFeatures->operator [](i);
            //Pmyfile1<< " ";
            //std::cout<<psqFeatures->operator[](i) << " ";
            //Pstd::cout<< psqFeatures->operator [](i);
            //Pstd::cout<< " ";
        }
        std::cout<<std::endl;
        //myfile1<<bestInd[0]->fitness->getValue()<<std::endl; //Fitness
    }
    myfile1.close();

    //********************************RESET STEP*******************************************************************//
    //-- Move the mental robot to 0 so env can be reset
    std::vector<double> dEncRaw2(6,0);  // NUM_MOTORS
    mentalPositionControl->positionMove(dEncRaw2.data());
    //-- Reset the wall
    //P:yarp::os::Bottle cmd3,res3;
    //P:cmd3.addString("reset");
    //P:pRpcClient->write(cmd3,res3);

}

/************************************************************************/

} // namespace teo
<|endoftext|>


<commit_before>#include <Python.h>
//For Travis
#include <moduleobject.h>const_cast<size_t>

#include "reformulation.h"

using namespace std;

static PyObject *
reformulation_init(PyObject *self, PyObject *args)
{
  (void)self;
  if (!PyArg_ParseTuple(args, ""))
        return NULL;
  if(init())
    return Py_True;
  else
    return Py_False;
}

static PyObject *
reformulation_save(PyObject *self, PyObject *args)
{
  (void)self;
  if (!PyArg_ParseTuple(args, ""))
        return NULL;
  save();
  return Py_True;
}

static PyObject *
reformulation_setDelta(PyObject *self, PyObject *args)
{
  (void)self;
  float delta;
  if (!PyArg_ParseTuple(args, "f",&delta))
        return NULL;
  setLearningprecision(delta);
  return Py_True;
}

static PyObject *
reformulation_reformulation(PyObject *self, PyObject *args)
{
  (void)self;
  const char *entry;
  if (!PyArg_ParseTuple(args, "s",&entry))
        return NULL;
  string req=entry;
  //delete entry;
  return PyUnicode_FromString(reformulation(req).c_str());
}

static PyObject *
reformulation_testtag(PyObject *self, PyObject *args)
{
  (void)self;
  const char *entry;
  if (!PyArg_ParseTuple(args, "s",&entry))
        return NULL;
  string req=entry;
  string res=testtag(req);
  //delete entry;
  return PyUnicode_FromString(res.c_str());
}

/*static PyObject *
reformulation_traincompact(PyObject *self, PyObject *args)
{
  if (!PyArg_ParseTuple(args, ""))
        return NULL;

  trainer.trainCompact();
  return Py_True;
}

static PyObject *
reformulation_trainuncompact(PyObject *self, PyObject *args)
{
  if (!PyArg_ParseTuple(args, ""))
        return NULL;

  trainer.trainUncompact();
  return Py_True;
}

static PyObject *
reformulation_trainword(PyObject *self, PyObject *args)
{
  const char *entry;
  if (!PyArg_ParseTuple(args, "",&entry))
        return NULL;

  string req=entry;
  //delete entry;
  trainer.trainWord(req);
  return Py_True;
}*/

struct module_state {
    PyObject *error;
};

#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))

static PyObject *
error_out(PyObject *m) {
    struct module_state *st = GETSTATE(m);
    PyErr_SetString(st->error, "something bad happened");
    return NULL;
}

static PyMethodDef reformulation_methods[] = {
    {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},
    {"init",  reformulation_init, METH_VARARGS,"First method you should call."},
    {"save",  reformulation_save, METH_VARARGS,"Saving is important."},
    {"setDelta",  reformulation_setDelta, METH_VARARGS,"Set delta factor for uncompact."},
    {"reformule",  reformulation_reformulation, METH_VARARGS,"Reformulate a request tree."},
    {"testtag",  reformulation_testtag, METH_VARARGS,"Test tag."},
    //{"trainCompact",  reformulation_traincompact, METH_VARARGS,"Train function Compact"},
    //{"trainUncompact",  reformulation_trainuncompact, METH_VARARGS,"Train function Uncompact"},
    //{"trainWord",  reformulation_trainword, METH_VARARGS,"Train a word placement"},
    {NULL, NULL, 0, NULL}
};

static int reformulation_traverse(PyObject *m, visitproc visit, void *arg) {
    Py_VISIT(GETSTATE(m)->error);
    return 0;
}

static int reformulation_clear(PyObject *m) {
    Py_CLEAR(GETSTATE(m)->error);
    return 0;
}

static struct PyModuleDef moduledef = {
        PyModuleDef_HEAD_INIT,
        "reformulation",
        NULL,
        sizeof(struct module_state),
        reformulation_methods,
        NULL,
        reformulation_traverse,
        reformulation_clear,
        NULL
};

//PyObject *
PyMODINIT_FUNC
PyInit_libreformulation(void)

{
    PyObject *module = PyModule_Create(&moduledef);

    if (module == NULL)
        return NULL;
    struct module_state *st = GETSTATE(module);

    st->error = PyErr_NewException("reformulation.Error", NULL, NULL);
    if (st->error == NULL) {
        Py_DECREF(module);
        return NULL;
    }

    return module;
}

<commit_msg>Travis<commit_after>#include <Python.h>
//For Travis
#include <moduleobject.h>

#include "reformulation.h"

using namespace std;

static PyObject *
reformulation_init(PyObject *self, PyObject *args)
{
  (void)self;
  if (!PyArg_ParseTuple(args, ""))
        return NULL;
  if(init())
    return Py_True;
  else
    return Py_False;
}

static PyObject *
reformulation_save(PyObject *self, PyObject *args)
{
  (void)self;
  if (!PyArg_ParseTuple(args, ""))
        return NULL;
  save();
  return Py_True;
}

static PyObject *
reformulation_setDelta(PyObject *self, PyObject *args)
{
  (void)self;
  float delta;
  if (!PyArg_ParseTuple(args, "f",&delta))
        return NULL;
  setLearningprecision(delta);
  return Py_True;
}

static PyObject *
reformulation_reformulation(PyObject *self, PyObject *args)
{
  (void)self;
  const char *entry;
  if (!PyArg_ParseTuple(args, "s",&entry))
        return NULL;
  string req=entry;
  //delete entry;
  return PyUnicode_FromString(reformulation(req).c_str());
}

static PyObject *
reformulation_testtag(PyObject *self, PyObject *args)
{
  (void)self;
  const char *entry;
  if (!PyArg_ParseTuple(args, "s",&entry))
        return NULL;
  string req=entry;
  string res=testtag(req);
  //delete entry;
  return PyUnicode_FromString(res.c_str());
}

/*static PyObject *
reformulation_traincompact(PyObject *self, PyObject *args)
{
  if (!PyArg_ParseTuple(args, ""))
        return NULL;

  trainer.trainCompact();
  return Py_True;
}

static PyObject *
reformulation_trainuncompact(PyObject *self, PyObject *args)
{
  if (!PyArg_ParseTuple(args, ""))
        return NULL;

  trainer.trainUncompact();
  return Py_True;
}

static PyObject *
reformulation_trainword(PyObject *self, PyObject *args)
{
  const char *entry;
  if (!PyArg_ParseTuple(args, "",&entry))
        return NULL;

  string req=entry;
  //delete entry;
  trainer.trainWord(req);
  return Py_True;
}*/

struct module_state {
    PyObject *error;
};

#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))

static PyObject *
error_out(PyObject *m) {
    struct module_state *st = GETSTATE(m);
    PyErr_SetString(st->error, "something bad happened");
    return NULL;
}

static PyMethodDef reformulation_methods[] = {
    {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},
    {"init",  reformulation_init, METH_VARARGS,"First method you should call."},
    {"save",  reformulation_save, METH_VARARGS,"Saving is important."},
    {"setDelta",  reformulation_setDelta, METH_VARARGS,"Set delta factor for uncompact."},
    {"reformule",  reformulation_reformulation, METH_VARARGS,"Reformulate a request tree."},
    {"testtag",  reformulation_testtag, METH_VARARGS,"Test tag."},
    //{"trainCompact",  reformulation_traincompact, METH_VARARGS,"Train function Compact"},
    //{"trainUncompact",  reformulation_trainuncompact, METH_VARARGS,"Train function Uncompact"},
    //{"trainWord",  reformulation_trainword, METH_VARARGS,"Train a word placement"},
    {NULL, NULL, 0, NULL}
};

static int reformulation_traverse(PyObject *m, visitproc visit, void *arg) {
    Py_VISIT(GETSTATE(m)->error);
    return 0;
}

static int reformulation_clear(PyObject *m) {
    Py_CLEAR(GETSTATE(m)->error);
    return 0;
}

static struct PyModuleDef moduledef = {
        PyModuleDef_HEAD_INIT,
        "reformulation",
        NULL,
        sizeof(struct module_state),
        reformulation_methods,
        NULL,
        reformulation_traverse,
        reformulation_clear,
        NULL
};

//PyObject *
PyMODINIT_FUNC
PyInit_libreformulation(void)

{
    PyObject *module = PyModule_Create(&moduledef);

    if (module == NULL)
        return NULL;
    struct module_state *st = GETSTATE(module);

    st->error = PyErr_NewException("reformulation.Error", NULL, NULL);
    if (st->error == NULL) {
        Py_DECREF(module);
        return NULL;
    }

    return module;
}

<|endoftext|>


<commit_before>//===--- Backend.cpp - Interface to LLVM backend technologies -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ASTConsumers.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/Compiler.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include <fstream> // FIXME: Remove

using namespace clang;
using namespace llvm;

namespace {
  class VISIBILITY_HIDDEN BackendConsumer  : public ASTConsumer {
    BackendAction Action;
    const std::string &InputFile;
    std::string OutputFile;
    llvm::OwningPtr<CodeGenerator> Gen;

    llvm::Module *TheModule;
    llvm::TargetData *TheTargetData;
    llvm::raw_ostream *AsmOutStream;
    std::ostream *AsmStdOutStream;

    mutable FunctionPassManager *CodeGenPasses;
    mutable PassManager *PerModulePasses;
    mutable FunctionPassManager *PerFunctionPasses;

    FunctionPassManager *getCodeGenPasses() const;
    PassManager *getPerModulePasses() const;
    FunctionPassManager *getPerFunctionPasses() const;

    void CreatePasses();

    /// AddEmitPasses - Add passes necessary to emit assembly or LLVM
    /// IR.
    ///
    /// \arg Fast - Whether "fast" native compilation should be
    /// used. This implies local register allocation and fast
    /// instruction selection.
    /// \return True on success. On failure \arg Error will be set to
    /// a user readable error message.
    bool AddEmitPasses(bool Fast, std::string &Error);

    void EmitAssembly();

  public:
    BackendConsumer(BackendAction action, Diagnostic &Diags,
                    const LangOptions &Features,
                    const std::string& infile, const std::string& outfile,
                    bool GenerateDebugInfo)  :
      Action(action),
      InputFile(infile),
      OutputFile(outfile),
      Gen(CreateLLVMCodeGen(Diags, Features, InputFile, GenerateDebugInfo)),
      TheModule(0), TheTargetData(0),
      AsmOutStream(0), AsmStdOutStream(0),
      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}

    ~BackendConsumer() {
      // FIXME: Move out of destructor.
      EmitAssembly();

      if (AsmStdOutStream != llvm::cout.stream())
        delete AsmStdOutStream;
      delete AsmOutStream;
      delete TheTargetData;
      delete TheModule;
      delete CodeGenPasses;
      delete PerModulePasses;
      delete PerFunctionPasses;
    }

    virtual void InitializeTU(TranslationUnit& TU) {
      Gen->InitializeTU(TU);

      TheModule = Gen->GetModule();
      TheTargetData =
        new llvm::TargetData(TU.getContext().Target.getTargetDescription());
    }

    virtual void HandleTopLevelDecl(Decl *D) {
      Gen->HandleTopLevelDecl(D);
    }

    virtual void HandleTranslationUnit(TranslationUnit& TU) {
      Gen->HandleTranslationUnit(TU);
    }

    virtual void HandleTagDeclDefinition(TagDecl *D) {
      Gen->HandleTagDeclDefinition(D);
    }
  };
}

FunctionPassManager *BackendConsumer::getCodeGenPasses() const {
  if (!CodeGenPasses) {
    CodeGenPasses =
      new FunctionPassManager(new ExistingModuleProvider(TheModule));
    CodeGenPasses->add(new TargetData(*TheTargetData));
  }

  return CodeGenPasses;
}

PassManager *BackendConsumer::getPerModulePasses() const {
  if (!PerModulePasses) {
    PerModulePasses = new PassManager();
    PerModulePasses->add(new TargetData(*TheTargetData));
  }

  return PerModulePasses;
}

FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
  if (!PerFunctionPasses) {
    PerFunctionPasses =
      new FunctionPassManager(new ExistingModuleProvider(TheModule));
    PerFunctionPasses->add(new TargetData(*TheTargetData));
  }

  return PerFunctionPasses;
}

bool BackendConsumer::AddEmitPasses(bool Fast, std::string &Error) {
  // Create the TargetMachine for generating code.
  const TargetMachineRegistry::entry *TME =
    TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Error);
  if (!TME) {
    Error = std::string("Unable to get target machine: ") + Error;
    return false;
  }

  // FIXME: Support features?
  std::string FeatureStr;
  TargetMachine *TM = TME->CtorFn(*TheModule, FeatureStr);

  // Set register scheduler & allocation policy.
  RegisterScheduler::setDefault(createDefaultScheduler);
  RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator :
                               createLinearScanRegisterAllocator);

  // This is ridiculous.
  // FIXME: These aren't being release for now. I'm just going to fix
  // things to use raw_ostream instead.
  if (OutputFile == "-" || (InputFile == "-" && OutputFile.empty())) {
    AsmStdOutStream = llvm::cout.stream();
    AsmOutStream = new raw_stdout_ostream();
    sys::Program::ChangeStdoutToBinary();
  } else {
    if (OutputFile.empty()) {
      llvm::sys::Path Path(InputFile);
      Path.eraseSuffix();
      if (Action == Backend_EmitBC) {
        Path.appendSuffix("bc");
      } else if (Action == Backend_EmitLL) {
        Path.appendSuffix("ll");
      } else {
        Path.appendSuffix("s");
      }
      OutputFile = Path.toString();
    }

    // FIXME: raw_fd_ostream should specify its non-error condition
    // better.
    Error = "";
    AsmStdOutStream = new std::ofstream(OutputFile.c_str(),
                                        (std::ios_base::binary |
                                         std::ios_base::out));
    AsmOutStream = new raw_os_ostream(*AsmStdOutStream);
    if (!Error.empty())
      return false;
  }

  if (Action == Backend_EmitBC) {
    getPerModulePasses()->add(CreateBitcodeWriterPass(*AsmStdOutStream));
  } else if (Action == Backend_EmitLL) {
    getPerModulePasses()->add(createPrintModulePass(AsmOutStream));
  } else {
    // From llvm-gcc:
    // If there are passes we have to run on the entire module, we do codegen
    // as a separate "pass" after that happens.
    // FIXME: This is disabled right now until bugs can be worked out.  Reenable
    // this for fast -O0 compiles!
    FunctionPassManager *PM = getCodeGenPasses();

    // Normal mode, emit a .s file by running the code generator.
    // Note, this also adds codegenerator level optimization passes.
    switch (TM->addPassesToEmitFile(*PM, *AsmOutStream,
                                    TargetMachine::AssemblyFile, Fast)) {
    default:
    case FileModel::Error:
      Error = "Unable to interface with target machine!\n";
      return false;
    case FileModel::AsmFile:
      break;
    }

    if (TM->addPassesToEmitFileFinish(*CodeGenPasses, 0, Fast)) {
      Error = "Unable to interface with target machine!\n";
      return false;
    }
  }

  return true;
}

void BackendConsumer::CreatePasses() {

}

/// EmitAssembly - Handle interaction with LLVM backend to generate
/// actual machine code.
void BackendConsumer::EmitAssembly() {
  // Silently ignore if we weren't initialized for some reason.
  if (!TheModule || !TheTargetData)
    return;

  bool Optimize = false; // FIXME

  // Make sure IR generation is happy with the module.
  // FIXME: Release this.
  Module *M = Gen->ReleaseModule();
  if (!M) {
    TheModule = 0;
    return;
  }

  assert(TheModule == M && "Unexpected module change during IR generation");

  CreatePasses();

  std::string Error;
  if (!AddEmitPasses(!Optimize, Error)) {
    // FIXME: Don't fail this way.
    llvm::cerr << "ERROR: " << Error << "\n";
    ::exit(1);
  }

  // Run passes. For now we do all passes at once, but eventually we
  // would like to have the option of streaming code generation.

  if (PerFunctionPasses) {
    PerFunctionPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        PerFunctionPasses->run(*I);
    PerFunctionPasses->doFinalization();
  }

  if (PerModulePasses)
    PerModulePasses->run(*M);

  if (CodeGenPasses) {
    CodeGenPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        CodeGenPasses->run(*I);
    CodeGenPasses->doFinalization();
  }
}

ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
                                          Diagnostic &Diags,
                                          const LangOptions &Features,
                                          const std::string& InFile,
                                          const std::string& OutFile,
                                          bool GenerateDebugInfo) {
  return new BackendConsumer(Action, Diags, Features, InFile, OutFile,
                             GenerateDebugInfo);
}
<commit_msg>[LLVM up] Get rid of std::ostream usage from Backend.cpp<commit_after>//===--- Backend.cpp - Interface to LLVM backend technologies -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ASTConsumers.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Compiler.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include <fstream> // FIXME: Remove

using namespace clang;
using namespace llvm;

namespace {
  class VISIBILITY_HIDDEN BackendConsumer  : public ASTConsumer {
    BackendAction Action;
    const std::string &InputFile;
    std::string OutputFile;
    llvm::OwningPtr<CodeGenerator> Gen;

    llvm::Module *TheModule;
    llvm::TargetData *TheTargetData;
    llvm::raw_ostream *AsmOutStream;

    mutable FunctionPassManager *CodeGenPasses;
    mutable PassManager *PerModulePasses;
    mutable FunctionPassManager *PerFunctionPasses;

    FunctionPassManager *getCodeGenPasses() const;
    PassManager *getPerModulePasses() const;
    FunctionPassManager *getPerFunctionPasses() const;

    void CreatePasses();

    /// AddEmitPasses - Add passes necessary to emit assembly or LLVM
    /// IR.
    ///
    /// \arg Fast - Whether "fast" native compilation should be
    /// used. This implies local register allocation and fast
    /// instruction selection.
    /// \return True on success. On failure \arg Error will be set to
    /// a user readable error message.
    bool AddEmitPasses(bool Fast, std::string &Error);

    void EmitAssembly();

  public:
    BackendConsumer(BackendAction action, Diagnostic &Diags,
                    const LangOptions &Features,
                    const std::string& infile, const std::string& outfile,
                    bool GenerateDebugInfo)  :
      Action(action),
      InputFile(infile),
      OutputFile(outfile),
      Gen(CreateLLVMCodeGen(Diags, Features, InputFile, GenerateDebugInfo)),
      TheModule(0), TheTargetData(0), AsmOutStream(0),
      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}

    ~BackendConsumer() {
      // FIXME: Move out of destructor.
      EmitAssembly();

      delete AsmOutStream;
      delete TheTargetData;
      delete TheModule;
      delete CodeGenPasses;
      delete PerModulePasses;
      delete PerFunctionPasses;
    }

    virtual void InitializeTU(TranslationUnit& TU) {
      Gen->InitializeTU(TU);

      TheModule = Gen->GetModule();
      TheTargetData =
        new llvm::TargetData(TU.getContext().Target.getTargetDescription());
    }

    virtual void HandleTopLevelDecl(Decl *D) {
      Gen->HandleTopLevelDecl(D);
    }

    virtual void HandleTranslationUnit(TranslationUnit& TU) {
      Gen->HandleTranslationUnit(TU);
    }

    virtual void HandleTagDeclDefinition(TagDecl *D) {
      Gen->HandleTagDeclDefinition(D);
    }
  };
}

FunctionPassManager *BackendConsumer::getCodeGenPasses() const {
  if (!CodeGenPasses) {
    CodeGenPasses =
      new FunctionPassManager(new ExistingModuleProvider(TheModule));
    CodeGenPasses->add(new TargetData(*TheTargetData));
  }

  return CodeGenPasses;
}

PassManager *BackendConsumer::getPerModulePasses() const {
  if (!PerModulePasses) {
    PerModulePasses = new PassManager();
    PerModulePasses->add(new TargetData(*TheTargetData));
  }

  return PerModulePasses;
}

FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
  if (!PerFunctionPasses) {
    PerFunctionPasses =
      new FunctionPassManager(new ExistingModuleProvider(TheModule));
    PerFunctionPasses->add(new TargetData(*TheTargetData));
  }

  return PerFunctionPasses;
}

bool BackendConsumer::AddEmitPasses(bool Fast, std::string &Error) {
  // Create the TargetMachine for generating code.
  const TargetMachineRegistry::entry *TME =
    TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Error);
  if (!TME) {
    Error = std::string("Unable to get target machine: ") + Error;
    return false;
  }

  // FIXME: Support features?
  std::string FeatureStr;
  TargetMachine *TM = TME->CtorFn(*TheModule, FeatureStr);

  // Set register scheduler & allocation policy.
  RegisterScheduler::setDefault(createDefaultScheduler);
  RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator :
                               createLinearScanRegisterAllocator);

  if (OutputFile == "-" || (InputFile == "-" && OutputFile.empty())) {
    AsmOutStream = new raw_stdout_ostream();
    sys::Program::ChangeStdoutToBinary();
  } else {
    if (OutputFile.empty()) {
      llvm::sys::Path Path(InputFile);
      Path.eraseSuffix();
      if (Action == Backend_EmitBC) {
        Path.appendSuffix("bc");
      } else if (Action == Backend_EmitLL) {
        Path.appendSuffix("ll");
      } else {
        Path.appendSuffix("s");
      }
      OutputFile = Path.toString();
    }

    // FIXME: Should be binary.
    AsmOutStream = new raw_fd_ostream(OutputFile.c_str(), Error);
    if (!Error.empty())
      return false;
  }

  if (Action == Backend_EmitBC) {
    getPerModulePasses()->add(createBitcodeWriterPass(*AsmOutStream));
  } else if (Action == Backend_EmitLL) {
    getPerModulePasses()->add(createPrintModulePass(AsmOutStream));
  } else {
    // From llvm-gcc:
    // If there are passes we have to run on the entire module, we do codegen
    // as a separate "pass" after that happens.
    // FIXME: This is disabled right now until bugs can be worked out.  Reenable
    // this for fast -O0 compiles!
    FunctionPassManager *PM = getCodeGenPasses();

    // Normal mode, emit a .s file by running the code generator.
    // Note, this also adds codegenerator level optimization passes.
    switch (TM->addPassesToEmitFile(*PM, *AsmOutStream,
                                    TargetMachine::AssemblyFile, Fast)) {
    default:
    case FileModel::Error:
      Error = "Unable to interface with target machine!\n";
      return false;
    case FileModel::AsmFile:
      break;
    }

    if (TM->addPassesToEmitFileFinish(*CodeGenPasses, 0, Fast)) {
      Error = "Unable to interface with target machine!\n";
      return false;
    }
  }

  return true;
}

void BackendConsumer::CreatePasses() {

}

/// EmitAssembly - Handle interaction with LLVM backend to generate
/// actual machine code.
void BackendConsumer::EmitAssembly() {
  // Silently ignore if we weren't initialized for some reason.
  if (!TheModule || !TheTargetData)
    return;

  bool Optimize = false; // FIXME

  // Make sure IR generation is happy with the module.
  // FIXME: Release this.
  Module *M = Gen->ReleaseModule();
  if (!M) {
    TheModule = 0;
    return;
  }

  assert(TheModule == M && "Unexpected module change during IR generation");

  CreatePasses();

  std::string Error;
  if (!AddEmitPasses(!Optimize, Error)) {
    // FIXME: Don't fail this way.
    llvm::cerr << "ERROR: " << Error << "\n";
    ::exit(1);
  }

  // Run passes. For now we do all passes at once, but eventually we
  // would like to have the option of streaming code generation.

  if (PerFunctionPasses) {
    PerFunctionPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        PerFunctionPasses->run(*I);
    PerFunctionPasses->doFinalization();
  }

  if (PerModulePasses)
    PerModulePasses->run(*M);

  if (CodeGenPasses) {
    CodeGenPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        CodeGenPasses->run(*I);
    CodeGenPasses->doFinalization();
  }
}

ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
                                          Diagnostic &Diags,
                                          const LangOptions &Features,
                                          const std::string& InFile,
                                          const std::string& OutFile,
                                          bool GenerateDebugInfo) {
  return new BackendConsumer(Action, Diags, Features, InFile, OutFile,
                             GenerateDebugInfo);
}
<|endoftext|>