public static unsafe Stack <KeyValuePair <Smoke.ModuleIndex, string> > GetAbstractMethods(Smoke *smoke, short classId) { Dictionary <Smoke.ModuleIndex, string> methods = new Dictionary <Smoke.ModuleIndex, string>(SmokeMethodEqualityComparer.AbstractRespectingComparer); SmokeMethodEqualityComparer defaultComparer = SmokeMethodEqualityComparer.DefaultEqualityComparer; smoke->FindAllMethods(classId, methods, true); var abstractMethods = new Stack <KeyValuePair <Smoke.ModuleIndex, string> >(); foreach (KeyValuePair <Smoke.ModuleIndex, string> pair in methods) { Smoke.Method *meth = pair.Key.smoke->methods + pair.Key.index; if ((meth->flags & (ushort)Smoke.MethodFlags.mf_purevirtual) == 0) { // only compare pure-virtuals continue; } abstractMethods.Push(pair); foreach (KeyValuePair <Smoke.ModuleIndex, string> other in methods) { // Break if we encounter our original Index. Anything after this one will be further up in the // hierarchy and thus can't override anything. if (pair.Key == other.Key) { break; } Smoke.Method *otherMeth = other.Key.smoke->methods + other.Key.index; if (defaultComparer.Equals(pair.Key, other.Key)) { if ((otherMeth->flags & (ushort)Smoke.MethodFlags.mf_purevirtual) == 0) { // overriden with implementation abstractMethods.Pop(); } break; } } } return(abstractMethods); }
private void FillEnums() { for (short i = 1; i < this.data.Smoke->numMethodMaps; i++) { Smoke.MethodMap *map = this.data.Smoke->methodMaps + i; if (map->method > 0) { Smoke.Method *meth = this.data.Smoke->methods + map->method; if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0) { this.eg.DefineMember(meth); } } else if (map->method < 0) { for (short *overload = this.data.Smoke->ambiguousMethodList + (-map->method); *overload > 0; overload++) { Smoke.Method *meth = this.data.Smoke->methods + *overload; if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0) { this.eg.DefineMember(meth); continue; } // if the methods differ only by constness, we will generate special code bool nextDiffersByConst = false; if (*(overload + 1) > 0) { if (SmokeMethodEqualityComparer.EqualExceptConstness(meth, this.data.Smoke->methods + *(overload + 1))) { nextDiffersByConst = true; } } if (nextDiffersByConst) { overload++; } } } } }
/* * Adds the methods to the classes created by Run() */ private void GenerateMethods() { short currentClassId = 0; Smoke.Class * klass = (Smoke.Class *)IntPtr.Zero; MethodsGenerator methgen = null; AttributeGenerator attrgen = null; CodeTypeDeclaration type = null; List <Smoke.ModuleIndex> alreadyImplemented = new List <Smoke.ModuleIndex>(); this.FillEnums(); for (short i = 1; i < data.Smoke->numMethodMaps; i++) { Smoke.MethodMap *map = data.Smoke->methodMaps + i; if (currentClassId != map->classId) { // we encountered a new class if (attrgen != null) { // generate inherited methods this.GenerateInheritedMethods(klass, methgen, attrgen, alreadyImplemented); // generate all scheduled attributes attrgen.Run(); if (PostMembersHooks != null) { PostMembersHooks(data.Smoke, klass, type); } methgen.GenerateProperties(); } currentClassId = map->classId; klass = data.Smoke->classes + currentClassId; type = data.SmokeTypeMap[(IntPtr)klass]; alreadyImplemented.Clear(); attrgen = new AttributeGenerator(data, translator, type); methgen = new MethodsGenerator(data, translator, type, klass); } string mungedName = ByteArrayManager.GetString(data.Smoke->methodNames[map->name]); if (map->method > 0) { Smoke.Method *meth = data.Smoke->methods + map->method; if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_property) > 0 && // non-virtual properties are excluded (meth->flags & (ushort)Smoke.MethodFlags.mf_virtual) == 0 && (meth->flags & (ushort)Smoke.MethodFlags.mf_purevirtual) == 0) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(meth); continue; } methgen.GenerateMethod(map->method, mungedName); alreadyImplemented.Add(new Smoke.ModuleIndex(data.Smoke, map->method)); } else if (map->method < 0) { for (short *overload = data.Smoke->ambiguousMethodList + (-map->method); *overload > 0; overload++) { Smoke.Method *meth = data.Smoke->methods + *overload; if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_property) > 0 && // non-virtual properties are excluded (meth->flags & (ushort)Smoke.MethodFlags.mf_virtual) == 0 && (meth->flags & (ushort)Smoke.MethodFlags.mf_purevirtual) == 0) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(meth); continue; } // if the methods differ only by constness, we will generate special code bool nextDiffersByConst = false; if (*(overload + 1) > 0) { if (SmokeMethodEqualityComparer.EqualExceptConstness(meth, data.Smoke->methods + *(overload + 1))) { nextDiffersByConst = true; } } methgen.GenerateMethod(*overload, mungedName); alreadyImplemented.Add(new Smoke.ModuleIndex(data.Smoke, *overload)); if (nextDiffersByConst) { overload++; } } } } // Generate the last scheduled attributes attrgen.Run(); // Generate remaining inherited methods this.GenerateInheritedMethods(klass, methgen, attrgen, alreadyImplemented); if (PostMembersHooks != null) { PostMembersHooks(data.Smoke, klass, type); } methgen.GenerateProperties(); AddMissingOperators(); }