text:
//
// Copyright yutopp 2013 - .
//
// 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)
//

#include <rill/semantic_analysis/semantic_analysis.hpp>
#include <rill/semantic_analysis/messaging.hpp>
#include <rill/semantic_analysis/message_code.hpp>
#include <rill/semantic_analysis/make_mangled_name.hpp>

#include <rill/environment/environment.hpp>
#include <rill/environment/make_module_name.hpp>
#include <rill/behavior/intrinsic_action_holder.hpp>

#include <rill/ast/ast.hpp>
#include <rill/utility/tie.hpp>

#include <algorithm>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

#include <boost/scope_exit.hpp>

namespace rill
{
    namespace semantic_analysis
    {
        // root of ast
        RILL_VISITOR_OP( analyzer, ast::module, s, parent_env )
        {
            auto const working_dir
                = s->fullpath.empty()
                ? fs::current_path()
                : s->fullpath.parent_path();
            working_dirs_.push( working_dir );
            if ( import_bases_.empty() ) {
                // set default import path!
                import_bases_.push( working_dir );
            }
            auto const& import_base = import_bases_.top();

            rill_dout << "working dir  : " << working_dir << std::endl
                      << "import_bases : " << import_base << std::endl;

            // to forward reference
            auto const& report = collect_identifier( g_env_, s, parent_env, import_base );
            if ( report->is_errored() ) {
                import_messages( report );
                working_dirs_.pop();
                return;
            }

            //
            auto const& module_name = make_module_name( import_base, s );

            auto module_env = g_env_->find_module( module_name );
            module_envs_.push( module_env );

            block_envs_.emplace( module_env );
            BOOST_SCOPE_EXIT_ALL(this) {
                block_envs_.pop();
            };

            if ( module_name.empty() || module_name == "basic_types" ) {
                builtin_class_envs_cache_
                    = std::make_shared<builtin_class_envs_cache>( module_env );

            } else {
                // all modules(except 'basic_types') must import 'basic_types' module.
                auto const i_decl = ast::import_decl_unit{
                    "basic_types"
                };
                import_module( i_decl, module_env );
            }

            //
            assert( s->program != nullptr );
            dispatch( s->program, module_env );
        }

        RILL_VISITOR_OP( analyzer, ast::statements, s, parent_env )
        {
            // build environment
            for( auto const& ss : s->statements_ )
                dispatch( ss, parent_env );
        }

        RILL_VISITOR_OP( analyzer, ast::import_statement, s, parent_env )
        {
            for( auto&& decl : s->module_decls ) {
                import_module( decl, parent_env );
            }
        }

        RILL_VISITOR_OP( analyzer, ast::block_statement, s, parent_env )
        {
            auto const& scope_env
                = parent_env->construct( kind::k_scope );
            scope_env->link_with_ast( s->statements_ );

            block_envs_.emplace( scope_env );
            BOOST_SCOPE_EXIT_ALL(this) {
                block_envs_.pop();
            };

            dispatch( s->statements_, scope_env );

            // delegate is_closed
            parent_env->mask_is_closed( scope_env->is_closed() );
        }

        RILL_VISITOR_OP( analyzer, ast::template_statement, s, parent_env )
        {
            // do nothing
        }

        // statement
        RILL_VISITOR_OP( analyzer, ast::expression_statement, s, parent_env )
        {
            auto const& ty_d = dispatch( s->expression_, parent_env );
            if ( ty_d->eval_mode == type_detail::evaluate_mode::k_only_meta
                 || ty_d->eval_mode == type_detail::evaluate_mode::k_meta
                )
            {
                substitute_by_ctfed_node( s->expression_, ty_d, parent_env );
            }

            // TODO: check this expression is [noreturn].
            // [noreturn] means control flow will go to elsewhere. so closed.
            // parent_env->mask_is_closed( true );
        }

        //
        RILL_VISITOR_OP( analyzer, ast::return_statement, s, parent_env )
        {
            // Return Statement is valid only in Function Envirionment...
            auto const& a_env = parent_env->lookup_layer( kind::type_value::e_function );
            assert( a_env != nullptr ); // TODO: change to error_handler

            rill_dout << "Return Statement [target: f_env] ------>> " << std::endl
                      << " type: " << debug_string( a_env->get_symbol_kind() ) << std::endl
                      << " env : " << a_env << std::endl;

            auto const& callee_f_env = cast_to<function_symbol_environment>( a_env );
            assert( callee_f_env != nullptr );

            auto const& return_type_detail
                = dispatch( s->expression_, parent_env );

            assert( !is_nontype_id( return_type_detail->type_id ) && "[[CE]] this object couldn't be returned" );

            if ( callee_f_env->is_return_type_decided() ) {
                // type check
                auto const& cf_tid = callee_f_env->get_return_type_id();
                auto const& cf_ty = g_env_->get_type_at( cf_tid );

                // check if available converting from return_type_detail->type_id to cf_tid

            } else {
                // return statement that first apeared in function env
                //   sets default return type, if return type is not decided
                callee_f_env->decide_return_type( return_type_detail->type_id );
            }

            // statement return to anywhare, so this environment is closed
            parent_env->mask_is_closed( true );
        }

        //
        //
        //
        RILL_VISITOR_OP( analyzer, ast::variable_declaration_statement, s, parent_env )
        {
            auto const related_env = g_env_->get_related_env_by_ast_ptr( s );
            assert( related_env == nullptr && "[[ice]]" ); // ??

            auto const& val_decl = s->declaration_;
            // TODO: decl_unit will be unit_list
            // for( auto const& unit : val_decl.decl_unit_list ) {
            auto const& unit = val_decl.decl_unit;
            auto& initializer = s->declaration_.decl_unit.init_unit.initializer;

            regard_variable_is_not_already_defined(
                parent_env,
                unit.name
                );

            // initial value
            auto iv_type_d
                = unit.init_unit.initializer
                ? dispatch( unit.init_unit.initializer, parent_env )
                : nullptr;

            //
            auto const& v_env = parent_env->incomplete_construct(
                kind::k_variable,
                unit.name
                );
            v_env->link_with_ast( s );

            auto const& void_class_id = get_primitive_class_env( "void" )->get_id();

            // TODO: make method to determine "type"

            // unit.kind -> val or ref
            // TODO: use unit.kind( default val )

            // TODO: evaluate type || type inference || type check
            //       default( int )

            if ( unit.init_unit.type ) { // is parameter variable type specified ?
                resolve_type(
                    unit.init_unit.type,
                    val_decl.quality,
                    parent_env,
                    [&]( type_detail_ptr const& ty_d,
                         type const& ty,
                         class_symbol_environment_ptr const& class_env
                        ) {
                        if ( is_nontype_id( ty_d->type_id ) ) {
                            assert( false && "[[error]] incomplete template class was not supported" );
                        }

                        if ( class_env->get_id() == void_class_id ) {
                            assert( false && "[[error]] the value typed void can not be assigned" );
                        }

                        // TODO: move to elsewhere
                        if ( class_env->is_incomplete() ) {
                            //
                            auto const& class_node = class_env->get_related_ast();
                            assert( class_node != nullptr );

                            dispatch( class_node, class_env->get_parent_env() );
                            assert( class_env->is_complete() );
                        }

                        //
                        v_env->complete( ty_d->type_id, s->declaration_.decl_unit.decl_attr );

                        if ( iv_type_d != nullptr ) {
                            // type check
                            RILL_PP_TIE( level, conv_function_env,
                                         try_type_conversion(
                                             ty_d->type_id,
                                             iv_type_d->type_id,
                                             parent_env
                                             )
                                );

                            switch( level ) {
                            case function_match_level::k_exact_match:
                                rill_dout << "Exact" << std::endl;
                                break;
                            case function_match_level::k_qualifier_conv_match:
                                rill_dout << "Qual" << std::endl;
                                break;
                            case function_match_level::k_implicit_conv_match:
                                rill_dout << "Implicit" << std::endl;
                                break;
                            case function_match_level::k_no_match:
                                rill_dout << "NoMatch" << std::endl;
                                assert( false && "[[error]] This value can not be assigned(type conversion)" );
                            }
                        }
                    });

                if ( initializer == nullptr ) {
                    // force creating initial value

                    // REWRITE: make "call_expression" as ctor invocation
                    initializer =
                        std::make_shared<ast::call_expression>(
                            clone( unit.init_unit.type ),
                            ast::expression_list{}
                            );

                    // recheck
                    iv_type_d = dispatch( unit.init_unit.initializer, parent_env );
                    if ( iv_type_d == nullptr ) {
                        assert( false && "[error] NOT default constructable" );
                    }
                }

            } else {
                // type inferenced by result of evaluated "iv_type_id_and_env"
                if ( iv_type_d == nullptr ) {
                    assert( false && "[[error]] initial value is required" );
                }

                auto const iv_type_class_env = ref_env( iv_type_d );
                if ( iv_type_class_env->get_id() == void_class_id ) {
                    assert( false && "[[error]] the value typed void can not be assigned" );
                }

                //
                v_env->complete( iv_type_d->type_id, s->declaration_.decl_unit.decl_attr );
            }

            // update decl
            //
            assert( iv_type_d != nullptr );
            rill_dregion {
                print_type_detail( iv_type_d );
            }
            if ( auto&& eval_attr = check_eval_mode( s->declaration_.decl_unit.decl_attr, iv_type_d->eval_mode ) ) {
                v_env->set_attribute( *eval_attr );

            } else {
                assert( false && "" );
            }

            //
            if ( v_env->has_attribute( attribute::decl::k_meta )
                || v_env->has_attribute( attribute::decl::k_onlymeta )
                )
            {
                if ( unit.init_unit.initializer ) {
                    auto val
                        = substitute_by_ctfed_node(
                            s->declaration_.decl_unit.init_unit.initializer,
                            iv_type_d,
                            parent_env
                            );
                    assert( val != nullptr );

                    auto const& orig_ty
                        = g_env_->get_type_at( iv_type_d->type_id );
                    auto const& orig_c_env
                        = g_env_->get_env_at_as_strong_ref<class_symbol_environment const>(
                            orig_ty.class_env_id
                            );
                    assert( orig_c_env != nullptr );

                    // bind
                    switch( orig_c_env->get_builtin_kind() ) {
                    case class_builtin_kind::k_type:
                        ctfe_engine_->value_holder()->bind_value_of_type(
                            v_env->get_id(),
                            static_cast<type_detail_ptr>( val )
                            );
                        break;

                    default:
                        ctfe_engine_->value_holder()->bind_value(
                            v_env->get_id(),
                            static_cast<raw_value_holder_ptr>( val )
                            );
                        break;
                    }

                } else {
                    assert( false && "[ice]" );
                }
            }
        }

