<commit_before>/*
 * Copyright (c) 2013, Hernan Saez
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Node.hpp"
#include "Group.hpp"

#include "Boundings/AABBBoundingVolume.hpp"

using namespace crimild;

Node::Node( std::string name )
	: NamedObject( name ),
	  _worldIsCurrent( false ),
	  _localBound( crimild::alloc< AABBBoundingVolume >( Vector3f( 0.0f, 0.0f, 0.0f ), 0.5f ) ),
	  _worldBound( crimild::alloc< AABBBoundingVolume >( Vector3f( 0.0f, 0.0f, 0.0f ), 0.5f ) )
{

}

Node::~Node( void )
{
	detachAllComponents();
}

NodePtr Node::getRootParent( void )
{
    auto root = getParent();
    if ( root != nullptr ) {
        while ( root->hasParent() ) {
            root = root->getParent();
        }
    }

    return root;
}

NodePtr Node::detachFromParent( void )
{
    auto node = getShared< Node >();

    GroupPtr parent = getParent< Group >();
    if ( parent != nullptr ) {
        parent->detachNode( node );
    }

    return node;
}

void Node::perform( NodeVisitor &visitor )
{
	visitor.traverse( getShared< Node >() );
}

void Node::perform( const NodeVisitor &visitor )
{
	const_cast< NodeVisitor & >( visitor ).traverse( getShared< Node >() );
}

void Node::accept( NodeVisitor &visitor )
{
	visitor.visitNode( getShared< Node >() );
}

void Node::attachComponent( NodeComponentPtr const &component )
{
	if ( component->getNode() == this ) {
		// the component is already attached to this node
		return;
	}

	detachComponentWithName( component->getComponentName() );
	component->setNode( this );
	_components[ component->getComponentName() ] = component;
	component->onAttach();
}

void Node::detachComponent( NodeComponentPtr const &component )
{
	if ( component->getNode() != this ) {
		// the component is not attached to this node
		return;
	}

	detachComponentWithName( component->getComponentName() );
}

void Node::detachComponentWithName( std::string name )
{
	if ( _components.find( name ) != _components.end() ) {
        auto current = _components[ name ];
        if ( current != nullptr ) {
            current->onDetach();
            current->setNode( nullptr );
        }

        _components[ name ] = nullptr;
		_components.erase( name );
	}
}

NodeComponentPtr Node::getComponentWithName( std::string name )
{
	return _components[ name ];
}

void Node::detachAllComponents( void )
{
    auto cs = _components;
	for ( auto cmp : cs ) {
		if ( cmp.second != nullptr ) {
			cmp.second->onDetach();
			cmp.second->setNode( nullptr );
		}
	}

	_components.clear();
}

void Node::startComponents( void )
{
	foreachComponent( [&]( NodeComponentPtr const &component ) {
		component->start();
	});
}

void Node::updateComponents( const Time &t )
{
    foreachComponent( [&]( NodeComponentPtr const &component ) {
		component->update( t );
	});
}

void Node::foreachComponent( std::function< void ( NodeComponentPtr const & ) > callback )
{
	// create a copy of the component's collection
	// to prevent errors when attaching or detaching
	// components during an update pass
	auto cs = _components;
	for ( auto cmp : cs ) {
		if ( cmp.second != nullptr ) {
			callback( cmp.second );
		}
	}
}

<commit_msg>Increased default bounding volume size<commit_after>/*
 * Copyright (c) 2013, Hernan Saez
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Node.hpp"
#include "Group.hpp"

#include "Boundings/AABBBoundingVolume.hpp"

using namespace crimild;

Node::Node( std::string name )
	: NamedObject( name ),
	  _worldIsCurrent( false ),
	  _localBound( crimild::alloc< AABBBoundingVolume >( Vector3f( 0.0f, 0.0f, 0.0f ), 1.0f ) ),
	  _worldBound( crimild::alloc< AABBBoundingVolume >( Vector3f( 0.0f, 0.0f, 0.0f ), 1.0f ) )
{

}

Node::~Node( void )
{
	detachAllComponents();
}

NodePtr Node::getRootParent( void )
{
    auto root = getParent();
    if ( root != nullptr ) {
        while ( root->hasParent() ) {
            root = root->getParent();
        }
    }

    return root;
}

NodePtr Node::detachFromParent( void )
{
    auto node = getShared< Node >();

    GroupPtr parent = getParent< Group >();
    if ( parent != nullptr ) {
        parent->detachNode( node );
    }

    return node;
}

void Node::perform( NodeVisitor &visitor )
{
	visitor.traverse( getShared< Node >() );
}

void Node::perform( const NodeVisitor &visitor )
{
	const_cast< NodeVisitor & >( visitor ).traverse( getShared< Node >() );
}

void Node::accept( NodeVisitor &visitor )
{
	visitor.visitNode( getShared< Node >() );
}

void Node::attachComponent( NodeComponentPtr const &component )
{
	if ( component->getNode() == this ) {
		// the component is already attached to this node
		return;
	}

	detachComponentWithName( component->getComponentName() );
	component->setNode( this );
	_components[ component->getComponentName() ] = component;
	component->onAttach();
}

void Node::detachComponent( NodeComponentPtr const &component )
{
	if ( component->getNode() != this ) {
		// the component is not attached to this node
		return;
	}

	detachComponentWithName( component->getComponentName() );
}

void Node::detachComponentWithName( std::string name )
{
	if ( _components.find( name ) != _components.end() ) {
        auto current = _components[ name ];
        if ( current != nullptr ) {
            current->onDetach();
            current->setNode( nullptr );
        }

        _components[ name ] = nullptr;
		_components.erase( name );
	}
}

NodeComponentPtr Node::getComponentWithName( std::string name )
{
	return _components[ name ];
}

void Node::detachAllComponents( void )
{
    auto cs = _components;
	for ( auto cmp : cs ) {
		if ( cmp.second != nullptr ) {
			cmp.second->onDetach();
			cmp.second->setNode( nullptr );
		}
	}

	_components.clear();
}

void Node::startComponents( void )
{
	foreachComponent( [&]( NodeComponentPtr const &component ) {
		component->start();
	});
}

void Node::updateComponents( const Time &t )
{
    foreachComponent( [&]( NodeComponentPtr const &component ) {
		component->update( t );
	});
}

void Node::foreachComponent( std::function< void ( NodeComponentPtr const & ) > callback )
{
	// create a copy of the component's collection
	// to prevent errors when attaching or detaching
	// components during an update pass
	auto cs = _components;
	for ( auto cmp : cs ) {
		if ( cmp.second != nullptr ) {
			callback( cmp.second );
		}
	}
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-present, H. Hernan Saez
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef CRIMILD_SCENE_GRAPH_NODE_
#define CRIMILD_SCENE_GRAPH_NODE_

#include "Boundings/BoundingVolume.hpp"
#include "Coding/Codable.hpp"
#include "Components/NodeComponent.hpp"
#include "Foundation/NamedObject.hpp"
#include "Foundation/SharedObject.hpp"
#include "Mathematics/Transformation.hpp"
#include "Mathematics/Transformation_constants.hpp"
#include "Visitors/NodeVisitor.hpp"

#include <map>

namespace crimild {

    /**
		\brief Base class for any object that can be attached to the scene graph
	*/
    class Node
        : public NamedObject,
          public coding::Codable {
        CRIMILD_IMPLEMENT_RTTI( crimild::Node )

    public:
        explicit Node( std::string name = "" );
        virtual ~Node( void );

    public:
        bool hasParent( void ) const { return _parent != nullptr; }

        Node *getParent( void ) { return _parent; }

        template< class NodeClass >
        NodeClass *getParent( void )
        {
            return static_cast< NodeClass * >( _parent );
        }

        void setParent( Node *parent ) { _parent = parent; }

        SharedPointer< Node > detachFromParent( void );

        Node *getRootParent( void );

        template< class NodeClass >
        NodeClass *getRootParent( void )
        {
            return static_cast< NodeClass * >( getRootParent() );
        }

    private:
        /**
			\brief A node's parent

			Every node if linked with its parent in the node hierarchy (provided
			one is available).
		*/
        Node *_parent = nullptr;

    public:
        void perform( NodeVisitor &visitor );
        void perform( const NodeVisitor &visitor );

        virtual void accept( NodeVisitor &visitor );

    public:
        NodeComponent *getComponentWithName( std::string name )
        {
            return crimild::get_ptr( _components[ name ] );
        }

        template< class NODE_COMPONENT_CLASS >
        NODE_COMPONENT_CLASS *getComponent( void )
        {
            return static_cast< NODE_COMPONENT_CLASS * >( getComponentWithName( NODE_COMPONENT_CLASS::__CLASS_NAME ) );
        }

        bool hasComponent( SharedPointer< NodeComponent > const &component )
        {
            return hasComponent( crimild::get_ptr( component ) );
        }

        bool hasComponent( NodeComponent *component )
        {
            auto it = _components.find( component->getComponentName() );
            return ( it != _components.end() && crimild::get_ptr( it->second ) == component );
        }

        void attachComponent( NodeComponent *component );
        void attachComponent( SharedPointer< NodeComponent > const &component );

        template< typename T, typename... Args >
        T *attachComponent( Args &&...args )
        {
            auto cmp = crimild::alloc< T >( std::forward< Args >( args )... );
            attachComponent( cmp );
            return crimild::get_ptr( cmp );
        }

        void detachComponent( NodeComponent *component );
        void detachComponent( SharedPointer< NodeComponent > const &component );

        SharedPointer< NodeComponent > detachComponentWithName( std::string name );

        void detachAllComponents( void );

        void startComponents( void );

        void updateComponents( const Clock &clock );

        void forEachComponent( std::function< void( NodeComponent * ) > callback );

    private:
        std::map< std::string, SharedPointer< NodeComponent > > _components;

    public:
        void setLocal( const Transformation &t ) { _local = t; }
        const Transformation &getLocal( void ) const { return _local; }
        Transformation &local( void ) { return _local; }

        void setWorld( const Transformation &t ) { _world = t; }
        const Transformation &getWorld( void ) const { return _world; }
        Transformation &world( void ) { return _world; }

        bool worldIsCurrent( void ) const { return _worldIsCurrent; }
        void setWorldIsCurrent( bool isCurrent ) { _worldIsCurrent = isCurrent; }

    private:
        Transformation _local = Transformation::Constants::IDENTITY;
        Transformation _world = Transformation::Constants::IDENTITY;

        /**
			\brief Indicates if the world transformation needs to be updated automatically

			This flag can be used to avoid the automatic update of world transformations.
			By default, the engine will compute the world transformation for a node as
			a function of its parent's one. If this flag is set to 'true' (default is 'false'),
			you need to provide a valid world matrix manually
		*/
        bool _worldIsCurrent;

    public:
        BoundingVolume *localBound( void ) { return crimild::get_ptr( _localBound ); }
        const BoundingVolume *getLocalBound( void ) const { return crimild::get_ptr( _localBound ); }
        void setLocalBound( BoundingVolume *bound ) { _localBound = crimild::retain( bound ); }
        void setLocalBound( SharedPointer< BoundingVolume > const &bound ) { _localBound = bound; }

        BoundingVolume *worldBound( void ) { return crimild::get_ptr( _worldBound ); }
        const BoundingVolume *getWorldBound( void ) const { return crimild::get_ptr( _worldBound ); }
        void setWorldBound( BoundingVolume *bound ) { _worldBound = crimild::retain( bound ); }
        void setWorldBound( SharedPointer< BoundingVolume > const &bound ) { _worldBound = bound; }

    private:
        SharedPointer< BoundingVolume > _localBound;
        SharedPointer< BoundingVolume > _worldBound;

    public:
        void setEnabled( bool enabled ) { _enabled = enabled; }
        bool isEnabled( void ) { return _enabled; }

    private:
        bool _enabled = true;

        /**
		   \name Layers
		*/
        //@{

    public:
        /**
		   \brief Node layers

		   Layers are defined as integers so users can create their own in between
		   the default ones.
		 */
        struct Layer {
            enum {
                DEFAULT = 0,
                SKYBOX = 1 << 10,
                SCREEN = 1 << 12
            };

            using Impl = crimild::Int32;
        };

        inline Layer::Impl getLayer( void ) const { return _layer; }
        void setLayer( Layer::Impl value ) { _layer = value; }

    private:
        Layer::Impl _layer = Layer::DEFAULT;

        //@}

        /**
		   \name Cull flag
		 */
        //@{
    public:
        struct CullMode {
            enum {
                NEVER,
                DEFAULT,
                ALWAYS,
            };

            using Impl = crimild::Int32;
        };

        inline CullMode::Impl getCullMode( void ) const { return _cullMode; }
        void setCullMode( CullMode::Impl value ) { _cullMode = value; }

    private:
        CullMode::Impl _cullMode = CullMode::DEFAULT;

        //@}

        /**
            \name Coding support
         */
        //@{
    public:
        virtual void encode( coding::Encoder &encoder ) override;
        virtual void decode( coding::Decoder &decoder ) override;

        //@}
    };

}

