<commit_before>#pragma once
#ifndef NIFTY_MARRAY_MARRAY_HXX
#define NIFTY_MARRAY_MARRAY_HXX

#define HAVE_CPP11_INITIALIZER_LISTS
#define HAVE_CPP11_STD_ARRAY
#include <andres/marray.hxx>

namespace nifty{
namespace marray{
    using namespace andres;
}

namespace tools{

    template<class T, class COORD>
    inline void readSubarray(
        const marray::View<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        marray::View<T> & subarray
    ){

        const auto dim = array.dimension();
        std::vector<int64_t> subShape(array.dimension());
        for(auto d = 0 ; d<dim; ++d){
            subShape[d] = beginCoord[d] - endCoord[d];
        }
        subarray = array.view(beginCoord.begin(), subShape.begin());
    }

    template<class T, class COORD>
    inline void writeSubarray(
        marray::View<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        const marray::View<T> & data
    ){
        const auto dim = array.dimension();

        COORD subShape;
        for(auto d = 0 ; d<dim; ++d){
            subShape[d] = beginCoord[d] - endCoord[d];
        }
        for(int d = 0; d < dim; ++d )
            NIFTY_CHECK_OP(subShape[d],==,data.shape(d),"Shapes don't match!")
        auto subarray = array.view(beginCoord.begin(), subShape.begin());

        // for dim < 4 we can use forEachCoordinate (this only works if COORD is nifty::array::StaticArray)
        if(dim <= 4) {
            forEachCoordinate(subShape, [&](const COORD & coord){
                subarray(coord.asStdArray()) = data(coord.asStdArray());
            });
        }
        else { // otherwise use iterators
            auto itArray = subarray.begin();
            auto itData  = data.begin();
            for(; itArray != subarray.end(); ++itArray, ++itData)
                *itArray = *itData;
        }
    }

    // dummy function, because we don't lock for marrays
    template<class T, class COORD>
    inline void readSubarrayLocked(
        const marray::View<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        marray::View<T> & subarray
    ){
        readSubarray(array,beginCoord,endCoord,subarray);
    }

    template<class T, class COORD>
    inline void writeSubarrayLocked(
        marray::View<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        const marray::View<T> & data
    ){
        writeSubarray(array,beginCoord,endCoord,data);
    }
}

}

#endif
<commit_msg>Fixed bug in tools::writeSubarray<commit_after>#pragma once
#ifndef NIFTY_MARRAY_MARRAY_HXX
#define NIFTY_MARRAY_MARRAY_HXX

#define HAVE_CPP11_INITIALIZER_LISTS
#define HAVE_CPP11_STD_ARRAY
#include <andres/marray.hxx>

namespace nifty{
namespace marray{
    using namespace andres;
}

namespace tools{

    template<class T, class COORD>
    inline void readSubarray(
        const marray::View<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        marray::View<T> & subarray
    ){

        const auto dim = array.dimension();
        std::vector<int64_t> subShape(array.dimension());
        for(auto d = 0 ; d<dim; ++d){
            subShape[d] = beginCoord[d] - endCoord[d];
        }
        subarray = array.view(beginCoord.begin(), subShape.begin());
    }

    template<class T, class COORD>
    inline void writeSubarray(
        marray::View<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        const marray::View<T> & data
    ){
        const auto dim = array.dimension();

        COORD subShape;
        for(auto d = 0 ; d<dim; ++d){
            subShape[d] = endCoord[d] - beginCoord[d];
        }
        for(int d = 0; d < dim; ++d )
            NIFTY_CHECK_OP(subShape[d],==,data.shape(d),"Shapes don't match!")
        auto subarray = array.view(beginCoord.begin(), subShape.begin());

        // for dim < 4 we can use forEachCoordinate (this only works if COORD is nifty::array::StaticArray)
        if(dim <= 4) {
            forEachCoordinate(subShape, [&](const COORD & coord){
                subarray(coord.asStdArray()) = data(coord.asStdArray());
            });
        }
        else { // otherwise use iterators
            auto itArray = subarray.begin();
            auto itData  = data.begin();
            for(; itArray != subarray.end(); ++itArray, ++itData)
                *itArray = *itData;
        }
    }

    // dummy function, because we don't lock for marrays
    template<class T, class COORD>
    inline void readSubarrayLocked(
        const marray::View<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        marray::View<T> & subarray
    ){
        readSubarray(array,beginCoord,endCoord,subarray);
    }

    template<class T, class COORD>
    inline void writeSubarrayLocked(
        marray::View<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        const marray::View<T> & data
    ){
        writeSubarray(array,beginCoord,endCoord,data);
    }
}

}

#endif
<|endoftext|>


<commit_before>/**
 * \file
 * \brief ThreadControlBlockList class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-09-18
 */

#ifndef INCLUDE_DISTORTOS_SCHEDULER_THREADCONTROLBLOCKLIST_HPP_
#define INCLUDE_DISTORTOS_SCHEDULER_THREADCONTROLBLOCKLIST_HPP_

#include "distortos/scheduler/ThreadControlBlockList-types.hpp"

#include "distortos/scheduler/ThreadControlBlock.hpp"

namespace distortos
{

namespace scheduler
{

/// functor which gives descending priority order of elements on the list
struct ThreadControlBlockDescendingPriority
{
	/**
	 * \brief operator()
	 *
	 * \param [in] left is the object on the left side of comparison
	 * \param [in] right is the object on the right side of comparison
	 *
	 * \return true if left's priority is less than right's priority
	 */

	bool operator() (const ThreadControlBlockListValueType& left, const ThreadControlBlockListValueType& right)
	{
		return left.get().getPriority() < right.get().getPriority();
	}
};

/// base of ThreadControlBlockList
using ThreadControlBlockListBase = containers::SortedContainer
		<
				ThreadControlBlockListContainer,
				ThreadControlBlockDescendingPriority
		>;

/// List of ThreadControlBlock objects in descending order of priority that configures state of kept objects
class ThreadControlBlockList : private ThreadControlBlockListBase
{
public:

	/// base of ThreadControlBlockList
	using Base = ThreadControlBlockListBase;

	using typename Base::iterator;
	using typename Base::value_type;

	using Base::begin;
	using Base::empty;
	using Base::end;
	using Base::size;

	/**
	 * \brief ThreadControlBlockList's constructor
	 *
	 * \param [in] allocator is a reference to ThreadControlBlockListAllocator object used to copy-construct allocator
	 * of base container
	 * \param [in] state is the state of ThreadControlBlock objects kept in this list
	 */

	ThreadControlBlockList(const ThreadControlBlockListAllocator& allocator, const ThreadControlBlock::State state) :
			Base{allocator},
			state_{state}
	{

	}

	/**
	 * \brief ThreadControlBlockList's destructor
	 *
	 * Clears list pointers in all elements.
	 */

	~ThreadControlBlockList()
	{
		for (auto& item : *this)
			item.get().setList(nullptr);
	}

	/**
	 * \brief Wrapper for sortedEmplace()
	 *
	 * Sets list pointer, iterator and state of emplaced element.
	 *
	 * \param Args are types of argument for value_type constructor
	 *
	 * \param [in] args are arguments for value_type constructor
	 *
	 * \return iterator to emplaced element
	 */

	template<typename... Args>
	iterator sortedEmplace(Args&&... args)
	{
		const auto it = Base::sortedEmplace(std::forward<Args>(args)...);
		auto& threadControlBlock = it->get();
		threadControlBlock.setList(this);
		threadControlBlock.setIterator(it);
		threadControlBlock.setState(state_);
		return it;
	}

	/**
	 * \brief Wrapper for sortedSplice()
	 *
	 * Sets list pointer and state of transfered element.
	 *
	 * \param [in] other is the container from which the object is transfered
	 * \param [in] otherPosition is the position of the transfered object in the other container
	 */

	void sortedSplice(ThreadControlBlockList& other, const iterator otherPosition)
	{
		Base::sortedSplice(other, otherPosition);
		otherPosition->get().setList(this);
		otherPosition->get().setState(state_);
	}

private:

	/// state of ThreadControlBlock objects kept in this list
	const ThreadControlBlock::State state_;
};

}	// namespace scheduler

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SCHEDULER_THREADCONTROLBLOCKLIST_HPP_
<commit_msg>ThreadControlBlockList: sort threads using their effective priority<commit_after>/**
 * \file
 * \brief ThreadControlBlockList class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-11-01
 */

#ifndef INCLUDE_DISTORTOS_SCHEDULER_THREADCONTROLBLOCKLIST_HPP_
#define INCLUDE_DISTORTOS_SCHEDULER_THREADCONTROLBLOCKLIST_HPP_

#include "distortos/scheduler/ThreadControlBlockList-types.hpp"

#include "distortos/scheduler/ThreadControlBlock.hpp"

namespace distortos
{

namespace scheduler
{

/// functor which gives descending effective priority order of elements on the list
struct ThreadControlBlockDescendingEffectivePriority
{
	/**
	 * \brief operator()
	 *
	 * \param [in] left is the object on the left side of comparison
	 * \param [in] right is the object on the right side of comparison
	 *
	 * \return true if left's effective priority is less than right's effective priority
	 */

	bool operator() (const ThreadControlBlockListValueType& left, const ThreadControlBlockListValueType& right)
	{
		return left.get().getEffectivePriority() < right.get().getEffectivePriority();
	}
};

/// base of ThreadControlBlockList
using ThreadControlBlockListBase = containers::SortedContainer
		<
				ThreadControlBlockListContainer,
				ThreadControlBlockDescendingEffectivePriority
		>;

/// List of ThreadControlBlock objects in descending order of effective priority that configures state of kept objects
class ThreadControlBlockList : private ThreadControlBlockListBase
{
public:

	/// base of ThreadControlBlockList
	using Base = ThreadControlBlockListBase;

	using typename Base::iterator;
	using typename Base::value_type;

	using Base::begin;
	using Base::empty;
	using Base::end;
	using Base::size;

	/**
	 * \brief ThreadControlBlockList's constructor
	 *
	 * \param [in] allocator is a reference to ThreadControlBlockListAllocator object used to copy-construct allocator
	 * of base container
	 * \param [in] state is the state of ThreadControlBlock objects kept in this list
	 */

	ThreadControlBlockList(const ThreadControlBlockListAllocator& allocator, const ThreadControlBlock::State state) :
			Base{allocator},
			state_{state}
	{

	}

	/**
	 * \brief ThreadControlBlockList's destructor
	 *
	 * Clears list pointers in all elements.
	 */

	~ThreadControlBlockList()
	{
		for (auto& item : *this)
			item.get().setList(nullptr);
	}

	/**
	 * \brief Wrapper for sortedEmplace()
	 *
	 * Sets list pointer, iterator and state of emplaced element.
	 *
	 * \param Args are types of argument for value_type constructor
	 *
	 * \param [in] args are arguments for value_type constructor
	 *
	 * \return iterator to emplaced element
	 */

	template<typename... Args>
	iterator sortedEmplace(Args&&... args)
	{
		const auto it = Base::sortedEmplace(std::forward<Args>(args)...);
		auto& threadControlBlock = it->get();
		threadControlBlock.setList(this);
		threadControlBlock.setIterator(it);
		threadControlBlock.setState(state_);
		return it;
	}