        //
        //
        //
        RILL_VISITOR_OP( analyzer, ast::class_variable_declaration_statement, s, parent_env )
        {
            assert( parent_env->get_symbol_kind() == kind::type_value::e_class );

            // TODO: make unit of variable decl to "AST NODE".
            // for( auto const& decl : s->decls_ ) {

            auto const related_env = g_env_->get_related_env_by_ast_ptr( s );
            // Forward referencable
            assert( related_env != nullptr );
            assert( related_env->get_symbol_kind() == kind::type_value::e_variable );

            auto const& v_env = cast_to<variable_symbol_environment>( related_env );
            assert( v_env != nullptr );

            // guard double check
            if ( v_env->is_checked() )
                return;
            v_env->change_progress_to_checked();

            auto const& parent_c_env
                = g_env_->get_env_at_as_strong_ref<class_symbol_environment>(
                    v_env->get_parent_class_env_id()
                    );
            assert( parent_c_env != nullptr );

            auto const& val_decl = s->declaration_;
            // TODO: decl_unit will be unit_list
            // for( auto const& unit : val_decl.decl_unit_list ) {
            auto const& unit = val_decl.decl_unit;

            // MEMO: do NOT check redefinition

            // TODO: make method to determine "type"

            // unit.kind -> val or ref
            // TODO: use unit.kind( default val )

            // TODO: evaluate type || type inference || type check
            if ( unit.init_unit.type ) { // is parameter variable type specified ?
                // in class, 'mutable' is DEFAULT!
                resolve_type(
                    unit.init_unit.type,
                    attribute::make( val_decl.quality, attribute::modifiability_kind::k_mutable ),
                    parent_env,
                    [&]( type_detail_ptr const& ty_d,
                         type const& ty,
                         class_symbol_environment_ptr const& class_env
                        ) {
                        auto attr = ty.attributes;

                        //
                        rill_dout << "class variable: " << unit.name->get_inner_symbol()->to_native_string() << std::endl;

                        if ( class_env->get_builtin_kind() == class_builtin_kind::k_void ) {
                            assert( false && "[error] void is not able to be instanced" );
                        }

                        //
                        if ( !class_env->is_default_copyable() ) {
                            parent_c_env->set_traits_flag( class_traits_kind::k_has_non_default_copyable_member, true );
                        }

                        //
                        {
                            auto const& padding
                                = parent_c_env->get_target_size()
                                % std::max( class_env->get_target_align(), std::size_t{1u} );
                            auto const& size = padding + class_env->get_target_size();

                            //
                            // set alignment
                            parent_c_env->set_target_size(
                                parent_c_env->get_target_size() + size
                                );

                            // set alignment
                            parent_c_env->set_target_align(
                                std::max(
                                    parent_c_env->get_target_align(),
                                    class_env->get_target_align()
                                    )
                                );
                        }

                        // completion
                        v_env->complete(
                            g_env_->make_type_id(
                                class_env,
                                attr
                                ),
                            s->declaration_.decl_unit.decl_attr
                            );
                    });

            } else {
                // type inferenced by result of evaluated [[default initializer expression]]

                // TODO: implement type inference
                assert( false );
            }
        }

        //
        //
        //
        RILL_VISITOR_OP( analyzer, ast::function_definition_statement, s, parent_env )
        {
            rill_dout
                << " != Semantic" << std::endl
                << "    function_definition_statement: " << std::endl
                << "     name -- " << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl
                << "     Args num -- " << s->parameter_list.size() << std::endl;

            auto const related_env = g_env_->get_related_env_by_ast_ptr( s );
            assert( related_env != nullptr );
            assert( related_env->get_symbol_kind() == kind::type_value::e_function );

            auto const& f_env = cast_to<function_symbol_environment>( related_env );
            assert( f_env != nullptr );

            rill_dout << "$" << std::endl;
            // guard double check
            if ( f_env->is_checked() ) return;
            f_env->change_progress_to_checked();
            rill_dout << "$ uncheckd" << std::endl;

            block_envs_.emplace( f_env );
            BOOST_SCOPE_EXIT_ALL(this) {
                block_envs_.pop();
            };

            //
            declare_function_parameters( f_env, s );

            // return type
            if ( s->return_type_ ) {
                // if return type was specified, decide type to it.
                resolve_type(
                    s->return_type_,
                    attribute::holder_kind::k_val,     // TODO: fix
                    f_env,
                    [&]( type_detail_ptr const& return_ty_d,
                         type const& ty,
                         class_symbol_environment_ptr const& class_env
                        ) {
                        rill_dout << "return type is >>" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

                        f_env->decide_return_type( return_ty_d->type_id );
                    });
            }

            // scan all statements in this function body
            rill_dout << ">>>>" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;
            dispatch( s->inner_, f_env );
            rill_dout << "<<<<" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

            rill_dout << "returned: " << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

            // Return type
            solve_function_return_type_semantics( f_env );

            //
            auto const& mangled_name = make_mangled_name( g_env_, f_env );
            f_env->complete( mangled_name, s->decl_attr_ );
            g_env_->map_mangled_env( mangled_name, f_env->get_id() );
        }

