public void OperatorCompositionNoInvoke()
        {
            var swiftCode =
                "infix operator ∘\n" +
                "    public func ∘<T>(left: @escaping (T) -> (T), right: @escaping (T) -> (T)) -> (T) -> (T) {\n" +
                "        return { (x) in\n" +
                "            left (right(x))\n" +
                "        }\n" +
                "}\n";

            var lbody1 = new CSCodeBlock();
            var lid    = new CSIdentifier("d");

            lbody1.Add(CSReturn.ReturnLine(lid * CSConstant.Val(2.0)));
            var pl = new CSParameterList();

            pl.Add(new CSParameter(CSSimpleType.Double, lid));
            var lam1   = new CSLambda(pl, lbody1);
            var lbody2 = new CSCodeBlock();

            lbody2.Add(CSReturn.ReturnLine(lid * CSConstant.Val(3.0)));
            var lam2 = new CSLambda(pl, lbody2);

            var compFunc = CSFunctionCall.FunctionCallLine("TopLevelEntities.InfixOperatorRing", false, lam1, lam2);
            var printIt  = CSFunctionCall.ConsoleWriteLine(CSConstant.Val(12.0));

            var callingCode = new CodeElementCollection <ICodeElement> {
                compFunc, printIt
            };

            TestRunning.TestAndExecute(swiftCode, callingCode, "12\n");
        }
		public void SimpleProtocolProGetIndexer ()
		{
			var swiftCode = @"
public protocol Simplest4 {
	associatedtype Item
	subscript (index: Int) -> Item {
		get
	}
}
public func doGetIt<T:Simplest4> (a: T, i: Int) -> T.Item {
	return a[i]
}
";
			var altClass = new CSClass (CSVisibility.Public, "Simple4Impl");
			altClass.Inheritance.Add (new CSIdentifier ("ISimplest4<SwiftString>"));

			var getBlock = CSCodeBlock.Create (CSReturn.ReturnLine (new CSFunctionCall ("SwiftString.FromString", false, CSConstant.Val ("Got here!"))));
			var parameters = new CSParameterList (new CSParameter (new CSSimpleType ("nint"), new CSIdentifier ("index")));
			var thingIndex = new CSProperty (new CSSimpleType ("SwiftString"), CSMethodKind.None,
				CSVisibility.Public, getBlock, CSVisibility.Public, null, parameters);
			altClass.Properties.Add (thingIndex);

			var ctor = new CSMethod (CSVisibility.Public, CSMethodKind.None, null, altClass.Name, new CSParameterList (), CSCodeBlock.Create ());
			altClass.Methods.Add (ctor);
			var instID = new CSIdentifier ("inst");
			var instDecl = CSVariableDeclaration.VarLine (instID, new CSFunctionCall ("Simple4Impl", true));
			var resultID = new CSIdentifier ("result");
			var resultDecl = CSVariableDeclaration.VarLine (resultID, new CSFunctionCall ("TopLevelEntities.DoGetIt<Simple4Impl, SwiftString>", false, instID, CSConstant.Val (3)));
			var printer = CSFunctionCall.ConsoleWriteLine (resultID);
			var callingCode = CSCodeBlock.Create (instDecl, resultDecl, printer);
			TestRunning.TestAndExecute (swiftCode, callingCode, "Got here!\n", otherClass: altClass, platform: PlatformName.macOS);
		}
예제 #3
0
        void WrapSingleProperty(string type, string returnVal, string csType, string csReplacement, string expected)
        {
            string appendage = type.Replace('.', '_');
            string swiftCode =
                $"open class MontyWSP{appendage} {{ public init() {{}}\n open var val: {type} {{\nget {{ return {returnVal}\n}} }} }}";

            CSClass overCS = new CSClass(CSVisibility.Public, $"OverWSP{appendage}");

            overCS.Inheritance.Add(new CSIdentifier($"MontyWSP{appendage}"));
            CSCodeBlock getterBody = CSCodeBlock.Create(CSReturn.ReturnLine(new CSIdentifier(csReplacement)));

            CSProperty overProp = new CSProperty(new CSSimpleType(csType), CSMethodKind.Override, new CSIdentifier("Val"),
                                                 CSVisibility.Public, getterBody, CSVisibility.Public, null);

            overCS.Properties.Add(overProp);

            CSCodeBlock printBody = CSCodeBlock.Create(CSFunctionCall.ConsoleWriteLine(CSConstant.Val("{0}, {1}"), (CSIdentifier)"base.Val", (CSIdentifier)"Val"));
            CSMethod    printIt   = new CSMethod(CSVisibility.Public, CSMethodKind.None, CSSimpleType.Void, new CSIdentifier("PrintIt"), new CSParameterList(), printBody);

            overCS.Methods.Add(printIt);

            CSLine      decl        = CSVariableDeclaration.VarLine(new CSSimpleType($"OverWSP{appendage}"), "printer", new CSFunctionCall($"OverWSP{appendage}", true));
            CSLine      invoker     = CSFunctionCall.FunctionCallLine("printer.PrintIt", false);
            CSCodeBlock callingCode = CSCodeBlock.Create(decl, invoker);

            TestRunning.TestAndExecute(swiftCode, callingCode, expected, testName: $"WrapSingleProperty{appendage}", otherClass: overCS, platform: PlatformName.macOS);
        }
		public void SimpleProtocolProGetSetIndexer ()
		{
			var swiftCode = @"
public protocol Simplest5 {
	associatedtype Item
	subscript (index: Int) -> Item {
		get set
	}
}
public func doSetIt<T:Simplest5> (a: inout T, i: Int, v: T.Item) {
	a[i] = v
}
";
			var altClass = new CSClass (CSVisibility.Public, "Simple5Impl");
			altClass.Inheritance.Add (new CSIdentifier ("ISimplest5<SwiftString>"));

			var fieldName = new CSIdentifier ("v");
			altClass.Fields.Add (CSFieldDeclaration.FieldLine (new CSSimpleType ("SwiftString"), fieldName));
			var getBlock = CSCodeBlock.Create (CSReturn.ReturnLine (fieldName));
			var setBlock = CSCodeBlock.Create (CSAssignment.Assign (fieldName, new CSIdentifier ("value")));

			var parameters = new CSParameterList (new CSParameter (new CSSimpleType ("nint"), new CSIdentifier ("index")));
			var thingIndex = new CSProperty (new CSSimpleType ("SwiftString"), CSMethodKind.None,
				CSVisibility.Public, getBlock, CSVisibility.Public, setBlock, parameters);
			altClass.Properties.Add (thingIndex);

			var ctor = new CSMethod (CSVisibility.Public, CSMethodKind.None, null, altClass.Name, new CSParameterList (), CSCodeBlock.Create ());
			altClass.Methods.Add (ctor);
			var instID = new CSIdentifier ("inst");
			var instDecl = CSVariableDeclaration.VarLine (instID, new CSFunctionCall ("Simple5Impl", true));
			var callSetter = CSFunctionCall.FunctionCallLine ("TopLevelEntities.DoSetIt", false, instID, CSConstant.Val (3), new CSFunctionCall ("SwiftString.FromString", false, CSConstant.Val ("Got here!")));
			var printer = CSFunctionCall.ConsoleWriteLine (new CSIdentifier ($"{instID.Name}[3]"));
			var callingCode = CSCodeBlock.Create (instDecl, callSetter, printer);
			TestRunning.TestAndExecute (swiftCode, callingCode, "Got here!\n", otherClass: altClass, platform: PlatformName.macOS);
		}
        void WrapSingleSubscriptGetOnly(string type, string csType, string csReplacement, string csAlt, string expected)
        {
            string swiftCode =
                TestRunningCodeGenerator.kSwiftFileWriter +
                $"public protocol MontyWSGO{type} {{ subscript(i:Int32) -> {type} {{ get }} \n  }}\n" +
                $"public class TestMontyWSGO{type} {{\npublic init() {{ }}\npublic func doIt(m:MontyWSGO{type}) {{\nvar s = \"\", t=\"\"\nprint(m[0], to:&s)\nprint(m[1], to:&t)\nwriteToFile(s+t, \"WrapSingleSubscriptGetOnly{type}\")\n}}\n}}\n";

            CSClass overCS = new CSClass(CSVisibility.Public, $"OverWSGO{type}");

            overCS.Inheritance.Add(new CSIdentifier($"IMontyWSGO{type}"));
            CSParameterList overParams = new CSParameterList();

            overParams.Add(new CSParameter(CSSimpleType.Int, "i"));
            CSCodeBlock overBody = CSCodeBlock.Create(CSReturn.ReturnLine(new CSTernary(new CSIdentifier("i") == CSConstant.Val(0),
                                                                                        new CSIdentifier(csReplacement), new CSIdentifier(csAlt), false)));
            CSProperty overProp = new CSProperty(new CSSimpleType(csType), CSMethodKind.None, CSVisibility.Public,
                                                 overBody, CSVisibility.Public, null, overParams);

            overCS.Properties.Add(overProp);

            CSLine      decl        = CSVariableDeclaration.VarLine(new CSSimpleType($"OverWSGO{type}"), "myOver", new CSFunctionCall($"OverWSGO{type}", true));
            CSLine      decl1       = CSVariableDeclaration.VarLine(new CSSimpleType($"TestMontyWSGO{type}"), "tester", new CSFunctionCall($"TestMontyWSGO{type}", true));
            CSLine      invoker     = CSFunctionCall.FunctionCallLine("tester.DoIt", false, new CSIdentifier("myOver"));
            CSCodeBlock callingCode = CSCodeBlock.Create(decl, decl1, invoker);


            TestRunning.TestAndExecute(swiftCode, callingCode, expected, testName: $"WrapSingleSubscriptGetOnly{type}", otherClass: overCS);
        }
		public void SimplestProtocolPropGetAssocTest ()
		{
			var swiftCode = @"
public protocol Simplest1 {
	associatedtype Item
	var printThing: Item { get }
}
public func doPrint<T>(a:T) where T:Simplest1 {
	let _ = a.printThing
}
";
			var altClass = new CSClass (CSVisibility.Public, "Simple1Impl");
			altClass.Inheritance.Add (new CSIdentifier ("ISimplest1<SwiftString>"));
			var strID = new CSIdentifier ("theStr");
			var strDecl = CSVariableDeclaration.VarLine (strID, CSConstant.Val ("Got here!"));
			var printPart = CSFunctionCall.ConsoleWriteLine (strID);
			var returnPart = CSReturn.ReturnLine (new CSFunctionCall ("SwiftString.FromString", false, strID));
			var printBody = CSCodeBlock.Create (strDecl, printPart, returnPart);
			var speak = new CSProperty (new CSSimpleType ("SwiftString"), CSMethodKind.None, new CSIdentifier ("PrintThing"),
				CSVisibility.Public, printBody, CSVisibility.Public, null);
			altClass.Properties.Add (speak);

			var ctor = new CSMethod (CSVisibility.Public, CSMethodKind.None, null, altClass.Name, new CSParameterList (), CSCodeBlock.Create ());
			altClass.Methods.Add (ctor);

			var instID = new CSIdentifier ("inst");
			var instDecl = CSVariableDeclaration.VarLine (instID, new CSFunctionCall ("Simple1Impl", true));
			var doPrint = CSFunctionCall.FunctionCallLine ("TopLevelEntities.DoPrint<Simple1Impl, SwiftString>", false, instID);
			var callingCode = CSCodeBlock.Create (instDecl, doPrint);
			TestRunning.TestAndExecute (swiftCode, callingCode, "Got here!\n", otherClass: altClass, platform: PlatformName.macOS);
		}
        static CSProperty MakeGetOnlyStringProp(string name, string val)
        {
            CSCodeBlock body = new CSCodeBlock();

            body.Add(CSReturn.ReturnLine(CSConstant.Val(val)));

            return(new CSProperty(CSSimpleType.String, CSMethodKind.None, new CSIdentifier(name), CSVisibility.Public,
                                  body, CSVisibility.Public, null));
        }
 public void StaticMethodParam()
 {
     using (Stream stm = Utils.BasicClass("None", "AClass", null, cl => {
         CSParameterList pl = new CSParameterList().And(new CSParameter(CSSimpleType.Int, "x"));
         CSCodeBlock b = new CSCodeBlock().And(CSReturn.ReturnLine(CSConstant.Val(0)));
         cl.Methods.Add(CSMethod.PublicMethod(CSMethodKind.Virtual, CSSimpleType.Int, "Foo", pl, b));
         return(cl);
     })) {
         Utils.CompileAStream(stm);
     }
 }