	/**
	 * \brief Wrapper for sortedSplice()
	 *
	 * Sets list pointer and state of transfered element.
	 *
	 * \param [in] other is the container from which the object is transfered
	 * \param [in] otherPosition is the position of the transfered object in the other container
	 */

	void sortedSplice(ThreadControlBlockList& other, const iterator otherPosition)
	{
		Base::sortedSplice(other, otherPosition);
		otherPosition->get().setList(this);
		otherPosition->get().setState(state_);
	}

private:

	/// state of ThreadControlBlock objects kept in this list
	const ThreadControlBlock::State state_;
};

}	// namespace scheduler

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SCHEDULER_THREADCONTROLBLOCKLIST_HPP_
<|endoftext|>


<commit_before>#include "MoltresApp.h"
#include "Moose.h"
#include "AppFactory.h"
#include "ModulesApp.h"
#include "SquirrelApp.h"
#include "MooseSyntax.h"

// Kernels
#include "DelayedNeutronSource.h"
#include "ScalarTransportTimeDerivative.h"
#include "ScalarAdvectionArtDiff.h"
#include "PrecursorDecay.h"
#include "NtTimeDerivative.h"
#include "PrecursorSource.h"
#include "FissionHeatSource.h"
#include "TransientFissionHeatSource.h"
#include "INSMomentumKEpsilon.h"
#include "INSBoussinesqBodyForce.h"
#include "SigmaR.h"
#include "CoupledFissionEigenKernel.h"
#include "CoupledFissionKernel.h"
#include "SelfFissionEigenKernel.h"
#include "InScatter.h"
#include "GroupDiffusion.h"
#include "CoupledScalarAdvection.h"
#include "DivFreeCoupledScalarAdvection.h"
#include "GammaHeatSource.h"

// Boundary conditions
#include "LinLogPenaltyDirichletBC.h"
#include "VacuumConcBC.h"
#include "ConservativeAdvectionNoBCBC.h"
#include "DiffusionNoBCBC.h"
#include "ScalarAdvectionArtDiffNoBCBC.h"
#include "INSOutflowBC.h"
#include "INSSymmetryAxisBC.h"
#include "MatDiffusionFluxBC.h"
#include "CoupledScalarAdvectionNoBCBC.h"

// Materials
#include "GenericMoltresMaterial.h"
#include "CammiFuel.h"
#include "CammiModerator.h"
#include "Nusselt.h"
#include "GraphiteTwoGrpXSFunctionMaterial.h"
#include "MsreFuelTwoGrpXSFunctionMaterial.h"
#include "RoddedMaterial.h"

// Postprocessors
#include "LimitK.h"
#include "AverageFissionHeat.h"
#include "ElementL2Diff.h"
#include "DivisionPostprocessor.h"
#include "IntegralOldVariablePostprocessor.h"
#include "IntegralNewVariablePostprocessor.h"
#include "ElmIntegTotFissPostprocessor.h"
#include "ElmIntegTotFissHeatPostprocessor.h"
#include "ElmIntegTotFissNtsPostprocessor.h"

// AuxKernels
#include "FissionHeatSourceAux.h"
#include "FissionHeatSourceTransientAux.h"
#include "ModeratorHeatSourceTransientAux.h"
#include "MatDiffusionAux.h"
#include "ConstantDifferenceAux.h"

// Actions
#include "PrecursorAction.h"
#include "NtAction.h"

// DiracKernels
#include "DiracHX.h"

template <>
InputParameters
validParams<MoltresApp>()
{
  InputParameters params = validParams<MooseApp>();

  params.set<bool>("use_legacy_uo_initialization") = false;
  params.set<bool>("use_legacy_uo_aux_computation") = false;
  params.set<bool>("use_legacy_output_syntax") = false;

  return params;
}

MoltresApp::MoltresApp(InputParameters parameters) : MooseApp(parameters)
{
  Moose::registerObjects(_factory);
  ModulesApp::registerObjects(_factory);
  SquirrelApp::registerObjects(_factory);
  MoltresApp::registerObjects(_factory);

  Moose::associateSyntax(_syntax, _action_factory);
  ModulesApp::associateSyntax(_syntax, _action_factory);
  SquirrelApp::associateSyntax(_syntax, _action_factory);
  MoltresApp::associateSyntax(_syntax, _action_factory);
}

MoltresApp::~MoltresApp() {}

// External entry point for dynamic application loading
extern "C" void
MoltresApp__registerApps()
{
  MoltresApp::registerApps();
}
void
MoltresApp::registerApps()
{
  registerApp(MoltresApp);
}

// External entry point for dynamic object registration
extern "C" void
MoltresApp__registerObjects(Factory & factory)
{
  MoltresApp::registerObjects(factory);
}
void
MoltresApp::registerObjects(Factory & factory)
{
  registerKernel(DelayedNeutronSource);
  registerKernel(SigmaR);
  registerKernel(GammaHeatSource);
  registerKernel(ScalarTransportTimeDerivative);
  registerKernel(PrecursorSource);
  registerKernel(PrecursorDecay);
  registerKernel(CoupledScalarAdvection);
  registerKernel(DivFreeCoupledScalarAdvection);
  registerKernel(NtTimeDerivative);
  registerKernel(FissionHeatSource);
  registerKernel(TransientFissionHeatSource);
  registerKernel(InScatter);
  registerKernel(CoupledFissionEigenKernel);
  registerKernel(ScalarAdvectionArtDiff);
  registerKernel(CoupledFissionKernel);
  registerKernel(SelfFissionEigenKernel);
  registerKernel(INSMomentumKEpsilon);
  registerKernel(INSBoussinesqBodyForce);
  registerKernel(GroupDiffusion);
  registerBoundaryCondition(LinLogPenaltyDirichletBC);
  registerBoundaryCondition(ScalarAdvectionArtDiffNoBCBC);
  registerBoundaryCondition(VacuumConcBC);
  registerBoundaryCondition(ConservativeAdvectionNoBCBC);
  registerBoundaryCondition(DiffusionNoBCBC);
  registerBoundaryCondition(CoupledScalarAdvectionNoBCBC);
  registerBoundaryCondition(INSOutflowBC);
  registerBoundaryCondition(INSSymmetryAxisBC);
  registerBoundaryCondition(MatDiffusionFluxBC);
  registerMaterial(GenericMoltresMaterial);
  registerMaterial(CammiFuel);
  registerMaterial(CammiModerator);
  registerMaterial(Nusselt);
  registerMaterial(GraphiteTwoGrpXSFunctionMaterial);
  registerMaterial(MsreFuelTwoGrpXSFunctionMaterial);
  registerMaterial(RoddedMaterial);
  registerPostprocessor(LimitK);
  registerPostprocessor(IntegralOldVariablePostprocessor);
  registerPostprocessor(ElementL2Diff);
  registerPostprocessor(IntegralNewVariablePostprocessor);
  registerPostprocessor(DivisionPostprocessor);
  registerPostprocessor(ElmIntegTotFissPostprocessor);
  registerPostprocessor(ElmIntegTotFissHeatPostprocessor);
  registerPostprocessor(ElmIntegTotFissNtsPostprocessor);
  registerPostprocessor(AverageFissionHeat);
  registerAux(FissionHeatSourceAux);
  registerAux(FissionHeatSourceTransientAux);
  registerAux(ModeratorHeatSourceTransientAux);
  registerAux(MatDiffusionAux);
  registerAux(ConstantDifferenceAux);
  registerDiracKernel(DiracHX);
}

// External entry point for dynamic syntax association
extern "C" void
MoltresApp__associateSyntax(Syntax & syntax, ActionFactory & action_factory)
{
  MoltresApp::associateSyntax(syntax, action_factory);
}
void
MoltresApp::associateSyntax(Syntax & syntax, ActionFactory & action_factory)
{
  syntax.registerActionSyntax("PrecursorAction", "Precursors/*");
  syntax.registerActionSyntax("NtAction", "Nt");

  registerAction(PrecursorAction, "add_kernel");
  registerAction(PrecursorAction, "add_postprocessor");
  registerAction(PrecursorAction, "add_bc");
  registerAction(PrecursorAction, "add_variable");
  registerAction(PrecursorAction, "add_ic");
  registerAction(PrecursorAction, "add_dg_kernel");
  registerAction(PrecursorAction, "add_transfer");
  registerAction(PrecursorAction, "check_copy_nodal_vars");
  registerAction(PrecursorAction, "copy_nodal_vars");
  registerAction(NtAction, "add_kernel");
  registerAction(NtAction, "add_bc");
  registerAction(NtAction, "add_variable");
  registerAction(NtAction, "add_ic");
  registerAction(NtAction, "add_aux_variable");
  registerAction(NtAction, "add_aux_kernel");
  registerAction(NtAction, "check_copy_nodal_vars");
  registerAction(NtAction, "copy_nodal_vars");
}
<commit_msg>add task dependency to MoltresApp<commit_after>#include "MoltresApp.h"
#include "Moose.h"
#include "AppFactory.h"
#include "ModulesApp.h"
#include "SquirrelApp.h"
#include "MooseSyntax.h"

// Kernels
#include "DelayedNeutronSource.h"
#include "ScalarTransportTimeDerivative.h"
#include "ScalarAdvectionArtDiff.h"
#include "PrecursorDecay.h"
#include "NtTimeDerivative.h"
#include "PrecursorSource.h"
#include "FissionHeatSource.h"
#include "TransientFissionHeatSource.h"
#include "INSMomentumKEpsilon.h"
#include "INSBoussinesqBodyForce.h"
#include "SigmaR.h"
#include "CoupledFissionEigenKernel.h"
#include "CoupledFissionKernel.h"
#include "SelfFissionEigenKernel.h"
#include "InScatter.h"
#include "GroupDiffusion.h"
#include "CoupledScalarAdvection.h"
#include "DivFreeCoupledScalarAdvection.h"
#include "GammaHeatSource.h"

// Boundary conditions
#include "LinLogPenaltyDirichletBC.h"
#include "VacuumConcBC.h"
#include "ConservativeAdvectionNoBCBC.h"
#include "DiffusionNoBCBC.h"
#include "ScalarAdvectionArtDiffNoBCBC.h"
#include "INSOutflowBC.h"
#include "INSSymmetryAxisBC.h"
#include "MatDiffusionFluxBC.h"
#include "CoupledScalarAdvectionNoBCBC.h"

// Materials
#include "GenericMoltresMaterial.h"
#include "CammiFuel.h"
#include "CammiModerator.h"
#include "Nusselt.h"
#include "GraphiteTwoGrpXSFunctionMaterial.h"
#include "MsreFuelTwoGrpXSFunctionMaterial.h"
#include "RoddedMaterial.h"

// Postprocessors
#include "LimitK.h"
#include "AverageFissionHeat.h"
#include "ElementL2Diff.h"
#include "DivisionPostprocessor.h"
#include "IntegralOldVariablePostprocessor.h"
#include "IntegralNewVariablePostprocessor.h"
#include "ElmIntegTotFissPostprocessor.h"
#include "ElmIntegTotFissHeatPostprocessor.h"
#include "ElmIntegTotFissNtsPostprocessor.h"

// AuxKernels
#include "FissionHeatSourceAux.h"
#include "FissionHeatSourceTransientAux.h"
#include "ModeratorHeatSourceTransientAux.h"
#include "MatDiffusionAux.h"
#include "ConstantDifferenceAux.h"

// Actions
#include "PrecursorAction.h"
#include "NtAction.h"

// DiracKernels
#include "DiracHX.h"

template <>
InputParameters
validParams<MoltresApp>()
{
  InputParameters params = validParams<MooseApp>();

  params.set<bool>("use_legacy_uo_initialization") = false;
  params.set<bool>("use_legacy_uo_aux_computation") = false;
  params.set<bool>("use_legacy_output_syntax") = false;

  return params;
}

MoltresApp::MoltresApp(InputParameters parameters) : MooseApp(parameters)
{
  Moose::registerObjects(_factory);
  ModulesApp::registerObjects(_factory);
  SquirrelApp::registerObjects(_factory);
  MoltresApp::registerObjects(_factory);

  Moose::associateSyntax(_syntax, _action_factory);
  ModulesApp::associateSyntax(_syntax, _action_factory);
  SquirrelApp::associateSyntax(_syntax, _action_factory);
  MoltresApp::associateSyntax(_syntax, _action_factory);
}

MoltresApp::~MoltresApp() {}

// External entry point for dynamic application loading
extern "C" void
MoltresApp__registerApps()
{
  MoltresApp::registerApps();
}
void
MoltresApp::registerApps()
{
  registerApp(MoltresApp);
}

// External entry point for dynamic object registration
extern "C" void
MoltresApp__registerObjects(Factory & factory)
{
  MoltresApp::registerObjects(factory);
}
void
MoltresApp::registerObjects(Factory & factory)
{
  registerKernel(DelayedNeutronSource);
  registerKernel(SigmaR);
  registerKernel(GammaHeatSource);
  registerKernel(ScalarTransportTimeDerivative);
  registerKernel(PrecursorSource);
  registerKernel(PrecursorDecay);
  registerKernel(CoupledScalarAdvection);
  registerKernel(DivFreeCoupledScalarAdvection);
  registerKernel(NtTimeDerivative);
  registerKernel(FissionHeatSource);
  registerKernel(TransientFissionHeatSource);
  registerKernel(InScatter);
  registerKernel(CoupledFissionEigenKernel);
  registerKernel(ScalarAdvectionArtDiff);
  registerKernel(CoupledFissionKernel);
  registerKernel(SelfFissionEigenKernel);
  registerKernel(INSMomentumKEpsilon);
  registerKernel(INSBoussinesqBodyForce);
  registerKernel(GroupDiffusion);
  registerBoundaryCondition(LinLogPenaltyDirichletBC);
  registerBoundaryCondition(ScalarAdvectionArtDiffNoBCBC);
  registerBoundaryCondition(VacuumConcBC);
  registerBoundaryCondition(ConservativeAdvectionNoBCBC);
  registerBoundaryCondition(DiffusionNoBCBC);
  registerBoundaryCondition(CoupledScalarAdvectionNoBCBC);
  registerBoundaryCondition(INSOutflowBC);
  registerBoundaryCondition(INSSymmetryAxisBC);
  registerBoundaryCondition(MatDiffusionFluxBC);
  registerMaterial(GenericMoltresMaterial);
  registerMaterial(CammiFuel);
  registerMaterial(CammiModerator);
  registerMaterial(Nusselt);
  registerMaterial(GraphiteTwoGrpXSFunctionMaterial);
  registerMaterial(MsreFuelTwoGrpXSFunctionMaterial);
  registerMaterial(RoddedMaterial);
  registerPostprocessor(LimitK);
  registerPostprocessor(IntegralOldVariablePostprocessor);
  registerPostprocessor(ElementL2Diff);
  registerPostprocessor(IntegralNewVariablePostprocessor);
  registerPostprocessor(DivisionPostprocessor);
  registerPostprocessor(ElmIntegTotFissPostprocessor);
  registerPostprocessor(ElmIntegTotFissHeatPostprocessor);
  registerPostprocessor(ElmIntegTotFissNtsPostprocessor);
  registerPostprocessor(AverageFissionHeat);
  registerAux(FissionHeatSourceAux);
  registerAux(FissionHeatSourceTransientAux);
  registerAux(ModeratorHeatSourceTransientAux);
  registerAux(MatDiffusionAux);
  registerAux(ConstantDifferenceAux);
  registerDiracKernel(DiracHX);
}

// External entry point for dynamic syntax association
extern "C" void
MoltresApp__associateSyntax(Syntax & syntax, ActionFactory & action_factory)
{
  MoltresApp::associateSyntax(syntax, action_factory);
}
void
MoltresApp::associateSyntax(Syntax & syntax, ActionFactory & action_factory)
{
  syntax.registerActionSyntax("PrecursorAction", "Precursors/*");
  syntax.registerActionSyntax("NtAction", "Nt");

  registerAction(PrecursorAction, "add_kernel");
  registerAction(PrecursorAction, "add_postprocessor");
  registerAction(PrecursorAction, "add_bc");
  registerAction(PrecursorAction, "add_variable");
  registerAction(PrecursorAction, "add_ic");
  registerAction(PrecursorAction, "add_dg_kernel");
  registerAction(PrecursorAction, "add_transfer");
  registerAction(PrecursorAction, "check_copy_nodal_vars");
  registerAction(PrecursorAction, "copy_nodal_vars");
  addTaskDependency("add_bc", "add_postprocessor");
  addTaskDependency("add_transfer", "add_postprocessor");
  registerAction(NtAction, "add_kernel");
  registerAction(NtAction, "add_bc");
  registerAction(NtAction, "add_variable");
  registerAction(NtAction, "add_ic");
  registerAction(NtAction, "add_aux_variable");
  registerAction(NtAction, "add_aux_kernel");
  registerAction(NtAction, "check_copy_nodal_vars");
  registerAction(NtAction, "copy_nodal_vars");
}
<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "ExecutionContext.h"

#include "cling/Interpreter/StoredValueRef.h"

#include "clang/AST/Type.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace cling;

std::set<std::string> ExecutionContext::m_unresolvedSymbols;
std::vector<ExecutionContext::LazyFunctionCreatorFunc_t>
  ExecutionContext::m_lazyFuncCreator;

bool ExecutionContext::m_LazyFuncCreatorDiagsSuppressed = false;

// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::ExecutionContext(llvm::Module* m)
  : m_RunningStaticInits(false), m_CxaAtExitRemapped(false)
{
  assert(m && "llvm::Module must not be null!");
  InitializeBuilder(m);
}

// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::~ExecutionContext() {}

void ExecutionContext::InitializeBuilder(llvm::Module* m) {
  //
  //  Create an execution engine to use.
  //
  assert(m && "Module cannot be null");

  // Note: Engine takes ownership of the module.
  llvm::EngineBuilder builder(m);

  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);

