void FindsProperty(string code, Func <ClassDeclaration, bool> classFinder, Func <PropertyDeclaration, bool> propFinder) { CustomSwiftCompiler compiler = Utils.CompileSwift(code, moduleName: "CanFind"); var errors = new ErrorHandling(); ModuleInventory mi = ModuleInventory.FromFile(Path.Combine(compiler.DirectoryPath, "libCanFind.dylib"), errors); ModuleDeclaration mod = compiler.ReflectToModules(new string [] { compiler.DirectoryPath }, new string [] { compiler.DirectoryPath }, null, "CanFind") [0]; ClassDeclaration classDecl = mod.AllClasses.FirstOrDefault(classFinder); Assert.IsNotNull(classDecl, "null class"); PropertyDeclaration propDecl = classDecl.Members.OfType <PropertyDeclaration> ().FirstOrDefault(propFinder); Assert.IsNotNull(propDecl, "null property"); FunctionDeclaration getter = propDecl.GetGetter(); Assert.IsNotNull(getter, "null getter"); FunctionDeclaration setter = propDecl.GetSetter(); Assert.IsNotNull(setter, "null setter"); TLFunction tlgetter = XmlToTLFunctionMapper.ToTLFunction(getter, mi); Assert.IsNotNull(tlgetter, "null tlgetter"); TLFunction tlsetter = XmlToTLFunctionMapper.ToTLFunction(setter, mi); Assert.IsNotNull(tlsetter, "null tlsetter"); }
public static ValueWitnessTable FromStream(Stream stm, TLFunction tlf, int sizeofMachinePointer) { if (sizeofMachinePointer != 4 && sizeofMachinePointer != 8) { throw ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 14, $"Expected a maching pointer size of either 4 or 8, but got {sizeofMachinePointer}"); } var wit = tlf.Signature as SwiftWitnessTableType; if (wit == null || wit.WitnessType != WitnessType.Value) { throw ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 15, $"Expected a SwiftWitnessTable, but got {tlf.Signature.GetType ().Name}."); } var reader = new BinaryReader(stm); reader.BaseStream.Seek((long)tlf.Offset, SeekOrigin.Begin); var table = new ValueWitnessTable(); table.MangledName = tlf.MangledName; if (sizeofMachinePointer == 4) { table.Read32(reader); } else { table.Read64(reader); } return(table); }
public override void Add(TLDefinition tld, Stream srcStm) { TLVariable vari = tld as TLVariable; if (vari != null) { VariableContents contents = GoGetIt(vari.Name); if (contents.Variable != null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 4, $"duplicate variable {vari.Name.Name}."); } contents.Variable = vari; return; } TLFunction tlf = tld as TLFunction; if (tlf != null) { VariableContents contents = GoGetIt(tlf.Name); contents.Addressors.Add(tlf); return; } throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 5, $"expected a top-level function or top-level variable but got a {tld.GetType ().Name}"); }
void CanFindThing(string code, Func <ClassDeclaration, bool> classFinder, Func <FunctionDeclaration, bool> funcFinder, Func <TLFunction, bool> tlVerifier) { CustomSwiftCompiler compiler = Utils.CompileSwift(code, moduleName: "CanFind"); var errors = new ErrorHandling(); ModuleInventory mi = ModuleInventory.FromFile(Path.Combine(compiler.DirectoryPath, "libCanFind.dylib"), errors); ModuleDeclaration mod = compiler.ReflectToModules(new string [] { compiler.DirectoryPath }, new string [] { compiler.DirectoryPath }, null, "CanFind") [0]; ClassDeclaration classDecl = mod.AllClasses.FirstOrDefault(classFinder); Assert.IsNotNull(classDecl, "nominal type not found"); FunctionDeclaration funcDecl = classDecl.AllMethodsNoCDTor().FirstOrDefault(funcFinder); Assert.IsNotNull(funcDecl, "func decl not found"); // see the note in the implementation of CanFindThing above TLFunction func = XmlToTLFunctionMapper.ToTLFunction(funcDecl, mi, null); Assert.IsNotNull(func, "TLFunction not found"); Assert.IsTrue(tlVerifier(func), "verifier failed"); }
public override void Add(TLDefinition tld, Stream srcStm) { TLFunction tlf = tld as TLFunction; if (tlf == null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 7, $"Expected a TLFunction for a property but got a {tld.GetType ().Name}."); } SwiftPropertyType prop = tlf.Signature as SwiftPropertyType; if (prop == null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 8, $"Expected a function of property type but got a {tlf.Signature.GetType ().Name}."); } PropertyContents contents = null; SwiftName nameToUse = prop.PrivateName ?? prop.Name; if (!values.TryGetValue(nameToUse, out contents)) { contents = new PropertyContents(tlf.Class, nameToUse, sizeofMachinePointer); values.Add(nameToUse, contents); } contents.Add(tlf, prop); }
static bool IsHomonym(TLFunction func1, TLFunction func2) { // Two functions are homonyms if and only if // 1. They are not the same function // 2. The same function name // 3. Matching argument types // 4. Either different argument names or different argument types // 1. not the same function if (func1.MangledName == func2.MangledName) { return(false); } // 2. same name if (!func1.Signature.Name.Equals(func2.Signature.Name)) { return(false); } // 3. same argument types if (!ArgumentTypesMatch(func1, func2)) { return(false); } return(!ArgumentNamesMatch(func1, func2) || !ReturnTypesMatch(func1, func2)); }
public void Add(TLDefinition tld, Stream srcStm) { TLFunction tlf = tld as TLFunction; if (tlf != null) { if (tlf.Signature.IsExtension) { Extensions.Add(tlf, srcStm); } else if (tlf.IsTopLevelFunction) { if (tlf.Signature is SwiftAddressorType) { Variables.Add(tlf, srcStm); } else if (tlf.Signature is SwiftWitnessTableType) { WitnessTables.Add(tld, srcStm); } else { Functions.Add(tlf, srcStm); } } else { if (tlf.Class.EntityKind == MemberNesting.Protocol) { Protocols.Add(tlf, srcStm); } else { Classes.Add(tld, srcStm); } } } else { if (tld is TLVariable tlvar && ((TLVariable)tld).Class == null) { if (tlvar is TLPropertyDescriptor propDesc) { if (propDesc.ExtensionOn != null) { ExtensionDescriptors.Add(propDesc); } else { PropertyDescriptors.Add(tlvar, srcStm); } } else { Variables.Add(tld, srcStm); } }
WitnessType FromTLF(TLFunction tlf) { SwiftWitnessTableType wit = tlf.Signature as SwiftWitnessTableType; if (wit == null) { throw new ArgumentException("tlf"); } return(wit.WitnessType); }
public static bool IsHomonym(TLFunction func, OverloadInventory inventory) { foreach (TLFunction f in inventory.Functions) { if (IsHomonym(func, f)) { return(true); } } return(false); }
public bool IsFinal(TLFunction func) { string funcMangledSuffix = func.MangledName.Substring(3); // drop the __T foreach (string mangledWitnessEntry in WitnessTable.MangledNames) { if (mangledWitnessEntry.EndsWith(funcMangledSuffix)) { return(false); } } return(true); }
void LoadWitnessTable(TLFunction tlf, Stream stm) { WitnessType type = FromTLF(tlf); switch (type) { case WitnessType.Value: ValueWitnessTable = ValueWitnessTable.FromStream(stm, tlf, sizeofMachinePointer); break; default: break; } }
public void Add(TLDefinition tld, Stream srcStm) { TLFunction tlf = tld as TLFunction; if (tlf == null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 9, $"Expected a TLFunction for a witness table but got a {tld.GetType ().Name}."); } if (values.ContainsKey(tlf.MangledName)) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 10, $"Already received witness table entry for {tlf.MangledName}."); } values.Add(tlf.MangledName, tlf); LoadWitnessTable(tlf, srcStm); }
static bool ArgumentTypesMatch(TLFunction func1, TLFunction func2) { if (func1.Signature.ParameterCount != func2.Signature.ParameterCount) { return(false); } for (int i = 0; i < func1.Signature.ParameterCount; i++) { var funcarg1 = func1.Signature.GetParameter(i); var funcarg2 = func2.Signature.GetParameter(i); if (!funcarg1.Equals(funcarg2)) { return(false); } } return(true); }
static List <string> HomonymPartsFor(TLFunction func, TypeMapper mapper) { var parts = func.Signature.EachParameter.Select(arg => arg.Name.Name).ToList(); if (func.Signature.ReturnType == null || func.Signature.ReturnType.IsEmptyTuple) { parts.Add("void"); } else { var use = new CSUsingPackages(); var ntb = mapper.MapType(func.Signature.ReturnType, false); var type = NetTypeBundle.ToCSSimpleType(ntb, use); var returnTypeName = type.ToString().Replace(".", "").Replace("<", "").Replace(">", ""); parts.Add(returnTypeName); } return(parts); }
public override void Add(TLDefinition tld, Stream srcStm) { TLFunction tlf = tld as TLFunction; if (tlf == null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 10, $"expected a top-level function but got a {tld.GetType ().Name}"); } OverloadInventory overloads = null; if (!values.TryGetValue(tlf.Name, out overloads)) { overloads = new OverloadInventory(tlf.Name, sizeofMachinePointer); values.Add(tlf.Name, overloads); } overloads.Add(tlf, srcStm); }
void CanFindThing(string code, Func <FunctionDeclaration, bool> funcFinder, Func <TLFunction, bool> tlVerifier) { CustomSwiftCompiler compiler = Utils.CompileSwift(code, moduleName: "CanFind"); var errors = new ErrorHandling(); ModuleInventory mi = ModuleInventory.FromFile(Path.Combine(compiler.DirectoryPath, "libCanFind.dylib"), errors); ModuleDeclaration mod = compiler.ReflectToModules(new string [] { compiler.DirectoryPath }, new string [] { compiler.DirectoryPath }, null, "CanFind") [0]; FunctionDeclaration funcDecl = mod.Functions.FirstOrDefault(funcFinder); Assert.IsNotNull(funcDecl, "no function found"); TLFunction func = XmlToTLFunctionMapper.ToTLFunction(funcDecl, mi); Assert.IsNotNull(func, $"failed to find TLFunction for {funcDecl.Name}"); Assert.IsTrue(tlVerifier(func), "verifier failed"); }
void CanFindThing(string code, Func <FunctionDeclaration, bool> funcFinder, Func <TLFunction, bool> tlVerifier) { CustomSwiftCompiler compiler = Utils.CompileSwift(code, moduleName: "CanFind"); var errors = new ErrorHandling(); ModuleInventory mi = ModuleInventory.FromFile(Path.Combine(compiler.DirectoryPath, "libCanFind.dylib"), errors); ModuleDeclaration mod = compiler.ReflectToModules(new string [] { compiler.DirectoryPath }, new string [] { compiler.DirectoryPath }, null, "CanFind") [0]; FunctionDeclaration funcDecl = mod.Functions.FirstOrDefault(funcFinder); Assert.IsNotNull(funcDecl, "no function found"); // note: if you get an NRE from here then you are testing an argument that includes // an associated type path from a generic. Don't do that. You need much more infrastructure to // do that than you really want here. TLFunction func = XmlToTLFunctionMapper.ToTLFunction(funcDecl, mi, null); Assert.IsNotNull(func, $"failed to find TLFunction for {funcDecl.Name}"); Assert.IsTrue(tlVerifier(func), "verifier failed"); }
public void Add(TLDefinition tld, Stream srcStm) { TLFunction tlf = tld as TLFunction; if (tlf != null) { if (IsConstructor(tlf.Signature, tlf.Class)) { Constructors.Add(tlf, srcStm); } else if (tlf.Signature is SwiftClassConstructorType) { if (ClassConstructor.Values.Count() == 0) { ClassConstructor.Add(tlf, srcStm); } else { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 12, $"multiple type metadata accessors for {tlf.Class.ClassName.ToFullyQualifiedName ()}"); } } else if (IsDestructor(tlf.Signature, tlf.Class)) { Destructors.Add(tlf, srcStm); } else if (IsProperty(tlf.Signature, tlf.Class)) { if (IsSubscript(tlf.Signature, tlf.Class)) { if (IsPrivateProperty(tlf.Signature, tlf.Class)) { PrivateSubscripts.Add(tlf); } else { Subscripts.Add(tlf); } } else { if (IsStaticProperty(tlf.Signature, tlf.Class)) { if (IsPrivateProperty(tlf.Signature, tlf.Class)) { StaticPrivateProperties.Add(tlf, srcStm); } else { StaticProperties.Add(tlf, srcStm); } } else { if (IsPrivateProperty(tlf.Signature, tlf.Class)) { PrivateProperties.Add(tlf, srcStm); } else { Properties.Add(tlf, srcStm); } } } } else if (IsMethodOnClass(tlf.Signature, tlf.Class)) { if (tlf is TLMethodDescriptor) { MethodDescriptors.Add(tlf, srcStm); } else { Methods.Add(tlf, srcStm); } } else if (IsStaticMethod(tlf.Signature, tlf.Class)) { StaticFunctions.Add(tlf, srcStm); } else if (IsWitnessTable(tlf.Signature, tlf.Class)) { WitnessTable.Add(tlf, srcStm); } else if (IsInitializer(tlf.Signature, tlf.Class)) { Initializers.Add(tlf, srcStm); } else { FunctionsOfUnknownDestination.Add(tlf); } return; } var meta = tld as TLDirectMetadata; if (meta != null) { if (DirectMetadata != null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 13, $"duplicate direct metadata in class {DirectMetadata.Class.ClassName.ToFullyQualifiedName ()}"); } DirectMetadata = meta; return; } var lazy = tld as TLLazyCacheVariable; if (lazy != null) { if (LazyCacheVariable != null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 14, $"duplicate lazy cache variable in class {LazyCacheVariable.Class.ClassName.ToFullyQualifiedName ()}"); } LazyCacheVariable = lazy; return; } var mc = tld as TLMetaclass; if (mc != null) { if (Metaclass != null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 15, $"duplicate type meta data descriptor in class {Metaclass.Class.ClassName.ToFullyQualifiedName ()}"); } Metaclass = mc; return; } var nom = tld as TLNominalTypeDescriptor; if (nom != null) { if (TypeDescriptor != null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 16, $"duplicate nominal type descriptor in class {TypeDescriptor.Class.ClassName.ToFullyQualifiedName ()}"); } TypeDescriptor = nom; return; } var tlvar = tld as TLVariable; if (tlvar != null) { if (tlvar is TLPropertyDescriptor tlpropDesc) { PropertyDescriptors.Add(tlpropDesc); } else { Variables.Add(tlvar, srcStm); } return; } var tlprot = tld as TLProtocolConformanceDescriptor; if (tlprot != null) { ProtocolConformanceDescriptors.Add(tlprot); return; } DefinitionsOfUnknownDestination.Add(tld); }
public void Add(TLFunction tlf, SwiftPropertyType prop) { var method = tlf as TLMethodDescriptor; if (method != null) { switch (prop.PropertyType) { case PropertyType.Getter: TLFGetterDescriptor = method; break; case PropertyType.Setter: TLFSetterDescriptor = method; break; case PropertyType.Materializer: TLFMaterializerDescriptor = method; break; case PropertyType.DidSet: TLFDidSetDescriptor = method; break; case PropertyType.WillSet: TLFWillSetDescriptor = method; break; case PropertyType.ModifyAccessor: TLFModifyDescriptor = method; break; default: throw ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 68, $"Unexpected property descriptor {prop.PropertyType.ToString ()}"); } } else { switch (prop.PropertyType) { case PropertyType.Getter: Getter = prop; TLFGetter = tlf; break; case PropertyType.Setter: Setter = prop; TLFSetter = tlf; break; case PropertyType.Materializer: Materializer = prop; TLFMaterializer = tlf; break; case PropertyType.DidSet: DidSet = prop; TLFDidSet = tlf; break; case PropertyType.WillSet: WillSet = prop; TLFWillSet = tlf; break; case PropertyType.ModifyAccessor: ModifyAccessor = prop; TLFModifyAccessor = tlf; break; default: throw ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 2, $"Unexpected property element {prop.PropertyType.ToString ()}"); } } }
public void Add(TLDefinition tld, Stream srcStm) { TLFunction tlf = tld as TLFunction; if (tlf != null) { if (ClassContents.IsWitnessTable(tlf.Signature, tlf.Class)) { WitnessTable.Add(tlf, srcStm); } FunctionsOfUnknownDestination.Add(tlf); return; } TLDirectMetadata meta = tld as TLDirectMetadata; if (meta != null) { if (DirectMetadata != null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 1, $"duplicate direct metadata in protocol {DirectMetadata.Class.ClassName.ToFullyQualifiedName ()}"); } DirectMetadata = meta; return; } TLMetaclass mc = tld as TLMetaclass; if (mc != null) { if (Metaclass != null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 2, $"duplicate type meta data descriptor in protocol {Metaclass.Class.ClassName.ToFullyQualifiedName ()}"); } Metaclass = mc; return; } TLProtocolTypeDescriptor ptd = tld as TLProtocolTypeDescriptor; if (ptd != null) { if (TypeDescriptor != null) { throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 3, $"duplicate protocol type descriptor in protocol {TypeDescriptor.Class.ClassName.ToFullyQualifiedName ()}"); } TypeDescriptor = ptd; return; } if (tld is TLProtocolRequirementsBaseDescriptor baseDescriptor) { BaseDescriptors.Add(baseDescriptor); return; } if (tld is TLBaseConformanceDescriptor baseConformanceDescriptor) { BaseConformanceDescriptors.Add(baseConformanceDescriptor); return; } DefinitionsOfUnknownDestination.Add(tld); }
static bool ReturnTypesMatch(TLFunction func1, TLFunction func2) { return(func1.Signature.ReturnType.Equals(func2.Signature.ReturnType)); }
static List <List <string> > HomonymPartsFor(TLFunction func, OverloadInventory inventory, TypeMapper mapper) { return(inventory.Functions.Where(f => IsHomonym(func, f)).Select(f => HomonymPartsFor(f, mapper)).ToList()); }
public static string HomonymSuffix(TLFunction func, OverloadInventory inventory, TypeMapper mapper) { return(HomonymSuffix(HomonymPartsFor(func, mapper), HomonymPartsFor(func, inventory, mapper))); }
static bool SignaturesMatch(FunctionDeclaration decl, TLFunction func, TypeMapper typeMap) { if (decl.IsConstructor && !(func.Signature is SwiftConstructorType) || (!decl.IsConstructor && func.Signature is SwiftConstructorType)) { return(false); } List <ParameterItem> significantParameterList = decl.ParameterLists.Last(); if (decl.ParameterLists.Count > 1 && !decl.IsStatic) { var ucf = func.Signature as SwiftUncurriedFunctionType; if (ucf == null) { return(false); } var uncurriedParameter = ucf.UncurriedParameter; var uncurriedTuple = uncurriedParameter as SwiftTupleType; // the !decl.IsConstructor is because the uncurried parameter in a constructor comes out // "funny" in XmlReflection and won't match if ((decl.Parent == null || !(decl.Parent is StructDeclaration)) && !decl.IsConstructor) { if (decl.ParameterLists [0].Count == 1) { if (!TypeMatches(decl, decl.ParameterLists [0] [0], uncurriedParameter, false, typeMap)) { return(false); } } else if (decl.ParameterLists [0].Count == 0) { if (uncurriedTuple == null || !uncurriedTuple.IsEmpty) { return(false); } } else { if (uncurriedTuple == null || !TypeMatches(decl, decl.ParameterLists [0], uncurriedTuple, typeMap)) { return(false); } } } } // return is implied in constructor - we're good on that, thanks bool dontMatchReturn = decl.IsConstructor; if (func.Signature.ParameterCount == significantParameterList.Count) { if (func.Signature.ParameterCount == 0) { return(dontMatchReturn || TypeMatches(decl, decl.ReturnTypeSpec, func.Signature.ReturnType, typeMap)); } if (func.Signature.ParameterCount == 1) { var tuple = func.Signature.Parameters as SwiftTupleType; var argsMatch = TypeMatches(decl, significantParameterList [0], tuple != null ? tuple.Contents [0] : func.Signature.Parameters, decl.IsSetter, typeMap); var returnMatches = (dontMatchReturn || TypeMatches(decl, decl.ReturnTypeSpec, func.Signature.ReturnType, typeMap)); return(argsMatch && returnMatches); } else { var argsMatch = TypeMatches(decl, significantParameterList, func.Signature.Parameters as SwiftTupleType, typeMap); var returnMatches = dontMatchReturn || TypeMatches(decl, decl.ReturnTypeSpec, func.Signature.ReturnType, typeMap); return(argsMatch && returnMatches); } } else { // oh, hooray. Swift does a reduction in the tuple-ness of arguments. // if I declare a function, func a(a:(Bool, Bool)) { } // This should get turned into: // __TF6Module1aFTTSbSb__T_ // Instead, swift turns it into: // __TF6Module1aFTSbSb_T_ // In other words, if the only argument to the function is a tuple, unwrap it. if (significantParameterList.Count == 1 && significantParameterList [0].TypeSpec is TupleTypeSpec) { return(TypeMatches(decl, significantParameterList [0], func.Signature.Parameters, false, typeMap) && (dontMatchReturn || TypeMatches(decl, decl.ReturnTypeSpec, func.Signature.ReturnType, typeMap))); } } return(false); }