<commit_before>//  (C) Copyright Gennadiy Rozental 2003-2005.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : implements support for test cases templates instantiated with
//                sequence of test types
// ***************************************************************************

#ifndef BOOST_TEST_TEST_CASE_TEMPLATE_HPP_071894GER
#define BOOST_TEST_TEST_CASE_TEMPLATE_HPP_071894GER

// Boost.Test
#include <boost/test/unit_test_suite.hpp>

// Boost
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type.hpp>
#include <boost/type_traits/is_const.hpp>

// STL
#include <typeinfo>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

#define BOOST_TEST_CASE_TEMPLATE( name, typelist )                          \
    boost::unit_test::ut_detail::template_test_case_gen<name,typelist >(    \
        BOOST_TEST_STRINGIZE( name ) )                                      \
/**/

//____________________________________________________________________________//

#define BOOST_TEST_CASE_TEMPLATE_FUNCTION( name, type_name )    \
template<typename type_name>                                    \
void BOOST_JOIN( name, _impl )( boost::type<type_name>* );      \
                                                                \
struct name {                                                   \
    template<typename TestType>                                 \
    static void run( boost::type<TestType>* frwrd = 0 )         \
    {                                                           \
       BOOST_JOIN( name, _impl )( frwrd );                      \
    }                                                           \
};                                                              \
                                                                \
template<typename type_name>                                    \
void BOOST_JOIN( name, _impl )( boost::type<type_name>* )       \
/**/

//____________________________________________________________________________//

namespace boost {

namespace unit_test {

namespace ut_detail {

// ************************************************************************** //
// **************          test_case_template_invoker          ************** //
// ************************************************************************** //

template<typename TestCaseTemplate,typename TestType>
class test_case_template_invoker {
public:
    void    operator()()    { TestCaseTemplate::template run<TestType>(); }
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************           generate_test_case_4_type          ************** //
// ************************************************************************** //

template<typename Generator,typename TestCaseTemplate>
struct generate_test_case_4_type {
    explicit    generate_test_case_4_type( const_string tc_name, Generator& G )
    : m_test_case_name( tc_name )
    , m_holder( G )
    {}

    template<typename TestType>
    void        operator()( mpl::identity<TestType> )
    {
        std::string full_name;
        assign_op( full_name, m_test_case_name );
        full_name += '<';
        full_name += typeid(TestType).name();
        if( boost::is_const<TestType>::value )
            full_name += " const";
        full_name += '>';

        m_holder.m_test_cases.push_back(
            new test_case( full_name, test_case_template_invoker<TestCaseTemplate,TestType>() ) );
    }

private:
    // Data members
    const_string    m_test_case_name;
    Generator&      m_holder;
};

// ************************************************************************** //
// **************              test_case_template              ************** //
// ************************************************************************** //

template<typename TestCaseTemplate,typename TestTypesList>
class template_test_case_gen : public test_unit_generator {
public:
    // Constructor
    template_test_case_gen( const_string tc_name )
    {
        typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,
                                          TestCaseTemplate
        > single_test_gen;
        mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, *this ) );
    }

    test_unit* next() const
    {
        if( m_test_cases.empty() )
            return 0;

        test_unit* res = m_test_cases.front();
        m_test_cases.pop_front();

        return res;
    }

    // Data members
    mutable std::list<test_unit*> m_test_cases;
};

//____________________________________________________________________________//

} // namespace ut_detail

} // unit_test

} // namespace boost

//____________________________________________________________________________//

#include <boost/test/detail/enable_warnings.hpp>

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.13  2005/04/12 06:50:46  rogeeff
//  assign_to -> assign_op
//
//  Revision 1.12  2005/03/22 06:58:47  rogeeff
//  assign_to made free function
//
//  Revision 1.11  2005/02/20 08:27:06  rogeeff
//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
//
//  Revision 1.10  2005/02/01 06:40:06  rogeeff
//  copyright update
//  old log entries removed
//  minor stilistic changes
//  depricated tools removed
//
//  Revision 1.9  2005/01/30 03:20:38  rogeeff
//  use BOOST_JOIN and BOOST_TEST_STRINGIZE
//
// ***************************************************************************

#endif // BOOST_TEST_TEST_CASE_TEMPLATE_HPP_071894GER

<commit_msg>forgot zero<commit_after>//  (C) Copyright Gennadiy Rozental 2003-2005.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : implements support for test cases templates instantiated with
//                sequence of test types
// ***************************************************************************

#ifndef BOOST_TEST_TEST_CASE_TEMPLATE_HPP_071894GER
#define BOOST_TEST_TEST_CASE_TEMPLATE_HPP_071894GER

// Boost.Test
#include <boost/test/unit_test_suite.hpp>

// Boost
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type.hpp>
#include <boost/type_traits/is_const.hpp>

// STL
#include <typeinfo>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

#define BOOST_TEST_CASE_TEMPLATE( name, typelist )                          \
    boost::unit_test::ut_detail::template_test_case_gen<name,typelist >(    \
        BOOST_TEST_STRINGIZE( name ) )                                      \
/**/

//____________________________________________________________________________//

#define BOOST_TEST_CASE_TEMPLATE_FUNCTION( name, type_name )    \
template<typename type_name>                                    \
void BOOST_JOIN( name, _impl )( boost::type<type_name>* );      \
                                                                \
struct name {                                                   \
    template<typename TestType>                                 \
    static void run( boost::type<TestType>* frwrd = 0 )         \
    {                                                           \
       BOOST_JOIN( name, _impl )( frwrd );                      \
    }                                                           \
};                                                              \
                                                                \
template<typename type_name>                                    \
void BOOST_JOIN( name, _impl )( boost::type<type_name>* )       \
/**/

//____________________________________________________________________________//

namespace boost {

namespace unit_test {

namespace ut_detail {

// ************************************************************************** //
// **************          test_case_template_invoker          ************** //
// ************************************************************************** //

template<typename TestCaseTemplate,typename TestType>
class test_case_template_invoker {
public:
    void    operator()()    { TestCaseTemplate::template run<TestType>(); }
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************           generate_test_case_4_type          ************** //
// ************************************************************************** //

template<typename Generator,typename TestCaseTemplate>
struct generate_test_case_4_type {
    explicit    generate_test_case_4_type( const_string tc_name, Generator& G )
    : m_test_case_name( tc_name )
    , m_holder( G )
    {}

    template<typename TestType>
    void        operator()( mpl::identity<TestType> )
    {
        std::string full_name;
        assign_op( full_name, m_test_case_name, 0 );
        full_name += '<';
        full_name += typeid(TestType).name();
        if( boost::is_const<TestType>::value )
            full_name += " const";
        full_name += '>';

        m_holder.m_test_cases.push_back(
            new test_case( full_name, test_case_template_invoker<TestCaseTemplate,TestType>() ) );
    }

private:
    // Data members
    const_string    m_test_case_name;
    Generator&      m_holder;
};

// ************************************************************************** //
// **************              test_case_template              ************** //
// ************************************************************************** //

template<typename TestCaseTemplate,typename TestTypesList>
class template_test_case_gen : public test_unit_generator {
public:
    // Constructor
    template_test_case_gen( const_string tc_name )
    {
        typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,
                                          TestCaseTemplate
        > single_test_gen;
        mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, *this ) );
    }

    test_unit* next() const
    {
        if( m_test_cases.empty() )
            return 0;

        test_unit* res = m_test_cases.front();
        m_test_cases.pop_front();

        return res;
    }

    // Data members
    mutable std::list<test_unit*> m_test_cases;
};

//____________________________________________________________________________//

} // namespace ut_detail

} // unit_test

} // namespace boost

//____________________________________________________________________________//

#include <boost/test/detail/enable_warnings.hpp>

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.14  2005/04/13 04:35:18  rogeeff
//  forgot zero
//
//  Revision 1.13  2005/04/12 06:50:46  rogeeff
//  assign_to -> assign_op
//
//  Revision 1.12  2005/03/22 06:58:47  rogeeff
//  assign_to made free function
//
//  Revision 1.11  2005/02/20 08:27:06  rogeeff
//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
//
//  Revision 1.10  2005/02/01 06:40:06  rogeeff
//  copyright update
//  old log entries removed
//  minor stilistic changes
//  depricated tools removed
//
//  Revision 1.9  2005/01/30 03:20:38  rogeeff
//  use BOOST_JOIN and BOOST_TEST_STRINGIZE
//
// ***************************************************************************

#endif // BOOST_TEST_TEST_CASE_TEMPLATE_HPP_071894GER

<|endoftext|>


<commit_before>/*****************************************************************************************
 *                                                                                *
 * GHOUL                                                                                *
 * General Helpful Open Utility Library                                                  *
 *                                                                                *
 * Copyright (c) 2012-2014                                                               *
 *                                                                                *
 * 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.                                         *
 ****************************************************************************************/