  // EngineBuilder uses default c'ted TargetOptions, too:
  llvm::TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElim = 1;
  TargetOpts.JITExceptionHandling = 1;
  TargetOpts.JITEmitDebugInfo = 1;

  builder.setTargetOptions(TargetOpts);

  m_engine.reset(builder.create());
  if (!m_engine)
     llvm::errs() << "cling::ExecutionContext::InitializeBuilder(): " << errMsg;
  assert(m_engine && "Cannot create module!");

  // install lazy function creators
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "ExecutionContext: calling unresolved symbol, "
    "see previous error message!\n";
}

void* ExecutionContext::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "ExecutionContext: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
ExecutionContext::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }

  if (m_LazyFuncCreatorDiagsSuppressed)
    return 0;

  return HandleMissingFunction(mangled_name);
}

static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    if (funcsToFreeUnique.insert(func)) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}

ExecutionContext::ExecutionResult
ExecutionContext::executeFunction(llvm::StringRef funcname,
                                  const clang::ASTContext& Ctx,
                                  clang::QualType retType,
                                  StoredValueRef* returnValue)
{
  // Call a function without arguments, or with an SRet argument, see SRet below

  if (!m_CxaAtExitRemapped) {
    // Rewire atexit:
    llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
    llvm::Function* clingAtExit
      = m_engine->FindFunctionNamed("cling_cxa_atexit");
    if (atExit && clingAtExit) {
      void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
      assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
      m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
      m_CxaAtExitRemapped = true;
    }
  }

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.str().c_str());
  if (!f) {
    llvm::errs() << "ExecutionContext::executeFunction: "
      "could not find function named " << funcname << '\n';
    return kExeFunctionNotCompiled;
  }
  m_engine->getPointerToFunction(f);
  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    llvm::SmallVector<llvm::Function*, 100> funcsToFree;
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "ExecutionContext::executeFunction: symbol '" << *i
                   << "' unresolved while linking function '" << funcname
                   << "'!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      assert(ff && "cannot find function to free");
      funcsToFree.push_back(ff);
    }
    freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
    m_unresolvedSymbols.clear();
    return kExeUnresolvedSymbols;
  }

  std::vector<llvm::GenericValue> args;
  bool wantReturn = (returnValue);
  StoredValueRef aggregateRet;

  if (f->hasStructRetAttr()) {
    // Function expects to receive the storage for the returned aggregate as
    // first argument. Allocate returnValue:
    aggregateRet = StoredValueRef::allocate(Ctx, retType, f->getReturnType());
    if (returnValue) {
      *returnValue = aggregateRet;
    } else {
      returnValue = &aggregateRet;
    }
    args.push_back(returnValue->get().getGV());
    // will get set as arg0, must not assign.
    wantReturn = false;
  }

  if (wantReturn) {
    llvm::GenericValue gvRet = m_engine->runFunction(f, args);
    // rescue the ret value (which might be aggregate) from the stack
    *returnValue = StoredValueRef::bitwiseCopy(Ctx, Value(gvRet, retType));
  } else {
    m_engine->runFunction(f, args);
  }

  return kExeSuccess;
}

ExecutionContext::ExecutionResult
ExecutionContext::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  if (m_RunningStaticInits)
     return kExeSuccess;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());
  if (InitList == 0)
    return kExeSuccess;

  m_RunningStaticInits = true;

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      m_engine->getPointerToFunction(F);
      // check if there is any unresolved symbol in the list
      if (!m_unresolvedSymbols.empty()) {
        llvm::SmallVector<llvm::Function*, 100> funcsToFree;
        for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
               e = m_unresolvedSymbols.end(); i != e; ++i) {
          llvm::errs() << "ExecutionContext::runStaticInitializersOnce: symbol '" << *i
                       << "' unresolved while linking static initializer '"
                       << F->getName() << "'!\n";
          llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
          assert(ff && "cannot find function to free");
          funcsToFree.push_back(ff);
        }
        freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
        m_unresolvedSymbols.clear();
        m_RunningStaticInits = false;
        return kExeUnresolvedSymbols;
      }
      m_engine->runFunction(F, std::vector<llvm::GenericValue>());
    }
  }

  GV->eraseFromParent();

  m_RunningStaticInits = false;
  return kExeSuccess;
}

void
ExecutionContext::runStaticDestructorsOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* gdtors
    = m->getGlobalVariable("llvm.global_dtors", true);
  if (gdtors) {
    m_engine->runStaticConstructorsDestructors(true);
  }

}