        //
        //
        //
        RILL_VISITOR_OP( analyzer, ast::class_function_definition_statement, s, parent_env )
        {
            rill_dout
                << " != Semantic" << std::endl
                << "    CLASS function_definition_statement: " << std::endl
                << "     name -- " << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl
                << "     Args num -- " << s->parameter_list.size() << std::endl;

            auto const related_env = g_env_->get_related_env_by_ast_ptr( s );
            assert( related_env != nullptr );
            assert( related_env->get_symbol_kind() == kind::type_value::e_function );

            auto const& f_env = cast_to<function_symbol_environment>( related_env );
            assert( f_env != nullptr );

            rill_dout << "$" << std::endl;
            // guard double check
            if ( f_env->is_checked() ) return;
            f_env->change_progress_to_checked();
            rill_dout << "$ unchecked" << std::endl;

            block_envs_.emplace( f_env );
            BOOST_SCOPE_EXIT_ALL(this) {
                block_envs_.pop();
            };

            auto const& parent_c_env
                = g_env_->get_env_at_as_strong_ref<class_symbol_environment>(
                    f_env->get_parent_class_env_id()
                    );
            assert( parent_c_env != nullptr );

            // TODO: fix
            bool const is_constructor
                = s->get_identifier()->get_inner_symbol()->to_native_string() == "ctor";

            //
            declare_function_parameters( f_env, s );

            if ( is_constructor ) {
                //
                f_env->mark_as_initialize_function();

                // constructor
                if ( s->return_type_ != nullptr ) {
                    semantic_error(
                        message_code::e_constructor_has_return_type,
                        s,
                        format( "Constructors can not have a return type" )
                        );
                }

                // force set, return type must be void
                auto const& void_class_env = get_primitive_class_env( "void" );
                auto ret_ty_id = g_env_->make_type_id(
                    void_class_env,
                    attribute::make_default_type_attributes()
                    );
                f_env->decide_return_type( ret_ty_id );

            } else {
                // normal function

                if ( s->initializers != boost::none ) {
                    semantic_error(
                        message_code::e_class_function_has_initializers,
                        s,
                        format( "Normal class functions can not have an initializer list" )
                        );
                }

                // return type
                if ( s->return_type_ ) {
                    // if return type was specified, decide type to it.
                    resolve_type(
                        s->return_type_,
                        attribute::holder_kind::k_val,     // TODO: fix
                        f_env,
                        [&]( type_detail_ptr const& return_ty_d,
                             type const& ty,
                             class_symbol_environment_ptr const& class_env
                            ) {
                            rill_dout << "return type is >>" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

                            f_env->decide_return_type( return_ty_d->type_id );
                        });
                }
            }

            // initializer list
            if ( s->initializers ) {
                // list
                for( auto&& var_unit : s->initializers->initializers ) {
                    assert( var_unit.init_unit.initializer != nullptr );
                    assert( var_unit.init_unit.type == nullptr );

                    // initial value
                    auto const& iv_type_d
                        = dispatch( var_unit.init_unit.initializer, f_env );
                    assert( iv_type_d != nullptr );

                    // search class variable
                    auto const& d_ty
                        = solve_identifier( var_unit.name, parent_c_env, false );
                    if ( d_ty == nullptr ) {
                        semantic_error(
                            message_code::e_id_not_found,
                            var_unit.name,
                            format( "Identifier '%1%' was not declared." ) % var_unit.name->get_inner_symbol()->to_native_string()
                            );
                    }

                    //
                    auto const& element_env
                        = g_env_->get_related_env_by_ast_ptr( var_unit.name );
                    assert( element_env != nullptr );
                    if ( element_env->get_symbol_kind() != kind::type_value::e_variable ) {
                        assert( false );
                    }
                    auto const& v_env
                        = cast_to<variable_symbol_environment const>( element_env );
                    assert( v_env != nullptr );

                    // type check
                    RILL_PP_TIE( level, conv_function_env,
                                 try_type_conversion(
                                     d_ty->type_id,
                                     iv_type_d->type_id,
                                     parent_env
                                     )
                        );

                    switch( level ) {
                    case function_match_level::k_exact_match:
                        rill_dout << "Exact" << std::endl;
                        break;
                    case function_match_level::k_qualifier_conv_match:
                        rill_dout << "Qual" << std::endl;
                        break;
                    case function_match_level::k_implicit_conv_match:
                        rill_dout << "Implicit" << std::endl;
                        break;
                    case function_match_level::k_no_match:
                        rill_dout << "NoMatch" << std::endl;
                        assert( false && "[[error]] This value can not be assigned(type conversion)" );
                    }
                }
            }

            // scan all statements in this function body
            rill_dout << ">>>>" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;
            dispatch( s->inner_, f_env );
            rill_dout << "<<<<" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

            rill_dout << "returned: " << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

            // Return type
            solve_function_return_type_semantics( f_env );

            if ( !f_env->is_closed() ) {
                //
                s->inner_->statements_.emplace_back(
                    std::make_shared<ast::return_statement>( nullptr )
                    );
            }

            //
            auto const& mangled_name = make_mangled_name( g_env_, f_env );
            f_env->complete( mangled_name, s->decl_attr_ );
            g_env_->map_mangled_env( mangled_name, f_env->get_id() );

            //
            assert( s->is_class_function() );
            auto const sig = make_signature_for_virtual_function( g_env_, f_env );

            //
            auto it = parent_c_env->vtable_.find( sig );
            if ( it != parent_c_env->vtable_.cend() ) {
                auto& unit = it->second;
                auto const index = unit.index;
                f_env->mark_as_virtual( index );

                parent_c_env->vtable_[sig]
                    = class_symbol_environment::virtual_function_unit{
                    index,
                    f_env->get_id()
                };

            }
        }

        RILL_VISITOR_OP( analyzer, ast::class_virtual_function_definition_statement, s, parent_env )
        {
            rill_dout
                << " != Semantic" << std::endl
                << "    CLASS virtual_function_definition_statement: " << std::endl
                << "     name -- " << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl
                << "     Args num -- " << s->parameter_list.size() << std::endl;

            auto const related_env = g_env_->get_related_env_by_ast_ptr( s );
            assert( related_env != nullptr );
            assert( related_env->get_symbol_kind() == kind::type_value::e_function );

            auto const& f_env = cast_to<function_symbol_environment>( related_env );
            assert( f_env != nullptr );

            rill_dout << "$" << std::endl;
            // guard double check
            if ( f_env->is_checked() ) return;
            f_env->change_progress_to_checked();
            rill_dout << "$ unchecked" << std::endl;

            block_envs_.emplace( f_env );
            BOOST_SCOPE_EXIT_ALL(this) {
                block_envs_.pop();
            };

            auto const& parent_c_env
                = g_env_->get_env_at_as_strong_ref<class_symbol_environment>(
                    f_env->get_parent_class_env_id()
                    );
            assert( parent_c_env != nullptr );

            //
            parent_c_env->set_traits_flag(
                class_traits_kind::k_has_virtual_functions,
                true
                );

            //
            declare_function_parameters( f_env, s );

            // return type
            if ( s->return_type_ ) {
                // if return type was specified, decide type to it.
                resolve_type(
                    s->return_type_,
                    attribute::holder_kind::k_val,     // TODO: fix
                    f_env,
                    [&]( type_detail_ptr const& return_ty_d,
                         type const& ty,
                         class_symbol_environment_ptr const& class_env
                        ) {
                        rill_dout << "return type is >>" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

                        f_env->decide_return_type( return_ty_d->type_id );
                    });
            }

            if ( s->inner_ ) {
                // scan all statements in this function body
                rill_dout << ">>>>" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;
                dispatch( s->inner_, f_env );
                rill_dout << "<<<<" << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

                rill_dout << "returned: " << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl;

                // Return type
                solve_function_return_type_semantics( f_env );

                if ( !f_env->is_closed() ) {
                    //
                    s->inner_->statements_.emplace_back(
                        std::make_shared<ast::return_statement>( nullptr )
                        );
                }
            }

            //
            auto const mangled_name = make_mangled_name( g_env_, f_env );
            f_env->complete( mangled_name, s->decl_attr_ );
            g_env_->map_mangled_env( mangled_name, f_env->get_id() );

            //
            assert( s->is_class_function() );
            auto const sig = make_signature_for_virtual_function( g_env_, f_env );

            //
            auto it = parent_c_env->vtable_.find( sig );
            if ( it != parent_c_env->vtable_.cend() ) {
                auto& unit = it->second;
                auto const index = unit.index;
                f_env->mark_as_virtual( index );

                parent_c_env->vtable_[sig]
                    = class_symbol_environment::virtual_function_unit{
                    index,
                    f_env->get_id()
                };

            } else {
                //
                auto const index = parent_c_env->get_virtual_count();
                f_env->mark_as_virtual( index );
                parent_c_env->increment_virtual_count();

                parent_c_env->vtable_[sig]
                    = class_symbol_environment::virtual_function_unit{
                    index,
                    f_env->get_id()
                };
            }
        }

        RILL_VISITOR_OP( analyzer, ast::class_definition_statement, s, parent_env )
        {
            // TODO: dup check...
            // enverinment is already pre constructed by identifier_collector
            auto const related_env = g_env_->get_related_env_by_ast_ptr( s );
            assert( related_env != nullptr );
            assert( related_env->get_symbol_kind() == kind::type_value::e_class );

            auto const& c_env
                = std::static_pointer_cast<class_symbol_environment>( related_env );
            assert( c_env != nullptr );

            //
            complete_class( s, c_env );
        }

        RILL_VISITOR_OP( analyzer, ast::while_statement, s, parent_env )
        {
            auto const& scope_env = g_env_->allocate_env<scope_environment>( parent_env ); // MEMO:
            scope_env->link_with_ast( s );

            // TODO: type check
            dispatch( s->conditional_, scope_env );
            parent_env->mask_is_closed( scope_env->is_closed() );

            auto const& body_scope_env = g_env_->allocate_env<scope_environment>( scope_env );
            body_scope_env->link_with_ast( s->body_statement_ );

            dispatch( s->body_statement_, body_scope_env );
            parent_env->mask_is_closed( body_scope_env->is_closed() );
        }

