protected void GenerateProperty(RgacUDT owner, RgacProperty property, bool isStatic, List <Action> methodInvokers)
        {
            WriteLine("(new PropertyDescriptor(L\"{0}\", IMemberDescriptor::{1}))", property.Name, (isStatic ? "Static" : "Normal"));
            WriteLine("->PropertyType(" + GetType(property.PropertyType) + ")");
            if (property.PublicGacFieldAccessor == null)
            {
                if (property.Getter != null)
                {
                    Begin("->Getter(");
                    GenerateMethod(owner, property.Getter, isStatic, methodInvokers);
                    End(")");
                }
                if (property.Setter != null)
                {
                    Begin("->Setter(");
                    GenerateMethod(owner, property.Setter, isStatic, methodInvokers);
                    End(")");
                }
            }
            else
            {
                Begin("->Getter(");
                GenerateFieldAccessGetter(owner, property.PropertyType, property.Name, isStatic, methodInvokers);
                End(")");

                if (property.PublicGacFieldAccessor.Type.Kind != GacTypeKind.Const && !property.IsNotAssignableClassField)
                {
                    Begin("->Setter(");
                    GenerateFieldAccessSetter(owner, property.PropertyType, property.Name, isStatic, methodInvokers);
                    End(")");
                }
            }
        }
 protected void GenerateEnumItemProperty(RgacUDT owner, RgacType ownerType, GacConst enumItem, List <Action> methodInvokers)
 {
     WriteLine("(new PropertyDescriptor(L\"{0}\", IMemberDescriptor::{1}))", enumItem.Name, "Static");
     WriteLine("->PropertyType(" + GetType(ownerType) + ")");
     Begin("->Getter(");
     GenerateFieldAccessGetter(owner, ownerType, enumItem.Name, true, methodInvokers);
     End(")");
 }
        protected string GetType(GacType type)
        {
            switch (type.Kind)
            {
            case GacTypeKind.Primitive:
            {
                return(type.Name);
            }

            case GacTypeKind.Pointer:
            {
                string element = GetType(type.ElementType);
                if (element != null)
                {
                    return(element + "*");
                }
            }
            break;

            case GacTypeKind.Reference:
            {
                if (type.ElementType.Kind == GacTypeKind.Const)
                {
                    string element = GetType(type.ElementType);
                    if (element != null)
                    {
                        return("const " + element + "&");
                    }
                }
                else
                {
                    string element = GetType(type.ElementType);
                    if (element != null)
                    {
                        return(element + "&");
                    }
                }
            }
            break;

            case GacTypeKind.Const:
            {
                return(GetType(type.ElementType) + " const");
            }

            case GacTypeKind.UDT:
            {
                RgacUDT elementType = options.Udts.Where(t => t.AssociatedGacType == type.AssociatedUDT).FirstOrDefault();
                if (elementType != null)
                {
                    return(GacUdtTypeName(elementType));
                }
            }
            break;
            }
            return(null);
        }
 protected void GenerateMethodInvoker(RgacUDT owner, string methodInvokerName, List <Action> methodInvokers, Action action)
 {
     methodInvokers.Add(() =>
     {
         WriteLine("static DescriptableValue {0}(const DescriptableValue& thisObject, const collections::IReadonlyList<DescriptableValue>& parameters)", methodInvokerName);
         Begin("{");
         action();
         End("}");
     });
 }
        protected void GenerateValueExtractor(RgacUDT udt)
        {
            WriteLine("template<>");
            WriteLine("class __GacUIInternal<{0}>", udt.ToString());
            WriteLine("{");
            Begin("public:");
            WriteLine("typedef {0} WrappedObjectType;", udt.ToString());
            WriteLine("typedef {0} InternalObjectType;", udt.AssociatedGacType.Name);
            WriteLine("");

            WriteLine("static InternalObjectType* GetInternalObject(const WrappedObjectType& wrappedObject)");
            Begin("{");
            WriteLine("return (InternalObjectType*)wrappedObject.__internal_object_reference;");
            End("}");
            WriteLine("");

            WriteLine("static InternalObjectType* GetInternalObject(const rptr<WrappedObjectType>& wrappedObject)");
            Begin("{");
            WriteLine("return (InternalObjectType*)wrappedObject->__internal_object_reference;");
            End("}");
            WriteLine("");

            WriteLine("static Ptr<InternalObjectType> GetInternalObject(const sptr<WrappedObjectType>& wrappedObject)");
            Begin("{");
            WriteLine("return _SptrBuilder<WrappedObjectType>::RetrivePtr<InternalObjectType>(wrappedObject);");
            End("}");
            WriteLine("");

            if (udt.Kind == RgacUDTKind.Struct)
            {
                WriteLine("static WrappedObjectType BuildCopy(const InternalObjectType* input)");
                Begin("{");
                WriteLine("return new InternalObjectType(*input);");
                End("}");
                WriteLine("");
            }

            WriteLine("static rptr<WrappedObjectType> BuildRptr(const InternalObjectType* input)");
            Begin("{");
            WriteLine("return _RptrBuilder<WrappedObjectType>::CreateRptr(input);");
            End("}");
            WriteLine("");

            WriteLine("static sptr<WrappedObjectType> BuildSptr(const vl::Ptr<InternalObjectType>& input)");
            Begin("{");
            WriteLine("return _SptrBuilder<WrappedObjectType>::CreateSptr(input);");
            End("}");
            WriteLine("");

            End("};");
            WriteLine("");
        }
        protected void GenerateFieldAccessGetter(RgacUDT owner, RgacType type, string name, bool isStatic, List <Action> methodInvokers)
        {
            WriteLine("(new MethodDescriptor(L\"{0}\", IMemberDescriptor::{1}))", "get_" + name, (isStatic ? "Static" : "Normal"));
            WriteLine("->ReturnType(" + GetType(type) + ")");

            string methodInvokerName = "method_handler_get_" + name + "_" + methodInvokers.Count.ToString();

            GenerateMethodHandler(owner, methodInvokerName);
            GenerateMethodInvoker(owner, methodInvokerName, methodInvokers, () =>
            {
                WriteLine("throw 0;");
            });
        }
 protected RgacUDT[] GetRelatedUdts(RgacUDT udt)
 {
     return
         (udt.Constructors.SelectMany(GetRelatedUdts).Concat(
              udt.Methods.SelectMany(GetRelatedUdts).Concat(
                  udt.StaticMethods.SelectMany(GetRelatedUdts).Concat(
                      udt.Properties.SelectMany(GetRelatedUdts).Concat(
                          udt.StaticProperties.SelectMany(GetRelatedUdts)
                          ))))
          .Where(t => !this.PredeclaredClasses.Contains(t.ToString()))
          .Concat(udt.BaseClasses.Select(t => t.UDT))
          .Where(t => this.options.Udts.Contains(t))
          .Distinct()
          .ToArray());
 }
 protected void GenerateConstructorInitializationList(RgacUDT udt, string internalObjectReferenceInput)
 {
     WriteLine("    :__internal_object_reference({0})", internalObjectReferenceInput);
     foreach (var baseUdt in udt.BaseClasses
              .Where(t => t.Access == GacAccess.Public && this.options.Udts.Contains(t.UDT))
              .Select(t => t.UDT)
              )
     {
         WriteLine("    ,{0}(static_cast<__GacUIInternal<{1}>::InternalObjectType*>((__GacUIInternal<{2}>::InternalObjectType*){3}))",
                   baseUdt.ToString(),
                   baseUdt.ToString(),
                   udt.ToString(),
                   internalObjectReferenceInput
                   );
     }
 }
        protected void GenerateMethod(RgacUDT owner, RgacMethod method, bool isStatic, List <Action> methodInvokers)
        {
            WriteLine("(new MethodDescriptor(L\"{0}\", IMemberDescriptor::{1}))", method.Name, (isStatic ? "Static" : method.Kind.ToString()));
            WriteLine("->ReturnType(" + GetType(method.ReturnType) + ")");
            for (int i = 0; i < method.ParameterTypes.Length; i++)
            {
                WriteLine("->Parameter(L\"{0}\", {1})", method.ParameterNames[i], GetType(method.ParameterTypes[i]));
            }

            string methodName = method.Name;

            if (methodName.StartsWith("operator"))
            {
                switch (methodName)
                {
                case "operator[]": methodName = "operator_index"; break;

                case "operator=": methodName = "operator_assign"; break;

                case "operator<": methodName = "operator_lt"; break;

                case "operator<=": methodName = "operator_le"; break;

                case "operator>": methodName = "operator_gt"; break;

                case "operator>=": methodName = "operator_ge"; break;

                case "operator==": methodName = "operator_eq"; break;

                case "operator!=": methodName = "operator_ne"; break;

                default:
                    throw new ArgumentException();
                }
            }
            string methodInvokerName = "method_handler_" + methodName + "_" + methodInvokers.Count.ToString();

            GenerateMethodHandler(owner, methodInvokerName);
            GenerateMethodInvoker(owner, methodInvokerName, methodInvokers, () =>
            {
                WriteLine("throw 0;");
            });
        }
        protected void GenerateMembers(RgacUDT udt)
        {
            {
                WriteLine("{0}{1}(void* __internal_object_reference_input)",
                          udt.Name.Aggregate("", (a, b) => a + b + "::"),
                          udt.Name.Last()
                          );
                GenerateConstructorInitializationList(udt, "__internal_object_reference_input");
                Begin("{");
                End("}");
                WriteLine("");

                WriteLine("{0}~{1}()",
                          udt.Name.Aggregate("", (a, b) => a + b + "::"),
                          udt.Name.Last()
                          );
                Begin("{");
                if (udt.Kind == RgacUDTKind.Struct)
                {
                    WriteLine("delete __GacUIInternal<{0}>::GetInternalObject(*this);", udt.Name.Last());
                }
                End("}");
                WriteLine("");

                WriteLine("void {0}ClearInternalObjectReference()",
                          udt.Name.Aggregate("", (a, b) => a + b + "::")
                          );
                Begin("{");
                WriteLine("__internal_object_reference = 0;");
                foreach (var baseUdt in udt.BaseClasses
                         .Where(t => t.Access == GacAccess.Public && this.options.Udts.Contains(t.UDT))
                         .Select(t => t.UDT)
                         )
                {
                    WriteLine("{0}ClearInternalObjectReference();",
                              baseUdt.Name.Aggregate("", (a, b) => a + b + "::")
                              );
                }
                End("}");
                WriteLine("");
            }
            if (!udt.IsAbstract)
            {
                foreach (var m in udt.Constructors)
                {
                    GenerateConstructor(m);
                }
            }

            foreach (var m in udt.Methods)
            {
                GenerateMethod(m, false);
            }

            foreach (var m in udt.StaticMethods)
            {
                GenerateMethod(m, true);
            }

            foreach (var m in udt.Properties)
            {
                GenerateProperty(m, false);
            }

            foreach (var m in udt.StaticProperties)
            {
                GenerateProperty(m, true);
            }
        }
        protected string GetType(GacType type)
        {
            switch (type.Kind)
            {
            case GacTypeKind.Primitive:
            {
                switch (type.Name)
                {
                case "signed __int8":
                    return(GetPrimaryTypeCacheVariable("SInt8"));

                case "signed __int16":
                    return(GetPrimaryTypeCacheVariable("SInt16"));

                case "int":
                case "signed __int32":
                    return(GetPrimaryTypeCacheVariable("SInt32"));

                case "signed __int64":
                    return(GetPrimaryTypeCacheVariable("SInt64"));

                case "unsigned __int8":
                    return(GetPrimaryTypeCacheVariable("UInt8"));

                case "unsigned __int16":
                    return(GetPrimaryTypeCacheVariable("UInt16"));

                case "unsigned __int32":
                    return(GetPrimaryTypeCacheVariable("UInt32"));

                case "unsigned __int64":
                    return(GetPrimaryTypeCacheVariable("UInt64"));

                case "wchar_t":
                    return(GetPrimaryTypeCacheVariable("Char"));

                case "bool":
                    return(GetPrimaryTypeCacheVariable("Bool"));

                case "float":
                    return(GetPrimaryTypeCacheVariable("Float"));

                case "double":
                    return(GetPrimaryTypeCacheVariable("Double"));

                case "void":
                    return(GetPrimaryTypeCacheVariable("Void"));
                }
            }
            break;

            case GacTypeKind.Pointer:
            {
                string element = GetType(type.ElementType);
                if (element != null)
                {
                    return(element + "->GetPointerType()");
                }
            }
            break;

            case GacTypeKind.Reference:
            {
                if (type.ElementType.Kind == GacTypeKind.Const)
                {
                    string element = GetType(type.ElementType);
                    if (element != null)
                    {
                        return(element + "->GetConstReferenceType()");
                    }
                }
                else
                {
                    string element = GetType(type.ElementType);
                    if (element != null)
                    {
                        return(element + "->GetReferenceType()");
                    }
                }
            }
            break;

            case GacTypeKind.Const:
            {
                return(GetType(type.ElementType));
            }

            case GacTypeKind.UDT:
            {
                RgacUDT elementType = options.Udts.Where(t => t.AssociatedGacType == type.AssociatedUDT).FirstOrDefault();
                if (elementType != null)
                {
                    return(GetTypeCacheVariable(elementType));
                }
            }
            break;
            }
            return(null);
        }
 protected void GenerateMethodHandler(RgacUDT owner, string methodInvokerName)
 {
     WriteLine("->Handler(MethodDescriptor::HandlerFuncType(&{0}::{1}))", GetCppClassName(owner), methodInvokerName);
 }
        protected void GenerateCppHeader()
        {
            foreach (var udt in this.PredeclaredClasses)
            {
                WriteLine("class {0};", udt);
            }

            List <string> classNames = new List <string>();

            foreach (var udt in GetSortedUdts().ToArray())
            {
                int commonClassNames = 0;
                for (int i = 0; i < udt.Name.Length; i++)
                {
                    if (i < classNames.Count && classNames[i] == udt.Name[i])
                    {
                        commonClassNames = i + 1;
                    }
                    else
                    {
                        break;
                    }
                }

                for (int i = classNames.Count; i > commonClassNames; i--)
                {
                    End("};");
                    WriteLine("");
                    classNames.RemoveAt(i - 1);
                }

                WriteSectionComment(string.Format("{0}", udt.ToString()));
                for (int i = commonClassNames; i < udt.Name.Length; i++)
                {
                    string className = udt.Name[i];
                    classNames.Add(className);

                    if (i == udt.Name.Length - 1 && udt.Kind == RgacUDTKind.Enum)
                    {
                        WriteLine("enum {0}", className);
                        Begin("{");
                        foreach (var item in udt.AssociatedGacType.Constants)
                        {
                            WriteLine("{0} = {1},", item.Name, item.EnumItemValue);
                        }
                    }
                    else
                    {
                        string    cppClassName = classNames.Aggregate((a, b) => a + " :: " + b);
                        RgacUDT   currentUdt   = this.options.Udts.Where(t => t.ToString() == cppClassName).FirstOrDefault();
                        RgacUDT[] currentBases = new RgacUDT[] { };
                        if (currentUdt != null)
                        {
                            currentBases = currentUdt.BaseClasses
                                           .Where(t => t.Access == GacAccess.Public && this.options.Udts.Contains(t.UDT))
                                           .Select(t => t.UDT)
                                           .ToArray();
                        }
                        if (currentBases.Length == 0)
                        {
                            WriteLine("class GACUI_API {0}", className);
                        }
                        else
                        {
                            WriteLine("class GACUI_API {0} : {1}",
                                      className,
                                      currentBases
                                      .Select(t => "public " + t.ToString())
                                      .Aggregate((a, b) => a + ", " + b)
                                      );
                        }
                        WriteLine("{");
                        Begin("public:");
                    }
                }
                if (udt.Kind != RgacUDTKind.Enum)
                {
                    GenerateMembers(udt);
                }
            }
            for (int i = 0; i < classNames.Count; i++)
            {
                End("};");
            }
        }
 protected string GetTypeCacheVariable(RgacUDT udt)
 {
     return("(gacui_tpimp_type_cache_table." + GetTypeCacheVariableName(udt) + ")");
 }
 protected string GacUdtTypeName(RgacUDT udt)
 {
     return(udt.Name
            .Aggregate((a, b) => a + " :: " + b));
 }
 protected void GenerateTypeDescriptorBody(RgacUDT udt, List <Action> methodInvokers)
 {
     if (udt.Kind == RgacUDTKind.Enum)
     {
         RgacType enumType = new RgacType
         {
             Kind = RgacTypeKind.Enum,
             AssociatedRgacType = udt,
             OriginalGacType    = new GacType
             {
                 Name          = udt.AssociatedGacType.Name,
                 Kind          = GacTypeKind.UDT,
                 AssociatedUDT = udt.AssociatedGacType,
             },
         };
         foreach (var c in udt.AssociatedGacType.Constants)
         {
             Begin("AddProperty(");
             GenerateEnumItemProperty(udt, enumType, c, methodInvokers);
             End(");");
         }
     }
     else
     {
         foreach (var t in udt.BaseClasses)
         {
             if (t.Access == GacAccess.Public && options.Udts.Contains(t.UDT))
             {
                 WriteLine("AddBaseType(" + GetTypeCacheVariable(t.UDT) + ");");
             }
         }
         if (udt.Constructors.Length > 0)
         {
             if (!udt.IsAbstract)
             {
                 foreach (var m in udt.Constructors)
                 {
                     Begin("AddConstructor(");
                     GenerateMethod(udt, m, false, methodInvokers);
                     End(");");
                 }
             }
         }
         foreach (var m in udt.Methods)
         {
             Begin("AddMethod(");
             GenerateMethod(udt, m, false, methodInvokers);
             End(");");
         }
         foreach (var m in udt.StaticMethods)
         {
             Begin("AddMethod(");
             GenerateMethod(udt, m, true, methodInvokers);
             End(");");
         }
         foreach (var p in udt.Properties)
         {
             Begin("AddProperty(");
             GenerateProperty(udt, p, false, methodInvokers);
             End(");");
         }
         foreach (var p in udt.StaticProperties)
         {
             Begin("AddProperty(");
             GenerateProperty(udt, p, true, methodInvokers);
             End(");");
         }
     }
 }
 protected string GetCppClassName(RgacUDT udt)
 {
     return(udt.Name
            .Select(n => GetCppClassName(n))
            .Aggregate((a, b) => a + " :: " + b));
 }
        protected void GenerateMembers(RgacUDT udt)
        {
            End("");
            Begin("protected:");
            WriteLine("template<typename T> friend class __GacUIInternal;");
            WriteLine("void* __internal_object_reference;");
            WriteLine("{0}(void* __internal_object_reference_input);", udt.Name.Last());
            WriteLine("void ClearInternalObjectReference();");
            End("");
            Begin("public:");
            WriteLine("virtual ~{0}();", udt.Name.Last());
            End("");
            Begin("public:");
            if (udt.Name.Length == 1)
            {
                foreach (var t in this.options.Udts)
                {
                    if (t.Kind != RgacUDTKind.Enum)
                    {
                        if (t.Name.Length == 2 && t.Name[0] == udt.Name[0])
                        {
                            WriteLine("class {0};", t.Name[1]);
                        }
                    }
                }
                WriteLine("");
            }

            if (udt.Constructors.Length > 0 && !udt.IsAbstract)
            {
                foreach (var m in udt.Constructors)
                {
                    GenerateConstructor(m);
                }
                WriteLine("");
            }

            if (udt.Methods.Length > 0)
            {
                foreach (var m in udt.Methods)
                {
                    GenerateMethod(m, false);
                }
                WriteLine("");
            }

            if (udt.StaticMethods.Length > 0)
            {
                foreach (var m in udt.StaticMethods)
                {
                    GenerateMethod(m, true);
                }
                WriteLine("");
            }

            if (udt.Properties.Length > 0)
            {
                foreach (var m in udt.Properties)
                {
                    GenerateProperty(m, false);
                }
                WriteLine("");
            }

            if (udt.StaticProperties.Length > 0)
            {
                foreach (var m in udt.StaticProperties)
                {
                    GenerateProperty(m, true);
                }
                WriteLine("");
            }
        }
 protected string GetTypeCacheVariableName(RgacUDT udt)
 {
     return("cache_" + udt.Name
            .Aggregate((a, b) => a + "_member_" + b));
 }