int
ExecutionContext::verifyModule(llvm::Module* m)
{
  //
  //  Verify generated module.
  //
  bool mod_has_errs = llvm::verifyModule(*m, llvm::PrintMessageAction);
  if (mod_has_errs) {
    return 1;
  }
  return 0;
}

void
ExecutionContext::printModule(llvm::Module* m)
{
  //
  //  Print module LLVM code in human-readable form.
  //
  llvm::PassManager PM;
  PM.add(llvm::createPrintModulePass(&llvm::errs()));
  PM.run(*m);
}

void
ExecutionContext::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool ExecutionContext::addSymbol(const char* symbolName,  void* symbolAddress) {

  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* ExecutionContext::getAddressOfGlobal(llvm::Module* m,
                                           const char* symbolName,
                                           bool* fromJIT /*=0*/) const {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (address) {
    if (fromJIT) *fromJIT = false;
  } else {
    if (fromJIT) *fromJIT = true;
    llvm::GlobalVariable* gvar = m->getGlobalVariable(symbolName, true);
    if (!gvar)
      return 0;

    address = m_engine->getPointerToGlobal(gvar);
  }
  return address;
}
<commit_msg>Turn opt off completely until llvm bug / stressGraphics is fixed.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "ExecutionContext.h"

#include "cling/Interpreter/StoredValueRef.h"

#include "clang/AST/Type.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace cling;

std::set<std::string> ExecutionContext::m_unresolvedSymbols;
std::vector<ExecutionContext::LazyFunctionCreatorFunc_t>
  ExecutionContext::m_lazyFuncCreator;

bool ExecutionContext::m_LazyFuncCreatorDiagsSuppressed = false;

// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::ExecutionContext(llvm::Module* m)
  : m_RunningStaticInits(false), m_CxaAtExitRemapped(false)
{
  assert(m && "llvm::Module must not be null!");
  InitializeBuilder(m);
}

// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::~ExecutionContext() {}

void ExecutionContext::InitializeBuilder(llvm::Module* m) {
  //
  //  Create an execution engine to use.
  //
  assert(m && "Module cannot be null");

  // Note: Engine takes ownership of the module.
  llvm::EngineBuilder builder(m);

  std::string errMsg;
  builder.setErrorStr(&errMsg);
  // FIXME: should be at least Less!
  builder.setOptLevel(llvm::CodeGenOpt::None);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);

  // EngineBuilder uses default c'ted TargetOptions, too:
  llvm::TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElim = 1;
  TargetOpts.JITExceptionHandling = 1;
  TargetOpts.JITEmitDebugInfo = 1;

  builder.setTargetOptions(TargetOpts);

  m_engine.reset(builder.create());
  if (!m_engine)
     llvm::errs() << "cling::ExecutionContext::InitializeBuilder(): " << errMsg;
  assert(m_engine && "Cannot create module!");

  // install lazy function creators
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "ExecutionContext: calling unresolved symbol, "
    "see previous error message!\n";
}

void* ExecutionContext::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "ExecutionContext: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
ExecutionContext::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }

  if (m_LazyFuncCreatorDiagsSuppressed)
    return 0;

  return HandleMissingFunction(mangled_name);
}

static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    if (funcsToFreeUnique.insert(func)) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}

ExecutionContext::ExecutionResult
ExecutionContext::executeFunction(llvm::StringRef funcname,
                                  const clang::ASTContext& Ctx,
                                  clang::QualType retType,
                                  StoredValueRef* returnValue)
{
  // Call a function without arguments, or with an SRet argument, see SRet below

  if (!m_CxaAtExitRemapped) {
    // Rewire atexit:
    llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
    llvm::Function* clingAtExit
      = m_engine->FindFunctionNamed("cling_cxa_atexit");
    if (atExit && clingAtExit) {
      void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
      assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
      m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
      m_CxaAtExitRemapped = true;
    }
  }

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.str().c_str());
  if (!f) {
    llvm::errs() << "ExecutionContext::executeFunction: "
      "could not find function named " << funcname << '\n';
    return kExeFunctionNotCompiled;
  }
  m_engine->getPointerToFunction(f);
  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    llvm::SmallVector<llvm::Function*, 100> funcsToFree;
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "ExecutionContext::executeFunction: symbol '" << *i
                   << "' unresolved while linking function '" << funcname
                   << "'!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      assert(ff && "cannot find function to free");
      funcsToFree.push_back(ff);
    }
    freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
    m_unresolvedSymbols.clear();
    return kExeUnresolvedSymbols;
  }

  std::vector<llvm::GenericValue> args;
  bool wantReturn = (returnValue);
  StoredValueRef aggregateRet;

  if (f->hasStructRetAttr()) {
    // Function expects to receive the storage for the returned aggregate as
    // first argument. Allocate returnValue:
    aggregateRet = StoredValueRef::allocate(Ctx, retType, f->getReturnType());
    if (returnValue) {
      *returnValue = aggregateRet;
    } else {
      returnValue = &aggregateRet;
    }
    args.push_back(returnValue->get().getGV());
    // will get set as arg0, must not assign.
    wantReturn = false;
  }

  if (wantReturn) {
    llvm::GenericValue gvRet = m_engine->runFunction(f, args);
    // rescue the ret value (which might be aggregate) from the stack
    *returnValue = StoredValueRef::bitwiseCopy(Ctx, Value(gvRet, retType));
  } else {
    m_engine->runFunction(f, args);
  }

  return kExeSuccess;
}

ExecutionContext::ExecutionResult
ExecutionContext::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  if (m_RunningStaticInits)
     return kExeSuccess;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());
  if (InitList == 0)
    return kExeSuccess;

  m_RunningStaticInits = true;

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      m_engine->getPointerToFunction(F);
      // check if there is any unresolved symbol in the list
      if (!m_unresolvedSymbols.empty()) {
        llvm::SmallVector<llvm::Function*, 100> funcsToFree;
        for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
               e = m_unresolvedSymbols.end(); i != e; ++i) {
          llvm::errs() << "ExecutionContext::runStaticInitializersOnce: symbol '" << *i
                       << "' unresolved while linking static initializer '"
                       << F->getName() << "'!\n";
          llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
          assert(ff && "cannot find function to free");
          funcsToFree.push_back(ff);
        }
        freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
        m_unresolvedSymbols.clear();
        m_RunningStaticInits = false;
        return kExeUnresolvedSymbols;
      }
      m_engine->runFunction(F, std::vector<llvm::GenericValue>());
    }
  }

  GV->eraseFromParent();

  m_RunningStaticInits = false;
  return kExeSuccess;
}

void
ExecutionContext::runStaticDestructorsOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* gdtors
    = m->getGlobalVariable("llvm.global_dtors", true);
  if (gdtors) {
    m_engine->runStaticConstructorsDestructors(true);
  }

}

int
ExecutionContext::verifyModule(llvm::Module* m)
{
  //
  //  Verify generated module.
  //
  bool mod_has_errs = llvm::verifyModule(*m, llvm::PrintMessageAction);
  if (mod_has_errs) {
    return 1;
  }
  return 0;
}

void
ExecutionContext::printModule(llvm::Module* m)
{
  //
  //  Print module LLVM code in human-readable form.
  //
  llvm::PassManager PM;
  PM.add(llvm::createPrintModulePass(&llvm::errs()));
  PM.run(*m);
}