        RILL_VISITOR_OP( analyzer, ast::if_statement, s, parent_env )
        {
            auto const& if_scope_env = g_env_->allocate_env<scope_environment>( parent_env ); // MEMO:
            if_scope_env->link_with_ast( s );

            // cond
            dispatch( s->conditional_, if_scope_env );  // TODO: type check
            parent_env->mask_is_closed( if_scope_env->is_closed() );

            // then
            auto const& if_then_env = g_env_->allocate_env<scope_environment>( if_scope_env );
            if_then_env->link_with_ast( s->then_statement_ );
            dispatch( s->then_statement_, if_then_env );
            bool const is_closed_0 = if_then_env->is_closed();

            // else( optional )
            bool is_closed_1 = false;
            if ( s->else_statement_ ) {
                auto const& if_else_env = g_env_->allocate_env<scope_environment>( if_scope_env );
                if_else_env->link_with_ast( s->else_statement_ );
                dispatch( s->else_statement_, if_else_env );
                is_closed_1 = if_else_env->is_closed();
            }

            parent_env->mask_is_closed( is_closed_0 && is_closed_1 );
        }

        //
        //
        //
        RILL_VISITOR_OP( analyzer, ast::extern_function_declaration_statement, s, parent_env )
        {
            rill_dout
                << "= extern_function_definition_statement:" << std::endl
                << " Name -- " << s->get_identifier()->get_inner_symbol()->to_native_string() << std::endl
                << " Args num -- " << s->parameter_list.size() << std::endl
                << " Parent env -- " << (const_environment_base_ptr)parent_env << std::endl;

            // enverinment is already pre constructed by identifier_collector
            auto const related_env = g_env_->get_related_env_by_ast_ptr( s );
            assert( related_env != nullptr );
            assert( related_env->get_symbol_kind() == kind::type_value::e_function );

            auto const& f_env = cast_to<function_symbol_environment>( related_env );
            assert( f_env != nullptr );

            // guard double check
            if ( f_env->is_checked() )
                return;
            f_env->change_progress_to_checked();

            block_envs_.emplace( f_env );
            BOOST_SCOPE_EXIT_ALL(this) {
                block_envs_.pop();
            };

            // construct function environment in progress phase

            declare_function_parameters( f_env, s );

            //
            // Return type
            if ( s->return_type_ ) {
                resolve_type(
                    s->return_type_,
                    attribute::holder_kind::k_val,     // TODO: fix
                    parent_env,
                    [&]( type_detail_ptr const& return_ty_d,
                         type const& ty,
                         class_symbol_environment_ptr const& class_env
                        ) {
                        f_env->decide_return_type( return_ty_d->type_id );

                        auto const& mangled_name = make_mangled_name( g_env_, f_env );
                        f_env->complete(
                            mangled_name,
                            attribute::decl::k_extern | s->decl_attr_
                            );
                        g_env_->map_mangled_env( mangled_name, f_env->get_id() );
                    });

            } else {
                // extern function MUST specifies RETURN TYPE. [[compilation error]]
                assert( false && "" );
            }

            //
            if ( f_env->has_attribute( attribute::decl::k_intrinsic ) ) {
                if ( auto&& id = action_holder_->is_registered( s->extern_symbol_name_ ) ) {
                    f_env->mark_as_intrinsic_function( *id );

                } else {
                    rill_dout << s->extern_symbol_name_ << std::endl;
                    assert( false && "[error] this intrinsic function is not registered" );
                }
            }
        }

        RILL_VISITOR_OP( analyzer, ast::extern_class_declaration_statement, s, parent_env )
        {
            // TODO: dup check...
            // enverinment is already pre constructed by identifier_collector
            auto const related_env = g_env_->get_related_env_by_ast_ptr( s );
            assert( related_env != nullptr );
            assert( related_env->get_symbol_kind() == kind::type_value::e_class );

            auto const& c_env
                = std::static_pointer_cast<class_symbol_environment>( related_env );
            assert( c_env != nullptr );

            complete_class( s, c_env );
        }

    } // namespace semantic_analysis
} // namespace rill

max_stars_repo_name: rhysd/rill

max_issues_repo_name: rhysd/rill

max_forks_repo_name: rhysd/rill


text:
#pragma once
#ifndef IGROW_LIGAND_HPP
#define IGROW_LIGAND_HPP

#include <boost/filesystem/path.hpp>
#include "atom.hpp"
using namespace boost::filesystem;

//! Represents a ROOT or a BRANCH in PDBQT structure.
class frame
{
public:
	size_t parent; //!< Frame array index pointing to the parent of current frame. For ROOT frame, this field is not used.
	size_t rotorX; //!< Serial number of the parent frame atom which forms a rotatable bond with rotorY.
	size_t rotorY; //!< Serial number of the current frame atom which forms a rotatable bond with rotorX.
	size_t begin; //!< The inclusive beginning index to the atoms of the current frame.
	size_t end; //!< The exclusive ending index to the atoms of the current frame.
	vector<size_t> branches; //!< Indexes to child branches.

	//! Constructs a frame, and initializes its parent frame, rotor connectors, and beginning atom index.
	explicit frame(const size_t parent, const size_t rotorX, const size_t rotorY, const size_t begin) : parent(parent), rotorX(rotorX), rotorY(rotorY), begin(begin) {}
};

//! Represents a ligand.
class ligand
{
public:
	path p; //!< Path to the current ligand.
	path parent1; //!< Parent ligand 1.
	path parent2; //!< Parent ligand 2.
	string connector1; //!< The connecting bond of parent 1.
	string connector2; //!< The connecting bond of parent 2.
	vector<frame> frames; //!< Frames.
	vector<atom> atoms; //!< Atoms.
	size_t max_atom_number; //!< Maximum atom serial number.
	size_t num_rotatable_bonds; //!< Number of rotatable bonds.
	size_t num_atoms; //!< Number of atoms.
	size_t num_hb_donors; //!< Number of hydrogen bond donors.
	size_t num_hb_acceptors; //!< Number of hydrogen bond acceptors.
	double mol_mass; //!< Molecular mass.
	double id_score; //!< Predicted idock score obtained by external docking.
	double rf_score; //!< Predicted RF-Score obtained by external docking.

	//! Constructs an empty ligand.
	explicit ligand() {}

	//! Constructs a ligand by parsing a given ligand file in PDBQT.
	explicit ligand(const path& p);

	//! Constructs a ligand by crossover.
	explicit ligand(const path& p, const ligand& l1, const ligand& l2, const size_t g1, const size_t g2);

	//! Returns true if the current ligand is able to perform crossover.
	bool crossoverable() const;

	//! Compares the efficacy of the current ligand and the other ligand for sorting ptr_vector<ligand>.
	bool operator<(const ligand& l) const;

	//! Saves the current ligand to a file in PDBQT format.
	void save() const;

	//! Parses the docked ligand to obtain predicted free energy and docked coordinates.
	void update();

	//! Gets the frame and index to which a atom belongs to given its serial number.
	pair<size_t, size_t> get_frame(const size_t srn) const;
};

#endif

ext: hpp

max_stars_repo_name: HongjianLi/igrow

max_issues_repo_name: HongjianLi/igrow

max_forks_repo_name: HongjianLi/igrow


text:
//  (C) Copyright Edward Diener 2011-2015
//  Use, modification and distribution are subject to 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).

#include <boost/vmd/elem.hpp>
#include <boost/vmd/is_empty.hpp>
#include <boost/vmd/is_identifier.hpp>
#include <boost/vmd/is_list.hpp>
#include <boost/vmd/is_type.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/detail/lightweight_test.hpp>

int main()
  {

#if BOOST_PP_VARIADICS

 #define BOOST_VMD_REGISTER_ANAME (ANAME)
 #define A_SEQUENCE (1,2,3) 46 (list_data1,(list_data2,BOOST_PP_NIL)) BOOST_VMD_TYPE_SEQ ANAME
 #define AN_EMPTY_SEQUENCE

 BOOST_TEST_EQ(BOOST_PP_TUPLE_ELEM(2,BOOST_VMD_ELEM(0,A_SEQUENCE)),3);
 BOOST_TEST_EQ(BOOST_VMD_ELEM(1,A_SEQUENCE),46);
 BOOST_TEST(BOOST_VMD_IS_LIST(BOOST_VMD_ELEM(2,A_SEQUENCE)));
 BOOST_TEST(BOOST_VMD_IS_TYPE(BOOST_VMD_ELEM(3,A_SEQUENCE)));
 BOOST_TEST(BOOST_VMD_IS_IDENTIFIER(BOOST_VMD_ELEM(4,A_SEQUENCE)));
 BOOST_TEST(BOOST_VMD_IS_EMPTY(BOOST_VMD_ELEM(5,A_SEQUENCE)));
 BOOST_TEST(BOOST_VMD_IS_EMPTY(BOOST_VMD_ELEM(0,AN_EMPTY_SEQUENCE)));

#else

BOOST_ERROR("No variadic macro support");

#endif

  return boost::report_errors();

  }

