diff options
author | Joe George <joe@zeroc.com> | 2019-02-18 13:21:34 -0500 |
---|---|---|
committer | Joe George <joe@zeroc.com> | 2019-02-18 13:21:34 -0500 |
commit | 68fa96c625a683f7cae45d5f6c646b9b5c269b3a (patch) | |
tree | 59ba0f3e2e839d233f724289b4b178108109674b /cpp/src/slice2swift/Gen.cpp | |
parent | Fixed formatting bug (diff) | |
download | ice-68fa96c625a683f7cae45d5f6c646b9b5c269b3a.tar.bz2 ice-68fa96c625a683f7cae45d5f6c646b9b5c269b3a.tar.xz ice-68fa96c625a683f7cae45d5f6c646b9b5c269b3a.zip |
Initial commit of Swift mapping
Diffstat (limited to 'cpp/src/slice2swift/Gen.cpp')
-rw-r--r-- | cpp/src/slice2swift/Gen.cpp | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/cpp/src/slice2swift/Gen.cpp b/cpp/src/slice2swift/Gen.cpp new file mode 100644 index 00000000000..8706928df71 --- /dev/null +++ b/cpp/src/slice2swift/Gen.cpp @@ -0,0 +1,496 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2018 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/OutputUtil.h> +#include <IceUtil/StringUtil.h> +#include <Slice/Parser.h> +#include <Slice/FileTracker.h> +#include <Slice/Util.h> + +#include "Gen.h" + +using namespace std; +using namespace Slice; +using namespace IceUtilInternal; + +namespace +{ + +} + +Gen::Gen(const string& base, const vector<string>& includePaths, const string& dir) : + _includePaths(includePaths) +{ + _fileBase = base; + string::size_type pos = base.find_last_of("/\\"); + if(pos != string::npos) + { + _fileBase = base.substr(pos + 1); + } + + string file = _fileBase + ".swift"; + + if(!dir.empty()) + { + file = dir + '/' + file; + } + + _out.open(file.c_str()); + if(!_out) + { + ostringstream os; + os << "cannot open `" << file << "': " << IceUtilInternal::errorToString(errno); + throw FileException(__FILE__, __LINE__, os.str()); + } + FileTracker::instance()->addFile(file); + + printHeader(); + printGeneratedHeader(_out, _fileBase + ".ice"); + + _out << nl << "import Foundation" << nl; +} + +Gen::~Gen() +{ + if(_out.isOpen()) + { + _out << nl; + } +} + +void +Gen::generate(const UnitPtr& p) +{ + SwiftGenerator::validateMetaData(p); + + TypesVisitor typesVisitor(_out); + p->visit(&typesVisitor, false); +} + +void +Gen::closeOutput() +{ + _out.close(); +} + +void +Gen::printHeader() +{ + static const char* header = +"// **********************************************************************\n" +"//\n" +"// Copyright (c) 2003-2018 ZeroC, Inc. All rights reserved.\n" +"//\n" +"// This copy of Ice is licensed to you under the terms described in the\n" +"// ICE_LICENSE file included in this distribution.\n" +"//\n" +"// **********************************************************************\n" + ; + + _out << header; + _out << "//\n"; + _out << "// Ice version " << ICE_STRING_VERSION << "\n"; + _out << "//\n"; +} + +Gen::TypesVisitor::TypesVisitor(IceUtilInternal::Output& o) : out(o) +{ +} + +bool Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string name = p->name(); + string swiftName = fixName(p); + ClassList bases = p->bases(); + ClassDefPtr baseClass; + if(!bases.empty() && !bases.front()->isInterface()) + { + baseClass = bases.front(); + } + + if(p->isDelegate()) + { + const OperationPtr op = p->operations().front(); + const ParamDeclList parameters = op->parameters(); + const string ret = typeToString(op->returnType()); + out << nl << "public typealias " << swiftName << " = "; + out << "("; + for(ParamDeclList::const_iterator q = parameters.begin(); q != parameters.end() && !(*q)->isOutParam(); ++q) + { + if(q != parameters.begin()) + { + out << ", "; + } + + out << typeToString((*q)->type()); + } + out << ") -> " << (ret.empty() ? "Void" : ret); + + return false; + } + + if(p->isLocal()) + { + // + // If there are any operations generate a protocol + // Otherwise if just datamembers then a class + // + if(p->allOperations().empty()) + { + out << nl << "public class " << swiftName; + if(baseClass) + { + out << ": " << fixName(baseClass); + } + out << sb; + + if(!p->dataMembers().empty()) + { + writeDataMembers(out, p->dataMembers()); + writeInitializer(out, p->dataMembers(), p->allDataMembers()); + } + out << eb << nl; + } + else + { + out << nl << "public protocol " << swiftName; + + // TODO check for delegate metadata and map to closure + + if(baseClass) + { + out << ": " << fixName(baseClass); + } + else + { + // All protocols must be implemented by a class + out << ": AnyObject"; + } + out << sb; + + if(!p->dataMembers().empty()) + { + writeDataMembers(out, p->dataMembers(), true); + } + + OperationList ops = p->operations(); + for(OperationList::iterator r = ops.begin(); r != ops.end(); ++r) + { + writeOperation(out, *r, p->isLocal()); + } + out << eb << nl; + } + + } + else + { + // + // interface: generate Swift protocol and protocolPrx + // class: generate class protocolPrx, and protocolDisp + // + + out << nl << "public protocol " << swiftName; + if(!p->isInterface()) + { + out << "Disp"; + } + if(baseClass) + { + out << ": " << fixIdent(baseClass->name()); + } + else + { + // All protocols must be implemented by a class + out << ": class"; + } + out << sb; + // TODO + out << eb << nl; + + if(!p->isInterface()) + { + out << nl << "public class " << swiftName; + if(baseClass) + { + out << ": " << fixIdent(baseClass->name()); + } + out << sb; + if(!p->dataMembers().empty()) + { + writeDataMembers(out, p->dataMembers(), true); + writeInitializer(out, p->dataMembers(), p->allDataMembers()); + } + out << eb << nl; + } + + out << nl << "public protocol " << swiftName << "Prx"; + if(baseClass) + { + out << ": " << fixIdent(baseClass->name()); + } + else + { + out << ": " << "Ice.ObjectPrx"; + } + out << sb << eb << nl; + + // TODO add class ClassResolver extension + // @objc dynamic Demo_ClassName() -> AnyObject + + if(p->isInterface()) + { + const string proxyImpl = "_" + swiftName + "PrxI"; + out << nl << "public extension " << swiftName + "Prx"; + out << sb; + OperationList ops = p->operations(); + for(OperationList::iterator r = ops.begin(); r != ops.end(); ++r) + { + const OperationPtr op = *r; + writeOperation(out, op, p->isLocal()); + out << sb << nl; + writeMarshalUnmarshalCode(out, p, op); + out << eb << nl; + } + out << eb << nl; + + out << "public class " << proxyImpl << ": _ObjectPrxI, " << swiftName + "Prx"; + out << sb; + out << nl << "override public class func ice_staticId() -> String"; + out << sb; + out << nl << "return \"" << p->scoped() << "\""; + out << eb; + out << eb << nl; + + writeCastFuncs(out, p); + writeStaticId(out, p); + } + } + + return false; +} + +bool Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + // const string name = fixIdent(p->name()); + const string name = p->name(); + const string scoped = p->scoped(); + // const string abs = getAbsolute(p); + // const bool basePreserved = p->inheritsMetaData("preserve-slice"); + // const bool preserved = p->hasMetaData("preserve-slice"); + + ExceptionPtr base = p->base(); + + out << nl << "public class " << name; + if(base) + { + out << ": " << getAbsolute(base); + } + else if(p->isLocal()) + { + out << ": Ice.LocalException"; + } + else + { + out << ": Ice.UserException"; + } + out << sb; + + if(!p->dataMembers().empty()) + { + + writeDataMembers(out, p->dataMembers()); + out << nl; + writeInitializer(out, p->dataMembers(), p->allDataMembers()); + } + + if(!p->isLocal()) + { + const DataMemberList members = p->dataMembers(); + + out << nl << nl << "required public init(from ins: Ice.InputStream) throws" << sb; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { + out << nl << "try self." << (*q)->name() << " = " << typeToString((*q)->type()) << "(from: ins)"; + } + out << eb; + + // TODO if we no longer need this. + // out << nl << nl << "public func ice_read(from ins: Ice.InputStream) throws" << sb; + // for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { + // out << nl << "try self." << (*q)->name() << ".ice_read(from: ins)"; + // } + // out << eb; + + out << nl << nl << "public func ice_write(to os: Ice.OutputStream)" << sb; + out << nl << "os.write("; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { + if(q != members.begin()) + { + out << ", "; + } + out << "self." << (*q)->name(); + } + out << ")"; + out << eb; + + out << nl << "public class func ice_staticId() -> String"; + out << sb; + out << nl << "return \"" << p->scoped() << "\""; + out << eb; + } + + out << nl << eb; + out << nl; + + return false; +} + +bool Gen::TypesVisitor::visitStructStart(const StructPtr& p) +{ + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + const string abs = getAbsolute(p); + + const DataMemberList members = p->dataMembers(); + + string hashable = ": Hashable"; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + if(!BuiltinPtr::dynamicCast((*q)->type())) + { + hashable = ""; + break; + } + } + + out << nl << "public struct " << name << hashable << sb; + + writeDataMembers(out, members); + writeInitializer(out, members); + + out << eb << nl; + + if(!p->isLocal()) { + out << nl << "extension " << name << ": Ice.Streamable" << sb; + + out << nl << nl << "public init()" << sb; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { + out << nl << "self." << (*q)->name() << " = " << typeToString((*q)->type()) << "()"; + } + out << eb; + + out << nl << nl << "public init(from ins: Ice.InputStream) throws" << sb; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { + out << nl << "try self." << (*q)->name() << " = " << typeToString((*q)->type()) << "(from: ins)"; + } + out << eb; + + // TODO: remove if we no longer need this + // out << nl << nl << "public mutating func ice_read(from ins: Ice.InputStream) throws" << sb; + // for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { + // out << nl << "try self." << (*q)->name() << ".ice_read(from: ins)"; + // } + // out << eb; + + out << nl << nl << "public func ice_write(to os: Ice.OutputStream)" << sb; + out << nl << "os.write("; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { + if(q != members.begin()) + { + out << ", "; + } + out << "self." << (*q)->name(); + } + out << ")"; + out << eb; + + out << eb << nl; + } + + return false; +} + +void Gen::TypesVisitor::visitSequence(const SequencePtr& p) +{ + const string name = fixIdent(p->name()); + const TypePtr type = p->type(); + + out << nl << "public typealias " << name << " = [" << typeToString(type) << "]"; +} + +void Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) +{ + const string name = fixIdent(p->name()); + + const TypePtr keyType = p->keyType(); + const TypePtr valueType = p->valueType(); + + out << nl << "public typealias " << name << " = [" << typeToString(keyType) << ":" << typeToString(valueType) << "]"; +} + +void Gen::TypesVisitor::visitEnum(const EnumPtr& p) +{ + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + const string abs = getAbsolute(p); + + const string enumType = p->maxValue() <= 0xFF ? "UInt8" : "Int32"; + + out << nl << "public enum " << name << ": " << enumType << sb; + + const EnumeratorList enumerators = p->enumerators(); + + for(EnumeratorList::const_iterator en = enumerators.begin(); en != enumerators.end(); ++en) + { + out << nl << "case " << fixIdent((*en)->name()) << " = " << (*en)->value(); + } + + out << eb << nl; + + out << nl << "extension " << name << ": Ice.Streamable" << sb; + + out << nl << nl << "public init()" << sb; + + out << nl << "self = ." << fixIdent((*enumerators.begin())->name()); + + out << eb; + + out << nl << nl << "public init(from ins: Ice.InputStream) throws" << sb; + out << nl << "var rawValue = " << enumType << "()"; + out << nl << "try ins.read(enum: &rawValue, maxValue: " << p->maxValue() << ")"; + out << nl << "guard let val = " << name << "(rawValue: rawValue) else" << sb; + out << nl << "throw MarshalException(reason: \"invalid enum value\")"; + out << eb; + out << nl << "self = val"; + out << eb; + + //TODO: remove if we no longer need this. + // out << nl << nl << "public mutating func ice_read(from ins: Ice.InputStream) throws" << sb; + // out << nl << "var rawValue = " << enumType << "()"; + // out << nl << "try ins.read(enum: &rawValue, maxValue: " << p->maxValue() << ")"; + // out << nl << "guard let val = " << name << "(rawValue: rawValue) else" << sb; + // out << nl << "throw MarshalException(reason: \"invalid enum value\")"; + // out << eb; + // out << nl << "self = val"; + // out << eb; + + out << nl << nl << "public func ice_write(to os: Ice.OutputStream)" << sb; + out << nl << "os.write(enum: self.rawValue, maxValue: " << p->maxValue() << ")"; + out << eb; + + out << eb << nl; +} + +void Gen::TypesVisitor::visitConst(const ConstPtr& p) +{ + const string name = fixIdent(p->name()); + const TypePtr type = p->type(); + + out << nl << "public let " << name << ": " << typeToString(type) << " = " << p->value(); + out << nl; +} |