From 97c63e0472cd1f4a20dd01dcb16b0e437b3e2290 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 4 Jan 2015 09:08:36 +0100 Subject: [PATCH] solution how to place and use the diff token constructors finally.... The problem is that the C++ "dependent types" defeat the typical DSL usage, where you define some helper function in a generic language setup class and mix this language in as superclass. This is, C++ requires us to refer explicitly to any dependent type, since, due to possible template specialisations, the parser can't know if a given symbol is a inherited type or a field. As a solution, we place the token constructor functors into a static struct "token", which allows to write e.g. token.insert(xyz) --- src/lib/diff/diff-language.hpp | 61 +++++++++++++++------ src/lib/diff/list-diff.hpp | 12 +++- tests/library/diff-list-generation-test.cpp | 18 +----- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/lib/diff/diff-language.hpp b/src/lib/diff/diff-language.hpp index f6510047b..74adeedb9 100644 --- a/src/lib/diff/diff-language.hpp +++ b/src/lib/diff/diff-language.hpp @@ -28,10 +28,10 @@ ** as a sequence of tokens of constant size. Using a linearised constant size ** representation allows to process diff generation and diff application in ** a pipeline, enabling maximum decoupling of sender and receiver. - ** Changes sent by diff serve as a generic meta-representation to keep separate - ** and different representations of the same logical structure in sync. This allows - ** for tight cooperation between strictly separated components, without the need - ** of a fixed, predefined and shared data structure. + ** Changes sent as diff message serve as a generic meta-representation to keep + ** separate and different representations of the same logical structure in sync. + ** Such an architecture allows for tight cooperation between strictly separated + ** components, without the need of a fixed, predefined and shared data structure. ** ** \par Basic Assumptions ** While the \em linearisation folds knowledge about the underlying data structure @@ -42,7 +42,7 @@ ** elements as values, which can be copied and moved cheaply. We include a copy of ** all content elements right within the tokens of the diff language, either to ** send the actual content data this way, or to serve as redundancy to verify - ** proper application of the changes at the diff receiver. + ** proper application of the changes at the diff receiver downstream. ** ** \par Solution Pattern ** The representation of this linearised diff language relies on a specialised form @@ -51,7 +51,7 @@ ** is provided as a private detail of the receiver, implemented as a concrete "Interpreter" ** (visitor) of the specific diff language flavour in use. Thus, our implementation relies ** on \em double-dispatch, based both on the type of the individual diff tokens and on the - ** concrete implementation of the Interpreter. The typical usage will employ an DiffApplicator, + ** concrete implementation of the Interpreter. Typical usage will employ a DiffApplicator, ** so the "interpretation" of the language means to apply it to a target data structure in ** this standard case. ** @@ -64,14 +64,14 @@ ** each token also bears a string id. And in addition, each token carries a single data ** content element as argument. The idea is, that the "verbs", the handler functions and ** the symbolic IDs are named alike (use the macro DiffStep_CTOR to define the tokens - ** in according to that rule). Such a combination of verb and data argument is called + ** in accordance to that rule). Such a combination of verb and data argument is called ** a DiffStep, since it represents a single step in the process of describing changes ** or transforming a data structure. For example, a list diff language can be built ** using the following four verbs: ** - pick-next ** - insert-new ** - delete-next - ** - push-back-next + ** - find reordered element ** ** @see list-diff-application.hpp ** @see diff-list-application-test.cpp @@ -150,23 +150,50 @@ namespace diff{ using HandlerFun = void (I::*) (E); + template + struct InterpreterScheme + { + using Interpreter = I; + using Val = typename I::Val; + using Handler = HandlerFun; + }; + + template class IP, typename E> + struct InterpreterScheme> + { + using Val = E; + using Interpreter = IP; + using Handler = HandlerFun; + }; + + template + struct InterpreterScheme> + { + using Val = E; + using Interpreter = I; + using Handler = HandlerFun; + }; + + - template - struct DiffStepBuilder; /** generator to produce specific language tokens */ - template - struct DiffStepBuilder> + template + struct DiffStepBuilder { - using Lang = DiffLanguage; + using Scheme = InterpreterScheme; + using Handler = typename Scheme::Handler; + using Val = typename Scheme::Val; + + using Lang = DiffLanguage; using Step = typename Lang::DiffStep; using Verb = typename Lang::DiffVerb; - HandlerFun handler; + Handler handler; Literal id; Step - operator() (E elm) const + operator() (Val elm) const { return { Verb(handler,id), elm }; } @@ -181,7 +208,7 @@ namespace diff{ * interface of the diff language. E.g. this consumer might apply the diff. */ template - inline DiffStepBuilder + inline DiffStepBuilder::Interpreter> diffTokenBuilder (H handlerFun, Literal id) { return { handlerFun, id }; @@ -197,7 +224,7 @@ namespace diff{ * type will be picked up from the given member function pointer. */ #define DiffStep_CTOR(_ID_) \ - const auto _ID_ = diffTokenBuilder (&Interpreter::_ID_, STRINGIFY(_ID_)); + const DiffStepBuilder _ID_ = diffTokenBuilder (&Interpreter::_ID_, STRINGIFY(_ID_)); diff --git a/src/lib/diff/list-diff.hpp b/src/lib/diff/list-diff.hpp index 7efc2f0d0..b10b73460 100644 --- a/src/lib/diff/list-diff.hpp +++ b/src/lib/diff/list-diff.hpp @@ -82,7 +82,17 @@ namespace diff{ }; template - using ListDiffLanguage = DiffLanguage, E>; + struct ListDiffLanguage + : DiffLanguage, E> + { + using Interpreter = ListDiffInterpreter; + + DiffStep_CTOR(ins); + DiffStep_CTOR(del); + DiffStep_CTOR(pick); + DiffStep_CTOR(find); + DiffStep_CTOR(skip); + }; diff --git a/tests/library/diff-list-generation-test.cpp b/tests/library/diff-list-generation-test.cpp index 7fbab6be0..4fd2c7673 100644 --- a/tests/library/diff-list-generation-test.cpp +++ b/tests/library/diff-list-generation-test.cpp @@ -59,20 +59,6 @@ namespace diff{ UNIMPLEMENTED("sequence size"); } }; - - template - struct Token - { - using Interpreter = typename ListDiffLanguage::Interpreter; - using HaHa = DiffStepBuilder>; - - HaHa skip = diffTokenBuilder (&Interpreter::skip, "skip"); - }; - - //DiffStep_CTOR(skip); - -// template -// typename Token::HaHa Token::skip = diffTokenBuilder (&Interpreter::skip, "skip"); @@ -107,7 +93,7 @@ namespace diff{ size_t oldHead_=0, newHead_=0; - static Token token; + static ListDiffLanguage token; DiffStep currentStep_{token.skip(Val())}; @@ -210,7 +196,7 @@ namespace diff{ }; template - Token::Val> DiffDetector::DiffFrame::token; + ListDiffLanguage::Val> DiffDetector::DiffFrame::token; //######################### namespace test{