namespace ghoul {
namespace cmdparser {

template<typename T, typename U = T, typename V = U, typename W = V>
SingleCommand<T, U, V, W>::SingleCommand(T* ptr1, const std::string& name,
                             const std::string& shortName,
                             const std::string& infoText,
                             const std::string parameterList)
    : CommandlineCommand(name, shortName, infoText, parameterList, 1, false)
	, _ptr1(ptr1)
	, _ptr2(nullptr)
	, _ptr3(nullptr)
	, _ptr4(nullptr)
{}

template<typename T, typename U = T, typename V = U, typename W = V>
SingleCommand<T, U, V, W>::SingleCommand(T* ptr1, U* ptr2, const std::string& name,
                             const std::string&  shortName,
                             const std::string& infoText,
                             const std::string parameterList)
    : CommandlineCommand(name, shortName, infoText, parameterList, 2, false)
	, _ptr1(ptr1)
	, _ptr2(ptr2)
	, _ptr3(nullptr)
	, _ptr4(nullptr)
{}

template<typename T, typename U = T, typename V = U, typename W = V>
SingleCommand<T, U, V, W>::SingleCommand(T* ptr1, U* ptr2, V* ptr3,
							const std::string& name,
                             const std::string& shortName,
                             const std::string& infoText,
                             const std::string parameterList)
    : CommandlineCommand(name, shortName, infoText, parameterList, 3, false)
	, _ptr1(ptr1)
	, _ptr2(ptr2)
	, _ptr3(ptr3)
	, _ptr4(nullptr)
{}

template<typename T, typename U = T, typename V = U, typename W = V>
SingleCommand<T, U, V, W>::SingleCommand(T* ptr1, U* ptr2, V* ptr3, W* ptr4,
							 const std::string& name,
							 const std::string& shortName,
							 const std::string& infoText,
							 const std::string parameterList)
    : CommandlineCommand(name, shortName, infoText, parameterList, 4, false)
	, _ptr1(ptr1)
	, _ptr2(ptr2)
	, _ptr3(ptr3)
	, _ptr4(ptr4)
{}

template<typename T, typename U = T, typename V = U, typename W = V>
bool SingleCommand<T, U, V, W>::execute(const std::vector<std::string>& parameters) {
    cast(parameters[0], *_ptr1);
    if (_ptr2 != nullptr)
        cast(parameters[1], *_ptr2);
    if (_ptr3 != nullptr)
        cast(parameters[2], *_ptr3);
    if (_ptr4 != nullptr)
        cast(parameters[3], *_ptr4);

    return true;
}

template<typename T, typename U = T, typename V = U, typename W = V>
bool SingleCommand<T, U, V, W>::checkParameters(
										const std::vector<std::string>& parameters)
{
    std::ostringstream errorStr;

    bool result = parameters.size() == static_cast<size_t>(_argumentNum);
    if (!result) {
        errorStr << "Invalid number of parameters: " << parameters.size();
        errorStr << ", expected: " << _argumentNum;
        _errorMsg = errorStr.str();
        return false;
    }

    result &= is<T>(parameters[0]);
    if (!result)
        errorStr << "First parameter invalid";

    if (result && (_ptr2 != nullptr)) {
        result &= is<U>(parameters[1]);
        if (!result)
            errorStr << "Second parameter invalid";
    }

    if (result && (_ptr3 != nullptr)) {
        result &= is<V>(parameters[2]);
        if (!result)
            errorStr << "Third parameter invalid";
    }

    if (result && (_ptr4 != nullptr)) {
        result &= is<W>(parameters[3]);
        if (!result)
            errorStr << "Fourth parameter invalid";
    }

    if (!result)
        _errorMsg = errorStr.str();

    return result;
}

} // namespace cmdparser
} // namespace ghoul<commit_msg>Fix default template parameter<commit_after>/*****************************************************************************************
 *                                                                                *
 * GHOUL                                                                                *
 * General Helpful Open Utility Library                                                  *
 *                                                                                *
 * Copyright (c) 2012-2014                                                               *
 *                                                                                *
 * 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.                                         *
 ****************************************************************************************/

namespace ghoul {
namespace cmdparser {

template<typename T, typename U, typename V, typename W>
SingleCommand<T, U, V, W>::SingleCommand(T* ptr1, const std::string& name,
                             const std::string& shortName,
                             const std::string& infoText,
                             const std::string parameterList)
    : CommandlineCommand(name, shortName, infoText, parameterList, 1, false)
	, _ptr1(ptr1)
	, _ptr2(nullptr)
	, _ptr3(nullptr)
	, _ptr4(nullptr)
{}

template<typename T, typename U, typename V, typename W>
SingleCommand<T, U, V, W>::SingleCommand(T* ptr1, U* ptr2, const std::string& name,
                             const std::string&  shortName,
                             const std::string& infoText,
                             const std::string parameterList)
    : CommandlineCommand(name, shortName, infoText, parameterList, 2, false)
	, _ptr1(ptr1)
	, _ptr2(ptr2)
	, _ptr3(nullptr)
	, _ptr4(nullptr)
{}

template<typename T, typename U, typename V, typename W>
SingleCommand<T, U, V, W>::SingleCommand(T* ptr1, U* ptr2, V* ptr3,
							const std::string& name,
                             const std::string& shortName,
                             const std::string& infoText,
                             const std::string parameterList)
    : CommandlineCommand(name, shortName, infoText, parameterList, 3, false)
	, _ptr1(ptr1)
	, _ptr2(ptr2)
	, _ptr3(ptr3)
	, _ptr4(nullptr)
{}

template<typename T, typename U, typename V, typename W>
SingleCommand<T, U, V, W>::SingleCommand(T* ptr1, U* ptr2, V* ptr3, W* ptr4,
							 const std::string& name,
							 const std::string& shortName,
							 const std::string& infoText,
							 const std::string parameterList)
    : CommandlineCommand(name, shortName, infoText, parameterList, 4, false)
	, _ptr1(ptr1)
	, _ptr2(ptr2)
	, _ptr3(ptr3)
	, _ptr4(ptr4)
{}

template<typename T, typename U, typename V, typename W>
bool SingleCommand<T, U, V, W>::execute(const std::vector<std::string>& parameters) {
    cast(parameters[0], *_ptr1);
    if (_ptr2 != nullptr)
        cast(parameters[1], *_ptr2);
    if (_ptr3 != nullptr)
        cast(parameters[2], *_ptr3);
    if (_ptr4 != nullptr)
        cast(parameters[3], *_ptr4);

    return true;
}

template<typename T, typename U, typename V, typename W>
bool SingleCommand<T, U, V, W>::checkParameters(
										const std::vector<std::string>& parameters)
{
    std::ostringstream errorStr;

    bool result = parameters.size() == static_cast<size_t>(_argumentNum);
    if (!result) {
        errorStr << "Invalid number of parameters: " << parameters.size();
        errorStr << ", expected: " << _argumentNum;
        _errorMsg = errorStr.str();
        return false;
    }

    result &= is<T>(parameters[0]);
    if (!result)
        errorStr << "First parameter invalid";

    if (result && (_ptr2 != nullptr)) {
        result &= is<U>(parameters[1]);
        if (!result)
            errorStr << "Second parameter invalid";
    }

    if (result && (_ptr3 != nullptr)) {
        result &= is<V>(parameters[2]);
        if (!result)
            errorStr << "Third parameter invalid";
    }

    if (result && (_ptr4 != nullptr)) {
        result &= is<W>(parameters[3]);
        if (!result)
            errorStr << "Fourth parameter invalid";
    }

    if (!result)
        _errorMsg = errorStr.str();

    return result;
}

} // namespace cmdparser
} // namespace ghoul<|endoftext|>


<commit_before>#pragma once

#include <map>
#include <array>

#include "acmacs-base/stream.hh"
#include "acmacs-base/fmt.hh"

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

namespace acmacs
{
    template <typename Obj> class Counter
    {
     public:
        using container_type = std::map<Obj, size_t>;
        using value_type = typename container_type::value_type;

        Counter() = default;
        template <typename Iter, typename F> Counter(Iter first, Iter last, F func)
            {
                for (; first != last; ++first)
                    ++counter_[func(*first)];
            }
        template <typename Container, typename F> Counter(const Container& container, F func) : Counter(std::begin(container), std::end(container), func) {}

        template <typename S> void count(const S& aObj) { ++counter_[Obj{aObj}]; }
        template <typename S> void count_if(bool cond, const S& aObj) { if (cond) ++counter_[Obj{aObj}]; }

        const auto& max() const { return *std::max_element(counter_.begin(), counter_.end(), [](const auto& e1, const auto& e2) { return e1.second < e2.second; }); }

        auto sorted_max_first() const
            {
                std::vector<const value_type*> result(counter_.size());
                std::transform(std::begin(counter_), std::end(counter_), std::begin(result), [](const auto& ee) { return ⅇ });
                std::sort(result.begin(), result.end(), [](const auto& e1, const auto& e2) { return e1->second > e2->second; });
                return result;
            }

        constexpr const auto& counter() const { return counter_; }
        constexpr size_t size() const { return counter_.size(); }
        constexpr bool empty() const { return counter_.empty(); }

        template <typename S> size_t operator[](const S& look_for) const
        {
            if (const auto found = counter_.find(look_for); found != counter_.end())
                return found->second;
            else
                return 0;
        }

        friend std::ostream& operator << (std::ostream& out, const Counter& counter)
            {
                return out << counter.counter_;
            }

        template <typename S> std::string report_sorted_max_first(S line_prefix) const
        {
            fmt::memory_buffer out;
            for (const auto& entry : sorted_max_first())
                fmt::format_to(out, "{}{:6d} {}\n", line_prefix, entry->second, entry->first);
            return fmt::to_string(out);
        }

        std::string report_sorted_max_first() const { return report_sorted_max_first(""); }

        size_t total() const
        {
            return std::accumulate(std::begin(counter_), std::end(counter_), 0UL, [](size_t sum, const auto& en) { return sum + en.second; });
        }

     private:
        container_type counter_;

    }; // class Counter<Obj>

    template <typename Iter, typename F> Counter(Iter first, Iter last, F func) -> Counter<decltype(func(*first))>;

    class CounterChar
    {
      public:
        CounterChar() { std::fill(std::begin(counter_), std::end(counter_), 0UL); }
        template <typename Iter, typename F> CounterChar(Iter first, Iter last, F func)
            : CounterChar()
        {
            for (; first != last; ++first)
                ++counter_[func(*first)];
        }
        template <typename Container, typename F> CounterChar(const Container& container, F func) : CounterChar(std::begin(container), std::end(container), func) {}
        void count(char aObj) { ++counter_[static_cast<unsigned char>(aObj)]; }

        std::pair<char, size_t> max() const
        {
            const auto me = std::max_element(counter_.begin(), counter_.end(), [](size_t e1, size_t e2) { return e1 < e2; });
            return {static_cast<char>(me - counter_.begin()), *me};
        }

