source: src/Actions/Action_impl_pre.hpp

Candidate_v1.6.1
Last change on this file was e7ad08, checked in by Frederik Heber <frederik.heber@…>, 7 years ago

Python interface now converts dashes in tokens to underscores, store-session used keyword arguments.

  • MoleCuilder's python functions (i.e. commands) typically have quite a number of arguments and therefore can be easily confused. We circumvent this by using keyword (or named) arguments that are also independent of position. Moreover, in that case only the non-default arguments need to be given.
  • TESTS: Marked failing python tests as XFAIL for the moment.
  • Property mode set to 100644
File size: 14.9 KB
RevLine 
[0b2ce9]1/*
2 * Action_impl.hpp
3 *
4 * Created on: Aug 25, 2010
5 * Author: heber
6 */
7
8/** These macros define the following functions, necessary but repetitive for
9 * every Action:
10 * -# Dialog* fillDialog()
11 * -# action command (e.g. AnalysisMolecularVolume() )
12 * -# void getParametersfromValuStorage()
13 * -# struct Action...Parameters
14 *
15 * For this, the user has the define the following values, each with
[b4fa106]16 * parenthesis, for the values/parameters the action needs
17 * -# paramtypes, e.g. (int)(double)
18 * -# paramtokens, e.g. ("Z")("length")
19 * -# paramreferences, e.g. (Z)(length)
20 * and for additional values/parameters to save in the state
21 * -# statetypes, e.g. (int)(double)
22 * -# statereferences, e.g. (Z)(length)
23 * and the name and category of the action
[0b2ce9]24 * -# CATEGORY, e.g. Analysis
25 * -# ACTIONNAME, e.g. MolecularVolume
26 */
27
[56f73b]28// include config.h
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
[9ee38b]32
[862b6a]33#include "CodePatterns/Chronos.hpp"
34
[9ee38b]35#include <boost/preprocessor/cat.hpp>
[b4fa106]36#include <boost/preprocessor/expand.hpp>
[9ee38b]37#include <boost/preprocessor/comparison/equal.hpp>
38#include <boost/preprocessor/comparison/not_equal.hpp>
[6ba9ba]39#include <boost/preprocessor/control/expr_if.hpp>
[9ee38b]40#include <boost/preprocessor/control/if.hpp>
41#include <boost/preprocessor/debug/assert.hpp>
[46b181]42#include <boost/preprocessor/facilities/empty.hpp>
[9ee38b]43#include <boost/preprocessor/iteration/local.hpp>
[6ba9ba]44#include <boost/preprocessor/list/adt.hpp>
[9ee38b]45#include <boost/preprocessor/punctuation/comma_if.hpp>
46#include <boost/preprocessor/repetition/repeat.hpp>
47#include <boost/preprocessor/seq/elem.hpp>
[46b181]48#include <boost/preprocessor/seq/filter.hpp>
[9ee38b]49#include <boost/preprocessor/seq/push_back.hpp>
50#include <boost/preprocessor/seq/seq.hpp>
51#include <boost/preprocessor/seq/size.hpp>
52#include <boost/preprocessor/seq/transform.hpp>
53
[628577]54#include "Actions/ActionQueue.hpp"
[9b56f34]55#include "Actions/toCLIString.hpp"
[992839]56#include "Actions/toPythonString.hpp"
[f10b0c]57#include "Parameters/Parameter.hpp"
58
[649aaa]59
[e4afb4]60// some derived names: if CATEGORY is not given, we don't prefix with it
61#ifdef CATEGORY
[9ee38b]62#define ACTION BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, Action))
63#define COMMAND BOOST_PP_CAT(CATEGORY, ACTIONNAME)
64#define STATE BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, State))
65#define PARAMS BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, Parameters))
[e4afb4]66#else
67#define ACTION BOOST_PP_CAT(ACTIONNAME, Action)
68#define COMMAND ACTIONNAME
69#define STATE BOOST_PP_CAT(ACTIONNAME, State)
70#define PARAMS BOOST_PP_CAT(ACTIONNAME, Parameters)
71#endif
[2a6a2c]72#define INSTANCE BOOST_PP_CAT(this_, BOOST_PP_CAT(ACTIONNAME, _instance))
[9ee38b]73
74// check if no lists given
[b4fa106]75#ifndef paramtypes
76#define MAXPARAMTYPES 0
[9ee38b]77#else
[b4fa106]78#define MAXPARAMTYPES BOOST_PP_SEQ_SIZE(paramtypes)
79#endif
80#ifndef statetypes
81#define MAXSTATETYPES 0
82#else
83#define MAXSTATETYPES BOOST_PP_SEQ_SIZE(statetypes)
[9ee38b]84#endif
[6ba9ba]85#ifndef paramdefaults
86#define MAXPARAMDEFAULTS 0
87// this is required for valid_print "else part"
88#define sequencer(z,n,data) \
89 BOOST_PP_SEQ_PUSH_BACK( data, NOPARAM_DEFAULT)
90#define paramdefaults BOOST_PP_REPEAT( MAXPARAMTYPES, sequencer, BOOST_PP_SEQ_NIL )
91#else
92#define MAXPARAMDEFAULTS BOOST_PP_SEQ_SIZE(paramdefaults)
93#endif
94#define PARAM_DEFAULT(x) \
95 (x, BOOST_PP_NIL)
[9ee38b]96
97// check user has given name and category
98#ifndef ACTIONNAME
99ERROR: No "ACTIONNAME" defined in: __FILE__
100#endif
101
102// calculate numbers and check whether all have same size
[b4fa106]103#ifdef paramtokens
104BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramtokens)),\
105 ERROR: There are not the same number of "paramtokens" and "paramtypes" in: __FILE__ \
[9ee38b]106)
107#endif
[b4fa106]108#ifdef paramreferences
109BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramreferences)),\
110 ERROR: There are not the same number of "paramtokens" and "paramreferences" in: __FILE__ \
111)
112#endif
[152e5c]113#ifdef paramdescriptions
114BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramdescriptions)),\
115 ERROR: There are not the same number of "paramtokens" and "paramdescriptions" in: __FILE__ \
116)
117#endif
[b4fa106]118
119#ifdef statetypes
120BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXSTATETYPES, BOOST_PP_SEQ_SIZE(statereferences)),\
121 ERROR: There are not the same number of "statetypes" and "statereferences" in: __FILE__ \
[9ee38b]122)
123#endif
124
125// print a list of type ref followed by a separator, i.e. "int i;"
[b4fa106]126#define initialiser_print(z,n,initialiserlist) \
127 BOOST_PP_SEQ_ELEM(n, initialiserlist) \
128 (BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(n, initialiserlist))),
129
130// print a list of ref(_ref) followed by a separator, i.e. "id(_id),"
131#define type_print(z,n,TYPELIST, VARLIST, separator) \
132 BOOST_PP_SEQ_ELEM(n, TYPELIST) \
133 BOOST_PP_SEQ_ELEM(n, VARLIST)\
[9ee38b]134 separator
135
136// print a list of type ref followed, i.e. "int i, double position"
[b4fa106]137#define type_list(z,n,TYPELIST,VARLIST) \
[9ee38b]138 BOOST_PP_COMMA_IF(n)\
[b4fa106]139 BOOST_PP_SEQ_ELEM(n, TYPELIST) \
140 BOOST_PP_SEQ_ELEM(n, VARLIST)
[9ee38b]141
[b4fa106]142// prints dialog->query calls for paramtypes with tokens
[9ee38b]143#define dialog_print(z,n,unused) \
144 dialog->query<\
[b4fa106]145 BOOST_PP_SEQ_ELEM(n, paramtypes)\
[f10b0c]146 >( params. \
147 BOOST_PP_SEQ_ELEM(n, paramreferences)\
148 ,\
[b4fa106]149 BOOST_PP_SEQ_ELEM(n, paramtokens)\
[152e5c]150 ,\
151 BOOST_PP_SEQ_ELEM(n, paramdescriptions)\
[e4afb4]152 );
[9ee38b]153
[46b181]154// prints command line call for this Action for paramtypes with tokens
155#define outputAsCLI_print(z,n,output) \
156 output << \
[477012]157 BOOST_PP_IF(n, " --", "--") \
158 << \
[46b181]159 BOOST_PP_SEQ_ELEM(n, paramtokens) \
[f6ff216]160 << " " << toCLIString(params. \
[9b56f34]161 BOOST_PP_SEQ_ELEM(n, paramreferences) \
[f6ff216]162 .get());
[46b181]163
164// prints if statement to check two strings (paramtokens[n] vs. TOKEN)
165#define checkpresenttoken_print(z, n, TOKEN, booltoken) \
166 if ( std::string(\
167 BOOST_PP_SEQ_ELEM(n, paramtokens) )\
168 == getName()) \
169 booltoken = false;
170
[477012]171// prints command line call for this Action for paramtypes with tokens
172#define outputAsPython_print(z,n,output) \
173 output << \
174 BOOST_PP_IF(n, ", ", "") \
[e7ad08]175 << normalizeToken( BOOST_PP_SEQ_ELEM(n, paramtokens) ) \
176 << "=" \
[db1048]177 << "\"" << params. \
[477012]178 BOOST_PP_SEQ_ELEM(n, paramreferences) \
[e7ad08]179 .getAsStringUnvalidated() \
180 << "\""; \
[477012]181
[6ba9ba]182// print an initialiser list, i.e. "var( token, valid (,default) )(,)"
183#define valid_print(z,n,TOKENLIST, VARLIST, VALIDLIST, DEFAULTLIST) \
[649aaa]184 BOOST_PP_COMMA_IF(n) \
185 BOOST_PP_SEQ_ELEM(n, VARLIST) \
186 ( \
187 BOOST_PP_SEQ_ELEM(n, TOKENLIST) \
188 , \
189 BOOST_PP_SEQ_ELEM(n, VALIDLIST) \
[6ba9ba]190 BOOST_PP_COMMA_IF( BOOST_PP_NOT( BOOST_PP_LIST_IS_NIL( BOOST_PP_SEQ_ELEM(n, DEFAULTLIST) ) ) ) \
191 BOOST_PP_EXPR_IF( \
192 BOOST_PP_NOT( BOOST_PP_LIST_IS_NIL( BOOST_PP_SEQ_ELEM(n, DEFAULTLIST) ) ), \
193 BOOST_PP_LIST_FIRST( BOOST_PP_SEQ_ELEM(n, DEFAULTLIST) )) \
[649aaa]194 )
195
[6ba9ba]196// print an initialiser list, i.e. "var( valid . var )(,)"
[649aaa]197#define validcopy_print(z,n,TOKENLIST, VARLIST, VALID) \
198 BOOST_PP_COMMA_IF(n) \
199 BOOST_PP_SEQ_ELEM(n, VARLIST) \
200 ( \
201 VALID . \
202 BOOST_PP_SEQ_ELEM(n, VARLIST) \
203 )
204
[9ee38b]205// prints set/queryCurrentValue (command) for paramreferences and paramtokens
[f10b0c]206#define value_print(z, n, container, prefix) \
207 prefix \
208 BOOST_PP_SEQ_ELEM(n, container)\
209 .set(\
210 BOOST_PP_SEQ_ELEM(n, container)\
[9ee38b]211 );
212
[88ba1f]213// prints set/queryCurrentValue (command) for paramreferences and paramtokens
[f10b0c]214#define valuetype_print(z,n,container, types, prefix) \
215 prefix \
216 BOOST_PP_SEQ_ELEM(n, container) \
217 .setAsString( \
218 BOOST_PP_SEQ_ELEM(n, container) \
[88ba1f]219 );
220
221#define stringtype std::string
222
223#define type2string(s, data, elem) \
224 stringtype
225
[a82f61]226// prints if ( token == "select-molecule-by-id" ) { prefix.ids.setAsString(_value); }
227#define setparameterifmatch_print(z,n,container, reference, token, value) \
228 if ( token == BOOST_PP_SEQ_ELEM(n, container) ) { \
229 params. \
230 BOOST_PP_SEQ_ELEM(n, reference) \
231 .setAsString( \
232 value \
233 ); \
234 }
[88ba1f]235
[3139b2]236//#include "Actions/ActionTraits.hpp"
[0b2ce9]237#include "UIElements/Dialog.hpp"
238
[e4afb4]239#ifdef paramtokens
240#define statenecessary 1
241#endif
242#ifndef statetokens
243#define statenecessary 1
244#endif
[9ee38b]245
[ce7fdc]246namespace MoleCuilder {
247
[b4fa106]248// =========== memento to remember the state when undoing ===========
[e4afb4]249#ifdef statenecessary
[b4fa106]250class STATE : public ActionState {
251public:
252 STATE(
253#if defined statetypes && defined statereferences // if we have parameters, we have to add "_" before each reference and add the params as the last one
254#define OP(s,data,elem) BOOST_PP_CAT(data, elem) // OP to add "_"
255#define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, BOOST_PP_SEQ_PUSH_BACK(statetypes, const ACTION::PARAMS &), BOOST_PP_SEQ_TRANSFORM(OP, _, BOOST_PP_SEQ_PUSH_BACK(statereferences, params)))
256#else /// if not, params is only list
257#define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, (const ACTION::PARAMS &), (_params))
258#endif
259#define BOOST_PP_LOCAL_LIMITS (0, MAXSTATETYPES)
260#include BOOST_PP_LOCAL_ITERATE()
261) :
262#if defined statetypes && defined statereferences // do we have parameters at all?
263BOOST_PP_REPEAT(MAXSTATETYPES, initialiser_print, statereferences)
264#endif
265params(_params)
266 {}
[0b2ce9]267
[b4fa106]268#if defined statetypes && defined statereferences // do we have parameters at all?
269#define BOOST_PP_LOCAL_MACRO(n) type_print(~, n, statetypes, statereferences, ;)
270#define BOOST_PP_LOCAL_LIMITS (0, MAXSTATETYPES-1)
271#include BOOST_PP_LOCAL_ITERATE()
272#endif
273 ACTION::PARAMS params;
274};
[e4afb4]275#endif /* statenecessary */
[0b2ce9]276
[2a6a2c]277// (const) prototype to be placed into the ActionRegistry (must be deleted by registry itself)
[83e90c]278//const ACTION INSTANCE;
279//boost::shared_ptr< ACTION > INSTANCE( new ACTION() );
[2a6a2c]280
[b4fa106]281// =========== constructor ===========
[0b2ce9]282ACTION::ACTION () :
[c09f94]283#if defined BASECLASS
284 BASECLASS(ActionTraits< ACTION >())
285#else
[126867]286 Action(ActionTraits< ACTION >())
[c09f94]287#endif
[0b2ce9]288{}
289
[b4fa106]290// =========== destructor ===========
[0b2ce9]291ACTION::~ACTION ()
[e4afb4]292{
293 //std::cout << "Action ACTION is being destroyed." << std::endl;
294}
[0b2ce9]295
[649aaa]296// =========== parameter constructor ===========
297ACTION::PARAMS::PARAMS()
298#if defined paramtokens && defined paramreferences && defined paramvalids
299 :
[6ba9ba]300#define BOOST_PP_LOCAL_MACRO(n) valid_print(~, n, paramtokens, paramreferences, paramvalids, paramdefaults)
[649aaa]301#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
302#include BOOST_PP_LOCAL_ITERATE()
303#endif
304 {}
305
306ACTION::PARAMS::PARAMS(const PARAMS &p)
307#if defined paramtokens && defined paramreferences
308 :
309#define BOOST_PP_LOCAL_MACRO(n) validcopy_print(~, n, paramtokens, paramreferences, p)
310#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
311#include BOOST_PP_LOCAL_ITERATE()
312#endif
313 {}
314
[a82f61]315void ACTION::setOptionValue(const std::string &_token, const std::string &_value)
316{
317 // check whether it is a valid token and set
318#if defined paramtokens && defined paramreferences
319#define BOOST_PP_LOCAL_MACRO(n) setparameterifmatch_print(~, n, paramtokens, paramreferences, _token, _value)
320#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
321#include BOOST_PP_LOCAL_ITERATE()
322#endif
323}
324
[af5384]325// =========== clone Action ===========
326Action* ACTION::clone(enum QueryOptions flag) const
327{
328 if (flag == Interactive)
329 return new ACTION();
330 else
331 return new ACTION(*this);
332}
333
[b4fa106]334// =========== fill a dialog ===========
[0b2ce9]335Dialog* ACTION::fillDialog(Dialog *dialog) {
336 ASSERT(dialog,"No Dialog given when filling actionname's dialog");
[b4fa106]337#if BOOST_PP_EQUAL(MAXPARAMTYPES,0)
[e4afb4]338 dialog->queryEmpty(TOKEN, Traits.getDescription());
[0b2ce9]339#else
340#define BOOST_PP_LOCAL_MACRO(n) dialog_print(~, n, ~)
[b4fa106]341#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
[0b2ce9]342#include BOOST_PP_LOCAL_ITERATE()
343#endif
344 return dialog;
345};
346
[46b181]347// =========== output as CLI ===========
348void ACTION::outputAsCLI(std::ostream &ost) const {
349 // check whether TOKEN is also an option
350 // is a bit ugly as preprocessor cannot compare strings
351 bool status = true;
352#if defined paramtokens && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
353#define BOOST_PP_LOCAL_MACRO(n) checkpresenttoken_print(~, n, TOKEN, status)
354#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
355#include BOOST_PP_LOCAL_ITERATE()
356#endif
[f6ff216]357 if (status) {
358 ost << "--" << TOKEN;
359#if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
360 ost << " ";
361#endif
362 }
[46b181]363 // then print option along with each argument if set
364#if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
365#define BOOST_PP_LOCAL_MACRO(n) outputAsCLI_print(~, n, ost)
366#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
367#include BOOST_PP_LOCAL_ITERATE()
368#endif
369}
370
[477012]371// =========== output as PYTHON ===========
372void ACTION::outputAsPython(std::ostream &ost, const std::string &prefix) const {
373 // print prefix and action command
374 ost << prefix << "." << BOOST_PP_STRINGIZE( COMMAND ) << "(";
375 // then print option along with each argument if set
376#if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
377#define BOOST_PP_LOCAL_MACRO(n) outputAsPython_print(~, n, ost)
378#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
379#include BOOST_PP_LOCAL_ITERATE()
380#endif
381 ost << ")" << std::endl;
382}
383
[862b6a]384// =========== time the action ===========
385// we need this here to have the correct function name
386void ACTION::startTimer() const { Chronos::getInstance().startTiming( std::string( TOKEN ) ); }
387void ACTION::endTimer() const { Chronos::getInstance().endTiming( std::string( TOKEN ) ); }
388
[b4fa106]389// =========== command for calling action directly ===========
390void COMMAND(
[f10b0c]391#if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
[b4fa106]392#define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, paramtypes, paramreferences)
393#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
394#include BOOST_PP_LOCAL_ITERATE()
395#endif
[05736a]396)
[0b2ce9]397{
[10aee4]398 ACTION * const ToCall = dynamic_cast<ACTION*>(ActionQueue::getInstance().getActionByName( TOKEN ).clone());
[ddde10]399 //ACTION::PARAMS params;
[f10b0c]400#if defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
401#define BOOST_PP_LOCAL_MACRO(n) value_print(~, n, paramreferences, ToCall->params.)
[b4fa106]402#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
[0b2ce9]403#include BOOST_PP_LOCAL_ITERATE()
404#endif
[975b83]405 Action::insertAction( ToCall, Action::NonInteractive);
[0b2ce9]406};
407
[88ba1f]408void BOOST_PP_CAT( COMMAND, _stringargs)(
[f10b0c]409#if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
[88ba1f]410#define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, BOOST_PP_SEQ_TRANSFORM( type2string, , paramtypes), paramreferences)
411#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
412#include BOOST_PP_LOCAL_ITERATE()
413#endif
414 ) {
[10aee4]415 ACTION * const ToCall = dynamic_cast<ACTION*>(ActionQueue::getInstance().getActionByName( TOKEN ).clone());
[88ba1f]416 //ACTION::PARAMS params;
[f10b0c]417#if defined paramtypes && defined paramtypes && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
418#define BOOST_PP_LOCAL_MACRO(n) valuetype_print(~, n, paramreferences, paramtypes, ToCall->params. )
[88ba1f]419#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
420#include BOOST_PP_LOCAL_ITERATE()
421#endif
[975b83]422 Action::insertAction( ToCall, Action::NonInteractive);
[88ba1f]423};
424
[ce7fdc]425}
426
[b4fa106]427// free up defines
[649aaa]428#undef paramvalids
[b4fa106]429#undef paramtypes
430#undef paramtokens
431#undef paramreferences
[649aaa]432#undef paramdescriptions
433#undef paramdefaults
[b4fa106]434#undef MAXPARAMTYPES
[6ba9ba]435#undef MAXPARAMDEFAULTS
[b4fa106]436#undef statetypes
437#undef statereferences
438#undef MAXSTATETYPES
[6ba9ba]439#undef PARAM_DEFAULT
[0b2ce9]440
[88ba1f]441#undef type2string
442#undef stringtype
[a02f78]443#undef initialiser_print
444#undef type_print
445#undef type_list
446#undef dialog_print
[6ba9ba]447#undef sequencer
[649aaa]448#undef valid_print
449#undef validcopy_print
[a02f78]450#undef value_print
[88ba1f]451#undef valuetype_print
[a02f78]452
[9ee38b]453#undef ACTION
454#undef COMMAND
455#undef PARAMS
456#undef STATE
[2a6a2c]457#undef INSTANCE
[b4fa106]458
459#undef ACTIONNAME
460#undef CATEGORY
[9ee38b]461#undef TOKEN
Note: See TracBrowser for help on using the repository browser.