Exemple #1
0
    static void ExportUdonTypes()
    {
        string path         = EditorUtility.SaveFilePanel("Save Udon Types", "", "UdonNodeInfo", "dll");
        var    typeResolver = new TypeResolverGroup(new List <IUAssemblyTypeResolver>()
        {
            new SystemTypeResolver(),
            new UnityEngineTypeResolver(),
            new VRCSDK2TypeResolver(),
            new UdonTypeResolver(),
            new ExceptionTypeResolver(),
            new UdonBehaviourTypeResolver(),
        });
        var rootType = new TDType();

        try
        {
            EditorUtility.DisplayProgressBar("Progress", "Parsing Definitions...", 1f / 2);
            ParseDefinitions(rootType, typeResolver);

            EditorUtility.DisplayProgressBar("Progress", "Saving to file...", 2f / 2);

            string codeString = UdonTypeDLLExporter.ExportTDTypeAsDLL(rootType, typeResolver);

            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateExecutable = false;
            parameters.CompilerOptions    = "-nostdlib -noconfig";
            parameters.OutputAssembly     = "Output.dll";
            CompilerResults r = CodeDomProvider.CreateProvider("CSharp")
                                .CompileAssemblyFromSource(parameters, codeString);

            foreach (var s in r.Output)
            {
                if (s.Contains("warning"))
                {
                    continue;
                }
                Debug.Log(s);
            }

            File.WriteAllLines("source.txt", new[] { codeString });

            File.Copy("Output.dll", path, true);
        }
        finally
        {
            EditorUtility.ClearProgressBar();
        }

        Debug.Log($"Done\nOutput to: {path}");
    }
Exemple #2
0
 private static void AddInputs(Class Class, Method method)
 {
     for (int i = 0; i < method.Inputs.Count; i++)
     {
         TDType input = method.Inputs[i];
         Class.Methods.Append(input);                                                                                                     //Type name
         Class.Methods.Append(
             $" {UdonTypeExporter.RemoveTypeSpecialCharacters(UdonTypeExporter.FirstCharacterToLower(input.UdonName), true, true)}_{i}"); //Parameter name
         if (i != method.Inputs.Count - 1)
         {
             Class.Methods.Append(", ");
         }
     }
 }
    public double[] GetStats(TDType type_)
    {
      double[] ret = new double[m_evals.Count];

      int endIndex, startIndex;
      if( (endIndex=m_pnls.Dates.IndexOf(AsOfDate))==-1)
        return ret;

      DateTime date = GetDate(type_);
      startIndex = m_pnls.Dates.IndexOf(date);

      if (startIndex == -1)
        return ret;

      for (int i = startIndex; i <= endIndex; ++i)
        for (int j = 0; j < m_pnls.ArrayLength; ++j)
          ret[j] += m_pnls.GetValue(m_pnls.Dates[i], j);

      return ret;
    }