ext: cxx


text:
/*! \file 2d_full.cpp
  \brief 2D plot of functions from map of doubles showing use of more options.
  \author Jacob Voytko
  \date 2007
*/

// Copyright Jacob Voytko 2007
// Distributed under the Boost Software License, Version 1.0.
// For more information, see http://www.boost.org

#include <boost/svg_plot/svg_2d_plot.hpp>
using namespace boost::svg;

#include <map>
using std::map;
#include <cmath>
using ::sqrt;

// Some functions to plot.
double f(double x)
{
  return sqrt(x);
}

double g(double x)
{
  return -2 + x*x;
}

double h(double x)
{
  return -1 + 2*x;
}

int main()
{
  map<double, double> data1, data2, data3;

  for(double i=0; i<=10.; i+=1.)
  {
    data1[i] = f(i);
    data2[i] = g(i);
    data3[i] = h(i);
  }

  svg_2d_plot my_plot;

  // Size/scale settings.
  my_plot.size(700, 500)
         .x_range(-1, 10)
         .y_range(-5, 100);

  // Text settings.
  my_plot.title("Plot of Mathematical Functions")
         .title_font_size(29)
         .x_label("X Axis Units");

  // Commands.
  my_plot.legend_on(true)
         .plot_window_on(true)
         .x_label_on(true)
         .x_major_labels_side(true);

  // Color settings.
  my_plot.background_color(svg_color(67, 111, 69))
         .legend_background_color(svg_color(207, 202,167))
         .legend_border_color(svg_color(102, 102, 84))
         .plot_background_color(svg_color(136, 188, 126))
         .title_color(white);

  //X axis settings.
  my_plot.x_major_interval(2)
         .x_major_tick_length(14)
         .x_major_tick_width(1)
         .x_minor_tick_length(7)
         .x_minor_tick_width(1)
         .x_num_minor_ticks(3)

  //Y axis settings.
         .y_major_interval(10)
         .y_num_minor_ticks(3);

  //legend settings
  my_plot.legend_title_font_size(15);

  my_plot.plot(data1, "Sqrt(x)").stroke_color(red);
  my_plot.plot(data2, "-2 + x^2").stroke_color(orange);
  my_plot.plot(data3, "-1 + 2x").stroke_color(yellow).shape(square).size(5);

  my_plot.write("./2d_full.svg");

  return 0;
} // int main()

ext: cpp


text:
/**
 *    Copyright (C) 2018-present MongoDB, Inc.
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the Server Side Public License, version 1,
 *    as published by MongoDB, Inc.
 *
 *    This program 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
 *    Server Side Public License for more details.
 *
 *    You should have received a copy of the Server Side Public License
 *    along with this program. If not, see
 *    <http://www.mongodb.com/licensing/server-side-public-license>.
 *
 *    As a special exception, the copyright holders give permission to link the
 *    code of portions of this program with the OpenSSL library under certain
 *    conditions as described in each individual source file and distribute
 *    linked combinations including the program with the OpenSSL library. You
 *    must comply with the Server Side Public License in all respects for
 *    all of the code used other than as permitted herein. If you modify file(s)
 *    with this exception, you may extend this exception to your version of the
 *    file(s), but you are not obligated to do so. If you do not wish to do so,
 *    delete this exception statement from your version. If you delete this
 *    exception statement from all source files in the program, then also delete
 *    it in the license file.
 */

#include <boost/optional.hpp>

#include "mongo/base/error_codes.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/platform/basic.h"

#include "mongo/unittest/barrier.h"
#include "mongo/unittest/unittest.h"

#include "mongo/util/periodic_runner_impl.h"

#include "mongo/db/concurrency/locker_noop_service_context_test_fixture.h"
#include "mongo/platform/mutex.h"
#include "mongo/stdx/condition_variable.h"
#include "mongo/util/clock_source_mock.h"

namespace mongo {

class Client;

namespace {

class PeriodicRunnerImplTestNoSetup : public LockerNoopServiceContextTest {
public:
    void setUp() override {
        _clockSource = std::make_unique<ClockSourceMock>();
        _runner = std::make_unique<PeriodicRunnerImpl>(getServiceContext(), _clockSource.get());
    }

    ClockSourceMock& clockSource() {
        return *_clockSource;
    }

    PeriodicRunner& runner() {
        return *_runner;
    }

private:
    std::unique_ptr<ClockSourceMock> _clockSource;
    std::unique_ptr<PeriodicRunner> _runner;
};

class PeriodicRunnerImplTest : public PeriodicRunnerImplTestNoSetup {
public:
    void setUp() override {
        PeriodicRunnerImplTestNoSetup::setUp();
    }

