Ejemplo n.º 1
0
        public string FindDelegateInvokeReference(IDelegatePairDefinition pairDefinitions,
                                                  PapyrusMethodDefinition papyrusMethod)
        {
            // In case this is a delegate inside a delegate...
            // _UtilizeDelegate4_b__0
            var functionName = papyrusMethod.Name.Value;
            var originalName = papyrusMethod.Name.Value;

            if (functionName.StartsWith("_") && functionName.Contains("b_"))
            {
                functionName = functionName.Split('_')[1];
                papyrusMethod.DelegateInvokeCount++;
            }

            var delegateMethod =
                pairDefinitions.DelegateMethodDefinitions.FirstOrDefault(
                    del =>
                    del.Name.Contains("_" + functionName + "_") &&
                    del.Name.EndsWith("_" + papyrusMethod.DelegateInvokeCount));

            if (delegateMethod == null)
            {
                delegateMethod =
                    pairDefinitions.DelegateMethodDefinitions.FirstOrDefault(
                        del =>
                        del.Name.Contains("_" + functionName + "_") && del.Name.Contains("b_") &&
                        del.Name != originalName);
            }
            papyrusMethod.DelegateInvokeCount++;
            return(delegateMethod?.Name);
        }
Ejemplo n.º 2
0
 public IEnumerable <PapyrusInstruction> ProcessInstructions(
     IEnumerable <PapyrusAssemblyDefinition> papyrusAssemblyCollection, IDelegatePairDefinition delegatePairDef,
     PapyrusAssemblyDefinition targetPapyrusAssembly, PapyrusTypeDefinition targetPapyrusType,
     PapyrusMethodDefinition targetPapyrusMethod, MethodDefinition method, MethodBody body,
     Collection <Instruction> instructions,
     PapyrusCompilerOptions options)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 3
0
        private void ProcessInstructions(IEnumerable <PapyrusAssemblyDefinition> papyrusAssemblyCollection,
                                         IDelegatePairDefinition delegatePairDef, MethodDefinition method, PapyrusAssemblyDefinition asm,
                                         PapyrusTypeDefinition papyrusType, PapyrusMethodDefinition m, PapyrusCompilerOptions options)
        {
            var papyrusInstructions =
                instructionProcessor.ProcessInstructions(papyrusAssemblyCollection, delegatePairDef, asm, papyrusType, m,
                                                         method, method.Body, method.Body.Instructions, options);

            if (method.Name.ToLower() == "oninit")
            {
                List <PapyrusInstruction> structGets;
                var ip = instructionProcessor as ClrInstructionProcessor;
                // TODO: Going against solid here just because im to damn tired, which I ended up breaking in lots of places.
                m.Body.Instructions.Insert(0,
                                           ip.CallProcessor.CreatePapyrusCallInstruction(instructionProcessor, PapyrusOpCodes.Callmethod, constructor,
                                                                                         "self",
                                                                                         "::nonevar", new List <object>(), out structGets));
            }

            m.Body.Instructions.AddRange(papyrusInstructions);
        }
Ejemplo n.º 4
0
        /// <summary>
        ///     Converts the assembly.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        protected override PapyrusAssemblyOutput ConvertAssembly(ClrAssemblyInput input)
        {
            var clr        = input.Assembly;
            var mainModule = clr.MainModule;

            papyrusAssemblies.Clear();

            propertyMethods = new List <MethodDefinition>();

            var papyrusAssemblyToTypeDefinition = new Dictionary <PapyrusAssemblyDefinition, TypeDefinition>();


            // Keep track on the enum types so we can verify any parameter, variables, etc, and change the type into integers.
            ResolveEnumDefinitions(mainModule);

            foreach (var type in mainModule.Types)
            {
                try
                {
                    // We will skip this one for now
                    // as it will not really provide us with any necessary information at this early stage.
                    if (type.Name == "<Module>")
                    {
                        continue;
                    }

                    // Find all delegate types and methods and create references to them.
                    delegatePairDefinition = delegateFinder.FindDelegateTypes(type);

                    activeClrType = type;

                    var pex = PapyrusAssemblyDefinition.CreateAssembly(input.TargetPapyrusVersion);

                    SetHeaderInfo(input, pex, type);

                    CreateType(pex, type, processorOptions);

                    papyrusAssemblies.Add(pex);

                    papyrusAssemblyToTypeDefinition.Add(pex, type);


                    // After the type has been processed
                    // we will create the methods and then create the debug info as we do not have any info regarding the methods until those have been created ;-)

                    foreach (var t in pex.Types)
                    {
                        var firstState = t.States.FirstOrDefault();
                        if (firstState == null)
                        {
                            continue;                     // no state was found??
                        }
                        CreateMethods(papyrusAssemblies, type, t, pex, processorOptions)
                        .ForEach(firstState.Methods.Add);

                        CreateDebugInfo(pex, t, type);
                    }
                }
                catch (ProhibitedCodingBehaviourException exc)
                {
                    userInterface.DrawError($"Error processing '{type.FullName}': Prohibited use of " + exc.OpCode.GetValueOrDefault().Code + " in " +
                                            exc.Method.FullName + " at " + exc.Offset);
                }
                catch (Exception exc)
                {
                    userInterface.DrawError($"Error processing '{type.FullName}': Unhandled Exception - " + exc);
                }
            }

            return(new PapyrusAssemblyOutput(papyrusAssemblies.ToArray()));
        }