#endif
<commit_msg>New perform function for Nodes<commit_after>/*
 * Copyright (c) 2002-present, H. Hernan Saez
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef CRIMILD_SCENE_GRAPH_NODE_
#define CRIMILD_SCENE_GRAPH_NODE_

#include "Boundings/BoundingVolume.hpp"
#include "Coding/Codable.hpp"
#include "Components/NodeComponent.hpp"
#include "Foundation/NamedObject.hpp"
#include "Foundation/SharedObject.hpp"
#include "Mathematics/Transformation.hpp"
#include "Mathematics/Transformation_constants.hpp"
#include "Visitors/NodeVisitor.hpp"

#include <map>

namespace crimild {

    /**
		\brief Base class for any object that can be attached to the scene graph
	*/
    class Node
        : public NamedObject,
          public coding::Codable {
        CRIMILD_IMPLEMENT_RTTI( crimild::Node )

    public:
        explicit Node( std::string name = "" );
        virtual ~Node( void );

    public:
        bool hasParent( void ) const { return _parent != nullptr; }

        Node *getParent( void ) { return _parent; }

        template< class NodeClass >
        NodeClass *getParent( void )
        {
            return static_cast< NodeClass * >( _parent );
        }

        void setParent( Node *parent ) { _parent = parent; }

        SharedPointer< Node > detachFromParent( void );

        Node *getRootParent( void );

        template< class NodeClass >
        NodeClass *getRootParent( void )
        {
            return static_cast< NodeClass * >( getRootParent() );
        }

    private:
        /**
			\brief A node's parent

			Every node if linked with its parent in the node hierarchy (provided
			one is available).
		*/
        Node *_parent = nullptr;

    public:
        void perform( NodeVisitor &visitor );
        void perform( const NodeVisitor &visitor );

        template< typename VisitorType, typename... Args >
        typename VisitorType::Result perform( Args &&...args ) noexcept
        {
            VisitorType visitor( std::forward< Args >( args )... );
            perform( visitor );
            return visitor.getResult();
        }

        virtual void accept( NodeVisitor &visitor );

    public:
        NodeComponent *getComponentWithName( std::string name )
        {
            return crimild::get_ptr( _components[ name ] );
        }

        template< class NODE_COMPONENT_CLASS >
        NODE_COMPONENT_CLASS *getComponent( void )
        {
            return static_cast< NODE_COMPONENT_CLASS * >( getComponentWithName( NODE_COMPONENT_CLASS::__CLASS_NAME ) );
        }

        bool hasComponent( SharedPointer< NodeComponent > const &component )
        {
            return hasComponent( crimild::get_ptr( component ) );
        }

        bool hasComponent( NodeComponent *component )
        {
            auto it = _components.find( component->getComponentName() );
            return ( it != _components.end() && crimild::get_ptr( it->second ) == component );
        }

        void attachComponent( NodeComponent *component );
        void attachComponent( SharedPointer< NodeComponent > const &component );

        template< typename T, typename... Args >
        T *attachComponent( Args &&...args )
        {
            auto cmp = crimild::alloc< T >( std::forward< Args >( args )... );
            attachComponent( cmp );
            return crimild::get_ptr( cmp );
        }

        void detachComponent( NodeComponent *component );
        void detachComponent( SharedPointer< NodeComponent > const &component );

        SharedPointer< NodeComponent > detachComponentWithName( std::string name );

        void detachAllComponents( void );

        void startComponents( void );

        void updateComponents( const Clock &clock );

        void forEachComponent( std::function< void( NodeComponent * ) > callback );

    private:
        std::map< std::string, SharedPointer< NodeComponent > > _components;

    public:
        void setLocal( const Transformation &t ) { _local = t; }
        const Transformation &getLocal( void ) const { return _local; }
        Transformation &local( void ) { return _local; }

        void setWorld( const Transformation &t ) { _world = t; }
        const Transformation &getWorld( void ) const { return _world; }
        Transformation &world( void ) { return _world; }

        bool worldIsCurrent( void ) const { return _worldIsCurrent; }
        void setWorldIsCurrent( bool isCurrent ) { _worldIsCurrent = isCurrent; }

    private:
        Transformation _local = Transformation::Constants::IDENTITY;
        Transformation _world = Transformation::Constants::IDENTITY;

        /**
			\brief Indicates if the world transformation needs to be updated automatically

			This flag can be used to avoid the automatic update of world transformations.
			By default, the engine will compute the world transformation for a node as
			a function of its parent's one. If this flag is set to 'true' (default is 'false'),
			you need to provide a valid world matrix manually
		*/
        bool _worldIsCurrent;

    public:
        BoundingVolume *localBound( void ) { return crimild::get_ptr( _localBound ); }
        const BoundingVolume *getLocalBound( void ) const { return crimild::get_ptr( _localBound ); }
        void setLocalBound( BoundingVolume *bound ) { _localBound = crimild::retain( bound ); }
        void setLocalBound( SharedPointer< BoundingVolume > const &bound ) { _localBound = bound; }

        BoundingVolume *worldBound( void ) { return crimild::get_ptr( _worldBound ); }
        const BoundingVolume *getWorldBound( void ) const { return crimild::get_ptr( _worldBound ); }
        void setWorldBound( BoundingVolume *bound ) { _worldBound = crimild::retain( bound ); }
        void setWorldBound( SharedPointer< BoundingVolume > const &bound ) { _worldBound = bound; }

    private:
        SharedPointer< BoundingVolume > _localBound;
        SharedPointer< BoundingVolume > _worldBound;

    public:
        void setEnabled( bool enabled ) { _enabled = enabled; }
        bool isEnabled( void ) { return _enabled; }

    private:
        bool _enabled = true;

        /**
		   \name Layers
		*/
        //@{

    public:
        /**
		   \brief Node layers

		   Layers are defined as integers so users can create their own in between
		   the default ones.
		 */
        struct Layer {
            enum {
                DEFAULT = 0,
                SKYBOX = 1 << 10,
                SCREEN = 1 << 12
            };

            using Impl = crimild::Int32;
        };

        inline Layer::Impl getLayer( void ) const { return _layer; }
        void setLayer( Layer::Impl value ) { _layer = value; }

    private:
        Layer::Impl _layer = Layer::DEFAULT;

        //@}

        /**
		   \name Cull flag
		 */
        //@{
    public:
        struct CullMode {
            enum {
                NEVER,
                DEFAULT,
                ALWAYS,
            };

            using Impl = crimild::Int32;
        };

        inline CullMode::Impl getCullMode( void ) const { return _cullMode; }
        void setCullMode( CullMode::Impl value ) { _cullMode = value; }

    private:
        CullMode::Impl _cullMode = CullMode::DEFAULT;

        //@}

        /**
            \name Coding support
         */
        //@{
    public:
        virtual void encode( coding::Encoder &encoder ) override;
        virtual void decode( coding::Decoder &decoder ) override;

        //@}
    };

}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2014 Kerem KAT
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files(the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Do not hesisate to contact me about usage of the code or to make comments
// about the code. Your feedback will be appreciated.
//
// http://dissipatedheat.com/
// http://github.com/krk/

#include <vector>
#include <iostream>
#include "LPModel.h"
#include <boost/range/algorithm/set_algorithm.hpp>
#include <chrono>
#include <boost/program_options.hpp>

#define TIMING

#ifdef TIMING
#define INIT_TIMER auto start = std::chrono::high_resolution_clock::now()
#define START_TIMER start = std::chrono::high_resolution_clock::now()
#define STOP_TIMER()  ( \
	std::chrono::duration_cast<std::chrono::milliseconds>( \
	std::chrono::high_resolution_clock::now()-start \
	).count())
