[asterisk-scf-commits] asterisk-scf/release/ice.git branch "visitor-generators" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Thu Dec 30 22:53:33 UTC 2010


branch "visitor-generators" has been created
        at  afc50c7afdd97dd35aac69569927e8778921b69b (commit)

- Log -----------------------------------------------------------------
commit afc50c7afdd97dd35aac69569927e8778921b69b
Author: Kevin P. Fleming <kpfleming at digium.com>
Date:   Thu Dec 30 13:17:11 2010 -0600

    Add support for code-generated operations attached to classes.
    Add support for 'visitor' metadata to automatically generate
    operations required for Visitor pattern to be employed on
    classes. Current implementation is only for C++, but it will
    be very easy to extend to the other supported languages.

diff --git a/cpp/include/Slice/Parser.h b/cpp/include/Slice/Parser.h
index ad390b1..8087615 100644
--- a/cpp/include/Slice/Parser.h
+++ b/cpp/include/Slice/Parser.h
@@ -83,6 +83,7 @@ class Proxy;
 class Exception;
 class Struct;
 class Operation;
+class GeneratedOperation;
 class ParamDecl;
 class DataMember;
 class Sequence;
@@ -109,6 +110,7 @@ typedef ::IceUtil::Handle<Proxy> ProxyPtr;
 typedef ::IceUtil::Handle<Exception> ExceptionPtr;
 typedef ::IceUtil::Handle<Struct> StructPtr;
 typedef ::IceUtil::Handle<Operation> OperationPtr;
+typedef ::IceUtil::Handle<GeneratedOperation> GeneratedOperationPtr;
 typedef ::IceUtil::Handle<ParamDecl> ParamDeclPtr;
 typedef ::IceUtil::Handle<DataMember> DataMemberPtr;
 typedef ::IceUtil::Handle<Sequence> SequencePtr;
@@ -135,6 +137,7 @@ typedef std::list<DictionaryPtr> DictionaryList;
 typedef std::list<EnumPtr> EnumList;
 typedef std::list<ConstPtr> ConstList;
 typedef std::list<OperationPtr> OperationList;
+typedef std::list<GeneratedOperationPtr> GeneratedOperationList;
 typedef std::list<DataMemberPtr> DataMemberList;
 typedef std::list<ParamDeclPtr> ParamDeclList;
 typedef std::list<EnumeratorPtr> EnumeratorList;
@@ -199,6 +202,7 @@ public:
     virtual bool visitStructStart(const StructPtr&) { return true; }
     virtual void visitStructEnd(const StructPtr&) { }
     virtual void visitOperation(const OperationPtr&) { }
+    virtual void visitGeneratedOperation(const GeneratedOperationPtr&) { }
     virtual void visitParamDecl(const ParamDeclPtr&) { }
     virtual void visitDataMember(const DataMemberPtr&) { }
     virtual void visitSequence(const SequencePtr&) { }
@@ -365,6 +369,7 @@ public:
         ContainedTypeException,
         ContainedTypeStruct,
         ContainedTypeOperation,
+	ContainedTypeGeneratedOperation,
         ContainedTypeParamDecl,
         ContainedTypeDataMember,
         ContainedTypeConstant
@@ -594,6 +599,35 @@ protected:
 };
 
 // ----------------------------------------------------------------------
+// GeneratedOperation
+// ----------------------------------------------------------------------
+
+class SLICE_API GeneratedOperation : virtual public Contained, virtual public Container
+{
+public:
+    
+    TypePtr returnType() const;
+    ParamDeclPtr createParamDecl(const std::string&, const TypePtr&, bool);
+    ParamDeclList parameters() const;
+    virtual ContainedType containedType() const;
+    virtual bool uses(const ContainedPtr&) const;
+    bool sendsClasses() const;
+    bool returnsClasses() const;
+    bool returnsData() const;
+    StringList body() const;
+    virtual std::string kindOf() const;
+    virtual void visit(ParserVisitor*, bool);
+
+protected:
+
+    GeneratedOperation(const ContainerPtr&, const std::string&, const TypePtr&, const StringList&);
+    friend class ClassDef;
+
+    TypePtr _returnType;
+    StringList _body;
+};
+
+// ----------------------------------------------------------------------
 // ClassDef
 // ----------------------------------------------------------------------
 