예제 #9
0
        public void NSObjectSubclassableMethodTest3()
        {
            string swiftCode =
                "import Foundation\n" +
                "@objc\n" +
                "open class Subclassable3 : NSObject {\n" +
                "   public override init () { }\n" +
                "   open var returnsTrue:Bool {\n" +
                "       get { return true\n } " +
                "   }\n" +
                "}\n" +
                "public func callIt (a: Subclassable3) -> Bool {\n" +
                "    return a.returnsTrue\n" +
                "}\n";


            var theSub = new CSClass(CSVisibility.Public, "TheSub3");
            var ctor   = new CSMethod(CSVisibility.Public, CSMethodKind.None, null, theSub.Name,
                                      new CSParameterList(), new CSBaseExpression [0], true, new CSCodeBlock());

            theSub.Constructors.Add(ctor);
            theSub.Inheritance.Add(new CSIdentifier("Subclassable3"));

            var theBody = new CSCodeBlock();

            theBody.Add(CSReturn.ReturnLine(CSConstant.Val(false)));

            LineCodeElementCollection <ICodeElement> getCode =
                new LineCodeElementCollection <ICodeElement> (
                    new ICodeElement [] {
                CSReturn.ReturnLine(CSConstant.Val(false))
            }, false, true);
            CSProperty returnsFalse = new CSProperty(CSSimpleType.Bool, CSMethodKind.Override, new CSIdentifier("ReturnsTrue"),
                                                     CSVisibility.Public, new CSCodeBlock(getCode),
                                                     CSVisibility.Public, null);

            theSub.Properties.Add(returnsFalse);


            var callingCode = new CodeElementCollection <ICodeElement> ();
            var objID       = new CSIdentifier("subTest");
            var objDecl     = CSVariableDeclaration.VarLine(CSSimpleType.Var, objID, new CSFunctionCall("TheSub3", true));
            var call        = CSFunctionCall.ConsoleWriteLine(objID.Dot((CSIdentifier)"ReturnsTrue"));
            var call2       = CSFunctionCall.ConsoleWriteLine(CSFunctionCall.Function("TopLevelEntities.CallIt", objID));

            callingCode.Add(objDecl);
            callingCode.Add(call);
            callingCode.Add(call2);

            TestRunning.TestAndExecute(swiftCode, callingCode, "False\nFalse\n", otherClass: theSub, platform: PlatformName.macOS);
        }
        void ClosureConstantFunc(string appendage, string swiftType, string csVal, string output, bool escaping)
        {
            appendage += escaping.ToString();
            string escapingAttribute = escaping ? "@escaping" : "";
            string swiftCode         =
                $"public func callClosureCCF{appendage}(f:{escapingAttribute}()->{swiftType}) -> {swiftType} {{\n" +
                "    return f()\n" +
                "}";

            CodeElementCollection <ICodeElement> callingCode = new CodeElementCollection <ICodeElement> ();
            CSCodeBlock body = new CSCodeBlock();

            body.Add(CSReturn.ReturnLine(new CSIdentifier(csVal)));
            CSLine invoker = CSFunctionCall.ConsoleWriteLine(CSFunctionCall.Function($"TopLevelEntities.CallClosureCCF{appendage}", new CSLambda(body)));

            callingCode.Add(invoker);
            TestRunning.TestAndExecute(swiftCode, callingCode, output, testName: $"ClosureConstantFunc{appendage}");
        }
        void ClosureSumFunc(string swiftType, string csVal1, string csVal2, string output, bool escaping)
        {
            string escapingAttribute = escaping ? "@escaping" : "";
            string swiftCode         =
                $"public func sumIt{swiftType}{escaping}(a:{swiftType}, b:{swiftType}, f:{escapingAttribute}({swiftType},{swiftType})->{swiftType}) -> {swiftType} {{\n" +
                "    return f(a, b)\n" +
                "}";

            CodeElementCollection <ICodeElement> callingCode = new CodeElementCollection <ICodeElement> ();
            CSCodeBlock body = new CSCodeBlock();

            body.Add(CSReturn.ReturnLine(new CSIdentifier("val1") + new CSIdentifier("val2")));
            CSLine invoker = CSFunctionCall.ConsoleWriteLine(CSFunctionCall.Function($"TopLevelEntities.SumIt{swiftType}{escaping}",
                                                                                     (CSIdentifier)csVal1, (CSIdentifier)csVal2, new CSLambda(body, "val1", "val2")));

            callingCode.Add(invoker);
            TestRunning.TestAndExecute(swiftCode, callingCode, output, testName: $"ClosureSumFunc{swiftType}{escaping}");
        }
        public void TestSimplest()
        {
            var swiftCode = @"
public protocol Identity1 {
	func whoAmI () -> Self
}

public func getName (a: Identity1) -> String {
	let o = a.whoAmI
	let t = type(of: o)
	return String(describing: t)
}
";

            // public class Foo : Identity1<Foo>
            // {
            //    public Foo () { }
            //    public Foo WhoAmI () {
            //        return this;
            //    }
            // }

            var auxClass = new CSClass(CSVisibility.Public, "Foo");

            auxClass.Inheritance.Add(new CSIdentifier("IIdentity1<Foo>"));

            var ctor = new CSMethod(CSVisibility.Public, CSMethodKind.None, null, auxClass.Name,
                                    new CSParameterList(), new CSCodeBlock());
            var whoAmI = new CSMethod(CSVisibility.Public, CSMethodKind.None, new CSSimpleType(auxClass.Name.Name),
                                      new CSIdentifier("WhoAmI"), new CSParameterList(),
                                      CSCodeBlock.Create(CSReturn.ReturnLine(CSIdentifier.This)));

            auxClass.Constructors.Add(ctor);
            auxClass.Methods.Add(whoAmI);

            var instName    = new CSIdentifier("inst");
            var nameName    = new CSIdentifier("name");
            var instDecl    = CSVariableDeclaration.VarLine(instName, new CSFunctionCall(auxClass.Name, new Dynamo.CommaListElementCollection <CSBaseExpression> (), true));
            var nameDecl    = CSVariableDeclaration.VarLine(nameName, new CSFunctionCall("TopLevelEntities.GetName", false, instName));
            var printer     = CSFunctionCall.ConsoleWriteLine(nameName);
            var callingCode = CSCodeBlock.Create(instDecl, nameDecl, printer);

            TestRunning.TestAndExecute(swiftCode, callingCode, "() -> Identity1\n", otherClass: auxClass, platform: PlatformName.macOS);
        }