        std::vector<char> sorted() const
        {
            std::vector<char> res;
            for (auto it = std::begin(counter_); it != std::end(counter_); ++it) {
                if (*it > 0)
                    res.push_back(static_cast<char>(it - std::begin(counter_)));
            }
            std::sort(std::begin(res), std::end(res), [this](auto e1, auto e2) { return counter_[static_cast<size_t>(e1)] > counter_[static_cast<size_t>(e2)]; });
            return res;
        }

        size_t operator[](char val) const { return counter_[static_cast<size_t>(val)]; }

        constexpr const auto& counter() const { return counter_; }

      private:
        std::array<size_t, 256> counter_;
    };

} // namespace acmacs

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

template <typename Key> struct fmt::formatter<acmacs::Counter<Key>>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const acmacs::Counter<Key>& counter, FormatContext& ctx)
    {
        return format_to(ctx.out(), "counter{{{}}}", counter.counter());
    }
};

template <> struct fmt::formatter<acmacs::CounterChar>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const acmacs::CounterChar& counter, FormatContext& ctx)
    {
        auto out = format_to(ctx.out(), "counter{{");
        const auto keys = counter.sorted();
        for (auto it = keys.begin(); it != keys.end(); ++it) {
            if (it != keys.begin())
                out = format_to(out, ", ");
            out = format_to(out, "{}: {}", *it, counter[*it]);
        }
        return format_to(out, "}}");
    }
};

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>porting to g++-8<commit_after>#pragma once

#include <map>
#include <array>
#include <numeric>

#include "acmacs-base/stream.hh"
#include "acmacs-base/fmt.hh"

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

namespace acmacs
{
    template <typename Obj> class Counter
    {
     public:
        using container_type = std::map<Obj, size_t>;
        using value_type = typename container_type::value_type;

        Counter() = default;
        template <typename Iter, typename F> Counter(Iter first, Iter last, F func)
            {
                for (; first != last; ++first)
                    ++counter_[func(*first)];
            }
        template <typename Container, typename F> Counter(const Container& container, F func) : Counter(std::begin(container), std::end(container), func) {}

        template <typename S> void count(const S& aObj) { ++counter_[Obj{aObj}]; }
        template <typename S> void count_if(bool cond, const S& aObj) { if (cond) ++counter_[Obj{aObj}]; }

        const auto& max() const { return *std::max_element(counter_.begin(), counter_.end(), [](const auto& e1, const auto& e2) { return e1.second < e2.second; }); }

        auto sorted_max_first() const
            {
                std::vector<const value_type*> result(counter_.size());
                std::transform(std::begin(counter_), std::end(counter_), std::begin(result), [](const auto& ee) { return ⅇ });
                std::sort(result.begin(), result.end(), [](const auto& e1, const auto& e2) { return e1->second > e2->second; });
                return result;
            }

        constexpr const auto& counter() const { return counter_; }
        constexpr size_t size() const { return counter_.size(); }
        constexpr bool empty() const { return counter_.empty(); }

        template <typename S> size_t operator[](const S& look_for) const
        {
            if (const auto found = counter_.find(look_for); found != counter_.end())
                return found->second;
            else
                return 0;
        }

        friend std::ostream& operator << (std::ostream& out, const Counter& counter)
            {
                return out << counter.counter_;
            }

        template <typename S> std::string report_sorted_max_first(S line_prefix) const
        {
            fmt::memory_buffer out;
            for (const auto& entry : sorted_max_first())
                fmt::format_to(out, "{}{:6d} {}\n", line_prefix, entry->second, entry->first);
            return fmt::to_string(out);
        }

        std::string report_sorted_max_first() const { return report_sorted_max_first(""); }

        size_t total() const
        {
            return std::accumulate(std::begin(counter_), std::end(counter_), 0UL, [](size_t sum, const auto& en) { return sum + en.second; });
        }

     private:
        container_type counter_;

    }; // class Counter<Obj>

    template <typename Iter, typename F> Counter(Iter first, Iter last, F func) -> Counter<decltype(func(*first))>;

    class CounterChar
    {
      public:
        CounterChar() { std::fill(std::begin(counter_), std::end(counter_), 0UL); }
        template <typename Iter, typename F> CounterChar(Iter first, Iter last, F func)
            : CounterChar()
        {
            for (; first != last; ++first)
                ++counter_[func(*first)];
        }
        template <typename Container, typename F> CounterChar(const Container& container, F func) : CounterChar(std::begin(container), std::end(container), func) {}
        void count(char aObj) { ++counter_[static_cast<unsigned char>(aObj)]; }

        std::pair<char, size_t> max() const
        {
            const auto me = std::max_element(counter_.begin(), counter_.end(), [](size_t e1, size_t e2) { return e1 < e2; });
            return {static_cast<char>(me - counter_.begin()), *me};
        }

        std::vector<char> sorted() const
        {
            std::vector<char> res;
            for (auto it = std::begin(counter_); it != std::end(counter_); ++it) {
                if (*it > 0)
                    res.push_back(static_cast<char>(it - std::begin(counter_)));
            }
            std::sort(std::begin(res), std::end(res), [this](auto e1, auto e2) { return counter_[static_cast<size_t>(e1)] > counter_[static_cast<size_t>(e2)]; });
            return res;
        }

        size_t operator[](char val) const { return counter_[static_cast<size_t>(val)]; }

        constexpr const auto& counter() const { return counter_; }

      private:
        std::array<size_t, 256> counter_;
    };

} // namespace acmacs

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

template <typename Key> struct fmt::formatter<acmacs::Counter<Key>>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const acmacs::Counter<Key>& counter, FormatContext& ctx)
    {
        return format_to(ctx.out(), "counter{{{}}}", counter.counter());
    }
};

template <> struct fmt::formatter<acmacs::CounterChar>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const acmacs::CounterChar& counter, FormatContext& ctx)
    {
        auto out = format_to(ctx.out(), "counter{{");
        const auto keys = counter.sorted();
        for (auto it = keys.begin(); it != keys.end(); ++it) {
            if (it != keys.begin())
                out = format_to(out, ", ");
            out = format_to(out, "{}: {}", *it, counter[*it]);
        }
        return format_to(out, "}}");
    }
};

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>//============================================================================
// include/vsmc/internal/compiler/sunpro.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distributed under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_COMPILER_SUNPRO_HPP
#define VSMC_INTERNAL_COMPILER_SUNPRO_HPP

#pragma error_messages(off, nonewline)
#pragma error_messages(off, anonnotype)

#ifndef VSMC_HAS_CXX11_LONG_LONG
#define VSMC_HAS_CXX11_LONG_LONG 1
#endif

#define VSMC_SUNPRO_NONEXIST 0xFFFFUL

#if __cplusplus >= 201103L

// C++11 language features

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_ACCESS_CONTROL_SFINAE
#define VSMC_HAS_CXX11_ACCESS_CONTROL_SFINAE 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_ALIAS_TEMPLATES
#define VSMC_HAS_CXX11_ALIAS_TEMPLATES 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_ALIGNAS
#define VSMC_HAS_CXX11_ALIGNAS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_ATTRIBUTES
#define VSMC_HAS_CXX11_ATTRIBUTES 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_AUTO_TYPE
#define VSMC_HAS_CXX11_AUTO_TYPE 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_CONSTEXPR
#define VSMC_HAS_CXX11_CONSTEXPR 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_DECLTYPE
#define VSMC_HAS_CXX11_DECLTYPE 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS
#define VSMC_HAS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
#define VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_DELEGATING_CONSTRUCTORS
#define VSMC_HAS_CXX11_DELEGATING_CONSTRUCTORS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_DELETED_FUNCTIONS
#define VSMC_HAS_CXX11_DELETED_FUNCTIONS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_EXPLICIT_CONVERSIONS
#define VSMC_HAS_CXX11_EXPLICIT_CONVERSIONS 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_GENERALIZED_INITIALIZERS
#define VSMC_HAS_CXX11_GENERALIZED_INITIALIZERS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_IMPLICIT_MOVES
#define VSMC_HAS_CXX11_IMPLICIT_MOVES 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_INHERITING_CONSTRUCTORS
#define VSMC_HAS_CXX11_INHERITING_CONSTRUCTORS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_INLINE_NAMESPACES
#define VSMC_HAS_CXX11_INLINE_NAMESPACES 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_LAMBDAS
#define VSMC_HAS_CXX11_LAMBDAS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_LOCAL_TYPE_TEMPLATE_ARGS
#define VSMC_HAS_CXX11_LOCAL_TYPE_TEMPLATE_ARGS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_NOEXCEPT
#define VSMC_HAS_CXX11_NOEXCEPT 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_NONSTATIC_MEMBER_INIT
#define VSMC_HAS_CXX11_NONSTATIC_MEMBER_INIT 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_NULLPTR
#define VSMC_HAS_CXX11_NULLPTR 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_OVERRIDE_CONTROL
#define VSMC_HAS_CXX11_OVERRIDE_CONTROL 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_RANGE_FOR
#define VSMC_HAS_CXX11_RANGE_FOR 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_RAW_STRING_LITERALS
#define VSMC_HAS_CXX11_RAW_STRING_LITERALS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_REFERENCE_QUALIFIED_FUNCTIONS
#define VSMC_HAS_CXX11_REFERENCE_QUALIFIED_FUNCTIONS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_RVALUE_REFERENCES
#define VSMC_HAS_CXX11_RVALUE_REFERENCES 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_STATIC_ASSERT
#define VSMC_HAS_CXX11_STATIC_ASSERT 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_STRONG_ENUMS
#define VSMC_HAS_CXX11_STRONG_ENUMS 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_THREAD_LOCAL
#define VSMC_HAS_CXX11_THREAD_LOCAL 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_TRAILING_RETURN
#define VSMC_HAS_CXX11_TRAILING_RETURN 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_UNICODE_LITERALS
#define VSMC_HAS_CXX11_UNICODE_LITERALS 1
#endif
#endif