@@ -610,6 +644,7 @@ public:
 
     virtual void destroy();
     OperationPtr createOperation(const std::string&, const TypePtr&, Operation::Mode = Operation::Normal);
+    GeneratedOperationPtr createGeneratedOperation(const std::string&, const TypePtr&, const StringList&);
     DataMemberPtr createDataMember(const std::string&, const TypePtr&, const SyntaxTreeBasePtr&, const std::string&,
                                    const std::string&);
     ClassDeclPtr declaration() const;
@@ -617,6 +652,7 @@ public:
     ClassList allBases() const;
     OperationList operations() const;
     OperationList allOperations() const;
+    GeneratedOperationList localOperations() const;
     DataMemberList dataMembers() const;
     DataMemberList allDataMembers() const;
     DataMemberList classDataMembers() const;
@@ -628,6 +664,7 @@ public:
     virtual bool isLocal() const;
     bool hasDataMembers() const;
     bool hasOperations() const;
+    bool hasGeneratedOperations() const;
     bool hasDefaultValues() const;
     virtual ContainedType containedType() const;
     virtual bool uses(const ContainedPtr&) const;
@@ -643,6 +680,7 @@ protected:
     bool _interface;
     bool _hasDataMembers;
     bool _hasOperations;
+    bool _hasGeneratedOperations;
     ClassList _bases;
     bool _local;
 };
@@ -895,6 +933,7 @@ protected:
 
     ParamDecl(const ContainerPtr&, const std::string&, const TypePtr&, bool isOutParam);
     friend class Operation;
+    friend class GeneratedOperation;
 
     TypePtr _type;
     bool _isOutParam;
diff --git a/cpp/include/Slice/VisitorPatternVisitor.h b/cpp/include/Slice/VisitorPatternVisitor.h
new file mode 100644
index 0000000..f8525b9
--- /dev/null
+++ b/cpp/include/Slice/VisitorPatternVisitor.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <Slice/Parser.h>
+
+namespace Slice
+{
+
+class SLICE_API VisitorPatternVisitor : public ParserVisitor
+{
+public:
+    virtual bool visitClassDefStart(const ClassDefPtr&);
+
+protected:
+    virtual StringList generateVisitFunctionBody(const std::string&, const ClassDefPtr&, const ClassDefPtr&, const std::string&) = 0;
+
+private:
+    std::map<std::string, ClassDefPtr> _visitorInterfaces;
+    std::map<std::string, std::pair<ClassDefPtr, ClassDefPtr> > _visitableBases;
+};
+
+}
diff --git a/cpp/src/Slice/Makefile b/cpp/src/Slice/Makefile
index d6a010c..a278595 100644
--- a/cpp/src/Slice/Makefile
+++ b/cpp/src/Slice/Makefile
@@ -30,7 +30,8 @@ OBJS		= Scanner.o \
 		  Util.o \
 		  FileTracker.o \
 		  MD5.o \
-		  MD5I.o
+		  MD5I.o \
+		  VisitorPatternVisitor.o
 
 SRCS		= $(OBJS:.o=.cpp)
 
diff --git a/cpp/src/Slice/Makefile.mak b/cpp/src/Slice/Makefile.mak
index b370fb1..e97d3ee 100644
--- a/cpp/src/Slice/Makefile.mak
+++ b/cpp/src/Slice/Makefile.mak
@@ -29,7 +29,8 @@ OBJS		= Scanner.obj \
 		  Util.obj \
 		  FileTracker.obj \
 		  MD5.obj \
-		  MD5I.obj
+		  MD5I.obj \
+		  VisitorPatternVisitor.obj
 
 SRCS		= $(OBJS:.obj=.cpp)
 
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index 5711c7b..56e07ac 100644
--- a/cpp/src/Slice/Parser.cpp
+++ b/cpp/src/Slice/Parser.cpp
@@ -2955,6 +2955,106 @@ Slice::ClassDef::createOperation(const string& name,
     return op;
 }
 