예제 #13
0
        void VirtualMethodException(string toAdd, string output)
        {
            string swiftCode = $"public enum MyErrorVME{toAdd} : Error {{\ncase itFailed\n}}\n" +
                               $"open class FooVME{toAdd} {{\npublic init() {{\n}}\n public final func doIt(doThrow:Bool) throws {{\n let _ = try throwIt(doThrow:doThrow)\n}}\n open func throwIt(doThrow: Bool) throws -> Int\n {{\n if doThrow {{\n throw MyErrorVME{toAdd}.itFailed\n}}\nelse {{\n return 5\n}}\n}}\n}}\n";
            CodeElementCollection <ICodeElement> callingCode = new CodeElementCollection <ICodeElement> ();

            CSClass fooOver = new CSClass(CSVisibility.Public, $"SubFooVME{toAdd}");

            fooOver.Inheritance.Add(new CSIdentifier($"FooVME{toAdd}"));
            CSCodeBlock overBody  = new CSCodeBlock();
            CSCodeBlock ifblock   = new CSCodeBlock();
            CSCodeBlock elseblock = new CSCodeBlock();

            ifblock.Add(new CSLine(new CSThrow(new CSFunctionCall("ArgumentException", true, CSConstant.Val("gotcha.")))));
            elseblock.Add(CSReturn.ReturnLine(CSConstant.Val(6)));
            CSIfElse ifElse = new CSIfElse(new CSIdentifier("doThrow"), ifblock, elseblock);

            overBody.Add(ifElse);

            CSMethod myThrowIt = new CSMethod(CSVisibility.Public,
                                              CSMethodKind.Override,
                                              new CSSimpleType("nint"),
                                              new CSIdentifier("ThrowIt"),
                                              new CSParameterList(new CSParameter(CSSimpleType.Bool, new CSIdentifier("doThrow"))), overBody);

            fooOver.Methods.Add(myThrowIt);

            CSCodeBlock tryBlock = new CSCodeBlock();
            CSLine      varLine  = CSVariableDeclaration.VarLine(new CSSimpleType($"SubFooVME{toAdd}"), "foo", new CSFunctionCall($"SubFooVME{toAdd}", true));

            tryBlock.Add(varLine);
            CSLine call = CSFunctionCall.FunctionCallLine("foo.DoIt", false, new CSIdentifier(toAdd));

            tryBlock.Add(call);
            CSCodeBlock catchBlock = new CSCodeBlock();

            catchBlock.Add(CSFunctionCall.FunctionCallLine("Console.Write", false, new CSIdentifier("e").Dot(new CSIdentifier("Message"))));
            CSTryCatch catcher = new CSTryCatch(tryBlock, typeof(SwiftException), "e", catchBlock);

            callingCode.Add(catcher);
            TestRunning.TestAndExecute(swiftCode, callingCode, output, testName: $"VirtualMethodException{toAdd}", otherClass: fooOver, platform: PlatformName.macOS);
        }
        public void HandlesAutoclosure()
        {
            var swiftCode =
                "public func autoClosureCheck(a: @autoclosure ()->Bool) -> Bool {\n" +
                "    return a()\n" +
                "}\n";

            var callingCode = new CodeElementCollection <ICodeElement> ();

            var body = new CSCodeBlock();

            body.Add(CSReturn.ReturnLine(CSConstant.Val(true)));
            var lambda = new CSLambda(body);

            var printer = CSFunctionCall.ConsoleWriteLine(CSFunctionCall.Function("TopLevelEntities.AutoClosureCheck", lambda));

            callingCode.Add(printer);

            TestRunning.TestAndExecute(swiftCode, callingCode, "True\n");
        }
        public void CustomStringConvertibleTest()
        {
            var swiftCode = TestRunningCodeGenerator.kSwiftFileWriter +
                            "public func printIt(a: CustomStringConvertible) {\n" +
                            "   writeToFile(a.description, \"CustomStringConvertibleTest\")\n" +
                            "}\n";

            var convertible = new CSClass(CSVisibility.Public, "MyConvert");

            convertible.Inheritance.Add(new CSIdentifier("ICustomStringConvertible"));
            var getBody  = CSCodeBlock.Create(CSReturn.ReturnLine(new CSFunctionCall("SwiftString.FromString", false, CSConstant.Val("I did it!"))));
            var declProp = new CSProperty(new CSSimpleType(typeof(SwiftString)), CSMethodKind.None, new CSIdentifier("Description"),
                                          CSVisibility.Public, getBody, CSVisibility.Public, null);

            convertible.Properties.Add(declProp);
            var caller      = CSFunctionCall.FunctionCallLine("TopLevelEntities.PrintIt", false, new CSFunctionCall("MyConvert", true));
            var callingCode = CSCodeBlock.Create(caller);

            TestRunning.TestAndExecute(swiftCode, callingCode, "I did it!", otherClass: convertible);
        }
        void MakeCapsuleAccessor(CSClass cl)
        {
            CSParameterList pl = new CSParameterList();

            pl.Add(new CSParameter(new CSSimpleType(typeof(EventArgs)), "evt"));
            CSCodeBlock body = new CSCodeBlock();

            // System.Reflection.PropertyInfo pi = evt.GetType().GetProperty("Capsule");
            // return pi.GetValue(evt);
            body.Add(CSVariableDeclaration.VarLine(new CSSimpleType("System.Reflection.PropertyInfo"),
                                                   "pi",
                                                   new CSFunctionCall("evt.GetType().GetProperty", false,
                                                                      CSConstant.Val("Capsule"))));
            body.Add(CSReturn.ReturnLine(new CSFunctionCall("pi.GetValue", false, new CSIdentifier("evt"))));


            CSMethod meth = new CSMethod(CSVisibility.Public, CSMethodKind.None,
                                         CSSimpleType.Object, new CSIdentifier("GetCapsule"), pl, body);

            cl.Methods.Add(meth);
        }
        public CSProperty CompileProperty(string propertyName, CSUsingPackages packs, SwiftType swiftPropertyType, bool hasGetter, bool hasSetter,
                                          CSMethodKind methodKind)
        {
            propertyName = typeMap.SanitizeIdentifier(propertyName);
            NetTypeBundle propertyType = typeMap.MapType(swiftPropertyType, false);

            if (!(swiftPropertyType is SwiftGenericArgReferenceType))
            {
                AddUsingBlock(packs, propertyType);
            }
            ICodeElement [] uselessLine = new ICodeElement [] { CSReturn.ReturnLine(new CSIdentifier("useless")) };

            CSCodeBlock getterBlock = null;

            if (hasGetter)
            {
                getterBlock = new CSCodeBlock(uselessLine);
            }
            CSCodeBlock setterBlock = null;

            if (hasSetter)
            {
                setterBlock = new CSCodeBlock(uselessLine);
            }

            CSProperty theProp = new CSProperty(propertyType.ToCSType(packs), methodKind,
                                                new CSIdentifier(propertyName), CSVisibility.Public, getterBlock, CSVisibility.Public, setterBlock);

            if (getterBlock != null)
            {
                getterBlock.Clear();
            }
            if (setterBlock != null)
            {
                setterBlock.Clear();
            }

            return(theProp);
        }
        public void ClosureIdentityIntBool()
        {
            var swiftCode =
                "public func closureIdentityIntBool(a: @escaping (Int) -> Bool) -> (Int) -> (Bool) {\n" +
                "    return a\n" +
                "}\n";

            var callingCode = new CodeElementCollection <ICodeElement> ();
            var body        = new CSCodeBlock();

            body.Add(CSFunctionCall.ConsoleWriteLine((CSIdentifier)"i"));
            body.Add(CSReturn.ReturnLine(CSConstant.Val(true)));
            var lambda     = new CSLambda(body, "i");
            var returnType = new CSSimpleType("Func", false, new CSSimpleType("nint"), CSSimpleType.Bool);

            callingCode.Add(CSVariableDeclaration.VarLine(returnType, "lam", lambda));
            callingCode.Add(CSVariableDeclaration.VarLine(returnType, "lamreturn",
                                                          new CSFunctionCall("TopLevelEntities.ClosureIdentityIntBool", false, new CSIdentifier("lam"))));
            callingCode.Add(CSFunctionCall.FunctionCallLine("lamreturn", false, CSConstant.Val(17)));

            TestRunning.TestAndExecute(swiftCode, callingCode, "17\n");
        }
        void WrapSingleMethod(string type, string csType, string csReplacement, string expected)
        {
            string swiftCode =
                TestRunningCodeGenerator.kSwiftFileWriter +
                $"public protocol MontyWSM{type} {{ func val() -> {type}\n  }}\n" +
                $"public class TestMontyWSM{type} {{\npublic init() {{ }}\npublic func doIt(m:MontyWSM{type}) {{\nvar s = \"\"\nprint(m.val(), to:&s)\nwriteToFile(s, \"WrapSingleMethod{type}\")\n}}\n}}\n";

            CSClass overCS = new CSClass(CSVisibility.Public, $"OverWSM{type}");

            overCS.Inheritance.Add(new CSIdentifier($"IMontyWSM{type}"));
            CSCodeBlock overBody = CSCodeBlock.Create(CSReturn.ReturnLine(new CSIdentifier(csReplacement)));
            CSMethod    overMeth = new CSMethod(CSVisibility.Public, CSMethodKind.None, new CSSimpleType(csType),
                                                new CSIdentifier("Val"), new CSParameterList(), overBody);

            overCS.Methods.Add(overMeth);
            CSLine      decl        = CSVariableDeclaration.VarLine(new CSSimpleType($"OverWSM{type}"), "myOver", new CSFunctionCall($"OverWSM{type}", true));
            CSLine      decl1       = CSVariableDeclaration.VarLine(new CSSimpleType($"TestMontyWSM{type}"), "tester", new CSFunctionCall($"TestMontyWSM{type}", true));
            CSLine      invoker     = CSFunctionCall.FunctionCallLine("tester.DoIt", false, new CSIdentifier("myOver"));
            CSCodeBlock callingCode = CSCodeBlock.Create(decl, decl1, invoker);

            TestRunning.TestAndExecute(swiftCode, callingCode, expected, testName: $"WrapSingleMethod{type}", otherClass: overCS, platform: PlatformName.macOS);
        }
예제 #20
0
        void WrapClassCallsVirtual(string type, string returnVal, string csType, string csReplacement, string expected)
        {
            string safeType  = type.Replace('.', '_');
            string swiftCode =
                TestRunningCodeGenerator.kSwiftFileWriter +
                $"open class HolderWCCV{safeType} {{ public init() {{}}\n open func val() -> {type} {{ return {returnVal}; }} }}\n" +
                $"public final class FooWVVC{safeType} {{ var holder:HolderWCCV{safeType}\npublic init(h:HolderWCCV{safeType}) {{ holder = h\n}}\npublic func doIt() {{ var s = \"\"\nprint(holder.val(), to:&s);\nwriteToFile(s, \"WrapClassCallsVirtual{safeType}\")\n }} }}";

            CSClass overCS = new CSClass(CSVisibility.Public, $"OverWCCV{safeType}");

            overCS.Inheritance.Add(new CSIdentifier($"HolderWCCV{safeType}"));
            CSCodeBlock overBody = CSCodeBlock.Create(CSReturn.ReturnLine(new CSIdentifier(csReplacement)));
            CSMethod    overMeth = new CSMethod(CSVisibility.Public, CSMethodKind.Override, new CSSimpleType(csType),
                                                new CSIdentifier("Val"), new CSParameterList(), overBody);

            overCS.Methods.Add(overMeth);

            CodeElementCollection <ICodeElement> callingCode = new CodeElementCollection <ICodeElement> ();

            callingCode.Add(CSVariableDeclaration.VarLine(new CSSimpleType($"FooWVVC{safeType}"), "foo", new CSFunctionCall($"FooWVVC{safeType}", true, new CSFunctionCall($"OverWCCV{safeType}", true))));
            callingCode.Add(CSFunctionCall.FunctionCallLine("foo.DoIt", false));
            TestRunning.TestAndExecute(swiftCode, callingCode, expected, testName: $"WrapClassCallsVirtual{safeType}", otherClass: overCS, platform: PlatformName.macOS);
        }
