source: src/Actions/Action_impl_pre.hpp@ e7ad08

Candidate_v1.6.1 ChemicalSpaceEvaluator PythonUI_with_named_parameters TremoloParser_IncreasedPrecision
Last change on this file since e7ad08 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
Line 
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
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
24 * -# CATEGORY, e.g. Analysis
25 * -# ACTIONNAME, e.g. MolecularVolume
26 */
27
28// include config.h
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32
33#include "CodePatterns/Chronos.hpp"
34
35#include <boost/preprocessor/cat.hpp>
36#include <boost/preprocessor/expand.hpp>
37#include <boost/preprocessor/comparison/equal.hpp>
38#include <boost/preprocessor/comparison/not_equal.hpp>
39#include <boost/preprocessor/control/expr_if.hpp>
40#include <boost/preprocessor/control/if.hpp>
41#include <boost/preprocessor/debug/assert.hpp>
42#include <boost/preprocessor/facilities/empty.hpp>
43#include <boost/preprocessor/iteration/local.hpp>
44#include <boost/preprocessor/list/adt.hpp>
45#include <boost/preprocessor/punctuation/comma_if.hpp>
46#include <boost/preprocessor/repetition/repeat.hpp>
47#include <boost/preprocessor/seq/elem.hpp>
48#include <boost/preprocessor/seq/filter.hpp>
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
54#include "Actions/ActionQueue.hpp"
55#include "Actions/toCLIString.hpp"
56#include "Actions/toPythonString.hpp"
57#include "Parameters/Parameter.hpp"
58
59
60// some derived names: if CATEGORY is not given, we don't prefix with it
61#ifdef CATEGORY
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))
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
72#define INSTANCE BOOST_PP_CAT(this_, BOOST_PP_CAT(ACTIONNAME, _instance))
73
74// check if no lists given
75#ifndef paramtypes
76#define MAXPARAMTYPES 0
77#else
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)
84#endif
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)
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
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__ \
106)
107#endif
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
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
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__ \
122)
123#endif
124
125// print a list of type ref followed by a separator, i.e. "int i;"
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)\
134 separator
135
136// print a list of type ref followed, i.e. "int i, double position"
137#define type_list(z,n,TYPELIST,VARLIST) \
138 BOOST_PP_COMMA_IF(n)\
139 BOOST_PP_SEQ_ELEM(n, TYPELIST) \
140 BOOST_PP_SEQ_ELEM(n, VARLIST)
141
142// prints dialog->query calls for paramtypes with tokens
143#define dialog_print(z,n,unused) \
144 dialog->query<\
145 BOOST_PP_SEQ_ELEM(n, paramtypes)\
146 >( params. \
147 BOOST_PP_SEQ_ELEM(n, paramreferences)\
148 ,\
149 BOOST_PP_SEQ_ELEM(n, paramtokens)\
150 ,\
151 BOOST_PP_SEQ_ELEM(n, paramdescriptions)\
152 );
153
154// prints command line call for this Action for paramtypes with tokens
155#define outputAsCLI_print(z,n,output) \
156 output << \
157 BOOST_PP_IF(n, " --", "--") \
158 << \
159 BOOST_PP_SEQ_ELEM(n, paramtokens) \
160 << " " << toCLIString(params. \
161 BOOST_PP_SEQ_ELEM(n, paramreferences) \
162 .get());
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
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, ", ", "") \
175 << normalizeToken( BOOST_PP_SEQ_ELEM(n, paramtokens) ) \
176 << "=" \
177 << "\"" << params. \
178 BOOST_PP_SEQ_ELEM(n, paramreferences) \
179 .getAsStringUnvalidated() \
180 << "\""; \
181
182// print an initialiser list, i.e. "var( token, valid (,default) )(,)"
183#define valid_print(z,n,TOKENLIST, VARLIST, VALIDLIST, DEFAULTLIST) \
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) \
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) )) \
194 )
195
196// print an initialiser list, i.e. "var( valid . var )(,)"
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
205// prints set/queryCurrentValue (command) for paramreferences and paramtokens
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)\
211 );
212
213// prints set/queryCurrentValue (command) for paramreferences and paramtokens
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) \
219 );
220
221#define stringtype std::string
222
223#define type2string(s, data, elem) \
224 stringtype
225
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 }
235
236//#include "Actions/ActionTraits.hpp"
237#include "UIElements/Dialog.hpp"
238
239#ifdef paramtokens
240#define statenecessary 1
241#endif
242#ifndef statetokens
243#define statenecessary 1
244#endif
245
246namespace MoleCuilder {
247
248// =========== memento to remember the state when undoing ===========
249#ifdef statenecessary
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 {}
267
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};
275#endif /* statenecessary */
276
277// (const) prototype to be placed into the ActionRegistry (must be deleted by registry itself)
278//const ACTION INSTANCE;
279//boost::shared_ptr< ACTION > INSTANCE( new ACTION() );
280
281// =========== constructor ===========
282ACTION::ACTION () :
283#if defined BASECLASS
284 BASECLASS(ActionTraits< ACTION >())
285#else
286 Action(ActionTraits< ACTION >())
287#endif
288{}
289
290// =========== destructor ===========
291ACTION::~ACTION ()
292{
293 //std::cout << "Action ACTION is being destroyed." << std::endl;
294}
295
296// =========== parameter constructor ===========
297ACTION::PARAMS::PARAMS()
298#if defined paramtokens && defined paramreferences && defined paramvalids
299 :
300#define BOOST_PP_LOCAL_MACRO(n) valid_print(~, n, paramtokens, paramreferences, paramvalids, paramdefaults)
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
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
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
334// =========== fill a dialog ===========
335Dialog* ACTION::fillDialog(Dialog *dialog) {
336 ASSERT(dialog,"No Dialog given when filling actionname's dialog");
337#if BOOST_PP_EQUAL(MAXPARAMTYPES,0)
338 dialog->queryEmpty(TOKEN, Traits.getDescription());
339#else
340#define BOOST_PP_LOCAL_MACRO(n) dialog_print(~, n, ~)
341#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
342#include BOOST_PP_LOCAL_ITERATE()
343#endif
344 return dialog;
345};
346
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
357 if (status) {
358 ost << "--" << TOKEN;
359#if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
360 ost << " ";
361#endif
362 }
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
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
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
389// =========== command for calling action directly ===========
390void COMMAND(
391#if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
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
396)
397{
398 ACTION * const ToCall = dynamic_cast<ACTION*>(ActionQueue::getInstance().getActionByName( TOKEN ).clone());
399 //ACTION::PARAMS params;
400#if defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
401#define BOOST_PP_LOCAL_MACRO(n) value_print(~, n, paramreferences, ToCall->params.)
402#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
403#include BOOST_PP_LOCAL_ITERATE()
404#endif
405 Action::insertAction( ToCall, Action::NonInteractive);
406};
407
408void BOOST_PP_CAT( COMMAND, _stringargs)(
409#if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0)
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 ) {
415 ACTION * const ToCall = dynamic_cast<ACTION*>(ActionQueue::getInstance().getActionByName( TOKEN ).clone());
416 //ACTION::PARAMS params;
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. )
419#define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1)
420#include BOOST_PP_LOCAL_ITERATE()
421#endif
422 Action::insertAction( ToCall, Action::NonInteractive);
423};
424
425}
426
427// free up defines
428#undef paramvalids
429#undef paramtypes
430#undef paramtokens
431#undef paramreferences
432#undef paramdescriptions
433#undef paramdefaults
434#undef MAXPARAMTYPES
435#undef MAXPARAMDEFAULTS
436#undef statetypes
437#undef statereferences
438#undef MAXSTATETYPES
439#undef PARAM_DEFAULT
440
441#undef type2string
442#undef stringtype
443#undef initialiser_print
444#undef type_print
445#undef type_list
446#undef dialog_print
447#undef sequencer
448#undef valid_print
449#undef validcopy_print
450#undef value_print
451#undef valuetype_print
452
453#undef ACTION
454#undef COMMAND
455#undef PARAMS
456#undef STATE
457#undef INSTANCE
458
459#undef ACTIONNAME
460#undef CATEGORY
461#undef TOKEN
Note: See TracBrowser for help on using the repository browser.