#ifndef _WIN32
#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_UNRESTRICTED_UNIONS
#define VSMC_HAS_CXX11_UNRESTRICTED_UNIONS 1
#endif
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_USER_LITERALS
#define VSMC_HAS_CXX11_USER_LITERALS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_VARIADIC_TEMPLATES
#define VSMC_HAS_CXX11_VARIADIC_TEMPLATES 1
#endif
#endif

// C++11 library features

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_ALGORITHM
#define VSMC_HAS_CXX11LIB_ALGORITHM 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_CHRONO
#define VSMC_HAS_CXX11LIB_CHRONO 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_CMATH
#define VSMC_HAS_CXX11LIB_CMATH 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_FUNCTIONAL
#define VSMC_HAS_CXX11LIB_FUNCTIONAL 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11LIB_FUTURE
#define VSMC_HAS_CXX11LIB_FUTURE 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11LIB_MUTEX
#define VSMC_HAS_CXX11LIB_MUTEX 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_RANDOM
#define VSMC_HAS_CXX11LIB_RANDOM 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11LIB_THREAD
#define VSMC_HAS_CXX11LIB_THREAD 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_TUPLE
#define VSMC_HAS_CXX11LIB_TUPLE 1
#endif
#endif

#endif // __cplusplus >= 201103L

// C99 library features

#ifndef VSMC_HAS_C99LIB_MATH
#define VSMC_HAS_C99LIB_MATH 1
#endif

// Preprocessor features

// Target specific features

// Parallelization features

#ifdef _OPENMP
#ifndef VSMC_HAS_OMP
#define VSMC_HAS_OMP 1
#endif
#endif

#endif // VSMC_INTERNAL_COMPILER_SUNPRO_HPP
<commit_msg>remove _WIN32 check in SunPro<commit_after>//============================================================================
// include/vsmc/internal/compiler/sunpro.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distributed under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_COMPILER_SUNPRO_HPP
#define VSMC_INTERNAL_COMPILER_SUNPRO_HPP

#pragma error_messages(off, nonewline)
#pragma error_messages(off, anonnotype)

#ifndef VSMC_HAS_CXX11_LONG_LONG
#define VSMC_HAS_CXX11_LONG_LONG 1
#endif

#define VSMC_SUNPRO_NONEXIST 0xFFFFUL

#if __cplusplus >= 201103L

// C++11 language features

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_ACCESS_CONTROL_SFINAE
#define VSMC_HAS_CXX11_ACCESS_CONTROL_SFINAE 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_ALIAS_TEMPLATES
#define VSMC_HAS_CXX11_ALIAS_TEMPLATES 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_ALIGNAS
#define VSMC_HAS_CXX11_ALIGNAS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_ATTRIBUTES
#define VSMC_HAS_CXX11_ATTRIBUTES 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_AUTO_TYPE
#define VSMC_HAS_CXX11_AUTO_TYPE 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_CONSTEXPR
#define VSMC_HAS_CXX11_CONSTEXPR 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_DECLTYPE
#define VSMC_HAS_CXX11_DECLTYPE 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS
#define VSMC_HAS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
#define VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_DELEGATING_CONSTRUCTORS
#define VSMC_HAS_CXX11_DELEGATING_CONSTRUCTORS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_DELETED_FUNCTIONS
#define VSMC_HAS_CXX11_DELETED_FUNCTIONS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_EXPLICIT_CONVERSIONS
#define VSMC_HAS_CXX11_EXPLICIT_CONVERSIONS 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_GENERALIZED_INITIALIZERS
#define VSMC_HAS_CXX11_GENERALIZED_INITIALIZERS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_IMPLICIT_MOVES
#define VSMC_HAS_CXX11_IMPLICIT_MOVES 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_INHERITING_CONSTRUCTORS
#define VSMC_HAS_CXX11_INHERITING_CONSTRUCTORS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_INLINE_NAMESPACES
#define VSMC_HAS_CXX11_INLINE_NAMESPACES 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_LAMBDAS
#define VSMC_HAS_CXX11_LAMBDAS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_LOCAL_TYPE_TEMPLATE_ARGS
#define VSMC_HAS_CXX11_LOCAL_TYPE_TEMPLATE_ARGS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_NOEXCEPT
#define VSMC_HAS_CXX11_NOEXCEPT 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_NONSTATIC_MEMBER_INIT
#define VSMC_HAS_CXX11_NONSTATIC_MEMBER_INIT 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_NULLPTR
#define VSMC_HAS_CXX11_NULLPTR 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_OVERRIDE_CONTROL
#define VSMC_HAS_CXX11_OVERRIDE_CONTROL 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_RANGE_FOR
#define VSMC_HAS_CXX11_RANGE_FOR 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_RAW_STRING_LITERALS
#define VSMC_HAS_CXX11_RAW_STRING_LITERALS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_REFERENCE_QUALIFIED_FUNCTIONS
#define VSMC_HAS_CXX11_REFERENCE_QUALIFIED_FUNCTIONS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_RVALUE_REFERENCES
#define VSMC_HAS_CXX11_RVALUE_REFERENCES 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_STATIC_ASSERT
#define VSMC_HAS_CXX11_STATIC_ASSERT 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_STRONG_ENUMS
#define VSMC_HAS_CXX11_STRONG_ENUMS 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_THREAD_LOCAL
#define VSMC_HAS_CXX11_THREAD_LOCAL 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_TRAILING_RETURN
#define VSMC_HAS_CXX11_TRAILING_RETURN 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_UNICODE_LITERALS
#define VSMC_HAS_CXX11_UNICODE_LITERALS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_UNRESTRICTED_UNIONS
#define VSMC_HAS_CXX11_UNRESTRICTED_UNIONS 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11_USER_LITERALS
#define VSMC_HAS_CXX11_USER_LITERALS 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11_VARIADIC_TEMPLATES
#define VSMC_HAS_CXX11_VARIADIC_TEMPLATES 1
#endif
#endif

// C++11 library features

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_ALGORITHM
#define VSMC_HAS_CXX11LIB_ALGORITHM 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_CHRONO
#define VSMC_HAS_CXX11LIB_CHRONO 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_CMATH
#define VSMC_HAS_CXX11LIB_CMATH 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_FUNCTIONAL
#define VSMC_HAS_CXX11LIB_FUNCTIONAL 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11LIB_FUTURE
#define VSMC_HAS_CXX11LIB_FUTURE 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11LIB_MUTEX
#define VSMC_HAS_CXX11LIB_MUTEX 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_RANDOM
#define VSMC_HAS_CXX11LIB_RANDOM 1
#endif
#endif

#if __SUNPRO_CC >= VSMC_SUNPRO_NONEXIST
#ifndef VSMC_HAS_CXX11LIB_THREAD
#define VSMC_HAS_CXX11LIB_THREAD 1
#endif
#endif

#if __SUNPRO_CC >= 0x5130UL
#ifndef VSMC_HAS_CXX11LIB_TUPLE
#define VSMC_HAS_CXX11LIB_TUPLE 1
#endif
#endif

#endif // __cplusplus >= 201103L

// C99 library features

#ifndef VSMC_HAS_C99LIB_MATH
#define VSMC_HAS_C99LIB_MATH 1
#endif

// Preprocessor features

// Target specific features

// Parallelization features

#ifdef _OPENMP
#ifndef VSMC_HAS_OMP
#define VSMC_HAS_OMP 1
#endif
#endif

#endif // VSMC_INTERNAL_COMPILER_SUNPRO_HPP
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      process.cpp
// Purpose:   Implementation of class wxExProcess
// Author:    Anton van Wezenbeek
// Copyright: (c) 2012 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/utils.h> // for wxGetEnv
#include <wx/extension/process.h>
#include <wx/extension/configdlg.h>
#include <wx/extension/defs.h>
#include <wx/extension/shell.h>
#include <wx/extension/util.h> // for wxExConfigFirstOf

BEGIN_EVENT_TABLE(wxExProcess, wxProcess)
  EVT_MENU(ID_SHELL_COMMAND, wxExProcess::OnCommand)
  EVT_MENU(ID_SHELL_COMMAND_STOP, wxExProcess::OnCommand)
  EVT_TIMER(-1, wxExProcess::OnTimer)
END_EVENT_TABLE()

wxExSTCEntryDialog* wxExProcess::m_Dialog = NULL;
wxString wxExProcess::m_WorkingDirKey = _("Process folder");

wxExProcess::wxExProcess()
  : wxProcess(wxPROCESS_REDIRECT)
  , m_Timer(new wxTimer(this))
  , m_Busy(false)
  , m_Error(false)
  , m_Sync(false)
{
  m_Command = wxExConfigFirstOf(_("Process"));
}

wxExProcess::~wxExProcess()
{
  delete m_Timer;
}

wxExProcess::wxExProcess(const wxExProcess& process)
{
  *this = process;
}

wxExProcess& wxExProcess::operator=(const wxExProcess& p)
{
  m_Busy = p.m_Busy;
  m_Error = p.m_Error;
  m_Output = p.m_Output;
  m_Sync = p.m_Sync;
  m_Timer = new wxTimer(this);

  return *this;
}

bool wxExProcess::CheckInput(const wxString& command)
{
  if (m_Busy)
  {
    return false;
  }

  m_Busy = true;

  wxString output;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());

    while (IsInputAvailable())
    {
      const wxChar c = tis.GetChar();

      if (c != 0)
      {
        output << c;
      }
    }
  }

  if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());

    while (IsErrorAvailable())
    {
      const wxChar c = tis.GetChar();

      if (c != 0)
      {
        output << c;
      }
    }
  }

  m_Busy = false;

  if (!output.empty())
  {
    if (!command.empty() && output.StartsWith(command))
    {
      m_Dialog->GetSTCShell()->AddText(output.substr(command.length()));
    }
    else
    {
      m_Dialog->GetSTCShell()->AddText(output);
    }

    return true;
  }
  else
  {
    return false;
  }
}

