summaryrefslogtreecommitdiff
path: root/cpp/src/slice2swift/Gen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/slice2swift/Gen.cpp')
-rw-r--r--cpp/src/slice2swift/Gen.cpp496
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;
+}