void
ExecutionContext::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool ExecutionContext::addSymbol(const char* symbolName,  void* symbolAddress) {

  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* ExecutionContext::getAddressOfGlobal(llvm::Module* m,
                                           const char* symbolName,
                                           bool* fromJIT /*=0*/) const {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (address) {
    if (fromJIT) *fromJIT = false;
  } else {
    if (fromJIT) *fromJIT = true;
    llvm::GlobalVariable* gvar = m->getGlobalVariable(symbolName, true);
    if (!gvar)
      return 0;

    address = m_engine->getPointerToGlobal(gvar);
  }
  return address;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "InputValidator.h"

#include "clang/Lex/Preprocessor.h"

using namespace clang;

namespace cling {
  InputValidator::ValidationResult
  InputValidator::validate(llvm::StringRef line, const LangOptions& LO) {
    if (!m_Input.empty())
      m_Input.append("\n");
    else
      m_Input = "";

    m_Input.append(line);

    // Imballanced ' or " drives our lexer nuts.
    llvm::StringRef fullInput(m_Input);
    if (fullInput.count('\'') % 2 || fullInput.count('"') % 2) {
      return kIncomplete;
    }

    llvm::OwningPtr<llvm::MemoryBuffer> MB;
    MB.reset(llvm::MemoryBuffer::getMemBuffer(line));

    Lexer RawLexer(SourceLocation(), LO, MB->getBufferStart(),
                   MB->getBufferStart(), MB->getBufferEnd());
    Token Tok;
    do {
      RawLexer.LexFromRawLexer(Tok);
      int kind = (int)Tok.getKind();
      if (kind >= (int)tok::l_square
          && kind <= (int)tok::r_brace) {
        kind -= (int)tok::l_square;
        if (kind % 2) {
          // closing the right one?
          if (m_ParenStack.empty())
            return kMismatch;
          int prev = m_ParenStack.top();
          if (prev != kind - 1)
            return kMismatch;
          m_ParenStack.pop();
        } else {
          m_ParenStack.push(kind);
        }
      }
    }
    while (Tok.isNot(tok::eof));

    if (!m_ParenStack.empty())
      return kIncomplete;

    return kComplete;
  }

  void InputValidator::reset() {
    m_Input = "";
    while (!m_ParenStack.empty())
      m_ParenStack.pop();
  }
} // end namespace cling
<commit_msg>Insert an actual new line, which means new line for the lexer too...<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "InputValidator.h"

#include "clang/Lex/Preprocessor.h"

using namespace clang;

namespace cling {
  InputValidator::ValidationResult
  InputValidator::validate(llvm::StringRef line, const LangOptions& LO) {
    if (!m_Input.empty())
      m_Input.append("\\n");
    else
      m_Input = "";

    m_Input.append(line);

    // Imballanced ' or " drives our lexer nuts.
    llvm::StringRef fullInput(m_Input);
    if (fullInput.count('\'') % 2 || fullInput.count('"') % 2) {
      return kIncomplete;
    }

    llvm::OwningPtr<llvm::MemoryBuffer> MB;
    MB.reset(llvm::MemoryBuffer::getMemBuffer(line));

    Lexer RawLexer(SourceLocation(), LO, MB->getBufferStart(),
                   MB->getBufferStart(), MB->getBufferEnd());
    Token Tok;
    do {
      RawLexer.LexFromRawLexer(Tok);
      int kind = (int)Tok.getKind();
      if (kind >= (int)tok::l_square
          && kind <= (int)tok::r_brace) {
        kind -= (int)tok::l_square;
        if (kind % 2) {
          // closing the right one?
          if (m_ParenStack.empty())
            return kMismatch;
          int prev = m_ParenStack.top();
          if (prev != kind - 1)
            return kMismatch;
          m_ParenStack.pop();
        } else {
          m_ParenStack.push(kind);
        }
      }
    }
    while (Tok.isNot(tok::eof));

    if (!m_ParenStack.empty())
      return kIncomplete;

    return kComplete;
  }

  void InputValidator::reset() {
    m_Input = "";
    while (!m_ParenStack.empty())
      m_ParenStack.pop();
  }
} // end namespace cling
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "InputValidator.h"

#include "MetaLexer.h"

namespace cling {
  InputValidator::ValidationResult
  InputValidator::validate(llvm::StringRef line) {
    ValidationResult Res = kComplete;

    Token Tok;
    const char* curPos = line.data();
    do {
      // If the input is "some//string" or '//some/string' we need to disable
      // the comment checks.
      bool hasQuoteOrApostrophe = false;
      for (unsigned i = 0, e = m_ParenStack.size(); i < e; ++i) {
        int entry = m_ParenStack[i];
        if (entry == (int)tok::quote || entry == (int)tok::apostrophe) {
          hasQuoteOrApostrophe = true;
          break;
        }
      }
      MetaLexer::LexPunctuatorAndAdvance(curPos, Tok,
                                         /*skipComments*/hasQuoteOrApostrophe);
      int kind = (int)Tok.getKind();

      // if (kind == tok::hash) {
      //   // Handle #ifdef ...
      //   //          ...
      //   //        #endif
      //   MetaLexer Lexer(curPos);
      //   Lexer.Lex(Tok);
      //   if (Tok.getKind() == tok::ident) {
      //     if (Tok.getIdent().startswith("if")) {
      //       Res = kIncomplete;
      //       m_ParenStack.push_back(kind);
      //     }
      //     else if (Tok.getIdent().startswith("end")) {
      //       assert(m_ParenStack.back() == kind && "No coresponding # to pop?");
      //       m_ParenStack.pop_back();
      //     }
      //   }
      // }

      if (kind >= (int)tok::quote && kind <= (int)tok::apostrophe) {
        // If there is " or ' we don't need to look for balancing until we
        // enounter matching " or '
        Res = kIncomplete;
        if (m_ParenStack.back() == kind) {
          // We know that the top of the stack will have the leading quote or
          // apostophe because nobody is pushing onto it until we find a balance
          m_ParenStack.pop_back();
          Res = kComplete;
        }
        if (!hasQuoteOrApostrophe)
          m_ParenStack.push_back(kind); // Register the first " or '
        continue;
      }
      // All the rest is irrelevant in QuoteOrApostrophe mode.
      if (hasQuoteOrApostrophe)
        continue;

      // In case when we need closing brace.
      if (kind >= (int)tok::l_square && kind <= (int)tok::r_brace) {
        // The closing paren kind is open paren kind + 1 (i.e odd number)
        if (kind % 2) {
          // closing the right one?
          if (m_ParenStack.empty()) {
            Res = kMismatch;
            break;
          }
          int prev = m_ParenStack.back();
          if (prev != kind - 1) {
            Res = kMismatch;
            break;
          }
          m_ParenStack.pop_back();
        }
        else
          m_ParenStack.push_back(kind);
      }
    }
    while (Tok.isNot(tok::eof));

    if (!m_ParenStack.empty() && Res != kMismatch)
      Res = kIncomplete;

    if (!m_Input.empty()) {
      if (!m_ParenStack.empty() && (m_ParenStack.back() == tok::quote
                                    || m_ParenStack.back() == tok::apostrophe))
        m_Input.append("\\n");
      else
        m_Input.append("\n");
    }
    else
      m_Input = "";

    m_Input.append(line);

    return Res;
  }

  void InputValidator::reset() {
    m_Input = "";
    m_ParenStack.clear();
  }
} // end namespace cling
<commit_msg>Check if the paren stack has elements first.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "InputValidator.h"

#include "MetaLexer.h"

namespace cling {
  InputValidator::ValidationResult
  InputValidator::validate(llvm::StringRef line) {
    ValidationResult Res = kComplete;

    Token Tok;
    const char* curPos = line.data();
    do {
      // If the input is "some//string" or '//some/string' we need to disable
      // the comment checks.
      bool hasQuoteOrApostrophe = false;
      for (unsigned i = 0, e = m_ParenStack.size(); i < e; ++i) {
        int entry = m_ParenStack[i];
        if (entry == (int)tok::quote || entry == (int)tok::apostrophe) {
          hasQuoteOrApostrophe = true;
          break;
        }
      }
      MetaLexer::LexPunctuatorAndAdvance(curPos, Tok,
                                         /*skipComments*/hasQuoteOrApostrophe);
      int kind = (int)Tok.getKind();

      // if (kind == tok::hash) {
      //   // Handle #ifdef ...
      //   //          ...
      //   //        #endif
      //   MetaLexer Lexer(curPos);
      //   Lexer.Lex(Tok);
      //   if (Tok.getKind() == tok::ident) {
      //     if (Tok.getIdent().startswith("if")) {
      //       Res = kIncomplete;
      //       m_ParenStack.push_back(kind);
      //     }
      //     else if (Tok.getIdent().startswith("end")) {
      //       assert(m_ParenStack.back() == kind && "No coresponding # to pop?");
      //       m_ParenStack.pop_back();
      //     }
      //   }
      // }

      if (kind >= (int)tok::quote && kind <= (int)tok::apostrophe) {
        // If there is " or ' we don't need to look for balancing until we
        // enounter matching " or '
        Res = kIncomplete;
        if (m_ParenStack.size() && m_ParenStack.back() == kind) {
          // We know that the top of the stack will have the leading quote or
          // apostophe because nobody is pushing onto it until we find a balance
          m_ParenStack.pop_back();
          Res = kComplete;
        }
        if (!hasQuoteOrApostrophe)
          m_ParenStack.push_back(kind); // Register the first " or '
        continue;
      }
      // All the rest is irrelevant in QuoteOrApostrophe mode.
      if (hasQuoteOrApostrophe)
        continue;

      // In case when we need closing brace.
      if (kind >= (int)tok::l_square && kind <= (int)tok::r_brace) {
        // The closing paren kind is open paren kind + 1 (i.e odd number)
        if (kind % 2) {
          // closing the right one?
          if (m_ParenStack.empty()) {
            Res = kMismatch;
            break;
          }
          int prev = m_ParenStack.back();
          if (prev != kind - 1) {
            Res = kMismatch;
            break;
          }
          m_ParenStack.pop_back();
        }
        else
          m_ParenStack.push_back(kind);
      }
    }
    while (Tok.isNot(tok::eof));

    if (!m_ParenStack.empty() && Res != kMismatch)
      Res = kIncomplete;

    if (!m_Input.empty()) {
      if (!m_ParenStack.empty() && (m_ParenStack.back() == tok::quote
                                    || m_ParenStack.back() == tok::apostrophe))
        m_Input.append("\\n");
      else
        m_Input.append("\n");
    }
    else
      m_Input = "";

    m_Input.append(line);

    return Res;
  }

  void InputValidator::reset() {
    m_Input = "";
    m_ParenStack.clear();
  }
} // end namespace cling
<|endoftext|>


<commit_before>#include <core/dsl.hpp>
#include <beatwave/drop.hpp>

Drop::Drop(const sf::Color &color):
    m_radius(0.0f),
    m_position(sf::Vector2f(0.0f, 0.0f)),
    m_color(color)
{}

void Drop::render(sf::RenderTarget *renderTarget) const
{
    sf::CircleShape circle(m_radius.value());
    circle.setFillColor(m_color);
    circle.setPosition(m_position.value() - sf::Vector2f(m_radius.value(), m_radius.value()));
    renderTarget->draw(circle);
}

void Drop::drop(const sf::Vector2f &begin,
                const sf::Vector2f &end,
                double radius)
{
    using namespace dsl;

    const int32_t DROP_DURATION = 400;

    m_radius.animate(from(radius).to(0.0f).during(DROP_DURATION));
    m_position.animate(from(begin).to(end).during(DROP_DURATION));
}

void Drop::tick(int32_t deltaTime)
{
    m_radius.tick(deltaTime);
    m_position.tick(deltaTime);
}
<commit_msg>Add FIXME #46<commit_after>#include <core/dsl.hpp>
#include <beatwave/drop.hpp>

Drop::Drop(const sf::Color &color):
    m_radius(0.0f),
    m_position(sf::Vector2f(0.0f, 0.0f)),
    m_color(color)
{}

void Drop::render(sf::RenderTarget *renderTarget) const
{
    sf::CircleShape circle(m_radius.value());
    circle.setFillColor(m_color);
    circle.setPosition(m_position.value() - sf::Vector2f(m_radius.value(), m_radius.value()));
    renderTarget->draw(circle);
}

void Drop::drop(const sf::Vector2f &begin,
                const sf::Vector2f &end,
                double radius)
{
    using namespace dsl;

    // FIXME(#46)
    const int32_t DROP_DURATION = 400;

    m_radius.animate(from(radius).to(0.0f).during(DROP_DURATION));
    m_position.animate(from(begin).to(end).during(DROP_DURATION));
}

void Drop::tick(int32_t deltaTime)
{
    m_radius.tick(deltaTime);
    m_position.tick(deltaTime);
}
<|endoftext|>


<commit_before>// Copyright 2017 The Abseil Authors.
//
// 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
//
//      https://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 "absl/base/internal/raw_logging.h"

#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/atomic_hook.h"
#include "absl/base/internal/errno_saver.h"
#include "absl/base/log_severity.h"

// We know how to perform low-level writes to stderr in POSIX and Windows.  For
// these platforms, we define the token ABSL_LOW_LEVEL_WRITE_SUPPORTED.
// Much of raw_logging.cc becomes a no-op when we can't output messages,
// although a FATAL ABSL_RAW_LOG message will still abort the process.

// ABSL_HAVE_POSIX_WRITE is defined when the platform provides posix write()
// (as from unistd.h)
//
// This preprocessor token is also defined in raw_io.cc.  If you need to copy
// this, consider moving both to config.h instead.
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
    defined(__Fuchsia__) || defined(__native_client__) ||               \
    defined(__OpenBSD__) || defined(__EMSCRIPTEN__) || defined(__ASYLO__)

#include <unistd.h>

#define ABSL_HAVE_POSIX_WRITE 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_POSIX_WRITE
#endif

// ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall
//   syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len);
// for low level operations that want to avoid libc.
#if (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && \
    !defined(__ANDROID__)
#include <sys/syscall.h>
#define ABSL_HAVE_SYSCALL_WRITE 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_SYSCALL_WRITE
#endif

#ifdef _WIN32
#include <io.h>

#define ABSL_HAVE_RAW_IO 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_RAW_IO
#endif

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace raw_logging_internal {
namespace {

// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
// Explicitly `#error` out when not `ABSL_LOW_LEVEL_WRITE_SUPPORTED`, except for
// a selected set of platforms for which we expect not to be able to raw log.

ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
absl::base_internal::AtomicHook<LogFilterAndPrefixHook>
    log_filter_and_prefix_hook;
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
absl::base_internal::AtomicHook<AbortHook> abort_hook;

#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
constexpr char kTruncated[] = " ... (message truncated)\n";

// sprintf the format to the buffer, adjusting *buf and *size to reflect the
// consumed bytes, and return whether the message fit without truncation.  If
// truncation occurred, if possible leave room in the buffer for the message
// kTruncated[].
bool VADoRawLog(char** buf, int* size, const char* format, va_list ap)
    ABSL_PRINTF_ATTRIBUTE(3, 0);
bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
  int n = vsnprintf(*buf, *size, format, ap);
  bool result = true;
  if (n < 0 || n > *size) {
    result = false;
    if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
      n = *size - sizeof(kTruncated);  // room for truncation message
    } else {
      n = 0;  // no room for truncation message
    }
  }
  *size -= n;
  *buf += n;
  return result;
}
#endif  // ABSL_LOW_LEVEL_WRITE_SUPPORTED

constexpr int kLogBufSize = 3000;

// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.

// Helper for RawLog below.
// *DoRawLog writes to *buf of *size and move them past the written portion.
// It returns true iff there was no overflow or error.
bool DoRawLog(char** buf, int* size, const char* format, ...)
    ABSL_PRINTF_ATTRIBUTE(3, 4);
bool DoRawLog(char** buf, int* size, const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  int n = vsnprintf(*buf, *size, format, ap);
  va_end(ap);
  if (n < 0 || n > *size) return false;
  *size -= n;
  *buf += n;
  return true;
}

void RawLogVA(absl::LogSeverity severity, const char* file, int line,
              const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0);
void RawLogVA(absl::LogSeverity severity, const char* file, int line,
              const char* format, va_list ap) {
  char buffer[kLogBufSize];
  char* buf = buffer;
  int size = sizeof(buffer);
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
  bool enabled = true;
#else
  bool enabled = false;
#endif

#ifdef ABSL_MIN_LOG_LEVEL
  if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
      severity < absl::LogSeverity::kFatal) {
    enabled = false;
  }
#endif

  auto log_filter_and_prefix_hook_ptr = log_filter_and_prefix_hook.Load();
  if (log_filter_and_prefix_hook_ptr) {
    enabled = log_filter_and_prefix_hook_ptr(severity, file, line, &buf, &size);
  } else {
    if (enabled) {
      DoRawLog(&buf, &size, "[%s : %d] RAW: ", file, line);
    }
  }
  const char* const prefix_end = buf;

#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
  if (enabled) {
    bool no_chop = VADoRawLog(&buf, &size, format, ap);
    if (no_chop) {
      DoRawLog(&buf, &size, "\n");
    } else {
      DoRawLog(&buf, &size, "%s", kTruncated);
    }
    AsyncSignalSafeWriteToStderr(buffer, strlen(buffer));
  }
#else
  static_cast<void>(format);
  static_cast<void>(ap);
#endif

  // Abort the process after logging a FATAL message, even if the output itself
  // was suppressed.
  if (severity == absl::LogSeverity::kFatal) {
    abort_hook(file, line, buffer, prefix_end, buffer + kLogBufSize);
    abort();
  }
}

// Non-formatting version of RawLog().
//
// TODO(gfalcon): When string_view no longer depends on base, change this
// interface to take its message as a string_view instead.
void DefaultInternalLog(absl::LogSeverity severity, const char* file, int line,
                        const std::string& message) {
  RawLog(severity, file, line, "%.*s", static_cast<int>(message.size()),
         message.data());
}

}  // namespace

