diff options
Diffstat (limited to 'cpp/src/Slice/PythonUtil.cpp')
-rw-r--r-- | cpp/src/Slice/PythonUtil.cpp | 1215 |
1 files changed, 558 insertions, 657 deletions
diff --git a/cpp/src/Slice/PythonUtil.cpp b/cpp/src/Slice/PythonUtil.cpp index 8fe29955ed6..05c928c0e7d 100644 --- a/cpp/src/Slice/PythonUtil.cpp +++ b/cpp/src/Slice/PythonUtil.cpp @@ -12,8 +12,6 @@ #include <Slice/Util.h> #include <IceUtil/IceUtil.h> #include <IceUtil/StringUtil.h> -#include <IceUtil/InputUtil.h> -#include <IceUtil/Unicode.h> #include <climits> #include <iterator> @@ -22,6 +20,27 @@ using namespace Slice; using namespace IceUtil; using namespace IceUtilInternal; +namespace +{ + +string +getEscapedParamName(const OperationPtr& p, const string& name) +{ + ParamDeclList params = p->parameters(); + + for(ParamDeclList::const_iterator i = params.begin(); i != params.end(); ++i) + { + if((*i)->name() == name) + { + return name + "_"; + } + } + return name; +} + +} + + namespace Slice { namespace Python @@ -49,7 +68,7 @@ private: // // Validates sequence metadata. // - void validateSequence(const string&, const string&, const TypePtr&, const StringList&); + StringList validateSequence(const string&, const string&, const TypePtr&, const StringList&); // // Checks a definition that doesn't currently support Python metadata. @@ -105,9 +124,14 @@ public: private: // + // Emit Python code for the class operations + // + void writeOperations(const ClassDefPtr&); + + // // Return a Python symbol for the given parser element. // - string getSymbol(const ContainedPtr&, const string& = string()); + string getSymbol(const ContainedPtr&, const string& = "", const string& = ""); // // Emit Python code to assign the given symbol in the current module. @@ -183,7 +207,7 @@ private: }; bool parseOpComment(const string&, OpComment&); - enum DocstringMode { DocSync, DocAsyncBegin, DocAsyncEnd, DocDispatch, DocAsyncDispatch }; + enum DocstringMode { DocSync, DocAsync, DocAsyncBegin, DocAsyncEnd, DocDispatch, DocAsyncDispatch }; void writeDocstring(const OperationPtr&, DocstringMode, bool); @@ -196,44 +220,6 @@ private: } } -string -u32CodePoint(unsigned int value) -{ - ostringstream s; - s << "\\U"; - s << hex; - s.width(8); - s.fill('0'); - s << value; - return s.str(); -} - -void -writeU8Buffer(const vector<unsigned char>& u8buffer, ostringstream& out) -{ - vector<unsigned int> u32buffer; - IceUtilInternal::ConversionResult result = convertUTF8ToUTF32(u8buffer, u32buffer, IceUtil::lenientConversion); - switch(result) - { - case conversionOK: - break; - case sourceExhausted: - throw IceUtil::IllegalConversionException(__FILE__, __LINE__, "string source exhausted"); - case sourceIllegal: - throw IceUtil::IllegalConversionException(__FILE__, __LINE__, "string source illegal"); - default: - { - assert(0); - throw IceUtil::IllegalConversionException(__FILE__, __LINE__); - } - } - - for(vector<unsigned int>::const_iterator c = u32buffer.begin(); c != u32buffer.end(); ++c) - { - out << u32CodePoint(*c); - } -} - static string lookupKwd(const string& name) { @@ -288,7 +274,7 @@ splitScopedName(const string& scoped) } static string -getDictLookup(const ContainedPtr& cont, const string& suffix = string()) +getDictLookup(const ContainedPtr& cont, const string& suffix = "", const string& prefix = "") { string scope = Slice::Python::scopedToName(cont->scope()); assert(!scope.empty()); @@ -299,7 +285,7 @@ getDictLookup(const ContainedPtr& cont, const string& suffix = string()) scope = package + "." + scope; } - return "'" + suffix + Slice::Python::fixIdent(cont->name()) + "' not in _M_" + scope + "__dict__"; + return "'" + suffix + Slice::Python::fixIdent(cont->name() + prefix) + "' not in _M_" + scope + "__dict__"; } // @@ -356,7 +342,8 @@ Slice::Python::ModuleVisitor::visitModuleStart(const ModulePtr& p) // CodeVisitor implementation. // Slice::Python::CodeVisitor::CodeVisitor(Output& out, set<string>& moduleHistory) : - _out(out), _moduleHistory(moduleHistory) + _out(out), + _moduleHistory(moduleHistory) { } @@ -440,10 +427,15 @@ Slice::Python::CodeVisitor::visitClassDecl(const ClassDeclPtr& p) { _out << sp << nl << "if " << getDictLookup(p) << ':'; _out.inc(); - string type = getAbsolute(p, "_t_"); - _out << nl << "_M_" << type << " = IcePy.declareClass('" << scoped << "')"; - if(!p->isLocal()) + + if(!p->isInterface() || p->isLocal()) { + _out << nl << "_M_" << getAbsolute(p, "_t_") << " = IcePy.declareValue('" << scoped << "')"; + } + + if(!p->isLocal() && (p->isInterface() || p->definition()->allOperations().size())) + { + _out << nl << "_M_" << getAbsolute(p, "_t_", "Disp") << " = IcePy.declareClass('" << scoped << "')"; _out << nl << "_M_" << getAbsolute(p, "_t_", "Prx") << " = IcePy.declareProxy('" << scoped << "')"; } _out.dec(); @@ -451,150 +443,10 @@ Slice::Python::CodeVisitor::visitClassDecl(const ClassDeclPtr& p) } } -bool -Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) +void +Slice::Python::CodeVisitor::writeOperations(const ClassDefPtr& p) { - string scoped = p->scoped(); - string type = getAbsolute(p, "_t_"); - string abs = getAbsolute(p); - string name = fixIdent(p->name()); - string prxAbs = getAbsolute(p, "", "Prx"); - string prxName = fixIdent(p->name() + "Prx"); - string prxType = getAbsolute(p, "_t_", "Prx"); - ClassList bases = p->bases(); - ClassDefPtr base; OperationList ops = p->operations(); - bool isAbstract = p->isInterface() || p->allOperations().size() > 0; // Don't use isAbstract() - see bug 3739 - - // - // Define the class. - // - _out << sp << nl << "if " << getDictLookup(p) << ':'; - _out.inc(); - _out << nl << "_M_" << abs << " = Ice.createTempClass()"; - _out << nl << "class " << name << '('; - if(bases.empty()) - { - if(p->isLocal()) - { - _out << "object"; - } - else - { - _out << "Ice.Object"; - } - } - else - { - for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) - { - if(q != bases.begin()) - { - _out << ", "; - } - _out << getSymbol(*q); - } - if(!bases.front()->isInterface()) - { - base = bases.front(); - } - } - _out << "):"; - - _out.inc(); - - writeDocstring(p->comment(), p->dataMembers()); - - // - // __init__ - // - _out << nl << "def __init__(self"; - MemberInfoList allMembers; - collectClassMembers(p, allMembers, false); - writeConstructorParams(allMembers); - _out << "):"; - _out.inc(); - if(!base && !p->hasDataMembers() && !isAbstract) - { - _out << nl << "pass"; - } - else - { - if(isAbstract) - { - _out << nl << "if Ice.getType(self) == _M_" << abs << ':'; - _out.inc(); - _out << nl << "raise RuntimeError('" << abs << " is an abstract class')"; - _out.dec(); - } - if(base) - { - _out << nl << getSymbol(base) << ".__init__(self"; - for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) - { - if(q->inherited) - { - _out << ", " << q->fixedName; - } - } - _out << ')'; - } - for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) - { - if(!q->inherited) - { - writeAssign(*q); - } - } - } - _out.dec(); - - if(!p->isLocal()) - { - // - // ice_ids - // - ClassList allBases = p->allBases(); - StringList ids; - transform(allBases.begin(), allBases.end(), back_inserter(ids), IceUtil::constMemFun(&Contained::scoped)); - StringList other; - other.push_back(scoped); - other.push_back("::Ice::Object"); - other.sort(); - ids.merge(other); - ids.unique(); - _out << sp << nl << "def ice_ids(self, current=None):"; - _out.inc(); - _out << nl << "return ("; - for(StringList::iterator q = ids.begin(); q != ids.end(); ++q) - { - if(q != ids.begin()) - { - _out << ", "; - } - _out << "'" << *q << "'"; - } - _out << ')'; - _out.dec(); - - // - // ice_id - // - _out << sp << nl << "def ice_id(self, current=None):"; - _out.inc(); - _out << nl << "return '" << scoped << "'"; - _out.dec(); - - // - // ice_staticId - // - _out << sp << nl << "def ice_staticId():"; - _out.inc(); - _out << nl << "return '" << scoped << "'"; - _out.dec(); - _out << nl << "ice_staticId = staticmethod(ice_staticId)"; - } - if(!ops.empty()) { // @@ -603,9 +455,9 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) for(OperationList::iterator oli = ops.begin(); oli != ops.end(); ++oli) { string fixedOpName = fixIdent((*oli)->name()); - if(!p->isLocal() && (p->hasMetaData("amd") || (*oli)->hasMetaData("amd"))) + if(!p->isLocal()) { - _out << sp << nl << "def " << (*oli)->name() << "_async(self, _cb"; + _out << sp << nl << "def " << fixedOpName << "(self"; ParamDeclList params = (*oli)->parameters(); @@ -616,9 +468,11 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) _out << ", " << fixIdent((*pli)->name()); } } + if(!p->isLocal()) { - _out << ", current=None"; + const string currentParamName = getEscapedParamName(*oli, "current"); + _out << ", " << currentParamName << "=None"; } _out << "):"; _out.inc(); @@ -643,7 +497,8 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) } if(!p->isLocal()) { - _out << ", current=None"; + const string currentParamName = getEscapedParamName(*oli, "current"); + _out << ", " << currentParamName << "=None"; } _out << "):"; _out.inc(); @@ -653,44 +508,276 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) } } } +} - // - // __str__ - // - _out << sp << nl << "def __str__(self):"; - _out.inc(); - _out << nl << "return IcePy.stringify(self, _M_" << getAbsolute(p, "_t_") << ")"; - _out.dec(); - _out << sp << nl << "__repr__ = __str__"; +bool +Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + bool isLocal = p->isLocal(); + bool isInterface = p->isInterface(); + bool isAbstract = isInterface || p->allOperations().size() > 0; // Don't use isAbstract() - see bug 3739 - _out.dec(); + string scoped = p->scoped(); + string type = getAbsolute(p, "_t_"); + string classType = getAbsolute(p, "_t_", "Disp"); + string abs = getAbsolute(p); + string className = isLocal ? fixIdent(p->name()) : isAbstract ? fixIdent("_" + p->name() + "Disp") : "None"; + string classAbs = getAbsolute(p, "_", "Disp"); + string valueName = (isInterface && !isLocal) ? "Ice.Value" : fixIdent(p->name()); + string prxAbs = getAbsolute(p, "", "Prx"); + string prxName = fixIdent(p->name() + "Prx"); + string prxType = getAbsolute(p, "_t_", "Prx"); + ClassList bases = p->bases(); + ClassDefPtr base; + + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } // - // Define the proxy class. + // Define a class type for Value types or local classes. // - if(!p->isLocal()) + if(isLocal || !isInterface) { - _out << sp << nl << "_M_" << prxAbs << " = Ice.createTempClass()"; - _out << nl << "class " << prxName << "("; - if(bases.empty()) + _out << sp << nl << "if " << getDictLookup(p) << ':'; + _out.inc(); + _out << nl << "_M_" << abs << " = Ice.createTempClass()"; + _out << nl << "class " << valueName << '('; + if(isLocal) { - _out << "Ice.ObjectPrx"; + if(bases.empty()) + { + _out << "object"; + } + else + { + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + if(q != bases.begin()) + { + _out << ", "; + } + _out << getSymbol(*q); + } + } } else { - ClassList::const_iterator q = bases.begin(); - while(q != bases.end()) + if(bases.empty() || bases.front()->isInterface()) { - _out << getSymbol(*q, "Prx"); - if(++q != bases.end()) + _out << "Ice.Value"; + } + else + { + _out << getSymbol(bases.front()); + } + } + _out << "):"; + + _out.inc(); + + writeDocstring(p->comment(), p->dataMembers()); + + // + // __init__ + // + _out << nl << "def __init__(self"; + MemberInfoList allMembers; + collectClassMembers(p, allMembers, false); + writeConstructorParams(allMembers); + _out << "):"; + _out.inc(); + if(!base && !p->hasDataMembers() && (!isAbstract || !isLocal)) + { + _out << nl << "pass"; + } + else + { + if(isAbstract && isLocal) + { + _out << nl << "if Ice.getType(self) == _M_" << abs << ':'; + _out.inc(); + _out << nl << "raise RuntimeError('" << abs << " is an abstract class')"; + _out.dec(); + } + if(base) + { + _out << nl << getSymbol(base) << ".__init__(self"; + for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { - _out << ", "; + if(q->inherited) + { + _out << ", " << q->fixedName; + } + } + _out << ')'; + } + for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(!q->inherited) + { + writeAssign(*q); + } + } + } + _out.dec(); + + if(!isLocal) + { + // + // ice_id + // + _out << sp << nl << "def ice_id(self):"; + _out.inc(); + _out << nl << "return '" << scoped << "'"; + _out.dec(); + + // + // ice_staticId + // + _out << sp << nl << "@staticmethod"; + _out << nl << "def ice_staticId():"; + _out.inc(); + _out << nl << "return '" << scoped << "'"; + _out.dec(); + } + else + { + writeOperations(p); + } + + // + // __str__ + // + _out << sp << nl << "def __str__(self):"; + _out.inc(); + _out << nl << "return IcePy.stringify(self, _M_" << type << ")"; + _out.dec(); + _out << sp << nl << "__repr__ = __str__"; + + _out.dec(); + + if(_classHistory.count(scoped) == 0 && p->canBeCyclic()) + { + // + // Emit a forward declaration for the class in case a data member refers to this type. + // + _out << sp << nl << "_M_" << type << " = IcePy.declareValue('" << scoped << "')"; + } + DataMemberList members = p->dataMembers(); + _out << sp << nl << "_M_" << type << " = IcePy.defineValue('" << scoped << "', " << valueName + << ", " << p->compactId() << ", "; + writeMetaData(p->getMetaData()); + const bool preserved = p->hasMetaData("preserve-slice") || p->inheritsMetaData("preserve-slice"); + _out << ", " << (preserved ? "True" : "False") << ", " << (isInterface ? "True" : "False") << ", "; + if(!base) + { + _out << "None"; + } + else + { + _out << "_M_" << getAbsolute(base, "_t_"); + } + _out << ", ("; + // + // Members + // + // Data members are represented as a tuple: + // + // ('MemberName', MemberMetaData, MemberType, Optional, Tag) + // + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // + if(members.size() > 1) + { + _out.inc(); + _out << nl; + } + bool isProtected = p->hasMetaData("protected"); + for(DataMemberList::iterator r = members.begin(); r != members.end(); ++r) + { + if(r != members.begin()) + { + _out << ',' << nl; + } + _out << "('"; + if(isProtected || (*r)->hasMetaData("protected")) + { + _out << '_'; + } + _out << fixIdent((*r)->name()) << "', "; + writeMetaData((*r)->getMetaData()); + _out << ", "; + writeType((*r)->type()); + _out << ", " << ((*r)->optional() ? "True" : "False") << ", " + << ((*r)->optional() ? (*r)->tag() : 0) << ')'; + } + if(members.size() == 1) + { + _out << ','; + } + else if(members.size() > 1) + { + _out.dec(); + _out << nl; + } + _out << "))"; + _out << nl << valueName << "._ice_type = _M_" << type; + + registerName(valueName); + + _out.dec(); + } + else if(!isLocal && isInterface) + { + _out << sp << nl << "_M_" << type << " = IcePy.defineValue('" << scoped << "', Ice.Value, -1, "; + writeMetaData(p->getMetaData()); + _out << ", False, True, None, ())"; + } + + if(!isLocal && isAbstract) + { + _out << sp << nl << "if " << getDictLookup(p, "", "Prx") << ':'; + _out.inc(); + + // Define the proxy class + _out << nl << "_M_" << prxAbs << " = Ice.createTempClass()"; + _out << nl << "class " << prxName << '('; + + { + vector<string> baseClasses; + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + ClassDefPtr d = *q; + if(d->isInterface() || d->allOperations().size() > 0) + { + baseClasses.push_back(getSymbol(*q, "", "Prx")); + } + } + + if(baseClasses.empty()) + { + _out << "Ice.ObjectPrx"; + } + else + { + vector<string>::const_iterator q = baseClasses.begin(); + while(q != baseClasses.end()) + { + _out << *q; + + if(++q != baseClasses.end()) + { + _out << ", "; + } } } } _out << "):"; _out.inc(); + OperationList ops = p->operations(); for(OperationList::iterator oli = ops.begin(); oli != ops.end(); ++oli) { string fixedOpName = fixIdent((*oli)->name()); @@ -721,170 +808,227 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) { _out << ", " << inParams; } - _out << ", _ctx=None):"; + const string contextParamName = getEscapedParamName(*oli, "context"); + _out << ", " << contextParamName << "=None):"; _out.inc(); - _out << nl << "return _M_" << abs << "._op_" << (*oli)->name() << ".invoke(self, ((" << inParams; + _out << nl << "return _M_" << classAbs << "._op_" << (*oli)->name() << ".invoke(self, ((" << inParams; if(!inParams.empty() && inParams.find(',') == string::npos) { _out << ", "; } - _out << "), _ctx))"; + _out << "), " << contextParamName << "))"; _out.dec(); // // Async operations. // _out << sp; + writeDocstring(*oli, DocAsync, false); + _out << nl << "def " << (*oli)->name() << "Async(self"; + if(!inParams.empty()) + { + _out << ", " << inParams; + } + _out << ", " << contextParamName << "=None):"; + _out.inc(); + _out << nl << "return _M_" << classAbs << "._op_" << (*oli)->name() << ".invokeAsync(self, ((" << inParams; + if(!inParams.empty() && inParams.find(',') == string::npos) + { + _out << ", "; + } + _out << "), " << contextParamName << "))"; + _out.dec(); + + _out << sp; writeDocstring(*oli, DocAsyncBegin, false); _out << nl << "def begin_" << (*oli)->name() << "(self"; if(!inParams.empty()) { _out << ", " << inParams; } - _out << ", _response=None, _ex=None, _sent=None, _ctx=None):"; + _out << ", _response=None, _ex=None, _sent=None, " << contextParamName << "=None):"; _out.inc(); - _out << nl << "return _M_" << abs << "._op_" << (*oli)->name() << ".begin(self, ((" << inParams; + _out << nl << "return _M_" << classAbs << "._op_" << (*oli)->name() << ".begin(self, ((" << inParams; if(!inParams.empty() && inParams.find(',') == string::npos) { _out << ", "; } - _out << "), _response, _ex, _sent, _ctx))"; + _out << "), _response, _ex, _sent, " << contextParamName << "))"; _out.dec(); _out << sp; writeDocstring(*oli, DocAsyncEnd, false); _out << nl << "def end_" << (*oli)->name() << "(self, _r):"; _out.inc(); - _out << nl << "return _M_" << abs << "._op_" << (*oli)->name() << ".end(self, _r)"; + _out << nl << "return _M_" << classAbs << "._op_" << (*oli)->name() << ".end(self, _r)"; _out.dec(); } - _out << sp << nl << "def checkedCast(proxy, facetOrCtx=None, _ctx=None):"; + _out << sp << nl << "@staticmethod"; + _out << nl << "def checkedCast(proxy, facetOrContext=None, context=None):"; _out.inc(); - _out << nl << "return _M_" << prxAbs << ".ice_checkedCast(proxy, '" << scoped << "', facetOrCtx, _ctx)"; + _out << nl << "return _M_" << prxAbs << ".ice_checkedCast(proxy, '" << scoped << "', facetOrContext, context)"; _out.dec(); - _out << nl << "checkedCast = staticmethod(checkedCast)"; - _out << sp << nl << "def uncheckedCast(proxy, facet=None):"; + _out << sp << nl << "@staticmethod"; + _out << nl << "def uncheckedCast(proxy, facet=None):"; _out.inc(); _out << nl << "return _M_" << prxAbs << ".ice_uncheckedCast(proxy, facet)"; _out.dec(); - _out << nl << "uncheckedCast = staticmethod(uncheckedCast)"; - // + // // ice_staticId // - _out << sp << nl << "def ice_staticId():"; + _out << sp << nl << "@staticmethod"; + _out << nl << "def ice_staticId():"; _out.inc(); _out << nl << "return '" << scoped << "'"; _out.dec(); - _out << nl << "ice_staticId = staticmethod(ice_staticId)"; - _out.dec(); + _out.dec(); // end prx class - _out << sp << nl << "_M_" << prxType << " = IcePy.defineProxy('" << scoped << "', " << prxName << ")"; - } + _out << nl << "_M_" << prxType << " = IcePy.defineProxy('" << scoped << "', " << prxName << ")"; + + registerName(prxName); + + // Define the servant class + _out << sp << nl << "_M_" << classAbs << " = Ice.createTempClass()"; + _out << nl << "class " << className << '('; + { + vector<string> baseClasses; + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + ClassDefPtr d = *q; + if(d->isInterface() || d->allOperations().size() > 0) + { + baseClasses.push_back(getSymbol(*q, "_", "Disp")); + } + } + + if(baseClasses.empty()) + { + _out << "Ice.Object"; + } + else + { + vector<string>::const_iterator q = baseClasses.begin(); + while(q != baseClasses.end()) + { + _out << *q; + + if(++q != baseClasses.end()) + { + _out << ", "; + } + } + } + } + _out << "):"; + + _out.inc(); - if(_classHistory.count(scoped) == 0 && p->canBeCyclic()) - { // - // Emit a forward declaration for the class in case a data member refers to this type. + // ice_ids // - _out << sp << nl << "_M_" << type << " = IcePy.declareClass('" << scoped << "')"; - } - - DataMemberList members = p->dataMembers(); - _out << sp << nl << "_M_" << type << " = IcePy.defineClass('" << scoped << "', " << name << ", " << p->compactId() - << ", "; - writeMetaData(p->getMetaData()); - const bool preserved = p->hasMetaData("preserve-slice") || p->inheritsMetaData("preserve-slice"); - _out << ", " << (isAbstract ? "True" : "False") << ", " << (preserved ? "True" : "False") << ", "; - if(!base) - { - _out << "None"; - } - else - { - _out << "_M_" << getAbsolute(base, "_t_"); - } - _out << ", ("; - // - // Interfaces - // - int interfaceCount = 0; - for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) - { - if((*q)->isInterface()) + ClassList allBases = p->allBases(); + StringList ids; + transform(allBases.begin(), allBases.end(), back_inserter(ids), IceUtil::constMemFun(&Contained::scoped)); + StringList other; + other.push_back(scoped); + other.push_back("::Ice::Object"); + other.sort(); + ids.merge(other); + ids.unique(); + _out << sp << nl << "def ice_ids(self, current=None):"; + _out.inc(); + _out << nl << "return ("; + for(StringList::iterator q = ids.begin(); q != ids.end(); ++q) { - if(interfaceCount > 0) + if(q != ids.begin()) { _out << ", "; } - _out << "_M_" << getAbsolute(*q, "_t_"); - ++interfaceCount; + _out << "'" << *q << "'"; } - } - if(interfaceCount == 1) - { - _out << ','; - } - // - // Members - // - // Data members are represented as a tuple: - // - // ('MemberName', MemberMetaData, MemberType, Optional, Tag) - // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. - // - _out << "), ("; - if(members.size() > 1) - { + _out << ')'; + _out.dec(); + + // + // ice_id + // + _out << sp << nl << "def ice_id(self, current=None):"; _out.inc(); - _out << nl; - } - bool isProtected = p->hasMetaData("protected"); - for(DataMemberList::iterator r = members.begin(); r != members.end(); ++r) - { - if(r != members.begin()) + _out << nl << "return '" << scoped << "'"; + _out.dec(); + + // + // ice_staticId + // + _out << sp << nl << "@staticmethod"; + _out << nl << "def ice_staticId():"; + _out.inc(); + _out << nl << "return '" << scoped << "'"; + _out.dec(); + + writeOperations(p); + + // + // __str__ + // + _out << sp << nl << "def __str__(self):"; + _out.inc(); + _out << nl << "return IcePy.stringify(self, _M_" << getAbsolute(p, "_t_", "Disp") << ")"; + _out.dec(); + _out << sp << nl << "__repr__ = __str__"; + + _out.dec(); + + _out << sp << nl << "_M_" << classType << " = IcePy.defineClass('" << scoped << "', " << className + << ", "; + writeMetaData(p->getMetaData()); + _out << ", "; + if(!base || (!base->isInterface() && base->allOperations().size() == 0)) { - _out << ',' << nl; + _out << "None"; } - _out << "('"; - if(isProtected || (*r)->hasMetaData("protected")) + else { - _out << '_'; + _out << "_M_" << getAbsolute(base, "_t_", "Disp"); } - _out << fixIdent((*r)->name()) << "', "; - writeMetaData((*r)->getMetaData()); - _out << ", "; - writeType((*r)->type()); - _out << ", " << ((*r)->optional() ? "True" : "False") << ", " - << ((*r)->optional() ? (*r)->tag() : 0) << ')'; - } - if(members.size() == 1) - { - _out << ','; - } - else if(members.size() > 1) - { - _out.dec(); - _out << nl; - } - _out << "))"; - _out << nl << name << "._ice_type = _M_" << type; + _out << ", ("; + // + // Interfaces + // + int interfaceCount = 0; + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + if((*q)->isInterface()) + { + if(interfaceCount > 0) + { + _out << ", "; + } + _out << "_M_" << getAbsolute(*q, "_t_", "Disp"); + ++interfaceCount; + } + } + if(interfaceCount == 1) + { + _out << ','; + } + _out << "))"; + _out << nl << className << "._ice_type = _M_" << classType; - // - // Define each operation. The arguments to the IcePy.Operation constructor are: - // - // 'opName', Mode, SendMode, AMD, Format, MetaData, (InParams), (OutParams), ReturnParam, (Exceptions) - // - // where InParams and OutParams are tuples of type descriptions, and Exceptions - // is a tuple of exception type ids. - // - if(!p->isLocal()) - { + + // + // Define each operation. The arguments to the IcePy.Operation constructor are: + // + // 'opName', Mode, SendMode, AMD, Format, MetaData, (InParams), (OutParams), ReturnParam, (Exceptions) + // + // where InParams and OutParams are tuples of type descriptions, and Exceptions + // is a tuple of exception type ids. + // if(!ops.empty()) { _out << sp; @@ -908,10 +1052,10 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) break; } - _out << nl << name << "._op_" << (*s)->name() << " = IcePy.Operation('" << (*s)->name() << "', " - << getOperationMode((*s)->mode()) << ", " << getOperationMode((*s)->sendMode()) << ", " - << ((p->hasMetaData("amd") || (*s)->hasMetaData("amd")) ? "True" : "False") << ", " - << format << ", "; + _out << nl << className << "._op_" << (*s)->name() << " = IcePy.Operation('" << (*s)->name() << "', " + << getOperationMode((*s)->mode()) << ", " << getOperationMode((*s)->sendMode()) << ", " + << ((p->hasMetaData("amd") || (*s)->hasMetaData("amd")) ? "True" : "False") << ", " + << format << ", "; writeMetaData((*s)->getMetaData()); _out << ", ("; for(t = params.begin(), count = 0; t != params.end(); ++t) @@ -949,7 +1093,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) _out << ", "; writeType((*t)->type()); _out << ", " << ((*t)->optional() ? "True" : "False") << ", " - << ((*t)->optional() ? (*t)->tag() : 0) << ')'; + << ((*t)->optional() ? (*t)->tag() : 0) << ')'; ++count; } } @@ -1000,20 +1144,14 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) { msg = deprecateMetadata.substr(pos + 1); } - _out << nl << name << "._op_" << (*s)->name() << ".deprecate(\"" << msg << "\")"; + _out << nl << className << "._op_" << (*s)->name() << ".deprecate(\"" << msg << "\")"; } } - } - registerName(name); - - if(!p->isLocal()) - { - registerName(prxName); + registerName(className); + _out.dec(); } - _out.dec(); - if(_classHistory.count(scoped) == 0) { _classHistory.insert(scoped); // Avoid redundant declarations. @@ -1102,9 +1240,9 @@ Slice::Python::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) _out << sp << nl << "__repr__ = __str__"; // - // _ice_name + // _ice_id // - _out << sp << nl << "_ice_name = '" << scoped.substr(2) << "'"; + _out << sp << nl << "_ice_id = '" << scoped << "'"; _out.dec(); @@ -1515,7 +1653,7 @@ Slice::Python::CodeVisitor::visitEnum(const EnumPtr& p) string scoped = p->scoped(); string abs = getAbsolute(p); string name = fixIdent(p->name()); - EnumeratorList enums = p->getEnumerators(); + EnumeratorList enums = p->enumerators(); EnumeratorList::iterator q; _out << sp << nl << "if " << getDictLookup(p) << ':'; @@ -1586,12 +1724,12 @@ Slice::Python::CodeVisitor::visitConst(const ConstPtr& p) } string -Slice::Python::CodeVisitor::getSymbol(const ContainedPtr& p, const string& nameSuffix) +Slice::Python::CodeVisitor::getSymbol(const ContainedPtr& p, const string& prefix, const string& suffix) { // // An explicit reference to another type must always be prefixed with "_M_". // - return "_M_" + getAbsolute(p, "", nameSuffix); + return "_M_" + getAbsolute(p, prefix, suffix); } void @@ -1651,8 +1789,9 @@ Slice::Python::CodeVisitor::writeType(const TypePtr& p) break; } case Builtin::KindObject: + case Builtin::KindValue: { - _out << "IcePy._t_Object"; + _out << "IcePy._t_Value"; break; } case Builtin::KindObjectProxy: @@ -1672,7 +1811,15 @@ Slice::Python::CodeVisitor::writeType(const TypePtr& p) ProxyPtr prx = ProxyPtr::dynamicCast(p); if(prx) { - _out << "_M_" << getAbsolute(prx->_class(), "_t_", "Prx"); + ClassDefPtr def = prx->_class()->definition(); + if(def->isInterface() || def->allOperations().size() > 0) + { + _out << "_M_" << getAbsolute(prx->_class(), "_t_", "Prx"); + } + else + { + _out << "IcePy._t_ObjectPrx"; + } return; } @@ -1714,6 +1861,7 @@ Slice::Python::CodeVisitor::writeInitializer(const DataMemberPtr& m) _out << "''"; break; } + case Builtin::KindValue: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: @@ -1728,7 +1876,7 @@ Slice::Python::CodeVisitor::writeInitializer(const DataMemberPtr& m) EnumPtr en = EnumPtr::dynamicCast(p); if(en) { - EnumeratorList enums = en->getEnumerators(); + EnumeratorList enums = en->enumerators(); _out << getSymbol(en) << "." << fixIdent(enums.front()->name()); return; } @@ -1875,274 +2023,17 @@ Slice::Python::CodeVisitor::writeConstantValue(const TypePtr& type, const Syntax } case Slice::Builtin::KindString: { - ostringstream sv2; - ostringstream sv3; - - // - // Expand strings into the basic source character set. We can't use isalpha() and the like - // here because they are sensitive to the current locale. - // - static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789" - "_{}[]#()<>%:;.?*+-/^&|~!=, '"; - static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end()); + string sv2 = toStringLiteral(value, "\a\b\f\n\r\t\v", "", Octal, 0); + string sv3 = toStringLiteral(value, "\a\b\f\n\r\t\v", "", UCN, 0); - for(size_t i = 0; i < value.size();) + _out << "\"" << sv2<< "\""; + if(sv2 != sv3) { - char c = value[i]; - switch(c) - { - case '"': - { - sv2 << "\\\""; - break; - } - case '\\': - { - string s = "\\"; - size_t j = i + 1; - for(; j < value.size(); ++j) - { - if(value[j] != '\\') - { - break; - } - s += "\\"; - } - - // - // An even number of slash \ will escape the backslash and - // the codepoint will be interpreted as its charaters - // - // \\u00000041 - ['\\', 'u', '0', '0', '0', '0', '0', '0', '4', '1'] - // \\\u00000041 - ['\\', 'A'] (41 is the codepoint for 'A') - // - if(s.size() % 2 != 0 && (value[j] == 'U' || value[j] == 'u')) - { - // - // Convert codepoint to UTF8 bytes and write the escaped bytes - // - sv2 << s.substr(0, s.size() - 1); - - size_t sz = value[j] == 'U' ? 8 : 4; - string codepoint = value.substr(j + 1, sz); - assert(codepoint.size() == sz); - - IceUtil::Int64 v = IceUtilInternal::strToInt64(codepoint.c_str(), 0, 16); - - vector<unsigned int> u32buffer; - u32buffer.push_back(static_cast<unsigned int>(v)); - - vector<unsigned char> u8buffer; - IceUtilInternal::ConversionResult result = convertUTF32ToUTF8(u32buffer, u8buffer, IceUtil::lenientConversion); - switch(result) - { - case conversionOK: - break; - case sourceExhausted: - throw IceUtil::IllegalConversionException(__FILE__, __LINE__, "string source exhausted"); - case sourceIllegal: - throw IceUtil::IllegalConversionException(__FILE__, __LINE__, "string source illegal"); - default: - { - assert(0); - throw IceUtil::IllegalConversionException(__FILE__, __LINE__); - } - } - - ostringstream s; - for(vector<unsigned char>::const_iterator q = u8buffer.begin(); q != u8buffer.end(); ++q) - { - s << "\\"; - s.fill('0'); - s.width(3); - s << oct; - s << static_cast<unsigned int>(*q); - } - sv2 << s.str(); - - i = j + 1 + sz; - } - else - { - sv2 << s; - i = j; - } - continue; - } - case '\r': - { - sv2 << "\\r"; - break; - } - case '\n': - { - sv2 << "\\n"; - break; - } - case '\t': - { - sv2 << "\\t"; - break; - } - case '\b': - { - sv2 << "\\b"; - break; - } - case '\f': - { - sv2 << "\\f"; - break; - } - default: - { - if(charSet.find(c) == charSet.end()) - { - unsigned char uc = c; // Char may be signed, so make it positive. - stringstream s; - s << "\\"; // Print as octal if not in basic source character set. - s.flags(ios_base::oct); - s.width(3); - s.fill('0'); - s << static_cast<unsigned>(uc); - sv2 << s.str(); - } - else - { - sv2 << c; // Print normally if in basic source character set. - } - break; - } - } - ++i; - } - - vector<unsigned char> u8buffer; // Buffer to convert multibyte characters - - for(size_t i = 0; i < value.size();) - { - if(charSet.find(value[i]) == charSet.end()) - { - char c = value[i]; - if(static_cast<unsigned char>(c) < 128) // Single byte character - { - // - // Print as unicode if not in basic source character set - // - switch(c) - { - // - // Don't encode this special characters as universal characters - // - case '\r': - { - sv3 << "\\r"; - break; - } - case '\n': - { - sv3 << "\\n"; - break; - } - case '\\': - { - sv3 << "\\"; - break; - } - default: - { - sv3 << u32CodePoint(c); - break; - } - } - } - else - { - u8buffer.push_back(value[i]); - } - } - else - { - // - // Write any pedding characters in the utf8 buffer - // - if(!u8buffer.empty()) - { - writeU8Buffer(u8buffer, sv3); - u8buffer.clear(); - } - switch(value[i]) - { - case '\\': - { - string s = "\\"; - size_t j = i + 1; - for(; j < value.size(); ++j) - { - if(value[j] != '\\') - { - break; - } - s += "\\"; - } - - // - // An even number of slash \ will escape the backslash and - // the codepoint will be interpreted as its charaters - // - // \\U00000041 - ['\\', 'U', '0', '0', '0', '0', '0', '0', '4', '1'] - // \\\U00000041 - ['\\', 'A'] (41 is the codepoint for 'A') - // - if(s.size() % 2 != 0 && (value[j] == 'U' || value[j] == 'u')) - { - size_t sz = value[j] == 'U' ? 8 : 4; - sv3 << s.substr(0, s.size() - 1); - i = j + 1; - - string codepoint = value.substr(j + 1, sz); - assert(codepoint.size() == sz); - - IceUtil::Int64 v = IceUtilInternal::strToInt64(codepoint.c_str(), 0, 16); - sv3 << u32CodePoint(static_cast<unsigned int>(v)); - i = j + 1 + sz; - } - else - { - sv3 << s; - i = j; - } - continue; - } - case '"': - { - sv3 << "\\"; - break; - } - } - sv3 << value[i]; // Print normally if in basic source character set - } - i++; - } - - // - // Write any pedding characters in the utf8 buffer - // - if(!u8buffer.empty()) - { - writeU8Buffer(u8buffer, sv3); - u8buffer.clear(); - } - - - _out << "\"" << sv2.str() << "\""; - if(sv2.str() != sv3.str()) - { - _out << " if _version_info_[0] < 3 else \"" << sv3.str() << "\""; + _out << " if _version_info_[0] < 3 else \"" << sv3 << "\""; } break; } + case Slice::Builtin::KindValue: case Slice::Builtin::KindObject: case Slice::Builtin::KindObjectProxy: case Slice::Builtin::KindLocalObject: @@ -2151,18 +2042,9 @@ Slice::Python::CodeVisitor::writeConstantValue(const TypePtr& type, const Syntax } else if(en) { - string enumName = getSymbol(en); - string::size_type colon = value.rfind(':'); - string enumerator; - if(colon != string::npos) - { - enumerator = fixIdent(value.substr(colon + 1)); - } - else - { - enumerator = fixIdent(value); - } - _out << enumName << '.' << enumerator; + EnumeratorPtr lte = EnumeratorPtr::dynamicCast(valueType); + assert(lte); + _out << getSymbol(lte); } else { @@ -2781,7 +2663,7 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, DocstringMode { return; } - else if(mode == DocAsyncBegin && inParams.empty()) + else if((mode == DocAsync || mode == DocAsyncBegin) && inParams.empty()) { return; } @@ -2814,6 +2696,7 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, DocstringMode switch(mode) { case DocSync: + case DocAsync: case DocAsyncBegin: case DocDispatch: needArgs = !local || !inParams.empty(); @@ -2827,10 +2710,6 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, DocstringMode if(needArgs) { _out << nl << "Arguments:"; - if(mode == DocAsyncDispatch) - { - _out << nl << "_cb -- The asynchronous callback object."; - } for(vector<string>::iterator q = inParams.begin(); q != inParams.end(); ++q) { string fixed = fixIdent(*q); @@ -2851,13 +2730,15 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, DocstringMode << nl << "_ex -- The asynchronous exception callback." << nl << "_sent -- The asynchronous sent callback."; } - if(!local && (mode == DocSync || mode == DocAsyncBegin)) + if(!local && (mode == DocSync || mode == DocAsync || mode == DocAsyncBegin)) { - _out << nl << "_ctx -- The request context for the invocation."; + const string contextParamName = getEscapedParamName(op, "context"); + _out << nl << contextParamName << " -- The request context for the invocation."; } if(!local && (mode == DocDispatch || mode == DocAsyncDispatch)) { - _out << nl << "current -- The Current object for the invocation."; + const string currentParamName = getEscapedParamName(op, "current"); + _out << nl << currentParamName << " -- The Current object for the invocation."; } } else if(mode == DocAsyncEnd) @@ -2869,6 +2750,10 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, DocstringMode // // Emit return value(s). // + if(mode == DocAsync || mode == DocAsyncDispatch) + { + _out << nl << "Returns: A future object for the invocation."; + } if(mode == DocAsyncBegin) { _out << nl << "Returns: An asynchronous result object for the invocation."; @@ -2936,7 +2821,8 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, DocstringMode } 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) { Slice::Python::MetaDataVisitor visitor; un->visit(&visitor, false); @@ -3064,14 +2950,7 @@ Slice::Python::getAbsolute(const ContainedPtr& cont, const string& suffix, const } } - if(suffix.empty()) - { - return scope + fixIdent(cont->name() + nameSuffix); - } - else - { - return scope + suffix + fixIdent(cont->name() + nameSuffix); - } + return scope + suffix + fixIdent(cont->name() + nameSuffix); } void @@ -3103,30 +2982,28 @@ Slice::Python::MetaDataVisitor::visitUnitStart(const UnitPtr& p) // Validate global metadata in the top-level file and all included files. // StringList files = p->allFiles(); - for(StringList::iterator q = files.begin(); q != files.end(); ++q) { string file = *q; DefinitionContextPtr dc = p->findDefinitionContext(file); assert(dc); StringList globalMetaData = dc->getMetaData(); - for(StringList::const_iterator r = globalMetaData.begin(); r != globalMetaData.end(); ++r) + for(StringList::const_iterator r = globalMetaData.begin(); r != globalMetaData.end();) { - string s = *r; - if(_history.count(s) == 0) + string s = *r++; + if(s.find(prefix) == 0) { - _history.insert(s); - if(s.find(prefix) == 0) + static const string packagePrefix = "python:package:"; + if(s.find(packagePrefix) == 0 && s.size() > packagePrefix.size()) { - static const string packagePrefix = "python:package:"; - if(s.find(packagePrefix) == 0 && s.size() > packagePrefix.size()) - { - continue; - } - emitWarning(file, "", "ignoring invalid global metadata `" + s + "'"); + continue; } + + dc->warning(InvalidMetaData, file, "", "ignoring invalid global metadata `" + s + "'"); + globalMetaData.remove(s); } } + dc->setMetaData(globalMetaData); } return true; } @@ -3194,6 +3071,11 @@ Slice::Python::MetaDataVisitor::visitSequence(const SequencePtr& p) StringList metaData = p->getMetaData(); const string file = p->file(); const string line = p->line(); + StringList protobufMetaData; + const UnitPtr unit = p->unit(); + const DefinitionContextPtr dc = unit->findDefinitionContext(file); + assert(dc); + for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ) { string s = *q++; @@ -3203,17 +3085,22 @@ Slice::Python::MetaDataVisitor::visitSequence(const SequencePtr& p) // Remove from list so validateSequence does not try to handle as well. // metaData.remove(s); - BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); if(!builtin || builtin->kind() != Builtin::KindByte) { - emitWarning(file, line, "ignoring invalid metadata `" + s + ": " + + dc->warning(InvalidMetaData, file, line, "ignoring invalid metadata `" + s + ": " + "`protobuf' encoding must be a byte sequence"); } + else + { + protobufMetaData.push_back(s); + } } } - validateSequence(file, line, p, metaData); + metaData = validateSequence(file, line, p, metaData); + metaData.insert(metaData.end(), protobufMetaData.begin(), protobufMetaData.end()); + p->setMetaData(metaData); } void @@ -3234,15 +3121,19 @@ Slice::Python::MetaDataVisitor::visitConst(const ConstPtr& p) reject(p); } -void +StringList Slice::Python::MetaDataVisitor::validateSequence(const string& file, const string& line, - const TypePtr& type, const StringList& meta) + const TypePtr& type, const StringList& metaData) { - static const string prefix = "python:"; + const UnitPtr unit = type->unit(); + const DefinitionContextPtr dc = unit->findDefinitionContext(file); + assert(dc); - for(StringList::const_iterator p = meta.begin(); p != meta.end(); ++p) + static const string prefix = "python:"; + StringList newMetaData = metaData; + for(StringList::const_iterator p = newMetaData.begin(); p != newMetaData.end();) { - string s = *p; + string s = *p++; if(s.find(prefix) == 0) { string::size_type pos = s.find(':', prefix.size()); @@ -3258,9 +3149,11 @@ Slice::Python::MetaDataVisitor::validateSequence(const string& file, const strin } } } - emitWarning(file, line, "ignoring invalid metadata `" + s + "'"); + dc->warning(InvalidMetaData, file, line, "ignoring invalid metadata `" + s + "'"); + newMetaData.remove(s); } } + return newMetaData; } void @@ -3268,11 +3161,19 @@ Slice::Python::MetaDataVisitor::reject(const ContainedPtr& cont) { StringList localMetaData = cont->getMetaData(); static const string prefix = "python:"; - for(StringList::const_iterator p = localMetaData.begin(); p != localMetaData.end(); ++p) + + const UnitPtr unit = cont->unit(); + const DefinitionContextPtr dc = unit->findDefinitionContext(cont->file()); + assert(dc); + + for(StringList::const_iterator p = localMetaData.begin(); p != localMetaData.end();) { - if(p->find(prefix) == 0) + string s = *p++; + if(s.find(prefix) == 0) { - emitWarning(cont->file(), cont->line(), "ignoring invalid metadata `" + *p + "'"); + dc->warning(InvalidMetaData, cont->file(), cont->line(), "ignoring invalid metadata `" + s + "'"); + localMetaData.remove(s); } } + cont->setMetaData(localMetaData); } |