+GeneratedOperationPtr
+Slice::ClassDef::createGeneratedOperation(const string& name,
+					  const TypePtr& returnType,
+					  const StringList& body)
+{
+    checkIdentifier(name);
+
+#if 0
+    ContainedList matches = _unit->findContents(thisScope() + name);
+    if(!matches.empty())
+    {
+        OperationPtr p = OperationPtr::dynamicCast(matches.front());
+        if(p)
+        {
+            if(_unit->ignRedefs())
+            {
+                p->updateIncludeLevel();
+                return p;
+            }
+        }
+        if(matches.front()->name() != name)
+        {
+            string msg = "operation `" + name + "' differs only in capitalization from ";
+            msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'";
+            _unit->error(msg);
+        }
+        string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name();
+        msg += "' as operation `" + name + "'";
+        _unit->error(msg);
+        return 0;
+    }
+#endif
+
+    //
+    // Check whether enclosing interface/class has the same name.
+    //
+    if(name == this->name())
+    {
+        string msg = isInterface() ? "interface" : "class";
+        msg += " name `" + name + "' cannot be used as operation name";
+        _unit->error(msg);
+        return 0;
+    }
+
+    string newName = IceUtilInternal::toLower(name);
+    string thisName = IceUtilInternal::toLower(this->name());
+    if(newName == thisName)
+    {
+        string msg = "operation `" + name + "' differs only in capitalization from enclosing ";
+        msg += isInterface() ? "interface" : "class";
+        msg += " name `" + this->name() + "'";
+        _unit->error(msg);
+    }
+
+#if 0
+    //
+    // Check whether any bases have defined something with the same name already.
+    //
+    for(ClassList::const_iterator p = _bases.begin(); p != _bases.end(); ++p)
+    {
+        ContainedList cl;
+        OperationList ol = (*p)->allOperations();
+        copy(ol.begin(), ol.end(), back_inserter(cl));
+        DataMemberList dml = (*p)->allDataMembers();
+        copy(dml.begin(), dml.end(), back_inserter(cl));
+        for(ContainedList::const_iterator q = cl.begin(); q != cl.end(); ++q)
+        {
+            if((*q)->name() == name)
+            {
+                string msg = "operation `" + name;
+                msg += "' is already defined as a";
+                static const string vowels = "aeiou";
+                string kindOf = (*q)->kindOf();
+                if(vowels.find_first_of(kindOf[0]) != string::npos)
+                {
+                    msg += "n";
+                }
+                msg += " " + kindOf + " in a base interface or class";
+                _unit->error(msg);
+                return 0;
+            }
+
+            string baseName = IceUtilInternal::toLower((*q)->name());
+            string newName = IceUtilInternal::toLower(name);
+            if(baseName == newName)
+            {
+                string msg = "operation `" + name + "' differs only in capitalization from " + (*q)->kindOf();
+                msg += " `" + (*q)->name() + "', which is defined in a base interface or class";
+                _unit->error(msg);
+            }
+        }
+    }
+#endif
+
+    _hasGeneratedOperations = true;
+    GeneratedOperationPtr gop = new GeneratedOperation(this, name, returnType, body);
+    _contents.push_back(gop);
+    return gop;
+}
+
 DataMemberPtr
 Slice::ClassDef::createDataMember(const string& name, const TypePtr& type, const SyntaxTreeBasePtr& defaultLiteralType,
                                   const string& defaultValue, const string& defaultLiteral)
@@ -4965,6 +5065,246 @@ Slice::Operation::Operation(const ContainerPtr& container,
 }
 
 // ----------------------------------------------------------------------