void AsyncSignalSafeWriteToStderr(const char* s, size_t len) {
  absl::base_internal::ErrnoSaver errno_saver;
#if defined(ABSL_HAVE_SYSCALL_WRITE)
  // We prefer calling write via `syscall` to minimize the risk of libc doing
  // something "helpful".
  syscall(SYS_write, STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_POSIX_WRITE)
  write(STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_RAW_IO)
  _write(/* stderr */ 2, s, len);
#else
  // stderr logging unsupported on this platform
  (void) s;
  (void) len;
#endif
}

void RawLog(absl::LogSeverity severity, const char* file, int line,
            const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  RawLogVA(severity, file, line, format, ap);
  va_end(ap);
}

bool RawLoggingFullySupported() {
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
  return true;
#else  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
  return false;
#endif  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
}

ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
    absl::base_internal::AtomicHook<InternalLogFunction>
        internal_log_function(DefaultInternalLog);

void RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func) {
  log_filter_and_prefix_hook.Store(func);
}

void RegisterAbortHook(AbortHook func) { abort_hook.Store(func); }

void RegisterInternalLogFunction(InternalLogFunction func) {
  internal_log_function.Store(func);
}

}  // namespace raw_logging_internal
ABSL_NAMESPACE_END
}  // namespace absl
<commit_msg>raw_logging: Extract the inlined no-hook-registered behavior for LogPrefixHook to a default implementation.<commit_after>// Copyright 2017 The Abseil Authors.
//
// 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
//
//      https://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 "absl/base/internal/raw_logging.h"

#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/atomic_hook.h"
#include "absl/base/internal/errno_saver.h"
#include "absl/base/log_severity.h"

// We know how to perform low-level writes to stderr in POSIX and Windows.  For
// these platforms, we define the token ABSL_LOW_LEVEL_WRITE_SUPPORTED.
// Much of raw_logging.cc becomes a no-op when we can't output messages,
// although a FATAL ABSL_RAW_LOG message will still abort the process.

// ABSL_HAVE_POSIX_WRITE is defined when the platform provides posix write()
// (as from unistd.h)
//
// This preprocessor token is also defined in raw_io.cc.  If you need to copy
// this, consider moving both to config.h instead.
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
    defined(__Fuchsia__) || defined(__native_client__) ||               \
    defined(__OpenBSD__) || defined(__EMSCRIPTEN__) || defined(__ASYLO__)

#include <unistd.h>

#define ABSL_HAVE_POSIX_WRITE 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_POSIX_WRITE
#endif

// ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall
//   syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len);
// for low level operations that want to avoid libc.
#if (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && \
    !defined(__ANDROID__)
#include <sys/syscall.h>
#define ABSL_HAVE_SYSCALL_WRITE 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_SYSCALL_WRITE
#endif

#ifdef _WIN32
#include <io.h>

#define ABSL_HAVE_RAW_IO 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_RAW_IO
#endif

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace raw_logging_internal {
namespace {

// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
// Explicitly `#error` out when not `ABSL_LOW_LEVEL_WRITE_SUPPORTED`, except for
// a selected set of platforms for which we expect not to be able to raw log.

#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
constexpr char kTruncated[] = " ... (message truncated)\n";

// sprintf the format to the buffer, adjusting *buf and *size to reflect the
// consumed bytes, and return whether the message fit without truncation.  If
// truncation occurred, if possible leave room in the buffer for the message
// kTruncated[].
bool VADoRawLog(char** buf, int* size, const char* format, va_list ap)
    ABSL_PRINTF_ATTRIBUTE(3, 0);
bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
  int n = vsnprintf(*buf, *size, format, ap);
  bool result = true;
  if (n < 0 || n > *size) {
    result = false;
    if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
      n = *size - sizeof(kTruncated);  // room for truncation message
    } else {
      n = 0;  // no room for truncation message
    }
  }
  *size -= n;
  *buf += n;
  return result;
}
#endif  // ABSL_LOW_LEVEL_WRITE_SUPPORTED

constexpr int kLogBufSize = 3000;

// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.

// Helper for RawLog below.
// *DoRawLog writes to *buf of *size and move them past the written portion.
// It returns true iff there was no overflow or error.
bool DoRawLog(char** buf, int* size, const char* format, ...)
    ABSL_PRINTF_ATTRIBUTE(3, 4);
bool DoRawLog(char** buf, int* size, const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  int n = vsnprintf(*buf, *size, format, ap);
  va_end(ap);
  if (n < 0 || n > *size) return false;
  *size -= n;
  *buf += n;
  return true;
}

bool DefaultLogFilterAndPrefix(absl::LogSeverity, const char* file, int line,
                               char** buf, int* buf_size) {
  DoRawLog(buf, buf_size, "[%s : %d] RAW: ", file, line);
  return true;
}

ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
absl::base_internal::AtomicHook<LogFilterAndPrefixHook>
    log_filter_and_prefix_hook(DefaultLogFilterAndPrefix);
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
absl::base_internal::AtomicHook<AbortHook> abort_hook;

void RawLogVA(absl::LogSeverity severity, const char* file, int line,
              const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0);
void RawLogVA(absl::LogSeverity severity, const char* file, int line,
              const char* format, va_list ap) {
  char buffer[kLogBufSize];
  char* buf = buffer;
  int size = sizeof(buffer);
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
  bool enabled = true;
#else
  bool enabled = false;
#endif

#ifdef ABSL_MIN_LOG_LEVEL
  if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
      severity < absl::LogSeverity::kFatal) {
    enabled = false;
  }
#endif

  enabled = log_filter_and_prefix_hook(severity, file, line, &buf, &size);
  const char* const prefix_end = buf;

#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
  if (enabled) {
    bool no_chop = VADoRawLog(&buf, &size, format, ap);
    if (no_chop) {
      DoRawLog(&buf, &size, "\n");
    } else {
      DoRawLog(&buf, &size, "%s", kTruncated);
    }
    AsyncSignalSafeWriteToStderr(buffer, strlen(buffer));
  }
#else
  static_cast<void>(format);
  static_cast<void>(ap);
#endif

  // Abort the process after logging a FATAL message, even if the output itself
  // was suppressed.
  if (severity == absl::LogSeverity::kFatal) {
    abort_hook(file, line, buffer, prefix_end, buffer + kLogBufSize);
    abort();
  }
}

// Non-formatting version of RawLog().
//
// TODO(gfalcon): When string_view no longer depends on base, change this
// interface to take its message as a string_view instead.
void DefaultInternalLog(absl::LogSeverity severity, const char* file, int line,
                        const std::string& message) {
  RawLog(severity, file, line, "%.*s", static_cast<int>(message.size()),
         message.data());
}

}  // namespace

void AsyncSignalSafeWriteToStderr(const char* s, size_t len) {
  absl::base_internal::ErrnoSaver errno_saver;
#if defined(ABSL_HAVE_SYSCALL_WRITE)
  // We prefer calling write via `syscall` to minimize the risk of libc doing
  // something "helpful".
  syscall(SYS_write, STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_POSIX_WRITE)
  write(STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_RAW_IO)
  _write(/* stderr */ 2, s, len);
#else
  // stderr logging unsupported on this platform
  (void) s;
  (void) len;
#endif
}

void RawLog(absl::LogSeverity severity, const char* file, int line,
            const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  RawLogVA(severity, file, line, format, ap);
  va_end(ap);
}

bool RawLoggingFullySupported() {
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
  return true;
#else  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
  return false;
#endif  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
}

ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
    absl::base_internal::AtomicHook<InternalLogFunction>
        internal_log_function(DefaultInternalLog);

void RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func) {
  log_filter_and_prefix_hook.Store(func);
}

void RegisterAbortHook(AbortHook func) { abort_hook.Store(func); }

void RegisterInternalLogFunction(InternalLogFunction func) {
  internal_log_function.Store(func);
}

}  // namespace raw_logging_internal
ABSL_NAMESPACE_END
}  // namespace absl
<|endoftext|>


<commit_before><commit_msg>1581. Teamwork<commit_after><|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/function/CEvaluationTree.cpp,v $
   $Revision: 1.23 $
   $Name:  $
   $Author: gauges $
   $Date: 2005/07/12 16:30:46 $
   End CVS Header */

