sans the implementation of the index lookup table(s) The algorithm is KISS, a variant of insertion sort, i.e. worst time quadratic, but known to perform well on small data sets. The mere generation of the diff description is O(n log n), since we do not verify that we can "find" out of order elements. We leave this to the consumer of the diff, which at this point has to scan into the rest of the data sequence (leading to quadratic complexity)
129 lines
4 KiB
C++
129 lines
4 KiB
C++
/*
|
|
VERB-TOKEN.hpp - double dispatch based on DSL tokens
|
|
|
|
Copyright (C) Lumiera.org
|
|
2014, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of
|
|
the License, or (at your option) any later version.
|
|
|
|
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
/** @file verb-token.hpp
|
|
** Building blocks for a simple DSL using double dispatch to a handler function.
|
|
** Actually this is a specialised variation of the visitor pattern, where the
|
|
** "verb tokens" of the language are the domain objects accepting a "receiver"
|
|
** (visitor) to provide the concrete implementation function for each "verb".
|
|
**
|
|
** The intended usage is to set up a language comprised of several abstract actions ("verbs"),
|
|
** but to defer the concrete implementation to a specific set of handler functions, which
|
|
** is provided late, at application time. This way, we can send a sequence of verbs towards
|
|
** an unknown receiver, which supplies the actual meaning within the target context. In
|
|
** the end, there is a double-dispatch based both on the individual verb given and the
|
|
** concrete receiver, which needs to implement the interface used in the definition
|
|
** of the verb tokens. The handler functions defined within this interface may
|
|
** take additional arguments, which are passed through on application to
|
|
** the concrete receiver, e.g. `VERB_doit (receiver, arg1, arg2)`
|
|
** results in the invocation of \c receiver.doit(arg1,arg2)
|
|
**
|
|
** @see ...TODO
|
|
** @see VerbFunctionDispatch_test
|
|
**
|
|
*/
|
|
|
|
|
|
#ifndef LIB_VERB_TOKEN_H
|
|
#define LIB_VERB_TOKEN_H
|
|
|
|
|
|
#include "lib/symbol.hpp"
|
|
#include "lib/util.hpp"
|
|
|
|
#include <utility>
|
|
#include <string>
|
|
#include <array>
|
|
|
|
|
|
namespace lib {
|
|
|
|
using std::string;
|
|
|
|
|
|
/**
|
|
* Action token implemented by double dispatch to a handler function,
|
|
* as defined in the "receiver" interface (parameter \c REC).
|
|
* The token is typically part of a DSL and can be applied
|
|
* to a concrete receiver subclass.
|
|
* @remarks while the included ID Literal is mostly for diagnostics,
|
|
* it also serves as identity for comparisons. Conceptually what
|
|
* we want is to compare the function "offset", but this leads
|
|
* into relying on implementation defined behaviour.
|
|
* @note the #VERB macro simplifies definition of actual tokens
|
|
*/
|
|
template<class REC, class SIG>
|
|
class VerbToken;
|
|
|
|
template<class REC, class RET, typename... ARGS>
|
|
class VerbToken<REC, RET(ARGS...)>
|
|
{
|
|
typedef RET (REC::*Handler) (ARGS...);
|
|
|
|
Handler handler_;
|
|
Literal token_;
|
|
|
|
public:
|
|
RET
|
|
applyTo (REC& receiver, ARGS&&... args)
|
|
{
|
|
REQUIRE ("NIL" != token_);
|
|
return (receiver.*handler_)(std::forward<ARGS>(args)...);
|
|
}
|
|
|
|
operator string()
|
|
{
|
|
return string(token_);
|
|
}
|
|
|
|
VerbToken(Handler handlerFunction, Literal token)
|
|
: handler_(handlerFunction)
|
|
, token_(token)
|
|
{ }
|
|
|
|
VerbToken() : token_("NIL") { }
|
|
|
|
/* default copyable */
|
|
|
|
|
|
bool
|
|
operator== (VerbToken const& o) const ///< @remarks member pointers to virtual functions aren't comparable, for good reason
|
|
{
|
|
return token_ == o.token_;
|
|
}
|
|
|
|
bool
|
|
operator!= (VerbToken const& o) const
|
|
{
|
|
return token_ != o.token_;
|
|
}
|
|
};
|
|
|
|
#define VERB(RECEIVER, FUN) VERB_##FUN (&RECEIVER::FUN, STRINGIFY(FUN))
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace lib
|
|
#endif /*LIB_VERB_TOKEN_H*/
|