예제 #21
0
        void WrapSingleMethod(string type, string returnVal, string csType, string csReplacement, string expected)
        {
            string swiftCode = $"open class MontyWSM{type} {{ public init() {{}}\n open func val() -> {type} {{ return {returnVal}; }} }}";
            CodeElementCollection <ICodeElement> callingCode = new CodeElementCollection <ICodeElement> ();

            CSClass overCS = new CSClass(CSVisibility.Public, $"OverWSM{type}");

            overCS.Inheritance.Add(new CSIdentifier($"MontyWSM{type}"));
            CSCodeBlock overBody = CSCodeBlock.Create(CSReturn.ReturnLine(new CSIdentifier(csReplacement)));
            CSMethod    overMeth = new CSMethod(CSVisibility.Public, CSMethodKind.Override, new CSSimpleType(csType),
                                                new CSIdentifier("Val"), new CSParameterList(), overBody);

            overCS.Methods.Add(overMeth);

            CSCodeBlock printBody = CSCodeBlock.Create(CSFunctionCall.ConsoleWriteLine(CSConstant.Val("{0}, {1}"),
                                                                                       CSFunctionCall.Function("base.Val"), CSFunctionCall.Function("Val")));
            CSMethod printIt = new CSMethod(CSVisibility.Public, CSMethodKind.None, CSSimpleType.Void, new CSIdentifier("PrintIt"), new CSParameterList(), printBody);

            overCS.Methods.Add(printIt);
            callingCode.Add(CSVariableDeclaration.VarLine(new CSSimpleType($"OverWSM{type}"), "printer", new CSFunctionCall($"OverWSM{type}", true)));
            callingCode.Add(CSFunctionCall.FunctionCallLine("printer.PrintIt", false));
            TestRunning.TestAndExecute(swiftCode, callingCode, expected, testName: $"WrapSingleMethod{type}", otherClass: overCS, platform: PlatformName.macOS);
        }
        void WrapSinglePropertyGetOnly(string appendage, string type, string csType, string csReplacement, string expected)
        {
            string swiftCode =
                TestRunningCodeGenerator.kSwiftFileWriter +
                $"public protocol MontyWSPGO{type} {{ var prop : {type} {{ get }} \n  }}\n" +
                $"public class TestMontyWSPGO{type} {{\npublic init() {{ }}\npublic func doIt(m:MontyWSPGO{type}) {{\nvar s = \"\"\nprint(m.prop, to:&s)\nwriteToFile(s, \"WrapSinglePropertyGetOnly{appendage}\")\n}}\n}}\n";

            CSClass overCS = new CSClass(CSVisibility.Public, $"OverWSPGO{type}");

            overCS.Inheritance.Add(new CSIdentifier($"IMontyWSPGO{type}"));
            CSCodeBlock overBody = CSCodeBlock.Create(CSReturn.ReturnLine(new CSIdentifier(csReplacement)));
            CSProperty  overProp = new CSProperty(new CSSimpleType(csType), CSMethodKind.None, new CSIdentifier("Prop"),
                                                  CSVisibility.Public, overBody, CSVisibility.Public, null);

            overCS.Properties.Add(overProp);

            CSLine      decl        = CSVariableDeclaration.VarLine(new CSSimpleType($"OverWSPGO{type}"), "myOver", new CSFunctionCall($"OverWSPGO{type}", true));
            CSLine      decl1       = CSVariableDeclaration.VarLine(new CSSimpleType($"TestMontyWSPGO{type}"), "tester", new CSFunctionCall($"TestMontyWSPGO{type}", true));
            CSLine      invoker     = CSFunctionCall.FunctionCallLine("tester.DoIt", false, new CSIdentifier("myOver"));
            CSCodeBlock callingCode = CSCodeBlock.Create(decl, decl1, invoker);

            TestRunning.TestAndExecute(swiftCode, callingCode, expected, testName: $"WrapSinglePropertyGetOnly{appendage}", otherClass: overCS, platform: PlatformName.macOS);
        }
        public void ClosureIdentityDoubleDoubleDouble()
        {
            var swiftCode =
                "public func closureIdentityDoubleDoubleDouble(a: @escaping (Double, Double) -> Double) -> (Double, Double) -> Double {\n" +
                "    return a\n" +
                "}\n";

            var callingCode = new CodeElementCollection <ICodeElement> ();
            var body        = new CSCodeBlock();
            var aId         = new CSIdentifier("a");
            var bId         = new CSIdentifier("b");

            body.Add(CSFunctionCall.ConsoleWriteLine(aId + bId));
            body.Add(CSReturn.ReturnLine(aId + bId));
            var lambda     = new CSLambda(body, "a", "b");
            var returnType = new CSSimpleType("Func", false, CSSimpleType.Double, CSSimpleType.Double, CSSimpleType.Double);

            callingCode.Add(CSVariableDeclaration.VarLine(returnType, "lam", lambda));
            callingCode.Add(CSVariableDeclaration.VarLine(returnType, "lamreturn",
                                                          new CSFunctionCall("TopLevelEntities.ClosureIdentityDoubleDoubleDouble", false, new CSIdentifier("lam"))));
            callingCode.Add(CSFunctionCall.FunctionCallLine("lamreturn", false, CSConstant.Val(3.1), CSConstant.Val(4.0)));

            TestRunning.TestAndExecute(swiftCode, callingCode, "7.1\n");
        }
        public List <ICodeElement> MarshalFromLambdaReceiverToCSProp(CSProperty prop, CSType thisType, string csProxyName, CSParameterList delegateParams,
                                                                     FunctionDeclaration funcDecl, CSType methodType, bool isObjC)
        {
            bool forProtocol     = csProxyName != null;
            bool needsReturn     = funcDecl.IsGetter;
            bool returnIsGeneric = funcDecl.IsTypeSpecGeneric(funcDecl.ReturnTypeSpec);

            var entity = !returnIsGeneric?typeMapper.GetEntityForTypeSpec(funcDecl.ReturnTypeSpec) : null;

            var entityType = !returnIsGeneric?typeMapper.GetEntityTypeForTypeSpec(funcDecl.ReturnTypeSpec) : EntityType.None;

            bool returnIsStructOrEnum = needsReturn && entity != null && entity.IsStructOrEnum;
            bool returnIsClass        = needsReturn && entity != null && entity.EntityType == EntityType.Class;
            bool returnIsProtocol     = needsReturn && entity != null && entity.EntityType == EntityType.Protocol;
            bool returnIsProtocolList = needsReturn && entityType == EntityType.ProtocolList;
            bool returnIsTuple        = needsReturn && entityType == EntityType.Tuple;
            bool returnIsClosure      = needsReturn && entityType == EntityType.Closure;

            string returnCsProxyName = returnIsProtocol ?
                                       NewClassCompiler.CSProxyNameForProtocol(entity.Type.ToFullyQualifiedName(true), typeMapper) : null;

            if (returnIsProtocol && returnCsProxyName == null)
            {
                throw ErrorHelper.CreateError(ReflectorError.kCompilerReferenceBase + 22, $"Unable to find C# interface for protocol {entity.Type.ToFullyQualifiedName ()}");
            }


            var body = new List <ICodeElement> ();

            if (isObjC)
            {
                use.AddIfNotPresent("ObjCRuntime");
            }
            else
            {
                use.AddIfNotPresent(typeof(SwiftObjectRegistry));
            }


            CSIdentifier csharpCall = null;

            if (forProtocol)
            {
                csharpCall = new CSIdentifier($"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{thisType.ToString()}> (self).{prop.Name.Name}");
            }
            else
            {
                var call = isObjC ?
                           $"ObjCRuntime.Runtime.GetNSObject<{thisType.ToString ()}> (self).{prop.Name.Name}" :
                           $"SwiftObjectRegistry.Registry.CSObjectForSwiftObject<{thisType.ToString ()}> (self).{prop.Name.Name}";

                csharpCall = new CSIdentifier(call);
            }

            if (funcDecl.IsGetter)
            {
                if (returnIsClass)
                {
                    if (isObjC)
                    {
                        body.Add(CSReturn.ReturnLine(csharpCall.Dot(new CSIdentifier("Handle"))));
                    }
                    else
                    {
                        body.Add(CSReturn.ReturnLine(csharpCall.Dot(NewClassCompiler.kSwiftObjectGetter)));
                    }
                }
                else if (returnIsStructOrEnum || returnIsTuple || returnIsGeneric)
                {
                    use.AddIfNotPresent(typeof(StructMarshal));
                    string retvalName = MarshalEngine.Uniqueify("retval", identifiersUsed);
                    var    retvalId   = new CSIdentifier(retvalName);
                    body.Add(CSFieldDeclaration.VarLine(methodType, retvalId, csharpCall));
                    if (returnIsGeneric)
                    {
                        body.Add(CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.ToSwift", false,
                                                                 methodType.Typeof(), retvalId, delegateParams [0].Name));
                    }
                    else
                    {
                        body.Add(CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.ToSwift", false,
                                                                 retvalId, delegateParams [0].Name));
                    }
                }
                else if (returnIsProtocol)
                {
                    string retvalName = MarshalEngine.Uniqueify("retval", identifiersUsed);
                    identifiersUsed.Add(retvalName);
                    var retvalId = new CSIdentifier(retvalName);
                    body.Add(CSFieldDeclaration.VarLine(methodType, retvalId, csharpCall));
                    var protocolMaker = new CSFunctionCall("SwiftExistentialContainer1", true,
                                                           new CSFunctionCall("SwiftObjectRegistry.Registry.ExistentialContainerForProtocols", false, retvalId, methodType.Typeof()));
                    body.Add(CSReturn.ReturnLine(protocolMaker));
                }
                else if (returnIsProtocolList)
                {
                    var protoTypeOf    = new List <CSBaseExpression> ();
                    var swiftProtoList = funcDecl.ReturnTypeSpec as ProtocolListTypeSpec;
                    foreach (var swiftProto in swiftProtoList.Protocols.Keys)
                    {
                        protoTypeOf.Add(typeMapper.MapType(funcDecl, swiftProto, false).ToCSType(use).Typeof());
                    }
                    var callExprs = new List <CSBaseExpression> ();
                    callExprs.Add(csharpCall);
                    callExprs.AddRange(protoTypeOf);
                    var retvalName = MarshalEngine.Uniqueify("retval", identifiersUsed);
                    identifiersUsed.Add(retvalName);
                    var retvalId = new CSIdentifier(retvalName);
                    body.Add(CSVariableDeclaration.VarLine(methodType, retvalId, new CSFunctionCall("StructMarshal.ThrowIfNotImplementsAll", false, callExprs.ToArray())));
                    var containerExprs = new List <CSBaseExpression> ();
                    containerExprs.Add(retvalId);
                    containerExprs.AddRange(protoTypeOf);

                    var returnContainerName = MarshalEngine.Uniqueify("returnContainer", identifiersUsed);
                    identifiersUsed.Add(returnContainerName);
                    var returnContainerId = new CSIdentifier(returnContainerName);
                    body.Add(CSVariableDeclaration.VarLine(CSSimpleType.Var, returnContainerId, new CSFunctionCall("SwiftObjectRegistry.Registry.ExistentialContainerForProtocols", false, containerExprs.ToArray())));
                    body.Add(CSFunctionCall.FunctionCallLine($"{returnContainerName}.CopyTo", false, new CSUnaryExpression(CSUnaryOperator.Ref, delegateParams [0].Name)));
                }
                else
                {
                    if (returnIsClosure)
                    {
                        body.Add(CSReturn.ReturnLine(MarshalEngine.BuildBlindClosureCall(csharpCall, methodType as CSSimpleType, use)));
                    }
                    else
                    {
                        body.Add(CSReturn.ReturnLine(csharpCall));
                    }
                }
            }
            else
            {
                CSBaseExpression valueExpr      = null;
                bool             valueIsGeneric = funcDecl.IsTypeSpecGeneric(funcDecl.ParameterLists [1] [0].TypeSpec);
                entity = !valueIsGeneric?typeMapper.GetEntityForTypeSpec(funcDecl.ParameterLists [1] [0].TypeSpec) : null;

                entityType = !valueIsGeneric?typeMapper.GetEntityTypeForTypeSpec(funcDecl.ParameterLists [1] [0].TypeSpec) : EntityType.None;

                var isUnusualNewValue = IsUnusualParameter(entity, delegateParams [1]);

                if (entityType == EntityType.Class || (entity != null && entity.IsObjCProtocol))
                {
                    var csParmType = delegateParams [1].CSType as CSSimpleType;
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 42, "Inconceivable! The class type for a method was a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(SwiftObjectRegistry));
                    var fullClassName = entity.Type.ToFullyQualifiedName(true);
                    var retrievecall  = NewClassCompiler.SafeMarshalClassFromIntPtr(delegateParams [1].Name, csParmType, use, fullClassName, typeMapper, entity.IsObjCProtocol);
                    valueExpr = retrievecall;
                }
                else if (entityType == EntityType.Protocol)
                {
                    use.AddIfNotPresent(typeof(SwiftObjectRegistry));
                    var retrievecall = new CSFunctionCall($"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{thisType.ToString ()}> (self).{prop.Name.Name}", false);
                    valueExpr = retrievecall;
                }
                else if (entityType == EntityType.Tuple || (entity != null && entity.IsStructOrEnum && !isUnusualNewValue))
                {
                    var ntb     = typeMapper.MapType(funcDecl, funcDecl.ParameterLists [1] [0].TypeSpec, false);
                    var valType = ntb.ToCSType(use);
                    if (entityType == EntityType.TrivialEnum)
                    {
                        valueExpr = new CSCastExpression(valType, new CSCastExpression(CSSimpleType.Long, delegateParams [1].Name));
                    }
                    else
                    {
                        var marshalCall = new CSFunctionCall("StructMarshal.Marshaler.ToNet", false, delegateParams [1].Name, valType.Typeof());
                        valueExpr = new CSCastExpression(valType, marshalCall);
                    }
                }
                else if (valueIsGeneric)
                {
                    // T someVal = (T)StructMarshal.Marshaler.ToNet(parm, typeof(T));
                    // someVal gets passed in
                    var depthIndex = funcDecl.GetGenericDepthAndIndex(funcDecl.ParameterLists [1] [0].TypeSpec);
                    var genRef     = new CSGenericReferenceType(depthIndex.Item1, depthIndex.Item2);
                    use.AddIfNotPresent(typeof(StructMarshal));
                    string valMarshalName = MarshalEngine.Uniqueify(delegateParams [1].Name + "Temp", identifiersUsed);
                    var    valMarshalId   = new CSIdentifier(valMarshalName);

                    var valDecl = CSVariableDeclaration.VarLine(genRef, valMarshalId,
                                                                new CSCastExpression(genRef, new CSFunctionCall("StructMarshal.Marshaler.ToNet", false,
                                                                                                                delegateParams [1].Name,
                                                                                                                genRef.Typeof())));
                    body.Add(valDecl);
                    valueExpr = valMarshalId;
                }
                else
                {
                    if (entityType == EntityType.Closure)
                    {
                        valueExpr = MarshalEngine.BuildWrappedClosureCall(delegateParams [1].Name, methodType as CSSimpleType);
                    }
                    else
                    {
                        valueExpr = delegateParams [1].Name;
                    }
                }
                body.Add(CSAssignment.Assign(csharpCall, valueExpr));
            }
            return(body);
        }
        public List <ICodeElement> MarshalFromLambdaReceiverToCSFunc(CSType thisType, string csProxyName, CSParameterList delegateParams,
                                                                     FunctionDeclaration funcDecl, CSType methodType, CSParameterList methodParams, string methodName, bool isObjC)
        {
            bool thisIsInterface = csProxyName != null;
            bool isIndexer       = funcDecl.IsSubscript;
            bool needsReturn     = methodType != null && methodType != CSSimpleType.Void;
            bool isSetter        = funcDecl.IsSubscriptSetter;
            bool returnIsGeneric = funcDecl.IsTypeSpecGeneric(funcDecl.ReturnTypeSpec);

            var entity = !returnIsGeneric?typeMapper.GetEntityForTypeSpec(funcDecl.ReturnTypeSpec) : null;

            var returnEntity = entity;
            var entityType   = !returnIsGeneric?typeMapper.GetEntityTypeForTypeSpec(funcDecl.ReturnTypeSpec) : EntityType.None;

            bool returnIsStruct   = needsReturn && entity != null && entity.IsStructOrEnum;
            bool returnIsClass    = needsReturn && entity != null && entity.EntityType == EntityType.Class;
            bool returnIsProtocol = needsReturn && ((entity != null && entity.EntityType == EntityType.Protocol) || entityType == EntityType.ProtocolList);
            bool returnIsTuple    = needsReturn && entityType == EntityType.Tuple;
            bool returnIsClosure  = needsReturn && entityType == EntityType.Closure;

            var callParams                    = new List <CSBaseExpression> ();
            var preMarshalCode                = new List <CSLine> ();
            var postMarshalCode               = new List <CSLine> ();
            CSBaseExpression valueExpr        = null;
            bool             marshalingThrows = false;


            if (isSetter)
            {
                var valueID = delegateParams [1].Name;
                valueExpr = valueID;
                var  swiftNewValue     = funcDecl.ParameterLists [1] [0];
                bool newValueIsGeneric = funcDecl.IsTypeSpecGeneric(funcDecl.PropertyType);
                entity = !newValueIsGeneric?typeMapper.GetEntityForTypeSpec(swiftNewValue.TypeSpec) : null;

                entityType = !newValueIsGeneric?typeMapper.GetEntityTypeForTypeSpec(swiftNewValue.TypeSpec) : EntityType.None;

                var isUnusualNewValue = IsUnusualParameter(entity, delegateParams [1]);

                if (entityType == EntityType.Class || entity.IsObjCProtocol)
                {
                    var csParmType = new CSSimpleType(entity.SharpNamespace + "." + entity.SharpTypeName);
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 26, "Inconceivable! The class type for a subscript was NOT a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(SwiftObjectRegistry));

                    var fullClassName = entity.Type.ToFullyQualifiedName(true);
                    valueExpr = NewClassCompiler.SafeMarshalClassFromIntPtr(valueID, csParmType, use, fullClassName, typeMapper, entity.IsObjCProtocol);
                }
                else if (entityType == EntityType.Protocol)
                {
                    var csParmType = new CSSimpleType(entity.SharpNamespace + "." + entity.SharpTypeName);
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 27, "Inconceivable! The protocol type for a subscript was NOT a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(StructMarshal));
                    use.AddIfNotPresent(typeof(SwiftObjectRegistry));
                    valueExpr = new CSFunctionCall($"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{csParmType.ToString ()}>", false, valueID);
                }
                else if ((entityType == EntityType.Struct || entityType == EntityType.Enum) && !isUnusualNewValue)
                {
                    var csParmType = new CSSimpleType(entity.SharpNamespace + "." + entity.SharpTypeName);
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 28, $"Inconceivable! The {entityType} type for a subscript was NOT a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(StructMarshal));
                    string valMarshalName = MarshalEngine.Uniqueify("val", identifiersUsed);
                    var    valMarshalId   = new CSIdentifier(valMarshalName);

                    CSLine valDecl = CSVariableDeclaration.VarLine(csParmType, valMarshalId,
                                                                   new CSCastExpression(csParmType, new CSFunctionCall("StructMarshal.Marshaler.ToNet", false, valueID,
                                                                                                                       csParmType.Typeof())));
                    preMarshalCode.Add(valDecl);
                    valueExpr = valMarshalId;
                }
                else if (entityType == EntityType.Tuple)
                {
                    var csParmType = new CSSimpleType(entity.SharpNamespace + "." + entity.SharpTypeName);
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 29, "Inconceivable! The tuple type for a subscript was NOT a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(StructMarshal));
                    string valMarshalName = MarshalEngine.Uniqueify("val", identifiersUsed);
                    var    valMarshalId   = new CSIdentifier(valMarshalName);

                    var valDecl = CSVariableDeclaration.VarLine(csParmType, valMarshalId,
                                                                new CSCastExpression(csParmType, new CSFunctionCall("StructMarshal.Marshaler.ToNet", false, valueID,
                                                                                                                    csParmType.Typeof())));
                    preMarshalCode.Add(valDecl);
                    valueExpr = valMarshalId;
                }
                else if (newValueIsGeneric)
                {
                    var depthIndex = funcDecl.GetGenericDepthAndIndex(swiftNewValue.TypeSpec);
                    var genRef     = new CSGenericReferenceType(depthIndex.Item1, depthIndex.Item2);
                    if (genRef == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 30, "Inconceivable! The generic type for a parameter in a method was NOT a CSGenericReferenceType!");
                    }
                    use.AddIfNotPresent(typeof(StructMarshal));
                    string valMarshalName = MarshalEngine.Uniqueify("valTemp", identifiersUsed);
                    var    valMarshalId   = new CSIdentifier(valMarshalName);

                    var valDecl = CSVariableDeclaration.VarLine(genRef, valMarshalId,
                                                                new CSCastExpression(genRef, new CSFunctionCall("StructMarshal.Marshaler.ToNet", false,
                                                                                                                valueID, genRef.Typeof())));
                    preMarshalCode.Add(valDecl);
                    valueExpr = valMarshalId;
                }
            }

            int j = 0;
            int k = isSetter ? 1 : 0;

            for (int i = (funcDecl.HasThrows || returnIsStruct || returnIsProtocol || isSetter || returnIsGeneric) ? 2 : 1; i < delegateParams.Count; i++, j++, k++)
            {
                var  swiftParm     = funcDecl.ParameterLists [1] [k];
                bool parmIsGeneric = funcDecl.IsTypeSpecGeneric(swiftParm);
                entity = !parmIsGeneric?typeMapper.GetEntityForTypeSpec(swiftParm.TypeSpec) : null;

                entityType = !parmIsGeneric?typeMapper.GetEntityTypeForTypeSpec(swiftParm.TypeSpec) : EntityType.None;

                var isUnusualParameter = IsUnusualParameter(entity, delegateParams [i]);
                var csParm             = methodParams [j];

                if (entityType == EntityType.Class || (entity != null && entity.IsObjCProtocol))
                {
                    var csParmType = csParm.CSType as CSSimpleType;
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 31, "Inconceivable! The class type for a method was NOT a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(SwiftObjectRegistry));

                    var fullClassName = entity.Type.ToFullyQualifiedName(true);
                    var retrievecall  = NewClassCompiler.SafeMarshalClassFromIntPtr(delegateParams [0].Name, csParmType, use, fullClassName, typeMapper, entity.IsObjCProtocol);
                    if (csParm.ParameterKind == CSParameterKind.Out || csParm.ParameterKind == CSParameterKind.Ref)
                    {
                        string id = MarshalEngine.Uniqueify(delegateParams [i].Name.Name, identifiersUsed);
                        identifiersUsed.Add(id);
                        preMarshalCode.Add(CSFieldDeclaration.FieldLine(csParmType, id, retrievecall));
                        callParams.Add(new CSIdentifier(String.Format("{0} {1}",
                                                                      csParm.ParameterKind == CSParameterKind.Out ? "out" : "ref", id)));
                        postMarshalCode.Add(CSAssignment.Assign(delegateParams [i].Name,
                                                                NewClassCompiler.SafeBackingFieldAccessor(new CSIdentifier(id), use, entity.Type.ToFullyQualifiedName(true), typeMapper)));
                    }
                    else
                    {
                        callParams.Add(retrievecall);
                    }
                }
                else if (entityType == EntityType.Protocol)
                {
                    var thePtr     = new CSIdentifier(MarshalEngine.Uniqueify("p", identifiersUsed));
                    var csParmType = csParm.CSType as CSSimpleType;
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 32, "Inconceivable! The protocol type for a method was NOT a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(SwiftObjectRegistry));
                    string csParmProxyType = NewClassCompiler.CSProxyNameForProtocol(entity.Type.ToFullyQualifiedName(true), typeMapper);
                    if (csParmProxyType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 33, $"Unable to find C# interface type for protocol {entity.Type.ToFullyQualifiedName ()}");
                    }

                    var retrievecall = new CSFunctionCall($"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{csParmType.Name}>", false, delegateParams [i].Name);
                    if (csParm.ParameterKind == CSParameterKind.Out || csParm.ParameterKind == CSParameterKind.Ref)
                    {
                        CSIdentifier id = new CSIdentifier(MarshalEngine.Uniqueify(delegateParams [i].Name.Name, identifiersUsed));
                        identifiersUsed.Add(id.Name);
                        preMarshalCode.Add(CSFieldDeclaration.FieldLine(csParmType, id.Name, retrievecall));
                        callParams.Add(new CSIdentifier(String.Format("{0} {1}",
                                                                      csParm.ParameterKind == CSParameterKind.Out ? "out" : "ref", id)));
                        postMarshalCode.Add(CSAssignment.Assign(delegateParams [i].Name,
                                                                new CSFunctionCall("SwiftExistentialContainer1", true,
                                                                                   new CSFunctionCall("SwiftObjectRegistry.Registry.ExistentialContainerForProtocol", false, id, csParmType.Typeof()))));
                    }
                    else
                    {
                        callParams.Add(retrievecall);
                    }
                }
                else if ((entityType == EntityType.Struct || entityType == EntityType.Enum) && !isUnusualParameter)
                {
                    var csParmType = csParm.CSType as CSSimpleType;
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 34, $"Inconceivable! The {entityType} type for a method was NOT a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(StructMarshal));
                    use.AddIfNotPresent(typeof(StructMarshal));
                    string valMarshalName = MarshalEngine.Uniqueify(delegateParams [i].Name + "Temp", identifiersUsed);
                    var    valMarshalId   = new CSIdentifier(valMarshalName);

                    var valDecl = CSVariableDeclaration.VarLine(csParmType, valMarshalId,
                                                                new CSCastExpression(csParmType, new CSFunctionCall("StructMarshal.Marshaler.ToNet", false, delegateParams [i].Name,
                                                                                                                    csParmType.Typeof())));
                    preMarshalCode.Add(valDecl);
                    callParams.Add(valMarshalId);
                }
                else if (entityType == EntityType.Tuple)
                {
                    var csParmType = csParm.CSType as CSSimpleType;
                    if (csParmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 35, "Inconceivable! The tuple type for a parameter in a method was NOT a CSSimpleType!");
                    }
                    use.AddIfNotPresent(typeof(StructMarshal));
                    string valMarshalName = MarshalEngine.Uniqueify(delegateParams [i].Name + "Temp", identifiersUsed);
                    var    valMarshalId   = new CSIdentifier(valMarshalName);

                    var valDecl = CSVariableDeclaration.VarLine(csParmType, valMarshalId,
                                                                new CSCastExpression(csParmType, new CSFunctionCall("StructMarshal.Marshaler.ToNet", false, delegateParams [i].Name,
                                                                                                                    csParmType.Typeof())));
                    preMarshalCode.Add(valDecl);
                    callParams.Add(valMarshalId);
                }
                else if (entityType == EntityType.Closure)
                {
                    // parm is a SwiftClosureRepresentation
                    // (FuncType)StructMarshal.Marshaler.MakeDelegateFromBlindClosure (arg, argTypes, returnType);
                    var argTypesId = new CSIdentifier(MarshalEngine.Uniqueify("argTypes" + delegateParams [i], identifiersUsed));
                    identifiersUsed.Add(argTypesId.Name);
                    var parmType = csParm.CSType as CSSimpleType;
                    if (parmType == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 44, "Inconceivable! The type for a closure should be a CSSimpleType");
                    }
                    var hasReturn      = parmType.GenericTypeName == "Func";
                    var returnType     = hasReturn ? (CSBaseExpression)parmType.GenericTypes [parmType.GenericTypes.Length - 1].Typeof() : CSConstant.Null;
                    var argTypesLength = hasReturn ? parmType.GenericTypes.Length - 1 : parmType.GenericTypes.Length;
                    var argTypes       = new CSBaseExpression [argTypesLength];
                    for (int idx = 0; idx < argTypesLength; idx++)
                    {
                        argTypes [idx] = parmType.GenericTypes [idx].Typeof();
                    }
                    var typeArr = new CSArray1DInitialized(CSSimpleType.Type, argTypes);

                    var closureExpr = new CSFunctionCall("StructMarshal.Marshaler.MakeDelegateFromBlindClosure", false, delegateParams [i].Name,
                                                         typeArr, returnType);
                    var castTo = new CSCastExpression(csParm.CSType, closureExpr);
                    callParams.Add(castTo);
                }
                else if (entityType == EntityType.ProtocolList)
                {
                    preMarshalCode.Add(CSFunctionCall.FunctionCallLine("throw new NotImplementedException", false, CSConstant.Val($"Argument {csParm.Name} is a protocol list type and can't be marshaled from a virtual method.")));
                    callParams.Add(CSConstant.Null);
                    marshalingThrows = true;
                }
                else if (parmIsGeneric)
                {
                    // parm is an IntPtr to some T
                    // to get T, we ask funcDecl for the depthIndex of T
                    // T someVal = (T)StructMarshal.Marshaler.ToNet(parm, typeof(T));
                    // someVal gets passed in
                    var genRef = csParm.CSType as CSGenericReferenceType;
                    if (genRef == null)
                    {
                        throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 36, "Inconceivable! The generic type for a parameter in a method was NOT a CSGenericReferenceType!");
                    }
                    use.AddIfNotPresent(typeof(StructMarshal));
                    string valMarshalName = MarshalEngine.Uniqueify(delegateParams [i].Name + "Temp", identifiersUsed);
                    var    valMarshalId   = new CSIdentifier(valMarshalName);

                    var valDecl = CSVariableDeclaration.VarLine(genRef, valMarshalId,
                                                                new CSCastExpression(genRef, new CSFunctionCall("StructMarshal.Marshaler.ToNet", false,
                                                                                                                delegateParams [i].Name,
                                                                                                                genRef.Typeof())));
                    preMarshalCode.Add(valDecl);
                    callParams.Add(valMarshalId);
                }
                else
                {
                    if (csParm.ParameterKind == CSParameterKind.Out || csParm.ParameterKind == CSParameterKind.Ref)
                    {
                        callParams.Add(new CSIdentifier(String.Format("{0} {1}",
                                                                      csParm.ParameterKind == CSParameterKind.Out ? "out" : "ref", delegateParams [i].Name.Name)));
                    }
                    else
                    {
                        callParams.Add(delegateParams [i].Name);
                    }
                }
            }

            var body = new CSCodeBlock();

            if (isObjC)
            {
                use.AddIfNotPresent("ObjCRuntime");
            }
            else
            {
                use.AddIfNotPresent(typeof(SwiftObjectRegistry));
            }


            CSBaseExpression invoker = null;

            if (isIndexer)
            {
                if (thisIsInterface)
                {
                    invoker = new CSIndexExpression(
                        $"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{thisType.ToString ()}> (self)",
                        false, callParams.ToArray());
                }
                else
                {
                    var registryCall = isObjC ?
                                       $"Runtime.GetNSObject<{thisType.ToString ()}> (self)" :
                                       $"SwiftObjectRegistry.Registry.CSObjectForSwiftObject <{thisType.ToString ()}> (self)";
                    invoker = new CSIndexExpression(registryCall, false, callParams.ToArray());
                }
            }
            else
            {
                if (thisIsInterface)
                {
                    invoker = new CSFunctionCall(
                        $"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{thisType.ToString ()}> (self).{methodName}",
                        false, callParams.ToArray());
                }
                else
                {
                    var registryCall = isObjC ?
                                       $"Runtime.GetNSObject<{thisType.ToString ()}>(self).{methodName}" :
                                       $"SwiftObjectRegistry.Registry.CSObjectForSwiftObject <{thisType.ToString ()}> (self).{methodName}";
                    invoker = new CSFunctionCall(registryCall, false, callParams.ToArray());
                }
            }

            var    tryBlock   = funcDecl.HasThrows ? new CSCodeBlock() : null;
            var    catchBlock = funcDecl.HasThrows ? new CSCodeBlock() : null;
            var    altBody    = tryBlock ?? body;
            string catchName  = MarshalEngine.Uniqueify("e", identifiersUsed);
            var    catchID    = new CSIdentifier(catchName);


            altBody.AddRange(preMarshalCode);
            if (marshalingThrows)
            {
                return(altBody);
            }

            if (funcDecl.HasThrows || needsReturn)               // function that returns or getter
            {
                if (funcDecl.HasThrows)
                {
                    use.AddIfNotPresent(typeof(SwiftError));
                    use.AddIfNotPresent(typeof(Tuple));
                    use.AddIfNotPresent(typeof(StructMarshal));
                    CSType returnTuple = null;
                    if (needsReturn)
                    {
                        returnTuple = new CSSimpleType("Tuple", false,
                                                       methodType,
                                                       new CSSimpleType(typeof(SwiftError)),
                                                       CSSimpleType.Bool);
                    }
                    else
                    {
                        returnTuple = new CSSimpleType("Tuple", false,
                                                       new CSSimpleType(typeof(SwiftError)),
                                                       CSSimpleType.Bool);
                    }


                    if (needsReturn)
                    {
                        string retvalName = MarshalEngine.Uniqueify("retval", identifiersUsed);
                        var    retvalId   = new CSIdentifier(retvalName);
                        altBody.Add(CSFieldDeclaration.VarLine(methodType, retvalId, invoker));
                        postMarshalCode.Add(CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.ToSwift", false,
                                                                            methodType.Typeof(),
                                                                            retvalId,
                                                                            delegateParams [0].Name));
                        altBody.Add(CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.SetErrorNotThrown", false,
                                                                    delegateParams [0].Name, returnTuple.Typeof()));
                    }
                    else
                    {
                        if (isSetter)
                        {
                            altBody.Add(CSAssignment.Assign(invoker, CSAssignmentOperator.Assign, valueExpr));
                        }
                        else
                        {
                            altBody.Add(new CSLine(invoker));
                        }
                        altBody.Add(CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.SetErrorNotThrown", false,
                                                                    delegateParams [0].Name, returnTuple.Typeof()));
                    }
                    string swiftError           = MarshalEngine.Uniqueify("err", identifiersUsed);
                    var    swiftErrorIdentifier = new CSIdentifier(swiftError);
                    catchBlock.Add(CSFieldDeclaration.VarLine(new CSSimpleType(typeof(SwiftError)), swiftErrorIdentifier,
                                                              new CSFunctionCall("SwiftError.FromException", false, catchID)));
                    catchBlock.Add(CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.SetErrorThrown", false,
                                                                   delegateParams [0].Name,
                                                                   swiftErrorIdentifier,
                                                                   returnTuple.Typeof()));
                }
                else
                {
                    if (returnIsClass)
                    {
                        string       retvalName = MarshalEngine.Uniqueify("retval", identifiersUsed);
                        CSIdentifier retvalId   = new CSIdentifier(retvalName);
                        altBody.Add(CSFieldDeclaration.VarLine(methodType, retvalId, invoker));
                        postMarshalCode.Add(CSReturn.ReturnLine(
                                                NewClassCompiler.SafeBackingFieldAccessor(retvalId, use, returnEntity.Type.ToFullyQualifiedName(), typeMapper)));
                    }
                    else if (returnIsProtocol)
                    {
                        string retvalName = MarshalEngine.Uniqueify("retval", identifiersUsed);
                        identifiersUsed.Add(retvalName);
                        var retvalId = new CSIdentifier(retvalName);
                        altBody.Add(CSFieldDeclaration.VarLine(methodType, retvalId, invoker));
                        var returnContainer = MarshalEngine.Uniqueify("returnContainer", identifiersUsed);
                        identifiersUsed.Add(returnContainer);
                        var returnContainerId = new CSIdentifier(returnContainer);
                        var protoGetter       = new CSFunctionCall($"SwiftObjectRegistry.Registry.ExistentialContainerForProtocols", false, retvalId, methodType.Typeof());
                        var protoDecl         = CSVariableDeclaration.VarLine(CSSimpleType.Var, returnContainerId, protoGetter);
                        var marshalBack       = CSFunctionCall.FunctionCallLine($"{returnContainer}.CopyTo", delegateParams [0].Name);
                        postMarshalCode.Add(protoDecl);
                        postMarshalCode.Add(marshalBack);
                    }
                    else if (returnIsStruct)
                    {
                        // non-blitable means that the parameter is an IntPtr and we can call the
                        // marshaler to copy into it
                        use.AddIfNotPresent(typeof(StructMarshal));
                        var marshalCall = CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.ToSwift", false,
                                                                          invoker, delegateParams [0].Name);
                        altBody.Add(marshalCall);
                    }
                    else if (returnIsTuple)
                    {
                        // non-blitable means that the parameter is an IntPtr and we can call the
                        // marshaler to copy into it
                        use.AddIfNotPresent(typeof(StructMarshal));
                        var marshalCall = CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.ToSwift", false,
                                                                          invoker, delegateParams [0].Name);
                        altBody.Add(marshalCall);
                    }
                    else if (returnIsGeneric)
                    {
                        // T retval = invoker();
                        // if (retval is ISwiftObject) {
                        //     Marshal.WriteIntPtr(delegateParams [0].Name, ((ISwiftObject)retval).SwiftObject);
                        // }
                        // else {
                        //    StructMarshal.Marshaler.ToSwift(typeof(T), retval, delegateParams[0].Name);
                        // }
                        string retvalName = MarshalEngine.Uniqueify("retval", identifiersUsed);
                        var    retvalId   = new CSIdentifier(retvalName);
                        altBody.Add(CSFieldDeclaration.VarLine(methodType, retvalId, invoker));
                        var ifClause = new CSCodeBlock();
                        ifClause.Add(CSFunctionCall.FunctionCallLine("Marshal.WriteIntPtr", false,
                                                                     delegateParams [0].Name,
                                                                     new CSParenthesisExpression(new CSCastExpression("ISwiftObject", retvalId)).Dot(NewClassCompiler.kSwiftObjectGetter)));
                        var elseClause = new CSCodeBlock();
                        elseClause.Add(CSFunctionCall.FunctionCallLine("StructMarshal.Marshaler.ToSwift", false,
                                                                       methodType.Typeof(),
                                                                       retvalId,
                                                                       delegateParams [0].Name));
                        CSBaseExpression ifExpr = new CSSimpleType("ISwiftObject").Typeof().Dot(new CSFunctionCall("IsAssignableFrom", false,
                                                                                                                   methodType.Typeof()));

                        var retTest = new CSIfElse(ifExpr, ifClause, elseClause);
                        altBody.Add(retTest);
                    }
                    else
                    {
                        if (returnIsClosure)
                        {
                            invoker = MarshalEngine.BuildBlindClosureCall(invoker, methodType as CSSimpleType, use);
                        }
                        if (postMarshalCode.Count > 0)
                        {
                            string       retvalName = MarshalEngine.Uniqueify("retval", identifiersUsed);
                            CSIdentifier retvalId   = new CSIdentifier(retvalName);
                            altBody.Add(CSFieldDeclaration.VarLine(methodType, retvalId, invoker));
                            postMarshalCode.Add(CSReturn.ReturnLine(retvalId));
                        }
                        else
                        {
                            altBody.Add(CSReturn.ReturnLine(invoker));
                        }
                    }
                }
            }
            else                 // no return or setter
            {
                if (isSetter)
                {
                    altBody.Add(CSAssignment.Assign(invoker, CSAssignmentOperator.Assign, valueExpr));
                }
                else
                {
                    altBody.Add(new CSLine(invoker));
                }
            }
            altBody.AddRange(postMarshalCode);

            if (funcDecl.HasThrows)
            {
                body.Add(new CSTryCatch(tryBlock, new CSCatch(typeof(Exception), catchName, catchBlock)));
            }
            return(body);
        }