#include "copasi.h"

#include <sstream>
#include <vector>

#include "CEvaluationNode.h"
#include "CEvaluationTree.h"
#include "CFunction.h"
#include "CExpression.h"
#include "CEvaluationLexer.h"

#include "report/CKeyFactory.h"
#include "report/CCopasiObjectReference.h"
#include "sbml/math/ASTNode.h"
#include "utilities/CCopasiTree.h"

const std::string CEvaluationTree::TypeName[] =
  {"userdefined", "predefined", "predefined", "userdefined", "userdefined", ""};

const char* CEvaluationTree::XMLType[] =
  {"Function", "MassAction", "PreDefined", "UserDefined", "Expression", NULL};

CEvaluationTree *
CEvaluationTree::create(CEvaluationTree::Type type)
{
  CEvaluationTree * pNew = NULL;

  switch (type)
    {
    case Function:
      pNew = new CFunction();
      break;

    case MassAction:
      pNew = new CMassAction();
      break;

    case PreDefined:
      pNew = new CKinFunction();
      pNew->setType(PreDefined);
      break;

    case UserDefined:
      pNew = new CKinFunction();
      break;

    case Expression:
      pNew = new CExpression();
      break;

    default:
      fatalError();
    }

  return pNew;
}

CEvaluationTree *
CEvaluationTree::copy(const CEvaluationTree & src)
{
  CEvaluationTree * pNew = NULL;

  switch (src.getType())
    {
    case Function:
      pNew = new CFunction(*static_cast<const CFunction *>(&src));
      break;

    case MassAction:
      pNew = new CMassAction(*static_cast<const CMassAction *>(&src));
      break;

    case PreDefined:
    case UserDefined:
      pNew = new CKinFunction(*static_cast<const CKinFunction *>(&src));
      break;

    case Expression:
      pNew = new CExpression(*static_cast<const CExpression *>(&src));
      break;

    default:
      fatalError();
    }

  return pNew;
}

CEvaluationTree::CEvaluationTree(const std::string & name,
                                 const CCopasiContainer * pParent,
                                 const CEvaluationTree::Type & type):
    CCopasiContainer(name, pParent, "Function"),
    mType(type),
    mKey(GlobalKeys.add("Function", this)),
    mInfix(),
    mErrorPosition(std::string::npos),
    mpNodeList(NULL),
    mpRoot(NULL),
    mValue(std::numeric_limits<C_FLOAT64>::quiet_NaN())
{initObjects();}