int wxExProcess::ConfigDialog(
  wxWindow* parent,
  const wxString& title,
  bool modal)
{
  std::vector<wxExConfigItem> v;

  v.push_back(wxExConfigItem(
    _("Process"),
    CONFIG_COMBOBOX,
    wxEmptyString,
    true));

  v.push_back(wxExConfigItem(
    m_WorkingDirKey,
    CONFIG_COMBOBOXDIR,
    wxEmptyString,
    true,
    1000));

  if (modal)
  {
    return wxExConfigDialog(parent,
      v,
      title).ShowModal();
  }
  else
  {
    wxExConfigDialog* dlg = new wxExConfigDialog(
      parent,
      v,
      title);

    return dlg->Show();
  }
}

bool wxExProcess::Execute(
  const wxString& command_to_execute,
  int flags,
  const wxString& wd)
{
  m_Error = false;

  struct wxExecuteEnv env;

  if (command_to_execute.empty())
  {
    if (wxExConfigFirstOf(_("Process")).empty())
    {
      if (ConfigDialog(wxTheApp->GetTopWindow()) == wxID_CANCEL)
      {
        return false;
      }
    }

    m_Command = wxExConfigFirstOf(_("Process"));
    env.cwd = wxExConfigFirstOf(m_WorkingDirKey);
  }
  else
  {
    m_Command = command_to_execute;
    env.cwd = wd;
  }

  m_Sync = (flags & wxEXEC_SYNC);

  // Construct the dialog.
  // This is necessary both in sync and async mode,
  // as for sync mode the dialog is used for presenting the
  // output member.
  if (m_Dialog == NULL)
  {
    m_Dialog = new wxExSTCEntryDialog(
      wxTheApp->GetTopWindow(),
      wxEmptyString,
      wxEmptyString,
      wxEmptyString,
      wxOK,
      true); // use_shell to force STCShell

    m_Dialog->SetProcess(this);
    m_Dialog->SetEscapeId(wxID_NONE);
    m_Dialog->GetSTCShell()->SetEventHandler(this);
  }

  m_Dialog->GetSTCShell()->EnableShell(!m_Sync);

  if (!m_Sync)
  {
    m_Dialog->SetTitle(m_Command);
    m_Dialog->GetSTCShell()->ClearAll();

    // If we have entered a shell, then the shell
    // itself has no prompt. So put one here.
    if (m_Command == "bash" ||
        m_Command == "csh" ||
        m_Command == "ksh" ||
        m_Command == "tcsh" ||
        m_Command == "sh")
    {
      wxString host;
      wxGetEnv("HOST", &host);
      m_Dialog->GetSTCShell()->SetPrompt(host + ">", false);
    }
    else
    {
      m_Dialog->GetSTCShell()->SetPrompt("");
    }

    // For asynchronous execution the return value is the process id and zero
    // value indicates that the command could not be executed.
    if (wxExecute(m_Command, flags, this, &env) > 0)
    {
      m_Dialog->Show();

      if (!CheckInput())
      {
        m_Dialog->GetSTCShell()->Prompt(wxEmptyString, false);
      }

      if (IsRunning())
      {
        m_Timer->Start(100); // each 100 milliseconds
      }
    }
    else
    {
      m_Dialog->Hide();

      m_Error = true;
    }
  }
  else
  {
    wxArrayString output;
    wxArrayString errors;

    // Call wxExecute to execute the command and
    // collect the output and the errors.
    if (wxExecute(
      m_Command,
      output,
      errors,
      flags,
      &env) == -1)
    {
      m_Output.clear();
      m_Error = true;
    }
    else
    {
      // Set output by converting array strings into normal strings.
      m_Output = wxJoin(errors, '\n', '\n') + wxJoin(output, '\n', '\n');
    }
  }

  return !m_Error;
}

bool wxExProcess::HandleCommand(const wxString& command) const
{
  wxString rest;

#ifdef __WXMSW__
  if (command.StartsWith("chdir", &rest))
#else
  if (command.StartsWith("cd", &rest))
#endif
  {
    rest.Trim(false);

    if (rest.empty() || rest == "~")
    {
#ifdef __WXMSW__
      return true;
#else
      return wxSetWorkingDirectory(wxGetHomeDir());
#endif
    }
    else
    {
      return wxSetWorkingDirectory(rest);
    }
  }

  return true;
}

bool wxExProcess::IsRunning() const
{
  if (
    // If we executed a sync process, then it always ended,
    // so it is not running.
    m_Sync ||
    GetPid() <= 0)
  {
    return false;
  }

  return Exists(GetPid());
}

wxKillError wxExProcess::Kill(wxSignal sig)
{
  if (!IsRunning())
  {
    return wxKILL_NO_PROCESS;
  }

  const wxKillError result = wxProcess::Kill(GetPid(), sig);

  switch (result)
  {
    case wxKILL_OK:
      wxLogStatus(_("Stopped"));
      DeletePendingEvents();
      m_Timer->Stop();
      m_Dialog->Hide();
      break;

    case wxKILL_BAD_SIGNAL:
      wxLogStatus("no such signal");
      break;

    case wxKILL_ACCESS_DENIED:
    	wxLogStatus("permission denied");
      break;

    case wxKILL_NO_PROCESS:
      wxLogStatus("no such process");
      break;

    case wxKILL_ERROR:
      wxLogStatus("another, unspecified error");
      break;

    default: wxFAIL;
  }

  return result;
}

void wxExProcess::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case ID_SHELL_COMMAND:
    m_Timer->Stop();
    m_Dialog->GetSTCShell()->LineEnd();

    if (m_Command != "cmd")
    {
      m_Dialog->GetSTCShell()->AddText(m_Dialog->GetSTCShell()->GetEOL());
    }

    if (IsRunning())
    {
      // send command to process
      wxOutputStream* os = GetOutputStream();

      if (os != NULL)
      {
        wxTextOutputStream os(*GetOutputStream());
        const wxString command(event.GetString());

        if (HandleCommand(command))
        {
          os.WriteString(command + "\n");

          wxMilliSleep(10);

          CheckInput(command);
          m_Dialog->GetSTCShell()->Prompt(wxEmptyString, false);

          m_Timer->Start();
        }
      }
    }
    else
    {
      wxLogStatus("Process is not running");
    }
    break;

  case ID_SHELL_COMMAND_STOP:
    if (IsRunning())
    {
      if (Kill() == wxKILL_OK)
      {
        wxBell();
      }
    }
    break;

  default: wxFAIL; break;
  }
}

void wxExProcess::OnTerminate(int pid, int status)
{
  m_Timer->Stop();

  wxLogStatus(_("Ready"));

  // Collect remaining input.
  CheckInput();
}

void wxExProcess::OnTimer(wxTimerEvent& event)
{
  CheckInput();
}

#if wxUSE_GUI
void wxExProcess::ShowOutput(const wxString& caption) const
{
  if (!m_Sync)
  {
    wxLogStatus("Output only available for sync processes");
  }
  else if (!m_Error)
  {
    if (m_Dialog != NULL)
    {
      m_Dialog->GetSTC()->SetText(m_Output);
      m_Dialog->SetTitle(caption.empty() ? m_Command: caption);
      m_Dialog->Show();
    }
    else if (!m_Output.empty())
    {
      wxLogMessage(m_Output);
    }
    else
    {
      wxLogStatus("No output available");
    }
  }
  else
  {
    // Executing command failed, so no output,
    // show failing command.
    wxLogError("Could not execute: " + m_Command);
  }
}
#endif
<commit_msg>filter more whitespace for tilde<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      process.cpp
// Purpose:   Implementation of class wxExProcess
// Author:    Anton van Wezenbeek
// Copyright: (c) 2012 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/utils.h> // for wxGetEnv
#include <wx/extension/process.h>
#include <wx/extension/configdlg.h>
#include <wx/extension/defs.h>
#include <wx/extension/shell.h>
#include <wx/extension/util.h> // for wxExConfigFirstOf

BEGIN_EVENT_TABLE(wxExProcess, wxProcess)
  EVT_MENU(ID_SHELL_COMMAND, wxExProcess::OnCommand)
  EVT_MENU(ID_SHELL_COMMAND_STOP, wxExProcess::OnCommand)
  EVT_TIMER(-1, wxExProcess::OnTimer)
END_EVENT_TABLE()

wxExSTCEntryDialog* wxExProcess::m_Dialog = NULL;
wxString wxExProcess::m_WorkingDirKey = _("Process folder");

wxExProcess::wxExProcess()
  : wxProcess(wxPROCESS_REDIRECT)
  , m_Timer(new wxTimer(this))
  , m_Busy(false)
  , m_Error(false)
  , m_Sync(false)
{
  m_Command = wxExConfigFirstOf(_("Process"));
}

wxExProcess::~wxExProcess()
{
  delete m_Timer;
}

wxExProcess::wxExProcess(const wxExProcess& process)
{
  *this = process;
}

wxExProcess& wxExProcess::operator=(const wxExProcess& p)
{
  m_Busy = p.m_Busy;
  m_Error = p.m_Error;
  m_Output = p.m_Output;
  m_Sync = p.m_Sync;
  m_Timer = new wxTimer(this);

  return *this;
}

bool wxExProcess::CheckInput(const wxString& command)
{
  if (m_Busy)
  {
    return false;
  }

  m_Busy = true;

  wxString output;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());

    while (IsInputAvailable())
    {
      const wxChar c = tis.GetChar();

      if (c != 0)
      {
        output << c;
      }
    }
  }

  if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());

    while (IsErrorAvailable())
    {
      const wxChar c = tis.GetChar();

      if (c != 0)
      {
        output << c;
      }
    }
  }

  m_Busy = false;

  if (!output.empty())
  {
    if (!command.empty() && output.StartsWith(command))
    {
      m_Dialog->GetSTCShell()->AddText(output.substr(command.length()));
    }
    else
    {
      m_Dialog->GetSTCShell()->AddText(output);
    }

    return true;
  }
  else
  {
    return false;
  }
}