+// GeneratedOperation
+// ----------------------------------------------------------------------
+
+TypePtr
+Slice::GeneratedOperation::returnType() const
+{
+    return _returnType;
+}
+
+ParamDeclPtr
+Slice::GeneratedOperation::createParamDecl(const string& name, const TypePtr& type, bool isOutParam)
+{
+    checkIdentifier(name);
+
+    if(_unit->profile() == IceE)
+    {
+        ClassDefPtr cl = ClassDefPtr::dynamicCast(this->container());
+        assert(cl);
+        if(!cl->isLocal())
+        {
+            BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+            if((builtin && builtin->kind() == Builtin::KindObject))
+            {
+                string msg = "Object `" + name + "' cannot be passed by value.";
+                _unit->error(msg);
+                return 0;
+            }
+            ClassDeclPtr classDecl =  ClassDeclPtr::dynamicCast(type);
+            if(classDecl != 0 && !classDecl->isLocal())
+            {
+                string msg = "Object `" + name + "' cannot be passed by value.";
+                _unit->error(msg);
+                return 0;
+            }
+        }
+    }
+
+    ContainedList matches = _unit->findContents(thisScope() + name);
+    if(!matches.empty())
+    {
+        ParamDeclPtr p = ParamDeclPtr::dynamicCast(matches.front());
+        if(p)
+        {
+            if(_unit->ignRedefs())
+            {
+                p->updateIncludeLevel();
+                return p;
+            }
+        }
+        if(matches.front()->name() != name)
+        {
+            string msg = "parameter `" + name + "' differs only in capitalization from ";
+            msg += "parameter `" + matches.front()->name() + "'";
+            _unit->error(msg);
+        }
+        else
+        {
+            string msg = "redefinition of parameter `" + name + "'";
+            _unit->error(msg);
+            return 0;
+        }
+    }
+
+    //
+    // Check whether enclosing operation has the same name.
+    //
+    if(name == this->name())
+    {
+        string msg = "operation name `";
+        msg += name;
+        msg += "' cannot be used as parameter name";
+        _unit->error(msg);
+        return 0;
+    }
+
+    string newName = IceUtilInternal::toLower(name);
+    string thisName = IceUtilInternal::toLower(this->name());
+    if(newName == thisName)
+    {
+        string msg = "parameter `" + name + "' differs only in capitalization from operation name `";
+        msg += this->name() + "'";
+        _unit->error(msg);
+    }
+
+    //
+    // Check that in parameters don't follow out parameters.
+    //
+    if(!_contents.empty())
+    {
+        ParamDeclPtr p = ParamDeclPtr::dynamicCast(_contents.back());
+        assert(p);
+        if(p->isOutParam() && !isOutParam)
+        {
+            _unit->error("`" + name + "': in parameters cannot follow out parameters");
+        }
+    }
+
+    ParamDeclPtr p = new ParamDecl(this, name, type, isOutParam);
+    _contents.push_back(p);
+    return p;
+}
+
+ParamDeclList
+Slice::GeneratedOperation::parameters() const
+{
+    ParamDeclList result;
+    for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p)
+    {
+        ParamDeclPtr q = ParamDeclPtr::dynamicCast(*p);
+        if(q)
+        {
+            result.push_back(q);
+        }
+    }
+    return result;
+}
+
+Contained::ContainedType
+Slice::GeneratedOperation::containedType() const
+{
+    return ContainedTypeGeneratedOperation;
+}
+
+bool
+Slice::GeneratedOperation::uses(const ContainedPtr& contained) const
+{
+    {
+        ContainedPtr contained2 = ContainedPtr::dynamicCast(_returnType);
+        if(contained2 && contained2 == contained)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool
+Slice::GeneratedOperation::sendsClasses() const
+{
+    ParamDeclList pdl = parameters();
+    for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i)
+    {
+        if(!(*i)->isOutParam() && (*i)->type()->usesClasses())
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+Slice::GeneratedOperation::returnsClasses() const
+{
+    TypePtr t = returnType();
+    if(t && t->usesClasses())
+    {
+        return true;
+    }
+    ParamDeclList pdl = parameters();
+    for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i)
+    {
+        if((*i)->isOutParam() && (*i)->type()->usesClasses())
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+Slice::GeneratedOperation::returnsData() const
+{
+    TypePtr t = returnType();
+    if(t)
+    {
+        return true;
+    }
+    ParamDeclList pdl = parameters();
+    for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i)
+    {
+        if((*i)->isOutParam())
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+StringList
+Slice::GeneratedOperation::body() const
+{
+	return _body;
+}
+
+string
+Slice::GeneratedOperation::kindOf() const
+{
+    return "generated operation";
+}
+
+void
+Slice::GeneratedOperation::visit(ParserVisitor* visitor, bool)
+{
+    visitor->visitGeneratedOperation(this);
+}
+
+Slice::GeneratedOperation::GeneratedOperation(const ContainerPtr& container,
+					      const string& name,
+					      const TypePtr& returnType,
+					      const StringList& body) :
+    SyntaxTreeBase(container->unit()),
+    Contained(container, name),
+    Container(container->unit()),
+    _returnType(returnType),
+    _body(body)
+{
+    if(_unit->profile() == IceE)
+    {
+        ClassDefPtr cl = ClassDefPtr::dynamicCast(this->container());
+        assert(cl);
+        if(!cl->isLocal())
+        {
+            BuiltinPtr builtin = BuiltinPtr::dynamicCast(returnType);
+            if((builtin && builtin->kind() == Builtin::KindObject))
+            {
+                string msg = "Method `" + name + "' cannot return an object by value.";
+                _unit->error(msg);
+            }
+            ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(returnType);
+            if(classDecl != 0 && !classDecl->isLocal())
+            {
+                string msg = "Method `" + name + "' cannot return an object by value.";
+                _unit->error(msg);
+            }
+        }
+    }
+}
+
+// ----------------------------------------------------------------------
 // ParamDecl
 // ----------------------------------------------------------------------
 
diff --git a/cpp/src/Slice/VisitorPatternVisitor.cpp b/cpp/src/Slice/VisitorPatternVisitor.cpp
new file mode 100644
index 0000000..eb0a533
--- /dev/null
+++ b/cpp/src/Slice/VisitorPatternVisitor.cpp
@@ -0,0 +1,126 @@
+#include <Slice/Parser.h>
+#include <Slice/VisitorPatternVisitor.h>
+#include <Slice/Util.h>
+
+using namespace std;
+using namespace Slice;
+
+static ClassDefPtr
+findVisitableBase(const map<string, pair<ClassDefPtr, ClassDefPtr> >& visitableBases,
+		  const ClassDefPtr& p, ClassDefPtr& baseVisitor,
+		  ClassDefPtr& derivedVisitor)
+{
+	ClassList bases = p->allBases();
+	for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
+	{
+		map<string, pair<ClassDefPtr, ClassDefPtr> >::const_iterator it = visitableBases.find((*q)->scoped());
+		if(it != visitableBases.end())
+		{
+			baseVisitor = it->second.first;
+			derivedVisitor = it->second.second;
+			return *q;
+		}
+	}
+	return 0;
+}
+
+bool
+Slice::VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+	ostringstream ostr;
+
+	StringList metaData = p->getMetaData();
+	for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); q++)
+	{
+		if(*q == "visitor")
+		{
+			if(!p->isLocal())
+			{
+				ostr << "ignoring invalid metadata `visitor`: directive can only be applied "
+				     << "to local interfaces but `" << p->name() << "` is not local";
+				emitWarning(p->file(), p->line(), ostr.str());
+			}
+			else if(p->isInterface())
+			{
+				ostr << "ignoring invalid metadata `visitor`: directive can only be applied "
+				     << "to local classes but `" << p->name() << "` is an interface";
+				emitWarning(p->file(), p->line(), ostr.str());
+			}
+			else
+			{
+				_visitorInterfaces[p->scoped()] = p;
+				return false;
+			}
+		}
+		else if(q->find("visitor:", 0) == 0)
+		{
+			if(p->isInterface())
+			{
+				ostr << "ignoring invalid `" << *q << "` metadata: directive can only be applied "
+				     << "to classes, but `" << p->name() << "` is an interface";
+				emitWarning(p->file(), p->line(), ostr.str());
+			}
+			else if(p->isAbstract())
+			{
+				ostr << "ignoring invalid `" << *q << "` metadata: directive can only be applied "
+				     << "to concrete classes, but `" << p->name() << "` is abstract";
+				emitWarning(p->file(), p->line(), ostr.str());
+			}
+			else
+			{
+				const string visitor = (*q).substr(8);
+				map<string, ClassDefPtr>::const_iterator it = _visitorInterfaces.find(visitor);
+				if(it != _visitorInterfaces.end())
+				{
+					ClassDefPtr baseVisitor = it->second, derivedVisitor;
+					findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor);
+					_visitableBases[p->scoped()] = make_pair(baseVisitor, it->second);
+					GeneratedOperationPtr gop = it->second->createGeneratedOperation("visit" + p->name(), 0, StringList());
+					gop->createParamDecl("item", p->declaration(), false);
+					gop = p->createGeneratedOperation("visit", 0,
+									  generateVisitFunctionBody("visitor", baseVisitor, it->second, "visit" + p->name()));
+					gop->createParamDecl("visitor", baseVisitor->declaration(), false);
+					return false;
+				}
+				else
+				{
+					ostr << "ignoring invalid `" << *q << "` metadata: directive specified on "
+					     << "class `" << p->name() << "` but specified interface '" << visitor << "` was "
+					     << "not marked with `visitor` metadata directive";
+					emitWarning(p->file(), p->line(), ostr.str());
+				}
+			}
+		}
+	}
+
+	if(!p->isInterface() && !p->isAbstract())
+	{
+		ClassDefPtr visitableBase, baseVisitor, derivedVisitor;
+		visitableBase = findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor);
+		if(visitableBase)
+		{
+			GeneratedOperationPtr gop = derivedVisitor->createGeneratedOperation("visit" + p->name(), 0, StringList());
+			gop->createParamDecl("item", p->declaration(), false);
+			gop = p->createGeneratedOperation("visit", 0,
+							  generateVisitFunctionBody("visitor", baseVisitor, derivedVisitor, "visit" + p->name()));
+			gop->createParamDecl("visitor", baseVisitor->declaration(), false);
+			return false;
+		}
+	}
+
+	if(p->isInterface())
+	{
+		ClassList bases = p->allBases();
+		for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
+		{
+			map<string, ClassDefPtr>::const_iterator it = _visitorInterfaces.find((*q)->scoped());
+			if(it != _visitorInterfaces.end())
+			{
+				_visitorInterfaces[p->scoped()] = p;
+				return false;
+			}
+		}
+	}
+
+	return false;
+}
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index 9442aea..ff7680f 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -10,6 +10,7 @@
 #include <IceUtil/DisableWarnings.h>
 #include <Gen.h>
 #include <Slice/Util.h>