Exemple #4
0
    private static void ParseDefinitions(
        TDType rootType, TypeResolverGroup typeResolverGroup)
    {
        foreach (var definition in UdonEditorManager.Instance.GetNodeDefinitions())
        {
            if (StartsWithIgnoredKeyword(definition) | IsSpecialDefinition(definition))
            {
                continue;
            }
            //Try to match by the non constructor regex, if it fails fallback to the constructor regex.
            //Perhaps they can be combined but this works.
            var match = NonCtorRegex.Match(definition.fullName);
            if (match.Groups.Count != NonCtorRegex.GetGroupNumbers().Length)
            {
                match = CtorRegex.Match(definition.fullName);
            }
            var groups = match.Groups;
            //Make sure all groups are filled. If not then the regex failed.
            if (groups.Count == NonCtorRegex.GetGroupNumbers().Length)
            {
                var definitionName = groups["namespace"].ToString();
                var methodType     = groups["methodType"].ToString();
                var methodName     = groups["methodName"].ToString();
                var inputsRaw      = groups["inputs"].ToString();
                var methodOutput   = groups["outputs"].ToString();

                //For some reason underscores are allowed and I'm not quite sure how to deal with them, so let's just do this
                //Replace with -, split by _, replace - with _
                inputsRaw = inputsRaw.Replace("VRCSDKBaseVRC_", "VRCSDKBaseVRC-");
                var methodInputs = inputsRaw.Split('_');
                for (int i = 0; i < methodInputs.Length; i++)
                {
                    methodInputs[i] = methodInputs[i].Replace("-", "_");
                }

                var isStatic = (definition.inputNames.Length > 0 && definition.inputNames[0] != "instance");
                //Some of the methods don't have any inputs(so definition.inputNames[0] doesn't exist) so we have to check the wrapper
                try
                {
                    int outputCount         = definition.outputs[0] != typeof(void) ? 1 : 0;
                    int inputParameterCount =
                        Wrapper.GetExternFunctionParameterCount(definition.fullName) - outputCount;
                    if (definition.inputNames.Length == 0 && inputParameterCount == 0)
                    {
                        isStatic = true;
                    }
                }
                catch //Catch because the wrapper just throws for some unsupported externs that exist in node definitions
                {
                }

                var fullUdonExternString = definition.fullName;
                var definitionType       = typeResolverGroup.GetTypeFromTypeStringWithErrors(definitionName);
                var namespaceName        = GetTypeFullName(definitionType);
                var definitionTDType     = GetOrCreateTDType(rootType, namespaceName, typeResolverGroup);
                definitionTDType.UdonName   = GenerateUdonName(definitionType);
                definitionTDType.CSharpType = definitionType;

                //Create TDTypes for all C# types encountered in the definition, and attach methods to them for each of the Extern functions
                var method = new Method
                {
                    FullUdonExternString = fullUdonExternString,
                    MethodName           = methodName,
                    MethodType           = methodType,
                    IsStatic             = isStatic
                };

                foreach (var udonTypeName in methodInputs)
                {
                    if (udonTypeName != "")
                    {
                        var    thisType = typeResolverGroup.GetTypeFromTypeStringWithErrors(udonTypeName);
                        var    typeName = GetTypeFullName(thisType);
                        TDType tdType   = GetOrCreateTDType(rootType, typeName, typeResolverGroup);
                        tdType.UdonName   = GenerateUdonName(thisType);
                        tdType.CSharpType = thisType;
                        if (typeResolverGroup.GetTypeFromTypeStringWithErrors(tdType.UdonName) != thisType)
                        {
                            Debug.LogError(
                                $"Could not generate proper udon name for {thisType}. Generated: {tdType.UdonName}");
                        }

                        method.Inputs.Add(tdType);
                    }
                }

                if (methodOutput != "")
                {
                    var    thisType = typeResolverGroup.GetTypeFromTypeStringWithErrors(methodOutput);
                    TDType tdType   = GetOrCreateTDType(rootType, GetTypeFullName(thisType), typeResolverGroup);
                    tdType.UdonName   = GenerateUdonName(thisType);
                    tdType.CSharpType = thisType;
                    method.Output     = tdType;
                }

                if (method.IsStatic)
                {
                    definitionTDType.StaticMethods.Add(method);
                }
                else
                {
                    definitionTDType.NonStaticMethods.Add(method);
                }
            }
            else
            {
                Debug.LogError($"Unhandled definition: {definition.fullName}");
            }
        }
    }