int wxExProcess::ConfigDialog(
  wxWindow* parent,
  const wxString& title,
  bool modal)
{
  std::vector<wxExConfigItem> v;

  v.push_back(wxExConfigItem(
    _("Process"),
    CONFIG_COMBOBOX,
    wxEmptyString,
    true));

  v.push_back(wxExConfigItem(
    m_WorkingDirKey,
    CONFIG_COMBOBOXDIR,
    wxEmptyString,
    true,
    1000));

  if (modal)
  {
    return wxExConfigDialog(parent,
      v,
      title).ShowModal();
  }
  else
  {
    wxExConfigDialog* dlg = new wxExConfigDialog(
      parent,
      v,
      title);

    return dlg->Show();
  }
}

bool wxExProcess::Execute(
  const wxString& command_to_execute,
  int flags,
  const wxString& wd)
{
  m_Error = false;

  struct wxExecuteEnv env;

  if (command_to_execute.empty())
  {
    if (wxExConfigFirstOf(_("Process")).empty())
    {
      if (ConfigDialog(wxTheApp->GetTopWindow()) == wxID_CANCEL)
      {
        return false;
      }
    }

    m_Command = wxExConfigFirstOf(_("Process"));
    env.cwd = wxExConfigFirstOf(m_WorkingDirKey);
  }
  else
  {
    m_Command = command_to_execute;
    env.cwd = wd;
  }

  m_Sync = (flags & wxEXEC_SYNC);

  // Construct the dialog.
  // This is necessary both in sync and async mode,
  // as for sync mode the dialog is used for presenting the
  // output member.
  if (m_Dialog == NULL)
  {
    m_Dialog = new wxExSTCEntryDialog(
      wxTheApp->GetTopWindow(),
      wxEmptyString,
      wxEmptyString,
      wxEmptyString,
      wxOK,
      true); // use_shell to force STCShell

    m_Dialog->SetProcess(this);
    m_Dialog->SetEscapeId(wxID_NONE);
    m_Dialog->GetSTCShell()->SetEventHandler(this);
  }

  m_Dialog->GetSTCShell()->EnableShell(!m_Sync);

  if (!m_Sync)
  {
    m_Dialog->SetTitle(m_Command);
    m_Dialog->GetSTCShell()->ClearAll();

    // If we have entered a shell, then the shell
    // itself has no prompt. So put one here.
    if (m_Command == "bash" ||
        m_Command == "csh" ||
        m_Command == "ksh" ||
        m_Command == "tcsh" ||
        m_Command == "sh")
    {
      wxString host;
      wxGetEnv("HOST", &host);
      m_Dialog->GetSTCShell()->SetPrompt(host + ">", false);
    }
    else
    {
      m_Dialog->GetSTCShell()->SetPrompt("");
    }

    // For asynchronous execution the return value is the process id and zero
    // value indicates that the command could not be executed.
    if (wxExecute(m_Command, flags, this, &env) > 0)
    {
      m_Dialog->Show();

      if (!CheckInput())
      {
        m_Dialog->GetSTCShell()->Prompt(wxEmptyString, false);
      }

      if (IsRunning())
      {
        m_Timer->Start(100); // each 100 milliseconds
      }
    }
    else
    {
      m_Dialog->Hide();

      m_Error = true;
    }
  }
  else
  {
    wxArrayString output;
    wxArrayString errors;

    // Call wxExecute to execute the command and
    // collect the output and the errors.
    if (wxExecute(
      m_Command,
      output,
      errors,
      flags,
      &env) == -1)
    {
      m_Output.clear();
      m_Error = true;
    }
    else
    {
      // Set output by converting array strings into normal strings.
      m_Output = wxJoin(errors, '\n', '\n') + wxJoin(output, '\n', '\n');
    }
  }

  return !m_Error;
}

bool wxExProcess::HandleCommand(const wxString& command) const
{
  wxString rest;

#ifdef __WXMSW__
  if (command.StartsWith("chdir", &rest))
#else
  if (command.StartsWith("cd", &rest))
#endif
  {
    rest.Trim(false);
    rest.Trim(true);

    if (rest.empty() || rest == "~")
    {
#ifdef __WXMSW__
      return true;
#else
      return wxSetWorkingDirectory(wxGetHomeDir());
#endif
    }
    else
    {
      return wxSetWorkingDirectory(rest);
    }
  }

  return true;
}

bool wxExProcess::IsRunning() const
{
  if (
    // If we executed a sync process, then it always ended,
    // so it is not running.
    m_Sync ||
    GetPid() <= 0)
  {
    return false;
  }

  return Exists(GetPid());
}

wxKillError wxExProcess::Kill(wxSignal sig)
{
  if (!IsRunning())
  {
    return wxKILL_NO_PROCESS;
  }

  const wxKillError result = wxProcess::Kill(GetPid(), sig);

  switch (result)
  {
    case wxKILL_OK:
      wxLogStatus(_("Stopped"));
      DeletePendingEvents();
      m_Timer->Stop();
      m_Dialog->Hide();
      break;

    case wxKILL_BAD_SIGNAL:
      wxLogStatus("no such signal");
      break;

    case wxKILL_ACCESS_DENIED:
    	wxLogStatus("permission denied");
      break;

    case wxKILL_NO_PROCESS:
      wxLogStatus("no such process");
      break;

    case wxKILL_ERROR:
      wxLogStatus("another, unspecified error");
      break;

    default: wxFAIL;
  }

  return result;
}

void wxExProcess::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case ID_SHELL_COMMAND:
    m_Timer->Stop();
    m_Dialog->GetSTCShell()->LineEnd();

    if (m_Command != "cmd")
    {
      m_Dialog->GetSTCShell()->AddText(m_Dialog->GetSTCShell()->GetEOL());
    }

    if (IsRunning())
    {
      // send command to process
      wxOutputStream* os = GetOutputStream();

      if (os != NULL)
      {
        wxTextOutputStream os(*GetOutputStream());
        const wxString command(event.GetString());

        if (HandleCommand(command))
        {
          os.WriteString(command + "\n");

          wxMilliSleep(10);

          if (!CheckInput(command))
          {
            m_Dialog->GetSTCShell()->Prompt(wxEmptyString, false);
          }
        }
      }

      m_Timer->Start();
    }
    else
    {
      wxLogStatus("Process is not running");
    }
    break;

  case ID_SHELL_COMMAND_STOP:
    if (IsRunning())
    {
      if (Kill() == wxKILL_OK)
      {
        wxBell();
      }
    }
    break;

  default: wxFAIL; break;
  }
}

void wxExProcess::OnTerminate(int pid, int status)
{
  m_Timer->Stop();

  wxLogStatus(_("Ready"));

  // Collect remaining input.
  CheckInput();
}

void wxExProcess::OnTimer(wxTimerEvent& event)
{
  CheckInput();
}

#if wxUSE_GUI
void wxExProcess::ShowOutput(const wxString& caption) const
{
  if (!m_Sync)
  {
    wxLogStatus("Output only available for sync processes");
  }
  else if (!m_Error)
  {
    if (m_Dialog != NULL)
    {
      m_Dialog->GetSTC()->SetText(m_Output);
      m_Dialog->SetTitle(caption.empty() ? m_Command: caption);
      m_Dialog->Show();
    }
    else if (!m_Output.empty())
    {
      wxLogMessage(m_Output);
    }
    else
    {
      wxLogStatus("No output available");
    }
  }
  else
  {
    // Executing command failed, so no output,
    // show failing command.
    wxLogError("Could not execute: " + m_Command);
  }
}
#endif
<|endoftext|>


<commit_before>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2015 ETH Zurich
 ** 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 ETH Zurich 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 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 "DeclarationVisitorHeader.h"
#include "ExpressionVisitorHeader.h"
#include "StatementVisitorHeader.h"
#include "ElementVisitorHeader.h"
#include "../source_visitors/DeclarationVisitorSource.h"

#include "OOModel/src/declarations/Project.h"
#include "OOModel/src/declarations/Module.h"
#include "OOModel/src/declarations/Class.h"
#include "OOModel/src/declarations/Declaration.h"
#include "OOModel/src/declarations/Method.h"
#include "OOModel/src/declarations/NameImport.h"
#include "OOModel/src/declarations/VariableDeclaration.h"
#include "OOModel/src/declarations/ExplicitTemplateInstantiation.h"
#include "OOModel/src/declarations/TypeAlias.h"

#include "Export/src/tree/SourceDir.h"
#include "Export/src/tree/SourceFile.h"
#include "Export/src/tree/CompositeFragment.h"
#include "Export/src/tree/TextFragment.h"

using namespace Export;
using namespace OOModel;

