[asterisk-scf-commits] asterisk-scf/release/ice.git branch "visitor-generators" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Mon Jan 3 15:13:25 UTC 2011
branch "visitor-generators" has been updated
via 8b166aa5de356c343b4a9d8c5666441c620a91df (commit)
via 84c3750d7e257e6b3db70b848c981584d9ce498f (commit)
from fa1f86fe0bf7a54b28ee87b1920adae595bf5186 (commit)
Summary of changes:
cpp/include/Slice/Parser.h | 27 ++++++++++++++--
cpp/include/Slice/VisitorPatternVisitor.h | 42 +++++++++++++++++++++++++
cpp/src/Slice/Parser.cpp | 27 +++++++++++++---
cpp/src/Slice/VisitorPatternVisitor.cpp | 48 +++++++++++++++++++++++++---
cpp/src/slice2cpp/Gen.cpp | 13 +++++++-
5 files changed, 142 insertions(+), 15 deletions(-)
- Log -----------------------------------------------------------------
commit 8b166aa5de356c343b4a9d8c5666441c620a91df
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Mon Jan 3 09:13:18 2011 -0600
Allow GeneratedOperations to be marked as non-mutating.
diff --git a/cpp/include/Slice/Parser.h b/cpp/include/Slice/Parser.h
index e5ba283..f2a72ef 100644
--- a/cpp/include/Slice/Parser.h
+++ b/cpp/include/Slice/Parser.h
@@ -617,7 +617,14 @@ class SLICE_API GeneratedOperation : virtual public Contained, virtual public Co
{
public:
+ enum Mode
+ {
+ Normal,
+ Nonmutating
+ };
+
TypePtr returnType() const;
+ Mode mode() const;
ParamDeclPtr createParamDecl(const std::string&, const TypePtr&, bool);
ParamDeclList parameters() const;
virtual ContainedType containedType() const;
@@ -632,10 +639,11 @@ public:
protected:
- GeneratedOperation(const ContainerPtr&, const std::string&, const TypePtr&, const StringList&, bool);
+ GeneratedOperation(const ContainerPtr&, const std::string&, const TypePtr&, const StringList&, bool, Mode);
friend class ClassDef;
TypePtr _returnType;
+ Mode _mode;
StringList _body;
bool _abstract;
};
@@ -657,8 +665,10 @@ public:
virtual void destroy();
OperationPtr createOperation(const std::string&, const TypePtr&, Operation::Mode = Operation::Normal);
- GeneratedOperationPtr createGeneratedOperation(const std::string&, const TypePtr&, const StringList&);
- GeneratedOperationPtr createGeneratedOperation(const std::string&, const TypePtr&);
+ GeneratedOperationPtr createGeneratedOperation(const std::string&, const TypePtr&, const StringList&,
+ GeneratedOperation::Mode = GeneratedOperation::Normal);
+ GeneratedOperationPtr createGeneratedOperation(const std::string&, const TypePtr&,
+ GeneratedOperation::Mode = GeneratedOperation::Normal);
DataMemberPtr createDataMember(const std::string&, const TypePtr&, const SyntaxTreeBasePtr&, const std::string&,
const std::string&);
ClassDeclPtr declaration() const;
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index d1e6694..aba72c9 100644
--- a/cpp/src/Slice/Parser.cpp
+++ b/cpp/src/Slice/Parser.cpp
@@ -2958,7 +2958,8 @@ Slice::ClassDef::createOperation(const string& name,
GeneratedOperationPtr
Slice::ClassDef::createGeneratedOperation(const string& name,
const TypePtr& returnType,
- const StringList& body)
+ const StringList& body,
+ GeneratedOperation::Mode mode)
{
checkIdentifier(name);
@@ -3050,14 +3051,15 @@ Slice::ClassDef::createGeneratedOperation(const string& name,
#endif
_hasGeneratedOperations = true;
- GeneratedOperationPtr gop = new GeneratedOperation(this, name, returnType, body, false);
+ GeneratedOperationPtr gop = new GeneratedOperation(this, name, returnType, body, false, mode);
_contents.push_back(gop);
return gop;
}
GeneratedOperationPtr
Slice::ClassDef::createGeneratedOperation(const string& name,
- const TypePtr& returnType)
+ const TypePtr& returnType,
+ GeneratedOperation::Mode mode)
{
checkIdentifier(name);
@@ -3149,7 +3151,7 @@ Slice::ClassDef::createGeneratedOperation(const string& name,
#endif
_hasGeneratedOperations = true;
- GeneratedOperationPtr gop = new GeneratedOperation(this, name, returnType, StringList(), false);
+ GeneratedOperationPtr gop = new GeneratedOperation(this, name, returnType, StringList(), false, mode);
_contents.push_back(gop);
return gop;
}
@@ -5195,6 +5197,12 @@ Slice::GeneratedOperation::returnType() const
return _returnType;
}
+GeneratedOperation::Mode
+Slice::GeneratedOperation::mode() const
+{
+ return _mode;
+}
+
ParamDeclPtr
Slice::GeneratedOperation::createParamDecl(const string& name, const TypePtr& type, bool isOutParam)
{
@@ -5403,11 +5411,13 @@ Slice::GeneratedOperation::GeneratedOperation(const ContainerPtr& container,
const string& name,
const TypePtr& returnType,
const StringList& body,
- bool abstract) :
+ bool abstract,
+ Mode mode) :
SyntaxTreeBase(container->unit()),
Contained(container, name),
Container(container->unit()),
_returnType(returnType),
+ _mode(mode),
_body(body),
_abstract(abstract)
{
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index b2b34b6..770fe87 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -4890,7 +4890,7 @@ Slice::Gen::ObjectVisitor::visitGeneratedOperation(const GeneratedOperationPtr&
params += ')';
paramsDecl += ')';
- bool isConst = false; //(p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const");
+ bool isConst = (p->mode() == GeneratedOperation::Nonmutating);
string deprecateSymbol = getDeprecateSymbol(p, cl);
commit 84c3750d7e257e6b3db70b848c981584d9ce498f
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Mon Jan 3 08:54:45 2011 -0600
Make this branch more commentatious.
As usual, writing documentation exposed a code improvement possibility.
diff --git a/cpp/include/Slice/Parser.h b/cpp/include/Slice/Parser.h
index d7f957c..e5ba283 100644
--- a/cpp/include/Slice/Parser.h
+++ b/cpp/include/Slice/Parser.h
@@ -600,6 +600,17 @@ protected:
// ----------------------------------------------------------------------
// GeneratedOperation
+//
+// Note: These are operations generated by translator code, not defined
+// in the Slice source file. In addition, they are *local* operations
+// on the class, not part of the remote interface to the class if it
+// has one.
+//
+// GeneratedOperations can be either abstract (no body specified) or
+// concrete (body specified). If the body is specified, it will be a
+// StringList, and each string in the list will be emitted into the
+// function body in a manner specific to the language the translator
+// writes.
// ----------------------------------------------------------------------
class SLICE_API GeneratedOperation : virtual public Contained, virtual public Container
diff --git a/cpp/include/Slice/VisitorPatternVisitor.h b/cpp/include/Slice/VisitorPatternVisitor.h
index 6251b06..45b4b63 100644
--- a/cpp/include/Slice/VisitorPatternVisitor.h
+++ b/cpp/include/Slice/VisitorPatternVisitor.h
@@ -5,16 +5,58 @@
namespace Slice
{
+// This Visitor iterates over the parse tree looking for 'visitor'
+// metadata directives; after validation, it uses these directives
+// to generate operations in both the visiting and visited classes.
+// The 'visitor' metadata is inherited into classes that extend
+// the classes where the directive appears.
+//
+// In the visited classes, an operation called 'visit' is generated
+// which accepts a visitor object as a parameter, and calls a
+// visit<FOO> operation on that object, where FOO is the name of the
+// visited class. If the visited class has been marked to be visited
+// by a derived visitor class, then the 'visit' operation will cast
+// the received visitor object to that derived type so it can call
+// the visit<FOO> operation (which will only exist in the derived
+// visitor class).
+//
+// In the visiting classes, an operation is generated for each class
+// that has been marked with that class' name as its visitor (or
+// has inherited that marking). The operation's name is 'visit<FOO>',
+// where FOO is the name of the class to be visited. The operation
+// receives the visited class object as a parameter.
+
class SLICE_API VisitorPatternVisitor : public ParserVisitor
{
public:
virtual bool visitClassDefStart(const ClassDefPtr&);
protected:
+ // This function generates the function body for the 'visit' functions
+ // in the visited classes. Its parameters are:
+ // 1 - the name assigned to the parameter this function will receive (the visitor object)
+ // 2 - the base visitor class (the parameter's type)
+ // 3 - the derived visitor class (where the visit<FOO> operation is defined)
+ // 4 - the name of the operation that should be called on the visitor
+ //
+ // The function returns a StringList; each string in the list will be placed into the
+ // function body in a language-appropriate manner.
virtual StringList generateVisitFunctionBody(const std::string&, const ClassDefPtr&, const ClassDefPtr&, const std::string&) = 0;
private:
+ // This map contains the list of classes known to be visitors;
+ // the key is the fully-scoped named of the class, and the value
+ // is a pointer to the class definition.
std::map<std::string, ClassDefPtr> _visitorClasses;
+ // This map contains the list of base classes that can be visited;
+ // the key is the fully scoped named of the class, and the value
+ // is a pair consisting of pointers to the class definitions for
+ // the visiting classes. The first element is the base visitor class,
+ // which defines the type of the parameter to the 'visit' operation
+ // generated in the visited class. The second element is the derived
+ // visitor class (which might be the same as the base visitor class),
+ // which defines the type the parameter must be cast to in order to
+ // invoke the visit<FOO> operation on the visitor as described above.
std::map<std::string, std::pair<ClassDefPtr, ClassDefPtr> > _visitableBases;
};
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index b7360ed..d1e6694 100644
--- a/cpp/src/Slice/Parser.cpp
+++ b/cpp/src/Slice/Parser.cpp
@@ -3499,6 +3499,13 @@ Slice::ClassDef::isAbstract() const
{
return true;
}
+ if(GeneratedOperationPtr gop = GeneratedOperationPtr::dynamicCast(*p))
+ {
+ if(gop->isAbstract())
+ {
+ return true;
+ }
+ }
}
return false;
diff --git a/cpp/src/Slice/VisitorPatternVisitor.cpp b/cpp/src/Slice/VisitorPatternVisitor.cpp
index 82ec11f..67faf73 100644
--- a/cpp/src/Slice/VisitorPatternVisitor.cpp
+++ b/cpp/src/Slice/VisitorPatternVisitor.cpp
@@ -5,7 +5,11 @@
using namespace std;
using namespace Slice;
-static ClassDefPtr
+// This function attempts to locate a base of the specified class that has been marked
+// with the 'visitor:<XYZ>' metadata directive. If it finds one, sets two output
+// parameters to indicate the base visitor class and derived visitor class that this
+// visitable class should support.
+static bool
findVisitableBase(const map<string, pair<ClassDefPtr, ClassDefPtr> >& visitableBases,
const ClassDefPtr& p, ClassDefPtr& baseVisitor,
ClassDefPtr& derivedVisitor)
@@ -29,6 +33,9 @@ Slice::VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
{
ostringstream ostr;
+ // First, search for classes tagged with the 'visitor' or 'visitor:XYZ'
+ // metadata directives. If they are found, validate the conditions they
+ // are used in and report warnings if the conditions are not appropriate.
StringList metaData = p->getMetaData();
for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); q++)
{
@@ -50,6 +57,7 @@ Slice::VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
}
else
{
+ // Remember this class as a visiting class.
_visitorClasses[p->scoped()] = p;
return false;
}
@@ -72,19 +80,36 @@ Slice::VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
}
else
{
+ // Attempt to find the specified visiting class in the list of known
+ // visiting classes.
const string visitor = (*q).substr(8);
map<string, ClassDefPtr>::const_iterator it = _visitorClasses.find(visitor);
if(it != _visitorClasses.end())
{
+ // Initially, assume the base visitor class will be the specified class.
ClassDefPtr baseVisitor = it->second, derivedVisitor;
+ // Note that the return value of this function is ignored; because this
+ // class has been directly marked with the 'visitor' metadata, we already
+ // know it must support a visitor; the function is being called
+ // to determine if there is a different base visitor class that must be
+ // supported.
findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor);
+ // We know our derived visitor class is the one specified in the directive.
derivedVisitor = it->second;
+ // Remember this class as a visitable base, so that any classes that extend
+ // it will automatically be visitable as well.
_visitableBases[p->scoped()] = make_pair(baseVisitor, derivedVisitor);
+ // There is no need to actually generate operations into the visitor
+ // class if it was defined in an include file, since the translator
+ // won't actually produce output for the include file.
if(derivedVisitor->includeLevel() == 0)
{
GeneratedOperationPtr gop = derivedVisitor->createGeneratedOperation("visit" + p->name(), 0, StringList());
gop->createParamDecl("item", p->declaration(), false);
}
+ // There is no need to actually generate operations into the visited
+ // class if it was defined in an include file, since the translator
+ // won't actually produce output for the include file.
if(p->includeLevel() == 0)
{
GeneratedOperationPtr gop = p->createGeneratedOperation("visit", 0,
@@ -105,11 +130,19 @@ Slice::VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
}
}
- if(!p->isInterface() && !p->isAbstract())
+ // Only classes are supported by 'visitor' metadata inheritance.
+ if(p->isInterface())
{
- ClassDefPtr visitableBase, baseVisitor, derivedVisitor;
- visitableBase = findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor);
- if(visitableBase)
+ return false;
+ }
+
+ // For concrete classes that aren't marked with the 'visitor' metadata,
+ // try to locate a visitable base class that they extend; if one is found,
+ // generate the appropriate operations to support the visitable class.
+ if(!p->isAbstract())
+ {
+ ClassDefPtr baseVisitor, derivedVisitor;
+ if (findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor))
{
if(derivedVisitor->includeLevel() == 0)
{
@@ -126,7 +159,10 @@ Slice::VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
return false;
}
- if(!p->isInterface())
+ // For abstract classes that aren't marked with 'visitor' metadata,
+ // try to locate a visiting base class that they extend; if one is found,
+ // remember the derived class as a visiting class.
+ if(p->isAbstract())
{
ClassList bases = p->allBases();
for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index 7f9a9c6..b2b34b6 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -565,6 +565,8 @@ Slice::Gen::writeExtraHeaders(IceUtilInternal::Output& out)
}
}
+// This function is fairly straightforward; see VisitorPatternVisitor.h for a description
+// of its parameters and return value.
StringList
Slice::Gen::CPPVisitorPatternVisitor::generateVisitFunctionBody(const string& paramName,
const ClassDefPtr& baseVisitor,
@@ -576,6 +578,10 @@ Slice::Gen::CPPVisitorPatternVisitor::generateVisitFunctionBody(const string& pa
if(baseVisitor != derivedVisitor)
{
+ // The visitor object will be passed by value, which for C++ means it will be an
+ // IceUtil::Handle-derived shared pointer. Since that is the case, we can use
+ // the dynamicCast() operation defined by IceUtil::Handle to convert the pointer
+ // into a derived visitor class pointer.
ostr << derivedVisitor->scoped() << "Ptr::dynamicCast(" << paramName << ")";
}
else
@@ -4830,6 +4836,8 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p)
}
}
+// This is just a cut-down version of visitOperation, since this only
+// has to support local operations (no proxies, no AMI/AMD, etc.)
void
Slice::Gen::ObjectVisitor::visitGeneratedOperation(const GeneratedOperationPtr& p)
{
@@ -4892,6 +4900,8 @@ Slice::Gen::ObjectVisitor::visitGeneratedOperation(const GeneratedOperationPtr&
if(!p->isAbstract())
{
+ // The operation has a body, so just leave the declaration as virtual
+ // and place the body in the code file.
H << ";";
StringList body = p->body();
@@ -4905,6 +4915,7 @@ Slice::Gen::ObjectVisitor::visitGeneratedOperation(const GeneratedOperationPtr&
}
else
{
+ // The operation is abstract, so mark it as 'pure virtual'.
H << " = 0;";
}
}
-----------------------------------------------------------------------
--
asterisk-scf/release/ice.git
More information about the asterisk-scf-commits
mailing list