Ejemplo n.º 5
0
        private PapyrusMethodDefinition CreatePapyrusMethodDefinition(
            IEnumerable <PapyrusAssemblyDefinition> papyrusAssemblyCollection, PapyrusAssemblyDefinition asm,
            PapyrusTypeDefinition papyrusType,
            MethodDefinition method, IDelegatePairDefinition delegatePairDef, PapyrusCompilerOptions options)
        {
            if (method.IsConstructor)
            {
                // Replace: .ctor with __ctor
                method.Name = method.Name.Replace(".", "__");
                constructor = method;
            }

            var m = new PapyrusMethodDefinition(asm);

            m.Documentation = "".Ref(asm);
            m.UserFlags     = attributeReader.ReadPapyrusAttributes(method).UserFlagsValue;
            m.IsGlobal      = method.IsStatic;
            m.IsNative      = method.CustomAttributes.Any(i => i.AttributeType.Name.Equals("NativeAttribute"));
            m.Name          = method.Name.Ref(asm);
            var papyrusReturnType = Utility.GetPapyrusReturnType(method.ReturnType, activeClrType);

            if (EnumDefinitions.Any(m2 => m2.FullName == method.ReturnType.FullName))
            {
                papyrusReturnType = "Int";
            }

            m.ReturnTypeName = papyrusReturnType.Ref(asm); // method.ReturnType.Name
            m.Parameters     = new List <PapyrusParameterDefinition>();
            foreach (var p in method.Parameters)
            {
                // TODO: Add support for delegate as parameter

                var paramTypeName = Utility.GetPapyrusReturnType(p.ParameterType, activeClrType, true);

                // Replace enum types into Integer
                if (EnumDefinitions.Any(i => i.FullName == p.ParameterType.FullName))
                {
                    paramTypeName = "Int";
                }

                m.Parameters.Add(new PapyrusParameterDefinition
                {
                    Name     = p.Name.Ref(asm),
                    TypeName = paramTypeName.Ref(asm)
                });
            }

            var clrVariables = method.Body.Variables;

            var varNum = 0;

            foreach (var clrVar in clrVariables)
            {
                var delegateVars =
                    delegatePairDef.DelegateMethodLocalPair.Where(d => d.Key == method).SelectMany(d => d.Value);

                if (delegateVars.Any(d => "V_" + d.Index == "V_" + clrVar.Index))
                {
                    // This local variable is pointing to a delegate
                    // and since we are removing all Delegate types, this wont work. So we have to change the type into something else.
                    // in this case, we are changing it into a Int

                    if (!clrVar.Name.Contains("$<>"))
                    // if we are reading symbols, delegate variables contains unwanted characters in their names.
                    // And since those are not going to be used. We can just skip these.
                    {
                        var varName = (!string.IsNullOrEmpty(clrVar.Name) ? clrVar.Name : clrVar.ToString()).Ref(asm);

                        var delegateInvokeRef = delegateFinder.FindDelegateInvokeReference(delegatePairDefinition, m);

                        m.Body.Variables.Add(new PapyrusVariableReference(varName, "Int".Ref(asm))
                        {
                            IsDelegateReference     = true,
                            DelegateInvokeReference = delegateInvokeRef,
                            Value = varName.Value,
                            Type  = PapyrusPrimitiveType.Reference
                        });
                    }
                }
                else
                {
                    var varName          = (!string.IsNullOrEmpty(clrVar.Name) ? clrVar.Name : clrVar.ToString()).Ref(asm);
                    var variableTypeName = Utility.GetPapyrusReturnType(clrVar.VariableType.FullName);

                    // If its an enum, we want to change the type into a Int
                    if (EnumDefinitions.Any(i => i.FullName == clrVar.VariableType.FullName))
                    {
                        variableTypeName = "Int";
                    }

                    m.Body.Variables.Add(new PapyrusVariableReference(varName, variableTypeName.Ref(asm))
                    {
                        Value = varName.Value,
                        Type  = PapyrusPrimitiveType.Reference
                    });
                }
                varNum++;
            }

            if (method.HasBody)
            {
                ProcessInstructions(papyrusAssemblyCollection, delegatePairDef, method, asm, papyrusType, m, options);

                if (papyrusReturnType == "None")
                {
                    if (m.Body.Variables.All(n => n.Name.Value.ToLower() != "::nonevar"))
                    {
                        var nonevar = "::NoneVar".Ref(asm);
                        m.Body.Variables.Add(new PapyrusVariableReference(nonevar, "None".Ref(asm))
                        {
                            Value = nonevar.Value,
                            Type  = PapyrusPrimitiveType.Reference
                        });
                    }
                }
                m.Body.Instructions.RecalculateOffsets();
            }

            return(m);
        }