namespace CppExport {

SourceFragment* DeclarationVisitorHeader::visit(Declaration* declaration)
{
	if (auto castDeclaration = DCast<Method>(declaration)) return visit(castDeclaration);
	if (auto castDeclaration = DCast<Class>(declaration)) return visit(castDeclaration);
	if (auto castDeclaration = DCast<VariableDeclaration>(declaration)) return visit(castDeclaration);
	if (auto castDeclaration = DCast<TypeAlias>(declaration)) return visit(castDeclaration);

	notAllowed(declaration);

	// TODO: handle comments
	auto fragment = new CompositeFragment(declaration);
	*fragment << "Invalid Declaration";
	return fragment;
}

SourceDir* DeclarationVisitorHeader::visitProject(Project* project, SourceDir* parent)
{
	auto projectDir = parent ? &parent->subDir(project->name()) : new SourceDir(nullptr, "src");

	for (auto node : *project->projects()) visitProject(node, projectDir);
	for (auto node : *project->modules()) visitModule(node, projectDir);
	for (auto node : *project->classes()) visitTopLevelClass(node, projectDir);

	notAllowed(project->methods());
	notAllowed(project->fields());

	return projectDir;
}

SourceDir* DeclarationVisitorHeader::visitModule(Module* module, SourceDir* parent)
{
	Q_ASSERT(parent);
	auto moduleDir = &parent->subDir(module->name());

	for (auto node : *module->modules()) visitModule(node, moduleDir);
	for (auto node : *module->classes()) visitTopLevelClass(node, moduleDir);

	notAllowed(module->methods());
	notAllowed(module->fields());

	return moduleDir;
}

SourceFile* DeclarationVisitorHeader::visitTopLevelClass(Class* classs, SourceDir* parent)
{
	Q_ASSERT(parent);
	auto classFile = &parent->file(classs->name() + ".h");

	CompositeFragment* fragment = classFile->append(new CompositeFragment(classs, "sections"));

	auto imports = fragment->append(new CompositeFragment(classs, "vertical"));
	for (auto node : *classs->subDeclarations())
	{
		if (auto ni = DCast<NameImport>(node)) *imports << visit(ni);
		else notAllowed(node);
	}

	*fragment << visit(classs);

	return classFile;
}

SourceFragment* DeclarationVisitorHeader::visitTopLevelClass(Class* classs)
{
	auto fragment = new CompositeFragment(classs, "spacedSections");
	*fragment << visit(classs);

	auto filter = [](Method* method) { return !method->typeArguments()->isEmpty(); };
	*fragment << list(classs->methods(), DeclarationVisitorSource(data()), "spacedSections", filter);
	return fragment;
}

SourceFragment* DeclarationVisitorHeader::visit(Class* classs)
{
	auto fragment = new CompositeFragment(classs);
	if (Class::ConstructKind::Class == classs->constructKind())
		*fragment << printAnnotationsAndModifiers(classs) << "class " << classs->nameNode();
	else if (Class::ConstructKind::Struct == classs->constructKind())
		*fragment << printAnnotationsAndModifiers(classs) << "struct " << classs->nameNode();
	else if (Class::ConstructKind::Enum == classs->constructKind())
		*fragment << printAnnotationsAndModifiers(classs) << "enum " << classs->nameNode();
	else
		notAllowed(classs);

	if (!classs->typeArguments()->isEmpty())
		*fragment << list(classs->typeArguments(), ElementVisitorHeader(data()), "typeArgsList");
	*fragment << printAnnotationsAndModifiers(classs);
	if (Class::ConstructKind::Class == classs->constructKind()) *fragment << "class ";
	else if (Class::ConstructKind::Struct == classs->constructKind()) *fragment << "struct ";
	else if (Class::ConstructKind::Enum == classs->constructKind()) *fragment << "enum ";
	else notAllowed(classs);

	if (auto namespaceModule = classs->firstAncestorOfType<Module>())
		*fragment << namespaceModule->name().toUpper() + "_API ";

	*fragment << classs->nameNode();

	if (!classs->baseClasses()->isEmpty())
		// TODO: inheritance modifiers like private, virtual... (not only public)
		*fragment << list(classs->baseClasses(), ExpressionVisitorHeader(data()), "baseClasses");

	notAllowed(classs->friends());

	auto sections = fragment->append( new CompositeFragment(classs, "bodySections"));

	if (classs->enumerators()->size() > 0)
		error(classs->enumerators(), "Enum unhandled"); // TODO

	auto publicSection = new CompositeFragment(classs, "accessorSections");
	auto publicFilter = [](Declaration* declaration) { return declaration->modifiers()->isSet(Modifier::Public); };
	bool hasPublicSection = addMemberDeclarations(classs, publicSection, publicFilter);
	if (hasPublicSection)
	{
		*sections << "public:";
		sections->append(publicSection);
	}

	auto protectedSection = new CompositeFragment(classs, "accessorSections");
	auto protectedFilter = [](Declaration* declaration) { return declaration->modifiers()->isSet(Modifier::Protected); };
	bool hasProtectedSection = addMemberDeclarations(classs, protectedSection, protectedFilter);
	if (hasProtectedSection)
	{
		if (hasPublicSection) *sections << "\n"; // add newline between two accessor sections

		*sections << "protected:";
		sections->append(protectedSection);
	}

	auto privateSection = new CompositeFragment(classs, "accessorSections");
	auto privateFilter = [](Declaration* declaration) { return !declaration->modifiers()->isSet(Modifier::Public) &&
																				  !declaration->modifiers()->isSet(Modifier::Protected); };
	bool hasPrivateSection = addMemberDeclarations(classs, privateSection, privateFilter);
	if (hasPrivateSection)
	{
		if (hasPublicSection || hasProtectedSection) *sections << "\n"; // add newline between two accessor sections

		*sections << "private:";
		sections->append(privateSection);
	}

	return fragment;
}

template<typename Predicate>
bool DeclarationVisitorHeader::addMemberDeclarations(Class* classs, CompositeFragment* section, Predicate filter)
{
	auto subDeclarations = list(classs->subDeclarations(), this, "sections", filter);
	auto fields = list(classs->fields(), this, "vertical", filter);
	auto classes = list(classs->classes(), this, "sections", filter);
	auto methods = list(classs->methods(), this, "sections", filter);

	*section << subDeclarations << fields << classes << methods;
	return !subDeclarations->fragments().empty() ||
			 !fields->fragments().empty() ||
			 !classes->fragments().empty() ||
			 !methods->fragments().empty();
}

SourceFragment* DeclarationVisitorHeader::visit(Method* method)
{
	auto fragment = new CompositeFragment(method);

	if (!method->typeArguments()->isEmpty())
		*fragment << list(method->typeArguments(), ElementVisitorHeader(data()), "templateArgsList");

	*fragment << printAnnotationsAndModifiers(method);

	if (method->results()->size() > 1)
		error(method->results(), "Cannot have more than one return value in C++");

	if (method->methodKind() != Method::MethodKind::Constructor &&
		 method->methodKind() != Method::MethodKind::Destructor)
	{
		if (!method->results()->isEmpty())
			*fragment << expression(method->results()->at(0)->typeExpression()) << " ";
		else
			*fragment << "void ";
	}

	if (method->methodKind() == Method::MethodKind::Destructor && !method->name().startsWith("~")) *fragment << "~";
	*fragment << method->nameNode();

	*fragment << list(method->arguments(), ElementVisitorHeader(data()), "argsList");

	if (!method->throws()->isEmpty())
	{
		*fragment << " throw (";
		*fragment << list(method->throws(), ExpressionVisitorHeader(data()), "comma");
		*fragment << ")";
	}

	notAllowed(method->subDeclarations());
	notAllowed(method->memberInitializers());

	if (method->modifiers()->isSet(Modifier::Override))
		*fragment << " " << new TextFragment(method->modifiers(), "override");

	*fragment << ";";

	return fragment;
}

SourceFragment* DeclarationVisitorHeader::visit(VariableDeclaration* vd)
{
	auto fragment = new CompositeFragment(vd);
	*fragment << printAnnotationsAndModifiers(vd);
	*fragment << expression(vd->typeExpression()) << " " << vd->nameNode();
	if (vd->initialValue())
		*fragment << " = " << expression(vd->initialValue());

	if (!DCast<Expression>(vd->parent())) *fragment << ";";
	return fragment;
}

SourceFragment* DeclarationVisitorHeader::visit(NameImport* nameImport)
{
	error(nameImport, "NameImport unhandled"); // TODO
	return new TextFragment(nameImport);
}

SourceFragment* DeclarationVisitorHeader::printAnnotationsAndModifiers(Declaration* declaration)
{
	auto fragment = new CompositeFragment(declaration, "vertical");
	if (!declaration->annotations()->isEmpty()) // avoid an extra new line if there are no annotations
		*fragment << list(declaration->annotations(), StatementVisitorHeader(data()), "vertical");
	auto header = fragment->append(new CompositeFragment(declaration, "space"));

	if (declaration->modifiers()->isSet(Modifier::Static))
		*header << new TextFragment(declaration->modifiers(), "static");

	if (declaration->modifiers()->isSet(Modifier::Final))
		*header << new TextFragment(declaration->modifiers(), "final");
	if (declaration->modifiers()->isSet(Modifier::Abstract))
		*header << new TextFragment(declaration->modifiers(), "abstract");

	if (declaration->modifiers()->isSet(Modifier::Virtual))
		*header << new TextFragment(declaration->modifiers(), "virtual");
	if (declaration->modifiers()->isSet(Modifier::Inline))
		*header << new TextFragment(declaration->modifiers(), "inline");

	return fragment;
}

SourceFragment* DeclarationVisitorHeader::visit(ExplicitTemplateInstantiation* eti)
{
	error(eti, "ExplicitTemplateInstantiation unhandled"); // TODO
	return new TextFragment(eti);
}

SourceFragment* DeclarationVisitorHeader::visit(TypeAlias* typeAlias)
{
	auto fragment = new CompositeFragment(typeAlias);
	*fragment << "using " << typeAlias->nameNode() << " = " << expression(typeAlias->typeExpression()) << ";";
	return fragment;
}

}
<commit_msg>remove duplicated code<commit_after>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2015 ETH Zurich
 ** 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 ETH Zurich 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 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 "DeclarationVisitorHeader.h"
#include "ExpressionVisitorHeader.h"
#include "StatementVisitorHeader.h"
#include "ElementVisitorHeader.h"
#include "../source_visitors/DeclarationVisitorSource.h"

#include "OOModel/src/declarations/Project.h"
#include "OOModel/src/declarations/Module.h"
#include "OOModel/src/declarations/Class.h"
#include "OOModel/src/declarations/Declaration.h"
#include "OOModel/src/declarations/Method.h"
#include "OOModel/src/declarations/NameImport.h"
#include "OOModel/src/declarations/VariableDeclaration.h"
#include "OOModel/src/declarations/ExplicitTemplateInstantiation.h"
#include "OOModel/src/declarations/TypeAlias.h"

