[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