CEvaluationTree::CEvaluationTree(const CEvaluationTree & src,
                                 const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mType(src.mType),
    mKey(GlobalKeys.add("Function", this)),
    mInfix(),
    mErrorPosition(std::string::npos),
    mpNodeList(NULL),
    mpRoot(NULL),
    mValue(src.mValue)
{initObjects(); setInfix(src.mInfix);}

CEvaluationTree::~CEvaluationTree()
{
  if (mpNodeList != NULL) CEvaluationParser::freeNodeList(mpNodeList);
  GlobalKeys.remove(mKey);
}

const CEvaluationTree::Type & CEvaluationTree::getType() const
{return mType;}

void CEvaluationTree::setType(const CEvaluationTree::Type & type)
{mType = type;}

const std::string & CEvaluationTree::getKey() const
  {return mKey;}

bool CEvaluationTree::setInfix(const std::string & infix)
{
  if (infix == mInfix) return true;

  mInfix = infix;

  return parse();
}

const std::string & CEvaluationTree::getInfix() const
{return mInfix;;}

const std::vector< CEvaluationNode * > & CEvaluationTree::getNodeList() const
  {return *mpNodeList;}

unsigned C_INT32 CEvaluationTree::getVariableIndex(const std::string & /*name*/) const
  {return C_INVALID_INDEX;}

const C_FLOAT64 & CEvaluationTree::getVariableValue(const unsigned C_INT32 & /*index*/) const
  {
    static C_FLOAT64 Value = std::numeric_limits<C_FLOAT64>::quiet_NaN();
    return Value;
  }

C_FLOAT64 * CEvaluationTree::getObjectValue(const CCopasiObjectName & /*CN*/) const
  {return NULL;}

bool CEvaluationTree::parse()
{
  bool success = true;

  // clean up
  CEvaluationParser::freeNodeList(mpNodeList);
  mpNodeList = NULL;
  mpRoot = NULL;

  // parse the description into a linked node tree
  std::istringstream buffer(mInfix);
  CEvaluationLexer Parser(&buffer);

  CCopasiMessage::clearDeque();

  success = (Parser.yyparse() == 0);

  mpNodeList = Parser.getNodeList();
  mpRoot = Parser.getRootNode();

  // clean up if parsing failed
  if (!success)
    {
      mErrorPosition = Parser.getErrorPosition();

      CEvaluationParser::freeNodeList(mpNodeList);
      mpNodeList = NULL;
      mpRoot = NULL;
    }

  return success;
}

bool CEvaluationTree::compileNodes()
{
  if (mpNodeList == NULL) return false;

  bool success = true;

  std::vector< CEvaluationNode * >::iterator it;
  std::vector< CEvaluationNode * >::iterator end = mpNodeList->end();

  for (it = mpNodeList->begin(); it != end && success; ++it)
    success = (*it)->compile(this);

  if (!success)
    {
      end = it;
      mErrorPosition = 0;

      for (it = mpNodeList->begin(); it != end; ++it)
        mErrorPosition += (*it)->getData().length();

      mErrorPosition -= (*--it)->getData().length();
      CCopasiMessage(CCopasiMessage::ERROR, MCFunction + 3, mErrorPosition);
    }

  return success;
}

bool CEvaluationTree::setRoot(CEvaluationNode* pRootNode)
{
  if (pRootNode == NULL) return false;
  if (mpNodeList != NULL)
    CEvaluationParser::freeNodeList(mpNodeList);

  mpRoot = pRootNode;

  mInfix = mpRoot->getInfix();

  CCopasiTree<CEvaluationNode>::iterator it = mpRoot;
  CCopasiTree<CEvaluationNode>::iterator end = NULL;

  mpNodeList = new std::vector< CEvaluationNode * >;

  for (; it != end; ++it)
    mpNodeList->push_back(&*it);

  return true;
}

bool CEvaluationTree::setTree(const ASTNode& pRootNode)
{
  return this->setRoot(CEvaluationTree::convertASTNode(pRootNode));
}

CEvaluationNode* CEvaluationTree::convertASTNode(const ASTNode& node)
{
  CEvaluationNode* pResultNode = NULL;
  ASTNodeType_t nodeType = node.getType();
  CCopasiMessage Message;
  switch (nodeType)
    {
    case AST_LAMBDA:
      break;
    case AST_PLUS:
    case AST_MINUS:
    case AST_TIMES:
    case AST_DIVIDE:
    case AST_POWER:
    case AST_FUNCTION_POWER:
      // create a CEvaluationNodeOperator
      pResultNode = CEvaluationNodeOperator::createNodeFromASTTree(node);
      break;
    case AST_INTEGER:
    case AST_REAL:
    case AST_REAL_E:
    case AST_RATIONAL:
      // create a CEvaluationNodeNumber
      pResultNode = CEvaluationNodeNumber::createNodeFromASTTree(node);
      break;
    case AST_NAME:
    case AST_NAME_TIME:
      // create a CEvaluationNodeObject
      pResultNode = CEvaluationNodeObject::createNodeFromASTTree(node);
      break;
    case AST_CONSTANT_E:
    case AST_CONSTANT_PI:
    case AST_CONSTANT_FALSE:
    case AST_CONSTANT_TRUE:
      // create a CEvaluationNodeConstant
      pResultNode = CEvaluationNodeConstant::createNodeFromASTTree(node);
      break;
    case AST_FUNCTION:
      // create a function call node
      //pRoot=CEvaluationNode???::createNodeFromASTTree(pRootNode);
      break;
    case AST_FUNCTION_ABS:
    case AST_FUNCTION_ARCCOS:
    case AST_FUNCTION_ARCCOSH:
    case AST_FUNCTION_ARCCOT:
    case AST_FUNCTION_ARCCOTH:
    case AST_FUNCTION_ARCCSC:
    case AST_FUNCTION_ARCCSCH:
    case AST_FUNCTION_ARCSEC:
    case AST_FUNCTION_ARCSECH:
    case AST_FUNCTION_ARCSIN:
    case AST_FUNCTION_ARCSINH:
    case AST_FUNCTION_ARCTAN:
    case AST_FUNCTION_ARCTANH:
    case AST_FUNCTION_CEILING:
    case AST_FUNCTION_COS:
    case AST_FUNCTION_COSH:
    case AST_FUNCTION_COT:
    case AST_FUNCTION_COTH:
    case AST_FUNCTION_CSC:
    case AST_FUNCTION_CSCH:
    case AST_FUNCTION_EXP:
    case AST_FUNCTION_FACTORIAL:
    case AST_FUNCTION_FLOOR:
    case AST_FUNCTION_LN:
    case AST_FUNCTION_LOG:
    case AST_FUNCTION_ROOT:
    case AST_FUNCTION_SEC:
    case AST_FUNCTION_SECH:
    case AST_FUNCTION_SIN:
    case AST_FUNCTION_SINH:
    case AST_FUNCTION_TAN:
    case AST_FUNCTION_TANH:
    case AST_LOGICAL_NOT:
      // create a CEvaluationNodeFunction
      pResultNode = CEvaluationNodeFunction::createNodeFromASTTree(node);
      break;

    case AST_LOGICAL_AND:
    case AST_LOGICAL_OR:
    case AST_LOGICAL_XOR:
    case AST_RELATIONAL_EQ:
    case AST_RELATIONAL_GEQ:
    case AST_RELATIONAL_GT:
    case AST_RELATIONAL_LEQ:
    case AST_RELATIONAL_LT:
    case AST_RELATIONAL_NEQ:
      pResultNode = CEvaluationNodeLogical::createNodeFromASTTree(node);
      break;
    case AST_FUNCTION_PIECEWISE:
      pResultNode = CEvaluationNodeChoice::createNodeFromASTTree(node);
      break;
    case AST_FUNCTION_DELAY:
      // create an unsupported element error
      Message = CCopasiMessage(CCopasiMessage::EXCEPTION, MCMathML + 1,
                               node.getName());
      break;

    case AST_UNKNOWN:
      // create an unknown element error
      Message = CCopasiMessage(CCopasiMessage::EXCEPTION, MCMathML + 2);

      break;
    }
  return pResultNode;
}

CEvaluationNode* CEvaluationTree::getRoot()
{
  return this->mpRoot;
}

void CEvaluationTree::initObjects()
{
  addObjectReference("Value", mValue, CCopasiObject::ValueDbl);
}

ASTNode* CEvaluationTree::toAST() const
  {
    return this->mpRoot->toAST();
  }

void CEvaluationTree::setSBMLId(const std::string& id)
{
  this->mSBMLId = id;
}

const std::string& CEvaluationTree::getSBMLId() const
  {
    return this->mSBMLId;
  }
<commit_msg>Just a comment.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/function/CEvaluationTree.cpp,v $
   $Revision: 1.24 $
   $Name:  $
   $Author: gauges $
   $Date: 2005/07/19 15:16:03 $
   End CVS Header */

#include "copasi.h"

#include <sstream>
#include <vector>

#include "CEvaluationNode.h"
#include "CEvaluationTree.h"
#include "CFunction.h"
#include "CExpression.h"
#include "CEvaluationLexer.h"

#include "report/CKeyFactory.h"
#include "report/CCopasiObjectReference.h"
#include "sbml/math/ASTNode.h"
#include "utilities/CCopasiTree.h"

const std::string CEvaluationTree::TypeName[] =
  {"userdefined", "predefined", "predefined", "userdefined", "userdefined", ""};

const char* CEvaluationTree::XMLType[] =
  {"Function", "MassAction", "PreDefined", "UserDefined", "Expression", NULL};

CEvaluationTree *
CEvaluationTree::create(CEvaluationTree::Type type)
{
  CEvaluationTree * pNew = NULL;

  switch (type)
    {
    case Function:
      pNew = new CFunction();
      break;

    case MassAction:
      pNew = new CMassAction();
      break;

    case PreDefined:
      pNew = new CKinFunction();
      pNew->setType(PreDefined);
      break;

    case UserDefined:
      pNew = new CKinFunction();
      break;

    case Expression:
      pNew = new CExpression();
      break;

    default:
      fatalError();
    }

  return pNew;
}

CEvaluationTree *
CEvaluationTree::copy(const CEvaluationTree & src)
{
  CEvaluationTree * pNew = NULL;

  switch (src.getType())
    {
    case Function:
      pNew = new CFunction(*static_cast<const CFunction *>(&src));
      break;

    case MassAction:
      pNew = new CMassAction(*static_cast<const CMassAction *>(&src));
      break;

    case PreDefined:
    case UserDefined:
      pNew = new CKinFunction(*static_cast<const CKinFunction *>(&src));
      break;

    case Expression:
      pNew = new CExpression(*static_cast<const CExpression *>(&src));
      break;

    default:
      fatalError();
    }

  return pNew;
}

CEvaluationTree::CEvaluationTree(const std::string & name,
                                 const CCopasiContainer * pParent,
                                 const CEvaluationTree::Type & type):
    CCopasiContainer(name, pParent, "Function"),
    mType(type),
    mKey(GlobalKeys.add("Function", this)),
    mInfix(),
    mErrorPosition(std::string::npos),
    mpNodeList(NULL),
    mpRoot(NULL),
    mValue(std::numeric_limits<C_FLOAT64>::quiet_NaN())
{initObjects();}

CEvaluationTree::CEvaluationTree(const CEvaluationTree & src,
                                 const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mType(src.mType),
    mKey(GlobalKeys.add("Function", this)),
    mInfix(),
    mErrorPosition(std::string::npos),
    mpNodeList(NULL),
    mpRoot(NULL),
    mValue(src.mValue)
{initObjects(); setInfix(src.mInfix);}

CEvaluationTree::~CEvaluationTree()
{
  if (mpNodeList != NULL) CEvaluationParser::freeNodeList(mpNodeList);
  GlobalKeys.remove(mKey);
}

const CEvaluationTree::Type & CEvaluationTree::getType() const
{return mType;}

void CEvaluationTree::setType(const CEvaluationTree::Type & type)
{mType = type;}

const std::string & CEvaluationTree::getKey() const
  {return mKey;}

bool CEvaluationTree::setInfix(const std::string & infix)
{
  if (infix == mInfix) return true;

  mInfix = infix;

  return parse();
}

const std::string & CEvaluationTree::getInfix() const
{return mInfix;;}

const std::vector< CEvaluationNode * > & CEvaluationTree::getNodeList() const
  {return *mpNodeList;}

unsigned C_INT32 CEvaluationTree::getVariableIndex(const std::string & /*name*/) const
  {return C_INVALID_INDEX;}

const C_FLOAT64 & CEvaluationTree::getVariableValue(const unsigned C_INT32 & /*index*/) const
  {
    static C_FLOAT64 Value = std::numeric_limits<C_FLOAT64>::quiet_NaN();
    return Value;
  }

C_FLOAT64 * CEvaluationTree::getObjectValue(const CCopasiObjectName & /*CN*/) const
  {return NULL;}

bool CEvaluationTree::parse()
{
  bool success = true;

  // clean up
  CEvaluationParser::freeNodeList(mpNodeList);
  mpNodeList = NULL;
  mpRoot = NULL;

  // parse the description into a linked node tree
  std::istringstream buffer(mInfix);
  CEvaluationLexer Parser(&buffer);

  CCopasiMessage::clearDeque();

  success = (Parser.yyparse() == 0);

  mpNodeList = Parser.getNodeList();
  mpRoot = Parser.getRootNode();

  // clean up if parsing failed
  if (!success)
    {
      mErrorPosition = Parser.getErrorPosition();

      CEvaluationParser::freeNodeList(mpNodeList);
      mpNodeList = NULL;
      mpRoot = NULL;
    }

  return success;
}

bool CEvaluationTree::compileNodes()
{
  if (mpNodeList == NULL) return false;

  bool success = true;

  std::vector< CEvaluationNode * >::iterator it;
  std::vector< CEvaluationNode * >::iterator end = mpNodeList->end();

  for (it = mpNodeList->begin(); it != end && success; ++it)
    success = (*it)->compile(this);

  if (!success)
    {
      end = it;
      mErrorPosition = 0;

      for (it = mpNodeList->begin(); it != end; ++it)
        mErrorPosition += (*it)->getData().length();

      mErrorPosition -= (*--it)->getData().length();
      CCopasiMessage(CCopasiMessage::ERROR, MCFunction + 3, mErrorPosition);
    }

  return success;
}

bool CEvaluationTree::setRoot(CEvaluationNode* pRootNode)
{
  if (pRootNode == NULL) return false;
  if (mpNodeList != NULL)
    CEvaluationParser::freeNodeList(mpNodeList);

  mpRoot = pRootNode;

  mInfix = mpRoot->getInfix();

  CCopasiTree<CEvaluationNode>::iterator it = mpRoot;
  CCopasiTree<CEvaluationNode>::iterator end = NULL;

  mpNodeList = new std::vector< CEvaluationNode * >;

  for (; it != end; ++it)
    mpNodeList->push_back(&*it);

  return true;
}

bool CEvaluationTree::setTree(const ASTNode& pRootNode)
{
  return this->setRoot(CEvaluationTree::convertASTNode(pRootNode));
}

CEvaluationNode* CEvaluationTree::convertASTNode(const ASTNode& node)
{
  CEvaluationNode* pResultNode = NULL;
  ASTNodeType_t nodeType = node.getType();
  CCopasiMessage Message;
  switch (nodeType)
    {
    case AST_LAMBDA:
      // this nodetype will never be handled directly
      break;
    case AST_PLUS:
    case AST_MINUS:
    case AST_TIMES:
    case AST_DIVIDE:
    case AST_POWER:
    case AST_FUNCTION_POWER:
      // create a CEvaluationNodeOperator
      pResultNode = CEvaluationNodeOperator::createNodeFromASTTree(node);
      break;
    case AST_INTEGER:
    case AST_REAL:
    case AST_REAL_E:
    case AST_RATIONAL:
      // create a CEvaluationNodeNumber
      pResultNode = CEvaluationNodeNumber::createNodeFromASTTree(node);
      break;
    case AST_NAME:
    case AST_NAME_TIME:
      // create a CEvaluationNodeObject
      pResultNode = CEvaluationNodeObject::createNodeFromASTTree(node);
      break;
    case AST_CONSTANT_E:
    case AST_CONSTANT_PI:
    case AST_CONSTANT_FALSE:
    case AST_CONSTANT_TRUE:
      // create a CEvaluationNodeConstant
      pResultNode = CEvaluationNodeConstant::createNodeFromASTTree(node);
      break;
    case AST_FUNCTION:
      // create a function call node
      //pRoot=CEvaluationNode???::createNodeFromASTTree(pRootNode);
      break;
    case AST_FUNCTION_ABS:
    case AST_FUNCTION_ARCCOS:
    case AST_FUNCTION_ARCCOSH:
    case AST_FUNCTION_ARCCOT:
    case AST_FUNCTION_ARCCOTH:
    case AST_FUNCTION_ARCCSC:
    case AST_FUNCTION_ARCCSCH:
    case AST_FUNCTION_ARCSEC:
    case AST_FUNCTION_ARCSECH:
    case AST_FUNCTION_ARCSIN:
    case AST_FUNCTION_ARCSINH:
    case AST_FUNCTION_ARCTAN:
    case AST_FUNCTION_ARCTANH:
    case AST_FUNCTION_CEILING:
    case AST_FUNCTION_COS:
    case AST_FUNCTION_COSH:
    case AST_FUNCTION_COT:
    case AST_FUNCTION_COTH:
    case AST_FUNCTION_CSC:
    case AST_FUNCTION_CSCH:
    case AST_FUNCTION_EXP:
    case AST_FUNCTION_FACTORIAL:
    case AST_FUNCTION_FLOOR:
    case AST_FUNCTION_LN:
    case AST_FUNCTION_LOG:
    case AST_FUNCTION_ROOT:
    case AST_FUNCTION_SEC:
    case AST_FUNCTION_SECH:
    case AST_FUNCTION_SIN:
    case AST_FUNCTION_SINH:
    case AST_FUNCTION_TAN:
    case AST_FUNCTION_TANH:
    case AST_LOGICAL_NOT:
      // create a CEvaluationNodeFunction
      pResultNode = CEvaluationNodeFunction::createNodeFromASTTree(node);
      break;

    case AST_LOGICAL_AND:
    case AST_LOGICAL_OR:
    case AST_LOGICAL_XOR:
    case AST_RELATIONAL_EQ:
    case AST_RELATIONAL_GEQ:
    case AST_RELATIONAL_GT:
    case AST_RELATIONAL_LEQ:
    case AST_RELATIONAL_LT:
    case AST_RELATIONAL_NEQ:
      pResultNode = CEvaluationNodeLogical::createNodeFromASTTree(node);
      break;
    case AST_FUNCTION_PIECEWISE:
      pResultNode = CEvaluationNodeChoice::createNodeFromASTTree(node);
      break;
    case AST_FUNCTION_DELAY:
      // create an unsupported element error
      Message = CCopasiMessage(CCopasiMessage::EXCEPTION, MCMathML + 1,
                               node.getName());
      break;

    case AST_UNKNOWN:
      // create an unknown element error
      Message = CCopasiMessage(CCopasiMessage::EXCEPTION, MCMathML + 2);

      break;
    }
  return pResultNode;
}

CEvaluationNode* CEvaluationTree::getRoot()
{
  return this->mpRoot;
}

void CEvaluationTree::initObjects()
{
  addObjectReference("Value", mValue, CCopasiObject::ValueDbl);
}

ASTNode* CEvaluationTree::toAST() const
  {
    return this->mpRoot->toAST();
  }

void CEvaluationTree::setSBMLId(const std::string& id)
{
  this->mSBMLId = id;
}

const std::string& CEvaluationTree::getSBMLId() const
  {
    return this->mSBMLId;
  }
<|endoftext|>