[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