diff --git a/alib2cli/src/ast/Param.h b/alib2cli/src/ast/Param.h index 4e2ef4a4630e3f12aeae4c83bd1b0fcc156cb921..50c16c24c3bf99befa52458145311fd1c6ca55ac 100644 --- a/alib2cli/src/ast/Param.h +++ b/alib2cli/src/ast/Param.h @@ -8,11 +8,20 @@ namespace cli { class Param { + bool m_move; + public: + Param ( bool move ) : m_move ( move ) { + } + virtual ~Param ( ) noexcept { } virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const = 0; + + bool getMove ( ) const { + return m_move; + } }; } /* namespace cli */ diff --git a/alib2cli/src/ast/common/CastHelper.h b/alib2cli/src/ast/common/CastHelper.h index 2b0142c88cbe35360b90eb71965d2eff5da17127..22a6d3d26452fe57b7b11c999018f447d69bbf71 100644 --- a/alib2cli/src/ast/common/CastHelper.h +++ b/alib2cli/src/ast/common/CastHelper.h @@ -7,7 +7,7 @@ namespace cli { class CastHelper { public: - static std::shared_ptr < abstraction::OperationAbstraction > castHelper ( const std::shared_ptr < abstraction::OperationAbstraction > & param, const std::string & type ) { + static std::shared_ptr < abstraction::OperationAbstraction > castHelper ( const std::shared_ptr < abstraction::OperationAbstraction > & param, const std::string & type, bool move ) { if ( abstraction::Registry::isCastNoOp ( type, param->getReturnType ( ) ) ) { return param; } @@ -15,14 +15,14 @@ public: bool normalize; std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getCastAbstraction ( type, param->getReturnType ( ), normalize ); - if ( ! res->attachInput ( param, 0 ) ) + if ( ! res->attachInput ( param, 0, move ) ) throw exception::CommonException ( "Can't connect param at 0 of cast to " + type + " with result of type " + param->getReturnType ( ) + "." ); if ( ! res->eval ( ) ) throw exception::CommonException ( "Eval of cast to " + type + " failed." ); if ( normalize ) { std::shared_ptr < abstraction::OperationAbstraction > normalized = abstraction::Registry::getNormalizeAbstraction ( res->getReturnType ( ) ); - if ( ! normalized->attachInput ( res, 0 ) ) + if ( ! normalized->attachInput ( res, 0, true ) ) throw exception::CommonException ( "Can't connect param at 0 of normalize of cast to " + type + " with result of type " + res->getReturnType ( ) + "." ); if ( ! normalized->eval ( ) ) throw exception::CommonException ( "Eval of normalize of cast to " + type + " failed." ); diff --git a/alib2cli/src/ast/params/CastParam.h b/alib2cli/src/ast/params/CastParam.h index b0aaf05ee3175b260de6ae5e260efa6972efe7fc..ceec38b00ada90fdf716692070b8475f99989b5f 100644 --- a/alib2cli/src/ast/params/CastParam.h +++ b/alib2cli/src/ast/params/CastParam.h @@ -11,7 +11,7 @@ class CastParam final : public Param { std::unique_ptr < Param > m_param; public: - CastParam ( std::unique_ptr < cli::Arg > type, std::unique_ptr < Param > param ) : m_type ( std::move ( type ) ), m_param ( std::move ( param ) ) { + CastParam ( std::unique_ptr < cli::Arg > type, std::unique_ptr < Param > param ) : Param ( true ), m_type ( std::move ( type ) ), m_param ( std::move ( param ) ) { } virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override { @@ -19,9 +19,8 @@ public: std::shared_ptr < abstraction::OperationAbstraction > translatedParam = m_param->translateAndEval ( prev, environment ); - return CastHelper::castHelper ( translatedParam, type ); + return CastHelper::castHelper ( translatedParam, type, getMove ( ) ); } - }; } /* namespace cli */ diff --git a/alib2cli/src/ast/params/FileParam.h b/alib2cli/src/ast/params/FileParam.h index 61a6535904f70d35f2051c4de23747bc2ba7e6c9..4c50a5e387941533682d30197669866e130c0a30 100644 --- a/alib2cli/src/ast/params/FileParam.h +++ b/alib2cli/src/ast/params/FileParam.h @@ -10,7 +10,7 @@ class FileParam final : public Param { std::unique_ptr < cli::Arg > m_arg; public: - FileParam ( std::unique_ptr < cli::Arg > arg ) : m_arg ( std::move ( arg ) ) { + FileParam ( std::unique_ptr < cli::Arg > arg ) : Param ( true ), m_arg ( std::move ( arg ) ) { } virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > &, Environment & environment ) const override { diff --git a/alib2cli/src/ast/params/ImmediateParam.h b/alib2cli/src/ast/params/ImmediateParam.h index d2f130cc34a7d8fba36b0837447acfc137c92cbe..b7c4325960ac80b4a93c6b509a567ea23a76874a 100644 --- a/alib2cli/src/ast/params/ImmediateParam.h +++ b/alib2cli/src/ast/params/ImmediateParam.h @@ -11,13 +11,12 @@ class ImmediateParam final : public Param { Type m_data; public: - ImmediateParam ( Type value ) : m_data ( value ) { + ImmediateParam ( Type value ) : Param ( true ), m_data ( std::move ( value ) ) { } virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > &, Environment & ) const override { return std::make_shared < abstraction::ImmediateValueAbstraction < Type > > ( m_data ); } - }; } /* namespace cli */ diff --git a/alib2cli/src/ast/params/PreviousResultParam.h b/alib2cli/src/ast/params/PreviousResultParam.h index 4f8286a30962883c73afe6e9d02098624c4cef5d..c26480b8efebb8a241bd971805180dc0ea28bb57 100644 --- a/alib2cli/src/ast/params/PreviousResultParam.h +++ b/alib2cli/src/ast/params/PreviousResultParam.h @@ -6,7 +6,11 @@ namespace cli { class PreviousResultParam final : public Param { + public: + PreviousResultParam ( bool move ) : Param ( move ) { + } + virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & ) const override { return prev; } diff --git a/alib2cli/src/ast/params/StatementParam.h b/alib2cli/src/ast/params/StatementParam.h index 91b5e3d9f5c20c898a1b2f6788f3cb082c361d12..4f465742699277685e22eada8c4d1cf5336589d7 100644 --- a/alib2cli/src/ast/params/StatementParam.h +++ b/alib2cli/src/ast/params/StatementParam.h @@ -9,7 +9,7 @@ class StatementParam final : public Param { std::shared_ptr < Statement > m_statement; public: - StatementParam ( std::shared_ptr < Statement > statement ) : m_statement ( statement ) { + StatementParam ( std::shared_ptr < Statement > statement, bool move ) : Param ( move ), m_statement ( statement ) { } virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > &, Environment & environment ) const override { diff --git a/alib2cli/src/ast/params/ValueParam.h b/alib2cli/src/ast/params/ValueParam.h index 9a9aaad4d638c62d549480aa2ec3d47f086c4d31..efcd9c5cc60bc912cfdd343fd16957c808b2613b 100644 --- a/alib2cli/src/ast/params/ValueParam.h +++ b/alib2cli/src/ast/params/ValueParam.h @@ -10,7 +10,7 @@ class ValueParam final : public Param { std::unique_ptr < cli::Arg > m_arg; public: - ValueParam ( std::unique_ptr < cli::Arg > arg ) : m_arg ( std::move ( arg ) ) { + ValueParam ( std::unique_ptr < cli::Arg > arg ) : Param ( true ), m_arg ( std::move ( arg ) ) { } virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > &, Environment & environment ) const override { diff --git a/alib2cli/src/ast/params/VariableParam.h b/alib2cli/src/ast/params/VariableParam.h index 8d10f949902cb969a755fa62f07d53c5020fd1e1..64fae34da9ba7f304034fec07193081a708408e8 100644 --- a/alib2cli/src/ast/params/VariableParam.h +++ b/alib2cli/src/ast/params/VariableParam.h @@ -10,7 +10,7 @@ class VariableParam final : public Param { std::unique_ptr < cli::Arg > m_name; public: - VariableParam ( std::unique_ptr < cli::Arg > name ) : m_name ( std::move ( name ) ) { + VariableParam ( std::unique_ptr < cli::Arg > name, bool move ) : Param ( move ), m_name ( std::move ( name ) ) { } virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > &, Environment & environment ) const override { diff --git a/alib2cli/src/ast/statements/CastStatement.h b/alib2cli/src/ast/statements/CastStatement.h index ce9034ca10f845fd9aac6bd6193588522b108bf6..ba0fc9bfdd1cda95564413ac52116621fb1428ce 100644 --- a/alib2cli/src/ast/statements/CastStatement.h +++ b/alib2cli/src/ast/statements/CastStatement.h @@ -9,9 +9,10 @@ namespace cli { class CastStatement final : public Statement { std::unique_ptr < cli::Arg > m_type; std::shared_ptr < Statement > m_statement; + bool m_move; public: - CastStatement ( std::unique_ptr < cli::Arg > type, std::shared_ptr < Statement > statement ) : m_type ( std::move ( type ) ), m_statement ( statement ) { + CastStatement ( std::unique_ptr < cli::Arg > type, std::shared_ptr < Statement > statement, bool move ) : m_type ( std::move ( type ) ), m_statement ( statement ), m_move ( move ) { } virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override { @@ -19,7 +20,7 @@ public: std::shared_ptr < abstraction::OperationAbstraction > translatedStatement = m_statement->translateAndEval ( prev, environment ); - return CastHelper::castHelper ( translatedStatement, type ); + return CastHelper::castHelper ( translatedStatement, type, m_move ); } }; diff --git a/alib2cli/src/ast/statements/ResultFileStatement.h b/alib2cli/src/ast/statements/ResultFileStatement.h index de1c053365e0ca6b94b4d5f8a383c87a0e224691..f327bff8c72c9d8dd7d94995065f694f250831fb 100644 --- a/alib2cli/src/ast/statements/ResultFileStatement.h +++ b/alib2cli/src/ast/statements/ResultFileStatement.h @@ -14,7 +14,7 @@ public: virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override { std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getXmlFileWriterAbstraction ( prev->getReturnType ( ), m_file->eval ( environment ) ); - if ( ! res->attachInput ( prev, 0 ) ) + if ( ! res->attachInput ( prev, 0, false ) ) throw exception::CommonException ( "Can't connect param at 0 of result file statement with result of type " + prev->getReturnType ( ) + "." ); if ( ! res->eval ( ) ) throw exception::CommonException ( "Eval of result file statement failed." ); diff --git a/alib2cli/src/ast/statements/ResultPrintStatement.h b/alib2cli/src/ast/statements/ResultPrintStatement.h index dc859d4c645bc1b96f84a802aad7af9bf3180ff9..187ce67bf5bced86c982f18920706637e7175e4c 100644 --- a/alib2cli/src/ast/statements/ResultPrintStatement.h +++ b/alib2cli/src/ast/statements/ResultPrintStatement.h @@ -12,7 +12,7 @@ public: virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & ) const override { std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getValuePrinterAbstraction ( prev->getReturnType ( ) ); - if ( ! res->attachInput ( prev, 0 ) ) + if ( ! res->attachInput ( prev, 0, false ) ) throw exception::CommonException ( "Can't connect param at 0 of result print statement with result of type " + prev->getReturnType ( ) + "." ); if ( ! res->eval ( ) ) throw exception::CommonException ( "Eval of result print statement failed." ); diff --git a/alib2cli/src/ast/statements/SingleStatement.cpp b/alib2cli/src/ast/statements/SingleStatement.cpp index f5cc92592404b26cca576576e32513e8745ba9ef..b3ac9752d5a90dffa451526effbe8acb98166e0f 100644 --- a/alib2cli/src/ast/statements/SingleStatement.cpp +++ b/alib2cli/src/ast/statements/SingleStatement.cpp @@ -18,6 +18,11 @@ std::shared_ptr < abstraction::OperationAbstraction > SingleStatement::translate params.push_back ( param->translateAndEval ( prev, environment ) ); } + std::vector < bool > moves; + for ( const std::unique_ptr < Param > & param : m_params ) { + moves.push_back ( param->getMove ( ) ); + } + ext::vector < std::string > paramTypes; for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : params ) { paramTypes.push_back ( param->getReturnType ( ) ); @@ -36,14 +41,15 @@ std::shared_ptr < abstraction::OperationAbstraction > SingleStatement::translate if ( abstraction::Registry::isCastNoOp ( algo->getParamType ( i ), param->getReturnType ( ) ) ) { casted_params.push_back ( param ); } else { - casted_params.push_back ( CastHelper::castHelper ( param, algo->getParamType ( i ) ) ); + casted_params.push_back ( CastHelper::castHelper ( param, algo->getParamType ( i ), moves [ i ] ) ); + moves [ i ] = true; } ++ i; } i = 0; for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : casted_params ) { - if ( ! algo->attachInput ( param, i ) ) + if ( ! algo->attachInput ( param, i, moves [ i ] ) ) throw exception::CommonException ( "Can't connect param at " + ext::to_string ( i ) + " of algorithm " + name + " with result of type " + param->getReturnType ( ) + "." ); ++ i; } @@ -53,7 +59,7 @@ std::shared_ptr < abstraction::OperationAbstraction > SingleStatement::translate if ( downcast ) { std::shared_ptr < abstraction::OperationAbstraction > downcaster = abstraction::Registry::getDowncastAbstraction ( algo->getRuntimeReturnType ( ), algo->getReturnType ( ) ); - if ( ! downcaster->attachInput ( algo, 0 ) ) + if ( ! downcaster->attachInput ( algo, 0, true ) ) throw exception::CommonException ( "Can't connect param at 0 of downcast of algorithm " + name + " with result of type " + algo->getReturnType ( ) + "." ); if ( ! downcaster->eval ( ) ) throw exception::CommonException ( "Eval of downcast of algorithm " + name + " failed." ); @@ -63,7 +69,7 @@ std::shared_ptr < abstraction::OperationAbstraction > SingleStatement::translate if ( normalize ) { std::shared_ptr < abstraction::OperationAbstraction > normalized = abstraction::Registry::getNormalizeAbstraction ( algo->getReturnType ( ) ); - if ( ! normalized->attachInput ( algo, 0 ) ) + if ( ! normalized->attachInput ( algo, 0, true ) ) throw exception::CommonException ( "Can't connect param at 0 of normalize of algorithm " + name + " with result of type " + algo->getReturnType ( ) + "." ); if ( ! normalized->eval ( ) ) throw exception::CommonException ( "Eval of normalize of algorithm " + name + " failed." ); diff --git a/alib2cli/src/lexer/Lexer.cpp b/alib2cli/src/lexer/Lexer.cpp index d70f22cc9de707b44aa1ec98bdc315bac7772e53..294f51e4db7b796c42f84c30645a86117d9395d0 100644 --- a/alib2cli/src/lexer/Lexer.cpp +++ b/alib2cli/src/lexer/Lexer.cpp @@ -50,6 +50,11 @@ q0: if ( m_index >= m_line.size ( ) ) { res.m_type = TokenType::PIPE_SIGN; return res; } + if ( m_line [ m_index ] == '^' ) { + m_index ++; + res.m_type = TokenType::CARET_SIGN; + return res; + } if ( m_line [ m_index ] == ':' ) { m_index ++; res.m_type = TokenType::COLON_SIGN; diff --git a/alib2cli/src/lexer/Lexer.h b/alib2cli/src/lexer/Lexer.h index 7eb4d8a426785331d79dafa4dddc4ed873f03a1b..c946a5f716c6c50cff0226b79d1e3b364f2a2d72 100644 --- a/alib2cli/src/lexer/Lexer.h +++ b/alib2cli/src/lexer/Lexer.h @@ -21,6 +21,7 @@ public: DOLAR_SIGN, AMPERSAND_SIGN, PIPE_SIGN, + CARET_SIGN, COLON_SIGN, DASH_SIGN, EQUAL_SIGN, @@ -57,6 +58,8 @@ public: return out << "ampersand_sign"; case TokenType::PIPE_SIGN : return out << "pipe_sign"; + case TokenType::CARET_SIGN : + return out << "caret_sign"; case TokenType::COLON_SIGN : return out << "colon_sign"; case TokenType::DASH_SIGN : diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp index 6fad60f800df45808edd58caffe1ece491b5ca7f..3001d2a506243bbca435fb7ca0211c5bd0659402 100644 --- a/alib2cli/src/parser/Parser.cpp +++ b/alib2cli/src/parser/Parser.cpp @@ -72,10 +72,19 @@ std::unique_ptr < Arg > Parser::optional_arg ( ) { } } +bool Parser::move_arg ( ) { + if ( check ( cli::Lexer::TokenType::CARET_SIGN ) ) { + match ( cli::Lexer::TokenType::CARET_SIGN ); + return true; + } else { + return false; + } +} + std::unique_ptr < Param > Parser::in_redirect_param ( ) { if ( check ( cli::Lexer::TokenType::LEFT_PAREN ) ) { match ( cli::Lexer::TokenType::LEFT_PAREN ); - auto sub_statement = std::make_unique < StatementParam > ( statement_list ( ) ); + auto sub_statement = std::make_unique < StatementParam > ( statement_list ( ), false ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); return sub_statement; } else { @@ -85,9 +94,37 @@ std::unique_ptr < Param > Parser::in_redirect_param ( ) { } std::unique_ptr < Param > Parser::param ( ) { + if ( check ( cli::Lexer::TokenType::CARET_SIGN ) ) { + match ( cli::Lexer::TokenType::CARET_SIGN ); + return move_param ( ); + } else { + return value_param ( ); + } +} + +std::unique_ptr < Param > Parser::move_param ( ) { + if ( check ( cli::Lexer::TokenType::DASH_SIGN ) ) { + match ( cli::Lexer::TokenType::DASH_SIGN ); + return std::make_unique < PreviousResultParam > ( true ); + } else if ( check ( cli::Lexer::TokenType::IN_REDIRECT ) ) { + match ( cli::Lexer::TokenType::IN_REDIRECT ); + match ( cli::Lexer::TokenType::LEFT_PAREN ); + auto sub_statement = std::make_unique < StatementParam > ( statement_list ( ), true ); + match ( cli::Lexer::TokenType::RIGHT_PAREN ); + return sub_statement; + } else if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) { + match ( cli::Lexer::TokenType::DOLAR_SIGN ); + std::unique_ptr < Arg > name = arg ( ); + return std::make_unique < VariableParam > ( std::move ( name ), true ); + } else { + throw exception::CommonException ( "Mismatched set while expanding move_param rule." ); + } +} + +std::unique_ptr < Param > Parser::value_param ( ) { if ( check ( cli::Lexer::TokenType::DASH_SIGN ) ) { match ( cli::Lexer::TokenType::DASH_SIGN ); - return std::make_unique < PreviousResultParam > ( ); + return std::make_unique < PreviousResultParam > ( false ); } else if ( check ( cli::Lexer::TokenType::IN_REDIRECT ) ) { match ( cli::Lexer::TokenType::IN_REDIRECT ); return in_redirect_param ( ); @@ -106,7 +143,7 @@ std::unique_ptr < Param > Parser::param ( ) { } else if ( check ( cli::Lexer::TokenType::DOLAR_SIGN ) ) { match ( cli::Lexer::TokenType::DOLAR_SIGN ); std::unique_ptr < Arg > name = arg ( ); - return std::make_unique < VariableParam > ( std::move ( name ) ); + return std::make_unique < VariableParam > ( std::move ( name ), false ); } else if ( check ( cli::Lexer::TokenType::HASH_SIGN ) ) { match ( cli::Lexer::TokenType::HASH_SIGN ); std::string value = getTokenValue ( ); @@ -130,8 +167,9 @@ std::shared_ptr < Statement > Parser::single_statement ( ) { match ( cli::Lexer::TokenType::LEFT_PAREN ); std::unique_ptr < Arg > type = arg ( ); match ( cli::Lexer::TokenType::RIGHT_PAREN ); + bool move = move_arg ( ); std::shared_ptr < Statement > casted_statement = single_statement ( ); - return std::make_shared < CastStatement > ( std::move ( type ), casted_statement ); + return std::make_shared < CastStatement > ( std::move ( type ), casted_statement, move ); } else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) { std::unique_ptr < Arg > name = std::make_unique < ImmediateArg > ( matchIdentifier ( ) ); ext::vector < std::unique_ptr < Option > > options; diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h index 7300c00c15474c85b1c86be838597bfce6a46966..245b152086c8b8ab8c03ef5817e4cdea530a740c 100644 --- a/alib2cli/src/parser/Parser.h +++ b/alib2cli/src/parser/Parser.h @@ -77,10 +77,16 @@ public: std::unique_ptr < Arg > optional_arg ( ); + bool move_arg ( ); + std::unique_ptr < Param > in_redirect_param ( ); std::unique_ptr < Param > param ( ); + std::unique_ptr < Param > move_param ( ); + + std::unique_ptr < Param > value_param ( ); + std::shared_ptr < Statement > single_statement ( ); std::shared_ptr < StatementList > statement_list ( ); diff --git a/alib2cli/test-src/cli/CliTest.cpp b/alib2cli/test-src/cli/CliTest.cpp index 532d8340c5515c2497ab044a1507f721bb13e439..72317664afcf5b2463ba52a3c10fd3bb5293ec61 100644 --- a/alib2cli/test-src/cli/CliTest.cpp +++ b/alib2cli/test-src/cli/CliTest.cpp @@ -106,3 +106,32 @@ void CliTest::testCreateUnique ( ) { } } + +class Source { +public: + static std::unique_ptr < int > source ( ) { + return std::make_unique < int > ( 1 ); + } +}; + +class Sink { +public: + static void sink ( std::unique_ptr < int > val ) { + std::cout << * val << std::endl; + } +}; + +void CliTest::testMove ( ) { + abstraction::AlgorithmRegistry::registerAlgorithm < Source > ( Source::source, false, false ); + abstraction::AlgorithmRegistry::registerAlgorithm < Sink > ( Sink::sink, false, false ); + + try { + cli::Environment environment; + cli::Parser parser ( cli::Lexer ( "execute Source | Sink ^ - >" ) ); + parser.parse ( )->run ( environment ); + } catch ( const char * ex ) { + std::cout << ex << std::endl; + } + +} + diff --git a/alib2cli/test-src/cli/CliTest.h b/alib2cli/test-src/cli/CliTest.h index f733be4c08ad99b5523c207b6c3439ff618aa84a..a4068d8d9fd5ad31f2459179405e89dad2ec418d 100644 --- a/alib2cli/test-src/cli/CliTest.h +++ b/alib2cli/test-src/cli/CliTest.h @@ -6,6 +6,7 @@ class CliTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE ( CliTest ); CPPUNIT_TEST ( testCreateUnique ); + CPPUNIT_TEST ( testMove ); CPPUNIT_TEST_SUITE_END ( ); public: @@ -13,6 +14,7 @@ public: void tearDown ( ); void testCreateUnique ( ); + void testMove ( ); }; #endif // CLI_TEST_H_ diff --git a/alib2common/src/abstraction/AlgorithmAbstraction.hpp b/alib2common/src/abstraction/AlgorithmAbstraction.hpp index 7b6b993bec77e9d59facb36ec1bc87f7e69106f3..08ec27b27cff93a4e8d816e279e4d8b4cad431e9 100644 --- a/alib2common/src/abstraction/AlgorithmAbstraction.hpp +++ b/alib2common/src/abstraction/AlgorithmAbstraction.hpp @@ -30,7 +30,7 @@ public: if ( this->cached ( ) ) return true; - this->run_helper ( m_callback, this->m_params, std::make_index_sequence < sizeof ... ( ParamTypes ) > { } ); + this->run_helper ( m_callback, this->m_params, this->m_moves, std::make_index_sequence < sizeof ... ( ParamTypes ) > { } ); return true; } diff --git a/alib2common/src/abstraction/NaryOperationAbstraction.hpp b/alib2common/src/abstraction/NaryOperationAbstraction.hpp index 7f3a55f02675eea4690d756f1b1bcb57fd89c1e2..16e5dbaee30e537b5db608be549e74b1a680afc2 100644 --- a/alib2common/src/abstraction/NaryOperationAbstraction.hpp +++ b/alib2common/src/abstraction/NaryOperationAbstraction.hpp @@ -19,9 +19,12 @@ template < class ReturnType, class ... ParamTypes > class NaryOperationAbstraction : public ValueOperationAbstraction < ReturnType > { protected: ext::tuple < std::shared_ptr < ValueProvider < ParamTypes > > ... > m_params; + std::array < bool, sizeof ... ( ParamTypes ) > m_moves; private: - virtual bool attachInput ( const std::shared_ptr < OperationAbstraction > & input, unsigned index ) override { + virtual bool attachInput ( const std::shared_ptr < OperationAbstraction > & input, unsigned index, bool move ) override { + m_moves [ index ] = move; + auto attachCallback = [ & ] ( auto & param ) { if ( param != nullptr ) return false; @@ -38,6 +41,8 @@ private: } virtual bool detachInput ( unsigned index ) override { + m_moves [ index ] = false; + auto detachCallback = [ & ] ( auto & param ) { param = nullptr; return true; @@ -46,6 +51,11 @@ private: } public: + NaryOperationAbstraction ( ) { + for ( unsigned i = 0; i < sizeof ... ( ParamTypes ); ++ i ) + m_moves [ i ] = false; + } + virtual bool inputsReady ( ) const override { auto readyCallback = [ ] ( const auto & param ) { return ( bool ) param && param->isReady ( ); diff --git a/alib2common/src/abstraction/NormalizeAbstraction.hpp b/alib2common/src/abstraction/NormalizeAbstraction.hpp index ce775fffa485f1b0dbac7350b5d676e3eed083fd..b1f1c50d233fa576bdf5a29972ad01f135e81829 100644 --- a/alib2common/src/abstraction/NormalizeAbstraction.hpp +++ b/alib2common/src/abstraction/NormalizeAbstraction.hpp @@ -26,7 +26,7 @@ public: if ( this->cached ( ) ) return true; - this->m_data = ReturnType ( * std::unique_ptr < ReturnType > ( static_cast < ReturnType * > ( std::move ( std::get < 0 > ( this->m_params )->getValue ( ) ).normalize ( ) ) ) ); + this->m_data = ReturnType ( * std::unique_ptr < ReturnType > ( static_cast < ReturnType * > ( std::move ( std::get < 0 > ( this->m_params )->getValue ( std::get < 0 > ( this->m_moves ) ) ).normalize ( ) ) ) ); return true; } diff --git a/alib2common/src/abstraction/OperationAbstraction.hpp b/alib2common/src/abstraction/OperationAbstraction.hpp index 5726da3b35b5c0cd79426d0a66e5740b8a4ac5c2..258d42e38feabecefbe9a066cc1fa625a33896fb 100644 --- a/alib2common/src/abstraction/OperationAbstraction.hpp +++ b/alib2common/src/abstraction/OperationAbstraction.hpp @@ -20,7 +20,7 @@ namespace abstraction { class OperationAbstraction : public std::enable_shared_from_this < OperationAbstraction > { public: - virtual bool attachInput ( const std::shared_ptr < OperationAbstraction > & input, unsigned index ) = 0; + virtual bool attachInput ( const std::shared_ptr < OperationAbstraction > & input, unsigned index, bool move ) = 0; virtual bool detachInput ( unsigned index ) = 0; virtual ~OperationAbstraction ( ) noexcept { diff --git a/alib2common/src/abstraction/ValueOperationAbstraction.hpp b/alib2common/src/abstraction/ValueOperationAbstraction.hpp index 1b947fb64935d31354dd66e2a12c6889b8f68014..d41eb14158f2c926bc5d40f35f2f8caae992792d 100644 --- a/alib2common/src/abstraction/ValueOperationAbstraction.hpp +++ b/alib2common/src/abstraction/ValueOperationAbstraction.hpp @@ -33,9 +33,13 @@ protected: public: template < typename Callable, typename ... Ts, size_t ... Indexes > - inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, std::index_sequence < Indexes ... > ) { + inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) { + /* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */ + ( void ) inputs; + ( void ) moves; + if ( ! isReady ( ) ) - m_data = callback ( std::get < Indexes > ( inputs )->getValue ( ) ... ); + m_data = callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... ); } virtual bool isReady ( ) const override { @@ -73,9 +77,13 @@ protected: public: template < typename Callable, typename ... Ts, size_t ... Indexes > - inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, std::index_sequence < Indexes ... > ) { + inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) { + /* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */ + ( void ) inputs; + ( void ) moves; + if ( ! isReady ( ) ) - m_data = std::reference_wrapper < ReturnType > ( callback ( std::get < Indexes > ( inputs )->getValue ( ) ... ) ); + m_data = std::reference_wrapper < ReturnType > ( callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... ) ); } virtual bool isReady ( ) const override { @@ -109,9 +117,13 @@ protected: public: template < typename Callable, typename ... Ts, size_t ... Indexes > - inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, std::index_sequence < Indexes ... > ) { + inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) { + /* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */ + ( void ) inputs; + ( void ) moves; + if ( ! isReady ( ) ) - m_data = std::reference_wrapper < const ReturnType > ( callback ( std::get < Indexes > ( inputs )->getValue ( ) ... ) ); + m_data = std::reference_wrapper < const ReturnType > ( callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... ) ); } virtual bool isReady ( ) const override { @@ -149,9 +161,13 @@ protected: public: template < typename Callable, typename ... Ts, size_t ... Indexes > - inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, std::index_sequence < Indexes ... > ) { + inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) { + /* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */ + ( void ) inputs; + ( void ) moves; + if ( ! isReady ( ) ) - m_data = std::unique_ptr < ReturnType > ( callback ( std::get < Indexes > ( inputs )->getValue ( ) ... ) ); + m_data = std::unique_ptr < ReturnType > ( callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... ) ); } virtual bool isReady ( ) const override { @@ -178,8 +194,12 @@ template < > class ValueOperationAbstraction < void > : public OperationAbstraction { public: template < typename Callable, typename ... Ts, size_t ... Indexes > - inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, std::index_sequence < Indexes ... > ) const { - callback ( std::get < Indexes > ( inputs )->getValue ( ) ... ); + inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) const { + /* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */ + ( void ) inputs; + ( void ) moves; + + callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... ); } virtual bool isReady ( ) const { diff --git a/alib2common/src/abstraction/ValueProvider.hpp b/alib2common/src/abstraction/ValueProvider.hpp index 92dd206d0ba6b322113b4f4062b292df32f40603..d0e5f2babbb694e3d2fb2cee54ce223db0d13c72 100644 --- a/alib2common/src/abstraction/ValueProvider.hpp +++ b/alib2common/src/abstraction/ValueProvider.hpp @@ -15,26 +15,42 @@ namespace abstraction { template < class Type > class ValueProvider { - bool m_move; - protected: virtual Type & getData ( ) const = 0; public: typedef Type return_type; - ValueProvider ( ) : m_move ( false ) { + template < class T = Type > + typename std::enable_if < std::is_copy_constructible < T >::value && std::is_move_constructible < T >::value, T >::type getValue ( bool move ) const { + if ( move ) + return std::move ( getData ( ) ); + else + return getData ( ); } - void setMove ( bool move ) { - m_move = move; + template < class T = Type > + typename std::enable_if < std::is_copy_constructible < T >::value && ! std::is_move_constructible < T >::value, T >::type getValue ( bool move ) const { + if ( move ) + throw exception::CommonException ( "Value not move constructible" ); + else + return getData ( ); } - Type getValue ( ) const { - if ( m_move ) + template < class T = Type > + typename std::enable_if < ! std::is_copy_constructible < T >::value && std::is_move_constructible < T >::value, T >::type getValue ( bool move ) const { + if ( move ) return std::move ( getData ( ) ); else - return getData ( ); + throw exception::CommonException ( "Value not copy constructible" ); + } + + template < class T = Type > + typename std::enable_if < ! std::is_copy_constructible < T >::value && ! std::is_move_constructible < T >::value, T >::type getValue ( bool move ) const { + if ( move ) + throw exception::CommonException ( "Value not move constructible" ); + else + throw exception::CommonException ( "Value not copy constructible" ); } virtual bool eval ( ) = 0; @@ -50,15 +66,11 @@ protected: public: typedef Type return_type; - void setMove ( bool ) { - throw exception::CommonException ( "Reference cannot be moved." ); - } - Type & getValueReference ( ) const { return getData ( ); } - Type & getValue ( ) const { + Type & getValue ( bool ) const { return getData ( ); } @@ -75,15 +87,11 @@ protected: public: typedef Type return_type; - void setMove ( bool ) { - throw exception::CommonException ( "Const reference cannot be moved." ); - } - const Type & getConstValueReference ( ) const { return getConstData ( ); } - const Type & getValue ( ) const{ + const Type & getValue ( bool ) const{ return getConstData ( ); }