Exemple #5
0
    public static TDType GetOrCreateTDType(TDType rootType, string fullName, TypeResolverGroup typeResolverGroup)
    {
        bool           containsGenericArguments = fullName.Contains("<");
        Queue <string> namespaces;
        string         genericArguments = null;

        if (containsGenericArguments) //Generic types
        {
            var match    = GenericsRegex.Match(fullName);
            var groups   = match.Groups;
            var baseType = groups["GenericBaseType"].ToString();
            genericArguments = groups["GenericArguments"].ToString();
            namespaces       = new Queue <string>(baseType.Split('.'));
        }
        else
        {
            namespaces = new Queue <string>(fullName.Split('.'));
        }

        var current = rootType;

        while (namespaces.Count > 0)
        {
            var name = namespaces.Dequeue();
            //Only the full string is "generic", so it must be the last thing in the queue.
            //IE. System.Collections.Generic isn't generic itself, but System.Collections.Generic.List is generic
            bool isGeneric = containsGenericArguments && namespaces.Count == 0;
            var  child     = current.Children.Find(x =>
                                                   x.TypeName == name && x.IsGeneric == isGeneric && genericArguments == x.InputGenericArguments);
            if (child != null)
            {
                //Go down tree
                current = child;
            }
            else
            {
                //Create an go down tree
                var type = new TDType
                {
                    NamespaceName         = current.FullName,
                    FullName              = (current.FullName != null ? current.FullName + "." : "") + name,
                    TypeName              = name,
                    InputGenericArguments = genericArguments
                };
                string attemptedUdonName =
                    GenerateUdonName(type.FullName, true); //Try to generate udon name and set it if it's correct.
                if (typeResolverGroup.GetTypeFromTypeString(attemptedUdonName) != null)
                {
                    type.UdonName = attemptedUdonName;
                }

                current.Children.Add(type);
                current           = type;
                current.IsGeneric = isGeneric;
            }
        }

        if (current.IsGeneric)
        {
            current.IsGeneric = true;
            if (!genericArguments.Contains("<"))
            {
                current.AddGenericArguments(rootType, typeResolverGroup, genericArguments.Replace(" ", "").Split(','));
            }
            else
            {
                //Only one thing contains a nested generic argument in Udon currently
                //and luckily it looks like "thing<other<something, else>>"
                //which means it's a single layer of nesting
                //So for now we can just pass "other<something, else>" to GetOrCreateTDType
                //In the future this might change?
                current.AddGenericArguments(rootType, typeResolverGroup, genericArguments);
            }
        }

        if (fullName.Contains("[]"))
        {
            //Add base type for arrays
            GetOrCreateTDType(rootType, fullName.Replace("[]", ""), typeResolverGroup);
        }

        return(current);
    }
 public DateTime GetDate(TDType type_)
 {
   DateTime ret = DateTime.MinValue;
   switch (type_)
   {
     case TDType.OneDay:
       ret=AsOfDate;
       while (PnlConstruct.Dates.Contains(ret) == false)
         ret = MyCalendar.NextWeekDay(ret);
       break;
     case TDType.WeekToDate:
       ret = AsOfDate;
       while (ret.DayOfWeek != DayOfWeek.Monday)
         ret = MyCalendar.PrevWeekDay(ret);
       break;
     case TDType.MonthToDate:
       ret = new DateTime(AsOfDate.Year, AsOfDate.Month, 1);
       while (PnlConstruct.Dates.Contains(ret) == false)
         ret = MyCalendar.NextWeekDay(ret);
       break;
     case TDType.QuarterToDate:
       int month = AsOfDate.Month;
       switch (month)
       {
         case 1:
         case 2:
         case 3:
           ret = new DateTime(AsOfDate.Year, 1, 1);
           break;
         case 4:
         case 5:
         case 6:
           ret = new DateTime(AsOfDate.Year, 4, 1);
           break;
         case 7:
         case 8:
         case 9:
           ret = new DateTime(AsOfDate.Year, 7, 1);
           break;
         case 10:
         case 11:
         case 12:
           ret = new DateTime(AsOfDate.Year, 10, 1);
           break;
       }
       while (PnlConstruct.Dates.Contains(ret) == false)
         ret = MyCalendar.NextWeekDay(ret);
       break;
     case TDType.YearToDate:
       ret = new DateTime(AsOfDate.Year, 1, 1);
       while (PnlConstruct.Dates.Contains(ret) == false)
         ret = MyCalendar.NextWeekDay(ret);
       break;
     case TDType.Inception:
       ret = PnlConstruct.Dates[0];
       break;
     case TDType.CustomToDate:
       ret = CustomStartDate;
       while (PnlConstruct.Dates.Contains(ret) == false)
       {
         if (ret > PnlConstruct.LastDate)
         {
           ret = PnlConstruct.LastDate;
           break;
         }
         ret = MyCalendar.NextWeekDay(ret);
       }
       break;
     case TDType.OneYear:
       ret = AsOfDate.AddYears(-1);
       if (MyCalendar.IsWeekend(ret))
         ret = MyCalendar.NextWeekDay(ret);
       break;
     case TDType.TwoYear:
       ret = AsOfDate.AddYears(-2);
       if (MyCalendar.IsWeekend(ret))
         ret = MyCalendar.NextWeekDay(ret);
       break;
   }
   return ret;
 }