예제 #26
0
        public static CSNamespace CreateManagedConsoleRedirect()
        {
            // Same as GetManagedConsoleRedirectCode, just different format.
            var cs = new CSNamespace();

            var console = new CSClass(CSVisibility.Public, "Console", isStatic: true);

            console.Fields.Add(CSFieldDeclaration.FieldLine(CSSimpleType.String, new CSIdentifier("filename"), isStatic: true));
            console.Properties.Add(
                new CSProperty(
                    CSSimpleType.String,
                    CSMethodKind.Static,
                    new CSIdentifier("Filename"),
                    CSVisibility.None,
                    CSCodeBlock.Create(
                        new CSIfElse(
                            new CSBinaryExpression(
                                CSBinaryOperator.Equal,
                                new CSIdentifier("filename"),
                                new CSIdentifier("null")
                                ),
                            CSCodeBlock.Create(
                                CSAssignment.Assign(
                                    new CSIdentifier("filename"),
                                    new CSBinaryExpression(
                                        CSBinaryOperator.NullCoalesce,
                                        CSFunctionCall.Function(
                                            "Environment.GetEnvironmentVariable",
                                            CSConstant.Val("LEAKTEST_STDOUT_PATH")
                                            ),
                                        new CSIdentifier("string.Empty")
                                        )
                                    )
                                )
                            ),
                        CSReturn.ReturnLine(new CSIdentifier("filename"))
                        ),
                    CSVisibility.None,
                    null
                    )
                );
            console.Methods.Add(
                new CSMethod(
                    CSVisibility.Public,
                    CSMethodKind.Static,
                    CSSimpleType.Void,
                    new CSIdentifier("write"),
                    new CSParameterList(
                        new CSParameter(CSSimpleType.String, new CSIdentifier("value"))
                        ),
                    CSCodeBlock.Create(
                        new CSIfElse(
                            new CSIdentifier("string.IsNullOrEmpty (Filename)"),
                            CSCodeBlock.Create(CSFunctionCall.FunctionCallLine("global::System.Console.Write", new CSIdentifier("value"))),
                            CSCodeBlock.Create(CSFunctionCall.FunctionCallLine("System.IO.File.AppendAllText", new CSIdentifier("Filename"), new CSIdentifier("value")))
                            )
                        )
                    )
                );
            console.Methods.Add(
                new CSMethod(
                    CSVisibility.Public,
                    CSMethodKind.Static,
                    CSSimpleType.Void,
                    new CSIdentifier("Write"),
                    new CSParameterList(
                        new CSParameter(CSSimpleType.Object, new CSIdentifier("value"))
                        ),
                    CSCodeBlock.Create(
                        CSFunctionCall.FunctionCallLine(
                            "write",
                            false,
                            new CSIdentifier("value?.ToString ()")
                            )
                        )
                    )
                );
            console.Methods.Add(
                new CSMethod(
                    CSVisibility.Public,
                    CSMethodKind.Static,
                    CSSimpleType.Void,
                    new CSIdentifier("Write"),
                    new CSParameterList(
                        new CSParameter(CSSimpleType.String, new CSIdentifier("value")),
                        new CSParameter(CSSimpleType.CreateArray("object"), new CSIdentifier("args"), CSParameterKind.Params)
                        ),
                    CSCodeBlock.Create(
                        CSFunctionCall.FunctionCallLine(
                            "write",
                            false,
                            new CSIdentifier("value == null ? string.Empty : string.Format (value, args)")
                            )
                        )
                    )
                );
            console.Methods.Add(
                new CSMethod(
                    CSVisibility.Public,
                    CSMethodKind.Static,
                    CSSimpleType.Void,
                    new CSIdentifier("WriteLine"),
                    new CSParameterList(
                        new CSParameter(CSSimpleType.Object, new CSIdentifier("value"))
                        ),
                    CSCodeBlock.Create(
                        CSFunctionCall.FunctionCallLine(
                            "write",
                            false,
                            new CSIdentifier("value?.ToString () + Environment.NewLine")
                            )
                        )
                    )
                );
            console.Methods.Add(
                new CSMethod(
                    CSVisibility.Public,
                    CSMethodKind.Static,
                    CSSimpleType.Void,
                    new CSIdentifier("WriteLine"),
                    new CSParameterList(
                        new CSParameter(CSSimpleType.String, new CSIdentifier("value")),
                        new CSParameter(CSSimpleType.CreateArray("object"), new CSIdentifier("args"), CSParameterKind.Params)
                        ),
                    CSCodeBlock.Create(
                        CSFunctionCall.FunctionCallLine(
                            "write",
                            false,
                            new CSIdentifier("(value == null ? string.Empty : string.Format (value, args)) + Environment.NewLine")
                            )
                        )
                    )
                );
            cs.Block.Add(console);
            return(cs);
        }
        public void ClassEquals()
        {
            // Note for future Steve
            // If an argument is a protocol with associated types, the calling conventions are different.
            // Typically, if a function accepts a protocol type as its argument it gets passed in as an existential
            // container.
            // It appears that if a function is generic with a protocol constraint then the argument gets
            // passed in as a pointer to the type then with the attendant metadata and protocol witness table
            // As a result, this code crashes since we're passing in the wrong type as far as I can tell.
            // This clearly needs more investigation

            // note to current or future Steve:
            // The calling conventions for this are:
            // rdi - pointer to value containing a
            // rsi - pointer to value containing b
            // rdx - metadata for type T
            // rcx - protocol witness table for T
            //
            // in pinvoke terms, this is
            // extern static void areEqualClass(IntPtr a, IntPtr b, SwiftMetatype mt, IntPtr protowitness);

            var swiftCode =
                $"public func areEqualClass<T:Equatable>(a: T, b: T) -> Bool {{\n" +
                "    return a == b\n" +
                "}\n" +
                "public protocol XXEquals {\n" +
                "    func Equals() -> Bool\n" +
                "}\n"
            ;

            var eqClass = new CSClass(CSVisibility.Public, "EqClass");
            var field   = CSVariableDeclaration.VarLine(CSSimpleType.Int, "X");

            eqClass.Fields.Add(field);
            var ctorParms = new CSParameterList();

            ctorParms.Add(new CSParameter(CSSimpleType.Int, new CSIdentifier("x")));
            var assignLine = CSAssignment.Assign("X", new CSIdentifier("x"));
            var ctor       = new CSMethod(CSVisibility.Public, CSMethodKind.None, null, new CSIdentifier("EqClass"), ctorParms,
                                          CSCodeBlock.Create(assignLine));

            eqClass.Constructors.Add(ctor);
            eqClass.Inheritance.Add(typeof(ISwiftEquatable));

            var eqParms = new CSParameterList();

            eqParms.Add(new CSParameter(new CSSimpleType("ISwiftEquatable"), new CSIdentifier("other")));
            var castLine = CSVariableDeclaration.VarLine(new CSSimpleType("EqClass"), "otherEqClass",
                                                         new CSBinaryExpression(CSBinaryOperator.As, new CSIdentifier("other"), new CSIdentifier("EqClass")));
            var nonNull    = new CSBinaryExpression(CSBinaryOperator.NotEqual, new CSIdentifier("otherEqClass"), CSConstant.Null);
            var valsEq     = new CSBinaryExpression(CSBinaryOperator.Equal, new CSIdentifier("otherEqClass.X"), new CSIdentifier("X"));
            var returnLine = CSReturn.ReturnLine(new CSBinaryExpression(CSBinaryOperator.And, nonNull, valsEq));
            var opEquals   = new CSMethod(CSVisibility.Public, CSMethodKind.None, CSSimpleType.Bool, new CSIdentifier("OpEquals"), eqParms,
                                          CSCodeBlock.Create(castLine, returnLine));

            eqClass.Methods.Add(opEquals);


            var newClass    = new CSFunctionCall("EqClass", true, CSConstant.Val(5));
            var isEqual     = new CSFunctionCall($"TopLevelEntities.AreEqualClass", false, newClass, newClass);
            var printer     = CSFunctionCall.ConsoleWriteLine(isEqual);
            var callingCode = CSCodeBlock.Create(printer);

            TestRunning.TestAndExecute(swiftCode, callingCode, "True\n", otherClass: eqClass, platform: PlatformName.macOS);
        }
        public CSProperty CompileProperty(CSUsingPackages packs, string propertyName,
                                          FunctionDeclaration getter, FunctionDeclaration setter, CSMethodKind methodKind = CSMethodKind.None)
        {
            var           swiftPropertyType = GetPropertyType(getter, setter);
            NetTypeBundle propertyType      = null;

            if (TypeMapper.IsCompoundProtocolListType(swiftPropertyType))
            {
                propertyType = new NetTypeBundle("System", "object", false, false, EntityType.ProtocolList);
            }
            else
            {
                propertyType = typeMap.MapType(getter, swiftPropertyType, false, true);
            }
            propertyName = propertyName ?? typeMap.SanitizeIdentifier(getter != null ? getter.PropertyName : setter.PropertyName);
            bool isSubscript = getter != null ? getter.IsSubscript :
                               setter.IsSubscript;

            if (!getter.IsTypeSpecGeneric(swiftPropertyType))
            {
                AddUsingBlock(packs, propertyType);
            }

            var uselessLine = new ICodeElement [] { CSReturn.ReturnLine(new CSIdentifier("useless")) };

            CSCodeBlock getterBlock = null;

            if (getter != null)
            {
                getterBlock = new CSCodeBlock(uselessLine);
            }
            CSCodeBlock setterBlock = null;

            if (setter != null)
            {
                setterBlock = new CSCodeBlock(uselessLine);
            }

            CSProperty theProp = null;

            if (isSubscript)
            {
                List <ParameterItem> swiftParms = null;
                if (getter != null)
                {
                    swiftParms = getter.ParameterLists [1];
                }
                else
                {
                    swiftParms = setter.ParameterLists [1].Skip(1).ToList();
                }
                var args = typeMap.MapParameterList(getter, swiftParms, false, false, null, null);
                args.ForEach(a => AddUsingBlock(packs, a.Type));

                var csParams =
                    new CSParameterList(
                        args.Select(a =>
                                    new CSParameter(a.Type.ToCSType(packs),
                                                    new CSIdentifier(a.Name), a.Type.IsReference ? CSParameterKind.Ref : CSParameterKind.None, null)));
                theProp = new CSProperty(propertyType.ToCSType(packs), methodKind, CSVisibility.Public, getterBlock,
                                         CSVisibility.Public, setterBlock, csParams);
            }
            else
            {
                theProp = new CSProperty(propertyType.ToCSType(packs), methodKind,
                                         new CSIdentifier(propertyName), CSVisibility.Public, getterBlock, CSVisibility.Public, setterBlock);
            }
            if (getterBlock != null)
            {
                getterBlock.Clear();
            }
            if (setterBlock != null)
            {
                setterBlock.Clear();
            }

            return(theProp);
        }