[asterisk-scf-commits] asterisk-scf/release/ice.git branch "slice-plugins" created.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Wed Jan 19 13:20:41 CST 2011
branch "slice-plugins" has been created
at 490e1ba4fec8eef351aeeafe6b0e4844b169ffdd (commit)
- Log -----------------------------------------------------------------
commit 490e1ba4fec8eef351aeeafe6b0e4844b169ffdd
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Wed Jan 19 13:18:52 2011 -0600
Add support for Slice translator plugins to slice2cpp, slice2java,
slice2cs and slice2py (including dynamic translation for Python).
diff --git a/cpp/include/Slice/CsUtil.h b/cpp/include/Slice/CsUtil.h
index eaa767d..2f3b729 100644
--- a/cpp/include/Slice/CsUtil.h
+++ b/cpp/include/Slice/CsUtil.h
@@ -32,10 +32,11 @@ public:
//
static void validateMetaData(const UnitPtr&);
+ static std::string typeToString(const TypePtr&);
+
protected:
static std::string fixId(const std::string&, int = 0, bool = false);
static std::string fixId(const ContainedPtr&, int = 0, bool = false);
- static std::string typeToString(const TypePtr&);
static bool isValueType(const TypePtr&);
//
diff --git a/cpp/include/Slice/JavaUtil.h b/cpp/include/Slice/JavaUtil.h
index c1fdd50..0bbd18f 100644
--- a/cpp/include/Slice/JavaUtil.h
+++ b/cpp/include/Slice/JavaUtil.h
@@ -54,6 +54,20 @@ public:
void close();
+ //
+ // Get the Java name for a type. If an optional scope is provided,
+ // the scope will be removed from the result if possible.
+ //
+ enum TypeMode
+ {
+ TypeModeIn,
+ TypeModeOut,
+ TypeModeMember,
+ TypeModeReturn
+ };
+ static std::string typeToString(const TypePtr&, TypeMode, const std::string& = std::string(),
+ const StringList& = StringList(), bool = true);
+
protected:
JavaGenerator(const std::string&);
@@ -70,57 +84,43 @@ protected:
// Check a symbol against any of the Java keywords. If a
// match is found, return the symbol with a leading underscore.
//
- std::string fixKwd(const std::string&) const;
+ static std::string fixKwd(const std::string&);
//
// Convert a Slice scoped name into a Java name.
//
- std::string convertScopedName(const std::string&,
- const std::string& = std::string(),
- const std::string& = std::string()) const;
+ static std::string convertScopedName(const std::string&,
+ const std::string& = std::string(),
+ const std::string& = std::string());
//
// Returns the package prefix for a give Slice file.
//
- std::string getPackagePrefix(const ContainedPtr&) const;
+ static std::string getPackagePrefix(const ContainedPtr&);
//
// Returns the Java package of a Contained entity.
//
- std::string getPackage(const ContainedPtr&) const;
+ static std::string getPackage(const ContainedPtr&);
//
// Returns the Java name for a Contained entity. If the optional
// package argument matches the entity's package name, then the
// package is removed from the result.
//
- std::string getAbsolute(const ContainedPtr&,
- const std::string& = std::string(),
- const std::string& = std::string(),
- const std::string& = std::string()) const;
-
- //
- // Get the Java name for a type. If an optional scope is provided,
- // the scope will be removed from the result if possible.
- //
- enum TypeMode
- {
- TypeModeIn,
- TypeModeOut,
- TypeModeMember,
- TypeModeReturn
- };
- std::string typeToString(const TypePtr&, TypeMode, const std::string& = std::string(),
- const StringList& = StringList(), bool = true) const;
+ static std::string getAbsolute(const ContainedPtr&,
+ const std::string& = std::string(),
+ const std::string& = std::string(),
+ const std::string& = std::string());
//
// Get the Java object name for a type. For primitive types, this returns the
// Java class type (e.g., Integer). For all other types, this function delegates
// to typeToString.
//
- std::string typeToObjectString(const TypePtr&, TypeMode, const std::string& = std::string(),
- const StringList& = StringList(), bool = true) const;
+ static std::string typeToObjectString(const TypePtr&, TypeMode, const std::string& = std::string(),
+ const StringList& = StringList(), bool = true);
//
// Generate code to marshal or unmarshal a type.
@@ -183,9 +183,9 @@ protected:
// The functions return true if a custom type was defined and false to indicate
// the default mapping was used.
//
- bool getDictionaryTypes(const DictionaryPtr&, const std::string&, const StringList&,
- std::string&, std::string&) const;
- bool getSequenceTypes(const SequencePtr&, const std::string&, const StringList&, std::string&, std::string&) const;
+ static bool getDictionaryTypes(const DictionaryPtr&, const std::string&, const StringList&,
+ std::string&, std::string&);
+ static bool getSequenceTypes(const SequencePtr&, const std::string&, const StringList&, std::string&, std::string&);
virtual JavaOutput* createOutput();
@@ -223,7 +223,7 @@ private:
std::string _dir;
::IceUtilInternal::Output* _out;
- mutable std::map<std::string, std::string> _filePackagePrefix;
+ static std::map<std::string, std::string> _filePackagePrefix;
};
}
diff --git a/cpp/include/Slice/Parser.h b/cpp/include/Slice/Parser.h
index ad390b1..86ee25b 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
@@ -452,12 +457,12 @@ public:
bool checkIntroduced(const std::string&, ContainedPtr = 0);
bool nameIsLegal(const std::string&, const char *);
bool checkForGlobalDef(const std::string&, const char *);
+ void checkIdentifier(const std::string&) const;
protected:
Container(const UnitPtr&);
- void checkIdentifier(const std::string&) const;
bool checkInterfaceAndLocal(const std::string&, bool, bool, bool, bool, bool);
bool checkGlobalMetaData(const StringList&, const StringList&);
bool validateConstant(const std::string&, const TypePtr&, const SyntaxTreeBasePtr&, const std::string&, bool);
@@ -594,6 +599,57 @@ 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. An empty list will be treated as 'no body', so if you want to
+// have a non-abstract operation generated without any code in the body
+// you'll need to provide a StringList with an empty string in it.
+// ----------------------------------------------------------------------
+
+class SLICE_API GeneratedOperation : virtual public Contained, virtual public Container
+{
+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;
+ virtual bool uses(const ContainedPtr&) const;
+ StringList body() const;
+ bool isAbstract() const;
+ bool isOverride() const;
+ void setOverride(bool);
+ virtual std::string kindOf() const;
+ virtual void visit(ParserVisitor*, bool);
+
+protected:
+
+ GeneratedOperation(const ContainerPtr&, const std::string&, const TypePtr&, const StringList&, Mode);
+ friend class ClassDef;
+
+ TypePtr _returnType;
+ Mode _mode;
+ StringList _body;
+ bool _override;
+};
+
+// ----------------------------------------------------------------------
// ClassDef
// ----------------------------------------------------------------------
@@ -610,6 +666,8 @@ public:
virtual void destroy();
OperationPtr createOperation(const std::string&, const TypePtr&, Operation::Mode = Operation::Normal);
+ GeneratedOperationPtr createGeneratedOperation(const std::string&, const TypePtr&, const StringList&,
+ GeneratedOperation::Mode = GeneratedOperation::Normal);
DataMemberPtr createDataMember(const std::string&, const TypePtr&, const SyntaxTreeBasePtr&, const std::string&,
const std::string&);
ClassDeclPtr declaration() const;
@@ -617,6 +675,7 @@ public:
ClassList allBases() const;
OperationList operations() const;
OperationList allOperations() const;
+ GeneratedOperationList generatedOperations() const;
DataMemberList dataMembers() const;
DataMemberList allDataMembers() const;
DataMemberList classDataMembers() const;
@@ -628,6 +687,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 +703,7 @@ protected:
bool _interface;
bool _hasDataMembers;
bool _hasOperations;
+ bool _hasGeneratedOperations;
ClassList _bases;
bool _local;
};
@@ -894,7 +955,11 @@ public:
protected:
ParamDecl(const ContainerPtr&, const std::string&, const TypePtr&, bool isOutParam);
+ static ParamDeclPtr createCommon(const std::string&, const TypePtr&, bool,
+ ContainedList&, const ContainerPtr&, const ContainedPtr&,
+ const UnitPtr&, bool);
friend class Operation;
+ friend class GeneratedOperation;
TypePtr _type;
bool _isOutParam;
diff --git a/cpp/include/Slice/Plugin.h b/cpp/include/Slice/Plugin.h
new file mode 100644
index 0000000..7649d90
--- /dev/null
+++ b/cpp/include/Slice/Plugin.h
@@ -0,0 +1,30 @@
+#ifndef SLICE_PLUGIN_H
+#define SLICE_PLUGIN_H
+
+#include <Slice/Parser.h>
+
+namespace Slice
+{
+
+namespace Plugin
+{
+
+ enum Language
+ {
+ LanguageCPlusPlus,
+ LanguageCs,
+ LanguageJava,
+ LanguagePython,
+ LanguageRuby,
+ LanguagePHP
+ };
+
+ typedef std::list<ParserVisitor *> VisitorList;
+
+ typedef VisitorList* (*FACTORY)(Plugin::Language);
+
+}
+
+}
+
+#endif
diff --git a/cpp/include/Slice/PythonUtil.h b/cpp/include/Slice/PythonUtil.h
index bd6bab1..a104de9 100644
--- a/cpp/include/Slice/PythonUtil.h
+++ b/cpp/include/Slice/PythonUtil.h
@@ -21,7 +21,8 @@ namespace Python
//
// Generate Python code for a translation unit.
//
-SLICE_API void generate(const Slice::UnitPtr&, bool, bool, const std::vector<std::string>&, IceUtilInternal::Output&);
+SLICE_API void generate(const Slice::UnitPtr&, bool, bool, const std::vector<std::string>&, IceUtilInternal::Output&,
+ const std::vector<std::string>&);
//
// Convert a scoped name into a Python name.
diff --git a/cpp/src/Slice/JavaUtil.cpp b/cpp/src/Slice/JavaUtil.cpp
index 5c06896..51ecce4 100644
--- a/cpp/src/Slice/JavaUtil.cpp
+++ b/cpp/src/Slice/JavaUtil.cpp
@@ -169,6 +169,8 @@ Slice::JavaOutput::printHeader()
const string Slice::JavaGenerator::_getSetMetaData = "java:getset";
+map<string, string> Slice::JavaGenerator::_filePackagePrefix;
+
Slice::JavaGenerator::JavaGenerator(const string& dir) :
_dir(dir),
_out(0)
@@ -292,7 +294,7 @@ splitScopedName(const string& scoped)
// otherwise, return the name unchanged.
//
string
-Slice::JavaGenerator::fixKwd(const string& name) const
+Slice::JavaGenerator::fixKwd(const string& name)
{
if(name.empty())
{
@@ -313,7 +315,7 @@ Slice::JavaGenerator::fixKwd(const string& name) const
}
string
-Slice::JavaGenerator::convertScopedName(const string& scoped, const string& prefix, const string& suffix) const
+Slice::JavaGenerator::convertScopedName(const string& scoped, const string& prefix, const string& suffix)
{
string result;
string::size_type start = 0;
@@ -363,7 +365,7 @@ Slice::JavaGenerator::convertScopedName(const string& scoped, const string& pref
}
string
-Slice::JavaGenerator::getPackagePrefix(const ContainedPtr& cont) const
+Slice::JavaGenerator::getPackagePrefix(const ContainedPtr& cont)
{
UnitPtr unit = cont->container()->unit();
string file = cont->file();
@@ -388,7 +390,7 @@ Slice::JavaGenerator::getPackagePrefix(const ContainedPtr& cont) const
}
string
-Slice::JavaGenerator::getPackage(const ContainedPtr& cont) const
+Slice::JavaGenerator::getPackage(const ContainedPtr& cont)
{
string scope = convertScopedName(cont->scope());
string prefix = getPackagePrefix(cont);
@@ -411,7 +413,7 @@ string
Slice::JavaGenerator::getAbsolute(const ContainedPtr& cont,
const string& package,
const string& prefix,
- const string& suffix) const
+ const string& suffix)
{
string name = cont->name();
if(prefix == "" && suffix == "")
@@ -438,7 +440,7 @@ Slice::JavaGenerator::typeToString(const TypePtr& type,
TypeMode mode,
const string& package,
const StringList& metaData,
- bool formal) const
+ bool formal)
{
static const char* builtinTable[] =
{
@@ -619,7 +621,7 @@ Slice::JavaGenerator::typeToObjectString(const TypePtr& type,
TypeMode mode,
const string& package,
const StringList& metaData,
- bool formal) const
+ bool formal)
{
static const char* builtinTable[] =
{
@@ -2458,7 +2460,7 @@ Slice::JavaGenerator::getDictionaryTypes(const DictionaryPtr& dict,
const string& package,
const StringList& metaData,
string& instanceType,
- string& formalType) const
+ string& formalType)
{
bool customType = false;
@@ -2516,7 +2518,7 @@ Slice::JavaGenerator::getSequenceTypes(const SequencePtr& seq,
const string& package,
const StringList& metaData,
string& instanceType,
- string& formalType) const
+ string& formalType)
{
bool customType = false;
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index 5711c7b..8eac593 100644
--- a/cpp/src/Slice/Parser.cpp
+++ b/cpp/src/Slice/Parser.cpp
@@ -2955,6 +2955,94 @@ Slice::ClassDef::createOperation(const string& name,
return op;
}
+GeneratedOperationPtr
+Slice::ClassDef::createGeneratedOperation(const string& name,
+ const TypePtr& returnType,
+ const StringList& body,
+ GeneratedOperation::Mode mode)
+{
+ checkIdentifier(name);
+
+ ContainedList matches = _unit->findContents(thisScope() + name);
+ if(!matches.empty())
+ {
+ 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;
+ }
+
+ //
+ // 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);
+ }
+
+ //
+ // 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);
+ }
+ }
+ }
+
+ _hasGeneratedOperations = true;
+ GeneratedOperationPtr gop = new GeneratedOperation(this, name, returnType, body, mode);
+ _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)
@@ -3248,6 +3336,21 @@ Slice::ClassDef::allClassDataMembers() const
return result;
}
+GeneratedOperationList
+Slice::ClassDef::generatedOperations() const
+{
+ GeneratedOperationList result;
+ for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p)
+ {
+ GeneratedOperationPtr q = GeneratedOperationPtr::dynamicCast(*p);
+ if(q)
+ {
+ result.push_back(q);
+ }
+ }
+ return result;
+}
+
bool
Slice::ClassDef::canBeCyclic() const
{
@@ -3285,6 +3388,13 @@ Slice::ClassDef::isAbstract() const
{
return true;
}
+ if(GeneratedOperationPtr gop = GeneratedOperationPtr::dynamicCast(*p))
+ {
+ if(gop->isAbstract())
+ {
+ return true;
+ }
+ }
}
return false;
@@ -3332,6 +3442,12 @@ Slice::ClassDef::hasOperations() const
}
bool
+Slice::ClassDef::hasGeneratedOperations() const
+{
+ return _hasGeneratedOperations;
+}
+
+bool
Slice::ClassDef::hasDefaultValues() const
{
DataMemberList dml = dataMembers();
@@ -4564,106 +4680,7 @@ Slice::Operation::sendMode() const
ParamDeclPtr
Slice::Operation::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");
- }
- }
-
- //
- // Non-local class/interface cannot have operation with local parameters.
- //
- ClassDefPtr cl = ClassDefPtr::dynamicCast(this->container());
- assert(cl);
- if(type->isLocal() && !cl->isLocal())
- {
- string msg = "non-local " + cl->kindOf() + " `" + cl->name() + "' cannot have local parameter `";
- msg += name + "' in operation `" + this->name() + "'";
- _unit->error(msg);
- }
-
- ParamDeclPtr p = new ParamDecl(this, name, type, isOutParam);
- _contents.push_back(p);
- return p;
+ return ParamDecl::createCommon(name, type, isOutParam, _contents, this, this, _unit, true);
}
ParamDeclList
@@ -4965,9 +4982,227 @@ Slice::Operation::Operation(const ContainerPtr& container,
}
// ----------------------------------------------------------------------
+// GeneratedOperation
+// ----------------------------------------------------------------------
+
+TypePtr
+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)
+{
+ return ParamDecl::createCommon(name, type, isOutParam, _contents, this, this, _unit, false);
+}
+
+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::isAbstract() const
+{
+ return _body.empty();
+}
+
+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);
+}
+
+bool
+Slice::GeneratedOperation::isOverride() const
+{
+ return _override;
+}
+
+void
+Slice::GeneratedOperation::setOverride(bool override)
+{
+ _override = override;
+}
+
+Slice::GeneratedOperation::GeneratedOperation(const ContainerPtr& container,
+ const string& name,
+ const TypePtr& returnType,
+ const StringList& body,
+ Mode mode) :
+ SyntaxTreeBase(container->unit()),
+ Contained(container, name),
+ Container(container->unit()),
+ _returnType(returnType),
+ _mode(mode),
+ _body(body),
+ _override(false)
+{
+}
+
+// ----------------------------------------------------------------------
// ParamDecl
// ----------------------------------------------------------------------
+ParamDeclPtr
+Slice::ParamDecl::createCommon(const string& name, const TypePtr& type, bool isOutParam,
+ ContainedList& contents, const ContainerPtr& ctr, const ContainedPtr& cont,
+ const UnitPtr& unit, bool restrictLocal)
+{
+ ctr->checkIdentifier(name);
+
+ if(unit->profile() == IceE)
+ {
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(cont->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(ctr->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 == cont->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(cont->name());
+ if(newName == thisName)
+ {
+ string msg = "parameter `" + name + "' differs only in capitalization from operation name `";
+ msg += cont->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");
+ }
+ }
+
+ if(restrictLocal)
+ {
+ //
+ // Non-local class/interface cannot have operation with local parameters.
+ //
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(cont->container());
+ assert(cl);
+ if(type->isLocal() && !cl->isLocal())
+ {
+ string msg = "non-local " + cl->kindOf() + " `" + cl->name() + "' cannot have local parameter `";
+ msg += name + "' in operation `" + cont->name() + "'";
+ unit->error(msg);
+ }
+ }
+
+ ParamDeclPtr p = new ParamDecl(ctr, name, type, isOutParam);
+ contents.push_back(p);
+ return p;
+}
+
TypePtr
Slice::ParamDecl::type() const
{
diff --git a/cpp/src/Slice/PythonUtil.cpp b/cpp/src/Slice/PythonUtil.cpp
index 08c30f4..8cf0296 100644
--- a/cpp/src/Slice/PythonUtil.cpp
+++ b/cpp/src/Slice/PythonUtil.cpp
@@ -10,9 +10,11 @@
#include <Slice/PythonUtil.h>
#include <Slice/Checksum.h>
#include <Slice/Util.h>
+#include <Slice/Plugin.h>
#include <IceUtil/IceUtil.h>
#include <IceUtil/StringUtil.h>
#include <IceUtil/InputUtil.h>
+#include <IceUtil/DynamicLibrary.h>
#include <climits>
#include <iterator>
@@ -409,7 +411,9 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
ClassList bases = p->bases();
ClassDefPtr base;
OperationList ops = p->operations();
- OperationList::iterator oli;
+ OperationList::const_iterator oli;
+ GeneratedOperationList gops = p->generatedOperations();
+ GeneratedOperationList::const_iterator goli;
bool isAbstract = p->isInterface() || p->allOperations().size() > 0; // Don't use isAbstract() - see bug 3739
//
@@ -480,7 +484,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
if(base)
{
_out << nl << getSymbol(base) << ".__init__(self";
- for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q)
+ for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q)
{
if(q->inherited)
{
@@ -489,7 +493,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
}
_out << ')';
}
- for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q)
+ for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q)
{
if(!q->inherited)
{
@@ -526,7 +530,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
_out << sp << nl << "def ice_ids(self, current=None):";
_out.inc();
_out << nl << "return (";
- for(StringList::iterator q = ids.begin(); q != ids.end(); ++q)
+ for(StringList::const_iterator q = ids.begin(); q != ids.end(); ++q)
{
if(q != ids.begin())
{
@@ -569,7 +573,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
ParamDeclList params = (*oli)->parameters();
- for(ParamDeclList::iterator pli = params.begin(); pli != params.end(); ++pli)
+ for(ParamDeclList::const_iterator pli = params.begin(); pli != params.end(); ++pli)
{
if(!(*pli)->isOutParam())
{
@@ -596,7 +600,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
ParamDeclList params = (*oli)->parameters();
- for(ParamDeclList::iterator pli = params.begin(); pli != params.end(); ++pli)
+ for(ParamDeclList::const_iterator pli = params.begin(); pli != params.end(); ++pli)
{
if(!(*pli)->isOutParam())
{
@@ -620,6 +624,48 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
}
}
+ if(!gops.empty())
+ {
+ //
+ // Emit each GeneratedOperation.
+ //
+ for(goli = gops.begin(); goli != gops.end(); ++goli)
+ {
+ string fixedOpName = fixIdent((*goli)->name());
+ _out << sp << nl << "def " << fixedOpName << "(self";
+
+ ParamDeclList params = (*goli)->parameters();
+
+ for(ParamDeclList::const_iterator pli = params.begin(); pli != params.end(); ++pli)
+ {
+ if(!(*pli)->isOutParam())
+ {
+ _out << ", " << fixIdent((*pli)->name());
+ }
+ }
+ _out << "):";
+ _out.inc();
+ if((*goli)->isAbstract())
+ {
+ _out << nl << "pass";
+ }
+ else
+ {
+ StringList body = (*goli)->body();
+ for(StringList::const_iterator it = body.begin(); it != body.end(); it++)
+ {
+ _out << nl << *it;
+ }
+ }
+ comment = (*goli)->comment();
+ if(!comment.empty())
+ {
+ _out << nl << "'''" << editComment(comment) << "'''";
+ }
+ _out.dec();
+ }
+ }
+
//
// __str__
//
@@ -842,7 +888,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
_out << nl;
}
bool isProtected = p->hasMetaData("protected");
- for(DataMemberList::iterator r = members.begin(); r != members.end(); ++r)
+ for(DataMemberList::const_iterator r = members.begin(); r != members.end(); ++r)
{
if(r != members.begin())
{
@@ -885,10 +931,10 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
{
_out << sp;
}
- for(OperationList::iterator s = ops.begin(); s != ops.end(); ++s)
+ for(OperationList::const_iterator s = ops.begin(); s != ops.end(); ++s)
{
ParamDeclList params = (*s)->parameters();
- ParamDeclList::iterator t;
+ ParamDeclList::const_iterator t;
int count;
_out << nl << name << "._op_" << (*s)->name() << " = IcePy.Operation('" << (*s)->name() << "', "
@@ -949,7 +995,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
}
_out << ", (";
ExceptionList exceptions = (*s)->throws();
- for(ExceptionList::iterator u = exceptions.begin(); u != exceptions.end(); ++u)
+ for(ExceptionList::const_iterator u = exceptions.begin(); u != exceptions.end(); ++u)
{
if(u != exceptions.begin())
{
@@ -2194,11 +2240,37 @@ Slice::Python::CodeVisitor::editComment(const string& comment)
}
void
-Slice::Python::generate(const UnitPtr& un, bool all, bool checksum, const vector<string>& includePaths, Output& out)
+Slice::Python::generate(const UnitPtr& un, bool all, bool checksum, const vector<string>& includePaths, Output& out,
+ const vector<string>& plugins)
{
Slice::Python::MetaDataVisitor visitor;
un->visit(&visitor, false);
+ for(vector<string>::const_iterator plugin = plugins.begin(); plugin != plugins.end(); plugin++)
+ {
+ IceUtil::DynamicLibraryPtr library = new IceUtil::DynamicLibrary();
+ IceUtil::DynamicLibrary::symbol_type sym = library->loadEntryPoint(*plugin, false);
+ if(sym == 0)
+ {
+ string msg = library->getErrorMessage();
+ cerr << "Unable to find " << *plugin << " = " << msg << endl;
+ }
+
+ Plugin::VisitorList* pluginVisitors;
+ Plugin::FACTORY factory = (Plugin::FACTORY) sym;
+ pluginVisitors = factory(Plugin::LanguagePython);
+
+ if(pluginVisitors)
+ {
+ for(Plugin::VisitorList::const_iterator it = pluginVisitors->begin(); it != pluginVisitors->end(); it++)
+ {
+ un->visit(*it, true);
+ delete *it;
+ }
+ delete pluginVisitors;
+ }
+ }
+
out << nl << "import Ice, IcePy, __builtin__";
if(!all)
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index 9442aea..21476de 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -8,6 +8,7 @@
// **********************************************************************
#include <IceUtil/DisableWarnings.h>
+#include <IceUtil/DynamicLibrary.h>
#include <Gen.h>
#include <Slice/Util.h>
#include <Slice/CPlusPlusUtil.h>
@@ -15,6 +16,7 @@
#include <IceUtil/Iterator.h>
#include <Slice/Checksum.h>
#include <Slice/FileTracker.h>
+#include <Slice/Plugin.h>
#include <limits>
@@ -128,7 +130,7 @@ writeDataMemberInitializers(IceUtilInternal::Output& C, const DataMemberList& me
Slice::Gen::Gen(const string& base, const string& headerExtension, const string& sourceExtension,
const vector<string>& extraHeaders, const string& include,
const vector<string>& includePaths, const string& dllExport, const string& dir,
- bool imp, bool checksum, bool stream, bool ice) :
+ bool imp, bool checksum, bool stream, bool ice, const vector<string>& plugins) :
_base(base),
_headerExtension(headerExtension),
_implHeaderExtension(headerExtension),
@@ -141,7 +143,8 @@ Slice::Gen::Gen(const string& base, const string& headerExtension, const string&
_impl(imp),
_checksum(checksum),
_stream(stream),
- _ice(ice)
+ _ice(ice),
+ _plugins(plugins)
{
for(vector<string>::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p)
{
@@ -171,6 +174,31 @@ void
Slice::Gen::generate(const UnitPtr& p)
{
string file = p->topLevelFile();
+
+ for(vector<string>::const_iterator plugin = _plugins.begin(); plugin != _plugins.end(); plugin++)
+ {
+ IceUtil::DynamicLibraryPtr library = new IceUtil::DynamicLibrary();
+ IceUtil::DynamicLibrary::symbol_type sym = library->loadEntryPoint(*plugin, false);
+ if(sym == 0)
+ {
+ string msg = library->getErrorMessage();
+ cerr << "Unable to find " << *plugin << " = " << msg << endl;
+ }
+
+ Plugin::VisitorList* pluginVisitors;
+ Plugin::FACTORY factory = (Plugin::FACTORY) sym;
+ pluginVisitors = factory(Plugin::LanguageCPlusPlus);
+
+ if(pluginVisitors)
+ {
+ for(Plugin::VisitorList::const_iterator it = pluginVisitors->begin(); it != pluginVisitors->end(); it++)
+ {
+ p->visit(*it, true);
+ delete *it;
+ }
+ delete pluginVisitors;
+ }
+ }
//
// Give precedence to header-ext global metadata.
@@ -4803,6 +4831,90 @@ 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)
+{
+ 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 = (p->mode() == GeneratedOperation::Nonmutating);
+
+ string deprecateSymbol = getDeprecateSymbol(p, cl);
+
+ H << sp;
+ H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << params
+ << (isConst ? " const" : "");
+
+ 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();
+ C << nl << retS << nl << scoped << paramsDecl;
+ C << sb;
+ for(StringList::const_iterator it = body.begin(); it != body.end(); it++)
+ {
+ C << nl << *it;
+ }
+ C << eb;
+ }
+ else
+ {
+ // The operation is abstract, so mark it as 'pure virtual'.
+ H << " = 0;";
+ }
+}
+
void
Slice::Gen::ObjectVisitor::emitGCFunctions(const ClassDefPtr& p)
{
diff --git a/cpp/src/slice2cpp/Gen.h b/cpp/src/slice2cpp/Gen.h
index b262fba..8b2cd0b 100644
--- a/cpp/src/slice2cpp/Gen.h
+++ b/cpp/src/slice2cpp/Gen.h
@@ -31,7 +31,8 @@ public:
bool,
bool,
bool,
- bool);
+ bool,
+ const std::vector<std::string>&);
~Gen();
void generate(const UnitPtr&);
@@ -70,6 +71,7 @@ private:
bool _checksum;
bool _stream;
bool _ice;
+ std::vector<std::string> _plugins;
class TypesVisitor : private ::IceUtil::noncopyable, public ParserVisitor
{
@@ -252,6 +254,7 @@ private:
virtual bool visitExceptionStart(const ExceptionPtr&);
virtual bool visitStructStart(const StructPtr&);
virtual void visitOperation(const OperationPtr&);
+ virtual void visitGeneratedOperation(const GeneratedOperationPtr&);
private:
diff --git a/cpp/src/slice2cpp/Main.cpp b/cpp/src/slice2cpp/Main.cpp
index 0ca754b..3381bfa 100644
--- a/cpp/src/slice2cpp/Main.cpp
+++ b/cpp/src/slice2cpp/Main.cpp
@@ -79,6 +79,7 @@ usage(const char* n)
"--underscore Permit underscores in Slice identifiers.\n"
"--checksum Generate checksums for Slice definitions.\n"
"--stream Generate marshaling support for public stream API.\n"
+ "--plugin PATH Load and apply plugin before generating output.\n"
;
}
@@ -105,6 +106,7 @@ compile(int argc, char* argv[])
opts.addOpt("", "underscore");
opts.addOpt("", "checksum");
opts.addOpt("", "stream");
+ opts.addOpt("", "plugin", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
vector<string> args;
try
@@ -156,6 +158,8 @@ compile(int argc, char* argv[])
cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i));
}
+ vector<string> plugins = opts.argVec("plugin");
+
bool preprocess = opts.isSet("E");
string include = opts.optArg("include-dir");
@@ -275,7 +279,7 @@ compile(int argc, char* argv[])
try
{
Gen gen(icecpp->getBaseName(), headerExtension, sourceExtension, extraHeaders, include,
- includePaths, dllExport, output, impl, checksum, stream, ice);
+ includePaths, dllExport, output, impl, checksum, stream, ice, plugins);
gen.generate(u);
}
catch(const Slice::FileException& ex)
diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp
index 7a089e9..de88696 100644
--- a/cpp/src/slice2cs/Gen.cpp
+++ b/cpp/src/slice2cs/Gen.cpp
@@ -10,6 +10,7 @@
#include <IceUtil/DisableWarnings.h>
#include <IceUtil/Functional.h>
#include <IceUtil/StringUtil.h>
+#include <IceUtil/DynamicLibrary.h>
#include <Gen.h>
#include <limits>
#include <sys/stat.h>
@@ -24,6 +25,7 @@
#include <Slice/DotNetNames.h>
#include <Slice/FileTracker.h>
#include <Slice/Util.h>
+#include <Slice/Plugin.h>
#include <string.h>
using namespace std;
@@ -982,6 +984,24 @@ Slice::CsVisitor::getParams(const OperationPtr& op)
}
vector<string>
+Slice::CsVisitor::getParams(const GeneratedOperationPtr& op)
+{
+ vector<string> params;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string param = getParamAttributes(*q);
+ if((*q)->isOutParam())
+ {
+ param += "out ";
+ }
+ param += typeToString((*q)->type()) + " " + fixId((*q)->name());
+ params.push_back(param);
+ }
+ return params;
+}
+
+vector<string>
Slice::CsVisitor::getParamsAsync(const OperationPtr& op, bool amd, bool newAMI)
{
vector<string> params;
@@ -1063,6 +1083,23 @@ Slice::CsVisitor::getArgs(const OperationPtr& op)
}
vector<string>
+Slice::CsVisitor::getArgs(const GeneratedOperationPtr& op)
+{
+ vector<string> args;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string arg = fixId((*q)->name());
+ if((*q)->isOutParam())
+ {
+ arg = "out " + arg;
+ }
+ args.push_back(arg);
+ }
+ return args;
+}
+
+vector<string>
Slice::CsVisitor::getArgsAsync(const OperationPtr& op, bool newAMI)
{
vector<string> args;
@@ -1849,9 +1886,10 @@ Slice::CsVisitor::writeDocCommentParam(const OperationPtr& p, ParamDir paramType
}
Slice::Gen::Gen(const string& base, const vector<string>& includePaths, const string& dir,
- bool impl, bool implTie, bool stream)
+ bool impl, bool implTie, bool stream, const vector<string>& plugins)
: _includePaths(includePaths),
- _stream(stream)
+ _stream(stream),
+ _plugins(plugins)
{
string fileBase = base;
string::size_type pos = base.find_last_of("/\\");
@@ -1924,6 +1962,31 @@ Slice::Gen::generate(const UnitPtr& p)
{
CsGenerator::validateMetaData(p);
+ for(vector<string>::const_iterator plugin = _plugins.begin(); plugin != _plugins.end(); plugin++)
+ {
+ IceUtil::DynamicLibraryPtr library = new IceUtil::DynamicLibrary();
+ IceUtil::DynamicLibrary::symbol_type sym = library->loadEntryPoint(*plugin, false);
+ if(sym == 0)
+ {
+ string msg = library->getErrorMessage();
+ cerr << "Unable to find " << *plugin << " = " << msg << endl;
+ }
+
+ Plugin::VisitorList* pluginVisitors;
+ Plugin::FACTORY factory = (Plugin::FACTORY) sym;
+ pluginVisitors = factory(Plugin::LanguageCs);
+
+ if(pluginVisitors)
+ {
+ for(Plugin::VisitorList::const_iterator it = pluginVisitors->begin(); it != pluginVisitors->end(); it++)
+ {
+ p->visit(*it, true);
+ delete *it;
+ }
+ delete pluginVisitors;
+ }
+ }
+
UnitVisitor unitVisitor(_out);
p->visit(&unitVisitor, false);
@@ -2275,7 +2338,7 @@ Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
if(!p->isInterface())
{
- if(p->hasDataMembers() && !p->hasOperations())
+ if(p->hasDataMembers() && !(p->hasOperations() || p->hasGeneratedOperations()))
{
_out << sp << nl << "#region Slice data members";
}
@@ -2283,14 +2346,14 @@ Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
{
_out << sp << nl << "#region Slice data members and operations";
}
- else if(p->hasOperations())
+ else if(p->hasOperations() || p->hasGeneratedOperations())
{
_out << sp << nl << "#region Slice operations";
}
}
else
{
- if(p->isLocal() && p->hasOperations())
+ if(p->isLocal() && (p->hasOperations() || p->hasGeneratedOperations()))
{
_out << sp << nl << "#region Slice operations";
}
@@ -2313,7 +2376,7 @@ Slice::Gen::TypesVisitor::visitClassDefEnd(const ClassDefPtr& p)
if(!p->isInterface())
{
- if(p->hasDataMembers() && !p->hasOperations())
+ if(p->hasDataMembers() && !(p->hasOperations() || p->hasGeneratedOperations()))
{
_out << sp << nl << "#endregion"; // Slice data members"
}
@@ -2321,7 +2384,7 @@ Slice::Gen::TypesVisitor::visitClassDefEnd(const ClassDefPtr& p)
{
_out << sp << nl << "#endregion"; // Slice data members and operations"
}
- else if(p->hasOperations())
+ else if(p->hasOperations() || p->hasGeneratedOperations())
{
_out << sp << nl << "#endregion"; // Slice operations"
}
@@ -2382,7 +2445,7 @@ Slice::Gen::TypesVisitor::visitClassDefEnd(const ClassDefPtr& p)
}
else
{
- if(p->isLocal() && p->hasOperations())
+ if(p->isLocal() && (p->hasOperations() || p->hasGeneratedOperations()))
{
_out << sp << nl << "#endregion"; // Slice operations"
}
@@ -2404,7 +2467,7 @@ Slice::Gen::TypesVisitor::visitOperation(const OperationPtr& p)
bool isInterface = classDef->isInterface();
//
- // Non-local classes and interfaces get the operations from their
+ // Non-local interfaces get the operations from their
// Operations base interfaces.
//
if(isInterface && !isLocal)
@@ -2522,6 +2585,72 @@ Slice::Gen::TypesVisitor::visitOperation(const OperationPtr& p)
}
void
+Slice::Gen::TypesVisitor::visitGeneratedOperation(const GeneratedOperationPtr& p)
+{
+ ClassDefPtr classDef = ClassDefPtr::dynamicCast(p->container());
+ bool isLocal = classDef->isLocal();
+ bool isInterface = classDef->isInterface();
+
+ //
+ // Non-local interfaces get the operations from their
+ // Operations base interfaces.
+ //
+ if(isInterface && !isLocal)
+ {
+ return;
+ }
+
+ string name = p->name();
+ ParamDeclList paramList = p->parameters();
+ vector<string> params;
+ vector<string> args;
+ string retS;
+
+ params = getParams(p);
+ args = getArgs(p);
+ name = fixId(name, DotNet::ICloneable, true);
+ retS = typeToString(p->returnType());
+
+ _out << sp;
+ if(isInterface && isLocal)
+ {
+ _out << nl;
+ }
+
+ writeDocComment(p, getDeprecateReason(p, classDef, "generatedOperation"));
+ emitAttributes(p);
+ emitGeneratedCodeAttribute();
+ _out << nl << "public ";
+ if(p->isAbstract())
+ {
+ _out << "abstract ";
+ }
+ else if(p->isOverride())
+ {
+ _out << "override ";
+ }
+ else
+ {
+ _out << "virtual ";
+ }
+ _out << retS << " " << name << spar << params << epar;
+ if(p->isAbstract())
+ {
+ _out << ";";
+ }
+ else
+ {
+ _out << sb;
+ StringList body = p->body();
+ for(StringList::const_iterator it = body.begin(); it != body.end(); it++)
+ {
+ _out << nl << *it;
+ }
+ _out << eb;
+ }
+}
+
+void
Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p)
{
//
diff --git a/cpp/src/slice2cs/Gen.h b/cpp/src/slice2cs/Gen.h
index 7e30421..d4c98df 100644
--- a/cpp/src/slice2cs/Gen.h
+++ b/cpp/src/slice2cs/Gen.h
@@ -28,9 +28,11 @@ protected:
virtual void writeInheritedOperations(const ClassDefPtr&);
virtual void writeDispatchAndMarshalling(const ClassDefPtr&, bool);
virtual std::vector<std::string> getParams(const OperationPtr&);
+ virtual std::vector<std::string> getParams(const GeneratedOperationPtr&);
virtual std::vector<std::string> getParamsAsync(const OperationPtr&, bool, bool = false);
virtual std::vector<std::string> getParamsAsyncCB(const OperationPtr&, bool = false, bool = true);
virtual std::vector<std::string> getArgs(const OperationPtr&);
+ virtual std::vector<std::string> getArgs(const GeneratedOperationPtr&);
virtual std::vector<std::string> getArgsAsync(const OperationPtr&, bool = false);
virtual std::vector<std::string> getArgsAsyncCB(const OperationPtr&, bool = false, bool = false);
@@ -74,7 +76,8 @@ public:
const std::string&,
bool,
bool,
- bool);
+ bool,
+ const std::vector<std::string>&);
~Gen();
void generate(const UnitPtr&);
@@ -93,6 +96,8 @@ private:
bool _stream;
+ std::vector<std::string> _plugins;
+
void printHeader();
class UnitVisitor : public CsVisitor
@@ -114,6 +119,7 @@ private:
virtual void visitModuleEnd(const ModulePtr&);
virtual bool visitClassDefStart(const ClassDefPtr&);
virtual void visitOperation(const OperationPtr&);
+ virtual void visitGeneratedOperation(const GeneratedOperationPtr&);
virtual void visitClassDefEnd(const ClassDefPtr&);
virtual bool visitExceptionStart(const ExceptionPtr&);
virtual void visitExceptionEnd(const ExceptionPtr&);
diff --git a/cpp/src/slice2cs/Main.cpp b/cpp/src/slice2cs/Main.cpp
index 87ed3c6..b8be8ab 100644
--- a/cpp/src/slice2cs/Main.cpp
+++ b/cpp/src/slice2cs/Main.cpp
@@ -76,6 +76,7 @@ usage(const char* n)
"--underscore Permit underscores in Slice identifiers.\n"
"--checksum Generate checksums for Slice definitions.\n"
"--stream Generate marshaling support for public stream API.\n"
+ "--plugin PATH Load and apply plugin before generating output.\n"
;
}
@@ -99,6 +100,7 @@ compile(int argc, char* argv[])
opts.addOpt("", "underscore");
opts.addOpt("", "checksum");
opts.addOpt("", "stream");
+ opts.addOpt("", "plugin", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
vector<string> args;
try
@@ -144,6 +146,8 @@ compile(int argc, char* argv[])
cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i));
}
+ vector<string> plugins = opts.argVec("plugin");
+
bool preprocess = opts.isSet("E");
string output = opts.optArg("output-dir");
@@ -268,7 +272,7 @@ compile(int argc, char* argv[])
{
try
{
- Gen gen(icecpp->getBaseName(), includePaths, output, impl, implTie, stream);
+ Gen gen(icecpp->getBaseName(), includePaths, output, impl, implTie, stream, plugins);
gen.generate(p);
if(tie)
{
diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp
index 2564f7e..3f49ed2 100644
--- a/cpp/src/slice2java/Gen.cpp
+++ b/cpp/src/slice2java/Gen.cpp
@@ -11,9 +11,11 @@
#include <Gen.h>
#include <Slice/Checksum.h>
#include <Slice/Util.h>
+#include <Slice/Plugin.h>
#include <IceUtil/Functional.h>
#include <IceUtil/Iterator.h>
#include <IceUtil/StringUtil.h>
+#include <IceUtil/DynamicLibrary.h>
#include <cstring>
#include <limits>
@@ -111,6 +113,27 @@ Slice::JavaVisitor::getParams(const OperationPtr& op, const string& package, boo
}
vector<string>
+Slice::JavaVisitor::getParams(const GeneratedOperationPtr& gop, const string& package, bool final)
+{
+ vector<string> params;
+
+ ParamDeclList paramList = gop->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ StringList metaData = (*q)->getMetaData();
+ string typeString = typeToString((*q)->type(), (*q)->isOutParam() ? TypeModeOut : TypeModeIn, package,
+ metaData);
+ if(final)
+ {
+ typeString = "final " + typeString;
+ }
+ params.push_back(typeString + ' ' + fixKwd((*q)->name()));
+ }
+
+ return params;
+}
+
+vector<string>
Slice::JavaVisitor::getInOutParams(const OperationPtr& op, const string& package, ParamDir paramType)
{
vector<string> params;
@@ -1721,10 +1744,11 @@ Slice::JavaVisitor::writeDocCommentParam(Output& out, const OperationPtr& p, Par
}
}
-Slice::Gen::Gen(const string& name, const string& base, const vector<string>& includePaths, const string& dir) :
+Slice::Gen::Gen(const string& name, const string& base, const vector<string>& includePaths, const string& dir, const vector<string>& plugins) :
_base(base),
_includePaths(includePaths),
- _dir(dir)
+ _dir(dir),
+ _plugins(plugins)
{
}
@@ -1735,6 +1759,31 @@ Slice::Gen::~Gen()
void
Slice::Gen::generate(const UnitPtr& p, bool stream)
{
+ for(vector<string>::const_iterator plugin = _plugins.begin(); plugin != _plugins.end(); plugin++)
+ {
+ IceUtil::DynamicLibraryPtr library = new IceUtil::DynamicLibrary();
+ IceUtil::DynamicLibrary::symbol_type sym = library->loadEntryPoint(*plugin, false);
+ if(sym == 0)
+ {
+ string msg = library->getErrorMessage();
+ cerr << "Unable to find " << *plugin << " = " << msg << endl;
+ }
+
+ Plugin::VisitorList* pluginVisitors;
+ Plugin::FACTORY factory = (Plugin::FACTORY) sym;
+ pluginVisitors = factory(Plugin::LanguageJava);
+
+ if(pluginVisitors)
+ {
+ for(Plugin::VisitorList::const_iterator it = pluginVisitors->begin(); it != pluginVisitors->end(); it++)
+ {
+ p->visit(*it, true);
+ delete *it;
+ }
+ delete pluginVisitors;
+ }
+ }
+
JavaGenerator::validateMetaData(p);
OpsVisitor opsVisitor(_dir);
@@ -2447,6 +2496,37 @@ Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
}
}
+ // Emit GeneratedOperations, which are always generated as local members
+ // even for abstract classes.
+ if(!p->isInterface())
+ {
+ GeneratedOperationList gops = p->generatedOperations();
+ for(GeneratedOperationList::const_iterator it = gops.begin(); it != gops.end(); it++)
+ {
+ GeneratedOperationPtr gop = *it;
+ string opname = gop->name();
+ TypePtr ret = gop->returnType();
+ string retS = typeToString(ret, TypeModeReturn, package, gop->getMetaData());
+ out << nl;
+ out << "public ";
+ if(gop->isAbstract())
+ {
+ out << "abstract ";
+ }
+ out << retS << ' ' << fixKwd(opname) << spar << getParams(gop, package) << epar;
+ if(!gop->isAbstract())
+ {
+ StringList body = gop->body();
+ out << sb;
+ for(StringList::const_iterator it = body.begin(); it != body.end(); it++)
+ {
+ out << nl << *it;
+ }
+ out << eb;
+ }
+ }
+ }
+
if(!p->isInterface() && !allDataMembers.empty())
{
//
diff --git a/cpp/src/slice2java/Gen.h b/cpp/src/slice2java/Gen.h
index 5e3f828..fab7fda 100644
--- a/cpp/src/slice2java/Gen.h
+++ b/cpp/src/slice2java/Gen.h
@@ -33,6 +33,7 @@ protected:
// Compose the parameter lists for an operation.
//
std::vector<std::string> getParams(const OperationPtr&, const std::string&, bool = false);
+ std::vector<std::string> getParams(const GeneratedOperationPtr&, const std::string&, bool = false);
std::vector<std::string> getInOutParams(const OperationPtr&, const std::string&, ParamDir);
std::vector<std::string> getParamsAsync(const OperationPtr&, const std::string&, bool);
std::vector<std::string> getParamsAsyncCB(const OperationPtr&, const std::string&);
@@ -99,7 +100,8 @@ public:
Gen(const std::string&,
const std::string&,
const std::vector<std::string>&,
- const std::string&);
+ const std::string&,
+ const std::vector<std::string>&);
~Gen();
void generate(const UnitPtr&, bool);
@@ -114,6 +116,7 @@ private:
std::string _base;
std::vector<std::string> _includePaths;
std::string _dir;
+ std::vector<std::string> _plugins;
class OpsVisitor : public JavaVisitor
{
diff --git a/cpp/src/slice2java/Main.cpp b/cpp/src/slice2java/Main.cpp
index 90978cf..281464d 100644
--- a/cpp/src/slice2java/Main.cpp
+++ b/cpp/src/slice2java/Main.cpp
@@ -80,6 +80,7 @@ usage(const char* n)
"--checksum CLASS Generate checksums for Slice definitions into CLASS.\n"
"--stream Generate marshaling support for public stream API.\n"
"--meta META Define global metadata directive META.\n"
+ "--plugin PATH Load and apply plugin before generating output.\n"
;
}
@@ -106,6 +107,7 @@ compile(int argc, char* argv[])
opts.addOpt("", "checksum", IceUtilInternal::Options::NeedArg);
opts.addOpt("", "stream");
opts.addOpt("", "meta", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
+ opts.addOpt("", "plugin", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
vector<string>args;
try
@@ -151,6 +153,8 @@ compile(int argc, char* argv[])
cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i));
}
+ vector<string> plugins = opts.argVec("plugin");
+
bool preprocess = opts.isSet("E");
string output = opts.optArg("output-dir");
@@ -308,7 +312,7 @@ compile(int argc, char* argv[])
{
try
{
- Gen gen(argv[0], icecpp->getBaseName(), includePaths, output);
+ Gen gen(argv[0], icecpp->getBaseName(), includePaths, output, plugins);
gen.generate(p, stream);
if(tie)
{
diff --git a/cpp/src/slice2py/Main.cpp b/cpp/src/slice2py/Main.cpp
index 0eed265..e31e8a8 100644
--- a/cpp/src/slice2py/Main.cpp
+++ b/cpp/src/slice2py/Main.cpp
@@ -378,6 +378,7 @@ usage(const char* n)
"--all Generate code for Slice definitions in included files.\n"
"--checksum Generate checksums for Slice definitions.\n"
"--prefix PREFIX Prepend filenames of Python modules with PREFIX.\n"
+ "--plugin PATH Load and apply plugin before generating output.\n"
;
}
@@ -400,6 +401,7 @@ compile(int argc, char* argv[])
opts.addOpt("", "no-package");
opts.addOpt("", "checksum");
opts.addOpt("", "prefix", IceUtilInternal::Options::NeedArg);
+ opts.addOpt("", "plugin", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
vector<string> args;
try
@@ -445,6 +447,8 @@ compile(int argc, char* argv[])
cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i));
}
+ vector<string> plugins = opts.argVec("plugin");
+
bool preprocess = opts.isSet("E");
string output = opts.optArg("output-dir");
@@ -597,7 +601,7 @@ compile(int argc, char* argv[])
//
// Generate the Python mapping.
//
- generate(u, all, checksum, includePaths, out);
+ generate(u, all, checksum, includePaths, out, plugins);
out.close();
diff --git a/py/modules/IcePy/Slice.cpp b/py/modules/IcePy/Slice.cpp
index b0d33be..ddeb3a4 100644
--- a/py/modules/IcePy/Slice.cpp
+++ b/py/modules/IcePy/Slice.cpp
@@ -71,6 +71,7 @@ IcePy_loadSlice(PyObject* /*self*/, PyObject* args)
opts.addOpt("", "underscore");
opts.addOpt("", "checksum");
opts.addOpt("", "all");
+ opts.addOpt("", "plugin", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
vector<string> files;
try
@@ -129,6 +130,8 @@ IcePy_loadSlice(PyObject* /*self*/, PyObject* args)
all = opts.isSet("all");
checksum = opts.isSet("checksum");
+ vector<string> plugins = opts.argVec("plugin");
+
bool ignoreRedefs = false;
bool keepComments = true;
@@ -160,7 +163,7 @@ IcePy_loadSlice(PyObject* /*self*/, PyObject* args)
ostringstream codeStream;
IceUtilInternal::Output out(codeStream);
out.setUseTab(false);
- generate(u, all, checksum, includePaths, out);
+ generate(u, all, checksum, includePaths, out, plugins);
u->destroy();
string code = codeStream.str();
-----------------------------------------------------------------------
--
asterisk-scf/release/ice.git
More information about the asterisk-scf-commits
mailing list