Exemple #7
0
    public static string ExportTDTypeAsDLL(TDType root, TypeResolverGroup typeResolverGroup)
    {
        HashSet <Class>            parentlessClasses = new HashSet <Class>();
        HashSet <Class>            extenstionClasses = new HashSet <Class>();
        Dictionary <string, Class> fullNameToClass   = new Dictionary <string, Class>();

        void WriteTypeCode(TDType type)
        {
            if (string.IsNullOrEmpty(type.FullName) || type.FullName.Contains("*"))
            {
                return;
            }
            var    fullName       = type.FullName.Replace("[]", "Array");
            var    typeName       = type.TypeName.Replace("[]", "Array");
            bool   extensionClass = type.FullName.EndsWith("[]");
            string dictionaryKey  = type.IsGeneric ? type.FullName + type.GenericArguments.Count : type.FullName;

            //Create or get class
            if (!fullNameToClass.TryGetValue(dictionaryKey, out var Class))
            {
                Class = new Class
                {
                    UdonName         = type.UdonName,
                    TypeName         = typeName,
                    IsExtentionClass = extensionClass,
                    Type             = type,
                    FullName         = type.FullName
                };
                Class.IsNamespace = Class.TypeName == "System" || Class.TypeName == "Collections" ||
                                    (string.IsNullOrEmpty(Class.UdonName) && type.GenericArguments.Count == 0);
                if (type.CSharpType != null)
                {
                    Class.IsEnum      = type.CSharpType.IsEnum;
                    Class.IsInterface = type.CSharpType.IsInterface;
                    Class.IsStruct    = type.CSharpType.IsValueType;
                    if (!Class.IsEnum && !Class.IsExtentionClass)
                    {
                        Class.InheritedClass = type.CSharpType.GetFirstInheritedUdonType(typeResolverGroup);
                    }
                    if (!Class.IsExtentionClass)
                    {
                        type.CSharpType.AddTypeInterfaces(Class.Interfaces, typeResolverGroup);
                    }
                    if (Class.IsEnum)
                    {
                        var names = Enum.GetNames(type.CSharpType);
                        foreach (var name in names)
                        {
                            Class.EnumNames.Add(name);
                        }
                    }
                }

                fullNameToClass[dictionaryKey] = Class;

                //Add new class to children
                if (string.IsNullOrEmpty(type.NamespaceName) || Class.IsNamespace)
                {
                    parentlessClasses.Add(Class);
                }
                else
                {
                    if (fullNameToClass.TryGetValue(type.NamespaceName, out var Parent))
                    {
                        if (extensionClass)
                        {
                            extenstionClasses.Add(Class);
                        }
                        else
                        {
                            Parent.Children.Add(Class);
                        }
                    }
                    else
                    {
                        Debug.LogError($"Parent class not created {type.NamespaceName}");
                    }
                }
            }

            if (type.UdonName != null)
            {
                AddMethods(type.StaticMethods, Class, extensionClass, type.FullName);
                AddMethods(type.NonStaticMethods, Class, extensionClass, type.FullName);
            }
        }

        void VisitType(TDType type)
        {
            WriteTypeCode(type);
            foreach (var child in type.Children)
            {
                VisitType(child);
            }
        }

        //Visit tree and build classes/namespaces
        VisitType(root);

        //Required for -nostdlib
        var collections = fullNameToClass["System.Collections"].Methods;

        collections.AppendLine("public interface IEnumerable { }");
        var system = fullNameToClass["System"].Methods;

        system.AppendLine("public abstract class ValueType { }");
        system.AppendLine("public abstract class Enum : ValueType { }");
        system.AppendLine("public class Attribute { }");
        system.AppendLine("public abstract class Delegate { }");
        system.AppendLine("public abstract class MulticastDelegate : Delegate { }");
        system.AppendLine("public struct IntPtr { }");
        system.AppendLine("public struct UIntPtr { }");
        system.AppendLine("public struct RuntimeTypeHandle { }");
        system.AppendLine("public struct RuntimeMethodHandle { }");
        system.AppendLine("public struct RuntimeFieldHandle { }");
        system.AppendLine("public interface IDisposable { }");
        system.AppendLine("public sealed class ParamArrayAttribute : Attribute { }");

        //Write all namespaces out
        var fullCode = new StringBuilder();

        foreach (var Class in parentlessClasses)
        {
            fullCode.AppendLine(Class.GenerateCode());
        }

        foreach (var Class in extenstionClasses)
        {
            fullCode.AppendLine(Class.GenerateCode());
        }

        fullCode.AppendLine(attributeClassString);

        return(fullCode.ToString());
    }