#define STOP_TIMER_SEC() (STOP_TIMER() / 60)
#else
#define INIT_TIMER
#define START_TIMER
#define STOP_TIMER() (0)
#define STOP_TIMER_SEC() (0)
#endif

using std::cout;
using std::endl;
using lpcompare::LPModel;

/**
\file lpcompare.cpp
Handles command line arguments and has the main method.
*/

namespace po = boost::program_options;

template <typename T>
void printCounts(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother);

template <>
void printCounts(std::string detail_name, std::vector<lpcompare::Bound> &vec, std::vector<lpcompare::Bound> &vecother);

template <>
void printCounts(std::string detail_name, std::vector<lpcompare::Constraint> &vec, std::vector<lpcompare::Constraint> &vecother);

template <typename T>
void printCountsWithSort(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother);

void printStats(LPModel *model);

template <typename T>
void dumpdiff_if_requested(std::string detail_name, std::vector<T> &set1Except2, std::vector<T> &set2Except1);

std::string first_filename;  /**< Filename of the first LP model. */
std::string second_filename; /**< Filename of the second LP model. */

po::variables_map vm; /**< Variable map for boost::program_options. */

/**
Parses program arguments using boost program_options.

\param argc argument count.
\param argv argument list.
*/
void setup_options(int argc, char *argv []) {

	po::positional_options_description p;
	p.add("first", 1);
	p.add("second", 1);

	po::options_description desc("Usage");
	desc.add_options()
		("help", "show usage information")
		("first", po::value<std::string>(&first_filename)->required(), "model 1 cplex lp file")
		("second", po::value<std::string>(&second_filename)->required(), "model 2 cplex lp file")
		("dump-prefix", po::value<std::string>()->default_value("diffdump"), "filename prefix for difference dumps")
		("dump-diffs", po::value<bool>()->default_value(true), "filename prefix for difference dumps")
		;

	try
	{
		po::store(po::command_line_parser(argc, argv).
			options(desc).positional(p).run(), vm);

		if (vm.count("help")) {
			cout << desc << "\n";
			exit(1);
		}

		po::notify(vm);
	}
	catch (po::required_option& e)
	{
		std::cerr << "Error: " << e.what() << std::endl << std::endl;

		cout << desc << "\n";
		exit(1);
	}
}

/**
Creates a filename to dump differences into.

\param model Model name.
\param detail Model detail.
\return dump filename.
*/
std::string get_dump_filename(std::string model, std::string detail) {
	return vm["dump-prefix"].as<std::string>() + "-" + model + "-" + detail + ".log";
}

/**
Checks if diff dumps are requested.

\return true if diff dumps are requested.
*/
bool is_diffdumps_requested() {
	return vm["dump-diffs"].as<bool>();
}

int main(int argc, char *argv [])
{
	INIT_TIMER;

	cout << "lpcompare: Compares two LP files created in cplex format and dumps differences to files." << endl;

	setup_options(argc, argv);

	LPModel* model1 = new LPModel();
	LPModel* model2 = new LPModel();

	START_TIMER;
	cout << "Reading first model: " << first_filename << endl;
	if (!model1->ReadModel(first_filename)) {
		exit(1);
	}
	cout << " First model:" << endl;
	printStats(model1);
	auto first_model_read_sec = STOP_TIMER_SEC();
	cout << " Model read in " << first_model_read_sec << " s" << endl;

	START_TIMER;
	cout << "Reading second model: " << second_filename << endl;
	if (!model2->ReadModel(second_filename)) {
		exit(1);
	}
	cout << " Second Model:" << endl;
	printStats(model2);
	auto second_model_read_sec = STOP_TIMER_SEC();
	cout << " Model read in " << second_model_read_sec << " s" << endl;

	cout << endl;

	printCounts("Generals", model1->Generals, model2->Generals);
	printCounts("Binaries", model1->Binaries, model2->Binaries);
	printCounts("SosVars", model1->SosVars, model2->SosVars);

	START_TIMER;
	printCounts("Bounds", model1->Bounds, model2->Bounds);
	auto bounds_check_sec = STOP_TIMER_SEC();
	cout << " Bounds check completed in " << bounds_check_sec << " s" << endl;

	START_TIMER;
	printCounts("Constraints", model1->Constraints, model2->Constraints);
	auto cons_check_sec = STOP_TIMER_SEC();
	cout << " Constraints check completed in " << cons_check_sec << " s" << endl;

	return 0;
}

/**
Prints statistics for a model.

\param model Model.
*/
void printStats(LPModel *model) {
	cout << "Binaries: " << model->Binaries.size() << endl;
	cout << "Bounds: " << model->Bounds.size() << endl;
	cout << "Constraints: " << model->Constraints.size() << endl;
	cout << "Generals: " << model->Generals.size() << endl;
	cout << "SosVars: " << model->SosVars.size() << endl;
}

/**
Dumps diffs to a file if dumping is requested.

\param set1Except2 List of elements that are in the first model but not in the second model.
\param set2Except1 List of elements that are in the second model but not in the first model.
*/
template <typename T>
void dumpdiff_if_requested(std::string detail_name, std::vector<T> &set1Except2, std::vector<T> &set2Except1) {

	if (!is_diffdumps_requested())
		return;

	if (set1Except2.size() > 0) {

		auto filename1e2 = get_dump_filename("firstEXCEPTsecond", detail_name);
		std::ofstream out_file_1(filename1e2);

		if (!out_file_1) {
			cout << "Cannot open or create file for writing: " << filename1e2;
			return;
		}

		out_file_1 << "firstEXCEPTsecond " << detail_name << std::endl;
		for (auto item : set1Except2) {
			out_file_1 << item << std::endl;
		}

		out_file_1.flush();
		out_file_1.close();

		cout << "firstEXCEPTsecond diff written for " << detail_name << " to " << filename1e2 << std::endl;
	}

	if (set2Except1.size() > 0) {

		auto filename2e1 = get_dump_filename("secondEXCEPTfirst", detail_name);
		std::ofstream out_file_2(filename2e1);

		if (!out_file_2) {
			cout << "Cannot open or create file for writing: " << filename2e1;
			return;
		}

		out_file_2 << "secondEXCEPTfirst " << detail_name << std::endl;
		for (auto item : set2Except1) {
			out_file_2 << item << std::endl;
		}

		out_file_2.flush();
		out_file_2.close();

		cout << "secondEXCEPTfirst diff written for " << detail_name << " to " << filename2e1 << std::endl;
	}
}

/**
Prints count of a given detail for both models, including differences.

\param detail_name Given name of the detail.
\param vec List of elements that are in the first model.
\param vecother List of elements that are in the second model.
*/
template <typename T>
void printCounts(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother)
{
	cout << detail_name << " First Model: " << vec.size() << endl;
	cout << detail_name << " Second Model: " << vecother.size() << endl;

	std::vector<T> set1Except2;
	std::set_difference(vec.begin(), vec.end(), vecother.begin(), vecother.end(), std::back_inserter(set1Except2));

	std::vector<T> set2Except1;
	std::set_difference(vecother.begin(), vecother.end(), vec.begin(), vec.end(), std::back_inserter(set2Except1));

	auto size1e2 = set1Except2.size();
	auto size2e1 = set1Except2.size();

	if (size1e2 == 0 && size2e1 == 0) {
		cout << detail_name << " are equivalent." << endl;
	}
	else {
		cout << detail_name << " First except Second: " << set1Except2.size() << endl;
		cout << detail_name << " Second except First: " << set2Except1.size() << endl;
	}

	dumpdiff_if_requested(detail_name, set1Except2, set2Except1);
}

/**
Prints count of a given detail for both models, including differences.
Performs in-place sorting of vec and vecother.
\param detail_name Given name of the detail.
\param vec List of elements that are in the first model.
\param vecother List of elements that are in the second model.
*/
template <typename T>
void printCountsWithSort(std::string name, std::vector<T> &vec, std::vector<T> &vecother)
{
	cout << name << " First Model: " << vec.size() << endl;
	cout << name << " Second Model: " << vecother.size() << endl;

	std::vector<T> set1Except2;
	std::vector<T> set2Except1;

	std::sort(vec.begin(), vec.end());
	std::sort(vecother.begin(), vecother.end());

	auto it = vec.begin();
	auto ot = vecother.begin();

	while (it != vec.end() && ot != vecother.end())
	{
		auto item = *it;
		auto other = *ot;

		if (item == other) {
			++it;
			++ot;
		}
		else if (item < other) {
			set1Except2.push_back(item);
			++it;
		}
		else {
			set2Except1.push_back(other);
			++ot;
		}
	}

	while (it != vec.end())
	{
		set1Except2.push_back(*it);
		++it;
	}

	while (ot != vecother.end())
	{
		set2Except1.push_back(*ot);
		++ot;
	}

	auto size1e2 = set1Except2.size();
	auto size2e1 = set2Except1.size();

	if (size1e2 == 0 && size2e1 == 0) {
		cout << name << " are equivalent." << endl;
	}
	else {
		cout << name << " First except Second: " << set1Except2.size() << endl;
		cout << name << " Second except First: " << set2Except1.size() << endl;
	}

	dumpdiff_if_requested(name, set1Except2, set2Except1);
}

/**
printCounts specialization for Constraints, which will be sorted before set operations.

\param detail_name Given name of the detail.
\param vec List of elements that are in the first model.
\param vecother List of elements that are in the second model.
*/
template <>
void printCounts(std::string detail_name, std::vector<lpcompare::Constraint> &vec, std::vector<lpcompare::Constraint> &vecother)
{
	printCountsWithSort(detail_name, vec, vecother);
}