+#include <Slice/VisitorPatternVisitor.h>
 #include <Slice/CPlusPlusUtil.h>
 #include <IceUtil/Functional.h>
 #include <IceUtil/Iterator.h>
@@ -171,6 +172,9 @@ void
 Slice::Gen::generate(const UnitPtr& p)
 {
     string file = p->topLevelFile();
+    
+    CPPVisitorPatternVisitor visitorPatternVisitor;
+    p->visit(&visitorPatternVisitor, true);
 
     //
     // Give precedence to header-ext global metadata.
@@ -561,6 +565,29 @@ Slice::Gen::writeExtraHeaders(IceUtilInternal::Output& out)
     }
 }
 
+StringList
+Slice::Gen::CPPVisitorPatternVisitor::generateVisitFunctionBody(const string& paramName,
+								const ClassDefPtr& baseVisitor,
+								const ClassDefPtr& derivedVisitor,
+								const string& operationName)
+{
+	ostringstream ostr;
+	StringList body;
+
+	if(baseVisitor != derivedVisitor)
+	{
+		ostr << derivedVisitor->scoped() << "Ptr::dynamicCast(" << paramName << ")";
+	}
+	else
+	{
+		ostr << paramName;
+	}
+	ostr << "->" << operationName << "(this);";
+	body.push_back(ostr.str());
+
+	return body;
+}
+
 Slice::Gen::TypesVisitor::TypesVisitor(Output& h, Output& c, const string& dllExport, bool stream) :
     H(h), C(c), _dllExport(dllExport), _stream(stream), _doneStaticSymbol(false), _useWstring(false)
 {
@@ -4804,6 +4831,79 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p)
 }
 
 void