    auto makeStoppedJob() {
        PeriodicRunner::PeriodicJob job("job", [](Client* client) {}, Seconds{1});
        auto jobAnchor = runner().makeJob(std::move(job));
        jobAnchor.start();
        jobAnchor.stop();
        return jobAnchor;
    }
};

TEST_F(PeriodicRunnerImplTest, OneJobTest) {
    int count = 0;
    Milliseconds interval{5};

    auto mutex = MONGO_MAKE_LATCH();
    stdx::condition_variable cv;

    // Add a job, ensure that it runs once
    PeriodicRunner::PeriodicJob job("job",
                                    [&count, &mutex, &cv](Client*) {
                                        {
                                            stdx::unique_lock<Latch> lk(mutex);
                                            count++;
                                        }
                                        cv.notify_all();
                                    },
                                    interval);

    auto jobAnchor = runner().makeJob(std::move(job));
    jobAnchor.start();

    // Fast forward ten times, we should run all ten times.
    for (int i = 0; i < 10; i++) {
        clockSource().advance(interval);
        {
            stdx::unique_lock<Latch> lk(mutex);
            cv.wait(lk, [&count, &i] { return count > i; });
        }
    }

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, OnePausableJobDoesNotRunWithoutStart) {
    int count = 0;
    Milliseconds interval{5};

    auto mutex = MONGO_MAKE_LATCH();
    stdx::condition_variable cv;

    // Add a job, ensure that it runs once
    PeriodicRunner::PeriodicJob job("job",
                                    [&count, &mutex, &cv](Client*) {
                                        {
                                            stdx::unique_lock<Latch> lk(mutex);
                                            count++;
                                        }
                                        cv.notify_all();
                                    },
                                    interval);

    auto jobAnchor = runner().makeJob(std::move(job));
    clockSource().advance(interval);
    ASSERT_EQ(count, 0);

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, OnePausableJobRunsCorrectlyWithStart) {
    int count = 0;
    Milliseconds interval{5};

    auto mutex = MONGO_MAKE_LATCH();
    stdx::condition_variable cv;

    // Add a job, ensure that it runs once
    PeriodicRunner::PeriodicJob job("job",
                                    [&count, &mutex, &cv](Client*) {
                                        {
                                            stdx::unique_lock<Latch> lk(mutex);
                                            count++;
                                        }
                                        cv.notify_all();
                                    },
                                    interval);

    auto jobAnchor = runner().makeJob(std::move(job));
    jobAnchor.start();
    // Fast forward ten times, we should run all ten times.
    for (int i = 0; i < 10; i++) {
        {
            stdx::unique_lock<Latch> lk(mutex);
            cv.wait(lk, [&] { return count == i + 1; });
        }
        clockSource().advance(interval);
    }

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, OnePausableJobPausesCorrectly) {
    bool hasExecuted = false;
    bool isPaused = false;
    Milliseconds interval{5};

    auto mutex = MONGO_MAKE_LATCH();
    stdx::condition_variable cv;

    // Add a job, ensure that it runs once
    PeriodicRunner::PeriodicJob job("job",
                                    [&](Client*) {
                                        {
                                            stdx::unique_lock<Latch> lk(mutex);
                                            // This will fail if pause does not work correctly.
                                            ASSERT_FALSE(isPaused);
                                            hasExecuted = true;
                                        }
                                        cv.notify_all();
                                    },
                                    interval);

    auto jobAnchor = runner().makeJob(std::move(job));
    jobAnchor.start();
    // Wait for the first execution.
    {
        stdx::unique_lock<Latch> lk(mutex);
        cv.wait(lk, [&] { return hasExecuted; });
    }

    {
        stdx::unique_lock<Latch> lk(mutex);
        isPaused = true;
        jobAnchor.pause();
    }

    // Fast forward ten times, we shouldn't run anymore. If we do, the assert inside the job will
    // fail. (Note that even if the pausing behavior were incorrect, this is racy since tearDown()
    // could happen before the job executes, leading the test to incorrectly succeed from time to
    // time.)
    for (int i = 0; i < 10; i++) {
        clockSource().advance(interval);
    }

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, OnePausableJobResumesCorrectly) {
    int count = 0;
    Milliseconds interval{5};

    auto mutex = MONGO_MAKE_LATCH();
    stdx::condition_variable cv;

    PeriodicRunner::PeriodicJob job("job",
                                    [&count, &mutex, &cv](Client*) {
                                        {
                                            stdx::unique_lock<Latch> lk(mutex);
                                            count++;
                                        }
                                        cv.notify_all();
                                    },
                                    interval);

    auto jobAnchor = runner().makeJob(std::move(job));
    jobAnchor.start();
    // Wait for the first execution.
    {
        stdx::unique_lock<Latch> lk(mutex);
        cv.wait(lk, [&] { return count == 1; });
    }

    // Reset the count before iterating to make other conditions in the test slightly simpler to
    // follow.
    count = 0;

    int numIterationsBeforePause = 10;
    // Fast forward ten times, we should run exactly 10 times.
    for (int i = 0; i < numIterationsBeforePause; i++) {
        clockSource().advance(interval);

        {
            stdx::unique_lock<Latch> lk(mutex);
            // Wait for count to increment due to job execution.
            cv.wait(lk, [&] { return count == i + 1; });
        }
    }

    jobAnchor.pause();

    // Fast forward ten times, we shouldn't run anymore.
    for (int i = 0; i < 10; i++) {
        clockSource().advance(interval);
    }

    // Make sure we didn't run anymore while paused.
    ASSERT_EQ(count, numIterationsBeforePause);

    jobAnchor.resume();
    // Fast forward, we should run at least once.
    clockSource().advance(interval);

    // Wait for count to increase. Test will hang if resume() does not work correctly.
    {
        stdx::unique_lock<Latch> lk(mutex);
        cv.wait(lk, [&] { return count > numIterationsBeforePause; });
    }

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, TwoJobsTest) {
    int countA = 0;
    int countB = 0;
    Milliseconds intervalA{5};
    Milliseconds intervalB{10};

    auto mutex = MONGO_MAKE_LATCH();
    stdx::condition_variable cv;

    // Add two jobs, ensure they both run the proper number of times
    PeriodicRunner::PeriodicJob jobA("job",
                                     [&countA, &mutex, &cv](Client*) {
                                         {
                                             stdx::unique_lock<Latch> lk(mutex);
                                             countA++;
                                         }
                                         cv.notify_all();
                                     },
                                     intervalA);

    PeriodicRunner::PeriodicJob jobB("job",
                                     [&countB, &mutex, &cv](Client*) {
                                         {
                                             stdx::unique_lock<Latch> lk(mutex);
                                             countB++;
                                         }
                                         cv.notify_all();
                                     },
                                     intervalB);

    auto jobAnchorA = runner().makeJob(std::move(jobA));
    auto jobAnchorB = runner().makeJob(std::move(jobB));

    jobAnchorA.start();
    jobAnchorB.start();

    // Fast forward and wait for both jobs to run the right number of times
    for (int i = 0; i <= 10; i++) {
        clockSource().advance(intervalA);
        {
            stdx::unique_lock<Latch> lk(mutex);
            cv.wait(lk, [&countA, &countB, &i] { return (countA > i && countB >= i / 2); });
        }
    }

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, TwoJobsDontDeadlock) {
    auto mutex = MONGO_MAKE_LATCH();
    stdx::condition_variable cv;
    stdx::condition_variable doneCv;
    bool a = false;
    bool b = false;

    PeriodicRunner::PeriodicJob jobA("job",
                                     [&](Client*) {
                                         stdx::unique_lock<Latch> lk(mutex);
                                         a = true;

                                         cv.notify_one();
                                         cv.wait(lk, [&] { return b; });
                                         doneCv.notify_one();
                                     },
                                     Milliseconds(1));

    PeriodicRunner::PeriodicJob jobB("job",
                                     [&](Client*) {
                                         stdx::unique_lock<Latch> lk(mutex);
                                         b = true;

                                         cv.notify_one();
                                         cv.wait(lk, [&] { return a; });
                                         doneCv.notify_one();
                                     },
                                     Milliseconds(1));

    auto jobAnchorA = runner().makeJob(std::move(jobA));
    auto jobAnchorB = runner().makeJob(std::move(jobB));

    jobAnchorA.start();
    jobAnchorB.start();

    clockSource().advance(Milliseconds(1));

    {
        stdx::unique_lock<Latch> lk(mutex);
        doneCv.wait(lk, [&] { return a && b; });

        ASSERT(a);
        ASSERT(b);
    }

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, ChangingIntervalWorks) {
    size_t timesCalled = 0;

    auto mutex = MONGO_MAKE_LATCH();
    stdx::condition_variable cv;

    // Add a job, ensure that it runs once
    PeriodicRunner::PeriodicJob job("job",
                                    [&](Client*) {
                                        {
                                            stdx::unique_lock<Latch> lk(mutex);
                                            timesCalled++;
                                        }
                                        cv.notify_one();
                                    },
                                    Milliseconds(5));

    auto jobAnchor = runner().makeJob(std::move(job));
    jobAnchor.start();
    // Wait for the first execution.
    {
        stdx::unique_lock<Latch> lk(mutex);
        cv.wait(lk, [&] { return timesCalled; });
    }

    jobAnchor.setPeriod(Milliseconds(10));
    ASSERT_EQ(jobAnchor.getPeriod(), Milliseconds(10));

    // if we change the period to a longer duration, that doesn't trigger a run
    {
        stdx::lock_guard<Latch> lk(mutex);
        ASSERT_EQ(timesCalled, 1ul);
    }

    clockSource().advance(Milliseconds(5));

    // We actually changed the period
    {
        stdx::lock_guard<Latch> lk(mutex);
        ASSERT_EQ(timesCalled, 1ul);
    }

    clockSource().advance(Milliseconds(5));

    // Now we hit the new cutoff
    {
        stdx::unique_lock<Latch> lk(mutex);
        cv.wait(lk, [&] { return timesCalled == 2ul; });
    }

    clockSource().advance(Milliseconds(5));

    // Haven't hit it
    {
        stdx::lock_guard<Latch> lk(mutex);
        ASSERT_EQ(timesCalled, 2ul);
    }

    jobAnchor.setPeriod(Milliseconds(4));
    ASSERT_EQ(jobAnchor.getPeriod(), Milliseconds(4));

    // shortening triggers the period
    {
        stdx::unique_lock<Latch> lk(mutex);
        cv.wait(lk, [&] { return timesCalled == 3ul; });
    }

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, StopProperlyInterruptsOpCtx) {
    Milliseconds interval{5};
    unittest::Barrier barrier(2);
    AtomicWord<bool> killed{false};

    PeriodicRunner::PeriodicJob job(
        "job",
        [&barrier, &killed](Client* client) {
            stdx::condition_variable cv;
            auto mutex = MONGO_MAKE_LATCH();
            barrier.countDownAndWait();

            try {
                auto opCtx = client->makeOperationContext();
                stdx::unique_lock<Latch> lk(mutex);
                opCtx->waitForConditionOrInterrupt(cv, lk, [] { return false; });
            } catch (const ExceptionForCat<ErrorCategory::Interruption>& e) {
                ASSERT_EQ(e.code(), ErrorCodes::ClientMarkedKilled);
                killed.store(true);
                return;
            }

            MONGO_UNREACHABLE;
        },
        interval);

    auto jobAnchor = runner().makeJob(std::move(job));
    jobAnchor.start();

    barrier.countDownAndWait();

    jobAnchor.stop();
    ASSERT(killed.load());

    tearDown();
}

TEST_F(PeriodicRunnerImplTest, ThrowsErrorOnceStopped) {
    auto jobAnchor = makeStoppedJob();
    ASSERT_THROWS_CODE_AND_WHAT(jobAnchor.start(),
                                AssertionException,
                                ErrorCodes::PeriodicJobIsStopped,
                                "Attempted to start an already stopped job");
    ASSERT_THROWS_CODE_AND_WHAT(jobAnchor.pause(),
                                AssertionException,
                                ErrorCodes::PeriodicJobIsStopped,
                                "Attempted to pause an already stopped job");
    ASSERT_THROWS_CODE_AND_WHAT(jobAnchor.resume(),
                                AssertionException,
                                ErrorCodes::PeriodicJobIsStopped,
                                "Attempted to resume an already stopped job");
    jobAnchor.stop();
}

}  // namespace
}  // namespace mongo

max_stars_repo_name: benety/mongo

max_issues_repo_name: benety/mongo

max_forks_repo_name: benety/mongo


text:
#include <bacs/archive/web/content/form/widgets/archiver_config.hpp>

#include <boost/algorithm/string/trim.hpp>