/**
printCounts specialization for Bounds, which will be sorted before set operations.

\param detail_name Given name of the detail.
\param vec List of elements that are in the first model.
\param vecother List of elements that are in the second model.
*/
template <>
void printCounts(std::string detail_name, std::vector<lpcompare::Bound> &vec, std::vector<lpcompare::Bound> &vecother)
{
	printCountsWithSort(detail_name, vec, vecother);
}
<commit_msg>Fix: set_difference requires sorted input.<commit_after>// Copyright (c) 2014 Kerem KAT
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files(the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Do not hesisate to contact me about usage of the code or to make comments
// about the code. Your feedback will be appreciated.
//
// http://dissipatedheat.com/
// http://github.com/krk/

#include <vector>
#include <iostream>
#include "LPModel.h"
#include <boost/range/algorithm/set_algorithm.hpp>
#include <chrono>
#include <boost/program_options.hpp>

#define TIMING

#ifdef TIMING
#define INIT_TIMER auto start = std::chrono::high_resolution_clock::now()
#define START_TIMER start = std::chrono::high_resolution_clock::now()
#define STOP_TIMER()  ( \
	std::chrono::duration_cast<std::chrono::milliseconds>( \
	std::chrono::high_resolution_clock::now()-start \
	).count())
#define STOP_TIMER_SEC() (STOP_TIMER() / 60)
#else
#define INIT_TIMER
#define START_TIMER
#define STOP_TIMER() (0)
#define STOP_TIMER_SEC() (0)
#endif

using std::cout;
using std::endl;
using lpcompare::LPModel;

/**
\file lpcompare.cpp
Handles command line arguments and has the main method.
*/

namespace po = boost::program_options;

template <typename T>
void printCounts(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother);

template <>
void printCounts(std::string detail_name, std::vector<lpcompare::Bound> &vec, std::vector<lpcompare::Bound> &vecother);

template <>
void printCounts(std::string detail_name, std::vector<lpcompare::Constraint> &vec, std::vector<lpcompare::Constraint> &vecother);

template <typename T>
void printCountsWithSort(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother);

void printStats(LPModel *model);

template <typename T>
void dumpdiff_if_requested(std::string detail_name, std::vector<T> &set1Except2, std::vector<T> &set2Except1);

std::string first_filename;  /**< Filename of the first LP model. */
std::string second_filename; /**< Filename of the second LP model. */

po::variables_map vm; /**< Variable map for boost::program_options. */

/**
Parses program arguments using boost program_options.

\param argc argument count.
\param argv argument list.
*/
void setup_options(int argc, char *argv []) {

	po::positional_options_description p;
	p.add("first", 1);
	p.add("second", 1);

	po::options_description desc("Usage");
	desc.add_options()
		("help", "show usage information")
		("first", po::value<std::string>(&first_filename)->required(), "model 1 cplex lp file")
		("second", po::value<std::string>(&second_filename)->required(), "model 2 cplex lp file")
		("dump-prefix", po::value<std::string>()->default_value("diffdump"), "filename prefix for difference dumps")
		("dump-diffs", po::value<bool>()->default_value(true), "filename prefix for difference dumps")
		;

	try
	{
		po::store(po::command_line_parser(argc, argv).
			options(desc).positional(p).run(), vm);

		if (vm.count("help")) {
			cout << desc << "\n";
			exit(1);
		}

		po::notify(vm);
	}
	catch (po::required_option& e)
	{
		std::cerr << "Error: " << e.what() << std::endl << std::endl;

		cout << desc << "\n";
		exit(1);
	}
}

/**
Creates a filename to dump differences into.

\param model Model name.
\param detail Model detail.
\return dump filename.
*/
std::string get_dump_filename(std::string model, std::string detail) {
	return vm["dump-prefix"].as<std::string>() + "-" + model + "-" + detail + ".log";
}

/**
Checks if diff dumps are requested.

\return true if diff dumps are requested.
*/
bool is_diffdumps_requested() {
	return vm["dump-diffs"].as<bool>();
}

int main(int argc, char *argv [])
{
	INIT_TIMER;

	cout << "lpcompare: Compares two LP files created in cplex format and dumps differences to files." << endl;

	setup_options(argc, argv);

	LPModel* model1 = new LPModel();
	LPModel* model2 = new LPModel();

	START_TIMER;
	cout << "Reading first model: " << first_filename << endl;
	if (!model1->ReadModel(first_filename)) {
		exit(1);
	}
	cout << " First model:" << endl;
	printStats(model1);
	auto first_model_read_sec = STOP_TIMER_SEC();
	cout << " Model read in " << first_model_read_sec << " s" << endl;

	START_TIMER;
	cout << "Reading second model: " << second_filename << endl;
	if (!model2->ReadModel(second_filename)) {
		exit(1);
	}
	cout << " Second Model:" << endl;
	printStats(model2);
	auto second_model_read_sec = STOP_TIMER_SEC();
	cout << " Model read in " << second_model_read_sec << " s" << endl;

	cout << endl;

	printCounts("Generals", model1->Generals, model2->Generals);
	printCounts("Binaries", model1->Binaries, model2->Binaries);
	printCounts("SosVars", model1->SosVars, model2->SosVars);

	START_TIMER;
	printCounts("Bounds", model1->Bounds, model2->Bounds);
	auto bounds_check_sec = STOP_TIMER_SEC();
	cout << " Bounds check completed in " << bounds_check_sec << " s" << endl;

	START_TIMER;
	printCounts("Constraints", model1->Constraints, model2->Constraints);
	auto cons_check_sec = STOP_TIMER_SEC();
	cout << " Constraints check completed in " << cons_check_sec << " s" << endl;

	return 0;
}

/**
Prints statistics for a model.

\param model Model.
*/
void printStats(LPModel *model) {
	cout << "Binaries: " << model->Binaries.size() << endl;
	cout << "Bounds: " << model->Bounds.size() << endl;
	cout << "Constraints: " << model->Constraints.size() << endl;
	cout << "Generals: " << model->Generals.size() << endl;
	cout << "SosVars: " << model->SosVars.size() << endl;
}

/**
Dumps diffs to a file if dumping is requested.

\param set1Except2 List of elements that are in the first model but not in the second model.
\param set2Except1 List of elements that are in the second model but not in the first model.
*/
template <typename T>
void dumpdiff_if_requested(std::string detail_name, std::vector<T> &set1Except2, std::vector<T> &set2Except1) {

	if (!is_diffdumps_requested())
		return;

	if (set1Except2.size() > 0) {

		auto filename1e2 = get_dump_filename("firstEXCEPTsecond", detail_name);
		std::ofstream out_file_1(filename1e2);

		if (!out_file_1) {
			cout << "Cannot open or create file for writing: " << filename1e2;
			return;
		}

		out_file_1 << "firstEXCEPTsecond " << detail_name << std::endl;
		for (auto item : set1Except2) {
			out_file_1 << item << std::endl;
		}

		out_file_1.flush();
		out_file_1.close();

		cout << "firstEXCEPTsecond diff written for " << detail_name << " to " << filename1e2 << std::endl;
	}

	if (set2Except1.size() > 0) {

		auto filename2e1 = get_dump_filename("secondEXCEPTfirst", detail_name);
		std::ofstream out_file_2(filename2e1);

		if (!out_file_2) {
			cout << "Cannot open or create file for writing: " << filename2e1;
			return;
		}

		out_file_2 << "secondEXCEPTfirst " << detail_name << std::endl;
		for (auto item : set2Except1) {
			out_file_2 << item << std::endl;
		}

		out_file_2.flush();
		out_file_2.close();

		cout << "secondEXCEPTfirst diff written for " << detail_name << " to " << filename2e1 << std::endl;
	}
}

/**
Prints count of a given detail for both models, including differences.

\param detail_name Given name of the detail.
\param vec List of elements that are in the first model.
\param vecother List of elements that are in the second model.
*/
template <typename T>
void printCounts(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother)
{
	cout << detail_name << " First Model: " << vec.size() << endl;
	cout << detail_name << " Second Model: " << vecother.size() << endl;

	std::sort(vec.begin(), vec.end());
	std::sort(vecother.begin(), vecother.end());

	std::vector<T> set1Except2;
	std::set_difference(vec.begin(), vec.end(), vecother.begin(), vecother.end(), std::back_inserter(set1Except2));

	std::vector<T> set2Except1;
	std::set_difference(vecother.begin(), vecother.end(), vec.begin(), vec.end(), std::back_inserter(set2Except1));

	auto size1e2 = set1Except2.size();
	auto size2e1 = set1Except2.size();

	if (size1e2 == 0 && size2e1 == 0) {
		cout << detail_name << " are equivalent." << endl;
	}
	else {
		cout << detail_name << " First except Second: " << set1Except2.size() << endl;
		cout << detail_name << " Second except First: " << set2Except1.size() << endl;
	}

	dumpdiff_if_requested(detail_name, set1Except2, set2Except1);
}

/**
Prints count of a given detail for both models, including differences.
Performs in-place sorting of vec and vecother.
\param detail_name Given name of the detail.
\param vec List of elements that are in the first model.
\param vecother List of elements that are in the second model.
*/
template <typename T>
void printCountsWithSort(std::string name, std::vector<T> &vec, std::vector<T> &vecother)
{
	cout << name << " First Model: " << vec.size() << endl;
	cout << name << " Second Model: " << vecother.size() << endl;

	std::vector<T> set1Except2;
	std::vector<T> set2Except1;

	std::sort(vec.begin(), vec.end());
	std::sort(vecother.begin(), vecother.end());

	auto it = vec.begin();
	auto ot = vecother.begin();

	while (it != vec.end() && ot != vecother.end())
	{
		auto item = *it;
		auto other = *ot;

		if (item == other) {
			++it;
			++ot;
		}
		else if (item < other) {
			set1Except2.push_back(item);
			++it;
		}
		else {
			set2Except1.push_back(other);
			++ot;
		}
	}

	while (it != vec.end())
	{
		set1Except2.push_back(*it);
		++it;
	}

	while (ot != vecother.end())
	{
		set2Except1.push_back(*ot);
		++ot;
	}

	auto size1e2 = set1Except2.size();
	auto size2e1 = set2Except1.size();

	if (size1e2 == 0 && size2e1 == 0) {
		cout << name << " are equivalent." << endl;
	}
	else {
		cout << name << " First except Second: " << set1Except2.size() << endl;
		cout << name << " Second except First: " << set2Except1.size() << endl;
	}

	dumpdiff_if_requested(name, set1Except2, set2Except1);
}

/**
printCounts specialization for Constraints, which will be sorted before set operations.

\param detail_name Given name of the detail.
\param vec List of elements that are in the first model.
\param vecother List of elements that are in the second model.
*/
template <>
void printCounts(std::string detail_name, std::vector<lpcompare::Constraint> &vec, std::vector<lpcompare::Constraint> &vecother)
{
	printCountsWithSort(detail_name, vec, vecother);
}