+Slice::Gen::ObjectVisitor::visitGeneratedOperation(const GeneratedOperationPtr& p)
+{
+    string name = p->name();
+    string scoped = fixKwd(p->scoped());
+    string scope = fixKwd(p->scope());
+
+    TypePtr ret = p->returnType();
+    string retS = returnTypeToString(ret, p->getMetaData(), _useWstring);
+
+    string params = "(";
+    string paramsDecl = "(";
+
+    ContainerPtr container = p->container();
+    ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+    string classScope = fixKwd(cl->scope());
+
+    ParamDeclList inParams;
+    ParamDeclList outParams;
+    ParamDeclList paramList = p->parameters();
+    for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+    {
+        string paramName = fixKwd((*q)->name());
+        TypePtr type = (*q)->type();
+        bool isOutParam = (*q)->isOutParam();
+        string typeString;
+        if(isOutParam)
+        {
+            outParams.push_back(*q);
+            typeString = outputTypeToString(type, (*q)->getMetaData(), _useWstring);
+        }
+        else
+        {
+            inParams.push_back(*q);
+            typeString = inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring);
+        }
+
+        if(q != paramList.begin())
+        {
+            params += ", ";
+	    paramsDecl += ", ";
+        }
+
+        params += typeString;
+        paramsDecl += typeString;
+        paramsDecl += ' ';
+        paramsDecl += paramName;
+    }
+
+    params += ')';
+    paramsDecl += ')';
+
+    bool isConst = false; //(p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const");
+
+    string deprecateSymbol = getDeprecateSymbol(p, cl);
+
+    H << sp;
+    H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << params
+      << (isConst ? " const" : "") << ";";
+
+    StringList body = p->body();
+    if(!body.empty())
+    {
+	    C << sp;
+	    C << nl << retS << nl << scoped << paramsDecl << nl << "{" << nl;
+	    for(StringList::const_iterator it = body.begin(); it != body.end(); it++)
+	    {
+		    C << *it << nl;
+	    }
+	    C << "}";
+    }
+}
+
+void
 Slice::Gen::ObjectVisitor::emitGCFunctions(const ClassDefPtr& p)
 {
     string scoped = fixKwd(p->scoped());
diff --git a/cpp/src/slice2cpp/Gen.h b/cpp/src/slice2cpp/Gen.h
index b262fba..c8a8e92 100644
--- a/cpp/src/slice2cpp/Gen.h
+++ b/cpp/src/slice2cpp/Gen.h
@@ -11,6 +11,7 @@
 #define GEN_H
 
 #include <Slice/Parser.h>
+#include <Slice/VisitorPatternVisitor.h>
 #include <IceUtil/OutputUtil.h>
 
 namespace Slice
@@ -252,6 +253,7 @@ private:
         virtual bool visitExceptionStart(const ExceptionPtr&);
         virtual bool visitStructStart(const StructPtr&);
         virtual void visitOperation(const OperationPtr&);
+        virtual void visitGeneratedOperation(const GeneratedOperationPtr&);
 
     private:
 
@@ -456,6 +458,12 @@ private:
 
 private:
 
+    class CPPVisitorPatternVisitor : public VisitorPatternVisitor
+    {
+    protected:
+        StringList generateVisitFunctionBody(const std::string&, const ClassDefPtr&, const ClassDefPtr&, const std::string&);
+    };
+
     class MetaDataVisitor : public ParserVisitor
     {
     public:

-----------------------------------------------------------------------


-- 
asterisk-scf/release/ice.git



More information about the asterisk-scf-commits mailing list