namespace bacs::archive::web::content::form::widgets {

archiver_config::archiver_config() {
  type.name("archiver_type");
  format.name("archiver_format");
  type.message(cppcms::locale::translate("Archiver type"));
  format.message(cppcms::locale::translate("Archiver format"));
  add(type);
  add(format);
}

archiver_options archiver_config::value() {
  archiver_options config;
  config.type = type.value();
  boost::algorithm::trim(config.type);
  std::string format_ = format.value();
  boost::algorithm::trim(format_);
  if (!format_.empty()) config.config.put("format", format_);
  return config;
}

}  // namespace bacs::archive::web::content::form::widgets

max_stars_repo_name: bacsorg/bacs

max_issues_repo_name: bacsorg/bacs

max_forks_repo_name: bacsorg/bacs


text:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <sys/malloc.h>
#include <vector>
#include <boost/thread/thread.hpp>

using namespace std;
using boost::asio::ip::udp;
boost::asio::io_service service;
boost::thread_group threads;

class Server {
public:
    char* buf = (char*) calloc(BUF_SIZE,sizeof(char));  // 改为calloc
    vector <string> msgpools;
public:
    Server(boost::asio::io_service& service) :
        sock(service, udp::endpoint(udp::v4(), 9998)) {
        start();
    }

private:
    void start() {
        memset(buf, 0, BUF_SIZE);
        sock.async_receive_from(boost::asio::buffer(buf,BUF_SIZE), remoteEndpoint,
                boost::bind(&Server::handleReceive, this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));
    }
    void handleReceive(const boost::system::error_code& error,
            std::size_t bytes_transferred) {
        if (!error || error == boost::asio::error::message_size) {
            cout << remoteEndpoint << endl;
            //在服务器端接受到数据之后，在这里将数据写到指定的内存空间去
            msgpools.push_back(buf);
            sock.async_send_to(boost::asio::buffer(buf, bytes_transferred),
                    remoteEndpoint, boost::bind(&Server::handleSend, this,
                            boost::asio::placeholders::error));
            //start();
        }
    }
    void handleSend(const boost::system::error_code& /*error*/) {
        //cout << buf <<endl;
        cout << msgpools.front() <<endl;
        std::cout << "ThreadId : " << boost::this_thread::get_id() <<endl;
        cout << count++ <<endl;
        start();
    }
private:
    udp::socket sock;
    udp::endpoint remoteEndpoint;

    enum {
        BUF_SIZE = 512
    };
    //char buf[BUF_SIZE];
    //使用malloc来给buf分配地址空间
    int count = 0;

};

void listen_thread(){
    service.run();
}

void start_listen(int thread_count){
    for(int i = 0 ; i< thread_count ; i++ ){
        threads.create_thread(listen_thread);
    }
}

int main() {
    try {
        //boost::asio::io_service service;
        Server server(service);

        start_listen(8);
        threads.join_all();

        //service.run(); // 注意：一定要调用 run()函数
    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}


text:
/*
 * Copyright (c) 2014 CodiLime, Inc. All rights reserved.
 */

#include "bfd/bfd_common.h"

#include <string>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/optional.hpp>
#include <boost/assign/list_of.hpp>

namespace BFD {
typedef boost::bimap<BFDState, std::string> BFDStateNames;

static BFDStateNames kBFDStateNames =
        boost::assign::list_of<BFDStateNames::relation>
        (kAdminDown, "AdminDown")
        (kDown,      "Down")
        (kInit,      "Init")
        (kUp,        "Up");

std::ostream &operator<<(std::ostream &out, BFDState state) {
    try {
        out << kBFDStateNames.left.at(state);
    } catch (std::out_of_range &) {
        out << "Unknown";
    }

    return out;
}

boost::optional<BFDState> BFDStateFromString(const char *str) {
    try {
        return boost::optional<BFDState>(kBFDStateNames.right.at(str));
    } catch (std::out_of_range &) {}

    return boost::optional<BFDState>();
}

const int kMinimalPacketLength = 24;
const TimeInterval kIdleTxInterval = boost::posix_time::seconds(1);
boost::random::taus88 randomGen;
}  // namespace BFD

ext: cc

max_stars_repo_name: jnpr-pranav/contrail-controller

max_issues_repo_name: jnpr-pranav/contrail-controller

max_forks_repo_name: jnpr-pranav/contrail-controller


text:
/*
Copyright (c) 2014, Randolph Voorhies, Shane Grant
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 cereal 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 RANDOLPH VOORHIES AND SHANE GRANT 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 "common.hpp"
#include <boost/test/unit_test.hpp>

template <class IArchive, class OArchive>
void test_valarray()
{
  std::random_device rd;
  std::mt19937 gen(rd());

  for (int ii = 0; ii<100; ++ii)
  {
    std::valarray<int> o_podvalarray(100);
    for (auto & elem : o_podvalarray)
      elem = random_value<int>(gen);

    std::valarray<StructInternalSerialize> o_iservalarray(100);
    for (auto & elem : o_iservalarray)
      elem = StructInternalSerialize(random_value<int>(gen), random_value<int>(gen));

    std::valarray<StructInternalSplit> o_isplvalarray(100);
    for (auto & elem : o_isplvalarray)
      elem = StructInternalSplit(random_value<int>(gen), random_value<int>(gen));

    std::valarray<StructExternalSerialize> o_eservalarray(100);
    for (auto & elem : o_eservalarray)
      elem = StructExternalSerialize(random_value<int>(gen), random_value<int>(gen));

    std::valarray<StructExternalSplit> o_esplvalarray(100);
    for (auto & elem : o_esplvalarray)
      elem = StructExternalSplit(random_value<int>(gen), random_value<int>(gen));

    std::ostringstream os;
    {
      OArchive oar(os);

      oar(o_podvalarray);
      oar(o_iservalarray);
      oar(o_isplvalarray);
      oar(o_eservalarray);
      oar(o_esplvalarray);
    }

    std::valarray<int> i_podvalarray;
    std::valarray<StructInternalSerialize> i_iservalarray;
    std::valarray<StructInternalSplit>     i_isplvalarray;
    std::valarray<StructExternalSerialize> i_eservalarray;
    std::valarray<StructExternalSplit>     i_esplvalarray;

    std::istringstream is(os.str());
    {
      IArchive iar(is);

      iar(i_podvalarray);
      iar(i_iservalarray);
      iar(i_isplvalarray);
      iar(i_eservalarray);
      iar(i_esplvalarray);
    }

    BOOST_CHECK_EQUAL(i_podvalarray.size(), o_podvalarray.size());
    BOOST_CHECK_EQUAL(i_iservalarray.size(), o_iservalarray.size());
    BOOST_CHECK_EQUAL(i_isplvalarray.size(), o_isplvalarray.size());
    BOOST_CHECK_EQUAL(i_eservalarray.size(), o_eservalarray.size());
    BOOST_CHECK_EQUAL(i_esplvalarray.size(), o_esplvalarray.size());

    BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_podvalarray), std::end(i_podvalarray), std::begin(o_podvalarray), std::end(o_podvalarray));
    BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_iservalarray), std::end(i_iservalarray), std::begin(o_iservalarray), std::end(o_iservalarray));
    BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_isplvalarray), std::end(i_isplvalarray), std::begin(o_isplvalarray), std::end(o_isplvalarray));
    BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_eservalarray), std::end(i_eservalarray), std::begin(o_eservalarray), std::end(o_eservalarray));
    BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_esplvalarray), std::end(i_esplvalarray), std::begin(o_esplvalarray), std::end(o_esplvalarray));
  }
}

BOOST_AUTO_TEST_CASE(binary_valarray)
{
  test_valarray<cereal::BinaryInputArchive, cereal::BinaryOutputArchive>();
}

BOOST_AUTO_TEST_CASE(portable_binary_valarray)
{
  test_valarray<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive>();
}

BOOST_AUTO_TEST_CASE(xml_valarray)
{
  test_valarray<cereal::XMLInputArchive, cereal::XMLOutputArchive>();
}

BOOST_AUTO_TEST_CASE(json_valarray)
{
  test_valarray<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
}

BOOST_AUTO_TEST_CASE( extendable_binary_valarray )
{
  test_valarray<cereal::ExtendableBinaryInputArchive, cereal::ExtendableBinaryOutputArchive>();
}


text:
/*
 * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2.0, as
 * published by the Free Software Foundation.
 *
 * This program is also distributed with certain software (including
 * but not limited to OpenSSL) that is licensed under separate terms,
 * as designated in a particular file or component or in included license
 * documentation.  The authors of MySQL hereby grant you an
 * additional permission to link the program and your derivative works
 * with the separately licensed software that they have included with
 * MySQL.
 *
 * Without limiting anything contained in the foregoing, this file,
 * which is part of MySQL Connector/C++, is also subject to the
 * Universal FOSS Exception, version 1.0, a copy of which can be found at
 * http://oss.oracle.com/licenses/universal-foss-exception.
 *
 * This program 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 General Public License, version 2.0, for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
 */

/**
* Basic example of creating a stand alone program linked against Connector/C++
*
* This example is not integrated into the Connector/C++ build environment.
* You must run "make install" prior to following the build instructions
* given here.
*
* To compile the standalone example on Linux try something like:
*
* /usr/bin/c++
*   -o standalone
*   -I/usr/local/include/cppconn/
*   -Wl,-Bdynamic -lmysqlcppconn
*    examples/standalone_example.cpp
*
* To run the example on Linux try something similar to:
*
*  LD_LIBRARY_PATH=/usr/local/lib/ ./standalone
*
* or:
*
*  LD_LIBRARY_PATH=/usr/local/lib/ ./standalone host user password database
*
*/

/* Standard C++ includes */
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <stdexcept>

#include <boost/scoped_ptr.hpp>

/*
  Include directly the different
  headers from cppconn/ and mysql_driver.h + mysql_util.h
  (and mysql_connection.h). This will reduce your build time!
*/
#include "mysql_connection.h"
#include "mysql_driver.h"

#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>

#define EXAMPLE_HOST "localhost"
#define EXAMPLE_USER "root"
#define EXAMPLE_PASS ""
#define EXAMPLE_DB "test"

using namespace std;

/**
* Usage example for Driver, Connection, (simple) Statement, ResultSet
*/
int main(int argc, const char **argv)
{
  string url(argc >= 2 ? argv[1] : EXAMPLE_HOST);
  const string user(argc >= 3 ? argv[2] : EXAMPLE_USER);
  const string pass(argc >= 4 ? argv[3] : EXAMPLE_PASS);
  const string database(argc >= 5 ? argv[4] : EXAMPLE_DB);

  cout << endl;
  cout << "Connector/C++ standalone program example..." << endl;
  cout << endl;

  try {
    sql::Driver * driver = sql::mysql::get_driver_instance();
    /* Using the Driver to create a connection */
    boost::scoped_ptr< sql::Connection > con(driver->connect(url, user, pass));
    con->setSchema(database);

    boost::scoped_ptr< sql::Statement > stmt(con->createStatement());
    boost::scoped_ptr< sql::ResultSet > res(stmt->executeQuery("SELECT 'Welcome to Connector/C++' AS _message"));
    cout << "\t... running 'SELECT 'Welcome to Connector/C++' AS _message'" << endl;
    while (res->next()) {
      cout << "\t... MySQL replies: " << res->getString("_message") << endl;
      cout << "\t... say it again, MySQL" << endl;
      cout << "\t....MySQL replies: " << res->getString(1) << endl;
    }

  } catch (sql::SQLException &e) {
    /*
    The MySQL Connector/C++ throws three different exceptions:

    - sql::MethodNotImplementedException (derived from sql::SQLException)
    - sql::InvalidArgumentException (derived from sql::SQLException)
    - sql::SQLException (derived from std::runtime_error)
    */
    cout << "# ERR: SQLException in " << __FILE__;
    cout << "(" << EXAMPLE_FUNCTION << ") on line " << __LINE__ << endl;
    /* Use what() (derived from std::runtime_error) to fetch the error message */
    cout << "# ERR: " << e.what();
    cout << " (MySQL error code: " << e.getErrorCode();
    cout << ", SQLState: " << e.getSQLState() << " )" << endl;

    return EXIT_FAILURE;
  }

  cout << endl;
  cout << "... find more at http://www.mysql.com" << endl;
  cout << endl;
  return EXIT_SUCCESS;
}


text:
#include "gamesettings.hpp"

#include <QTextStream>
#include <QDir>
#include <QString>
#include <QRegExp>
#include <QMap>

#include <components/files/configurationmanager.hpp>

#include <boost/version.hpp>

/**
 * Workaround for problems with whitespaces in paths in older versions of Boost library
 */
#if (BOOST_VERSION <= 104600)
namespace boost
{

    template<>
    inline boost::filesystem::path lexical_cast<boost::filesystem::path, std::string>(const std::string& arg)
    {
        return boost::filesystem::path(arg);
    }

} /* namespace boost */
#endif /* (BOOST_VERSION <= 104600) */

Launcher::GameSettings::GameSettings(Files::ConfigurationManager &cfg)
    : mCfgMgr(cfg)
{
}

Launcher::GameSettings::~GameSettings()
{
}

void Launcher::GameSettings::validatePaths()
{
    if (mSettings.isEmpty() || !mDataDirs.isEmpty())
        return; // Don't re-validate paths if they are already parsed

    QStringList paths = mSettings.values(QString("data"));
    Files::PathContainer dataDirs;

    foreach (const QString &path, paths) {
        QByteArray bytes = path.toUtf8();
        dataDirs.push_back(Files::PathContainer::value_type(std::string(bytes.constData(), bytes.length())));
    }

    // Parse the data dirs to convert the tokenized paths
    mCfgMgr.processPaths(dataDirs);
    mDataDirs.clear();

    for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) {
        QString path = QString::fromUtf8(it->string().c_str());
        path.remove(QChar('\"'));

        QDir dir(path);
        if (dir.exists())
            mDataDirs.append(path);
    }

    // Do the same for data-local
    QString local = mSettings.value(QString("data-local"));

    if (local.isEmpty())
        return;

    dataDirs.clear();
    QByteArray bytes = local.toUtf8();
    dataDirs.push_back(Files::PathContainer::value_type(std::string(bytes.constData(), bytes.length())));

    mCfgMgr.processPaths(dataDirs);

    if (!dataDirs.empty()) {
        QString path = QString::fromUtf8(dataDirs.front().string().c_str());
        path.remove(QChar('\"'));

        QDir dir(path);
        if (dir.exists())
            mDataLocal = path;
    }
}