/**
printCounts specialization for Bounds, which will be sorted before set operations.

\param detail_name Given name of the detail.
\param vec List of elements that are in the first model.
\param vecother List of elements that are in the second model.
*/
template <>
void printCounts(std::string detail_name, std::vector<lpcompare::Bound> &vec, std::vector<lpcompare::Bound> &vecother)
{
	printCountsWithSort(detail_name, vec, vecother);
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include "lexer.hh"
#include "vm.hh"
#include "string_object.hh"
#include "parser.hh"

namespace tadpole {

GlobalParser::GlobalParser(VM& vm, Lexer& lex) noexcept
  : vm_(vm), lex_(lex) {
}

void GlobalParser::mark_parser() {
  for (FunCompiler* c = curr_compiler_; c != nullptr; c = c->enclosing())
    vm_.mark_object(c->fn());
}

FunctionObject* GlobalParser::compile() {
  FunCompiler compiler;
  init_compiler(&compiler, 0, FunType::TOPLEVEL);

  advance();
  while (!check(TokenKind::TK_EOF))
    declaration();
  FunctionObject* fn = finish_compiler();

  return had_error_ ? nullptr : fn;
}

const ParseRule& GlobalParser::get_rule(TokenKind kind) const noexcept {
#define _RULE(fn) [](GlobalParser& p, bool b) { p.fn(b); }

  static const ParseRule _rules[] = {
    {_RULE(grouping), _RULE(call), Precedence::CALL}, // PUNCTUATOR(LPAREN, "(")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(RPAREN, ")")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(LBRACE, "{")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(RBRACE, "}")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(COMMA, ",")
    {nullptr, _RULE(binary), Precedence::TERM},       // PUNCTUATOR(MINUS, "-")
    {nullptr, _RULE(binary), Precedence::TERM},       // PUNCTUATOR(PLUS, "+")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(SEMI, ";")
    {nullptr, _RULE(binary), Precedence::FACTOR},     // PUNCTUATOR(SLASH, "/")
    {nullptr, _RULE(binary), Precedence::FACTOR},     // PUNCTUATOR(STAR, "*")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(EQ, "=")

    {_RULE(variable), nullptr, Precedence::NONE},     // TOKEN(IDENTIFIER, "Identifier")
    {_RULE(numeric), nullptr, Precedence::NONE},      // TOKEN(NUMERIC, "Numeric")
    {_RULE(string), nullptr, Precedence::NONE},       // TOKEN(STRING, "String")

    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(FALSE, "false")
    {nullptr, nullptr, Precedence::NONE},             // KEYWORD(FN, "fn")
    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(NIL, "nil")
    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(TRUE, "true")
    {nullptr, nullptr, Precedence::NONE},             // KEYWORD(VAR, "var")

    {nullptr, nullptr, Precedence::NONE},             // TOKEN(EOF, "Eof")
    {nullptr, nullptr, Precedence::NONE},             // TOKEN(ERR, "Error")
  };

#undef _RULE
  return _rules[as_type<int>(kind)];
}

void GlobalParser::error_at(const Token& tok, const str_t& msg) noexcept {
  if (panic_mode_)
    return;
  panic_mode_ = true;

  std::cerr
    << "SyntaxError:" << std::endl
    << "  [LINE: " << tok.lineno() << "] ERROR ";
  if (tok.kind() == TokenKind::TK_EOF)
    std::cerr << "at end ";
  else if (tok.kind() == TokenKind::TK_ERR)
    (void)0;
  else
    std::cerr << "at `" << tok.literal() << "` ";
  std::cerr << ": " << msg << std::endl;

  had_error_ = true;
}

void GlobalParser::advance() {
  prev_ = curr_;

  for (;;) {
    curr_ = lex_.next_token();
    if (!check(TokenKind::TK_ERR))
      break;

    error_at_current(curr_.as_string());
  }
}

void GlobalParser::consume(TokenKind kind, const str_t& msg) {
  if (check(kind))
    advance();
  else
    error_at_current(msg);
}

bool GlobalParser::match(TokenKind kind) {
  if (check(kind)) {
    advance();
    return true;
  }
  return false;
}

void GlobalParser::init_compiler(FunCompiler* compiler, int scope_depth, FunType fn_type) {
  StringObject* func_name{};
  if (fn_type == FunType::FUNCTION)
    func_name = StringObject::create(vm_, prev_.as_string());

  compiler->set_compiler(
      curr_compiler_,
      FunctionObject::create(vm_, func_name),
      fn_type,
      scope_depth);
  curr_compiler_ = compiler;

  curr_compiler_->append_local(LocalVar(Token::make(""), curr_compiler_->scope_depth(), false));
}

FunctionObject* GlobalParser::finish_compiler() {
  emit_return();

  FunctionObject* fn = curr_compiler_->fn();

#if defined(_TADPOLE_DEBUG_VM)
  if (!had_error_)
    curr_chunk()->dis(fn->name_asstr());
#endif

  curr_compiler_ = curr_compiler_->enclosing();
  return fn;
}

void GlobalParser::enter_scope() {
  curr_compiler_->enter_scope();
}

void GlobalParser::leave_scope() {
  curr_compiler_->leave_scope([this](const LocalVar& var) {
        emit_byte(var.is_upvalue ? Code::CLOSE_UPVALUE : Code::POP);
      });
}

u8_t GlobalParser::identifier_constant(const Token& name) noexcept {
  return curr_chunk()->add_constant(StringObject::create(vm_, name.as_string()));
}

u8_t GlobalParser::parse_variable(const str_t& msg) {
  consume(TokenKind::TK_IDENTIFIER, msg);

  curr_compiler_->declare_localvar(prev_, [this](const str_t& m) { error(m); });
  if (curr_compiler_->scope_depth() > 0)
    return 0;
  return identifier_constant(prev_);
}

void GlobalParser::mark_initialized() {
  if (curr_compiler_->scope_depth() == 0)
    return;
  curr_compiler_->peek_local().depth = curr_compiler_->scope_depth();
}

void GlobalParser::define_global(u8_t global) {
  if (curr_compiler_->scope_depth() > 0) {
    mark_initialized();
    return;
  }
  emit_bytes(Code::DEF_GLOBAL, global);
}

u8_t GlobalParser::arguments() {
  u8_t argc = 0;
  if (!check(TokenKind::TK_RPAREN)) {
    do {
      expression();
      ++argc;

      if (argc > kMaxArgs)
        error(from_fmt("cannot have more than `%d` arguments", kMaxArgs));
    } while (match(TokenKind::TK_COMMA));
  }
  consume(TokenKind::TK_RPAREN, "expect `;` after function arguments");

  return argc;
}

void GlobalParser::named_variable(const Token& name, bool can_assign) {
  auto errfn = [this](const str_t& msg) { error(msg); };

  Code getop, setop;
  int arg = curr_compiler_->resolve_local(name, errfn);
  if (arg != -1) {
    getop = Code::GET_LOCAL;
    setop = Code::SET_LOCAL;
  }
  else if (arg = curr_compiler_->resolve_upvalue(name, errfn); arg != -1) {
    getop = Code::GET_UPVALUE;
    setop = Code::SET_UPVALUE;
  }
  else {
    arg = identifier_constant(name);
    getop = Code::GET_GLOBAL;
    setop = Code::SET_GLOBAL;
  }

  if (can_assign && match(TokenKind::TK_EQ)) {
    expression();
    emit_bytes(setop, arg);
  }
  else {
    emit_bytes(getop, arg);
  }
}

void GlobalParser::parse_precedence(Precedence precedence) {
  advance();
  auto& prefix_fn = get_rule(prev_.kind()).prefix;
  if (!prefix_fn) {
    error("expect expression");
    return;
  }

  bool can_assign = precedence <= Precedence::ASSIGN;
  prefix_fn(*this, can_assign);

  while (precedence <= get_rule(curr_.kind()).precedence) {
    advance();
    auto& infix_fn = get_rule(prev_.kind()).infix;

    if (infix_fn)
      infix_fn(*this, can_assign);
  }

  if (can_assign && match(TokenKind::TK_EQ)) {
    error("invalid assignment target");
    expression();
  }
}

void GlobalParser::binary(bool can_assign) {
  TokenKind op = prev_.kind();

  parse_precedence(get_rule(op).precedence + 1);
  switch (op) {
    case TokenKind::TK_PLUS: emit_byte(Code::ADD); break;
    case TokenKind::TK_MINUS: emit_byte(Code::SUB); break;
    case TokenKind::TK_STAR: emit_byte(Code::MUL); break;
    case TokenKind::TK_SLASH: emit_byte(Code::DIV); break;
  }
}

void GlobalParser::call(bool can_assign) {
  emit_byte(Code::CALL_0 + arguments());
}

void GlobalParser::grouping(bool can_assign) {
  expression();
  consume(TokenKind::TK_RPAREN, "expect `)` after grouping expression");
}

void GlobalParser::literal(bool can_assign) {
  switch (prev_.kind()) {
  case TokenKind::KW_NIL: emit_byte(Code::NIL); break;
  case TokenKind::KW_TRUE: emit_byte(Code::TRUE); break;
  case TokenKind::KW_FALSE: emit_byte(Code::FALSE); break;
  }
}

void GlobalParser::variable(bool can_assign) {
  named_variable(prev_, can_assign);
}

void GlobalParser::numeric(bool can_assign) {
  emit_constant(prev_.as_numeric());
}

void GlobalParser::string(bool can_assign) {
  emit_constant(StringObject::create(vm_, prev_.as_string()));
}

void GlobalParser::block() {
  while (!check(TokenKind::TK_EOF) && !check(TokenKind::TK_RBRACE))
    declaration();
  consume(TokenKind::TK_RBRACE, "expect `}` after block body");
}

void GlobalParser::function(FunType fn_type) {}
void GlobalParser::synchronize() {}
void GlobalParser::expression() {}
void GlobalParser::declaration() {}
void GlobalParser::statement() {}
void GlobalParser::fn_decl() {}
void GlobalParser::var_decl() {}
void GlobalParser::expr_stmt() {}

}
<commit_msg>:construction: chore(function): udpated the implementation of function<commit_after>// Copyright (c) 2020 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include "lexer.hh"
#include "vm.hh"
#include "string_object.hh"
#include "parser.hh"

namespace tadpole {

GlobalParser::GlobalParser(VM& vm, Lexer& lex) noexcept
  : vm_(vm), lex_(lex) {
}

void GlobalParser::mark_parser() {
  for (FunCompiler* c = curr_compiler_; c != nullptr; c = c->enclosing())
    vm_.mark_object(c->fn());
}

FunctionObject* GlobalParser::compile() {
  FunCompiler compiler;
  init_compiler(&compiler, 0, FunType::TOPLEVEL);

  advance();
  while (!check(TokenKind::TK_EOF))
    declaration();
  FunctionObject* fn = finish_compiler();

  return had_error_ ? nullptr : fn;
}

const ParseRule& GlobalParser::get_rule(TokenKind kind) const noexcept {
#define _RULE(fn) [](GlobalParser& p, bool b) { p.fn(b); }

  static const ParseRule _rules[] = {
    {_RULE(grouping), _RULE(call), Precedence::CALL}, // PUNCTUATOR(LPAREN, "(")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(RPAREN, ")")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(LBRACE, "{")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(RBRACE, "}")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(COMMA, ",")
    {nullptr, _RULE(binary), Precedence::TERM},       // PUNCTUATOR(MINUS, "-")
    {nullptr, _RULE(binary), Precedence::TERM},       // PUNCTUATOR(PLUS, "+")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(SEMI, ";")
    {nullptr, _RULE(binary), Precedence::FACTOR},     // PUNCTUATOR(SLASH, "/")
    {nullptr, _RULE(binary), Precedence::FACTOR},     // PUNCTUATOR(STAR, "*")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(EQ, "=")

    {_RULE(variable), nullptr, Precedence::NONE},     // TOKEN(IDENTIFIER, "Identifier")
    {_RULE(numeric), nullptr, Precedence::NONE},      // TOKEN(NUMERIC, "Numeric")
    {_RULE(string), nullptr, Precedence::NONE},       // TOKEN(STRING, "String")

    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(FALSE, "false")
    {nullptr, nullptr, Precedence::NONE},             // KEYWORD(FN, "fn")
    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(NIL, "nil")
    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(TRUE, "true")
    {nullptr, nullptr, Precedence::NONE},             // KEYWORD(VAR, "var")

    {nullptr, nullptr, Precedence::NONE},             // TOKEN(EOF, "Eof")
    {nullptr, nullptr, Precedence::NONE},             // TOKEN(ERR, "Error")
  };

#undef _RULE
  return _rules[as_type<int>(kind)];
}

void GlobalParser::error_at(const Token& tok, const str_t& msg) noexcept {
  if (panic_mode_)
    return;
  panic_mode_ = true;

  std::cerr
    << "SyntaxError:" << std::endl
    << "  [LINE: " << tok.lineno() << "] ERROR ";
  if (tok.kind() == TokenKind::TK_EOF)
    std::cerr << "at end ";
  else if (tok.kind() == TokenKind::TK_ERR)
    (void)0;
  else
    std::cerr << "at `" << tok.literal() << "` ";
  std::cerr << ": " << msg << std::endl;

  had_error_ = true;
}

void GlobalParser::advance() {
  prev_ = curr_;

  for (;;) {
    curr_ = lex_.next_token();
    if (!check(TokenKind::TK_ERR))
      break;

    error_at_current(curr_.as_string());
  }
}

void GlobalParser::consume(TokenKind kind, const str_t& msg) {
  if (check(kind))
    advance();
  else
    error_at_current(msg);
}

bool GlobalParser::match(TokenKind kind) {
  if (check(kind)) {
    advance();
    return true;
  }
  return false;
}

void GlobalParser::init_compiler(FunCompiler* compiler, int scope_depth, FunType fn_type) {
  StringObject* func_name{};
  if (fn_type == FunType::FUNCTION)
    func_name = StringObject::create(vm_, prev_.as_string());

  compiler->set_compiler(
      curr_compiler_,
      FunctionObject::create(vm_, func_name),
      fn_type,
      scope_depth);
  curr_compiler_ = compiler;

  curr_compiler_->append_local(LocalVar(Token::make(""), curr_compiler_->scope_depth(), false));
}

FunctionObject* GlobalParser::finish_compiler() {
  emit_return();

  FunctionObject* fn = curr_compiler_->fn();

#if defined(_TADPOLE_DEBUG_VM)
  if (!had_error_)
    curr_chunk()->dis(fn->name_asstr());
#endif

  curr_compiler_ = curr_compiler_->enclosing();
  return fn;
}

void GlobalParser::enter_scope() {
  curr_compiler_->enter_scope();
}

void GlobalParser::leave_scope() {
  curr_compiler_->leave_scope([this](const LocalVar& var) {
        emit_byte(var.is_upvalue ? Code::CLOSE_UPVALUE : Code::POP);
      });
}

u8_t GlobalParser::identifier_constant(const Token& name) noexcept {
  return curr_chunk()->add_constant(StringObject::create(vm_, name.as_string()));
}

u8_t GlobalParser::parse_variable(const str_t& msg) {
  consume(TokenKind::TK_IDENTIFIER, msg);

  curr_compiler_->declare_localvar(prev_, [this](const str_t& m) { error(m); });
  if (curr_compiler_->scope_depth() > 0)
    return 0;
  return identifier_constant(prev_);
}

void GlobalParser::mark_initialized() {
  if (curr_compiler_->scope_depth() == 0)
    return;
  curr_compiler_->peek_local().depth = curr_compiler_->scope_depth();
}

void GlobalParser::define_global(u8_t global) {
  if (curr_compiler_->scope_depth() > 0) {
    mark_initialized();
    return;
  }
  emit_bytes(Code::DEF_GLOBAL, global);
}

u8_t GlobalParser::arguments() {
  u8_t argc = 0;
  if (!check(TokenKind::TK_RPAREN)) {
    do {
      expression();
      ++argc;

      if (argc > kMaxArgs)
        error(from_fmt("cannot have more than `%d` arguments", kMaxArgs));
    } while (match(TokenKind::TK_COMMA));
  }
  consume(TokenKind::TK_RPAREN, "expect `;` after function arguments");

  return argc;
}

void GlobalParser::named_variable(const Token& name, bool can_assign) {
  auto errfn = [this](const str_t& msg) { error(msg); };

  Code getop, setop;
  int arg = curr_compiler_->resolve_local(name, errfn);
  if (arg != -1) {
    getop = Code::GET_LOCAL;
    setop = Code::SET_LOCAL;
  }
  else if (arg = curr_compiler_->resolve_upvalue(name, errfn); arg != -1) {
    getop = Code::GET_UPVALUE;
    setop = Code::SET_UPVALUE;
  }
  else {
    arg = identifier_constant(name);
    getop = Code::GET_GLOBAL;
    setop = Code::SET_GLOBAL;
  }

  if (can_assign && match(TokenKind::TK_EQ)) {
    expression();
    emit_bytes(setop, arg);
  }
  else {
    emit_bytes(getop, arg);
  }
}

void GlobalParser::parse_precedence(Precedence precedence) {
  advance();
  auto& prefix_fn = get_rule(prev_.kind()).prefix;
  if (!prefix_fn) {
    error("expect expression");
    return;
  }

  bool can_assign = precedence <= Precedence::ASSIGN;
  prefix_fn(*this, can_assign);

  while (precedence <= get_rule(curr_.kind()).precedence) {
    advance();
    auto& infix_fn = get_rule(prev_.kind()).infix;

    if (infix_fn)
      infix_fn(*this, can_assign);
  }

  if (can_assign && match(TokenKind::TK_EQ)) {
    error("invalid assignment target");
    expression();
  }
}

void GlobalParser::binary(bool can_assign) {
  TokenKind op = prev_.kind();

  parse_precedence(get_rule(op).precedence + 1);
  switch (op) {
    case TokenKind::TK_PLUS: emit_byte(Code::ADD); break;
    case TokenKind::TK_MINUS: emit_byte(Code::SUB); break;
    case TokenKind::TK_STAR: emit_byte(Code::MUL); break;
    case TokenKind::TK_SLASH: emit_byte(Code::DIV); break;
  }
}

void GlobalParser::call(bool can_assign) {
  emit_byte(Code::CALL_0 + arguments());
}

void GlobalParser::grouping(bool can_assign) {
  expression();
  consume(TokenKind::TK_RPAREN, "expect `)` after grouping expression");
}

void GlobalParser::literal(bool can_assign) {
  switch (prev_.kind()) {
  case TokenKind::KW_NIL: emit_byte(Code::NIL); break;
  case TokenKind::KW_TRUE: emit_byte(Code::TRUE); break;
  case TokenKind::KW_FALSE: emit_byte(Code::FALSE); break;
  }
}

void GlobalParser::variable(bool can_assign) {
  named_variable(prev_, can_assign);
}

void GlobalParser::numeric(bool can_assign) {
  emit_constant(prev_.as_numeric());
}

void GlobalParser::string(bool can_assign) {
  emit_constant(StringObject::create(vm_, prev_.as_string()));
}

void GlobalParser::block() {
  while (!check(TokenKind::TK_EOF) && !check(TokenKind::TK_RBRACE))
    declaration();
  consume(TokenKind::TK_RBRACE, "expect `}` after block body");
}

void GlobalParser::function(FunType fn_type) {
  FunCompiler fn_compiler;
  init_compiler(&fn_compiler, 1, fn_type);

  consume(TokenKind::TK_LPAREN, "expect `(` after function name");
  if (!check(TokenKind::TK_RPAREN)) {
    do {
      u8_t param_constant = parse_variable("expect function parameter's name");
      define_global(param_constant);

      curr_compiler_->fn()->inc_arity();
      if (curr_compiler_->fn()->arity() > kMaxArgs)
        error(from_fmt("cannot have more than `%d` parameters", kMaxArgs));
    } while (match(TokenKind::TK_COMMA));
  }
  consume(TokenKind::TK_RPAREN, "expect `)` after function parameters");

  consume(TokenKind::TK_LBRACE, "expect `{` before function body");
  block();

  leave_scope();
  FunctionObject* fn = finish_compiler();

  emit_bytes(Code::CLOSURE, curr_chunk()->add_constant(fn));
  for (sz_t i = 0; i < fn->upvalues_count(); ++i) {
    auto& upvalue = fn_compiler.get_upvalue(i);
    emit_bytes(upvalue.is_local ? 1 : 0, upvalue.index);
  }
}

void GlobalParser::synchronize() {}
void GlobalParser::expression() {}
void GlobalParser::declaration() {}
void GlobalParser::statement() {}
void GlobalParser::fn_decl() {}
void GlobalParser::var_decl() {}
void GlobalParser::expr_stmt() {}

}
<|endoftext|>


<commit_before>//--
// This file is part of Sonic Pi: http://sonic-pi.net
// Full project source: https://github.com/samaaron/sonic-pi
// License: https://github.com/samaaron/sonic-pi/blob/master/LICENSE.md
//
// Copyright 2013, 2014 by Sam Aaron (http://sam.aaron.name).
// All rights reserved.
//
// Permission is granted for use, copying, modification, distribution,
// and distribution of modified versions of this work as long as this
// notice is included.
//++

#include <QApplication>
#include <QSplashScreen>
#include <QPixmap>
#include <QBitmap>

#include "mainwindow.h"
int main(int argc, char *argv[])
{
        Q_INIT_RESOURCE(application);

    QApplication app(argc, argv);
    app.setStyle("gtk");
    QPixmap pixmap(":/images/splash.png");
    QSplashScreen splash(pixmap);
    splash.setMask(pixmap.mask());
    splash.show();

    //    QIcon icon(":images/app.icns");
    MainWindow mainWin(app, splash);

    //    mainWin.setWindowIcon(icon);
    return app.exec();
}
<commit_msg>update main.cpp to use csplashscreen<commit_after>//--
// This file is part of Sonic Pi: http://sonic-pi.net
// Full project source: https://github.com/samaaron/sonic-pi
// License: https://github.com/samaaron/sonic-pi/blob/master/LICENSE.md
//
// Copyright 2013, 2014 by Sam Aaron (http://sam.aaron.name).
// All rights reserved.
//
// Permission is granted for use, copying, modification, distribution,
// and distribution of modified versions of this work as long as this
// notice is included.
//++

#include <QApplication>
#include <QSplashScreen>
#include <QPixmap>
#include <QBitmap>
#include "csplashscreen.h"

#include "mainwindow.h"
int main(int argc, char *argv[])
{
        Q_INIT_RESOURCE(application);

    QApplication app(argc, argv);
    app.setStyle("gtk");

    QPixmap pixmap(":/images/splash.png");
    CSplashScreen* splash = new CSplashScreen(pixmap);
    splash->show();

    //    QIcon icon(":images/app.icns");
    MainWindow mainWin(app, splash);

    //    mainWin.setWindowIcon(icon);
    return app.exec();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: appquit.cxx,v $
 *
 *  $Revision: 1.23 $
 *
 *  last change: $Author: rt $ $Date: 2003-09-19 07:56:44 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _BASMGR_HXX //autogen
#include <basic/basmgr.hxx>
#endif
#ifndef _SB_SBSTAR_HXX //autogen
#include <basic/sbstar.hxx>
#endif

#ifdef WIN
#define _TL_LANG_SPECIAL
#endif

#ifndef _SVDDE_HXX //autogen
#include <svtools/svdde.hxx>
#endif
#ifndef _MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif

#ifndef _SFXENUMITEM_HXX
#include <svtools/eitem.hxx>
#endif

#include <svtools/inethist.hxx>
#include <svtools/saveopt.hxx>

#pragma hdrstop

#include "app.hrc"
#include "app.hxx"
#include "unoctitm.hxx"
#include "appdata.hxx"
#include "viewsh.hxx"
#include "dispatch.hxx"
#include "printer.hxx"
#include "plugobj.hxx"
#include "arrdecl.hxx"
#include "sfxresid.hxx"
#include "newhdl.hxx"
#include "cfgmgr.hxx"
#include "accmgr.hxx"
#include "event.hxx"
#include "macrconf.hxx"
#include "mnumgr.hxx"
#include "imgmgr.hxx"
#include "templdlg.hxx"
#include "tbxconf.hxx"
#include "msgpool.hxx"
#include "frameobj.hxx"
#include "docfile.hxx"
#include "sfxtypes.hxx"
#include "appimp.hxx"
#include "sfxlocal.hrc"
#include "dataurl.hxx"
#include "fcontnr.hxx"
#include "nochaos.hxx"
#include "appuno.hxx"
#include "doctempl.hxx"
#include "viewfrm.hxx"
#include "bmkmenu.hxx"
#include "objsh.hxx"
#include "dlgcont.hxx"
#include "scriptcont.hxx"
#include <misccfg.hxx>
#include "docfac.hxx"

#ifndef PRODUCT
DECLARE_LIST( SfxFrameWindowFactoryArray_Impl, SfxFrameWindowFactory* )
SV_DECL_PTRARR(SfxInitLinkList, Link*, 2, 2);
#endif

//===================================================================
/*
void SfxApplication::Quit()
{
    QueryExit_Impl();
}
*/
//--------------------------------------------------------------------
BOOL SfxApplication::QueryExit_Impl()

/*  [Beschreibung]

    Liefert FALSE, wenn entweder ein modaler Dialog offen ist, oder
    der Printer einer SfxViewShell einen laufenden Druckjob hat.

    [Anmerkung]

    Wenn diese aus StarView stammende virtuelle Methode vom Applikations-
    entwickler "uberladen wird, mu"s diese SfxApplication::QueryExit() rufen
    und falls diese FALSE zur"uckgibt, ebenfalls FALSE zur"uckgeben.
*/

{
    SaveConfiguration();
    BOOL bQuit = TRUE;

/*
    BOOL bPrinting = FALSE;
    for ( SfxViewShell *pViewSh = SfxViewShell::GetFirst();
          !bPrinting && pViewSh;
          pViewSh = SfxViewShell::GetNext(*pViewSh) )
    {
        SfxPrinter *pPrinter = pViewSh->GetPrinter();
        bPrinting = pPrinter && pPrinter->IsPrinting();
    }

    if ( bPrinting )
    {
        // Benutzer fragen, ob abgebrochen werden soll
        if ( RET_OK == QueryBox( 0, SfxResId( MSG_ISPRINTING_QUERYABORT ) ).Execute() )
        {
            // alle Jobs canceln
            for ( SfxViewShell *pViewSh = SfxViewShell::GetFirst();
                  !bPrinting && pViewSh;
                  pViewSh = SfxViewShell::GetNext(*pViewSh) )
            {
                SfxPrinter *pPrinter = pViewSh->GetPrinter();
                if ( pPrinter && pPrinter->IsPrinting() )
                    pPrinter->AbortJob();
            }

            // da das Canceln asynchron ist, Quit erstmal wieder verlassen
            GetDispatcher_Impl()->Execute( SID_QUITAPP, SFX_CALLMODE_ASYNCHRON );
            DBG_TRACE( "QueryExit => FALSE (printing)" );
            return FALSE;
        }
    }
*/
    // alles canceln was zu canceln ist
    GetCancelManager()->Cancel(TRUE);

/*
    SfxObjectShell *pLastDocSh = SfxObjectShell::GetFirst();
    if ( bQuit )
    {
        // Jetzt zur Sicherheit auch hidden Frames abr"aumen
        SfxViewFrame::CloseHiddenFrames_Impl();
        pLastDocSh = SfxObjectShell::GetFirst();
    }
*/
    // will trotzdem noch jemand, den man nicht abschiessen kann, die App haben?
    if ( !bQuit )
    {
        // nicht wirklich beenden, nur minimieren
        pAppData_Impl->bOLEResize = TRUE;
        InfoBox aInfoBox( NULL, SfxResId(MSG_CANT_QUIT) );
        aInfoBox.Execute();
        DBG_TRACE( "QueryExit => FALSE (in use)" );
        return FALSE;
    }

    return TRUE;
}

//-------------------------------------------------------------------------

void SfxApplication::Deinitialize()
{
    if ( bDowning )
        return;

    // Falls man nochmal beim Runterfahren in ein Reschedule l"auft
    pAppData_Impl->EndListening( *this );
    if ( pAppData_Impl->pCancelMgr )
        pAppData_Impl->EndListening( *pAppData_Impl->pCancelMgr );

    //!Wait();
    StarBASIC::Stop();

    // ggf. BASIC speichern
    if ( pImp->pBasicMgr && pImp->pBasicMgr->IsModified() )
        SaveBasicManager();

    SaveBasicContainer();
    SaveDialogContainer();

    bDowning = TRUE; // wegen Timer aus DecAliveCount und QueryExit

    DELETEZ( pAppData_Impl->pTemplates );

    DELETEZ(pImp->pTemplateDlg);
    SetViewFrame(0);
    bDowning = FALSE;
    DBG_ASSERT( !SfxViewFrame::GetFirst(),
                "existing SfxViewFrame after Execute" );
    DBG_ASSERT( !SfxObjectShell::GetFirst(),
                "existing SfxObjectShell after Execute" );
    pAppDispat->Pop( *this, SFX_SHELL_POP_UNTIL );
    pAppDispat->Flush();
    bDowning = TRUE;
    pAppDispat->DoDeactivate_Impl( TRUE );

    INetURLHistory::Delete();

    // call derived application-exit
    bInExit = TRUE;
    Exit();

    // Controller u."a. freigeben
    // dabei sollten auch restliche Komponenten ( Beamer! ) verschwinden
    DELETEZ(pMenuMgr);
    DELETEZ(pAcceleratorMgr);
    SfxObjectFactory::ClearAll_Impl();
    DELETEZ( pImp->pBasicMgr );
    if( pImp->pBasicLibContainer )
        pImp->pBasicLibContainer->release();
    if( pImp->pDialogLibContainer )
        pImp->pDialogLibContainer->release();

    bInExit = FALSE;

    DBG_ASSERT( pViewFrame == 0, "active foreign ViewFrame" );

    delete[] pInterfaces, pInterfaces = 0;
    DELETEZ(pImageMgr);

    // free administration managers
    DELETEZ(pImp->pAutoSaveTimer);
    DELETEZ(pAppDispat);
    DELETEZ(pImp->pSfxResManager);
    DELETEZ(pImp->pOfaResMgr);

    // ab hier d"urfen keine SvObjects mehr existieren
    DELETEX(pAppData_Impl->pMatcher);
    DELETEX(pAppData_Impl->pSfxFrameObjectFactoryPtr);
    DELETEX(pAppData_Impl->pSfxPluginObjectFactoryPtr);

    delete pAppData_Impl->pLabelResMgr;

#ifndef PRODUCT
    DELETEX(pSlotPool);
    DELETEX(pAppData_Impl->pEventConfig);
    DELETEX(pAppData_Impl->pMiscConfig);
    SfxMacroConfig::Release_Impl();
    DELETEX(pAppData_Impl->pVerbs);
    DELETEX(pAppData_Impl->pFactArr);
    DELETEX(pAppData_Impl->pInitLinkList);
#endif

#ifndef PRODUCT
    DELETEX(pImp->pTbxCtrlFac);
    DELETEX(pImp->pStbCtrlFac);
    DELETEX(pImp->pMenuCtrlFac);
    DELETEX(pImp->pEventHdl);
    SfxNewHdl::Delete();
    DELETEX(pImp->pAutoSaveTimer);
    DELETEX(pImp->pViewFrames);
    DELETEX(pImp->pViewShells);
    DELETEX(pImp->pObjShells);
#endif

    NoChaos::ReleaseItemPool();
    pAppData_Impl->pPool = NULL;
}
<commit_msg>INTEGRATION: CWS dialogdiet (1.23.28); FILE MERGED 2003/11/28 16:22:41 mba 1.23.28.1: #i22972#: misccfg moved to svtools; ResMgr now static<commit_after>/*************************************************************************
 *
 *  $RCSfile: appquit.cxx,v $
 *
 *  $Revision: 1.24 $
 *
 *  last change: $Author: hr $ $Date: 2004-02-03 19:53:41 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _BASMGR_HXX //autogen
#include <basic/basmgr.hxx>
#endif
#ifndef _SB_SBSTAR_HXX //autogen
#include <basic/sbstar.hxx>
#endif

#ifdef WIN
#define _TL_LANG_SPECIAL
#endif

#ifndef _SVDDE_HXX //autogen
#include <svtools/svdde.hxx>
#endif
#ifndef _MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif

#ifndef _SFXENUMITEM_HXX
#include <svtools/eitem.hxx>
#endif

#include <svtools/inethist.hxx>
#include <svtools/saveopt.hxx>

#pragma hdrstop

#include "app.hrc"
#include "app.hxx"
#include "unoctitm.hxx"
#include "appdata.hxx"
#include "viewsh.hxx"
#include "dispatch.hxx"
#include "printer.hxx"
#include "plugobj.hxx"
#include "arrdecl.hxx"
#include "sfxresid.hxx"
#include "newhdl.hxx"
#include "cfgmgr.hxx"
#include "accmgr.hxx"
#include "event.hxx"
#include "macrconf.hxx"
#include "mnumgr.hxx"
#include "imgmgr.hxx"
#include "templdlg.hxx"
#include "tbxconf.hxx"
#include "msgpool.hxx"
#include "frameobj.hxx"
#include "docfile.hxx"
#include "sfxtypes.hxx"
#include "appimp.hxx"
#include "sfxlocal.hrc"
#include "dataurl.hxx"
#include "fcontnr.hxx"
#include "nochaos.hxx"
#include "appuno.hxx"
#include "doctempl.hxx"
#include "viewfrm.hxx"
#include "bmkmenu.hxx"
#include "objsh.hxx"
#include "dlgcont.hxx"
#include "scriptcont.hxx"
#include <svtools/misccfg.hxx>
#include "docfac.hxx"

#ifndef PRODUCT
DECLARE_LIST( SfxFrameWindowFactoryArray_Impl, SfxFrameWindowFactory* )
SV_DECL_PTRARR(SfxInitLinkList, Link*, 2, 2);
#endif

//===================================================================
/*
void SfxApplication::Quit()
{
    QueryExit_Impl();
}
*/
//--------------------------------------------------------------------
BOOL SfxApplication::QueryExit_Impl()

/*  [Beschreibung]

    Liefert FALSE, wenn entweder ein modaler Dialog offen ist, oder
    der Printer einer SfxViewShell einen laufenden Druckjob hat.

    [Anmerkung]

    Wenn diese aus StarView stammende virtuelle Methode vom Applikations-
    entwickler "uberladen wird, mu"s diese SfxApplication::QueryExit() rufen
    und falls diese FALSE zur"uckgibt, ebenfalls FALSE zur"uckgeben.
*/

{
    SaveConfiguration();
    BOOL bQuit = TRUE;

/*
    BOOL bPrinting = FALSE;
    for ( SfxViewShell *pViewSh = SfxViewShell::GetFirst();
          !bPrinting && pViewSh;
          pViewSh = SfxViewShell::GetNext(*pViewSh) )
    {
        SfxPrinter *pPrinter = pViewSh->GetPrinter();
        bPrinting = pPrinter && pPrinter->IsPrinting();
    }

    if ( bPrinting )
    {
        // Benutzer fragen, ob abgebrochen werden soll
        if ( RET_OK == QueryBox( 0, SfxResId( MSG_ISPRINTING_QUERYABORT ) ).Execute() )
        {
            // alle Jobs canceln
            for ( SfxViewShell *pViewSh = SfxViewShell::GetFirst();
                  !bPrinting && pViewSh;
                  pViewSh = SfxViewShell::GetNext(*pViewSh) )
            {
                SfxPrinter *pPrinter = pViewSh->GetPrinter();
                if ( pPrinter && pPrinter->IsPrinting() )
                    pPrinter->AbortJob();
            }

            // da das Canceln asynchron ist, Quit erstmal wieder verlassen
            GetDispatcher_Impl()->Execute( SID_QUITAPP, SFX_CALLMODE_ASYNCHRON );
            DBG_TRACE( "QueryExit => FALSE (printing)" );
            return FALSE;
        }
    }
*/
    // alles canceln was zu canceln ist
    GetCancelManager()->Cancel(TRUE);

/*
    SfxObjectShell *pLastDocSh = SfxObjectShell::GetFirst();
    if ( bQuit )
    {
        // Jetzt zur Sicherheit auch hidden Frames abr"aumen
        SfxViewFrame::CloseHiddenFrames_Impl();
        pLastDocSh = SfxObjectShell::GetFirst();
    }
*/
    // will trotzdem noch jemand, den man nicht abschiessen kann, die App haben?
    if ( !bQuit )
    {
        // nicht wirklich beenden, nur minimieren
        pAppData_Impl->bOLEResize = TRUE;
        InfoBox aInfoBox( NULL, SfxResId(MSG_CANT_QUIT) );
        aInfoBox.Execute();
        DBG_TRACE( "QueryExit => FALSE (in use)" );
        return FALSE;
    }

    return TRUE;
}

//-------------------------------------------------------------------------

void SfxApplication::Deinitialize()
{
    if ( bDowning )
        return;

    // Falls man nochmal beim Runterfahren in ein Reschedule l"auft
    pAppData_Impl->EndListening( *this );
    if ( pAppData_Impl->pCancelMgr )
        pAppData_Impl->EndListening( *pAppData_Impl->pCancelMgr );

    //!Wait();
    StarBASIC::Stop();

    // ggf. BASIC speichern
    if ( pImp->pBasicMgr && pImp->pBasicMgr->IsModified() )
        SaveBasicManager();

    SaveBasicContainer();
    SaveDialogContainer();

    bDowning = TRUE; // wegen Timer aus DecAliveCount und QueryExit

    DELETEZ( pAppData_Impl->pTemplates );

    DELETEZ(pImp->pTemplateDlg);
    SetViewFrame(0);
    bDowning = FALSE;
    DBG_ASSERT( !SfxViewFrame::GetFirst(),
                "existing SfxViewFrame after Execute" );
    DBG_ASSERT( !SfxObjectShell::GetFirst(),
                "existing SfxObjectShell after Execute" );
    pAppDispat->Pop( *this, SFX_SHELL_POP_UNTIL );
    pAppDispat->Flush();
    bDowning = TRUE;
    pAppDispat->DoDeactivate_Impl( TRUE );

    INetURLHistory::Delete();

    // call derived application-exit
    bInExit = TRUE;
    Exit();

    // Controller u."a. freigeben
    // dabei sollten auch restliche Komponenten ( Beamer! ) verschwinden
    DELETEZ(pMenuMgr);
    DELETEZ(pAcceleratorMgr);
    SfxObjectFactory::ClearAll_Impl();
    DELETEZ( pImp->pBasicMgr );
    if( pImp->pBasicLibContainer )
        pImp->pBasicLibContainer->release();
    if( pImp->pDialogLibContainer )
        pImp->pDialogLibContainer->release();

    bInExit = FALSE;

    DBG_ASSERT( pViewFrame == 0, "active foreign ViewFrame" );

    delete[] pInterfaces, pInterfaces = 0;
    DELETEZ(pImageMgr);

    // free administration managers
    DELETEZ(pImp->pAutoSaveTimer);
    DELETEZ(pAppDispat);
    SfxResId::DeleteResMgr();
    DELETEZ(pImp->pOfaResMgr);

    // ab hier d"urfen keine SvObjects mehr existieren
    DELETEX(pAppData_Impl->pMatcher);
    DELETEX(pAppData_Impl->pSfxFrameObjectFactoryPtr);
    DELETEX(pAppData_Impl->pSfxPluginObjectFactoryPtr);

    delete pAppData_Impl->pLabelResMgr;

#ifndef PRODUCT
    DELETEX(pSlotPool);
    DELETEX(pAppData_Impl->pEventConfig);
    DELETEX(pAppData_Impl->pMiscConfig);
    SfxMacroConfig::Release_Impl();
    DELETEX(pAppData_Impl->pVerbs);
    DELETEX(pAppData_Impl->pFactArr);
    DELETEX(pAppData_Impl->pInitLinkList);
#endif

#ifndef PRODUCT
    DELETEX(pImp->pTbxCtrlFac);
    DELETEX(pImp->pStbCtrlFac);
    DELETEX(pImp->pMenuCtrlFac);
    DELETEX(pImp->pEventHdl);
    SfxNewHdl::Delete();
    DELETEX(pImp->pAutoSaveTimer);
    DELETEX(pImp->pViewFrames);
    DELETEX(pImp->pViewShells);
    DELETEX(pImp->pObjShells);
#endif

    NoChaos::ReleaseItemPool();
    pAppData_Impl->pPool = NULL;
}
<|endoftext|>