#include "Export/src/tree/SourceDir.h"
#include "Export/src/tree/SourceFile.h"
#include "Export/src/tree/CompositeFragment.h"
#include "Export/src/tree/TextFragment.h"

using namespace Export;
using namespace OOModel;

namespace CppExport {

SourceFragment* DeclarationVisitorHeader::visit(Declaration* declaration)
{
	if (auto castDeclaration = DCast<Method>(declaration)) return visit(castDeclaration);
	if (auto castDeclaration = DCast<Class>(declaration)) return visit(castDeclaration);
	if (auto castDeclaration = DCast<VariableDeclaration>(declaration)) return visit(castDeclaration);
	if (auto castDeclaration = DCast<TypeAlias>(declaration)) return visit(castDeclaration);

	notAllowed(declaration);

	// TODO: handle comments
	auto fragment = new CompositeFragment(declaration);
	*fragment << "Invalid Declaration";
	return fragment;
}

SourceDir* DeclarationVisitorHeader::visitProject(Project* project, SourceDir* parent)
{
	auto projectDir = parent ? &parent->subDir(project->name()) : new SourceDir(nullptr, "src");

	for (auto node : *project->projects()) visitProject(node, projectDir);
	for (auto node : *project->modules()) visitModule(node, projectDir);
	for (auto node : *project->classes()) visitTopLevelClass(node, projectDir);

	notAllowed(project->methods());
	notAllowed(project->fields());

	return projectDir;
}

SourceDir* DeclarationVisitorHeader::visitModule(Module* module, SourceDir* parent)
{
	Q_ASSERT(parent);
	auto moduleDir = &parent->subDir(module->name());

	for (auto node : *module->modules()) visitModule(node, moduleDir);
	for (auto node : *module->classes()) visitTopLevelClass(node, moduleDir);

	notAllowed(module->methods());
	notAllowed(module->fields());

	return moduleDir;
}

SourceFile* DeclarationVisitorHeader::visitTopLevelClass(Class* classs, SourceDir* parent)
{
	Q_ASSERT(parent);
	auto classFile = &parent->file(classs->name() + ".h");

	CompositeFragment* fragment = classFile->append(new CompositeFragment(classs, "sections"));

	auto imports = fragment->append(new CompositeFragment(classs, "vertical"));
	for (auto node : *classs->subDeclarations())
	{
		if (auto ni = DCast<NameImport>(node)) *imports << visit(ni);
		else notAllowed(node);
	}

	*fragment << visit(classs);

	return classFile;
}

SourceFragment* DeclarationVisitorHeader::visitTopLevelClass(Class* classs)
{
	auto fragment = new CompositeFragment(classs, "spacedSections");
	*fragment << visit(classs);

	auto filter = [](Method* method) { return !method->typeArguments()->isEmpty(); };
	*fragment << list(classs->methods(), DeclarationVisitorSource(data()), "spacedSections", filter);
	return fragment;
}

SourceFragment* DeclarationVisitorHeader::visit(Class* classs)
{
	auto fragment = new CompositeFragment(classs);

	if (!classs->typeArguments()->isEmpty())
		*fragment << list(classs->typeArguments(), ElementVisitorHeader(data()), "typeArgsList");
	*fragment << printAnnotationsAndModifiers(classs);
	if (Class::ConstructKind::Class == classs->constructKind()) *fragment << "class ";
	else if (Class::ConstructKind::Struct == classs->constructKind()) *fragment << "struct ";
	else if (Class::ConstructKind::Enum == classs->constructKind()) *fragment << "enum ";
	else notAllowed(classs);

	if (auto namespaceModule = classs->firstAncestorOfType<Module>())
		*fragment << namespaceModule->name().toUpper() + "_API ";

	*fragment << classs->nameNode();

	if (!classs->baseClasses()->isEmpty())
		// TODO: inheritance modifiers like private, virtual... (not only public)
		*fragment << list(classs->baseClasses(), ExpressionVisitorHeader(data()), "baseClasses");

	notAllowed(classs->friends());

	auto sections = fragment->append( new CompositeFragment(classs, "bodySections"));

	if (classs->enumerators()->size() > 0)
		error(classs->enumerators(), "Enum unhandled"); // TODO

	auto publicSection = new CompositeFragment(classs, "accessorSections");
	auto publicFilter = [](Declaration* declaration) { return declaration->modifiers()->isSet(Modifier::Public); };
	bool hasPublicSection = addMemberDeclarations(classs, publicSection, publicFilter);
	if (hasPublicSection)
	{
		*sections << "public:";
		sections->append(publicSection);
	}

	auto protectedSection = new CompositeFragment(classs, "accessorSections");
	auto protectedFilter = [](Declaration* declaration) { return declaration->modifiers()->isSet(Modifier::Protected); };
	bool hasProtectedSection = addMemberDeclarations(classs, protectedSection, protectedFilter);
	if (hasProtectedSection)
	{
		if (hasPublicSection) *sections << "\n"; // add newline between two accessor sections

		*sections << "protected:";
		sections->append(protectedSection);
	}

	auto privateSection = new CompositeFragment(classs, "accessorSections");
	auto privateFilter = [](Declaration* declaration) { return !declaration->modifiers()->isSet(Modifier::Public) &&
																				  !declaration->modifiers()->isSet(Modifier::Protected); };
	bool hasPrivateSection = addMemberDeclarations(classs, privateSection, privateFilter);
	if (hasPrivateSection)
	{
		if (hasPublicSection || hasProtectedSection) *sections << "\n"; // add newline between two accessor sections

		*sections << "private:";
		sections->append(privateSection);
	}

	return fragment;
}

template<typename Predicate>
bool DeclarationVisitorHeader::addMemberDeclarations(Class* classs, CompositeFragment* section, Predicate filter)
{
	auto subDeclarations = list(classs->subDeclarations(), this, "sections", filter);
	auto fields = list(classs->fields(), this, "vertical", filter);
	auto classes = list(classs->classes(), this, "sections", filter);
	auto methods = list(classs->methods(), this, "sections", filter);

	*section << subDeclarations << fields << classes << methods;
	return !subDeclarations->fragments().empty() ||
			 !fields->fragments().empty() ||
			 !classes->fragments().empty() ||
			 !methods->fragments().empty();
}

SourceFragment* DeclarationVisitorHeader::visit(Method* method)
{
	auto fragment = new CompositeFragment(method);

	if (!method->typeArguments()->isEmpty())
		*fragment << list(method->typeArguments(), ElementVisitorHeader(data()), "templateArgsList");

	*fragment << printAnnotationsAndModifiers(method);

	if (method->results()->size() > 1)
		error(method->results(), "Cannot have more than one return value in C++");

	if (method->methodKind() != Method::MethodKind::Constructor &&
		 method->methodKind() != Method::MethodKind::Destructor)
	{
		if (!method->results()->isEmpty())
			*fragment << expression(method->results()->at(0)->typeExpression()) << " ";
		else
			*fragment << "void ";
	}

	if (method->methodKind() == Method::MethodKind::Destructor && !method->name().startsWith("~")) *fragment << "~";
	*fragment << method->nameNode();

	*fragment << list(method->arguments(), ElementVisitorHeader(data()), "argsList");

	if (!method->throws()->isEmpty())
	{
		*fragment << " throw (";
		*fragment << list(method->throws(), ExpressionVisitorHeader(data()), "comma");
		*fragment << ")";
	}

	notAllowed(method->subDeclarations());
	notAllowed(method->memberInitializers());

	if (method->modifiers()->isSet(Modifier::Override))
		*fragment << " " << new TextFragment(method->modifiers(), "override");

	*fragment << ";";

	return fragment;
}

SourceFragment* DeclarationVisitorHeader::visit(VariableDeclaration* vd)
{
	auto fragment = new CompositeFragment(vd);
	*fragment << printAnnotationsAndModifiers(vd);
	*fragment << expression(vd->typeExpression()) << " " << vd->nameNode();
	if (vd->initialValue())
		*fragment << " = " << expression(vd->initialValue());

	if (!DCast<Expression>(vd->parent())) *fragment << ";";
	return fragment;
}

SourceFragment* DeclarationVisitorHeader::visit(NameImport* nameImport)
{
	error(nameImport, "NameImport unhandled"); // TODO
	return new TextFragment(nameImport);
}

SourceFragment* DeclarationVisitorHeader::printAnnotationsAndModifiers(Declaration* declaration)
{
	auto fragment = new CompositeFragment(declaration, "vertical");
	if (!declaration->annotations()->isEmpty()) // avoid an extra new line if there are no annotations
		*fragment << list(declaration->annotations(), StatementVisitorHeader(data()), "vertical");
	auto header = fragment->append(new CompositeFragment(declaration, "space"));

	if (declaration->modifiers()->isSet(Modifier::Static))
		*header << new TextFragment(declaration->modifiers(), "static");

	if (declaration->modifiers()->isSet(Modifier::Final))
		*header << new TextFragment(declaration->modifiers(), "final");
	if (declaration->modifiers()->isSet(Modifier::Abstract))
		*header << new TextFragment(declaration->modifiers(), "abstract");

	if (declaration->modifiers()->isSet(Modifier::Virtual))
		*header << new TextFragment(declaration->modifiers(), "virtual");
	if (declaration->modifiers()->isSet(Modifier::Inline))
		*header << new TextFragment(declaration->modifiers(), "inline");

	return fragment;
}

SourceFragment* DeclarationVisitorHeader::visit(ExplicitTemplateInstantiation* eti)
{
	error(eti, "ExplicitTemplateInstantiation unhandled"); // TODO
	return new TextFragment(eti);
}

SourceFragment* DeclarationVisitorHeader::visit(TypeAlias* typeAlias)
{
	auto fragment = new CompositeFragment(typeAlias);
	*fragment << "using " << typeAlias->nameNode() << " = " << expression(typeAlias->typeExpression()) << ";";
	return fragment;
}

}
<|endoftext|>