QStringList Launcher::GameSettings::values(const QString &key, const QStringList &defaultValues)
{
    if (!mSettings.values(key).isEmpty())
        return mSettings.values(key);
    return defaultValues;
}

bool Launcher::GameSettings::readFile(QTextStream &stream)
{
    return readFile(stream, mSettings);
}

bool Launcher::GameSettings::readUserFile(QTextStream &stream)
{
    return readFile(stream, mUserSettings);
}

bool Launcher::GameSettings::readFile(QTextStream &stream, QMap<QString, QString> &settings)
{
    QMap<QString, QString> cache;
    QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");

    while (!stream.atEnd()) {
        QString line = stream.readLine();

        if (line.isEmpty() || line.startsWith("#"))
            continue;

        if (keyRe.indexIn(line) != -1) {

            QString key = keyRe.cap(1).trimmed();
            QString value = keyRe.cap(2).trimmed();

            // Don't remove existing data entries
            if (key != QLatin1String("data"))
                settings.remove(key);

            QStringList values = cache.values(key);
            values.append(settings.values(key));

            if (!values.contains(value)) {
                cache.insertMulti(key, value);
            }
        }
    }

    if (settings.isEmpty()) {
        settings = cache; // This is the first time we read a file
        validatePaths();
        return true;
    }

    // Merge the changed keys with those which didn't
    settings.unite(cache);
    validatePaths();

    return true;
}

bool Launcher::GameSettings::writeFile(QTextStream &stream)
{
    // Iterate in reverse order to preserve insertion order
    QMapIterator<QString, QString> i(mUserSettings);
    i.toBack();

    while (i.hasPrevious()) {
        i.previous();

        if (i.key() == QLatin1String("content"))
            continue;

        // Quote paths with spaces
        if (i.key() == QLatin1String("data")
            || i.key() == QLatin1String("data-local")
            || i.key() == QLatin1String("resources"))
        {
            if (i.value().contains(QChar(' ')))
            {
                QString stripped = i.value();
                stripped.remove(QChar('\"')); // Remove quotes

                stream << i.key() << "=\"" << stripped << "\"\n";
                continue;
            }
        }

        stream << i.key() << "=" << i.value() << "\n";

    }

    QStringList content = mUserSettings.values(QString("content"));
    for (int i = content.count(); i--;) {
        stream << "content=" << content.at(i) << "\n";
    }

    return true;
}

bool Launcher::GameSettings::hasMaster()
{
    bool result = false;
    QStringList content = mSettings.values(QString("content"));
    for (int i = 0; i < content.count(); ++i) {
        if (content.at(i).contains(".omwgame") || content.at(i).contains(".esm")) {
            result = true;
            break;
        }
    }

    return result;
}

max_stars_repo_name: Bodillium/openmw

max_issues_repo_name: Bodillium/openmw

max_forks_repo_name: Bodillium/openmw